<?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=Kirill.vakhrushev&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=Kirill.vakhrushev&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/Kirill.vakhrushev"/>
		<updated>2026-08-03T23:31:17Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72971</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72971"/>
				<updated>2020-03-20T07:18:30Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Дополнительные */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling (statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в ''независимой'' переменной;&lt;br /&gt;
* Недостаточное представление класса в ''зависимой'' переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/S0957417408003527 Show-Jane Yen, Yue-Shi Lee,Cluster-based under-sampling approaches for imbalanced data distributions, Expert Systems with Applications, Volume 36, Issue 3, Part 1, 2009, Pages 5718-5727, ISSN 0957-4174]&amp;lt;/ref&amp;gt; {{---}} уменьшает количество примеров мажоритарного класса, заменяя некоторые кластеры примеров мажоритарного класса их представителем (центроидом кластера).&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;I. Mani, J. Zhang. “kNN approach to unbalanced data distributions: A case study involving information extraction,” In Proceedings of the Workshop on Learning from Imbalanced Data Sets, pp. 1-7, 2003.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, для которых среднее расстояние до ближайших соседей ([[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]) миноритарного класса является наименьшим. Также может использоваться расстояние до самых дальних соседей, либо среднее расстояние до всех соседей. &lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt;D. Wilson, “Asymptotic Properties of Nearest Neighbor Rules Using Edited Data,” IEEE Transactions on Systems, Man, and Cybernetrics, vol. 2(3), pp. 408-421, 1972.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, если при классификации методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]] они определяются как примеры миноритарного класса.&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC&amp;lt;ref&amp;gt;N. V. Chawla, K. W. Bowyer, L. O. Hall, W. P. Kegelmeyer, “SMOTE: Synthetic minority over-sampling technique,” Journal of Artificial Intelligence Research, vol. 16, pp. 321-357, 2002.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', работает с непрерывными признаками у примеров обучающей выборки.&lt;br /&gt;
* Borderline-SMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;H. Han, W.-Y. Wang, B.-H. Mao, “Borderline-SMOTE: A new over-sampling method in imbalanced data sets learning,” In Proceedings of the 1st International Conference on Intelligent Computing, pp. 878-887, 2005.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', для создания новых синтетических примеров используются только примеры на границе классов.&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt;H. M. Nguyen, E. W. Cooper, K. Kamei, “Borderline over-sampling for imbalanced data classification,” In Proceedings of the 5th International Workshop on computational Intelligence and Applications, pp. 24-29, 2009.&amp;lt;/ref&amp;gt; {{---}} вариант алгоритма ''SMOTE'', который использует алгоритм [[Метод_опорных_векторов_(SVM)|SVM]] для обнаружения примеров, рядом с которыми будут создаваться новые синтетические примеры.&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt;G. E. A. P. A. Batista, A. L. C. Bazzan, M. C. Monard, “Balancing training data for automated annotation of keywords: A case study,” In Proceedings of the 2nd Brazilian Workshop on Bioinformatics, pp. 10-18, 2003.&amp;lt;/ref&amp;gt; {{---}} сначала выполняет передискретизацию с использованием ''SMOTE'', а потом субдискретизацию используя ''Tomek Links''.&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt;G. E. A. P. A. Batista, R. C. Prati, M. C. Monard, “A study of the behavior of several methods for balancing machine learning training data,” ACM Sigkdd Explorations Newsletter, vol. 6(1), pp. 20-29, 2004.&amp;lt;/ref&amp;gt; {{---}} последовательно использует ''SMOTE'' и ''Edited Nearest Neighbours''.&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt;X.-Y. Liu, J. Wu and Z.-H. Zhou, “Exploratory undersampling for class-imbalance learning,” IEEE Transactions on Systems, Man, and Cybernetics, vol. 39(2), pp. 539-550, 2009.&amp;lt;/ref&amp;gt; {{---}} независимые классификаторы обучаются на случайных подвыборках, из которых постепенно удаляются правильно классифицирующиеся примеры мажоритарных классов.&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt;C. Chao, A. Liaw, and L. Breiman. &amp;quot;Using random forest to learn imbalanced data.&amp;quot; University of California, Berkeley 110 (2004): 1-12.&amp;lt;/ref&amp;gt; {{---}} в отличие от классического [[Дерево_решений_и_случайный_лес|случайного леса]], может работать на несбалансированных данных. &lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt;Hido, Shohei &amp;amp; Kashima, Hisashi. (2008). Roughly Balanced Bagging for Imbalanced Data. 143-152. 10.1137/1.9781611972788.13. &amp;lt;/ref&amp;gt; {{---}} в отличие от классического [[Виды_ансамблей#.D0.91.D1.8D.D0.B3.D0.B3.D0.B8.D0.BD.D0.B3|бэггинга]], имеет дополнительный шаг субдискретизации обучающей подвыборки.&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72970</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72970"/>
				<updated>2020-03-20T07:15:36Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling (statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в ''независимой'' переменной;&lt;br /&gt;
* Недостаточное представление класса в ''зависимой'' переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/S0957417408003527 Show-Jane Yen, Yue-Shi Lee,Cluster-based under-sampling approaches for imbalanced data distributions, Expert Systems with Applications, Volume 36, Issue 3, Part 1, 2009, Pages 5718-5727, ISSN 0957-4174]&amp;lt;/ref&amp;gt; {{---}} уменьшает количество примеров мажоритарного класса, заменяя некоторые кластеры примеров мажоритарного класса их представителем (центроидом кластера).&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;I. Mani, J. Zhang. “kNN approach to unbalanced data distributions: A case study involving information extraction,” In Proceedings of the Workshop on Learning from Imbalanced Data Sets, pp. 1-7, 2003.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, для которых среднее расстояние до ближайших соседей ([[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]) миноритарного класса является наименьшим. Также может использоваться расстояние до самых дальних соседей, либо среднее расстояние до всех соседей. &lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt;D. Wilson, “Asymptotic Properties of Nearest Neighbor Rules Using Edited Data,” IEEE Transactions on Systems, Man, and Cybernetrics, vol. 2(3), pp. 408-421, 1972.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, если при классификации методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]] они определяются как примеры миноритарного класса.&lt;br /&gt;
* Neighboorhood Cleaning Rule&amp;lt;ref&amp;gt;J. Laurikkala, “Improving identification of difficult small classes by balancing class distribution,” Proceedings of the 8th Conference on Artificial Intelligence in Medicine in Europe, pp. 63-66, 2001.&amp;lt;/ref&amp;gt; {{---}} улучшение предыдущего алгоритма, в дополнение к удалению неверно классифицируемых примеров мажоритарного классов, удаляются все соседи примеров миноритарного класса, которые влияют на их неправильную классификацию методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]].&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC&amp;lt;ref&amp;gt;N. V. Chawla, K. W. Bowyer, L. O. Hall, W. P. Kegelmeyer, “SMOTE: Synthetic minority over-sampling technique,” Journal of Artificial Intelligence Research, vol. 16, pp. 321-357, 2002.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', работает с непрерывными признаками у примеров обучающей выборки.&lt;br /&gt;
* Borderline-SMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;H. Han, W.-Y. Wang, B.-H. Mao, “Borderline-SMOTE: A new over-sampling method in imbalanced data sets learning,” In Proceedings of the 1st International Conference on Intelligent Computing, pp. 878-887, 2005.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', для создания новых синтетических примеров используются только примеры на границе классов.&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt;H. M. Nguyen, E. W. Cooper, K. Kamei, “Borderline over-sampling for imbalanced data classification,” In Proceedings of the 5th International Workshop on computational Intelligence and Applications, pp. 24-29, 2009.&amp;lt;/ref&amp;gt; {{---}} вариант алгоритма ''SMOTE'', который использует алгоритм [[Метод_опорных_векторов_(SVM)|SVM]] для обнаружения примеров, рядом с которыми будут создаваться новые синтетические примеры.&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt;G. E. A. P. A. Batista, A. L. C. Bazzan, M. C. Monard, “Balancing training data for automated annotation of keywords: A case study,” In Proceedings of the 2nd Brazilian Workshop on Bioinformatics, pp. 10-18, 2003.&amp;lt;/ref&amp;gt; {{---}} сначала выполняет передискретизацию с использованием ''SMOTE'', а потом субдискретизацию используя ''Tomek Links''.&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt;G. E. A. P. A. Batista, R. C. Prati, M. C. Monard, “A study of the behavior of several methods for balancing machine learning training data,” ACM Sigkdd Explorations Newsletter, vol. 6(1), pp. 20-29, 2004.&amp;lt;/ref&amp;gt; {{---}} последовательно использует ''SMOTE'' и ''Edited Nearest Neighbours''.&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt;X.-Y. Liu, J. Wu and Z.-H. Zhou, “Exploratory undersampling for class-imbalance learning,” IEEE Transactions on Systems, Man, and Cybernetics, vol. 39(2), pp. 539-550, 2009.&amp;lt;/ref&amp;gt; {{---}} независимые классификаторы обучаются на случайных подвыборках, из которых постепенно удаляются правильно классифицирующиеся примеры мажоритарных классов.&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt;C. Chao, A. Liaw, and L. Breiman. &amp;quot;Using random forest to learn imbalanced data.&amp;quot; University of California, Berkeley 110 (2004): 1-12.&amp;lt;/ref&amp;gt; {{---}} в отличие от классического [[Дерево_решений_и_случайный_лес|случайного леса]], может работать на несбалансированных данных. &lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt;Hido, Shohei &amp;amp; Kashima, Hisashi. (2008). Roughly Balanced Bagging for Imbalanced Data. 143-152. 10.1137/1.9781611972788.13. &amp;lt;/ref&amp;gt; {{---}} в отличие от классического [[Виды_ансамблей#.D0.91.D1.8D.D0.B3.D0.B3.D0.B8.D0.BD.D0.B3|бэггинга]], имеет дополнительный шаг субдискретизации обучающей подвыборки.&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72969</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72969"/>
				<updated>2020-03-20T07:13:19Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Ансамбль сбалансированных наборов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling (statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в независимой переменной;&lt;br /&gt;
* Недостаточное представление класса в зависимой переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/S0957417408003527 Show-Jane Yen, Yue-Shi Lee,Cluster-based under-sampling approaches for imbalanced data distributions, Expert Systems with Applications, Volume 36, Issue 3, Part 1, 2009, Pages 5718-5727, ISSN 0957-4174]&amp;lt;/ref&amp;gt; {{---}} уменьшает количество примеров мажоритарного класса, заменяя некоторые кластеры примеров мажоритарного класса их представителем (центроидом кластера).&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;I. Mani, J. Zhang. “kNN approach to unbalanced data distributions: A case study involving information extraction,” In Proceedings of the Workshop on Learning from Imbalanced Data Sets, pp. 1-7, 2003.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, для которых среднее расстояние до ближайших соседей ([[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]) миноритарного класса является наименьшим. Также может использоваться расстояние до самых дальних соседей, либо среднее расстояние до всех соседей. &lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt;D. Wilson, “Asymptotic Properties of Nearest Neighbor Rules Using Edited Data,” IEEE Transactions on Systems, Man, and Cybernetrics, vol. 2(3), pp. 408-421, 1972.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, если при классификации методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]] они определяются как примеры миноритарного класса.&lt;br /&gt;
* Neighboorhood Cleaning Rule&amp;lt;ref&amp;gt;J. Laurikkala, “Improving identification of difficult small classes by balancing class distribution,” Proceedings of the 8th Conference on Artificial Intelligence in Medicine in Europe, pp. 63-66, 2001.&amp;lt;/ref&amp;gt; {{---}} улучшение предыдущего алгоритма, в дополнение к удалению неверно классифицируемых примеров мажоритарного классов, удаляются все соседи примеров миноритарного класса, которые влияют на их неправильную классификацию методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]].&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC&amp;lt;ref&amp;gt;N. V. Chawla, K. W. Bowyer, L. O. Hall, W. P. Kegelmeyer, “SMOTE: Synthetic minority over-sampling technique,” Journal of Artificial Intelligence Research, vol. 16, pp. 321-357, 2002.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', работает с непрерывными признаками у примеров обучающей выборки.&lt;br /&gt;
* Borderline-SMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;H. Han, W.-Y. Wang, B.-H. Mao, “Borderline-SMOTE: A new over-sampling method in imbalanced data sets learning,” In Proceedings of the 1st International Conference on Intelligent Computing, pp. 878-887, 2005.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', для создания новых синтетических примеров используются только примеры на границе классов.&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt;H. M. Nguyen, E. W. Cooper, K. Kamei, “Borderline over-sampling for imbalanced data classification,” In Proceedings of the 5th International Workshop on computational Intelligence and Applications, pp. 24-29, 2009.&amp;lt;/ref&amp;gt; {{---}} вариант алгоритма ''SMOTE'', который использует алгоритм [[Метод_опорных_векторов_(SVM)|SVM]] для обнаружения примеров, рядом с которыми будут создаваться новые синтетические примеры.&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt;G. E. A. P. A. Batista, A. L. C. Bazzan, M. C. Monard, “Balancing training data for automated annotation of keywords: A case study,” In Proceedings of the 2nd Brazilian Workshop on Bioinformatics, pp. 10-18, 2003.&amp;lt;/ref&amp;gt; {{---}} сначала выполняет передискретизацию с использованием ''SMOTE'', а потом субдискретизацию используя ''Tomek Links''.&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt;G. E. A. P. A. Batista, R. C. Prati, M. C. Monard, “A study of the behavior of several methods for balancing machine learning training data,” ACM Sigkdd Explorations Newsletter, vol. 6(1), pp. 20-29, 2004.&amp;lt;/ref&amp;gt; {{---}} последовательно использует ''SMOTE'' и ''Edited Nearest Neighbours''.&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt;X.-Y. Liu, J. Wu and Z.-H. Zhou, “Exploratory undersampling for class-imbalance learning,” IEEE Transactions on Systems, Man, and Cybernetics, vol. 39(2), pp. 539-550, 2009.&amp;lt;/ref&amp;gt; {{---}} независимые классификаторы обучаются на случайных подвыборках, из которых постепенно удаляются правильно классифицирующиеся примеры мажоритарных классов.&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt;C. Chao, A. Liaw, and L. Breiman. &amp;quot;Using random forest to learn imbalanced data.&amp;quot; University of California, Berkeley 110 (2004): 1-12.&amp;lt;/ref&amp;gt; {{---}} в отличие от классического [[Дерево_решений_и_случайный_лес|случайного леса]], может работать на несбалансированных данных. &lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt;Hido, Shohei &amp;amp; Kashima, Hisashi. (2008). Roughly Balanced Bagging for Imbalanced Data. 143-152. 10.1137/1.9781611972788.13. &amp;lt;/ref&amp;gt; {{---}} в отличие от классического [[Виды_ансамблей#.D0.91.D1.8D.D0.B3.D0.B3.D0.B8.D0.BD.D0.B3|бэггинга]], имеет дополнительный шаг субдискретизации обучающей подвыборки.&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72967</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72967"/>
				<updated>2020-03-20T06:45:02Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Комбинирование */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling (statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в независимой переменной;&lt;br /&gt;
* Недостаточное представление класса в зависимой переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/S0957417408003527 Show-Jane Yen, Yue-Shi Lee,Cluster-based under-sampling approaches for imbalanced data distributions, Expert Systems with Applications, Volume 36, Issue 3, Part 1, 2009, Pages 5718-5727, ISSN 0957-4174]&amp;lt;/ref&amp;gt; {{---}} уменьшает количество примеров мажоритарного класса, заменяя некоторые кластеры примеров мажоритарного класса их представителем (центроидом кластера).&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;I. Mani, J. Zhang. “kNN approach to unbalanced data distributions: A case study involving information extraction,” In Proceedings of the Workshop on Learning from Imbalanced Data Sets, pp. 1-7, 2003.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, для которых среднее расстояние до ближайших соседей ([[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]) миноритарного класса является наименьшим. Также может использоваться расстояние до самых дальних соседей, либо среднее расстояние до всех соседей. &lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt;D. Wilson, “Asymptotic Properties of Nearest Neighbor Rules Using Edited Data,” IEEE Transactions on Systems, Man, and Cybernetrics, vol. 2(3), pp. 408-421, 1972.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, если при классификации методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]] они определяются как примеры миноритарного класса.&lt;br /&gt;
* Neighboorhood Cleaning Rule&amp;lt;ref&amp;gt;J. Laurikkala, “Improving identification of difficult small classes by balancing class distribution,” Proceedings of the 8th Conference on Artificial Intelligence in Medicine in Europe, pp. 63-66, 2001.&amp;lt;/ref&amp;gt; {{---}} улучшение предыдущего алгоритма, в дополнение к удалению неверно классифицируемых примеров мажоритарного классов, удаляются все соседи примеров миноритарного класса, которые влияют на их неправильную классификацию методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]].&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC&amp;lt;ref&amp;gt;N. V. Chawla, K. W. Bowyer, L. O. Hall, W. P. Kegelmeyer, “SMOTE: Synthetic minority over-sampling technique,” Journal of Artificial Intelligence Research, vol. 16, pp. 321-357, 2002.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', работает с непрерывными признаками у примеров обучающей выборки.&lt;br /&gt;
* Borderline-SMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;H. Han, W.-Y. Wang, B.-H. Mao, “Borderline-SMOTE: A new over-sampling method in imbalanced data sets learning,” In Proceedings of the 1st International Conference on Intelligent Computing, pp. 878-887, 2005.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', для создания новых синтетических примеров используются только примеры на границе классов.&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt;H. M. Nguyen, E. W. Cooper, K. Kamei, “Borderline over-sampling for imbalanced data classification,” In Proceedings of the 5th International Workshop on computational Intelligence and Applications, pp. 24-29, 2009.&amp;lt;/ref&amp;gt; {{---}} вариант алгоритма ''SMOTE'', который использует алгоритм [[Метод_опорных_векторов_(SVM)|SVM]] для обнаружения примеров, рядом с которыми будут создаваться новые синтетические примеры.&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt;G. E. A. P. A. Batista, A. L. C. Bazzan, M. C. Monard, “Balancing training data for automated annotation of keywords: A case study,” In Proceedings of the 2nd Brazilian Workshop on Bioinformatics, pp. 10-18, 2003.&amp;lt;/ref&amp;gt; {{---}} сначала выполняет передискретизацию с использованием ''SMOTE'', а потом субдискретизацию используя ''Tomek Links''.&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt;G. E. A. P. A. Batista, R. C. Prati, M. C. Monard, “A study of the behavior of several methods for balancing machine learning training data,” ACM Sigkdd Explorations Newsletter, vol. 6(1), pp. 20-29, 2004.&amp;lt;/ref&amp;gt; {{---}} последовательно использует ''SMOTE'' и ''Edited Nearest Neighbours''.&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72966</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72966"/>
				<updated>2020-03-20T06:37:01Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Дополнительные */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling (statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в независимой переменной;&lt;br /&gt;
* Недостаточное представление класса в зависимой переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/S0957417408003527 Show-Jane Yen, Yue-Shi Lee,Cluster-based under-sampling approaches for imbalanced data distributions, Expert Systems with Applications, Volume 36, Issue 3, Part 1, 2009, Pages 5718-5727, ISSN 0957-4174]&amp;lt;/ref&amp;gt; {{---}} уменьшает количество примеров мажоритарного класса, заменяя некоторые кластеры примеров мажоритарного класса их представителем (центроидом кластера).&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;I. Mani, J. Zhang. “kNN approach to unbalanced data distributions: A case study involving information extraction,” In Proceedings of the Workshop on Learning from Imbalanced Data Sets, pp. 1-7, 2003.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, для которых среднее расстояние до ближайших соседей ([[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]) миноритарного класса является наименьшим. Также может использоваться расстояние до самых дальних соседей, либо среднее расстояние до всех соседей. &lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt;D. Wilson, “Asymptotic Properties of Nearest Neighbor Rules Using Edited Data,” IEEE Transactions on Systems, Man, and Cybernetrics, vol. 2(3), pp. 408-421, 1972.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, если при классификации методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]] они определяются как примеры миноритарного класса.&lt;br /&gt;
* Neighboorhood Cleaning Rule&amp;lt;ref&amp;gt;J. Laurikkala, “Improving identification of difficult small classes by balancing class distribution,” Proceedings of the 8th Conference on Artificial Intelligence in Medicine in Europe, pp. 63-66, 2001.&amp;lt;/ref&amp;gt; {{---}} улучшение предыдущего алгоритма, в дополнение к удалению неверно классифицируемых примеров мажоритарного классов, удаляются все соседи примеров миноритарного класса, которые влияют на их неправильную классификацию методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]].&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC&amp;lt;ref&amp;gt;N. V. Chawla, K. W. Bowyer, L. O. Hall, W. P. Kegelmeyer, “SMOTE: Synthetic minority over-sampling technique,” Journal of Artificial Intelligence Research, vol. 16, pp. 321-357, 2002.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', работает с непрерывными признаками у примеров обучающей выборки.&lt;br /&gt;
* Borderline-SMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;H. Han, W.-Y. Wang, B.-H. Mao, “Borderline-SMOTE: A new over-sampling method in imbalanced data sets learning,” In Proceedings of the 1st International Conference on Intelligent Computing, pp. 878-887, 2005.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', для создания новых синтетических примеров используются только примеры на границе классов.&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt;H. M. Nguyen, E. W. Cooper, K. Kamei, “Borderline over-sampling for imbalanced data classification,” In Proceedings of the 5th International Workshop on computational Intelligence and Applications, pp. 24-29, 2009.&amp;lt;/ref&amp;gt; {{---}} вариант алгоритма ''SMOTE'', который использует алгоритм [[Метод_опорных_векторов_(SVM)|SVM]] для обнаружения примеров, рядом с которыми будут создаваться новые синтетические примеры.&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72964</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72964"/>
				<updated>2020-03-20T06:36:16Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Дополнительные */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling (statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в независимой переменной;&lt;br /&gt;
* Недостаточное представление класса в зависимой переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/S0957417408003527 Show-Jane Yen, Yue-Shi Lee,Cluster-based under-sampling approaches for imbalanced data distributions, Expert Systems with Applications, Volume 36, Issue 3, Part 1, 2009, Pages 5718-5727, ISSN 0957-4174]&amp;lt;/ref&amp;gt; {{---}} уменьшает количество примеров мажоритарного класса, заменяя некоторые кластеры примеров мажоритарного класса их представителем (центроидом кластера).&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;I. Mani, J. Zhang. “kNN approach to unbalanced data distributions: A case study involving information extraction,” In Proceedings of the Workshop on Learning from Imbalanced Data Sets, pp. 1-7, 2003.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, для которых среднее расстояние до ближайших соседей ([[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]) миноритарного класса является наименьшим. Также может использоваться расстояние до самых дальних соседей, либо среднее расстояние до всех соседей. &lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt;D. Wilson, “Asymptotic Properties of Nearest Neighbor Rules Using Edited Data,” IEEE Transactions on Systems, Man, and Cybernetrics, vol. 2(3), pp. 408-421, 1972.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, если при классификации методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]] они определяются как примеры миноритарного класса.&lt;br /&gt;
* Neighboorhood Cleaning Rule&amp;lt;ref&amp;gt;J. Laurikkala, “Improving identification of difficult small classes by balancing class distribution,” Proceedings of the 8th Conference on Artificial Intelligence in Medicine in Europe, pp. 63-66, 2001.&amp;lt;/ref&amp;gt; {{---}} улучшение предыдущего алгоритма, в дополнение к удалению неверно классифицируемых примеров мажоритарного классов, удаляются все соседи примеров миноритарного класса, которые влияют на их неправильную классификацию методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]].&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt;N. V. Chawla, K. W. Bowyer, L. O. Hall, W. P. Kegelmeyer, “SMOTE: Synthetic minority over-sampling technique,” Journal of Artificial Intelligence Research, vol. 16, pp. 321-357, 2002.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', работает с непрерывными признаками у примеров обучающей выборки.&lt;br /&gt;
* Borderline-SMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;H. Han, W.-Y. Wang, B.-H. Mao, “Borderline-SMOTE: A new over-sampling method in imbalanced data sets learning,” In Proceedings of the 1st International Conference on Intelligent Computing, pp. 878-887, 2005.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', для создания новых синтетических примеров используются только примеры на границе классов.&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt;H. M. Nguyen, E. W. Cooper, K. Kamei, “Borderline over-sampling for imbalanced data classification,” In Proceedings of the 5th International Workshop on computational Intelligence and Applications, pp. 24-29, 2009.&amp;lt;/ref&amp;gt; {{---}} вариант алгоритма ''SMOTE'', который использует алгоритм [[Метод_опорных_векторов_(SVM)|SVM]] для обнаружения примеров, рядом с которыми будут создаваться новые синтетические примеры.&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72962</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72962"/>
				<updated>2020-03-20T06:28:11Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Дополнительные */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling (statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в независимой переменной;&lt;br /&gt;
* Недостаточное представление класса в зависимой переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/S0957417408003527 Show-Jane Yen, Yue-Shi Lee,Cluster-based under-sampling approaches for imbalanced data distributions, Expert Systems with Applications, Volume 36, Issue 3, Part 1, 2009, Pages 5718-5727, ISSN 0957-4174]&amp;lt;/ref&amp;gt; {{---}} уменьшает количество примеров мажоритарного класса, заменяя некоторые кластеры примеров мажоритарного класса их представителем (центроидом кластера).&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;I. Mani, J. Zhang. “kNN approach to unbalanced data distributions: A case study involving information extraction,” In Proceedings of the Workshop on Learning from Imbalanced Data Sets, pp. 1-7, 2003.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, для которых среднее расстояние до ближайших соседей ([[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]) миноритарного класса является наименьшим. Также может использоваться расстояние до самых дальних соседей, либо среднее расстояние до всех соседей. &lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt;D. Wilson, “Asymptotic Properties of Nearest Neighbor Rules Using Edited Data,” IEEE Transactions on Systems, Man, and Cybernetrics, vol. 2(3), pp. 408-421, 1972.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, если при классификации методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]] они определяются как примеры миноритарного класса.&lt;br /&gt;
* Neighboorhood Cleaning Rule&amp;lt;ref&amp;gt;J. Laurikkala, “Improving identification of difficult small classes by balancing class distribution,” Proceedings of the 8th Conference on Artificial Intelligence in Medicine in Europe, pp. 63-66, 2001.&amp;lt;/ref&amp;gt; {{---}} улучшение предыдущего алгоритма, в дополнение к удалению неверно классифицируемых примеров мажоритарного классов, удаляются все соседи примеров миноритарного класса, которые влияют на их неправильную классификацию методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]].&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt;N. V. Chawla, K. W. Bowyer, L. O. Hall, W. P. Kegelmeyer, “SMOTE: Synthetic minority over-sampling technique,” Journal of Artificial Intelligence Research, vol. 16, pp. 321-357, 2002.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', работает с непрерывными признаками у объектов обучающей выборки.&lt;br /&gt;
* Borderline-SMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;H. Han, W.-Y. Wang, B.-H. Mao, “Borderline-SMOTE: A new over-sampling method in imbalanced data sets learning,” In Proceedings of the 1st International Conference on Intelligent Computing, pp. 878-887, 2005.&amp;lt;/ref&amp;gt; {{---}} в отличие от ''SMOTE'', для создания новых синтетических примеров используются только примеры на границе классов.&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt; {{---}}&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt; {{---}}&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt; {{---}}&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt; {{---}}&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72959</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72959"/>
				<updated>2020-03-20T06:13:31Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Дополнительные */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling (statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в независимой переменной;&lt;br /&gt;
* Недостаточное представление класса в зависимой переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/S0957417408003527 Show-Jane Yen, Yue-Shi Lee,Cluster-based under-sampling approaches for imbalanced data distributions, Expert Systems with Applications, Volume 36, Issue 3, Part 1, 2009, Pages 5718-5727, ISSN 0957-4174]&amp;lt;/ref&amp;gt; {{---}} уменьшает количество примеров мажоритарного класса, заменяя некоторые кластеры примеров мажоритарного класса их представителем (центроидом кластера).&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;I. Mani, J. Zhang. “kNN approach to unbalanced data distributions: A case study involving information extraction,” In Proceedings of the Workshop on Learning from Imbalanced Data Sets, pp. 1-7, 2003.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, для которых среднее расстояние до ближайших соседей ([[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]) миноритарного класса является наименьшим. Также может использоваться расстояние до самых дальних соседей, либо среднее расстояние до всех соседей. &lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt;D. Wilson, “Asymptotic Properties of Nearest Neighbor Rules Using Edited Data,” IEEE Transactions on Systems, Man, and Cybernetrics, vol. 2(3), pp. 408-421, 1972.&amp;lt;/ref&amp;gt; {{---}} удаляет примеры мажоритарного класса, если при классификации методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]] они определяются как примеры миноритарного класса.&lt;br /&gt;
* Neighboorhood Cleaning Rule&amp;lt;ref&amp;gt;J. Laurikkala, “Improving identification of difficult small classes by balancing class distribution,” Proceedings of the 8th Conference on Artificial Intelligence in Medicine in Europe, pp. 63-66, 2001.&amp;lt;/ref&amp;gt; {{---}} улучшение предыдущего алгоритма, в дополнение к удалению неверно классифицируемых примеров мажоритарного классов, удаляются все соседи примеров миноритарного класса, которые влияют на их неправильную классификацию методом [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]].&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72953</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72953"/>
				<updated>2020-03-20T05:41:58Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling (statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в независимой переменной;&lt;br /&gt;
* Недостаточное представление класса в зависимой переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/S0957417408003527 Show-Jane Yen, Yue-Shi Lee,Cluster-based under-sampling approaches for imbalanced data distributions, Expert Systems with Applications, Volume 36, Issue 3, Part 1, 2009, Pages 5718-5727, ISSN 0957-4174]&amp;lt;/ref&amp;gt; {{---}} уменьшает количество примеров мажоритарного класса, заменяя некоторые кластеры примеров мажоритарного класса их представителем (центроидом кластера).&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72952</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72952"/>
				<updated>2020-03-20T05:21:15Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в независимой переменной;&lt;br /&gt;
