<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=31.173.28.101&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=31.173.28.101&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%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/31.173.28.101"/>
		<updated>2026-08-04T13:48:43Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%B1%D0%BB%D0%B8%D0%B6%D0%B0%D0%B9%D1%88%D0%B8%D1%85_%D1%81%D0%BE%D1%81%D0%B5%D0%B4%D0%B5%D0%B9_%D1%81_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B3%D0%BE_%D0%BC%D0%B0%D0%BB%D0%B5%D0%BD%D1%8C%D0%BA%D0%BE%D0%B3%D0%BE_%D0%BC%D0%B8%D1%80%D0%B0&amp;diff=73234</id>
		<title>Поиск ближайших соседей с помощью иерархического маленького мира</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%B1%D0%BB%D0%B8%D0%B6%D0%B0%D0%B9%D1%88%D0%B8%D1%85_%D1%81%D0%BE%D1%81%D0%B5%D0%B4%D0%B5%D0%B9_%D1%81_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B3%D0%BE_%D0%BC%D0%B0%D0%BB%D0%B5%D0%BD%D1%8C%D0%BA%D0%BE%D0%B3%D0%BE_%D0%BC%D0%B8%D1%80%D0%B0&amp;diff=73234"/>
				<updated>2020-03-24T14:45:30Z</updated>
		
		<summary type="html">&lt;p&gt;31.173.28.101: /* Операции над структурой */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Иерархический маленький мир''' (англ. ''Hierarchical Navigable Small World'') {{---}} структура данных, позволяющая эффективно искать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; почти что ближайших соседей на больших множествах вершин.&lt;br /&gt;
Поиск ближайших соседей нужен в задачах [[Общие понятия|классификации]] и [[кластеризация|кластеризации]].&lt;br /&gt;
&lt;br /&gt;
По своей концепции напоминает [[список с пропусками]].&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Представим себе ситуацию:&lt;br /&gt;
* У социальной сети есть &amp;lt;tex&amp;gt;10^{11}&amp;lt;/tex&amp;gt; пользовательских фотографий с отмеченными лицами на них.&lt;br /&gt;
* По новой фотографии требуется быстро узнать кто на ней и предложить пользователю отметить этого человека.&lt;br /&gt;
&lt;br /&gt;
Возможный процесс:&lt;br /&gt;
# Обучаем [https://github.com/davidsandberg/facenet FaceNet] выдавать &amp;lt;tex&amp;gt;128&amp;lt;/tex&amp;gt;-мерные вектора по изображению лица, такие, что у фотографий одного человека похожие значения векторов.&lt;br /&gt;
# Добавляем &amp;lt;tex&amp;gt;10^{11}&amp;lt;/tex&amp;gt; векторов в иерархический маленький мир.&lt;br /&gt;
# При добавлении новой фотографии, вычисляем соответствующий лицу вектор.&lt;br /&gt;
# Ищем &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; его ближайших соседей.&lt;br /&gt;
# Классифицируем лицо с использованием [[Метрический классификатор и метод ближайших соседей#Использование ядер сглаживания|ядер сглаживания]].&lt;br /&gt;
# Если пользователь подтвердил нашу догадку, добавляем этот вектор в иерархический маленький мир.&lt;br /&gt;
&lt;br /&gt;
==Маленький мир==&lt;br /&gt;
[[Файл:SmallWorld_Greedy.png|мини|500px|Жадный поиск ближайшего соседа. &lt;br /&gt;
Чёрные ребра {{---}} короткие связи с соседями в небольшом радиусе &amp;lt;tex&amp;gt;R&amp;lt;/tex&amp;gt;, красные рёбра {{---}} длинные связи, созданные по какой-то эвристике, обеспечивающие логарифмическое мат. ожидание длины пути.&lt;br /&gt;
[https://www.hse.ru/mirror/pubs/lib/data/access/ram/ticket/30/1551306415713d428dca7fd05f3d108fe8e66042c4/Approximate%20nearest%20neighbor%20algorithm%20based%20on%20navigable%20(Information%20Systems).pdf Оригинал]]]&lt;br /&gt;
'''Маленький мир''' (англ. ''Small World'') {{---}} граф, в котором мат. ожидание кратчайшего пути между двумя случайно выбранными вершинами растёт пропорционально &amp;lt;tex&amp;gt;\log{N}&amp;lt;/tex&amp;gt;. Но при этом средняя степень вершины мала.&lt;br /&gt;
&lt;br /&gt;
Для маленького мира на точках в Евклидовом пространстве жадный поиск &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; ближайших соседей будет выглядеть так:&lt;br /&gt;
 '''knn'''(V, E, request, m, k)''':'''&lt;br /&gt;
     W = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие к q вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     C = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вершины, которые предстоит посетить. &amp;lt;/font&amp;gt;&lt;br /&gt;
     V = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Посещённые вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' i = 1 '''to''' m&lt;br /&gt;
         C = С &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;random_v&amp;lt;/tex&amp;gt; v &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; G&lt;br /&gt;
         TN = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие вершины в этом проходе.&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''while''' ''true''&lt;br /&gt;
             u = {q1 | &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt; q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; C, |q - q1| &amp;lt;= |q - q2|} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшая к q вершина из C. &amp;lt;/font&amp;gt;&lt;br /&gt;
             C = C &amp;lt;tex&amp;gt;\setminus&amp;lt;/tex&amp;gt; u&lt;br /&gt;
             '''if''' u дальше чем k-й элемент W&lt;br /&gt;
                 '''break'''&lt;br /&gt;
             '''for''' e: (u, e) '''in''' G&lt;br /&gt;
                 '''if''' e &amp;lt;tex&amp;gt;{\notin}&amp;lt;/tex&amp;gt; V&lt;br /&gt;
                     C = C &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                     V = V &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                     TN = TN &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
         W = W &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; TN&lt;br /&gt;
     '''return''' k ближайших к q вершин из W&lt;br /&gt;
