Что такое Scikit Learn — гайд по популярной библиотеке Python для начинающих
Scikit-learn — один из наиболее широко используемых пакетов Python для Data Science и Machine Learning. Он позволяет выполнять множество операций и предоставляет множество алгоритмов. Scikit-learn также предлагает отличную документацию о своих классах, методах и функциях, а также описание используемых алгоритмов.
- предварительную обработку данных;
- уменьшение размерности;
- выбор модели;
- регрессии;
- классификации;
- кластерный анализ.
Он также предоставляет несколько наборов данных, которые вы можете использовать для тестирования ваших моделей.
Scikit-learn не реализует все, что связано с машинным обучением. Например, он не имеет комплексной поддержки для:
- нейронных сетей;
- самоорганизующихся карт (сетей Кохонена);
- обучения ассоциативным правилам;
- обучения с подкреплением (reinforcement learning).
Scikit-learn основан на NumPy и SciPy, поэтому необходимо понять хотя бы азы этих двух библиотек, чтобы эффективно применять Scikit-learn.
Scikit-learn — это пакет с открытым исходным кодом. Как и большинство материалов из экосистемы Python, он бесплатный даже для коммерческого использования. Он лицензирован под лицензией BSD.
В этой статье кратко представим некоторые возможности scikit-learn.
Предварительная обработка данных
Вы можете использовать scikit-learn для подготовки ваших данных к алгоритмам машинного обучения: стандартизации или нормализации данных, кодирования категориальных переменных и многое другое.
Давайте сначала определим массив NumPy, с которым будем работать:
>>> import numpy as np
>>> x = np.array([[0.1, 1.0, 22.8],
. [0.5, 5.0, 41.2],
. [1.2, 12.0, 2.8],
. [0.8, 8.0, 14.0]])
>>> x
array([[ 0.1, 1. , 22.8],
[ 0.5, 5. , 41.2],
[ 1.2, 12. , 2.8],
[ 0.8, 8. , 14. ]])
Вам часто нужно преобразовывать данные таким образом, чтобы среднее значение каждого столбца (элемента) было равно нулю, а стандартное отклонение — единице. В этом случае, можно использовать sklearn.preprocessing.StandardScaler:
>>> from sklearn.preprocessing import StandardScaler
>>> scaler = StandardScaler()
>>> scaled_x = scaler.fit_transform(x)
>>> scaler.scale_
array([ 0.40311289, 4.03112887, 14.04421589])
>>> scaler.mean_
array([ 0.65, 6.5 , 20.2 ])
>>> scaler.var_
array([1.6250e-01, 1.6250e+01, 1.9724e+02])
>>> scaled_x
array([[-1.36438208, -1.36438208, 0.18512959],
[-0.3721042 , -0.3721042 , 1.4952775 ],
[ 1.36438208, 1.36438208, -1.23894421],
[ 0.3721042 , 0.3721042 , -0.44146288]])
>>> scaled_x.mean().round(decimals=4)
0.0
>>> scaled_x.mean(axis=0)
array([ 1.66533454e-16, -1.38777878e-17, 1.52655666e-16])
>>> scaled_x.std(axis=0)
array([1., 1., 1.])
>>> scaler.inverse_transform(scaled_x)
array([[ 0.1, 1. , 22.8],
[ 0.5, 5. , 41.2],
[ 1.2, 12. , 2.8],
[ 0.8, 8. , 14. ]])
Бывает, что у вас есть некоторые категориальные данные, и вам нужно преобразовать их в числа. Один из способов сделать это — использовать класс sklearn.preprocessing.OneHotEncoder. Рассмотрим следующий пример с массивами ролей в компании:
>>> from sklearn.preprocessing import OneHotEncoder
>>> roles = np.array([('Tom', 'manager'),
. ('Mary', 'developer'),
. ('Ann', 'recruiter'),
. ('Jim', 'developer')])
>>> roles
array([['Tom', 'manager'],
['Mary', 'developer'],
['Ann', 'recruiter'],
['Jim', 'developer']], dtype='>> encoder = OneHotEncoder()
>>> encoded_roles = encoder.fit_transform(roles[:, [1]])
>>> encoded_roles.toarray()
array([[0., 1., 0.],
[1., 0., 0.],
[0., 0., 1.],
[1., 0., 0.]])
В приведенном выше примере первый столбец объекта encoded_roles указывает, является ли каждый сотрудник разработчиком. Второй и четвертый сотрудник (Мэри и Джим) — разработчики. Второй столбец связан с должностью менеджера. Только первый сотрудник (Том) имеет эту должность. Наконец, третий столбец соответствует должности рекрутера, и им является третий сотрудник (Энн).
Уменьшение размерности
Уменьшение размерности включает в себя выбор или извлечение наиболее важных компонентов (признаков) многомерного набора данных. Scikit-learn предлагает несколько подходов к уменьшению размерности. Одним из них является анализ основных компонентов (PCA).
Выбор модели
Для обучения и тестирования моделей машинного обучения, вам необходимо случайным образом разбивать данные на подмножества. Это включает как входы, так и их соответствующие выходы. Функция sklearn.model_selection.train_test_split () полезна в таких случаях:
>>> import numpy as np
>>> from sklearn.model_selection import train_test_split
>>> x, y = np.arange(1, 21).reshape(-1, 2), np.arange(3, 40, 4)
>>> x
array([[ 1, 2],
[ 3, 4],
[ 5, 6],
[ 7, 8],
[ 9, 10],
[11, 12],
[13, 14],
[15, 16],
[17, 18],
[19, 20]])
>>> y
array([ 3, 7, 11, 15, 19, 23, 27, 31, 35, 39])
>>> x_train, x_test, y_train, y_test =\
. train_test_split(x, y, test_size=0.4, random_state=0)
>>> x_train
array([[ 3, 4],
[13, 14],
[15, 16],
[ 7, 8],
[ 1, 2],
[11, 12]])
>>> y_train
array([ 7, 27, 31, 15, 3, 23])
>>> x_test
array([[ 5, 6],
[17, 18],
[ 9, 10],
[19, 20]])
>>> y_test
array([11, 35, 19, 39])
В дополнение к обычному разделению наборов данных, scikit-learn предоставляет средства для осуществления перекрестной проверки, настройки гиперпараметров ваших моделей с помощью поиска по сетке, вычисления многих величин, которые показывают производительность модели (например, коэффициент детерминации, среднеквадратичная ошибка, показатель отклонения с пояснением, матрица ошибок, отчет о классификации, f-показатели и многое другое).
Набор данных
Scikit-learn предоставляет несколько наборов данных, подходящих для изучения и тестирования ваших моделей. В основном, это известные наборы данных. Они представляют собой достаточный объем данных для тестирования моделей и в то же время не очень большой, что обеспечивает приемлемую продолжительность обучения.
Например, функция sklearn.datasets.load_boston () отображает данные о ценах на дома в районе Бостона (цены не обновляются!). Есть 506 наблюдений, а входная матрица имеет 13 столбцов (признаков):
>>> from sklearn.datasets import load_boston
>>> x, y = load_boston(return_X_y=True)
>>> x.shape, y.shape
((506, 13), (506,))
Этот набор данных подходит для многовариантной регрессии.
Другой пример — набор данных, связанный с вином. Его можно получить с помощью функции sklearn.datasets.load_wine ():
>>> from sklearn.datasets import load_wine
>>> x, y = load_wine(return_X_y=True)
>>> x.shape, y.shape
((178, 13), (178,))
>>> np.unique(y)
array([0, 1, 2])
Этот набор данных подходит для классификации. Он содержит 13 функций, связанных с тремя различными винодельческими компаниями из Италии, и 178 наблюдений.
Регрессия
Scikit-learn поддерживает различные методы регрессии начиная с линейной регрессии, метода k-ближайших соседей посредством полиномиальной регрессии, регрессии опорных векторов, деревьев принятия решений и т.д., до ансамбля методов, таких как random forest и градиентный бустинг. Он также поддерживает нейронные сети, но не в такой степени, как специализированные библиотеки, например, как TensorFlow.
Ниже покажем регрессию random forest.
Обычно мы начинаем наше регрессионное путешествие с импорта необходимых нам пакетов, классов и функций:
>>> import numpy as np
>>> from sklearn.datasets import load_boston
>>> from sklearn.ensemble import RandomForestRegressor
>>> from sklearn.model_selection import train_test_split
Следующим шагом является получение данных для работы и разделение этих данных на обучающее и тестовое подмножества. Мы будем использовать набор данных Бостона:
>>> x, y = load_boston(return_X_y=True)
>>> x_train, x_test, y_train, y_test =\
. train_test_split(x, y, test_size=0.33, random_state=0)
Некоторые методы требуют масштабирования (стандартизации) данных, в то время как для других методов это необязательно. На этот раз мы продолжим без масштабирования.
Теперь нам нужно создать наш регрессор и обучить его с помощью подмножества данных, выбранного для обучения:
>>> regressor = RandomForestRegressor(n_estimators=10, random_state=0)
>>> regressor.fit(x_train, y_train)
RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,
max_features='auto', max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=10,
n_jobs=None, oob_score=False, random_state=0, verbose=0,
warm_start=False)
После того, как модель обучена, мы проверяем коэффициент детерминации на обучающем подмножестве данных и, что более важно, на тестовом подмножестве данных, который не использовался при обучении моделей.
>>> regressor.score(x_train, y_train)
0.9680930547240916
>>> regressor.score(x_test, y_test)
0.8219576562705848
Модель, обученная достаточно хорошо, может использоваться для прогнозирования выходных данных при других новых входных данных x_new. В данном случае, используется команда .predict(): regressor.predict(x_new).
Классификация
Scikit-learn выполняет классификацию почти так же, как регрессию. Он поддерживает различные методы классификации, такие как логистическая регрессия и k-ближайшие соседи, метод опорных векторов, наивный байесовский классификатор, дерево принятия решений, а также ансамбль методов, такие как random forest, AdaBoost и градиентный бустинг.
В этой статье показано, как использовать метод random forest для классификации. Этот подход весьма аналогичен подходу, применяемому в случае регрессии. Но теперь мы будем использовать набор данных, связанных с вином, определять классификатор и оценивать его с точностью классификации вместо коэффициента детерминации.
>>> import numpy as np
>>> from sklearn.datasets import load_wine
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.model_selection import train_test_split
>>> x, y = load_wine(return_X_y=True)
>>> x_train, x_test, y_train, y_test =\
. train_test_split(x, y, test_size=0.33, random_state=0)
>>> classifier = RandomForestClassifier(n_estimators=10, random_state=0)
>>> classifier.fit(x_train, y_train)
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
max_depth=None, max_features='auto', max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=10,
n_jobs=None, oob_score=False, random_state=0, verbose=0,
warm_start=False)
>>> classifier.score(x_train, y_train)
1.0
>>> classifier.score(x_test, y_test)
1.0
Модель, обученная достаточно хорошо, может использоваться для прогнозирования выходных данных при других новых входных данных. В данном случае, используется команда .predict(): regressor.predict(x_new).
Кластерный анализ
Кластеризация — это ветвь неконтролируемого обучения, широко поддерживаемая в scikit-learn. В дополнение к методу k-средних, есть возможность применять метод распространения близости, спектральную кластеризацию, агломеративную кластеризацию и т.д.
В этой статье мы покажем метод k-средних. При его реализации, будьте внимательны, имеет ли смысл стандартизировать или нормализовать ваши данные и особенно, какая мера расстояния подходит (в большинстве случаев, это евклидово расстояние).
Опять же, мы начинаем с импорта и получения данных. На этот раз мы возьмем NumPy и sklearn.cluster.KMeans:
>>> import numpy as np
>>> from sklearn.cluster import KMeans
>>> x = np.array([(0.0, 0.0),
. (9.9, 8.1),
. (-1.0, 1.0),
. (7.1, 5.6),
. (-5.0, -5.5),
. (8.0, 9.8),
. (0.5, 0.5)])
>>> x
array([[ 0. , 0. ],
[ 9.9, 8.1],
[-1. , 1. ],
[ 7.1, 5.6],
[-5. , -5.5],
[ 8. , 9.8],
[ 0.5, 0.5]])
Следующим шагом является масштабирование данных, но это не всегда обязательно. Однако во многих случаях это действительно хорошая идея. Как только предварительная обработка данных завершена, мы создаем копию KMeans и подгоняем ее под наши данные:
>>> cluster_analyzer = KMeans(n_clusters=3, init='k-means++')
>>> cluster_analyzer.fit()
>>> cluster_analyzer.fit(x)
KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
n_clusters=3, n_init=10, n_jobs=None, precompute_distances='auto',
random_state=None, tol=0.0001, verbose=0)
Итак, мы готовы получить результаты, такие как координаты центров кластеров и метки кластеров, которым принадлежит каждое наблюдение:
>>> cluster_analyzer.cluster_centers_
array([[ 8.33333333, 7.83333333],
[-0.16666667, 0.5 ],
[-5. , -5.5 ]])
>>> cluster_analyzer.labels_
array([1, 0, 1, 0, 2, 0, 1], dtype=int32)
Вы можете использовать метод . predict() для получения ближайших кластеров для новых наблюдений.
Заключение
В этой статье представлены только основы Scikit-Learn, очень популярного пакета Python по data science и machine learning. Это одна из основных библиотек Python для этих целей.
Примеры разделения датасета на train и test c Scikit-learn
Если вы разбиваете датасет на данные для обучения и тестирования, нужно помнить о некоторых моментах. Далее следует обсуждение трех передовых практик, которые стоит учитывать при подобном разделении. А также демонстрация того, как реализовать эти соображения в Python.
В данной статье обсуждаются три конкретных особенности, которые следует учитывать при разделении набора данных, подходы к решению связанных проблем и практическая реализация на Python.
Для наших примеров мы будем использовать модуль train_test_split библиотеки Scikit-learn, который очень полезен для разделения датасетов, независимо от того, будете ли вы применять Scikit-learn для выполнения других задач машинного обучения. Конечно, можно выполнить такие разбиения каким-либо другим способом (возможно, используя только Numpy). Библиотека Scikit-learn включает полезные функции, позволяющее сделать это немного проще.
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.67, random_state=42)Возможно, вы использовали этот модуль для разделения данных в прошлом, но при этом не приняли во внимание некоторые детали.
Случайное перемешивание строк
Первое, на что следует обратить внимание: перемешаны ли ваши экземпляры? Это следует делать пока нет причин не перетасовывать данные (например, они представляют собой временные интервалы). Мы должны убедиться в том, что наши экземпляры не разбиты на выборки по классам. Это потенциально вносит в нашу модель некоторую нежелательную предвзятость.
Например, посмотрите, как одна из версий набора данных iris, упорядочивает свои экземпляры при загрузке:
from sklearn.datasets import load_iris iris = load_iris() X, y = iris.data, iris.target print(f"Классы датасета: ")Классы датасета: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
Если такой набор данных с тремя классами при равном числе экземпляров в каждом разделить на две выборки: 2/3 для обучения и 1/3 для тестирования, то полученные поднаборы будут иметь нулевое пересечение классовых меток. Это, очевидно, недопустимо при изучении признаков для предсказания классов. К счастью, функция train_test_split по умолчанию автоматически перемешивает данные (вы можете переопределить это, установив для параметра shuffle значение False ).
- В функцию должны быть переданы как вектор признаков, так и целевой вектор (X и y).
- Для воспроизводимости вы должны установить аргумент random_state .
- Также необходимо определить либо train_size , либо test_size , но оба они не нужны. Если вы явно устанавливаете оба параметра, они должны составлять в сумме 1.
Вы можете убедится, что теперь наши классы перемешаны.
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.67, random_state=42) print(f"Классы в y_train:\n") print(f"Классы в y_test:\n")Классы в y_train: [1 2 1 0 2 1 0 0 0 1 2 0 0 0 1 0 1 2 0 1 2 0 2 2 1 1 2 1 0 1 2 0 0 1 1 0 2 0 0 1 1 2 1 2 2 1 0 0 2 2 0 0 0 1 2 0 2 2 0 1 1 2 1 2 0 2 1 2 1 1 1 0 1 1 0 1 2 2 0 1 2 2 0 2 0 1 2 2 1 2 1 1 2 2 0 1 2 0 1 2] Классы в y_test: [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1 0 0 0 2 1 1 0 0 1 2 2 1 2]
Стратификация (равномерное распределение) классов
Данное размышление заключается в следующем. Равномерно ли распределено количество классов в наборах данных, разделенных для обучения и тестирования?
import numpy as np print(f"Количество строк в y_train по классам: ") print(f"Количество строк в y_test по классам: ")Количество строк в y_train по классам: [31 35 34] Количество строк в y_test по классам: [19 15 16]
Это не равная разбивка. Главная идея заключается в том, получает ли наш алгоритм равные возможности для изучения признаков каждого из представленных классов и последующего тестирования результатов обучения, на равном числе экземпляров каждого класса. Хотя это особенно важно для небольших наборов данных, желательно постоянно уделять внимание данному вопросу.
Мы можем задать пропорцию классов при разделении на обучающий и проверяющий датасеты с помощью параметра stratify функции train_test_split . Стоит отметить, что мы будем стратифицировать в соответствии распределению по классам в y .
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.67, random_state=42, stratify=y) print(f"Количество строк в y_train по классам: ") print(f"Количество строк в y_test по классам: ")Количество строк в y_train по классам: [34 33 33] Количество строк в y_test по классам: [16 17 17]
Сейчас это выглядит лучше, и представленные числа говорят нам, что это наиболее оптимально возможное разделение.
Дополнительное разделение
Третье соображение относится к проверочным данным (выборке валидации). Есть ли смысл для нашей задачи иметь только один тестовый датасет. Или мы должны подготовить два таких набора — один для проверки наших моделей во время их точной настройки, а еще один — в качестве окончательного датасета для сравнения моделей и выбора лучшей.
Если мы определим 2 таких набора, это будет означать, что одна выборка, будет храниться до тех пор, пока все предположения не будут проверены, все гиперпараметры не настроены, а все модели обучены для достижения максимальной производительности. Затем она будет показана моделям только один раз в качестве последнего шага в наших экспериментах.
Если вы хотите использовать датасеты для тестирования и валидации, создать их с помощью train_test_split легко. Для этого мы разделяем весь набор данных один раз для выделения обучающей выборки. Затем еще раз, чтобы разбить оставшиеся данные на датасеты для тестирования и валидации.
Ниже, используя набор данных digits, мы разделяем 70% для обучения и временно назначаем остаток для тестирования. Не забывайте применять методы, описанные выше.
from sklearn.datasets import load_digits digits = load_digits() X, y = digits.data, digits.target X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, random_state=42, stratify=y) print(f"Количество строк в y_train по классам: ") print(f"Количество строк в y_test по классам: ")Количество строк в y_train по классам: [124 127 124 128 127 127 127 125 122 126] Количество строк в y_test по классам: [54 55 53 55 54 55 54 54 52 54]
Обратите внимание на стратифицированные классы в полученных наборах. Затем мы повторно делим тестовый датасет.
X_test, X_val, y_test, y_val = train_test_split(X_test, y_test, train_size=0.5, random_state=42, stratify=y_test) print(f"Количество строк в y_test по классам: ") print(f"Количество строк в y_val по классам: ")Количество строк в y_test по классам: [27 27 27 27 27 28 27 27 26 27] Количество строк в y_val по классам: [27 28 26 28 27 27 27 27 26 27]
Обратите внимание на стратификацию классов по всем наборам данных, которая является оптимальной.
Теперь вы готовы обучать, проверять и тестировать столько моделей машинного обучения, сколько вы сочтете нужным для ваших данных.Еще один совет: вы можете подумать об использовании перекрестной валидации вместо простой стратегии обучение/тестирование или обучение/валидация/тестирование. Мы рассмотрим вопросы кросс-валидации в следующий раз.
sklearn.datasets .make_blobs¶
sklearn.datasets. make_blobs ( n_samples = 100 , n_features = 2 , * , centers = None , cluster_std = 1.0 , center_box = (-10.0, 10.0) , shuffle = True , random_state = None , return_centers = False ) [source] ¶
Generate isotropic Gaussian blobs for clustering.
Read more in the User Guide .
Parameters : n_samples int or array-like, default=100
If int, it is the total number of points equally divided among clusters. If array-like, each element of the sequence indicates the number of samples per cluster.
Changed in version v0.20: one can now pass an array-like to the n_samples parameter
n_features int, default=2
The number of features for each sample.
centers int or array-like of shape (n_centers, n_features), default=None
The number of centers to generate, or the fixed center locations. If n_samples is an int and centers is None, 3 centers are generated. If n_samples is array-like, centers must be either None or an array of length equal to the length of n_samples.
cluster_std float or array-like of float, default=1.0
The standard deviation of the clusters.
center_box tuple of float (min, max), default=(-10.0, 10.0)
The bounding box for each cluster center when centers are generated at random.
shuffle bool, default=True
Shuffle the samples.
random_state int, RandomState instance or None, default=None
Determines random number generation for dataset creation. Pass an int for reproducible output across multiple function calls. See Glossary .
return_centers bool, default=False
If True, then return the centers of each cluster.
New in version 0.23.
Returns : X ndarray of shape (n_samples, n_features)
The generated samples.
y ndarray of shape (n_samples,)
The integer labels for cluster membership of each sample.
centers ndarray of shape (n_centers, n_features)
The centers of each cluster. Only returned if return_centers=True .
A more intricate variant.
>>> from sklearn.datasets import make_blobs >>> X, y = make_blobs(n_samples=10, centers=3, n_features=2, . random_state=0) >>> print(X.shape) (10, 2) >>> y array([0, 0, 1, 0, 2, 2, 2, 1, 1, 0]) >>> X, y = make_blobs(n_samples=[3, 3, 4], centers=None, n_features=2, . random_state=0) >>> print(X.shape) (10, 2) >>> y array([0, 1, 2, 0, 2, 2, 2, 1, 1, 0])What is Random State? And Why is it Always 42?
An inquiry into what the number 42 has to do with machine learning and the universe
4 min read
Nov 30, 2020If you’re like me and have used or been interested in using artificial intelligence or machine learning to solve various real-world problems, then you have undoubtedly run into the mystical Random State variable and wondered: why is it always 42? Well, turns out the answer is far less mundane than the explanation you typically get on StackOverflow threads about esoteric variable settings.
If you’re just here for the answer to the titular question, then here it is: the number doesn’t really matter; it’s an arbitrary number fed into the program to dictate that the program should use a specific seed of randomness (42). This is so the same set of pseudo-random numbers is generated each time we run the program. This answer isn’t quite satisfactory though as it leads us to another larger question: If it doesn’t matter then why do people always choose 42?
Turns out the answer to this question is equal parts science and fiction. The number 42 is sort of an ongoing inside joke in the scientific and science fiction community and is derived from the legendary Hitchhiker’s Guide to the Galaxy by Douglas Adams wherein an enormous supercomputer named Deep Thought calculates the “Answer to the Ultimate Question of Life…” over the period of 7.5 million years. This was originally intended to be entirely a joke but since its publication in 1979, science fiction junkies and nerds alike have attempted to impute meaning to the number and somewhat verify its claim of answering the “Ultimate Question of Life, the Universe and Everything”. You can check out the many pop culture references to the number 42 on its dedicated Wikipedia page.
The ironic part is that Douglas Adams himself undermines everyone’s obsession with the number:
“It was a joke. It had to be a number, an ordinary, smallish number, and I chose that one. Binary representations, base 13, Tibetan monks are all complete nonsense. I sat on my desk, stared in to the garden and thought 42 will do. I typed it out. End of story.”
Despite Adams’ attempts to quell the world’s feverish fascination with the number, people don’t hesitate to search for and point out the occurrences of the number 42. To name a few:
- The Titanic was traveling at a speed of 42 km/hour when it collided with the iceberg
- On page 42 of Harry Potter and the Philosopher’s Stone, Harry finds out he is a wizard
- In the Book of Revelation, it is prophesied that the beast will hold dominion over the earth for 42 months.
- 42 is the angle rounded to whole degrees for which a rainbow appears (the critical angle).
- Lewis Carrol, a mathematician and writer made use of the number several times in his works. For example, rule Forty-two in Alice’s Adventures in Wonderland (“All persons more than a mile high to leave the court”).
- Alice’s attempts at multiplication (chapter two of Alice in Wonderland) work if one uses base 18 to write the first answer, and increases the base by threes to 21, 24, etc. (the answers working up to 4 × 12 = “19” in base 39), but “breaks” precisely when one attempts the answer to 4 × 13 in base 42, leading Alice to declare “oh dear! I shall never get to twenty at that rate!”
So, why do we set Random State to 42 when running Machine Learning algorithms?
Because, it is simply the answer to life, the universe and everything.
…Or if you’re a bit less romantic about it, it’s because geeks and nerds alike really enjoy science fiction and one of the most famous science fiction books ever written heavily associates the number 42 with advanced machine learning and artificial intelligence.
I, personally, love running into little easter eggs like this in my life, and get a kick out of the fact that people around the world unquestioningly set 42 as their random state variable, unaware of its hilarious history and pop culture relevance.
If you liked this article and would like to read more stuff like this in the future, consider giving me a follow on Medium. Thanks for reading.