* Недостаточное представление класса в зависимой переменной.&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, со слишком большим количеством представителей, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинирование''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинирование ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72913</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72913"/>
				<updated>2020-03-17T01:58:35Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой переменной).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), другие, сильно представленные, — '''мажоритарными''' (англ. ''majority''). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей, обследованных в больнице, на больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количества примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количества примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самый простой алгоритм. Рассчитывается число &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72912</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72912"/>
				<updated>2020-03-17T01:39:04Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самая простая стратегия. Для этого рассчитывается число K – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72911</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72911"/>
				<updated>2020-03-17T01:38:28Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* См. также */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самая простая стратегия. Для этого рассчитывается число K – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72910</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72910"/>
				<updated>2020-03-17T01:37:46Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Стратегии сэмплирования */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных методов сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самая простая стратегия. Для этого рассчитывается число K – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72909</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72909"/>
				<updated>2020-03-17T01:36:52Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} использование встроенных метода сэмплирования в процессе построения ансамблей классификаторов.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самая простая стратегия. Для этого рассчитывается число K – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.6|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.2|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
[https://github.com/scikit-learn-contrib/imbalanced-learn Imbalanced-learn] {{---}} набор инструментов с открытым исходным кодом на Python, целью которого является предоставление широкого спектра методов для решения проблемы несбалансированного набора данных. На рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt; представлена таблица реализованных в библиотеке методов.&lt;br /&gt;
&lt;br /&gt;
Пример кода для передискретизации набора данных с использованием ''SMOTE'':&lt;br /&gt;
&lt;br /&gt;
  from sklearn.datasets import make_classification&lt;br /&gt;
  from sklearn.decomposition import PCA&lt;br /&gt;
  from imblearn.oversampling import SMOTE&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;
  X, y = makeclassification (n_classes=2, weights =[0.1, 0.9],&lt;br /&gt;
  n_features=20, n_samples=5000)&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;Применение SMOTE over-sampling&amp;lt;/font&amp;gt;&lt;br /&gt;
  sm = SMOTE(ratio=’auto’, kind=’regular’)&lt;br /&gt;
  X_resampled , y_resampled=sm.fit_sample(X, y)&lt;br /&gt;
&lt;br /&gt;
[[Файл:Imbalanced-learn.png|none|thumb|upright=2|Рис. &amp;lt;math&amp;gt;7&amp;lt;/math&amp;gt;. Методы imbalanced-learn]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
#[https://en.wikipedia.org/wiki/Oversampling_and_undersampling_in_data_analysis#Undersampling_techniques_for_classification_problems Oversampling and undersampling in data analysis]&lt;br /&gt;
#[https://basegroup.ru/community/articles/imbalance-datasets Различные стратегии сэмплинга в условиях несбалансированности классов]&lt;br /&gt;
# Lemaître, G. Nogueira, F. Aridas, Ch.K. (2017)  [http://www.jmlr.org/papers/volume18/16-365/16-365.pdf Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning], Journal of Machine Learning Research, vol. 18, no. 17, 2017, pp. 1-5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Imbalanced-learn.png&amp;diff=72908</id>
		<title>Файл:Imbalanced-learn.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Imbalanced-learn.png&amp;diff=72908"/>
				<updated>2020-03-17T01:22:53Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72907</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72907"/>
				<updated>2020-03-17T00:39:59Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} ансамбли классификаторов, использующие сэмплирование внутри.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
Передискретизации, как правило, применяется чаще, чем субдискретизация. Подбор проб применяется гораздо реже. Переизбыток собранных данных стал проблемой только в эпоху «больших данных», и причины использования субдискретизация в основном практичны и связаны с затратами на ресурсы.&lt;br /&gt;
Переизбыток уже собранных данных стал проблемой только в эпоху «больших данных», и причины использования недостаточной выборки в основном практичны и связаны с затр%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%атами на ресурсы. В частности, хотя для получения достоверных статистических выводов требуется достаточно большой размер выборки, данные должны быть очищены перед использованием. Очистка обычно включает в себя значительную человеческую составляющую и, как правило, специфична для набора данных и аналитической проблемы, и поэтому требует времени и денег. Например:&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самая простая стратегия. Для этого рассчитывается число K – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;. Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;. Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
[[Файл:Smote.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;. Искусственно созданные новые примеры миноритарного класса]]&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Smote_overgeneralization.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;. Негативное влияние алгоритма SMOTE]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Asmo.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;. Основная идея алгоритма ASMO]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]k-means).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
&lt;br /&gt;
Большинство рассмотренных алгоритмов реализованы в&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%5]]&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%%%%%%]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Asmo.png&amp;diff=72906</id>
		<title>Файл:Asmo.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Asmo.png&amp;diff=72906"/>
				<updated>2020-03-17T00:38:28Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Smote_overgeneralization.png&amp;diff=72905</id>
		<title>Файл:Smote overgeneralization.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Smote_overgeneralization.png&amp;diff=72905"/>
				<updated>2020-03-17T00:37:33Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Smote.png&amp;diff=72904</id>
		<title>Файл:Smote.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Smote.png&amp;diff=72904"/>
				<updated>2020-03-17T00:36:32Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72903</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72903"/>
				<updated>2020-03-16T23:43:05Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} ансамбли классификаторов, использующие сэмплирование внутри.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