&lt;br /&gt;
Расстояние между вершинами графа может измеряться [[Метрический классификатор и метод ближайших соседей#Использование различных метрик расстояния|различными метриками]]. &amp;lt;br/&amp;gt;&lt;br /&gt;
Очевидный недостаток этого алгоритма {{---}} опасность свалиться в локальный минимум, остановившись в каком-то кластере. С увеличением числа &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, вероятность такого застревания экспоненциально падает.&lt;br /&gt;
&lt;br /&gt;
==Описание структуры==&lt;br /&gt;
'''Иерархический Маленький мир''' {{---}} слоистая структура графов. На нулевом слое представлены все &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; вершин из исходной выборки. Вершина, присутствующая на уровне &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; так же присутствует на уровне &amp;lt;tex&amp;gt;L + 1&amp;lt;/tex&amp;gt; с вероятностью &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Т.е. кол-во слоёв растет как &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;. Количество соседей каждой вершины на каждом уровне ограниченно константой, что позволяет делать запросы на добавление и удаление вершины за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[Файл:HNSW.png|мини|500px|Иерархический маленький мир. [https://arxiv.org/abs/1603.09320 Источник]]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
==Операции над структурой==&lt;br /&gt;
&lt;br /&gt;
===Поиск ближайших соседей в слое===&lt;br /&gt;
Жадно идём по уровню в сторону запроса.   &lt;br /&gt;
 '''searchLayer'''(q, ep, ef, layer)''':'''&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входные данные: иерархия графов hnsw, запрос q, входные точки ep, искомое количество ближайших соседей ef, номер слоя layer.&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Возвращает: ef ближайших соседей q в слое layer.&amp;lt;/font&amp;gt;&lt;br /&gt;
     W = {ep}  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие к q вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     C = {ep}  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вершины, которые предстоит посетить. &amp;lt;/font&amp;gt;&lt;br /&gt;
     V = {ep}  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Посещённые вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' C != &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;&lt;br /&gt;
         u = {q1 | &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt; q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; C, |q - q1| &amp;lt;= |q - q2|} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшая к q вершина из C. &amp;lt;/font&amp;gt;&lt;br /&gt;
         f = {q1 | &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt; q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; W, |q - q1| &amp;gt;= |q - q2|} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Самая дальняя от q вершина из W. &amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' |u - q| &amp;gt; |f - q|&lt;br /&gt;
             '''break''' &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Мы в локальном минимуме. &amp;lt;/font&amp;gt;&lt;br /&gt;
         '''for''' e : (u, e) '''in''' G&lt;br /&gt;
             '''if''' e &amp;lt;tex&amp;gt;{\notin}&amp;lt;/tex&amp;gt; V&lt;br /&gt;
                 V = V &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                 f = {q1 | &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt; q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; W, |q - q1| &amp;gt;= |q - q2|} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Самая дальняя от q вершина из W. &amp;lt;/font&amp;gt;&lt;br /&gt;
                 '''if''' |e - q| &amp;lt; |f - q| or |W| &amp;lt; ef&lt;br /&gt;
                     C = C &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                     W = W &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                     if |W| &amp;gt; ef&lt;br /&gt;
                         W = W \ f&lt;br /&gt;
     '''return''' W&lt;br /&gt;
&lt;br /&gt;
===Поиск ближайших соседей во всей структуре===&lt;br /&gt;
[[Файл:HnswSearch.png|мини|500px|Жадный поиск вершины.&lt;br /&gt;
[https://arxiv.org/abs/1603.09320 Оригинал]]]&lt;br /&gt;
# Идём с верхнего уровня до первого:&lt;br /&gt;
## Жадно ищем ближайшую к &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; вершину на текущем уровне.&lt;br /&gt;
## Спускаемся в соответствующую соседу вершине на уровень ниже.&lt;br /&gt;
# На нулевом уровне жадно ищем &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; ближайших соседей.&lt;br /&gt;
 '''knn'''(hnsw, q, k, ef)''':'''&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входные данные: иерархия графов hnsw, запрос q, искомое количество ближайших соседей  k, количество кандидатов при поиске ef. &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Возвращает: k ближайших соседей q. &amp;lt;/font&amp;gt;&lt;br /&gt;
     W = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие к q вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     mL = |hnsw| - 1&lt;br /&gt;
     ep = &amp;lt;tex&amp;gt;random_v&amp;lt;/tex&amp;gt; v &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; hnsw[mL]&lt;br /&gt;
     '''for''' level = mL to 1&lt;br /&gt;
         W = searchLayer(hnsw, q, ep, ef=1, level) &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// На каждом уровне, кроме нижнего мы ищем всего одну ближайшую вершину. &amp;lt;/font&amp;gt;&lt;br /&gt;
         ep = W&lt;br /&gt;
     W = searchLayer(hnsw, q, ep, ef, lc=0)&lt;br /&gt;
     '''return''' k ближайших к q вершин из W&lt;br /&gt;
&lt;br /&gt;
===Вставка элемента===&lt;br /&gt;
# Случайным образом выбираем максимальный слой, на котором будет представлена &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# На каждом уровне, где будет представлена &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;, сверху вниз:&lt;br /&gt;
## Жадно ищем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; ближайших к &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
## Добавляем связи &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; с ними.&lt;br /&gt;
## Удаляем лишние связи у новообразовавшихся соседей.&lt;br /&gt;
 '''insert'''(hnsw, q, m, mMax, ef, mL)''':'''&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входные данные: иерархия графов hnsw, запрос на добавление q, желаемое количество связей m, максимальное количество связей вершины &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//       на одном слое mMax, количество кандидатов при поиске ef, коэффициент выбора высоты mL. &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Возвращает: hnsw с вставленным элементом q. &amp;lt;/font&amp;gt;&lt;br /&gt;
     W = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие к q вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     mL = |hnsw| - 1&lt;br /&gt;
     ep = &amp;lt;tex&amp;gt;random_v&amp;lt;/tex&amp;gt; v &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; hnsw[mL]&lt;br /&gt;
     qL = -ln(rand(eps, 1.0)) * mL &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Верхний слой для вершины q. &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' level = mL to qL + 1&lt;br /&gt;
         W = searchLayer(q, ep, ef=1, level)&lt;br /&gt;
         ep = W&lt;br /&gt;
     '''for''' level = min(mL, qL) to 0&lt;br /&gt;
         W = searchLayer(q, ep, ef, level)&lt;br /&gt;
         neighbours = M ближайших к q вершин из W&lt;br /&gt;
         '''for''' n &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; neighbours:&lt;br /&gt;
             &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем двусторонние связи между n и q. &amp;lt;/font&amp;gt;&lt;br /&gt;
             hnsw[level] = hnsw[level] &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; (n, q)&lt;br /&gt;
             hnsw[level] = hnsw[level] &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; (q, n)&lt;br /&gt;
             &lt;br /&gt;
             nNeighbours = {v| (v, n) '''in''' hnsw[level]} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ищем всех соседей n на уровне level. &amp;lt;/font&amp;gt;&lt;br /&gt;
             &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Убираем лишние связи, если требуется. &amp;lt;/font&amp;gt;&lt;br /&gt;
             '''if''' nNeighbours.Count() &amp;gt; mMax&lt;br /&gt;
                 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Самая дальняя от n вершина, смежняя с ней. &amp;lt;/font&amp;gt;&lt;br /&gt;
                 v = {q1 | (q2, n) &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; nNeighbours &amp;amp; &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt;q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; hnsw[level], |q - q1| &amp;gt;= |q - q2|}&lt;br /&gt;
                 hnsw[level] = hnsw[level] &amp;lt;tex&amp;gt;\setminus&amp;lt;/tex&amp;gt; (n, v)&lt;br /&gt;
                 hnsw[level] = hnsw[level] &amp;lt;tex&amp;gt;\setminus&amp;lt;/tex&amp;gt; (v, n)&lt;br /&gt;
         ep = W&lt;br /&gt;
     '''if''' qL &amp;gt; mL&lt;br /&gt;
         '''for''' level = mL to qL&lt;br /&gt;
             hnsw.append({q, {}})&lt;br /&gt;
&lt;br /&gt;
== Практическое использование ==&lt;br /&gt;
В библиотеке [https://github.com/nmslib/hnswlib Hnswlib] есть реализация иерархического маленького мира. Эта библиотека написана на C++, с биндингами на python.&lt;br /&gt;
Пример использования:&lt;br /&gt;
 '''import''' hnswlib&lt;br /&gt;
 '''import''' numpy '''as''' np&lt;br /&gt;
 &lt;br /&gt;
 dim = 128&lt;br /&gt;
 num_elements = 10000&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Создаём тестовые данные.&amp;lt;/font&amp;gt;&lt;br /&gt;
 data = np.float32(np.random.random((num_elements, dim)))&lt;br /&gt;
 data_labels = np.arange(num_elements)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Создаём иерархический маленький мир в L2.&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Возможные метрики {{---}} l2, cosine, ip (L2, косинус угла между векторами, скалярное произведение).&amp;lt;/font&amp;gt;&lt;br /&gt;
 p = hnswlib.Index(space = 'l2', dim = dim)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Инициализируем структуру.&amp;lt;/font&amp;gt;&lt;br /&gt;
 p.init_index(max_elements = num_elements, ef_construction = 200, M = 16)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Добавляем данные (можно вызывать много раз).&amp;lt;/font&amp;gt;&lt;br /&gt;
 p.add_items(data, data_labels)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Настраиваем качество, выставляя ef:&amp;lt;/font&amp;gt;&lt;br /&gt;
 p.set_ef(50) &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# ef должно быть &amp;gt; k&amp;lt;/font&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Делаем запрос.&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# k - количество ближайших вершин&amp;lt;/font&amp;gt;&lt;br /&gt;
 labels, distances = p.knn_query(data, k = 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;
* [https://arxiv.org/abs/1603.09320 Yu. A. Malkov, D. A. Yashunin {{---}} Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs]&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/%D0%9C%D0%B8%D1%80_%D1%82%D0%B5%D1%81%D0%B5%D0%BD_(%D0%B3%D1%80%D0%B0%D1%84) Википедия {{---}} Мир тесен (граф)]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Small-world_network Wikipedia {{---}} Small-world network]&lt;br /&gt;
* [https://github.com/sgjurano/ysda-celebrity-faces Поиск знаменитостей на фотографии с помощью иерархического маленького мира]&lt;br /&gt;
* [https://m.habr.com/ru/company/mailru/blog/338360/ Статья от Mail.ru об использовании иерархического маленького мира]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;/div&gt;</summary>
		<author><name>31.173.28.101</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%B1%D0%BB%D0%B8%D0%B6%D0%B0%D0%B9%D1%88%D0%B8%D1%85_%D1%81%D0%BE%D1%81%D0%B5%D0%B4%D0%B5%D0%B9_%D1%81_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B3%D0%BE_%D0%BC%D0%B0%D0%BB%D0%B5%D0%BD%D1%8C%D0%BA%D0%BE%D0%B3%D0%BE_%D0%BC%D0%B8%D1%80%D0%B0&amp;diff=73233</id>
		<title>Поиск ближайших соседей с помощью иерархического маленького мира</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%B1%D0%BB%D0%B8%D0%B6%D0%B0%D0%B9%D1%88%D0%B8%D1%85_%D1%81%D0%BE%D1%81%D0%B5%D0%B4%D0%B5%D0%B9_%D1%81_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B3%D0%BE_%D0%BC%D0%B0%D0%BB%D0%B5%D0%BD%D1%8C%D0%BA%D0%BE%D0%B3%D0%BE_%D0%BC%D0%B8%D1%80%D0%B0&amp;diff=73233"/>
				<updated>2020-03-24T14:44:02Z</updated>
		
		<summary type="html">&lt;p&gt;31.173.28.101: /* Поиск ближайших соседей в слое */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Иерархический маленький мир''' (англ. ''Hierarchical Navigable Small World'') {{---}} структура данных, позволяющая эффективно искать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; почти что ближайших соседей на больших множествах вершин.&lt;br /&gt;
Поиск ближайших соседей нужен в задачах [[Общие понятия|классификации]] и [[кластеризация|кластеризации]].&lt;br /&gt;
&lt;br /&gt;
По своей концепции напоминает [[список с пропусками]].&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Представим себе ситуацию:&lt;br /&gt;
* У социальной сети есть &amp;lt;tex&amp;gt;10^{11}&amp;lt;/tex&amp;gt; пользовательских фотографий с отмеченными лицами на них.&lt;br /&gt;
* По новой фотографии требуется быстро узнать кто на ней и предложить пользователю отметить этого человека.&lt;br /&gt;
&lt;br /&gt;
Возможный процесс:&lt;br /&gt;
# Обучаем [https://github.com/davidsandberg/facenet FaceNet] выдавать &amp;lt;tex&amp;gt;128&amp;lt;/tex&amp;gt;-мерные вектора по изображению лица, такие, что у фотографий одного человека похожие значения векторов.&lt;br /&gt;
# Добавляем &amp;lt;tex&amp;gt;10^{11}&amp;lt;/tex&amp;gt; векторов в иерархический маленький мир.&lt;br /&gt;
# При добавлении новой фотографии, вычисляем соответствующий лицу вектор.&lt;br /&gt;
# Ищем &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; его ближайших соседей.&lt;br /&gt;
# Классифицируем лицо с использованием [[Метрический классификатор и метод ближайших соседей#Использование ядер сглаживания|ядер сглаживания]].&lt;br /&gt;
# Если пользователь подтвердил нашу догадку, добавляем этот вектор в иерархический маленький мир.&lt;br /&gt;
&lt;br /&gt;
==Маленький мир==&lt;br /&gt;
[[Файл:SmallWorld_Greedy.png|мини|500px|Жадный поиск ближайшего соседа. &lt;br /&gt;
Чёрные ребра {{---}} короткие связи с соседями в небольшом радиусе &amp;lt;tex&amp;gt;R&amp;lt;/tex&amp;gt;, красные рёбра {{---}} длинные связи, созданные по какой-то эвристике, обеспечивающие логарифмическое мат. ожидание длины пути.&lt;br /&gt;
[https://www.hse.ru/mirror/pubs/lib/data/access/ram/ticket/30/1551306415713d428dca7fd05f3d108fe8e66042c4/Approximate%20nearest%20neighbor%20algorithm%20based%20on%20navigable%20(Information%20Systems).pdf Оригинал]]]&lt;br /&gt;
'''Маленький мир''' (англ. ''Small World'') {{---}} граф, в котором мат. ожидание кратчайшего пути между двумя случайно выбранными вершинами растёт пропорционально &amp;lt;tex&amp;gt;\log{N}&amp;lt;/tex&amp;gt;. Но при этом средняя степень вершины мала.&lt;br /&gt;
&lt;br /&gt;
Для маленького мира на точках в Евклидовом пространстве жадный поиск &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; ближайших соседей будет выглядеть так:&lt;br /&gt;
 '''knn'''(V, E, request, m, k)''':'''&lt;br /&gt;
     W = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие к q вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     C = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вершины, которые предстоит посетить. &amp;lt;/font&amp;gt;&lt;br /&gt;
     V = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Посещённые вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' i = 1 '''to''' m&lt;br /&gt;
         C = С &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;random_v&amp;lt;/tex&amp;gt; v &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; G&lt;br /&gt;
         TN = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие вершины в этом проходе.&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''while''' ''true''&lt;br /&gt;
             u = {q1 | &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt; q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; C, |q - q1| &amp;lt;= |q - q2|} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшая к q вершина из C. &amp;lt;/font&amp;gt;&lt;br /&gt;
             C = C &amp;lt;tex&amp;gt;\setminus&amp;lt;/tex&amp;gt; u&lt;br /&gt;
             '''if''' u дальше чем k-й элемент W&lt;br /&gt;
                 '''break'''&lt;br /&gt;
             '''for''' e: (u, e) '''in''' G&lt;br /&gt;
                 '''if''' e &amp;lt;tex&amp;gt;{\notin}&amp;lt;/tex&amp;gt; V&lt;br /&gt;
                     C = C &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                     V = V &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                     TN = TN &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
         W = W &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; TN&lt;br /&gt;
     '''return''' k ближайших к q вершин из W&lt;br /&gt;
&lt;br /&gt;
Расстояние между вершинами графа может измеряться [[Метрический классификатор и метод ближайших соседей#Использование различных метрик расстояния|различными метриками]]. &amp;lt;br/&amp;gt;&lt;br /&gt;
Очевидный недостаток этого алгоритма {{---}} опасность свалиться в локальный минимум, остановившись в каком-то кластере. С увеличением числа &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, вероятность такого застревания экспоненциально падает.&lt;br /&gt;
&lt;br /&gt;
==Описание структуры==&lt;br /&gt;
'''Иерархический Маленький мир''' {{---}} слоистая структура графов. На нулевом слое представлены все &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; вершин из исходной выборки. Вершина, присутствующая на уровне &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; так же присутствует на уровне &amp;lt;tex&amp;gt;L + 1&amp;lt;/tex&amp;gt; с вероятностью &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Т.е. кол-во слоёв растет как &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;. Количество соседей каждой вершины на каждом уровне ограниченно константой, что позволяет делать запросы на добавление и удаление вершины за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[Файл:HNSW.png|мини|500px|Иерархический маленький мир. [https://arxiv.org/abs/1603.09320 Источник]]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
==Операции над структурой==&lt;br /&gt;
&lt;br /&gt;
===Поиск ближайших соседей в слое===&lt;br /&gt;
Жадно идём по уровню в сторону запроса.   &lt;br /&gt;
 '''searchLayer'''(q, ep, ef, layer)''':'''&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входные данные: иерархия графов hnsw, запрос q, входные точки ep, искомое количество ближайших соседей ef, номер слоя layer.&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Возвращает: ef ближайших соседей q в слое layer.&amp;lt;/font&amp;gt;&lt;br /&gt;
     W = &amp;lt;tex&amp;gt;\{ep\}&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие к q вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     C = &amp;lt;tex&amp;gt;\{ep\}&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вершины, которые предстоит посетить. &amp;lt;/font&amp;gt;&lt;br /&gt;
     V = &amp;lt;tex&amp;gt;\{ep\}&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Посещённые вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' C != &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;&lt;br /&gt;
         u = {q1 | &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt; q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; C, |q - q1| &amp;lt;= |q - q2|} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшая к q вершина из C. &amp;lt;/font&amp;gt;&lt;br /&gt;
         f = {q1 | &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt; q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; W, |q - q1| &amp;gt;= |q - q2|} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Самая дальняя от q вершина из W. &amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' |u - q| &amp;gt; |f - q|&lt;br /&gt;
             '''break''' &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Мы в локальном минимуме. &amp;lt;/font&amp;gt;&lt;br /&gt;
         '''for''' e : (u, e) '''in''' G&lt;br /&gt;
             '''if''' e &amp;lt;tex&amp;gt;{\notin}&amp;lt;/tex&amp;gt; V&lt;br /&gt;
                 V = V &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                 f = {q1 | &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt; q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; W, |q - q1| &amp;gt;= |q - q2|} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Самая дальняя от q вершина из W. &amp;lt;/font&amp;gt;&lt;br /&gt;
                 '''if''' |e - q| &amp;lt; |f - q| or |W| &amp;lt; ef&lt;br /&gt;
                     C = C &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                     W = W &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; e&lt;br /&gt;
                     if |W| &amp;gt; ef&lt;br /&gt;
                         W = W \ f&lt;br /&gt;
     '''return''' W&lt;br /&gt;
&lt;br /&gt;
===Поиск ближайших соседей во всей структуре===&lt;br /&gt;
[[Файл:HnswSearch.png|мини|500px|Жадный поиск вершины.&lt;br /&gt;
[https://arxiv.org/abs/1603.09320 Оригинал]]]&lt;br /&gt;
# Идём с верхнего уровня до первого:&lt;br /&gt;
## Жадно ищем ближайшую к &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; вершину на текущем уровне.&lt;br /&gt;
## Спускаемся в соответствующую соседу вершине на уровень ниже.&lt;br /&gt;
# На нулевом уровне жадно ищем &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; ближайших соседей.&lt;br /&gt;
 '''knn'''(hnsw, q, k, ef)''':'''&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входные данные: иерархия графов hnsw, запрос q, искомое количество ближайших соседей  k, количество кандидатов при поиске ef. &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Возвращает: k ближайших соседей q. &amp;lt;/font&amp;gt;&lt;br /&gt;
     W = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие к q вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     mL = |hnsw| - 1&lt;br /&gt;
     ep = &amp;lt;tex&amp;gt;random_v&amp;lt;/tex&amp;gt; v &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; hnsw[mL]&lt;br /&gt;
     '''for''' level = mL to 1&lt;br /&gt;
         W = searchLayer(hnsw, q, ep, ef=1, level) &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// На каждом уровне, кроме нижнего мы ищем всего одну ближайшую вершину. &amp;lt;/font&amp;gt;&lt;br /&gt;
         ep = W&lt;br /&gt;
     W = searchLayer(hnsw, q, ep, ef, lc=0)&lt;br /&gt;
     '''return''' k ближайших к q вершин из W&lt;br /&gt;
&lt;br /&gt;
===Вставка элемента===&lt;br /&gt;
# Случайным образом выбираем максимальный слой, на котором будет представлена &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# На каждом уровне, где будет представлена &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;, сверху вниз:&lt;br /&gt;
## Жадно ищем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; ближайших к &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
## Добавляем связи &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; с ними.&lt;br /&gt;
## Удаляем лишние связи у новообразовавшихся соседей.&lt;br /&gt;
 '''insert'''(hnsw, q, m, mMax, ef, mL)''':'''&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входные данные: иерархия графов hnsw, запрос на добавление q, желаемое количество связей m, максимальное количество связей вершины &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//       на одном слое mMax, количество кандидатов при поиске ef, коэффициент выбора высоты mL. &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Возвращает: hnsw с вставленным элементом q. &amp;lt;/font&amp;gt;&lt;br /&gt;
     W = &amp;lt;tex&amp;gt;\emptyset&amp;lt;/tex&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ближайшие к q вершины. &amp;lt;/font&amp;gt;&lt;br /&gt;
     mL = |hnsw| - 1&lt;br /&gt;
     ep = &amp;lt;tex&amp;gt;random_v&amp;lt;/tex&amp;gt; v &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; hnsw[mL]&lt;br /&gt;
     qL = -ln(rand(eps, 1.0)) * mL &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Верхний слой для вершины q. &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' level = mL to qL + 1&lt;br /&gt;
         W = searchLayer(q, ep, ef=1, level)&lt;br /&gt;
         ep = W&lt;br /&gt;
     '''for''' level = min(mL, qL) to 0&lt;br /&gt;
         W = searchLayer(q, ep, ef, level)&lt;br /&gt;
         neighbours = M ближайших к q вершин из W&lt;br /&gt;
         '''for''' n &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; neighbours:&lt;br /&gt;
             &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем двусторонние связи между n и q. &amp;lt;/font&amp;gt;&lt;br /&gt;
             hnsw[level] = hnsw[level] &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; (n, q)&lt;br /&gt;
             hnsw[level] = hnsw[level] &amp;lt;tex&amp;gt;\bigcup&amp;lt;/tex&amp;gt; (q, n)&lt;br /&gt;
             &lt;br /&gt;
             nNeighbours = {v| (v, n) '''in''' hnsw[level]} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Ищем всех соседей n на уровне level. &amp;lt;/font&amp;gt;&lt;br /&gt;
             &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Убираем лишние связи, если требуется. &amp;lt;/font&amp;gt;&lt;br /&gt;
             '''if''' nNeighbours.Count() &amp;gt; mMax&lt;br /&gt;
                 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Самая дальняя от n вершина, смежняя с ней. &amp;lt;/font&amp;gt;&lt;br /&gt;
                 v = {q1 | (q2, n) &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; nNeighbours &amp;amp; &amp;lt;tex&amp;gt;\forall&amp;lt;/tex&amp;gt;q2 &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; hnsw[level], |q - q1| &amp;gt;= |q - q2|}&lt;br /&gt;
                 hnsw[level] = hnsw[level] &amp;lt;tex&amp;gt;\setminus&amp;lt;/tex&amp;gt; (n, v)&lt;br /&gt;
                 hnsw[level] = hnsw[level] &amp;lt;tex&amp;gt;\setminus&amp;lt;/tex&amp;gt; (v, n)&lt;br /&gt;
         ep = W&lt;br /&gt;
     '''if''' qL &amp;gt; mL&lt;br /&gt;
         '''for''' level = mL to qL&lt;br /&gt;
             hnsw.append({q, {}})&lt;br /&gt;
&lt;br /&gt;
== Практическое использование ==&lt;br /&gt;
В библиотеке [https://github.com/nmslib/hnswlib Hnswlib] есть реализация иерархического маленького мира. Эта библиотека написана на C++, с биндингами на python.&lt;br /&gt;
Пример использования:&lt;br /&gt;
 '''import''' hnswlib&lt;br /&gt;
 '''import''' numpy '''as''' np&lt;br /&gt;
 &lt;br /&gt;
 dim = 128&lt;br /&gt;
 num_elements = 10000&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Создаём тестовые данные.&amp;lt;/font&amp;gt;&lt;br /&gt;
 data = np.float32(np.random.random((num_elements, dim)))&lt;br /&gt;
 data_labels = np.arange(num_elements)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Создаём иерархический маленький мир в L2.&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Возможные метрики {{---}} l2, cosine, ip (L2, косинус угла между векторами, скалярное произведение).&amp;lt;/font&amp;gt;&lt;br /&gt;
 p = hnswlib.Index(space = 'l2', dim = dim)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Инициализируем структуру.&amp;lt;/font&amp;gt;&lt;br /&gt;
 p.init_index(max_elements = num_elements, ef_construction = 200, M = 16)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Добавляем данные (можно вызывать много раз).&amp;lt;/font&amp;gt;&lt;br /&gt;
 p.add_items(data, data_labels)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Настраиваем качество, выставляя ef:&amp;lt;/font&amp;gt;&lt;br /&gt;
 p.set_ef(50) &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# ef должно быть &amp;gt; k&amp;lt;/font&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# Делаем запрос.&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;# k - количество ближайших вершин&amp;lt;/font&amp;gt;&lt;br /&gt;
 labels, distances = p.knn_query(data, k = 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;
* [https://arxiv.org/abs/1603.09320 Yu. A. Malkov, D. A. Yashunin {{---}} Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs]&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/%D0%9C%D0%B8%D1%80_%D1%82%D0%B5%D1%81%D0%B5%D0%BD_(%D0%B3%D1%80%D0%B0%D1%84) Википедия {{---}} Мир тесен (граф)]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Small-world_network Wikipedia {{---}} Small-world network]&lt;br /&gt;
* [https://github.com/sgjurano/ysda-celebrity-faces Поиск знаменитостей на фотографии с помощью иерархического маленького мира]&lt;br /&gt;
* [https://m.habr.com/ru/company/mailru/blog/338360/ Статья от Mail.ru об использовании иерархического маленького мира]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;/div&gt;</summary>
		<author><name>31.173.28.101</name></author>	</entry>

	</feed>