Исследование исходного кода Scikit-Learn (этап 2) Детали реализации базовых классов

машинное обучение
Исследование исходного кода Scikit-Learn (этап 2) Детали реализации базовых классов

Проект sklearn можно рассматривать как большое дерево, различные оценщики — это плоды, а костяк, поддерживающий эти оценщики, — один из немногих базовых классов. Несколько общих классов: BaseEstimator, BaseSGD, ClassifierMixin, RegressorMixin и так далее.

На справочной странице API официальной документации перечислены основные интерфейсы API, давайте взглянем на класс Base.

В этом выпуске мы изучаем только BaseEstimator, ClassifierMixin, RegressorMixin и TransformerMixin. BaseSGD — относительно большая тема, и ее нужно тщательно изучить в отдельном выпуске.

BaseEstimator

Нижний уровень — это класс BaseEstimator. В основном выставляют два метода:set_params,get_params.

get_params

Этот метод предназначен для получения параметров объекта, а возвращаемый объект по умолчанию представляет собой пару ключ-значение {параметр:значение параметра}. еслиget_paramsпараметрыdeepПри значении True также возвращаются (если есть) дочерние объекты (которые являются оценщиками). Давайте подробнее рассмотрим детали реализации этого метода:

В целях экономии места я буду опускать неважные комментарии, которые будут обрабатываться таким же образом в будущем и не будут повторяться, если не указано иное.

(1) Основная часть функцииgetattrметод, синтаксис: getattr(объект, атрибут для получения [ возвращаемое значение, если атрибут не существует]). Задача Line200~208 состоит в том, чтобы определить, содержит ли self (обычно экземпляр оценщика) ключевой параметр, и если да, то вернуть значение его параметра, в противном случае ему искусственно присваивается значение None.

Почему так сложно писать? На самом деле, вы можете прямо написатьvalue = getattr(self, key, None), немного запутался~

(2) Давайте посмотрим на Line209~212, если пользователь установилdeep=True, а объект значения реализуетget_params(Это означает, что объект значения является подобъектом, то есть оценщиком, иначе обычные параметры не будут реализованы сноваget_paramsметод), извлеките пары ключ-значение из словаря параметров и запишите их в словарь. Вся функция, наконец, возвращает словарь.

(3) Кратко рассмотрим, как используется этот метод, а затем продолжим отслеживать реализацию исходного кода.

from sklearn.ensemble import RandomForestClassifier

clf = RandomForestClassifier(random_state=0)
X = [[ 1,  2,  3],  # 2 samples, 3 features
     [11, 12, 13]]
y = [0, 1]  # classes of each sample
clf.fit(X, y)

Просто создайте экземпляр объекта классификатора случайного леса, давайте посмотрим, как его вызвать.get_paramsЧто будет возвращено:

clf.get_params()