Передискретизации, как правило, применяется чаще, чем субдискретизация. Подбор проб применяется гораздо реже. Переизбыток собранных данных стал проблемой только в эпоху «больших данных», и причины использования субдискретизация в основном практичны и связаны с затратами на ресурсы.&lt;br /&gt;
Переизбыток уже собранных данных стал проблемой только в эпоху «больших данных», и причины использования недостаточной выборки в основном практичны и связаны с затр%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%атами на ресурсы. В частности, хотя для получения достоверных статистических выводов требуется достаточно большой размер выборки, данные должны быть очищены перед использованием. Очистка обычно включает в себя значительную человеческую составляющую и, как правило, специфична для набора данных и аналитической проблемы, и поэтому требует времени и денег. Например:&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
Это самая простая стратегия. Для этого рассчитывается число K – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
[[Файл:Tomek_links.png|thumb|right|upright=1.7|Рисунок 2 – Удаление мажоритарных примеров, участвующих в связях Томека]]&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
[[Файл:Condensed_nearest_neighbor_rule.png|thumb|right|upright=1.7|Рисунок 3 – Удаление примеров мажоритарного класса правилом сосредоточенного ближайшего соседа]]&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
[[Файл:Random_undersampling.png|thumb|right|upright=1.7|Рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Случайное удаление примеров мажоритарного класса]]&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]k-means).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительные ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль сбалансированных наборов ===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
&lt;br /&gt;
Большинство рассмотренных алгоритмов реализованы в&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%5]]&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%%%%%%]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Condensed_nearest_neighbor_rule.png&amp;diff=72902</id>
		<title>Файл:Condensed nearest neighbor rule.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Condensed_nearest_neighbor_rule.png&amp;diff=72902"/>
				<updated>2020-03-16T23:41:30Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Tomek_links.png&amp;diff=72901</id>
		<title>Файл:Tomek links.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Tomek_links.png&amp;diff=72901"/>
				<updated>2020-03-16T23:38:40Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Random_undersampling.png&amp;diff=72900</id>
		<title>Файл:Random undersampling.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Random_undersampling.png&amp;diff=72900"/>
				<updated>2020-03-16T23:34:49Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: Kirill.vakhrushev загрузил новую версию Файл:Random undersampling.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Random_undersampling.png&amp;diff=72899</id>
		<title>Файл:Random undersampling.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Random_undersampling.png&amp;diff=72899"/>
				<updated>2020-03-16T23:28:10Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72897</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72897"/>
				<updated>2020-03-16T23:13:29Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} Создания ансамбля сбалансированных выборок путем итеративного применения субдискретизации к набору данных.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
