Scikit-Learn невероятен. Он позволяет своим пользователям использовать практически любую модель машинного обучения, о которой вы только можете подумать, а также многие из них, о которых вы, возможно, даже не слышали! Всего в двух строчках кода!
Однако в нем нет всего. Например, нигде нет порядковой регрессии. А его возможности глубокого обучения… отсутствуют. Но кого это волнует? Вы можете найти это в другом месте, верно?
Правда. Но! Scikit-Learn - это не просто моделирование. Есть также несколько действительно отличных инструментов, которые помогут вам упростить процесс моделирования, например GridSearchCV
и Pipeline
. Эти инструменты бесценны, но они работают только с моделями Scikit-Learn. Оказывается, если Scikit-Learn и наши повелители Google не передадут его нам напрямую, мы сможем создать наши собственные модели, совместимые с Scikit-Learn! И это проще, чем вы думаете!
В этом посте я собираюсь создать то, чего явно не хватает в Scikit-Learn: возможность использовать кластеризацию k -средств для переноса обучения в Pipeline
. То есть ввод результатов кластеризации в модель обучения с учителем, чтобы найти оптимальное значение k.
Предупреждение: впереди ООП!
Этот пост будет немного техническим. В частности, я предполагаю, что у вас есть практические знания в области объектно-ориентированного программирования (ООП). То есть вы знаете, как и зачем использовать ключевое слово class
Python.
Шаблон Scikit-Learn
Одна из лучших особенностей Scikit-Learn - его невероятная согласованность. Установка одного типа модели номинально аналогична установке любого другого типа модели. То есть моделировать в Scikit-Learn так же просто, как:
model = MyModel(parameters) model.fit(X, y)
Вот и все! Теперь вы можете проанализировать свою модель, возможно, с помощью методов модели .predict()
и .score()
. Фактически, каждый оценщик Scikit-Learn гарантированно имеет 5 методов:
.fit()
.predict()
.score()
.set_params()
.get_params()
Создайте свой собственный
Чтобы построить нашу собственную модель, нам нужно только создать класс, который имеет перечисленные выше 5 методов, и реализовать их «обычным способом». Похоже, это большая работа. К счастью, Scikit-Learn делает за нас тяжелую работу. Чтобы построить нашу собственную модель, мы можем наследовать от базового класса, встроенного в Scikit-Learn.
В сторону: наследование
В ООП, если мы указываем, что один класс наследует от другого, «подкласс» получает все методы «суперкласса».
Синтаксис наследования выглядит так:
class Car(Vehicle): # stuff...
Автомобиль - это вид транспортного средства. Класс Car
будет включать все методы класса Vehicle
, а также многое другое, что мы можем определить в определении класса Car
.
Что дает нам Scikit-Learn?
Чтобы соответствовать Scikit-Learn, наша модель должна наследовать от некоторого миксина. mixin - это просто класс, который никогда не предназначался для работы сам по себе, вместо этого он просто содержит множество методов, которые вы можете добавить к своему текущему классу посредством наследования. Scikit-Learn дает нам по одной модели для каждого общего типа: RegressorMixin
, ClassifierMixin
, ClusterMixin
, TransformerMixin
и некоторых других, о которых нам не нужно беспокоиться.
Все, что мы хотим построить сами, мы делаем, просто отменяя то, что мы унаследовали!
Это было утомительно, и примеров, которые можно было бы показать, нет. Сначала простой пример. Далее пример мотивации с помощью кластеризации.
Пример 1: нулевая модель
Нулевая модель, иногда называемая «базовой» моделью, - это модель, в которой у вас нет информации, кроме случайных предположений. Например, нулевая модель для задачи регрессии будет просто брать среднее y ваших обучающих данных и использовать его в качестве каждого прогноза. Для классификации нужно просто брать класс большинства для каждого прогноза. Например, если вам нужно было предсказать, выиграет ли кто-нибудь в лотерею, нулевая модель будет диктовать, что вы всегда проигрываете, поскольку это наиболее вероятный результат.
Нулевая модель полезна для определения того, насколько хорошо работает ваша текущая модель. В конце концов, если ваша модель хороша, она должна превосходить базовую. Нулевая модель не встроена в Scikit-Learn, но нам легко реализовать!
import numpy as np from sklearn.base import RegressorMixin class NullRegressor(RegressorMixin): def fit(self, X=None, y=None): # The prediction will always just be the mean of y self.y_bar_ = np.mean(y) def predict(self, X=None): # Give back the mean of y, in the same # length as the number of X observations return np.ones(X.shape[0]) * self.y_bar_
Достаточно просто! Теперь мы можем делать как обычно ...
model = NullRegressor() model.fit(X, y) model.predict(X)
Важная часть состоит в том, что наш новый NullRegressor
теперь совместим со всеми встроенными инструментами Scikit-Learn, такими как cross_val_score
и GridSearchCV
.
Пример 2: «Настройка» кластера с помощью поиска по сетке
Этот пример был получен из любопытства, когда коллега спросил меня, могу ли я «настроить» модель k -means, используя GridSearchCV
и Pipeline
. Первоначально я сказал нет, поскольку вам нужно будет использовать кластеризатор в качестве преобразователя для передачи в вашу контролируемую модель, что не позволяет Scikit-Learn. Но почему это нас останавливает? Мы только что узнали, как взломать Scikit-Learn, чтобы делать все, что мы хотим! По сути, я хочу создать следующий конвейер:
Pipeline([ ("sc", StandardScaler()), ("km", KMeansSomehow()), ("lr", LogisticRegression() ])
Где KMeansSomehow()
- кластер, используемый в качестве преобразователя Scikit-Learn. То есть он добавляет метки кластера, закодированные одним нажатием, в матрицу данных X
, чтобы затем передать их в нашу модель. Чтобы это работало, мы начнем с определения класса, который наследуется от TransformerMixin
. Затем мы дадим ему соответствующие методы .fit()
, .transform()
и .fit_transform()
.
Но для начала инициализация:
from sklearn.base import TransformerMixin from sklearn.cluster import KMeans class KMeansTransformer(TransformerMixin): def __init__(self, *args, **args): self.model = KMeans(*args, **args)
Цель self.model
- содержать базовую модель кластера. Но что такое *args
и **kwargs
, спросите вы? Это ярлык для ленивых программистов. По сути, они захватывают все остальные аргументы, которые вы передаете в __init__()
, и передают их прямо KMeans()
. По сути, я говорю: «Все, что я передаю в KMeansTransformer
, будет также передано в KMeans
, и мне слишком лень выяснять, какими могут быть эти аргументы в будущем».
Далее нам нужно указать соответствующие методы подгонки:
from self.preprocessing import OneHotEncoder class KMeansTransformer(TransformerMixin): def __init__(self, *args, **args): self.model = KMeans(*args, **args) def fit(self, X): self.X = X self.model.fit(X) def transform(self, X): # Need to reshape into a column vector in order to use # the onehot encoder. cl = self.model.predict(X).reshape(-1, 1) self.oh = OneHotEncoder( categories="auto", sparse=False, drop="first" ) cl_matrix = self.oh.fit_transform(cl) return np.hstack([self.X, cl_matrix]) def fit_transform(self, X, y=None): self.fit(X) return self.transform(X)
Так и должно быть! Теперь мы можем использовать этот KmeansTransformer
как встроенный преобразователь Scikit-Learn. В довершение всего, попробуйте этот пример:
from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.datasets import make_blobs X, y = make_blobs( n_samples=100, n_features=2, centers=3 ) pipe = Pipeline([ ("sc", StandardScaler()), ("km", KMeansTransformer()), ("lr", LogisticRegression(penalty="none", solver="lbfgs")) ]) pipe.fit(X, y) pipe.score(X, y) # ==> 1.0
В менее искусственных примерах вы также можете использовать GridSearchCV
, чтобы найти оптимальное количество кластеров для передачи в вашу логистическую регрессию (или любую другую модель, которая у вас есть).
Заключение
Теперь вы должны понять, как создавать собственные модели машинного обучения в рамках Scikit-Learn, которая в настоящее время является самой популярной и (во многих случаях) мощной библиотекой машинного обучения.
Этот пост в блоге педантичен? Конечно. Вам это когда-нибудь понадобится? Нет, возможно, вам это никогда не понадобится, но дело не в этом. Этот метод используется для создания чего-либо. Требуется строитель, чтобы понять необходимость создания более креативного решения. Плюс, как однажды сказал один мудрый человек:
Вы никогда не меньше хотите знать больше.
Надеюсь, вы оцените добавление этого инструмента в свой набор инструментов. Овладейте им, и вы можете просто достичь настоящего подъема в области машинного обучения.