<?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=Kravtsovkirill</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=Kravtsovkirill"/>
	<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/Kravtsovkirill"/>
	<updated>2026-10-22T23:55:47Z</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=19509</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=19509"/>
		<updated>2016-11-29T19:56:12Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса Московского университета. Алгоритм был реализован с помощью языка Fortran 90. &lt;br /&gt;
&lt;br /&gt;
Реализация тестировалась со следующими параметрами: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер входного слоя сети, а также слоя Кохонена (были установлены равными друг другу) [1000 : 4000].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Файл:Plot_s2.svg|thumb|600px|center| На рисунке представлен график зависимости времени выполнения от числа процессоров и размерности входных данных]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Plot_s3.svg|thumb|600px|center| Производительность в зависимости от числа процессоров и размерности входных данных]]&lt;br /&gt;
&lt;br /&gt;
Можно сделать вывод, что с протестированными параметрами запуска, алгоритм хорошо параллелится только до момента, когда начинают расти накладные расходы, и для максимальных протестированных размеров слоев сети, оптимальным количество процессоров является 32. Из графиков видно, что при увеличении объема задачи эффективность от большего, чем 32, количества процессоров будет расти.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая авторская реализация алгоритма.&lt;br /&gt;
&lt;br /&gt;
    program Kohonen&lt;br /&gt;
        implicit none&lt;br /&gt;
        include &#039;mpif.h&#039;&lt;br /&gt;
        integer rank,ierr,size,sizeBlock&lt;br /&gt;
        integer n,perProc,i,j,k,jmin,jAbsWin&lt;br /&gt;
        integer iterNum,IOS&lt;br /&gt;
        real learning_rate&lt;br /&gt;
        real dist,prom,minDist&lt;br /&gt;
        real, allocatable :: W(:,:),sample(:,:),maswin(:,:)&lt;br /&gt;
        real, allocatable :: buf(:,:),win(:)&lt;br /&gt;
        double precision start,finish&lt;br /&gt;
        character str&lt;br /&gt;
        	&lt;br /&gt;
        iterNum = 1000&lt;br /&gt;
        n=1000&lt;br /&gt;
        &lt;br /&gt;
            learning_rate = 1.0&lt;br /&gt;
            &lt;br /&gt;
            allocate(W(n,n))&lt;br /&gt;
            allocate(sample(iterNum,n))&lt;br /&gt;
            allocate(win(2))&lt;br /&gt;
            &lt;br /&gt;
            call randMatr(sample,iterNum,n,.FALSE.)&lt;br /&gt;
            call randMatr(W,n,n,.True.)&lt;br /&gt;
            &lt;br /&gt;
            call MPI_INIT(IERR)&lt;br /&gt;
            call MPI_COMM_SIZE(MPI_COMM_WORLD,SIZE,IERR)&lt;br /&gt;
            call MPI_COMM_RANK(MPI_COMM_WORLD,RANK,IERR)&lt;br /&gt;
            &lt;br /&gt;
            perProc = n/size&lt;br /&gt;
            allocate(buf(n,perProc))&lt;br /&gt;
            allocate(maswin(2,size))&lt;br /&gt;
            sizeBlock = perProc * n&lt;br /&gt;
            &lt;br /&gt;
            if (rank .eq. 0) then&lt;br /&gt;
                start = MPI_WTIME(IERR)&lt;br /&gt;
            end if&lt;br /&gt;
            &lt;br /&gt;
            do i=1,IterNum,1&lt;br /&gt;
                call obnul(buf,n,perProc)&lt;br /&gt;
                call MPI_SCATTER(W,sizeBlock,MPI_REAL,buf,sizeBlock,MPI_REAL,0,MPI_COMM_WORLD,IERR)&lt;br /&gt;
                &lt;br /&gt;
                dist = euclDist(sample(i,1:n),buf(1:n,1),n)&lt;br /&gt;
                do j=1,perProc,1&lt;br /&gt;
                    prom = euclDist(sample(i,1:n),buf(1:n,j),n)&lt;br /&gt;
                    if (prom .le. dist) then&lt;br /&gt;
                        dist = prom&lt;br /&gt;
                        jmin = j + rank*perProc&lt;br /&gt;
                    end if&lt;br /&gt;
                enddo		&lt;br /&gt;
                win(1) = jmin&lt;br /&gt;
                win(2) = dist&lt;br /&gt;
                &lt;br /&gt;
                call MPI_BARRIER(MPI_COMM_WORLD,IERR)	&lt;br /&gt;
                			&lt;br /&gt;
                call MPI_GATHER(win,2,MPI_REAL,maswin,2,MPI_REAL,0,MPI_COMM_WORLD,IERR)&lt;br /&gt;
                &lt;br /&gt;
                if (rank .eq. 0) then&lt;br /&gt;
                    minDist = maswin(2,1)&lt;br /&gt;
                    jAbsWin = maswin(1,1)&lt;br /&gt;
                    do j=2,size,1&lt;br /&gt;
                        if (mindist .ge. maswin(2,j)) then&lt;br /&gt;
                            minDist = maswin(2,j)&lt;br /&gt;
                            jAbsWin = maswin(1,j)&lt;br /&gt;
                        endif&lt;br /&gt;
                    enddo&lt;br /&gt;
                    call modW(W,n,learning_rate,i,jAbsWin)&lt;br /&gt;
                    end if&lt;br /&gt;
            enddo&lt;br /&gt;
            &lt;br /&gt;
            if (rank .eq. 0) then&lt;br /&gt;
                finish = MPI_WTIME(IERR)&lt;br /&gt;
                open(1,file=&amp;quot;Rezult.txt&amp;quot;,iostat=IOS)&lt;br /&gt;
                do while (.NOT. eof(1))&lt;br /&gt;
                    read(1,*) str&lt;br /&gt;
                enddo&lt;br /&gt;
                write (1,*) &#039;Neurons: &#039;,n,&#039;Processes: &#039;,size,&#039;Time: &#039;,finish-start&lt;br /&gt;
                close(1)&lt;br /&gt;
            end if       &lt;br /&gt;
            &lt;br /&gt;
            call MPI_FINALIZE(IERR)&lt;br /&gt;
            &lt;br /&gt;
            !call printm(W,n,n)&lt;br /&gt;
        &lt;br /&gt;
            deallocate(W,sample,win,maswin,buf)&lt;br /&gt;
            	&lt;br /&gt;
            &lt;br /&gt;
        contains&lt;br /&gt;
        &lt;br /&gt;
        subroutine printm(W,a,b)&lt;br /&gt;
            integer a,b,i,j&lt;br /&gt;
            real W(n,n)&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                write(*,*)(W(i,j), i=1,a)&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine printm&lt;br /&gt;
        &lt;br /&gt;
        subroutine obnul(W,a,b)&lt;br /&gt;
            integer a,b&lt;br /&gt;
            integer i,j&lt;br /&gt;
            real W(a,b)&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                do i=1,a,1&lt;br /&gt;
                    W(i,j) = 0.0&lt;br /&gt;
                enddo&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine obnul&lt;br /&gt;
        &lt;br /&gt;
        real function euclDist(a,b,n)&lt;br /&gt;
            integer n,i&lt;br /&gt;
                real a(n),b(n),res&lt;br /&gt;
                &lt;br /&gt;
                res = 0&lt;br /&gt;
                do i = 1,n,1&lt;br /&gt;
                    res = res + (a(i) - b(i)) * (a(i) - b(i))&lt;br /&gt;
                enddo&lt;br /&gt;
                &lt;br /&gt;
                euclDist = sqrt(res)&lt;br /&gt;
        end function euclDist&lt;br /&gt;
        &lt;br /&gt;
        subroutine modW(W,n,learning_rate,iter,jAbsWin)&lt;br /&gt;
            integer n,iter,JAbsWin&lt;br /&gt;
            real learning_rate,W(n,n)&lt;br /&gt;
            integer i,j&lt;br /&gt;
            &lt;br /&gt;
            do j=1,n,1&lt;br /&gt;
                if (j .ne. jAbsWin) then &lt;br /&gt;
                    do i=1,n,1&lt;br /&gt;
                        W(i,j) = W(i,j) + learning_rate/sqrt(iter+1.0)*(W(i,jAbsWin)-W(i,j))&lt;br /&gt;
                    enddo&lt;br /&gt;
                end if&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine modW&lt;br /&gt;
        &lt;br /&gt;
        subroutine randMatr(matr,a,b,small)&lt;br /&gt;
            integer a,b&lt;br /&gt;
            logical small&lt;br /&gt;
            integer i,j&lt;br /&gt;
            real matr(a,b),x&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                do i=1,a,1&lt;br /&gt;
                    call random_seed&lt;br /&gt;
                    call random_number(x)&lt;br /&gt;
                    x = x * 10 - x * 8&lt;br /&gt;
                    if (small) then&lt;br /&gt;
                        x = x / 40&lt;br /&gt;
                    end if&lt;br /&gt;
                    matr(i,j) = x&lt;br /&gt;
                enddo&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine randMatr&lt;br /&gt;
    end program Kohonen&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=19508</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=19508"/>
		<updated>2016-11-29T19:55:18Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса Московского университета. Алгоритм был реализован с помощью языка Fortran 90. &lt;br /&gt;