Передискретизации, как правило, применяется чаще, чем субдискретизация. Подбор проб применяется гораздо реже. Переизбыток собранных данных стал проблемой только в эпоху «больших данных», и причины использования субдискретизация в основном практичны и связаны с затратами на ресурсы.&lt;br /&gt;
Переизбыток уже собранных данных стал проблемой только в эпоху «больших данных», и причины использования недостаточной выборки в основном практичны и связаны с затр%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%атами на ресурсы. В частности, хотя для получения достоверных статистических выводов требуется достаточно большой размер выборки, данные должны быть очищены перед использованием. Очистка обычно включает в себя значительную человеческую составляющую и, как правило, специфична для набора данных и аналитической проблемы, и поэтому требует времени и денег. Например:&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самая простая стратегия. Для этого рассчитывается число K – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== Дополнительно ====&lt;br /&gt;
* Under-sampling with Cluster Centroids&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* NearMiss &amp;lt;math&amp;gt;(1 \And 2 \And 3)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Instance Hardness Threshold&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* AllKNN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
==== '''ASMO''' (англ. ''Adaptive Synthetic Minority Oversampling'') ====&lt;br /&gt;
Алгоритм ''SMOTE'' имеет недостаток в том, что «вслепую» увеличивает плотность примерами в области слабо представленного класса (рис. &amp;lt;math&amp;gt;5&amp;lt;/math&amp;gt;). В случае, если миноритарные примеры равномерно распределены среди мажоритарных и имеют низкую плотность, алгоритм SMOTE только сильнее перемешает классы.&lt;br /&gt;
В качестве решения данной проблемы был предложен алгоритм адаптивного искусственного увеличения числа примеров миноритарного класса ''ASMO'':&lt;br /&gt;
# Если для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ого примера миноритарного класса из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей &amp;lt;math&amp;gt;g, (g≤k)&amp;lt;/math&amp;gt; принадлежит к мажоритарному, то набор данных считается «рассеянным». В этом случае используют алгоритм ASMO, иначе применяют SMOTE (как правило, &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; задают равным &amp;lt;math&amp;gt;20&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Используя только примеры миноритарного класса, выделить несколько кластеров (например, алгоритмом [[K-средних|&amp;lt;tex&amp;gt;\mathrm{k}&amp;lt;/tex&amp;gt;-средних]]k-means).&lt;br /&gt;
# Сгенерировать искусственные записи в пределах отдельных кластеров на основе всех классов. Для каждого примера миноритарного класса находят &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ближайших соседей, и на основе них (также как в ''SMOTE'') создаются новые записи.&lt;br /&gt;
Такая модификация алгоритма ''SMOTE'' делает его более адаптивным к различным наборам данных с несбалансированными классами. Общее представление идеи алгоритма показано на рис. &amp;lt;math&amp;gt;6&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Дополнительно ====&lt;br /&gt;
* SMOTENC - SMOTE for Nominal Continuous&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* bSMOTE &amp;lt;math&amp;gt;(1 \And 2)&amp;lt;/math&amp;gt; - Borderline SMOTE of types &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SVM SMOTE - Support Vectors SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* ADASYN - Adaptive synthetic sampling approach for imbalanced learning&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Repeated Edited Nearest Neighbours&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* KMeans-SMOTE&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
* SMOTE &amp;lt;math&amp;gt;+&amp;lt;/math&amp;gt; Tomek links&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* SMOTE + ENN&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ансамбль классификаторов, использующие сэмплирование внутри===&lt;br /&gt;
* Easy Ensemble classifier&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Random Forest&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Balanced Bagging&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* RUSBoost&amp;lt;ref&amp;gt; [https://en.wikipedia.org Sampling_(statistics)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
&lt;br /&gt;
Большинство рассмотренных алгоритмов реализованы в&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%5]]&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%%%%%%]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72895</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72895"/>
				<updated>2020-03-16T22:43:40Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} Создания ансамбля сбалансированных выборок путем итеративного применения субдискретизации к набору данных.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
