Я расскажу, как обучать модель линейной регрессии в TensorFlow.NET от SciSharp.

Что такое линейная регрессия?

Линейная регрессия — это линейный подход к моделированию связи между скалярным откликом (или зависимой переменной) и одной или несколькими независимыми переменными (или независимыми переменными).

Рассмотрим случай одной интересующей переменной y и одной переменной-предиктора x. Переменные-предикторы называются по-разному: ковариаты, входные данные, признаки; прогнозируемую переменную часто называют откликом, выходом, результатом.

У нас есть некоторые данные $D={x{\tiny i},y{\tiny i}}$, и мы предполагаем простую линейную модель этого набора данных с гауссовским шумом:

// Prepare training Data
var train_X = np.array(3.3f, 4.4f, 5.5f, 6.71f, 6.93f, 4.168f, 9.779f, 6.182f, 7.59f, 2.167f, 7.042f, 10.791f, 5.313f, 7.997f, 5.654f, 9.27f, 3.1f);
var train_Y = np.array(1.7f, 2.76f, 2.09f, 3.19f, 1.694f, 1.573f, 3.366f, 2.596f, 2.53f, 1.221f, 2.827f, 3.465f, 1.65f, 2.904f, 2.42f, 2.94f, 1.3f);
var n_samples = train_X.shape[0];

На основе заданных точек данных мы пытаемся построить линию, которая лучше всего моделирует точки. Красная линия может быть смоделирована на основе линейного уравнения: $y = wx + b$. Цель алгоритма линейной регрессии — найти наилучшие значения для $w$ и $b$. Прежде чем перейти к алгоритму, давайте рассмотрим две важные концепции, которые вы должны знать, чтобы лучше понять линейную регрессию.

Функция стоимости

Функция стоимости помогает нам определить наилучшие возможные значения для $w$ и $b$, которые обеспечат наилучшую линию соответствия для точек данных. Поскольку нам нужны наилучшие значения для $w$ и $b$, мы преобразуем эту задачу поиска в задачу минимизации, где мы хотели бы минимизировать ошибку между прогнозируемым значением и фактическим значением.

Мы выбираем указанную выше функцию для минимизации. Разница между предсказанными значениями и наземной истиной измеряет разницу ошибок. Мы возводим в квадрат разницу ошибок и суммируем по всем точкам данных и делим это значение на общее количество точек данных. Это обеспечивает среднеквадратичную ошибку по всем точкам данных. Поэтому эта функция стоимости также известна как функция среднеквадратичной ошибки (MSE). Теперь, используя эту функцию MSE, мы собираемся изменить значения $w$ и $b$ так, чтобы значение MSE достигло минимума.

// tf Graph Input
var X = tf.placeholder(tf.float32);
var Y = tf.placeholder(tf.float32);
​
// Set model weights 
var W = tf.Variable(rng.randn<float>(), name: "weight");
var b = tf.Variable(rng.randn<float>(), name: "bias");
​
// Construct a linear model
var pred = tf.add(tf.multiply(X, W), b);
​
// Mean squared error
var cost = tf.reduce_sum(tf.pow(pred - Y, 2.0f)) / (2.0f * n_samples);

Градиентный спуск

Еще одна важная концепция, которую необходимо понять, — это градиентный спуск. Градиентный спуск — это метод обновления $w$ и $b$ для минимизации функции стоимости. Идея состоит в том, что мы начинаем с некоторых случайных значений для $w$ и $b$, а затем итеративно меняем эти значения, чтобы снизить стоимость. Градиентный спуск помогает нам в том, как обновить значения или в каком направлении двигаться дальше. Градиентный спуск также известен как самый крутой спуск.

Чтобы провести аналогию, представьте себе яму в форме буквы U, и вы стоите в самой верхней точке ямы, и ваша цель — добраться до дна ямы. Есть одна загвоздка, вы можете сделать только дискретное количество шагов, чтобы достичь дна. Если вы решите делать один шаг за раз, вы в конечном итоге достигнете дна ямы, но это займет больше времени. Если вы решите делать более длинные шаги каждый раз, вы достигнете раньше, но есть шанс, что вы можете промахнуться через дно ямы, а не точно на дно. В алгоритме градиентного спуска количество шагов, которые вы делаете, является скоростью обучения. Это определяет, насколько быстро алгоритм сходится к минимуму.

// Gradient descent
// Note, minimize() knows to modify W and b because Variable objects are trainable=True by default
var optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost);

Когда мы визуализируем график в TensorBoard:

Полный пример — здесь.