Всем привет. Каждый из нас наверняка интересовался, как же устроены различные библиотеки машинного обучения? Так вот, сейчас вы читаете продолжение рубрики экспериментов в машинном обучении. Мы пошагово будем создавать свой интерфейс, свои функции и свои модели. Поехали!
Подпишись на группу Вконтакте и Телеграм-канал. Там еще больше полезного контента для программистов.
А на YouTube-канале ты найдешь обучающие видео по программированию. Подписывайся!
Класс модели
Для начала создадим класс модели. Реализуем некоторые методы, связанны со стандартным программным интерфейсом моделей машинного обучения, реализованных классов.
class Model: def __init__(self, layers=None): if not layers: layers = list() for layer in layers: if not isinstance(layer, Layer): raise TypeError('Argument is not a layer.') self.__layers = layers self.__fitted = False
В конструктор класса можно передать список слоёв, каждый из которых мы проверяем на принадлежность класса Layer
, который мы реализуем позже.
Также реализуем метод, который позволяет добавить доп.слой до обучения модели:
Model... def add(self, layer): if self.__fitted: raise AttributeError('The model has already been fitted.') if not isinstance(layer, Layer): raise TypeError('Argument is not a layer.') self.__layers.append(layer) return self
Мы возвращяем этот же класс, дабы дать возможность пользователям использовать цепной интерфейс.
Теперь реализуем метод обучения, основанный на Дельта-правиле (правиле обучения персептрона).
Model... def fit(self, X, Y, epochs=10, eta=.01): X = np.array(X); Y = np.array(Y) self.__input_shape = X[0].shape if X.shape[0] != Y.shape[0]: raise ValueError('Inputs have different shape.') for layer in self.__layers: layer._set_input_shape(self.__input_shape) for epoch in range(epochs): for i in range(len(X)): x = X[i]; y = Y[i]; for layer in self.__layers: x = layer._net_input(x) update = eta * (y - x) for layer in self.__layers: layer._update(update) self.__fitted = True return self
Всё это вы могли видеть в моей статье про Персептрон.
Реализуем метод предсказывания. В первой части мы ограничимся разделением на два класса:
Model... def predict(self, X): if not self.__fitted: raise TypeError('The model is not fitted.') return [1 if self._net_input(x) > 0 else 0 for x in X]
Также реализуем метод расчёта для определённого набора признаков:
Model... def _net_input(self, x): for layer in self.__layers: x = layer._net_input(x) return x.sum()
Ну и метод оценивания, возвращающий точность предсказания модели.
Model... def score(self, X, Y): return sum(np.array(self.predict(X)) == Y) / len(Y)
Слои — строительные блоки модели
В первой части мы реализуем класс, который даже не будет иметь функции активации :)
class Layer: def _net_input(self, x): if not self.__input_shape == x.shape: raise ValueError(f'X has bad shape {x.shape}, must be {self.__input_shape}') self.__input = x return x * self.__weights + self.__intercept def _set_input_shape(self, shape): self.__input_shape = shape self.__weights = np.random.random(self.__input_shape) self.__intercept = 0 def _update(self, update): delta_w = update * self.__input self.__weights += delta_w self.__intercept += delta_w
Использование всех реализованных методов мы могли лицезреть в классе Model
.
Оценивание
Я не надеялся на высокую точность, таким результат и оказался.
In[1]: import numpy as np from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split
In[4]: data = load_breast_cancer() X = data.data y = data.target
Теперь обучим модель на полученных данных:
In[5]: model = Model() model.add(Layer()) model.add(Layer()) model.add(Layer()) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1) model.fit(X_train, y_train, epochs=500, eta=0.1)
Точность модели:
In[6]: model.score(X_test, y_test) Out[6]: 0.49122807017543857
Заключение
В первой части я всего лишь хотел ввести вас в курс дела и получить какой-то фидбек. В будущем нас ждут функции активации, оптимизаторы, метрики и так далее. Всем хорошего обучения и достаточного количества памяти!
Ссылочка на документ с кодом тута.
Также рекомендую прочитать статью Функциональный API библиотеки Keras. А также подписывайтесь на группу ВКонтакте, Telegram и YouTube-канал. Там еще больше полезного и интересного для программистов.