Передискретизации, как правило, применяется чаще, чем субдискретизация. Подбор проб применяется гораздо реже. Переизбыток собранных данных стал проблемой только в эпоху «больших данных», и причины использования субдискретизация в основном практичны и связаны с затратами на ресурсы.&lt;br /&gt;
Переизбыток уже собранных данных стал проблемой только в эпоху «больших данных», и причины использования недостаточной выборки в основном практичны и связаны с затр%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%атами на ресурсы. В частности, хотя для получения достоверных статистических выводов требуется достаточно большой размер выборки, данные должны быть очищены перед использованием. Очистка обычно включает в себя значительную человеческую составляющую и, как правило, специфична для набора данных и аналитической проблемы, и поэтому требует времени и денег. Например:&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
=== Cубдискретизация (удаление примеров мажоритарного класса) ===&lt;br /&gt;
==== '''Случайное удаление примеров мажоритарного класса''' (англ. ''Random Undersampling'') ====&lt;br /&gt;
Это самая простая стратегия. Для этого рассчитывается число K – количество мажоритарных примеров, которое необходимо удалить для достижения требуемого уровня соотношения различных классов. Затем случайным образом выбираются K мажоритарных примеров и удаляются.&lt;br /&gt;
На рис. &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; изображены примеры некоторого набора данных в двумерном пространстве признаков до и после использования алгоритма.&lt;br /&gt;
==== '''Поиск связей Томека''' (англ. ''Tomek Links'') ====&lt;br /&gt;
Пусть примеры &amp;lt;math&amp;gt;E_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_j&amp;lt;/math&amp;gt; принадлежат к различным классам, &amp;lt;math&amp;gt;d(E_i,E_j)&amp;lt;/math&amp;gt; – расстояние между указанными примерами. Пара &amp;lt;math&amp;gt;(E_i,E_j)&amp;lt;/math&amp;gt; называется связью Томека, если не найдется ни одного примера &amp;lt;math&amp;gt;E_l&amp;lt;/math&amp;gt; такого, что будет справедлива совокупность неравенств:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
   d(E_i,E_l)&amp;lt;d(E_i,E_j),\\&lt;br /&gt;
   d(E_j,E_l)&amp;lt;d(E_i,E_j)&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Согласно данному подходу, все мажоритарные записи, входящие в связи Томека, должны быть удалены из набора данных. Этот способ хорошо удаляет записи, которые можно рассматривать в качестве «зашумляющих». На рис. &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; визуально показан набор данных в двумерном пространстве признаков до и после применения стратегии поиска связей Томека.&lt;br /&gt;
