В машинном обучении всегда есть этап, на котором вы делаете прогнозы, а затем сравниваете свои прогнозы с реальной истиной. Это этап обучения. Алгоритм сравнения ваших прогнозов с фактами - это функция потери. На следующем этапе вы оптимизируете потери, чтобы попытаться уменьшить их. Хотя это не единственная цель, она часто используется чаще всего.

Большинство студентов, изучающих машинное обучение, учат реализовывать алгоритмы пакетного градиентного спуска, мини-пакетного градиентного спуска и стохастического градиентного спуска с нуля. Изучив принципы работы, только исследователи могут продолжить реализацию с нуля.

Все три алгоритма имеют свои преимущества и, что более важно, свои ограничения. Я не буду здесь вдаваться в подробности, но вы можете прочитать блестящую статью Себастьяна Рудера здесь.

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

import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow.python.ops import confusion_matrix
from tensorflow.python.ops import math_ops

Мы импортируем обычных подозреваемых и двух необычных, чтобы мы могли вычислить среднеквадратичную ошибку. Набор данных, используемый в этом примере, взят из прогноза цен Boston House на сайте Kaggle.

train_df = pd.read_csv('./train.csv', index_col='ID')

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

y = train_df['medv'].values
y = y.reshape(-1, 1)

Для наших предикторов мы добавим столбец констант, поэтому нам не нужно делать никаких добавлений в нашей функции. Нам также нужно будет извлечь из него наш ndarray.

train_df['constant'] = 1
columns = ['constant', 'rm', 'zn', 'indus']
x = train_df[columns].values

Поскольку мы работаем с TensorFlow, нам нужно работать с тензорами. Что еще более важно, чтобы оптимизировать нашу функцию, нам нужно указать, что наши веса можно обучать. Делаем это при инициализации.

w = tf.Variable([[0],[0],[0],[0]], trainable=True, dtype=tf.float64) # this is needed to make the weights trainable
x = tf.convert_to_tensor(x)
y = tf.convert_to_tensor(y)

Далее реализуем наш прогноз.

y_pred = tf.matmul(x, w)

Затем мы объявляем нашу функцию потерь. TensorFlow предоставляет ряд стандартных функций потерь в tf.losses.

mse = tf.losses.mean_squared_error(y, y_pred) # the loss function

Затем мы создаем экземпляр нашего оптимизатора. Здесь мы используем оптимизатор адама. В tf.train доступен ряд оптимизаторов.

adam = tf.train.AdamOptimizer(learning_rate=0.3) # the optimizer

Нам нужен способ вызова функции оптимизации на каждом шаге градиентного спуска. Мы делаем это, назначая вызов минимизации дескриптору.

a = adam.minimize(mse, var_list=w) # this runs one step of gradient descent

Нам нужен способ узнать, что такое наша MSE. Хотя это существует в TensorFlow, он продолжал генерировать исключение, поэтому я просто реализовал его здесь.

l, p = confusion_matrix.remove_squeezable_dimensions(y, y_pred)
s = math_ops.square(p - l)
mean_t = math_ops.reduce_mean(s)
print(mean_t)

Вот и все, мы закончили. Конечно, это TensorFlow, нам нужна сессия.

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(200):
        sess.run(a) # run for the number of training steps
    w = sess.run(w)
    
    print(w) # this will output our current weights after training
    e_val = sess.run(mean_t) # compute our MSE
    print(e_val) # print our MSE.

Я надеюсь, что вы найдете это полезным для вашей работы или исследования. Удачного кодирования!