{'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}

Очевидно, что это схема параметров по умолчанию для этого классификатора случайного леса.

(4) Замечаем строку Line199 и используем другой методfor key in self._get_param_names():, теперь изучите функцию

Повторюсь здесь, в крупномасштабном проекте Python, таком как sklearn, многие открытые методы по сути являются просто оболочкой.Вы можете понять, что она несет в себе вещи, сделанные другими, просто украшая и упаковывая их для вызывающей стороны. Напримерget_paramsметод, он на самом деле не получает параметры экземпляра оценщика, потому что_get_param_namesПомогая ему в этой работе.

@classmethodЭтот декоратор прямо говорит нам, что применимым объектом этого метода является сам класс, а не объект-экземпляр.

В этой функции много проверок, та, которая фактически получает параметр,inspect.signature(init).parameters.values()и, наконец, получить значение каждого объекта в спискеnameАтрибуты.

set_params

Этот метод используется для установки параметров. Обычно мы настраиваем параметры при инициализации оценщика, но также есть необходимость временно изменить параметры, которые можно вызвать вручную.set_paramsметод. Но чаще этот метод вызывается классом, наследующим BaseEstimator.

В частности, давайте посмотрим на детали реализации:

Эта схема поддерживает обработку вложенных словарей, но мы такими мелочами не заморачиваемся, а смотрим напрямую L251,setattr(self, key, value), который устанавливает новое значение для ключевого свойства средства оценки.

Примеры приложений:

ClassifierMixin

Mixin означает смешивание в классе, что можно просто понимать как добавление некоторых дополнительных методов к другим классам. Классификация Sklearn и смешанные классы регрессии реализованы толькоscoreметоды, любой класс, который их наследует, должен реализовать их самfit,predictи другие методы.

Что касается смешанного класса, то это просто родительский класс, но он немного отличается от обычного класса, ему нужно указать метаобъект,_estimator_type. Здесь нет дальнейшего обсуждения, заинтересованные читатели должны прочитать это обсуждение.What is a mixin, and why are they useful?

Как видите, реализация этого класса примесей очень проста: для расчета точности прогнозируемого значения и фактического значения возвращаемое значение представляет собой число с плавающей запятой. Обратите внимание, что прогнозируемое значение исходит изself.predict(), поэтому класс, который наследует класс миксина, должен реализовать его самpredictметод, в противном случае возникает ошибка. Эта деталь в дальнейшем не повторяется.

Еще раз, смешанный класс задачи классификации несет в себе результаты труда других функций, так что давайте изучим егоaccuracy_scoreдетали реализации

Для краткости мы сначала проигнорируем код между L185~189, а позже будет статья, посвященная методу измерения задачи классификации, где мы подробно изучим его. Посмотрите прямо на L191,y_ture == y_pred, это простой способ записи, тонкость заключается в том, чтобы избежать цикла for, быстро проверить, равен ли каждый элемент между двумя объектами, и вернуть True/False. L193 упаковывает результаты оценки.

  • L116: если установленоnormalizeЕсли параметр имеет значение True, среднее значение списка оценок равно количеству правильных выборок/населенности = точности прогноза.
  • L118: Если есть вес, взвесьте баллы каждой выборки в соответствии с весом в качестве конечной точности прогноза.
  • L121: Если указанные выше две настройки отсутствуют, количество правильно предсказанных выборок будет возвращено напрямую. Примечание. По умолчанию sklearnscoreМетод возвращает точность предсказания, а не правильное количество выборок.

RegressorMixin

Неудивительно, что класс миксина для задачи регрессии реализует толькоscoreметод, основной математический принципR^2ценность. Формула 1-((y_true - y_pred)**2)/((y_true - y_true_mean)**2). Интуитивно это значение является мерой отклонения между предсказанным значением и реальным значением, а также отклонением сама реальная стоимость отношение.R^2Максимальное значение равно 1, что указывает на то, что прогноз полностью точен, а значение 0 указывает на то, что модель не имеет возможности прогнозирования.

scoreметод называетсяmetricsмодульныйr2_scoreметод, возвращаемое значение является числом с плавающей запятой. Давай учитьсяr2_score, эта функция, безусловно, самая сложная из тех, что мы видели. Итак, давайте изучать его по частям.

Проверить входящий объект

(1) Проверьте длину входящего объекта вызов L577check_consistent_lengthПроверьте, имеют ли входные метки, выходные метки и веса одинаковую длину. Метод проверки также очень прост.Вычислить длину каждого объекта, а затем взять, сколько существует различных значений длины.Если их больше одного, то это означает, что длины между несколькими объектами разные, и ошибка поднимается, чтобы предупредить.

(2) Проверьте, являются ли входящие параметры допустимыми. L575 вызов_check_reg_targetsметод, предназначенный для проверки корректности входящего параметра.

Эта функция немного длиннее, но примерно делает следующее:

  • L83~95 все выполняют проверку и преобразование формата.
  • L97~114 Проверить вводmultioutputиy_trueСовпадет ли, то есть если размерность реального массива меток равна 1, очевидно заданаmultioutputНедопустимо, чтобы этот параметр был отличным от None. А когда размерность реального массива меток больше 1, если его размерность иmultioutputОшибки также поднимаются, чтобы предупредить.
  • L115 согласноy_trueРазмер определяет тип этикетки и делится на: непрерывный тип и непрерывный тип многоклассового вывода. Уведомление:multioutputЭто может быть строка, массив или значение None (учитывая обратную совместимость), поэтому этот параметр очень гибкий. Я упомяну об этом снова, когда буду изучать конкретный алгоритм позже, поэтому не буду здесь слишком много запутываться.

Проверьте размер выборки и весовые коэффициенты

Продолжай смотретьr2_scoreРеализация:

(3) Количество выборок для L597~582 для проверки предсказанного значения Если количество выборок прогнозируемого значения меньше 2, будет выдано предупреждение об ошибке. потому что коэффициент детерминации (т.е.R^2) требуется как минимум 2 образца

(4) Весовой коэффициент обработки L584~588

  • L585 вызовnp.ravel(), сгладить массив весов до одного измерения
  • Пара L586sample_weightsРасширение измерения, расширение одного измерения в два измерения, расширение двух измерений в три измерения и так далее. В частности,np.newaxisМесто размещения другое, и направление расширения другое.Подробнее смотрите в следующем небольшом примере:
  • L588, если весовой коэффициент не передается, значение по умолчанию равно 1.

выполнитьR^2Детали расчета

(5) Построить числитель и знаменатель

(6) Подсчитайте оценку каждого образца.

  • L595~596 Запишите значение индекса, отличное от 0, в массиве знаменателя и числителя (то есть положение значения, отличного от 0)
  • L597 Запишите значение индекса выборки, у которой числитель и знаменатель одновременно не равны 0. Если вы не знакомы с этим способом написания, вот небольшой пример, который поможет понять:
  • L598~599 создать массив из всех единиц той же длины, что и реальная метка, а затем вычислить реальнуюR^2ценность.
  • L603 Установите значение позиции индекса, знаменатель которой равен от 0 до 0. Здесь также можно установить другие константы, и это не влияет на оценку той же задачи регрессии.

(7) Согласноmultioutputпараметры для определения веса оценок, полученных по каждой выборке

  • L605~607, если указаноraw_values, затем выведите оценку каждого образца
  • L608~610, если указаноuniform_average, то для avg_weights устанавливается значение None, что на самом деле является равномерным распределением весов.
  • L611~612, если указаноvariance_weighted, затем непосредственно используйте знаменатель в качестве веса
  • L614~618 имеют дело с постоянными значениями y или одномерными массивами. Если в знаменателе все 0, то: если числитель не равен 0, сразу вернуть 1, иначе вернуть 0
  • L620, еслиmultioutputне является строкой, используйте его непосредственно как окончательный весовой коэффициент

(8) Вернуть счет

return np.average(output_scores, weights=avg_weights)

только сказал,uniform_average, тогда avg_weights имеет значение None. существуетnumpy.averageВ этом методе, если вес равен None, вычислить среднее значение просто.mean()функция.

TransformerMixin

Реализация этого смешанного класса относительно проста и полностью зависит от реализации класса, который его использует.fitМетоды иtransformметод. Но он решит, является ли это контролируемой задачей или неконтролируемой задачей, в зависимости от того, есть ли метка или нет. Подробно обсудим позже.

Пополнить

Когда мы изучаем смешанный класс классификации и смешанный класс регрессии, мы обнаруживаем, что существуют_estimator_typeЭта переменная, ее конкретная роль показана здесь, чтобы определить, используется ли оценщик для задач классификации или задач регрессии.


Если есть какие-либо ошибки, пожалуйста, прокомментируйте и взаимодействуйте.