==== '''Правило сосредоточенного ближайшего соседа''' (англ. ''Condensed Nearest Neighbor Rule'') ====&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; – исходный набор данных. Из него выбираются все миноритарные примеры и (случайным образом) один мажоритарный. Обозначим это множество как &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Все примеры из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; классифицируются по правилу одного ближайшего соседа. Записи, получившие ошибочную метку, добавляются во множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; (рис. &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;).&lt;br /&gt;
Таким образом, мы будем учить классификатор находить отличие между похожими примерами, но принадлежащими к разным классам.&lt;br /&gt;
==== '''Односторонний сэмплинг''' (англ. ''One-side sampling, one-sided selection'') ====&lt;br /&gt;
Главная идея этой стратегии – это последовательное сочетание предыдущих двух, рассмотренных выше.&lt;br /&gt;
Для этого на первом шаге применяется правило сосредоточенного ближайшего соседа, а на втором – удаляются все мажоритарные примеры, участвующие в связях Томека.&lt;br /&gt;
Таким образом, удаляются большие «сгустки» мажоритарных примеров, а затем область пространства со скоплением миноритарных очищается от потенциального шума.&lt;br /&gt;
==== '''Правило «очищающего» соседа''' (англ. ''Neighborhood cleaning rule'') ====&lt;br /&gt;
Эта стратегия также направлена на то, чтобы удалить те примеры, которые негативно влияют на исход классификации миноритарных классов.&lt;br /&gt;
Для этого все примеры классифицируются по правилу трех ближайших соседей. Удаляются следующие мажоритарные примеры:&lt;br /&gt;
* получившие верную метку класса;&lt;br /&gt;
* являющиеся соседями миноритарных примеров, которые были неверно классифицированы.&lt;br /&gt;
==== '''Сэмплирование''' (англ. ''sampling'') ====&lt;br /&gt;
==== '''Сэмплирование''' (англ. ''sampling'') ====&lt;br /&gt;
&lt;br /&gt;
=== Передискретизации (увеличение числа примеров миноритарного класса) ===&lt;br /&gt;
==== '''Дублирование примеров миноритарного класса''' (англ. ''Oversampling'') ====&lt;br /&gt;
Самый простой метод – это дублирование примеров миноритарного класса. В зависимости от того, какое соотношение классов необходимо, выбирается количество случайных записей для дублирования.&lt;br /&gt;
==== '''SMOTE''' (англ. ''Synthetic Minority Oversampling Technique'') ====&lt;br /&gt;
Этот алгоритм основан на идее генерации некоторого количества искусственных примеров, которые были бы похожи на имеющиеся в миноритарном классе, но при этом не дублировали их. Для создания новой записи находят разность &amp;lt;math&amp;gt;d=X_b–X_a&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;X_a&amp;lt;math&amp;gt;,&amp;lt;math&amp;gt;X_b&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; из миноритарного класса. Их находят, используя алгоритм ближайшего соседа [[Метрический_классификатор_и_метод_ближайших_соседей|KNN]]. В данном случае необходимо и достаточно для примера &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; получить набор из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; соседей, из которого в дальнейшем будет выбрана запись &amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt;. Остальные шаги алгоритма ''KNN'' не требуются.&lt;br /&gt;
&lt;br /&gt;
Далее из &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; путем умножения каждого его элемента на случайное число в интервале &amp;lt;math&amp;gt;(0, 1)&amp;lt;/math&amp;gt; получают &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Вектор признаков нового примера вычисляется путем сложения &amp;lt;math&amp;gt;X_a&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\hat{d}&amp;lt;/math&amp;gt;. Алгоритм ''SMOTE'' позволяет задавать количество записей, которое необходимо искусственно сгенерировать. Степень сходства примеров &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;k&amp;lt;/math&amp;gt;. На рис. &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt; схематично изображено то, как в двумерном пространстве признаков могут располагаться искусственно сгенерированные примеры.&lt;br /&gt;
==== '''Сэмплирование''' (англ. ''sampling'') ====&lt;br /&gt;
==== '''Сэмплирование''' (англ. ''sampling'') ====&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
=== Ансамбль сбалансированных наборов===&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
&lt;br /&gt;
Большинство рассмотренных алгоритмов реализованы в&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%5]]&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%%%%%%]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72889</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72889"/>
				<updated>2020-03-16T02:52:56Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} Создания ансамбля сбалансированных выборок путем итеративного применения субдискретизации к набору данных.&lt;br /&gt;