&lt;br /&gt;
Реализация тестировалась со следующими параметрами: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер входного слоя сети, а также слоя Кохонена (были установлены равными друг другу) [1000 : 4000].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Файл:Plot_s2.svg|thumb|600px|center| На рисунке представлен график зависимости времени выполнения от числа процессоров и размерности входных данных]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Plot_s3.svg|thumb|600px|center| Производительность в зависимости от числа процессоров и размерности входных данных]]&lt;br /&gt;
&lt;br /&gt;
Можно сделать вывод, что с протестированными параметрами запуска, алгоритм хорошо параллелится только до момента, когда начинают расти накладные расходы, и для максимальных протестированных размеров слоев сети, оптимальным количество процессоров является 32. Из графиков видно, что при увеличении объема задачи эффективность от большего, чем 32, количества процессоров будет расти.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая авторская реализация алгоритма.&lt;br /&gt;
&lt;br /&gt;
    program Kohonen&lt;br /&gt;
        implicit none&lt;br /&gt;
        include &#039;mpif.h&#039;&lt;br /&gt;
        integer rank,ierr,size,sizeBlock&lt;br /&gt;
        integer n,perProc,i,j,k,jmin,jAbsWin&lt;br /&gt;
        integer iterNum,IOS&lt;br /&gt;
        real learning_rate&lt;br /&gt;
        real dist,prom,minDist&lt;br /&gt;
        real, allocatable :: W(:,:),sample(:,:),maswin(:,:)&lt;br /&gt;
        real, allocatable :: buf(:,:),win(:)&lt;br /&gt;
        double precision start,finish&lt;br /&gt;
        character str&lt;br /&gt;
        	&lt;br /&gt;
        iterNum = 1000&lt;br /&gt;
        n=1000&lt;br /&gt;
        &lt;br /&gt;
            learning_rate = 1.0&lt;br /&gt;
            &lt;br /&gt;
            allocate(W(n,n))&lt;br /&gt;
            allocate(sample(iterNum,n))&lt;br /&gt;
            allocate(win(2))&lt;br /&gt;
            &lt;br /&gt;
            call randMatr(sample,iterNum,n,.FALSE.)&lt;br /&gt;
            call randMatr(W,n,n,.True.)&lt;br /&gt;
            &lt;br /&gt;
            call MPI_INIT(IERR)&lt;br /&gt;
            call MPI_COMM_SIZE(MPI_COMM_WORLD,SIZE,IERR)&lt;br /&gt;
            call MPI_COMM_RANK(MPI_COMM_WORLD,RANK,IERR)&lt;br /&gt;
            &lt;br /&gt;
            perProc = n/size&lt;br /&gt;
            allocate(buf(n,perProc))&lt;br /&gt;
            allocate(maswin(2,size))&lt;br /&gt;
            sizeBlock = perProc * n&lt;br /&gt;
            &lt;br /&gt;
            if (rank .eq. 0) then&lt;br /&gt;
                start = MPI_WTIME(IERR)&lt;br /&gt;
            end if&lt;br /&gt;
            &lt;br /&gt;
            do i=1,IterNum,1&lt;br /&gt;
                call obnul(buf,n,perProc)&lt;br /&gt;
                call MPI_SCATTER(W,sizeBlock,MPI_REAL,buf,sizeBlock,MPI_REAL,0,MPI_COMM_WORLD,IERR)&lt;br /&gt;
                &lt;br /&gt;
                dist = euclDist(sample(i,1:n),buf(1:n,1),n)&lt;br /&gt;
                do j=1,perProc,1&lt;br /&gt;
                    prom = euclDist(sample(i,1:n),buf(1:n,j),n)&lt;br /&gt;
                    if (prom .le. dist) then&lt;br /&gt;
                        dist = prom&lt;br /&gt;
                        jmin = j + rank*perProc&lt;br /&gt;
                    end if&lt;br /&gt;
                enddo		&lt;br /&gt;
                win(1) = jmin&lt;br /&gt;
                win(2) = dist&lt;br /&gt;
                &lt;br /&gt;
                call MPI_BARRIER(MPI_COMM_WORLD,IERR)	&lt;br /&gt;
                			&lt;br /&gt;
                call MPI_GATHER(win,2,MPI_REAL,maswin,2,MPI_REAL,0,MPI_COMM_WORLD,IERR)&lt;br /&gt;
                &lt;br /&gt;
                if (rank .eq. 0) then&lt;br /&gt;
                    minDist = maswin(2,1)&lt;br /&gt;
                    jAbsWin = maswin(1,1)&lt;br /&gt;
                    do j=2,size,1&lt;br /&gt;
                        if (mindist .ge. maswin(2,j)) then&lt;br /&gt;
                            minDist = maswin(2,j)&lt;br /&gt;
                            jAbsWin = maswin(1,j)&lt;br /&gt;
                        endif&lt;br /&gt;
                    enddo&lt;br /&gt;
                    call modW(W,n,learning_rate,i,jAbsWin)&lt;br /&gt;
                    end if&lt;br /&gt;
            enddo&lt;br /&gt;
            &lt;br /&gt;
            if (rank .eq. 0) then&lt;br /&gt;
                finish = MPI_WTIME(IERR)&lt;br /&gt;
                open(1,file=&amp;quot;Rezult.txt&amp;quot;,iostat=IOS)&lt;br /&gt;
                do while (.NOT. eof(1))&lt;br /&gt;
                    read(1,*) str&lt;br /&gt;
                enddo&lt;br /&gt;
                write (1,*) &#039;Neurons: &#039;,n,&#039;Processes: &#039;,size,&#039;Time: &#039;,finish-start&lt;br /&gt;
                close(1)&lt;br /&gt;
            end if       &lt;br /&gt;
            &lt;br /&gt;
            call MPI_FINALIZE(IERR)&lt;br /&gt;
            &lt;br /&gt;
            !call printm(W,n,n)&lt;br /&gt;
        &lt;br /&gt;
            deallocate(W,sample,win,maswin,buf)&lt;br /&gt;
            	&lt;br /&gt;
            &lt;br /&gt;
        contains&lt;br /&gt;
        &lt;br /&gt;
        subroutine printm(W,a,b)&lt;br /&gt;
            integer a,b,i,j&lt;br /&gt;
            real W(n,n)&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                write(*,*)(W(i,j), i=1,a)&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine printm&lt;br /&gt;
        &lt;br /&gt;
        subroutine obnul(W,a,b)&lt;br /&gt;
            integer a,b&lt;br /&gt;
            integer i,j&lt;br /&gt;
            real W(a,b)&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                do i=1,a,1&lt;br /&gt;
                    W(i,j) = 0.0&lt;br /&gt;
                enddo&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine obnul&lt;br /&gt;
        &lt;br /&gt;
        real function euclDist(a,b,n)&lt;br /&gt;
            integer n,i&lt;br /&gt;
                real a(n),b(n),res&lt;br /&gt;
                &lt;br /&gt;
                res = 0&lt;br /&gt;
                do i = 1,n,1&lt;br /&gt;
                    res = res + (a(i) - b(i)) * (a(i) - b(i))&lt;br /&gt;
                enddo&lt;br /&gt;
                &lt;br /&gt;
                euclDist = sqrt(res)&lt;br /&gt;
        end function euclDist&lt;br /&gt;
        &lt;br /&gt;
        subroutine modW(W,n,learning_rate,iter,jAbsWin)&lt;br /&gt;
            integer n,iter,JAbsWin&lt;br /&gt;
            real learning_rate,W(n,n)&lt;br /&gt;
            integer i,j&lt;br /&gt;
            &lt;br /&gt;
            do j=1,n,1&lt;br /&gt;
                if (j .ne. jAbsWin) then &lt;br /&gt;
                    do i=1,n,1&lt;br /&gt;
                        W(i,j) = W(i,j) + learning_rate/sqrt(iter+1.0)*(W(i,jAbsWin)-W(i,j))&lt;br /&gt;
                    enddo&lt;br /&gt;
                end if&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine modW&lt;br /&gt;
        &lt;br /&gt;
        subroutine randMatr(matr,a,b,small)&lt;br /&gt;
            integer a,b&lt;br /&gt;
            logical small&lt;br /&gt;
            integer i,j&lt;br /&gt;
            real matr(a,b),x&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                do i=1,a,1&lt;br /&gt;
                    call random_seed&lt;br /&gt;
                    call random_number(x)&lt;br /&gt;
                    x = x * 10 - x * 8&lt;br /&gt;
                    if (small) then&lt;br /&gt;
                        x = x / 40&lt;br /&gt;
                    end if&lt;br /&gt;
                    matr(i,j) = x&lt;br /&gt;
                enddo&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine randMatr&lt;br /&gt;
    end program Kohonen&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=19507</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=19507"/>
		<updated>2016-11-29T19:54:12Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса Московского университета. Алгоритм был реализован с помощью языка Fortran 90. &lt;br /&gt;
&lt;br /&gt;
Реализация тестировалась со следующими параметрами: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер входного слоя сети, а также слоя Кохонена (были установлены равными друг другу) [1000 : 4000].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Файл:Plot_s2.svg|thumb|600px|center| На рисунке представлен график зависимости времени выполнения от числа процессоров и размерности входных данных]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Plot_s3.svg|thumb|600px|center| Производительность в зависимости от числа процессоров и размерности входных данных]]&lt;br /&gt;
&lt;br /&gt;
Можно сделать вывод, что с протестированными параметрами запуска, алгоритм хорошо параллелится только до момента, когда начинают расти накладные расходы, и для максимальных протестированных размеров слоев сети, оптимальным количество процессоров является 32. Из графиков видно, что при увеличении объема задачи эффективность от большего, чем 32, количества процессоров будет расти.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма.&lt;br /&gt;
&lt;br /&gt;
    program Kohonen&lt;br /&gt;
        implicit none&lt;br /&gt;
        include &#039;mpif.h&#039;&lt;br /&gt;
        integer rank,ierr,size,sizeBlock&lt;br /&gt;
        integer n,perProc,i,j,k,jmin,jAbsWin&lt;br /&gt;
        integer iterNum,IOS&lt;br /&gt;
        real learning_rate&lt;br /&gt;
        real dist,prom,minDist&lt;br /&gt;
        real, allocatable :: W(:,:),sample(:,:),maswin(:,:)&lt;br /&gt;
        real, allocatable :: buf(:,:),win(:)&lt;br /&gt;
        double precision start,finish&lt;br /&gt;
        character str&lt;br /&gt;
        	&lt;br /&gt;
        iterNum = 1000&lt;br /&gt;
        n=1000&lt;br /&gt;
        &lt;br /&gt;
            learning_rate = 1.0&lt;br /&gt;
            &lt;br /&gt;
            allocate(W(n,n))&lt;br /&gt;
            allocate(sample(iterNum,n))&lt;br /&gt;
            allocate(win(2))&lt;br /&gt;
            &lt;br /&gt;
            call randMatr(sample,iterNum,n,.FALSE.)&lt;br /&gt;
            call randMatr(W,n,n,.True.)&lt;br /&gt;
            &lt;br /&gt;
            call MPI_INIT(IERR)&lt;br /&gt;
            call MPI_COMM_SIZE(MPI_COMM_WORLD,SIZE,IERR)&lt;br /&gt;
            call MPI_COMM_RANK(MPI_COMM_WORLD,RANK,IERR)&lt;br /&gt;
            &lt;br /&gt;
            perProc = n/size&lt;br /&gt;
            allocate(buf(n,perProc))&lt;br /&gt;
            allocate(maswin(2,size))&lt;br /&gt;
            sizeBlock = perProc * n&lt;br /&gt;
            &lt;br /&gt;
            if (rank .eq. 0) then&lt;br /&gt;
                start = MPI_WTIME(IERR)&lt;br /&gt;
            end if&lt;br /&gt;
            &lt;br /&gt;
            do i=1,IterNum,1&lt;br /&gt;
                call obnul(buf,n,perProc)&lt;br /&gt;
                call MPI_SCATTER(W,sizeBlock,MPI_REAL,buf,sizeBlock,MPI_REAL,0,MPI_COMM_WORLD,IERR)&lt;br /&gt;
                &lt;br /&gt;
                dist = euclDist(sample(i,1:n),buf(1:n,1),n)&lt;br /&gt;
                do j=1,perProc,1&lt;br /&gt;
                    prom = euclDist(sample(i,1:n),buf(1:n,j),n)&lt;br /&gt;
                    if (prom .le. dist) then&lt;br /&gt;
                        dist = prom&lt;br /&gt;
                        jmin = j + rank*perProc&lt;br /&gt;
                    end if&lt;br /&gt;
                enddo		&lt;br /&gt;
                win(1) = jmin&lt;br /&gt;
                win(2) = dist&lt;br /&gt;
                &lt;br /&gt;
                call MPI_BARRIER(MPI_COMM_WORLD,IERR)	&lt;br /&gt;
                			&lt;br /&gt;
                call MPI_GATHER(win,2,MPI_REAL,maswin,2,MPI_REAL,0,MPI_COMM_WORLD,IERR)&lt;br /&gt;
                &lt;br /&gt;
                if (rank .eq. 0) then&lt;br /&gt;
                    minDist = maswin(2,1)&lt;br /&gt;
                    jAbsWin = maswin(1,1)&lt;br /&gt;
                    do j=2,size,1&lt;br /&gt;
                        if (mindist .ge. maswin(2,j)) then&lt;br /&gt;
                            minDist = maswin(2,j)&lt;br /&gt;
                            jAbsWin = maswin(1,j)&lt;br /&gt;
                        endif&lt;br /&gt;
                    enddo&lt;br /&gt;
                    call modW(W,n,learning_rate,i,jAbsWin)&lt;br /&gt;
                    end if&lt;br /&gt;
            enddo&lt;br /&gt;
            &lt;br /&gt;
            if (rank .eq. 0) then&lt;br /&gt;
                finish = MPI_WTIME(IERR)&lt;br /&gt;
                open(1,file=&amp;quot;Rezult.txt&amp;quot;,iostat=IOS)&lt;br /&gt;
                do while (.NOT. eof(1))&lt;br /&gt;
                    read(1,*) str&lt;br /&gt;
                enddo&lt;br /&gt;
                write (1,*) &#039;Neurons: &#039;,n,&#039;Processes: &#039;,size,&#039;Time: &#039;,finish-start&lt;br /&gt;
                close(1)&lt;br /&gt;
            end if       &lt;br /&gt;
            &lt;br /&gt;
            call MPI_FINALIZE(IERR)&lt;br /&gt;
            &lt;br /&gt;
            !call printm(W,n,n)&lt;br /&gt;
        &lt;br /&gt;
            deallocate(W,sample,win,maswin,buf)&lt;br /&gt;
            	&lt;br /&gt;
            &lt;br /&gt;
        contains&lt;br /&gt;
        &lt;br /&gt;
        subroutine printm(W,a,b)&lt;br /&gt;
            integer a,b,i,j&lt;br /&gt;
            real W(n,n)&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                write(*,*)(W(i,j), i=1,a)&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine printm&lt;br /&gt;
        &lt;br /&gt;
        subroutine obnul(W,a,b)&lt;br /&gt;
            integer a,b&lt;br /&gt;
            integer i,j&lt;br /&gt;
            real W(a,b)&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                do i=1,a,1&lt;br /&gt;
                    W(i,j) = 0.0&lt;br /&gt;
                enddo&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine obnul&lt;br /&gt;
        &lt;br /&gt;
        real function euclDist(a,b,n)&lt;br /&gt;
            integer n,i&lt;br /&gt;
                real a(n),b(n),res&lt;br /&gt;
                &lt;br /&gt;
                res = 0&lt;br /&gt;
                do i = 1,n,1&lt;br /&gt;
                    res = res + (a(i) - b(i)) * (a(i) - b(i))&lt;br /&gt;
                enddo&lt;br /&gt;
                &lt;br /&gt;
                euclDist = sqrt(res)&lt;br /&gt;
        end function euclDist&lt;br /&gt;
        &lt;br /&gt;
        subroutine modW(W,n,learning_rate,iter,jAbsWin)&lt;br /&gt;
            integer n,iter,JAbsWin&lt;br /&gt;
            real learning_rate,W(n,n)&lt;br /&gt;
            integer i,j&lt;br /&gt;
            &lt;br /&gt;
            do j=1,n,1&lt;br /&gt;
                if (j .ne. jAbsWin) then &lt;br /&gt;
                    do i=1,n,1&lt;br /&gt;
                        W(i,j) = W(i,j) + learning_rate/sqrt(iter+1.0)*(W(i,jAbsWin)-W(i,j))&lt;br /&gt;
                    enddo&lt;br /&gt;
                end if&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine modW&lt;br /&gt;
        &lt;br /&gt;
        subroutine randMatr(matr,a,b,small)&lt;br /&gt;
            integer a,b&lt;br /&gt;
            logical small&lt;br /&gt;
            integer i,j&lt;br /&gt;
            real matr(a,b),x&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                do i=1,a,1&lt;br /&gt;
                    call random_seed&lt;br /&gt;
                    call random_number(x)&lt;br /&gt;
                    x = x * 10 - x * 8&lt;br /&gt;
                    if (small) then&lt;br /&gt;
                        x = x / 40&lt;br /&gt;
                    end if&lt;br /&gt;
                    matr(i,j) = x&lt;br /&gt;
                enddo&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine randMatr&lt;br /&gt;
    end program Kohonen&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=19506</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=19506"/>
		<updated>2016-11-29T19:53:51Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса Московского университета. Алгоритм был реализован с помощью языка Fortran 90. &lt;br /&gt;