&lt;br /&gt;
Также все методы можно разделить на две группы: случайные (недетерминированные) и специальные (детерминированные).&lt;br /&gt;
&lt;br /&gt;
Передискретизации, как правило, применяется чаще, чем субдискретизация. Подбор проб применяется гораздо реже. Переизбыток собранных данных стал проблемой только в эпоху «больших данных», и причины использования субдискретизация в основном практичны и связаны с затратами на ресурсы.&lt;br /&gt;
Переизбыток уже собранных данных стал проблемой только в эпоху «больших данных», и причины использования недостаточной выборки в основном практичны и связаны с затр%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%атами на ресурсы. В частности, хотя для получения достоверных статистических выводов требуется достаточно большой размер выборки, данные должны быть очищены перед использованием. Очистка обычно включает в себя значительную человеческую составляющую и, как правило, специфична для набора данных и аналитической проблемы, и поэтому требует времени и денег. Например:&lt;br /&gt;
&lt;br /&gt;
== Примеры алгоритмов ==&lt;br /&gt;
=== Cубдискретизация ===&lt;br /&gt;
=== Передискретизации===&lt;br /&gt;
=== Комбинированние ===&lt;br /&gt;
=== Ансамбль сбалансированных наборов===&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
&lt;br /&gt;
Большинство рассмотренных алгоритмов реализованы в&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%5]]&lt;br /&gt;
*[[%%%%%%%%%%%%%%%%%%%%%%%%%%%%%]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Классификация и регрессия]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72888</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72888"/>
				<updated>2020-03-16T02:42:05Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Подобные тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что значимость ошибочной классификации может быть разной. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс) лучше будет отправить на дополнительное обследование здоровых пациентов, чем пропустить людей с раком.&lt;br /&gt;