&lt;br /&gt;
Реализация тестировалась со следующими параметрами: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер входного слоя сети, а также слоя Кохонена (были установлены равными друг другу) [1000 : 4000].&lt;br /&gt;
&lt;br /&gt;
[[Файл:Plot_s2.svg|thumb|600px|center| На рисунке представлен график зависимости времени выполнения от числа процессоров и размерности входных данных]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Plot_s3.svg|thumb|600px|center| Производительность в зависимости от числа процессоров и размерности входных данных]]&lt;br /&gt;
&lt;br /&gt;
Можно сделать вывод, что с протестированными параметрами запуска, алгоритм хорошо параллелится только до момента, когда начинают расти накладные расходы, и для максимальных протестированных размеров слоев сети, оптимальным количество процессоров является 32. Из графиков видно, что при увеличении объема задачи эффективность от большего, чем 32, количества процессоров будет расти.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма.&lt;br /&gt;
&lt;br /&gt;
    program Kohonen&lt;br /&gt;
        implicit none&lt;br /&gt;
        include &#039;mpif.h&#039;&lt;br /&gt;
        integer rank,ierr,size,sizeBlock&lt;br /&gt;
        integer n,perProc,i,j,k,jmin,jAbsWin&lt;br /&gt;
        integer iterNum,IOS&lt;br /&gt;
        real learning_rate&lt;br /&gt;
        real dist,prom,minDist&lt;br /&gt;
        real, allocatable :: W(:,:),sample(:,:),maswin(:,:)&lt;br /&gt;
        real, allocatable :: buf(:,:),win(:)&lt;br /&gt;
        double precision start,finish&lt;br /&gt;
        character str&lt;br /&gt;
        	&lt;br /&gt;
        iterNum = 1000&lt;br /&gt;
        n=1000&lt;br /&gt;
        &lt;br /&gt;
            learning_rate = 1.0&lt;br /&gt;
            &lt;br /&gt;
            allocate(W(n,n))&lt;br /&gt;
            allocate(sample(iterNum,n))&lt;br /&gt;
            allocate(win(2))&lt;br /&gt;
            &lt;br /&gt;
            call randMatr(sample,iterNum,n,.FALSE.)&lt;br /&gt;
            call randMatr(W,n,n,.True.)&lt;br /&gt;
            &lt;br /&gt;
            call MPI_INIT(IERR)&lt;br /&gt;
            call MPI_COMM_SIZE(MPI_COMM_WORLD,SIZE,IERR)&lt;br /&gt;
            call MPI_COMM_RANK(MPI_COMM_WORLD,RANK,IERR)&lt;br /&gt;
            &lt;br /&gt;
            perProc = n/size&lt;br /&gt;
            allocate(buf(n,perProc))&lt;br /&gt;
            allocate(maswin(2,size))&lt;br /&gt;
            sizeBlock = perProc * n&lt;br /&gt;
            &lt;br /&gt;
            if (rank .eq. 0) then&lt;br /&gt;
                start = MPI_WTIME(IERR)&lt;br /&gt;
            end if&lt;br /&gt;
            &lt;br /&gt;
            do i=1,IterNum,1&lt;br /&gt;
                call obnul(buf,n,perProc)&lt;br /&gt;
                call MPI_SCATTER(W,sizeBlock,MPI_REAL,buf,sizeBlock,MPI_REAL,0,MPI_COMM_WORLD,IERR)&lt;br /&gt;
                &lt;br /&gt;
                dist = euclDist(sample(i,1:n),buf(1:n,1),n)&lt;br /&gt;
                do j=1,perProc,1&lt;br /&gt;
                    prom = euclDist(sample(i,1:n),buf(1:n,j),n)&lt;br /&gt;
                    if (prom .le. dist) then&lt;br /&gt;
                        dist = prom&lt;br /&gt;
                        jmin = j + rank*perProc&lt;br /&gt;
                    end if&lt;br /&gt;
                enddo		&lt;br /&gt;
                win(1) = jmin&lt;br /&gt;
                win(2) = dist&lt;br /&gt;
                &lt;br /&gt;
                call MPI_BARRIER(MPI_COMM_WORLD,IERR)	&lt;br /&gt;
                			&lt;br /&gt;
                call MPI_GATHER(win,2,MPI_REAL,maswin,2,MPI_REAL,0,MPI_COMM_WORLD,IERR)&lt;br /&gt;
                &lt;br /&gt;
                if (rank .eq. 0) then&lt;br /&gt;
                    minDist = maswin(2,1)&lt;br /&gt;
                    jAbsWin = maswin(1,1)&lt;br /&gt;
                    do j=2,size,1&lt;br /&gt;
                        if (mindist .ge. maswin(2,j)) then&lt;br /&gt;
                            minDist = maswin(2,j)&lt;br /&gt;
                            jAbsWin = maswin(1,j)&lt;br /&gt;
                        endif&lt;br /&gt;
                    enddo&lt;br /&gt;
                    call modW(W,n,learning_rate,i,jAbsWin)&lt;br /&gt;
                    end if&lt;br /&gt;
            enddo&lt;br /&gt;
            &lt;br /&gt;
            if (rank .eq. 0) then&lt;br /&gt;
                finish = MPI_WTIME(IERR)&lt;br /&gt;
                open(1,file=&amp;quot;Rezult.txt&amp;quot;,iostat=IOS)&lt;br /&gt;
                do while (.NOT. eof(1))&lt;br /&gt;
                    read(1,*) str&lt;br /&gt;
                enddo&lt;br /&gt;
                write (1,*) &#039;Neurons: &#039;,n,&#039;Processes: &#039;,size,&#039;Time: &#039;,finish-start&lt;br /&gt;
                close(1)&lt;br /&gt;
            end if       &lt;br /&gt;
            &lt;br /&gt;
            call MPI_FINALIZE(IERR)&lt;br /&gt;
            &lt;br /&gt;
            !call printm(W,n,n)&lt;br /&gt;
        &lt;br /&gt;
            deallocate(W,sample,win,maswin,buf)&lt;br /&gt;
            	&lt;br /&gt;
            &lt;br /&gt;
        contains&lt;br /&gt;
        &lt;br /&gt;
        subroutine printm(W,a,b)&lt;br /&gt;
            integer a,b,i,j&lt;br /&gt;
            real W(n,n)&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                write(*,*)(W(i,j), i=1,a)&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine printm&lt;br /&gt;
        &lt;br /&gt;
        subroutine obnul(W,a,b)&lt;br /&gt;
            integer a,b&lt;br /&gt;
            integer i,j&lt;br /&gt;
            real W(a,b)&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                do i=1,a,1&lt;br /&gt;
                    W(i,j) = 0.0&lt;br /&gt;
                enddo&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine obnul&lt;br /&gt;
        &lt;br /&gt;
        real function euclDist(a,b,n)&lt;br /&gt;
            integer n,i&lt;br /&gt;
                real a(n),b(n),res&lt;br /&gt;
                &lt;br /&gt;
                res = 0&lt;br /&gt;
                do i = 1,n,1&lt;br /&gt;
                    res = res + (a(i) - b(i)) * (a(i) - b(i))&lt;br /&gt;
                enddo&lt;br /&gt;
                &lt;br /&gt;
                euclDist = sqrt(res)&lt;br /&gt;
        end function euclDist&lt;br /&gt;
        &lt;br /&gt;
        subroutine modW(W,n,learning_rate,iter,jAbsWin)&lt;br /&gt;
            integer n,iter,JAbsWin&lt;br /&gt;
            real learning_rate,W(n,n)&lt;br /&gt;
            integer i,j&lt;br /&gt;
            &lt;br /&gt;
            do j=1,n,1&lt;br /&gt;
                if (j .ne. jAbsWin) then &lt;br /&gt;
                    do i=1,n,1&lt;br /&gt;
                        W(i,j) = W(i,j) + learning_rate/sqrt(iter+1.0)*(W(i,jAbsWin)-W(i,j))&lt;br /&gt;
                    enddo&lt;br /&gt;
                end if&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine modW&lt;br /&gt;
        &lt;br /&gt;
        subroutine randMatr(matr,a,b,small)&lt;br /&gt;
            integer a,b&lt;br /&gt;
            logical small&lt;br /&gt;
            integer i,j&lt;br /&gt;
            real matr(a,b),x&lt;br /&gt;
            &lt;br /&gt;
            do j=1,b,1&lt;br /&gt;
                do i=1,a,1&lt;br /&gt;
                    call random_seed&lt;br /&gt;
                    call random_number(x)&lt;br /&gt;
                    x = x * 10 - x * 8&lt;br /&gt;
                    if (small) then&lt;br /&gt;
                        x = x / 40&lt;br /&gt;
                    end if&lt;br /&gt;
                    matr(i,j) = x&lt;br /&gt;
                enddo&lt;br /&gt;
            enddo&lt;br /&gt;
        end subroutine randMatr&lt;br /&gt;
    end program Kohonen&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18976</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18976"/>
		<updated>2016-11-22T18:58:45Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Ниже представлен график зависимости времени выполнения от числа потоков и размера сети при MPI реализации. &lt;br /&gt;
[[Файл:Openmp1.PNG|thumb|600px|center| График зависимости времени выполнения от числа потоков и размера сети]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Гистограмма ускорения выполнения алгоритма с различными размерами карт. Хорошо видно, что наибольший эффект достигается на 6-8 потоках.&lt;br /&gt;
[[Файл:Openmp2.PNG|thumb|600px|center| Гистограмма ускорения]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть, на участках от 1 ядра (потока) до 8 программа хорошо масштабируема, но при увеличении количества ядер (потоков) до 9 и более происходит увеличение времени выполнения и [[Ускорение| ускорение]] программы уменьшается вследствие запроса на слишком большое количество ресурсов при относительно небольшом объёме входных данных.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма.&lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **sample;&lt;br /&gt;
    double **W;&lt;br /&gt;
    int inputSize=3;&lt;br /&gt;
    int numNeurons = 10;&lt;br /&gt;
    int iterNum = 2000;&lt;br /&gt;
    double learning_rate = 1;&lt;br /&gt;
    double radius = 0.2;&lt;br /&gt;
    double eucledeDist(double vect1[],double vect2[]) {&lt;br /&gt;
        double sum = 0;&lt;br /&gt;
        for (int i = 0; i &amp;lt;inputSize; ++i){&lt;br /&gt;
            sum += (vect1[i]-vect2[i])*(vect1[i]-vect2[i]);&lt;br /&gt;
        }&lt;br /&gt;
        return sqrt(sum);&lt;br /&gt;
    }&lt;br /&gt;
    double ** getRandomArray(int rows, int cols, int randomize, int init=0){&lt;br /&gt;
        double ** matr = new double* [rows];&lt;br /&gt;
        for (int i = 0; i &amp;lt; rows; ++i){&lt;br /&gt;
            matr[i] = new double[cols]();&lt;br /&gt;
        }&lt;br /&gt;
        if (randomize==1){&lt;br /&gt;
            for (int i = 0; i &amp;lt; rows; ++i){&lt;br /&gt;
                for (int j = 0; j &amp;lt; cols; ++j){&lt;br /&gt;
                    matr[i][j] = (10*rand()-8*rand())/32767.0;&lt;br /&gt;
                    if (init){matr[i][j] /= 40;}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        return matr;&lt;br /&gt;
    }&lt;br /&gt;
    int main()&lt;br /&gt;
    {&lt;br /&gt;
        double **sample = getRandomArray(iterNum,inputSize,1,0);&lt;br /&gt;
        double **W = getRandomArray(numNeurons,inputSize,1,1);&lt;br /&gt;
        //for each epoch&lt;br /&gt;
        for (int iter = 0; iter &amp;lt; iterNum; ++iter){&lt;br /&gt;
            //choose winner&lt;br /&gt;
            int winner_num = 0;&lt;br /&gt;
            double winnerDist = eucledeDist(sample[iter],W[0]);&lt;br /&gt;
            double dist = 0;&lt;br /&gt;
            for (int i = 1; i &amp;lt; numNeurons; ++i){&lt;br /&gt;
                dist = eucledeDist(sample[iter],W[i]);&lt;br /&gt;
                if ( dist &amp;lt; winnerDist) {&lt;br /&gt;
                    winner_num=i;&lt;br /&gt;
                    winnerDist=dist;&lt;br /&gt;
                };&lt;br /&gt;
            }&lt;br /&gt;
            // correct weights&lt;br /&gt;
            double *winner = W[winner_num];&lt;br /&gt;
            for (int i = 0; i &amp;lt; numNeurons; ++i){&lt;br /&gt;
                dist = eucledeDist(winner,W[i]);&lt;br /&gt;
                if (dist&amp;lt;radius &amp;amp;&amp;amp; i!=winner_num) {&lt;br /&gt;
                    for (int j = 0; j &amp;lt; inputSize; ++j){&lt;br /&gt;
                        W[i][j] += learning_rate/sqrt(iter+1) * (winner[j]-W[i][j]);&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&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;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18975</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18975"/>
		<updated>2016-11-22T18:57:55Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Ниже представлен график зависимости времени выполнения от числа потоков и размера сети при OpenMP реализации. &lt;br /&gt;
[[Файл:Openmp1.PNG|thumb|600px|center| График зависимости времени выполнения от числа потоков и размера сети]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Гистограмма ускорения выполнения алгоритма с различными размерами карт. Хорошо видно, что наибольший эффект достигается на 6-8 потоках.&lt;br /&gt;
[[Файл:Openmp2.PNG|thumb|600px|center| Гистограмма ускорения]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть, на участках от 1 ядра (потока) до 8 программа хорошо масштабируема, но при увеличении количества ядер (потоков) до 9 и более происходит увеличение времени выполнения и [[Ускорение| ускорение]] программы уменьшается вследствие запроса на слишком большое количество ресурсов при относительно небольшом объёме входных данных.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма.&lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **sample;&lt;br /&gt;
    double **W;&lt;br /&gt;
    int inputSize=3;&lt;br /&gt;
    int numNeurons = 10;&lt;br /&gt;
    int iterNum = 2000;&lt;br /&gt;
    double learning_rate = 1;&lt;br /&gt;
    double radius = 0.2;&lt;br /&gt;
    double eucledeDist(double vect1[],double vect2[]) {&lt;br /&gt;
        double sum = 0;&lt;br /&gt;
        for (int i = 0; i &amp;lt;inputSize; ++i){&lt;br /&gt;
            sum += (vect1[i]-vect2[i])*(vect1[i]-vect2[i]);&lt;br /&gt;
        }&lt;br /&gt;
        return sqrt(sum);&lt;br /&gt;
    }&lt;br /&gt;
    double ** getRandomArray(int rows, int cols, int randomize, int init=0){&lt;br /&gt;
        double ** matr = new double* [rows];&lt;br /&gt;
        for (int i = 0; i &amp;lt; rows; ++i){&lt;br /&gt;
            matr[i] = new double[cols]();&lt;br /&gt;
        }&lt;br /&gt;
        if (randomize==1){&lt;br /&gt;
            for (int i = 0; i &amp;lt; rows; ++i){&lt;br /&gt;
                for (int j = 0; j &amp;lt; cols; ++j){&lt;br /&gt;
                    matr[i][j] = (10*rand()-8*rand())/32767.0;&lt;br /&gt;
                    if (init){matr[i][j] /= 40;}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        return matr;&lt;br /&gt;
    }&lt;br /&gt;
    int main()&lt;br /&gt;
    {&lt;br /&gt;
        double **sample = getRandomArray(iterNum,inputSize,1,0);&lt;br /&gt;
        double **W = getRandomArray(numNeurons,inputSize,1,1);&lt;br /&gt;
        //for each epoch&lt;br /&gt;
        for (int iter = 0; iter &amp;lt; iterNum; ++iter){&lt;br /&gt;
            //choose winner&lt;br /&gt;
            int winner_num = 0;&lt;br /&gt;
            double winnerDist = eucledeDist(sample[iter],W[0]);&lt;br /&gt;
            double dist = 0;&lt;br /&gt;
            for (int i = 1; i &amp;lt; numNeurons; ++i){&lt;br /&gt;
                dist = eucledeDist(sample[iter],W[i]);&lt;br /&gt;
                if ( dist &amp;lt; winnerDist) {&lt;br /&gt;
                    winner_num=i;&lt;br /&gt;
                    winnerDist=dist;&lt;br /&gt;
                };&lt;br /&gt;
            }&lt;br /&gt;
            // correct weights&lt;br /&gt;
            double *winner = W[winner_num];&lt;br /&gt;
            for (int i = 0; i &amp;lt; numNeurons; ++i){&lt;br /&gt;
                dist = eucledeDist(winner,W[i]);&lt;br /&gt;
                if (dist&amp;lt;radius &amp;amp;&amp;amp; i!=winner_num) {&lt;br /&gt;
                    for (int j = 0; j &amp;lt; inputSize; ++j){&lt;br /&gt;
                        W[i][j] += learning_rate/sqrt(iter+1) * (winner[j]-W[i][j]);&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&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;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18894</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18894"/>
		<updated>2016-11-21T21:25:27Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; {{Assignment}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Ниже представлен график зависимости времени выполнения от числа потоков и размера сети при OpenMP реализации. &lt;br /&gt;
[[Файл:Openmp1.PNG|thumb|600px|center| График зависимости времени выполнения от числа потоков и размера сети]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Гистограмма ускорения выполнения алгоритма с различными размерами карт. Хорошо видно, что наибольший эффект достигается на 6-8 потоках.&lt;br /&gt;
[[Файл:Openmp2.PNG|thumb|600px|center| Гистограмма ускорения]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть, на участках от 1 ядра (потока) до 8 программа хорошо масштабируема, но при увеличении количества ядер (потоков) до 9 и более происходит увеличение времени выполнения и [[Ускорение| ускорение]] программы уменьшается вследствие запроса на слишком большое количество ресурсов при относительно небольшом объёме входных данных.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма.&lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **sample;&lt;br /&gt;
    double **W;&lt;br /&gt;
    int inputSize=3;&lt;br /&gt;
    int numNeurons = 10;&lt;br /&gt;
    int iterNum = 2000;&lt;br /&gt;
    double learning_rate = 1;&lt;br /&gt;
    double radius = 0.2;&lt;br /&gt;
    double eucledeDist(double vect1[],double vect2[]) {&lt;br /&gt;
        double sum = 0;&lt;br /&gt;
        for (int i = 0; i &amp;lt;inputSize; ++i){&lt;br /&gt;
            sum += (vect1[i]-vect2[i])*(vect1[i]-vect2[i]);&lt;br /&gt;
        }&lt;br /&gt;
        return sqrt(sum);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    double ** getRandomArray(int rows, int cols, int randomize, int init=0){&lt;br /&gt;
        double ** matr = new double* [rows];&lt;br /&gt;
        for (int i = 0; i &amp;lt; rows; ++i){&lt;br /&gt;
            matr[i] = new double[cols]();&lt;br /&gt;
        }&lt;br /&gt;
        if (randomize==1){&lt;br /&gt;
            for (int i = 0; i &amp;lt; rows; ++i){&lt;br /&gt;
                for (int j = 0; j &amp;lt; cols; ++j){&lt;br /&gt;
                    matr[i][j] = (10*rand()-8*rand())/32767.0;&lt;br /&gt;
                    if (init){matr[i][j] /= 40;}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        return matr;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int main()&lt;br /&gt;
    {&lt;br /&gt;
        double **sample = getRandomArray(iterNum,inputSize,1,0);&lt;br /&gt;
        double **W = getRandomArray(numNeurons,inputSize,1,1);&lt;br /&gt;
&lt;br /&gt;
        //for each epoch&lt;br /&gt;
        for (int iter = 0; iter &amp;lt; iterNum; ++iter){&lt;br /&gt;
&lt;br /&gt;
            //choose winner&lt;br /&gt;
            int winner_num = 0;&lt;br /&gt;
            double winnerDist = eucledeDist(sample[iter],W[0]);&lt;br /&gt;
            double dist = 0;&lt;br /&gt;
            for (int i = 1; i &amp;lt; numNeurons; ++i){&lt;br /&gt;
                dist = eucledeDist(sample[iter],W[i]);&lt;br /&gt;
                if ( dist &amp;lt; winnerDist) {&lt;br /&gt;
                    winner_num=i;&lt;br /&gt;
                    winnerDist=dist;&lt;br /&gt;
                };&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // correct weights&lt;br /&gt;
            double *winner = W[winner_num];&lt;br /&gt;
            for (int i = 0; i &amp;lt; numNeurons; ++i){&lt;br /&gt;
                dist = eucledeDist(winner,W[i]);&lt;br /&gt;
                if (dist&amp;lt;radius &amp;amp;&amp;amp; i!=winner_num) {&lt;br /&gt;
                    for (int j = 0; j &amp;lt; inputSize; ++j){&lt;br /&gt;
                        W[i][j] += learning_rate/sqrt(iter+1) * (winner[j]-W[i][j]);&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
            }&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;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18893</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18893"/>
		<updated>2016-11-21T21:24:23Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; {{Assignment}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Ниже представлен график зависимости времени выполнения от числа потоков и размера сети при OpenMP реализации. &lt;br /&gt;
[[Файл:Openmp1.PNG|thumb|600px|center| График зависимости времени выполнения от числа потоков и размера сети]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Гистограмма ускорения выполнения алгоритма с различными размерами карт. Хорошо видно, что наибольший эффект достигается на 6-8 потоках.&lt;br /&gt;
[[Файл:Openmp2.PNG|thumb|600px|center| Гистограмма ускорения]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть, на участках от 1 ядра (потока) до 8 программа хорошо масштабируема, но при увеличении количества ядер (потоков) до 9 и более происходит увеличение времени выполнения и [[Ускорение| ускорение]] программы уменьшается вследствие запроса на слишком большое количество ресурсов при относительно небольшом объёме входных данных.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма.&lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
&lt;br /&gt;
    double **sample;&lt;br /&gt;
    double **W;&lt;br /&gt;
    int inputSize=3;&lt;br /&gt;
    int numNeurons = 10;&lt;br /&gt;
    int iterNum = 2000;&lt;br /&gt;
    double learning_rate = 1;&lt;br /&gt;
    double radius = 0.2;&lt;br /&gt;
&lt;br /&gt;
    double eucledeDist(double vect1[],double vect2[]) {&lt;br /&gt;
        double sum = 0;&lt;br /&gt;
        for (int i = 0; i &amp;lt;inputSize; ++i){&lt;br /&gt;
            sum += (vect1[i]-vect2[i])*(vect1[i]-vect2[i]);&lt;br /&gt;
        }&lt;br /&gt;
        return sqrt(sum);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    double ** getRandomArray(int rows, int cols, int randomize, int init=0){&lt;br /&gt;
        double ** matr = new double* [rows];&lt;br /&gt;
        for (int i = 0; i &amp;lt; rows; ++i){&lt;br /&gt;
            matr[i] = new double[cols]();&lt;br /&gt;
        }&lt;br /&gt;
        if (randomize==1){&lt;br /&gt;
            for (int i = 0; i &amp;lt; rows; ++i){&lt;br /&gt;
                for (int j = 0; j &amp;lt; cols; ++j){&lt;br /&gt;
                    matr[i][j] = (10*rand()-8*rand())/32767.0;&lt;br /&gt;
                    if (init){matr[i][j] /= 40;}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        return matr;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    int main()&lt;br /&gt;
    {&lt;br /&gt;
        double **sample = getRandomArray(iterNum,inputSize,1,0);&lt;br /&gt;
        double **W = getRandomArray(numNeurons,inputSize,1,1);&lt;br /&gt;
&lt;br /&gt;
        //for each epoch&lt;br /&gt;
        for (int iter = 0; iter &amp;lt; iterNum; ++iter){&lt;br /&gt;
&lt;br /&gt;
            //choose winner&lt;br /&gt;
            int winner_num = 0;&lt;br /&gt;
            double winnerDist = eucledeDist(sample[iter],W[0]);&lt;br /&gt;
            double dist = 0;&lt;br /&gt;
            for (int i = 1; i &amp;lt; numNeurons; ++i){&lt;br /&gt;
                dist = eucledeDist(sample[iter],W[i]);&lt;br /&gt;
                if ( dist &amp;lt; winnerDist) {&lt;br /&gt;
                    winner_num=i;&lt;br /&gt;
                    winnerDist=dist;&lt;br /&gt;
                };&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            // correct weights&lt;br /&gt;
            double *winner = W[winner_num];&lt;br /&gt;
            for (int i = 0; i &amp;lt; numNeurons; ++i){&lt;br /&gt;
                dist = eucledeDist(winner,W[i]);&lt;br /&gt;
                if (dist&amp;lt;radius &amp;amp;&amp;amp; i!=winner_num) {&lt;br /&gt;
                    for (int j = 0; j &amp;lt; inputSize; ++j){&lt;br /&gt;
                        W[i][j] += learning_rate/sqrt(iter+1) * (winner[j]-W[i][j]);&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&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;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18230</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=18230"/>
		<updated>2016-11-18T18:11:25Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; {{Assignment}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Ниже представлен график зависимости времени выполнения от числа потоков и размера сети при OpenMP реализации. &lt;br /&gt;
[[Файл:Openmp1.PNG|thumb|600px|center| График зависимости времени выполнения от числа потоков и размера сети]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Гистограмма ускорения выполнения алгоритма с различными размерами карт. Хорошо видно, что наибольший эффект достигается на 6-8 потоках.&lt;br /&gt;
[[Файл:Openmp2.PNG|thumb|600px|center| Гистограмма ускорения]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть, на участках от 1 ядра (потока) до 8 программа хорошо масштабируема, но при увеличении количества ядер (потоков) до 9 и более происходит увеличение времени выполнения и [[Ускорение| ускорение]] программы уменьшается вследствие запроса на слишком большое количество ресурсов при относительно небольшом объёме входных данных.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=17081</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=17081"/>
		<updated>2016-11-14T17:23:35Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; {{Assignment}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Как было описано в [[1.8 | п. 1.8]], для алгоритма кластеризации имеет место массовый параллелизм, поскольку основные этапы алгоритма (поиск евклидовых расстояний для определения нейрона-победителя и обновление весов) информационно независимы, что означает хорошую масштабируемость алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Ниже представлен график зависимости времени выполнения от числа потоков и размера сети при OpenMP реализации. &lt;br /&gt;
[[Файл:Openmp1.PNG|thumb|600px|center| График зависимости времени выполнения от числа потоков и размера сети]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Гистограмма ускорения выполнения алгоритма с различными размерами карт. Хорошо видно, что наибольший эффект достигается на 6-8 потоках.&lt;br /&gt;
[[Файл:Openmp2.PNG|thumb|600px|center| Гистограмма ускорения]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Сравнительные результаты реализаций самоорганизующихся карт с помощью Fortran-OpenMP и C-Thread:&lt;br /&gt;
[[Файл:Compare.PNG|thumb|600px|center| Время выполнения (сверху) и ускорение (снизу) в зависимости от числа процессоров]]&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть, на участках от 1 ядра (потока) до 8 программа хорошо масштабируема, но при увеличении количества ядер (потоков) до 9 и более происходит увеличение времени выполнения и [[Ускорение| ускорение]] программы уменьшается вследствие запроса на слишком большое количество ресурсов при относительно небольшом объёме входных данных.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=16803</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=16803"/>
		<updated>2016-11-13T21:29:29Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; {{Assignment|Teplov}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
[[Файл:Openmp1.PNG|thumb|600px|center| описание]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Openmp2.PNG|thumb|600px|center| описание]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Compare.PNG|thumb|600px|center| описание]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=16802</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=16802"/>
		<updated>2016-11-13T21:28:49Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; {{Assignment|Teplov}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
[[Файл:Openmp1.png|thumb|600px|center| описание]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Openmp2.png|thumb|600px|center| описание]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Compare.png|thumb|600px|center| описание]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Compare.PNG&amp;diff=16799</id>
		<title>Файл:Compare.PNG</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Compare.PNG&amp;diff=16799"/>
		<updated>2016-11-13T21:28:31Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Openmp2.PNG&amp;diff=16797</id>
		<title>Файл:Openmp2.PNG</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Openmp2.PNG&amp;diff=16797"/>
		<updated>2016-11-13T21:28:10Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Openmp1.PNG&amp;diff=16796</id>
		<title>Файл:Openmp1.PNG</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Openmp1.PNG&amp;diff=16796"/>
		<updated>2016-11-13T21:27:08Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=16788</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=16788"/>
		<updated>2016-11-13T21:25:06Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; {{Assignment|Teplov}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 2.4, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.4, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15204</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15204"/>
		<updated>2016-10-31T18:04:36Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15203</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15203"/>
		<updated>2016-10-31T18:02:41Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.6, 1.7, 1.8, 1.9, 1.10, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15202</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15202"/>
		<updated>2016-10-31T18:00:43Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.7, 1.8, 1.9, 1.10, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15201</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15201"/>
		<updated>2016-10-31T18:00:26Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.7, 1.8, 1.9, 1.10, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&#039;&#039;&#039;Объем входные данных:&#039;&#039;&#039; так как обучение происходит не на всем входном векторе, а только на количестве векторов равном &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, то алгоритм может быть организован так, чтобы принять на выход только &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; случайных векторов из исходной выборки. И, соответственно, объем входных данных можно считать равным &amp;lt;math&amp;gt;m*T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов.&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; равен &amp;lt;math&amp;gt;m*k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15191</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=15191"/>
		<updated>2016-10-31T17:20:38Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]] (1.1, 1.2, 1.4, 1.5, 1.6, 1.7, 1.9, 1.10)&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]] (1.2, 1.3, 1.7, 1.8, 1.9, 1.10, 2.7)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обучения сети без учителя==== &lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
==== Инициализация начальных весов==== &lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
==== Функция соседства нейронов==== &lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &lt;br /&gt;
 &amp;lt;math&amp;gt;&lt;br /&gt;
 h(d,t) = \begin{cases}&lt;br /&gt;
   c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
   0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &lt;br /&gt;
 &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
==== Функция скорости обучения сети==== &lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=10909</id>
		<title>Обсуждение участника:Lineprinter</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=10909"/>
		<updated>2016-10-15T17:46:35Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Перенос */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Перенос ==&lt;br /&gt;
Статья: [[Кластеризация сетями Кохонена]]&lt;br /&gt;
Выполняют: [[Участник:Kravtsovkirill| Кравцов Кирилл]] и [[Участник:Emaksimov| Максимов Егор]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нахождение собственных чисел квадратной матрицы методом QR разложения (2)]]&lt;br /&gt;
Выполняют: Баев Олег и Шевелев Александр&lt;br /&gt;
&lt;br /&gt;
Статья: [[Стабилизированный метод биспоряженных градиентов (BiCGSTAB)]]&lt;br /&gt;
Выполняют: Гаврилов Алексей и Новиков Александр&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участники: Бобошко А., Юмакаева А./Решение начальной задачи Коши для системы ОДУ методом Рунге-Кутта 4-го порядка]];&lt;br /&gt;
Выполняют: Бобошко Алексей и Юмакаева Алина&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на сетях Кохоннена]];&lt;br /&gt;
Выполняют:  Логвиненко Александра и Адиев Тохтар&lt;br /&gt;
&lt;br /&gt;
Статья: [[Ортогонализация Грама-Шмидта]];&lt;br /&gt;
Выполняют: [[Участник:KibAndrey| Кибанов Андрей]] и Аджиева Татьяна&lt;br /&gt;
&lt;br /&gt;
Статья: [[Самоорганизующиеся карты Кохонена]];&lt;br /&gt;
Выполняет: [[Участник:Anton goy| Гой Антон]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[ЕМ-алгоритм_(Тематическое_моделирование)]];&lt;br /&gt;
Выполняют: Мурат Апишев и Андрей Заночкин&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_Ланцоша_с_полной_переортогонализацией]];&lt;br /&gt;
Выполняет:[[Участник:Sfedotov| Федотов С.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_k-средних]]&lt;br /&gt;
Выполняют: [[Участник:Error2407|Богомазов Евгений]], [[Участник:Илья_Егоров|Егоров Илья]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм k-means]]&lt;br /&gt;
Выполняют: [[Участник:Бротиковская Данута|Данута Бротиковская]] и [[Участник:DennZo1993|Денис Зобнин]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий_алгоритм_С_средних]]&lt;br /&gt;
Выполняют: [[Участник:Demon smd|Д.А.Гуськов]], [[Участник:marina abramenkova|М.А.Абраменкова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Решение_задачи_Коши_для_системы_ОДУ_методом_Рунге-Кутты_4_порядка]];&lt;br /&gt;
Выполняют: [[Участник:Алимов_Дамир_Алиевич|Алимов Дамир]] и [[Участник:Anlesnichiy|Антон Лесничий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Строгий_алгоритм_С_средних_(Hard_C-Means,_HCM)]];&lt;br /&gt;
Выполняют: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]] и [[Участник:Юрий_Комаров|Комаров Юрий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на минимальном остовном дереве]];&lt;br /&gt;
Выполняет: [[Участник:Astandrik | Стандрик Антон Сергеевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняет: [[Участник:Lexaloris | Новоселов Алексей]], Выполняет: [[Участник:pahom | Кочетков Павел]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(3)|Нахождение собственных чисел квадратной матрицы методом QR разложения (3)]];&lt;br /&gt;
Выполняют: [[Участник:Смирнова_Александра|Смирнова А.С.]], [[Участник:Александра_Киямова|Киямова А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Якоби_вычисления_сингулярных_чисел_и_векторов]];&lt;br /&gt;
Выполняют: [[Участница:Почернина_Елена| Почернина Елена]] и [[Участница:Светлана|Костюкова Светлана]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Ньютона_для_решения_систем_нелинейных_уравнений(2)]];&lt;br /&gt;
Выполняют: [[Участник:Oleggium|Гирняк О.Р.]], [[Участник:Dimx19|Васильков Д.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений]];&lt;br /&gt;
Выполняют: [[Участник:Cookie|Шатков С.А.]], [[Участница:JuliaA|Антохина Ю.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_преобразование_Фурье_(FFT)|Быстрое преобразование Фурье (FFT)]];&lt;br /&gt;
Выполняют: [[Участник:Victoria_Stepanischeva|Степанищева Виктория]] и [[Участник:Igor_Munkin|Мунькин Игорь]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_дискретное_преобразование_Фурье|Быстрое_дискретное_преобразование_Фурье]];&lt;br /&gt;
Выполняют: [[Участник:ivanov.kir.m | К.М.Иванов]], [[Участник:Pumpkin | А.C.Сапин]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_средних]]&lt;br /&gt;
Выполняют: [[Участник:Parkhomenko|Пархоменко Павел]], [[Участник:ivan.mashonskiy|Машонский Иван]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[EM-алгоритм_кластеризации]]&lt;br /&gt;
Выполняет: [[Участник:Noite|Зинченко Дмитрий]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_means]]&lt;br /&gt;
Выполняют: [[Участник:IanaV| Валуйская Яна]], [[Участник:GlotovES| Глотов Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы ЗП |Метод Якоби вычисления собственных значений симметричной матрицы ЗП]];&lt;br /&gt;
Выполняют: [[Участник:Зиновьев Владимир|Зиновьев В.С.]], [[Участник:Пронин Андрей|Пронин А.М.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_кластеризации,_основанный_на_минимальном_покрывающем_дереве]]&lt;br /&gt;
Выполняет: [[Участник:Kanast74|Дмитриева Анастасия]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(4)]]&lt;br /&gt;
Выполняют: [[Участник:F-morozov|Морозов Ф. В.]], [[Участник:Nataliya|Пащенко Н. Ф.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Хранение_ненулевых_элементов_разреженных_матриц._Умножение_разреженной_матрицы_на_вектор]];&lt;br /&gt;
Выполняют: [[Участник:Trrufina|Третьякова Р.М.]] и [[Участник:Екатерина_Буторина|Буторина Е.В.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений2]];&lt;br /&gt;
Выполняет: [[Участник:Лукьянова Анна|Лукьянова А.Я.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы]];&lt;br /&gt;
Выполняют: [[Участник: Galkina|Галкина А.С.]], [[Участник: Игорь|Плахов И.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод рекурсивной координатной бисекции]];&lt;br /&gt;
Выполняют: [[Участник: Obirvalger|Гордеев Михаил]], [[Участник: KolmakovEA|Колмаков Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Итерационный метод решения системы линейных алгебраических уравнений GMRES (обобщенный метод минимальных невязок)]];&lt;br /&gt;
Выполняют: [[Участник: Эльвира Ахиярова|Ахиярова Эльвира]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Хранение ненулевых элементов разреженной матрицы. Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняют: [[Участник: Janyell|Сычева Евгения]], [[Участник: Ahahalin|Хахалин Анатолий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Построение матрицы Адамара произвольного размера]];&lt;br /&gt;
Выполняют: [[Участник: Бугаков Юрий|Бугаков Юрий]], Кужамалиев Ернур&lt;br /&gt;
&lt;br /&gt;
Статья: [[Вычисление определенного интеграла с использованием адаптивно сгущающейся сетки (1)]]&lt;br /&gt;
Выполняют: [[Участница:Sannikovats| Санникова Татьяна Сергеевна]], [[Участник:Plukshin| Лукшин Петр Андреевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на построении каркаса]];&lt;br /&gt;
Выполняют: [[Участник:SenderovichNikita| Сендерович Никита]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на максимизации ожидания]];&lt;br /&gt;
Выполняют: Готман Мария, Лукашкина Юлия&lt;br /&gt;
&lt;br /&gt;
Статья: [[Partitioning_Around_Medoids_(PAM)]]&lt;br /&gt;
Выполняют: [[Участник:Avasilenko|А.Э.Василенко]], [[Участник:Anastasia|А.В.Тузикова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм С-средних (Fuzzy C-means)]]&lt;br /&gt;
Выполняют: [[Участник:Nikmedoed|Н.А. Муромцев]], [[Участник:illusive_mike|М.С. Дворецкий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм C средних]]&lt;br /&gt;
Выполняют: [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Плотностный алгоритм кластеризации DBSCAN]]&lt;br /&gt;
Выполняют: [[Участник:Elena777mc|Малахова Е.С.]], [[Участник:Жаннат_Сагиолданова|Сагиолданова Ж.]]&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=10900</id>
		<title>Обсуждение участника:Lineprinter</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=10900"/>
		<updated>2016-10-15T17:45:08Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Перенос */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Перенос ==&lt;br /&gt;
Статья: [[Кластеризация сетями Кохонена]]&lt;br /&gt;
Выполняют: Кравцов Кирилл и Максимов Егор&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нахождение собственных чисел квадратной матрицы методом QR разложения (2)]]&lt;br /&gt;
Выполняют: Баев Олег и Шевелев Александр&lt;br /&gt;
&lt;br /&gt;
Статья: [[Стабилизированный метод биспоряженных градиентов (BiCGSTAB)]]&lt;br /&gt;
Выполняют: Гаврилов Алексей и Новиков Александр&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участники: Бобошко А., Юмакаева А./Решение начальной задачи Коши для системы ОДУ методом Рунге-Кутта 4-го порядка]];&lt;br /&gt;
Выполняют: Бобошко Алексей и Юмакаева Алина&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на сетях Кохоннена]];&lt;br /&gt;
Выполняют:  Логвиненко Александра и Адиев Тохтар&lt;br /&gt;
&lt;br /&gt;
Статья: [[Ортогонализация Грама-Шмидта]];&lt;br /&gt;
Выполняют: [[Участник:KibAndrey| Кибанов Андрей]] и Аджиева Татьяна&lt;br /&gt;
&lt;br /&gt;
Статья: [[Самоорганизующиеся карты Кохонена]];&lt;br /&gt;
Выполняет: [[Участник:Anton goy| Гой Антон]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[ЕМ-алгоритм_(Тематическое_моделирование)]];&lt;br /&gt;
Выполняют: Мурат Апишев и Андрей Заночкин&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_Ланцоша_с_полной_переортогонализацией]];&lt;br /&gt;
Выполняет:[[Участник:Sfedotov| Федотов С.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_k-средних]]&lt;br /&gt;
Выполняют: [[Участник:Error2407|Богомазов Евгений]], [[Участник:Илья_Егоров|Егоров Илья]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм k-means]]&lt;br /&gt;
Выполняют: [[Участник:Бротиковская Данута|Данута Бротиковская]] и [[Участник:DennZo1993|Денис Зобнин]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий_алгоритм_С_средних]]&lt;br /&gt;
Выполняют: [[Участник:Demon smd|Д.А.Гуськов]], [[Участник:marina abramenkova|М.А.Абраменкова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Решение_задачи_Коши_для_системы_ОДУ_методом_Рунге-Кутты_4_порядка]];&lt;br /&gt;
Выполняют: [[Участник:Алимов_Дамир_Алиевич|Алимов Дамир]] и [[Участник:Anlesnichiy|Антон Лесничий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Строгий_алгоритм_С_средних_(Hard_C-Means,_HCM)]];&lt;br /&gt;
Выполняют: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]] и [[Участник:Юрий_Комаров|Комаров Юрий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на минимальном остовном дереве]];&lt;br /&gt;
Выполняет: [[Участник:Astandrik | Стандрик Антон Сергеевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняет: [[Участник:Lexaloris | Новоселов Алексей]], Выполняет: [[Участник:pahom | Кочетков Павел]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(3)|Нахождение собственных чисел квадратной матрицы методом QR разложения (3)]];&lt;br /&gt;
Выполняют: [[Участник:Смирнова_Александра|Смирнова А.С.]], [[Участник:Александра_Киямова|Киямова А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Якоби_вычисления_сингулярных_чисел_и_векторов]];&lt;br /&gt;
Выполняют: [[Участница:Почернина_Елена| Почернина Елена]] и [[Участница:Светлана|Костюкова Светлана]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Ньютона_для_решения_систем_нелинейных_уравнений(2)]];&lt;br /&gt;
Выполняют: [[Участник:Oleggium|Гирняк О.Р.]], [[Участник:Dimx19|Васильков Д.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений]];&lt;br /&gt;
Выполняют: [[Участник:Cookie|Шатков С.А.]], [[Участница:JuliaA|Антохина Ю.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_преобразование_Фурье_(FFT)|Быстрое преобразование Фурье (FFT)]];&lt;br /&gt;
Выполняют: [[Участник:Victoria_Stepanischeva|Степанищева Виктория]] и [[Участник:Igor_Munkin|Мунькин Игорь]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_дискретное_преобразование_Фурье|Быстрое_дискретное_преобразование_Фурье]];&lt;br /&gt;
Выполняют: [[Участник:ivanov.kir.m | К.М.Иванов]], [[Участник:Pumpkin | А.C.Сапин]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_средних]]&lt;br /&gt;
Выполняют: [[Участник:Parkhomenko|Пархоменко Павел]], [[Участник:ivan.mashonskiy|Машонский Иван]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[EM-алгоритм_кластеризации]]&lt;br /&gt;
Выполняет: [[Участник:Noite|Зинченко Дмитрий]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_means]]&lt;br /&gt;
Выполняют: [[Участник:IanaV| Валуйская Яна]], [[Участник:GlotovES| Глотов Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы ЗП |Метод Якоби вычисления собственных значений симметричной матрицы ЗП]];&lt;br /&gt;
Выполняют: [[Участник:Зиновьев Владимир|Зиновьев В.С.]], [[Участник:Пронин Андрей|Пронин А.М.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_кластеризации,_основанный_на_минимальном_покрывающем_дереве]]&lt;br /&gt;
Выполняет: [[Участник:Kanast74|Дмитриева Анастасия]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(4)]]&lt;br /&gt;
Выполняют: [[Участник:F-morozov|Морозов Ф. В.]], [[Участник:Nataliya|Пащенко Н. Ф.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Хранение_ненулевых_элементов_разреженных_матриц._Умножение_разреженной_матрицы_на_вектор]];&lt;br /&gt;
Выполняют: [[Участник:Trrufina|Третьякова Р.М.]] и [[Участник:Екатерина_Буторина|Буторина Е.В.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений2]];&lt;br /&gt;
Выполняет: [[Участник:Лукьянова Анна|Лукьянова А.Я.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы]];&lt;br /&gt;
Выполняют: [[Участник: Galkina|Галкина А.С.]], [[Участник: Игорь|Плахов И.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод рекурсивной координатной бисекции]];&lt;br /&gt;
Выполняют: [[Участник: Obirvalger|Гордеев Михаил]], [[Участник: KolmakovEA|Колмаков Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Итерационный метод решения системы линейных алгебраических уравнений GMRES (обобщенный метод минимальных невязок)]];&lt;br /&gt;
Выполняют: [[Участник: Эльвира Ахиярова|Ахиярова Эльвира]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Хранение ненулевых элементов разреженной матрицы. Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняют: [[Участник: Janyell|Сычева Евгения]], [[Участник: Ahahalin|Хахалин Анатолий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Построение матрицы Адамара произвольного размера]];&lt;br /&gt;
Выполняют: [[Участник: Бугаков Юрий|Бугаков Юрий]], Кужамалиев Ернур&lt;br /&gt;
&lt;br /&gt;
Статья: [[Вычисление определенного интеграла с использованием адаптивно сгущающейся сетки (1)]]&lt;br /&gt;
Выполняют: [[Участница:Sannikovats| Санникова Татьяна Сергеевна]], [[Участник:Plukshin| Лукшин Петр Андреевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на построении каркаса]];&lt;br /&gt;
Выполняют: [[Участник:SenderovichNikita| Сендерович Никита]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на максимизации ожидания]];&lt;br /&gt;
Выполняют: Готман Мария, Лукашкина Юлия&lt;br /&gt;
&lt;br /&gt;
Статья: [[Partitioning_Around_Medoids_(PAM)]]&lt;br /&gt;
Выполняют: [[Участник:Avasilenko|А.Э.Василенко]], [[Участник:Anastasia|А.В.Тузикова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм С-средних (Fuzzy C-means)]]&lt;br /&gt;
Выполняют: [[Участник:Nikmedoed|Н.А. Муромцев]], [[Участник:illusive_mike|М.С. Дворецкий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм C средних]]&lt;br /&gt;
Выполняют: [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Плотностный алгоритм кластеризации DBSCAN]]&lt;br /&gt;
Выполняют: [[Участник:Elena777mc|Малахова Е.С.]], [[Участник:Жаннат_Сагиолданова|Сагиолданова Ж.]]&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10880</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10880"/>
		<updated>2016-10-15T17:41:25Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10839</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10839"/>
		<updated>2016-10-15T17:32:18Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых норм, (функция &amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;2m-1&amp;lt;/math&amp;gt; операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения и один квадратный корень. (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*количество операций на корректировку весов одного нейрона можно оценить как &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак, как уже было сказано, общая последовательная сложность алгоритма составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох обучения (итераций), &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов (иначе говоря, количество нейронов во входном слое сети Кохонена), &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество кластеров (иначе говоря, количество нейронов во втором слое сети - слое Кохонена).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10798</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10798"/>
		<updated>2016-10-15T17:22:24Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|550px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10795</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10795"/>
		<updated>2016-10-15T17:21:56Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|450px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10791</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10791"/>
		<updated>2016-10-15T17:21:30Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле:&lt;br /&gt;
 &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10788</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10788"/>
		<updated>2016-10-15T17:21:06Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
#Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
#Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10778</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10778"/>
		<updated>2016-10-15T17:19:35Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
    1. Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
    2. Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
    3. Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10775</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10775"/>
		<updated>2016-10-15T17:18:42Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
1. Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
2. Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
3. Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10773</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10773"/>
		<updated>2016-10-15T17:18:10Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10768</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10768"/>
		<updated>2016-10-15T17:17:35Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Литература */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;br /&gt;
# Нейский И.М. Классификация и сравнение методов кластеризации http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10752</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10752"/>
		<updated>2016-10-15T17:13:30Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10747</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=10747"/>
		<updated>2016-10-15T17:13:04Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рис. 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Риc. 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
 &lt;br /&gt;
# Teuvo Kohonen, Self-Organizing Maps/Helsinki University of Technology,1997/Second Edition.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Kravtsovkirill&amp;diff=9509</id>
		<title>Участник:Kravtsovkirill</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:Kravtsovkirill&amp;diff=9509"/>
		<updated>2016-10-15T12:39:08Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: Новая страница: «ВМК МГУ, 620 группа»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ВМК МГУ, 620 группа&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9491</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9491"/>
		<updated>2016-10-15T12:35:33Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 1. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 2. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Рис. 3. Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Рис. 4. Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Рис. 5. Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9474</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9474"/>
		<updated>2016-10-15T12:32:45Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(mnT)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*log(max(m,n)))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(max(mk,mn))&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кирилл Кравцов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Первый этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Второй этап алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(T * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9437</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9437"/>
		<updated>2016-10-15T12:18:49Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{i} \neq \mathbf{c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Первый ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Второй ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(t * \log max(m,n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9388</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9388"/>
		<updated>2016-10-15T12:07:28Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм кластеризации можно разбить на следующие этапы:&lt;br /&gt;
*Инициализация &amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{X} \leftarrow ChooseRandomVector(\mathbf{V})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется вычисление расстояний &amp;lt;math&amp;gt;\mathbf{D_i} \leftarrow CalculateEucledeNorm(X, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Выбор победителя &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вложенный цикл, в котором осуществляется корректировка весов &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t:=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} := ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} := CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} := ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i:=1 \ \mathbf{TO} \ N \ \mathbf{DO} \ \mathbf{AND} \ \mathbf{W_i} \neq \mathbf{W_c}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} := CorrectWeights(\mathbf{W_i(t)}, \mathbf{W_c})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Первый ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Второй ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. &lt;br /&gt;
Этап Winner заключается в поиске минимума по подсчитанным расстояниям для определения нейрона-победителя. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
Этап Correct состоит из нескольких операций, но асимптотически сложность определяет именно подсчет евклидова расстояния. Аналогично получаем, что сложность данного этапа составляет &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговую параллельную сложность кластеризации сетями Кохонена можно оценить как &amp;lt;math&amp;gt;O(t * \log nm^{2})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9364</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9364"/>
		<updated>2016-10-15T11:59:28Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Первый ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Второй ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + PComplexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;PComplexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Этап Norm заключается в параллельном вычислении евклидовых норм. Сложность этого этапа можно оценить с учетом доступности неограниченного числа процессоров как &amp;lt;math&amp;gt;O(\log m)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина векторов. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. Таким образом, сложность этапа распределения векторов по кластерам &amp;lt;math&amp;gt;O(\log mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельная сложность этапа обновления центров масс кластеров вычисляется следующим образом: так как обновление значений каждого из центров масс кластеров можно выполнять независимо, параллельная сложность определяется сложностью обновления центра масс самого большого кластера. В худшем случае для нахождения значения выражения &amp;lt;math&amp;gt;\mu^{(t+1)}_j = \frac{1}{|S^{(t)}_i|} \sum_{x_j \in S^{(t)}_i} x_j &amp;lt;/math&amp;gt; требуется &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
С учетом вышесказанного, итоговая параллельная сложность алгоритма k средних определяется выражением &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9204</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9204"/>
		<updated>2016-10-15T11:06:18Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Первый ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph4.png|thumb|600px|center| Второй ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма кластеризации сетями Кохонена средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (поиска евклидовых расстояний для определения нейрона-победителя и обновления весов) лежат информационно независимые действия.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;Complexity = T * (PComplexity_{Norm} + Complexity_{Winner} + PComplexity_{Correct})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;PComplexity_{Norm}&amp;lt;/math&amp;gt; - параллельная сложность поиска евклидовых расстояний для определения нейрона-победителя, &amp;lt;math&amp;gt;PComplexity_{Correct}&amp;lt;/math&amp;gt; - параллельная сложность обновления весов нейронов, &amp;lt;math&amp;gt;Complexity_{Winner}&amp;lt;/math&amp;gt; - сложность глобального поиска минимального значения расстояния, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - количество эпох (итераций) алгоритма.&lt;br /&gt;
&lt;br /&gt;
Параллельная сложность этапа распределения векторов по кластерам с учетом доступности неограниченного числа процессоров вычисляется следующим образом: так как вычисление значений &amp;lt;math&amp;gt;\big \| x_i - \mu^{(t)}_j \big \|^2&amp;lt;/math&amp;gt; для каждой пары векторов &amp;lt;math&amp;gt;x_i, i = 1, 2, ..., n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mu^{(t)}_j, j = 1, 2, ..., k&amp;lt;/math&amp;gt; можно выполнять независимо и для вычисления этого выражения требуется &amp;lt;math&amp;gt;O(\log d)&amp;lt;/math&amp;gt; операций в соответствии с [[Нахождение_частных_сумм_элементов_массива_сдваиванием | параллельной реализацией нахождения сумм элементов массива сдваиванием]]. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log k)&amp;lt;/math&amp;gt;. Таким образом, сложность этапа распределения векторов по кластерам &amp;lt;math&amp;gt;O(\log kd)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельная сложность этапа обновления центров масс кластеров вычисляется следующим образом: так как обновление значений каждого из центров масс кластеров можно выполнять независимо, параллельная сложность определяется сложностью обновления центра масс самого большого кластера. В худшем случае для нахождения значения выражения &amp;lt;math&amp;gt;\mu^{(t+1)}_j = \frac{1}{|S^{(t)}_i|} \sum_{x_j \in S^{(t)}_i} x_j &amp;lt;/math&amp;gt; требуется &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
С учетом вышесказанного, итоговая параллельная сложность алгоритма k средних определяется выражением &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9170</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9170"/>
		<updated>2016-10-15T10:56:33Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Первый ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм кластеризации k средних имеет место массовый параллелизм: в основе каждого из основных этапов алгоритма (распределения векторов по кластерам и обновления центров масс кластеров) лежат циклы, итерации которых являются информационно независимыми.&lt;br /&gt;
Учитывая данный факт можно оценить параллельную сложность алгоритма в предположении доступности неограниченного числа необходимых процессоров.&lt;br /&gt;
&lt;br /&gt;
В силу особенностей алгоритма k средних порядок выполнения основных этапов существенен, что не позволяет выполнять их параллельно. Таким образом, итоговая сложность параллельного алгоритма будет определяться, исходя из формулы &amp;lt;math&amp;gt;T = t * (T_{as} + T_{up})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{as}&amp;lt;/math&amp;gt; - параллельная сложность этапа распределения векторов по кластерам, &amp;lt;math&amp;gt;T_{up}&amp;lt;/math&amp;gt; - параллельная сложность этапа обновления центров масс кластеров, &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - общее число итераций алгоритма.&lt;br /&gt;
&lt;br /&gt;
Параллельная сложность этапа распределения векторов по кластерам с учетом доступности неограниченного числа процессоров вычисляется следующим образом: так как вычисление значений &amp;lt;math&amp;gt;\big \| x_i - \mu^{(t)}_j \big \|^2&amp;lt;/math&amp;gt; для каждой пары векторов &amp;lt;math&amp;gt;x_i, i = 1, 2, ..., n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mu^{(t)}_j, j = 1, 2, ..., k&amp;lt;/math&amp;gt; можно выполнять независимо и для вычисления этого выражения требуется &amp;lt;math&amp;gt;O(\log d)&amp;lt;/math&amp;gt; операций в соответствии с [[Нахождение_частных_сумм_элементов_массива_сдваиванием | параллельной реализацией нахождения сумм элементов массива сдваиванием]]. Параллельная сложность реализации операции нахождения минимума из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; элементов определяется как &amp;lt;math&amp;gt;O(\log k)&amp;lt;/math&amp;gt;. Таким образом, сложность этапа распределения векторов по кластерам &amp;lt;math&amp;gt;O(\log kd)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельная сложность этапа обновления центров масс кластеров вычисляется следующим образом: так как обновление значений каждого из центров масс кластеров можно выполнять независимо, параллельная сложность определяется сложностью обновления центра масс самого большого кластера. В худшем случае для нахождения значения выражения &amp;lt;math&amp;gt;\mu^{(t+1)}_j = \frac{1}{|S^{(t)}_i|} \sum_{x_j \in S^{(t)}_i} x_j &amp;lt;/math&amp;gt; требуется &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
С учетом вышесказанного, итоговая параллельная сложность алгоритма k средних определяется выражением &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9158</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9158"/>
		<updated>2016-10-15T10:51:13Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Первый ярус алгоритма]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9149</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9149"/>
		<updated>2016-10-15T10:50:25Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
[[Файл:Graph3.png|thumb|600px|center| Параллельная схема поиска победителя]]&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций вычисления евклидового расстояния до случайно выбранного входного вектора. &lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем значение расстояние соответствующего нейрона. &lt;br /&gt;
Далее находим минимальное расстояние, тем самым определим нейрона победителя.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций коррекций весов.&lt;br /&gt;
&lt;br /&gt;
На выходе, собрав из каждой ветки откорректированный вектор весов, получаем обновленную матрицу весов, которая используется на следующей эпохе.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9059</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=9059"/>
		<updated>2016-10-15T10:35:11Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Общая схема работы алгоритма выглядит следующим образом:&lt;br /&gt;
[[Файл:Graph2.png|thumb|400px|center| Общая схема работы алгоритма кластеризации]]&lt;br /&gt;
Здесь In - входные данные, Init - шаг, на котором происходит инициализация весов, Norm - вычисление расстояний, Win - выбор победителя, Correct - корректировка весов, Out - выходные данные.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=8875</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=8875"/>
		<updated>2016-10-15T09:48:56Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. Сложность евклидового расстояния растет линейно с увеличением длины вектора. Следовательно получаем сложность данного шага &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Сложность обновления веса одного нейрона линейно зависит от &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Т.е. сложность данного шага также &amp;lt;math&amp;gt;O(mn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем, что для всего алгоритма с количеством эпох равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; сложность составляет &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=8848</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=8848"/>
		<updated>2016-10-15T09:35:52Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. На вычисление каждого евклидового расстояния требуется  &lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Тогда для обновления весов всех &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; нейронов (кроме &amp;quot;победителя&amp;quot;) требуется&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com Matlab realization]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf SAS EM]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=8846</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=8846"/>
		<updated>2016-10-15T09:34:59Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. На вычисление каждого евклидового расстояния требуется  &lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Тогда для обновления весов всех &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; нейронов (кроме &amp;quot;победителя&amp;quot;) требуется&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Вычислительная мощность алгоритма кластеризации сетями Кохонена равна &amp;lt;math&amp;gt;\frac{m*n*T}{m*k+m*n} = \frac{n*T}{k+n}&amp;lt;/math&amp;gt;, где, напомним, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число нейронов выходного слоя, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Описанный алгоритм кластеризации случайно выбирает элемент входного множества, следовательно, не является детерминированным. Как и все простые сети, построенный алгоритм является устойчивым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&#039;&#039;Сильные и слабые стороны алгоритма&#039;&#039;&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://cran.r-project.org/web/packages/kohonen/ kohonen] Бибилиотека для R&lt;br /&gt;
* [https://pypi.python.org/pypi/kohonen kohonen] Бибилиотека для Python&lt;br /&gt;
* [http://knnl.sourceforge.net/ KNNL]: C++ бибилиотека.&lt;br /&gt;
* [https://www.mathworks.com/help/nnet/ug/cluster-with-self-organizing-map-neural-network.html?requestedDomain=www.mathworks.com]: Реализация в Matlab.&lt;br /&gt;
* [http://jknnl.sourceforge.net/ JKNNL]: Библиотека для Java.&lt;br /&gt;
* [https://support.sas.com/documentation/onlinedoc/miner/casestudy_59123.pdf]: Реализация в SAS Enterprise Miner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельные реализации:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/peterwittek/somoclu Somoclu]: Библиотека для Python, R, Julia, и Matlab с поддержкой OpenMP, MPI и CUDA.&lt;/div&gt;</summary>
		<author><name>Kravtsovkirill</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=8802</id>
		<title>Участник:Emaksimov/Кластеризация сетями Кохонена</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:Emaksimov/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81%D0%B5%D1%82%D1%8F%D0%BC%D0%B8_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0&amp;diff=8802"/>
		<updated>2016-10-15T09:11:33Z</updated>

		<summary type="html">&lt;p&gt;Kravtsovkirill: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Кластеризация сетями Кохонена&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tmn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mk&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(t * \log kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(kdn)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы страницы &amp;lt;b&amp;gt;[[Участник:Emaksimov|Егор Максимов]]&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;[[Участник:Kravtsovkirill|Кравц Кириллов]]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Искусственная нейронная сеть Кохонена&#039;&#039;&#039; или самоорганизующаяся карта признаков (SOM) была предложена финским исследователем Тойво Кохоненом в начале 1980-х годов.&lt;br /&gt;
[[Файл:Teuvokohonen.jpg|thumb|150px|right|Рисунок 2. Кохонен, Теуво.]]&lt;br /&gt;
Она представляет собой двухслойную сеть. Каждый нейрон первого (распределительного) слоя соединен со всеми нейронами второго (выходного) слоя, которые расположены в виде двумерной решетки. Для визуализации топологии слоя Кохонена используют либо шестиугольные, либо прямоугольные ячейки, в которых распологаются нейроны. Шестиугольные ячейки часто являются более предпочтительными, так как расстояние от центра выбранной ячейки до ее соседей одинаково.Нейроны выходного слоя называются кластерными элементами, их количество определят максимальное количество групп, на которые система может разделить входные данные. Увеличивая количество нейронов второго слоя можно увеличивать детализацию результатов процесса кластеризации.&lt;br /&gt;
&lt;br /&gt;
Система работает по принципу соревнования – нейроны второго слоя соревнуются друг с другом за право наилучшим образом сочетаться с входным вектором сигналов, побеждает тот элемент-нейрон, чей вектор весов ближе всего к входному вектору сигналов. За меру близости двух векторов можно взять квадрат евклидова расстояния. Таким образом, каждый входной вектор относится к некоторому кластерному элементу.&lt;br /&gt;
&lt;br /&gt;
Для обучения сети Кохонена используется соревновательный метод. На каждом шаге обучения из исходного набора данных случайно выбирается один вектор. Затем производится поиск нейрона выходного слоя, для которого расстояние между его вектором весов и входным вектором - минимально.&lt;br /&gt;
По определённому правилу производится корректировка весов для нейрона-победителя и нейронов из его окрестности, которая задаётся соответствующей функцией окрестности. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
[[Файл:FNaEm.png|thumb|350px|right|Рисунок 1. Кластеризация сетями Кохонена]]&lt;br /&gt;
Пусть имеется некоторое множество векторов &amp;lt;math&amp;gt; x^{(i)}=(x_1^{(i)},x_2^{(i)},...,x_m^{(i)}) \in \mathbb{R}^m,  i=1, \dots, k&amp;lt;/math&amp;gt;. Заранее зададим количество кластеров равным &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Соответственно, Карта Кохонена представляет собой двухслойную fully-connected нейронную сеть, где первый слой состоит из &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; нейронов, а второй - из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый j-ый нейрон описывается вектором весов &amp;lt;math&amp;gt; w_j=(w_{1j},w_{2j},...,w_{mj}),  j=1, \dots, n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм обучения сети без учителя&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Обучение состоит из последовательности коррекций векторов, представляющих собой нейроны. Сначала следует инициализировать векторы весов. Далее определенное количество раз (эпох) производятся следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Случайным образов выбирается вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; из входных данных.&lt;br /&gt;
&lt;br /&gt;
# Выбирается нейрон-победитель &amp;lt;math&amp;gt;w_c&amp;lt;/math&amp;gt; &amp;quot;наиболее похожий&amp;quot; (по евклидову расстоянию) на вектор &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; ||x(t)-w_c||=\min\limits_{i}(||x(t)-w_i(t)||)&amp;lt;/math&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
# Веса всех нейронов обновляются по формуле: &lt;br /&gt;
           &amp;lt;center&amp;gt; &amp;lt;math&amp;gt; w_i(t+1)=w_i(t)+\alpha(t)h_{ic}(t)||x(t)-w_i(t)||&amp;lt;/math&amp;gt;, &amp;lt;/center&amp;gt; &lt;br /&gt;
где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - номер эпохи, &amp;lt;math&amp;gt; h_{ic}(t)&amp;lt;/math&amp;gt;- функция соседства нейронов,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha (t)&amp;lt;/math&amp;gt; - функция скорости обучения сети.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация начальных весов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Инициализация случайными значениями, когда всем весам даются малые случайные величины.&lt;br /&gt;
Инициализация примерами, когда в качестве начальных значений задаются значения случайно выбранных примеров из обучающей выборки&lt;br /&gt;
Линейная инициализация. В этом случае веса инициируются значениями векторов, линейно упорядоченных вдоль линейного подпространства, проходящего между двумя главных собственными векторами исходного набора данных. Собственные вектора могут быть найдены например при помощи процедуры Грама-Шмидта.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция соседства нейронов&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Функции от расстояния применяются двух видов: &lt;br /&gt;
&lt;br /&gt;
Константа: &amp;lt;math&amp;gt;&lt;br /&gt;
h(d,t) = \begin{cases}&lt;br /&gt;
  c,  &amp;amp; \mbox{if } n \ d&amp;lt;=\delta \\&lt;br /&gt;
  0, &amp;amp; \mbox{if } n \ d&amp;gt;\delta&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Функция Гаусса: &amp;lt;math&amp;gt;h_{ic}(t)=\exp(-\frac{\|r_c-r_i\|^2}{2\sigma^2(t)})&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; определяет положение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го нейрона в сетке&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Функция скорости обучения сети&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Главное требование к ней - монотонное убывание при возрастании &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; для замедления темпов вариации весов нейронов слоя Кохонена.&lt;br /&gt;
Функция может быть задана, например, как &amp;lt;math&amp;gt;\alpha(t)=\frac{A}{B+t}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - некоторые константы.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию (эпоху):&lt;br /&gt;
*Вычисление расстояния от случайно выбранного вектора &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; до каждого нейрона и выбор нейрона с наименьшим расстоянием. Т.е. вычисление &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; евклидовых расстояний и сортировка полученного массива расстояний. На вычисление каждого евклидового расстояния требуется  &lt;br /&gt;
*Обновление весов всех нейронов. Пусть используется гауссовская функция для вычисления расстояний между нейронами. Тогда для обновления весов всех &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; нейронов (кроме &amp;quot;победителя&amp;quot;) требуется&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{W} \leftarrow ComputeInitialWeights(\mathbf{W})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее следует цикл, повторяющийся &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; (максимальное число &amp;quot;эпох&amp;quot;) раз:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i} \leftarrow CalculateEucledeNorm(\mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mathbf{W_i(t+1)}\leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\mathbf{W}&amp;lt;/math&amp;gt; - матрица весов, &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt; - максимальное число &amp;quot;эпох&amp;quot;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - мощность входного множества, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - число нейронов выходного слоя. Тогда схема реализации последовательного алгоритма будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{W} := InitializeWeights()&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathbf{FOR} \ t=1 \ \mathbf{TO} \ T_{max} \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt; \quad \mathbf{X} \leftarrow ChooseRandomVector\left( \{1, \dots, k\} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{D} \leftarrow CalculateEucledeNorm(\mathbf{X}, \mathbf{W_i})&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;\mathbf{FOR} \ i=1 \ \mathbf{TO} \ N \ \mathbf{DO}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_c} \leftarrow ChooseWinner(\mathbf{D})&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mathbf{W_i(t+1)} \leftarrow CorrectWeights(\mathbf{W_i(t)})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вычислительную сложность описанного алгоритма. Основная часть операций алгоритма приходится на вложенные циклы, где &lt;br /&gt;
*выполняется вычисление &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; евклидовых норм, функция (&amp;lt;math&amp;gt;CalculateEucledeNorm&amp;lt;/math&amp;gt;), на вычисление каждой из которых требуется по &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math&amp;gt;m*(N-1)&amp;lt;/math&amp;gt; операций сложения (&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность входных векторов) для вычисления всех норм&lt;br /&gt;
*на сравнение &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных чисел (функция &amp;lt;math&amp;gt;ChooseWinner&amp;lt;/math&amp;gt;)&lt;br /&gt;
*на корректировку весов - порядка &amp;lt;math&amp;gt;m*N&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; множество входных векторов (нейронов первого уровня), множество кластеров (выходов, нейронов второго уровня), максимальное число &amp;quot;эпох&amp;quot; &amp;lt;math&amp;gt;T_{max}&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt; \delta &amp;lt;/math&amp;gt;, константы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, константа &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; (в случае, если выбрана простая константа).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; матрица весов&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Устойчивость к зашумленным данным, быстрое и неуправляемое обучение, возможность упрощения многомерных входных данных с помощью визуализации.&lt;br /&gt;
Главное преимущество самоорганизующихся карт Кохонена является их способность &amp;quot;проецирования&amp;quot; многомерных пространств на двумерное. Важной особенностью карт Кохонена является то, что объекты с похожими характеристиками (по всем компонентам) располагаются рядом, образуя кластеры.&lt;br /&gt;
&lt;br /&gt;
Визуализация данных в виде двумерной карты позволяет проводить кластеризацию данных и значительно упрощает корреляционный анализ.&lt;br /&gt;
Важным недостатком является то, что окончательный результат работы нейронных сетей зависит от начальных установок сети. С другой стороны, нейронные сети теоретически могут аппроксимировать любую непрерывную функцию, что позволяет исследователю не принимать заранее какие-либо гипотезы относительно модели.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;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>Kravtsovkirill</name></author>
	</entry>
</feed>