&lt;br /&gt;
Неравномерное распределение может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Многие модели машинного обучения, например, нейронные сети, дают более надежные прогнозы на основе обучения со сбалансированными данными. Однако некоторые аналитические методы, в частности [[Линейная_регрессия|линейная регрессия]] и [[Логистическая_регрессия|логистическая регрессия]], не получают дополнительного преимущества.&lt;br /&gt;
&lt;br /&gt;
== Стратегии сэмплирования ==&lt;br /&gt;
* '''Cубдискретизация''' (англ. ''under-sampling'') {{---}} удаление некоторого количество примеров мажоритарного класса.&lt;br /&gt;
* '''Передискретизации''' (англ. ''over-sampling'') {{---}} увеличение количество примеров миноритарного класса.&lt;br /&gt;
* '''Комбинированние''' (англ. ''сombining over- and under-sampling'') {{---}} последовательное применение субдискретизации и передискретизации.&lt;br /&gt;
* '''Ансамбль сбалансированных наборов''' (англ. ''ensemble balanced sets'') {{---}} Создания ансамбля сбалансированных выборок путем итеративного применения субдискретизации к набору данных.&lt;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>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72887</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72887"/>
				<updated>2020-03-16T02:02:20Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных. Нужно отличать этот метод от [[Активное обучение#Методы отбора объектов |сэмплирования в активном обучении]] для отбора кандидатов и от сэмплирования в статистике&amp;lt;ref&amp;gt; [https://en.wikipedia.org/wiki/Sampling_(statistics) Sampling_(statistics)]&amp;lt;/ref&amp;gt; для создания подвыборки с сохранением распределения классов. &lt;br /&gt;
&lt;br /&gt;
Неравномерное распределения данных может быть следующих типов:&lt;br /&gt;
* Недостаточное представление класса в переменной предикторе (независимой переменной);&lt;br /&gt;
* Недостаточное представление класса в критериальной переменной (зависимой).&lt;br /&gt;
&lt;br /&gt;
Нередко возникают ситуации, когда в обучающем наборе данных доля примеров некоторого класса слишком мала, такие классы называются '''миноритарными''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарными''' (англ. ''majority'')). Такие тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге. Построенный на таких наборах данных классификатор может оказаться абсолютно неэффективным.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что может различаться значимость ошибочной классификации. Неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примеров мажоритарного класса. Например, при классификации людей обследованных в больнице на людей больных раком (миноритарный класс) и здоровых (мажоритарный класс).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Одним из подходов для решения указанной проблемы является применение различных стратегий сэмплинга, которые можно разделить на две группы: случайные и специальные.&lt;br /&gt;
&lt;br /&gt;
Восстановление баланса классов может проходить двумя путями. В первом случае удаляют некоторое количество примеров мажоритарного класса (undersampling), во втором – увеличивают количество примеров миноритарного (oversampling). Простейшие подходы сэмплинга описаны в книге «Бизнес-аналитика: от данных к знаниям» (обучение в условиях несбалансированности классов) и в учебном курсе (K.01 Корпоративные аналитические системы), а данная статья посвящена более сложным методам.&lt;br /&gt;
&lt;br /&gt;
Перейдем к кратким теоретическим сведениям о наиболее распространенных стратегиях сэмплинга, а затем некоторые из них сравним, применив на наборе данных с несбалансированными классами.&lt;br /&gt;
&lt;br /&gt;
Two sampling strategies&lt;br /&gt;
We can sample from a bigger class a subsample, or upsample from a smaller class Subsampling this days is used mostly for data exploration and results validation &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи сэмплирования ==&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72886</id>
		<title>Алгоритмы сэмплирования</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D1%81%D1%8D%D0%BC%D0%BF%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=72886"/>
				<updated>2020-03-15T23:35:59Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: Новая страница: «'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью ба…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сэмплирование''' (англ. ''data sampling'') {{---}} метод корректировки обучающей выборки с целью балансировки распределения классов в исходном наборе данных.&lt;br /&gt;
&lt;br /&gt;
Нередко возникают ситуации, когда в обучающем наборе данных доля примеров некоторого класса слишком мала (такие классы называются '''миноритарным ''' (англ. ''minority''), а другие, сильно представленные, — '''мажоритарным''' (англ. ''majority'')). Такие тенденции хорошо заметны в кредитном скоринге, в медицине, в директ-маркетинге. Обученная на таких наборах данных модель может оказаться абсолютно неэффективной.&lt;br /&gt;
&lt;br /&gt;
Следует отметить то, что могут отличаться и издержки ошибочной классификации. Причем неверная классификация примеров миноритарного класса, как правило, обходится в разы дороже, чем ошибочная классификация примера мажоритарного класса.&lt;br /&gt;
&lt;br /&gt;
Одним из подходов для решения указанной проблемы является применение различных стратегий сэмплинга, которые можно разделить на две группы: случайные и специальные.&lt;br /&gt;
&lt;br /&gt;
Восстановление баланса классов может проходить двумя путями. В первом случае удаляют некоторое количество примеров мажоритарного класса (undersampling), во втором – увеличивают количество примеров миноритарного (oversampling). Простейшие подходы сэмплинга описаны в книге «Бизнес-аналитика: от данных к знаниям» (обучение в условиях несбалансированности классов) и в учебном курсе (K.01 Корпоративные аналитические системы), а данная статья посвящена более сложным методам.&lt;br /&gt;
&lt;br /&gt;
Перейдем к кратким теоретическим сведениям о наиболее распространенных стратегиях сэмплинга, а затем некоторые из них сравним, применив на наборе данных с несбалансированными классами.&lt;br /&gt;
&lt;br /&gt;
Two sampling strategies&lt;br /&gt;
We can sample from a bigger class a subsample, or upsample from a smaller class Subsampling this days is used mostly for data exploration and results validation &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи сэмплирования ==&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66449</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66449"/>
				<updated>2018-10-06T18:01:02Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 2) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Рассмотрим реализацию этого принципа алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. &amp;quot;Невезучий&amp;quot; поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм Лампорта – алгоритм разделения общих ресурсов между несколькими потоками обладающий взаимным исключением. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и линейное ожидание.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&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;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     want[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (want[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66448</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66448"/>
				<updated>2018-10-06T17:06:27Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Рассмотрим реализацию этого принципа алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. &amp;quot;Невезучий&amp;quot; поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм Лампорта – алгоритм разделения общих ресурсов между несколькими потоками обладающий взаимным исключением. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и линейное ожидание.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&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;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66447</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66447"/>
				<updated>2018-10-06T17:04:56Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Критическая секция */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Рассмотрим реализацию этого принципа алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. &amp;quot;Невезучий&amp;quot; поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм Лампорта – алгоритм разделения общих ресурсов между несколькими потоками обладающий взаимным исключением. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&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;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66446</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66446"/>
				<updated>2018-10-06T17:04:34Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Аналогия */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Рассмотрим реализацию этого принципа алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. &amp;quot;Невезучий&amp;quot; поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм Лампорта – алгоритм разделения общих ресурсов между несколькими потоками обладающий взаимным исключением. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&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;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66445</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66445"/>
				<updated>2018-10-06T17:04:07Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Рассмотрим реализацию этого принципа алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. &amp;quot;Невезучий&amp;quot; поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм Лампорта – алгоритм разделения общих ресурсов между несколькими потоками обладающий взаимным исключением. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66444</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66444"/>
				<updated>2018-10-06T17:02:01Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Рассмотрим реализацию этого принципа алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. &amp;quot;Невезучий&amp;quot; поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм Лампорта – алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66443</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66443"/>
				<updated>2018-10-06T17:01:10Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Петерсона для N потоков */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Рассмотрим реализацию этого принципа алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. &amp;quot;Невезучий&amp;quot; поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66442</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66442"/>
				<updated>2018-10-06T17:00:24Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Петерсона для 2 потоков */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Рассмотрим реализацию этого принципа алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66441</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66441"/>
				<updated>2018-10-06T16:58:59Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Петерсона для 2 потоков */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66440</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66440"/>
				<updated>2018-10-06T16:58:27Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66439</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66439"/>
				<updated>2018-10-06T16:56:18Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Петерсона для 2 потоков */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66313</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66313"/>
				<updated>2018-09-30T19:36:07Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г. Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66308</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66308"/>
				<updated>2018-09-30T17:59:07Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г. Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм_Лампорта_взаимного_исключения]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66307</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66307"/>
				<updated>2018-09-30T17:56:26Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 2) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г. Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм_Лампорта_взаимного_исключения]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66305</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66305"/>
				<updated>2018-09-30T17:49:21Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г. Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году. Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и отсутствие голодания.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Обладает всеми свойствами классического варианта, но дополнительно позволяет решить проблему с бесконечными метками.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм_Лампорта_взаимного_исключения]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66304</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66304"/>
				<updated>2018-09-30T17:44:15Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г. Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди.&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Обладает всеми свойствами классического варианта, но дополнительно позволяет решить проблему с бесконечными метками.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм_Лампорта_взаимного_исключения]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66303</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66303"/>
				<updated>2018-09-30T17:35:32Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г. Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной.&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Обладает всеми свойствами классического варианта, но дополнительно позволяет решить проблему с бесконечными метками.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм_Лампорта_взаимного_исключения]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66302</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66302"/>
				<updated>2018-09-30T17:05:27Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Алгоритм Лампорта (вариант 1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г. Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Лампорт предлагает рассмотреть пекарню с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной. При наличии нескольких потоков, получивших номер &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; при входе в критическую секцию, поток с меньшим номером &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; будет иметь больший приоритет при обслуживании (входе в критическую секцию).&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Обладает всеми свойствами классического варианта, но дополнительно позволяет решить проблему с бесконечными метками.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм_Лампорта_взаимного_исключения]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66301</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66301"/>
				<updated>2018-09-30T17:01:43Z</updated>
		
		<summary type="html">&lt;p&gt;Kirill.vakhrushev: /* Критическая секция */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waitnig'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г. Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Посмотрим, как реализуется этот общий принцип алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. Невезучий поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм пекарни Лампорта алгоритм разделения общих ресурсов между несколькими потоками путём взаимного исключения. Опубликован Лесли Лампортом в 1974 году.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Лампорт предлагает рассмотреть пекарню с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; от глобальной переменной. При наличии нескольких потоков, получивших номер &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; при входе в критическую секцию, поток с меньшим номером &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; будет иметь больший приоритет при обслуживании (входе в критическую секцию).&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
Ключевое свойство: если поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнил &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, то у него более ранний номер очереди.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (FCFS). Это сильнее чем линейное ожидание, cамое сильное свойство прогресса.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Обладает всеми свойствами классического варианта, но дополнительно позволяет решить проблему с бесконечными метками.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     choosing[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     choosing[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (choosing[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм_Лампорта_взаимного_исключения]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>Kirill.vakhrushev</name></author>	</entry>

	</feed>