Краткое введение в линейную регрессию в PyTorch

Для всех тех, кто занимается машинным обучением и глубоким обучением, линейная регрессия - лучший способ начать свое путешествие. Если вы новичок в машинном обучении и имеете некоторый опыт работы с PyTorch, пристегнитесь, потому что вы только что оказались в нужном месте. Если нет, не волнуйтесь, ознакомьтесь с моей предыдущей статьей, чтобы познакомиться с некоторыми основами PyTorch, и тогда все готово.

Так что же такое линейная регрессия?

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

Например, давайте рассмотрим простое линейное уравнение y = w * x + b. Здесь y - это выход, а x - входная переменная. «W» и «b» образуют наклон и точку пересечения y уравнения соответственно. Поэтому мы будем называть «w» и «b» параметрами уравнения, потому что, узнав эти значения, вы можете легко предсказать результат для данного значения x.

А теперь немного изменим сценарий. Предположим, вам даны значения x и y (мы назовем их обучающим набором), и вас просят определить новое значение y, соответствующее новой переменной x. Очевидно, что простая линейная алгебра поможет и легко даст вам правильные параметры. Как только вы включите их в уравнение, вы сможете мгновенно узнать новое значение y, соответствующее x.

Так в чем же дело, это вещи, которые мы изучали в нашей старшей школе. Но вот что следует учитывать:

  1. В наборах данных реального мира может быть шум, т.е. в вашем обучающем наборе могут быть некоторые значения x и y, которые не будут идти рука об руку с некоторыми другими значениями x и y в том же наборе, что, очевидно, положит конец вашему попытаться найти правильные значения параметров, используя традиционный подход.
  2. Кроме того, в наборах данных реального мира может быть несколько переменных, определяющих выходную переменную, поэтому выяснение параметров становится сложной задачей, когда задействованы несколько входных переменных.

Здесь на помощь приходит машинное обучение. Я постараюсь дать вам обзор того, что происходит за кулисами печально известного метода линейной регрессии. Изначально нашу Машину знал не больше, чем средний ребенок. Потребуется несколько случайных значений «w» и «b», которые с этого момента мы будем называть весом и смещением, и подставить их в уравнение y = w * x + b. Теперь он возьмет некоторые значения x в обучающем наборе и найдет соответствующие значения y, используя параметры, которые он принял ранее. Затем он сравнит предсказанные значения y say yhat с фактическими значениями y, вычислив нечто, известное как функция потерь (функция стоимости).

Функция потерь по сути обозначает ошибку в нашем прогнозе. Чем больше значение функции потерь, тем больше ошибка. Здесь мы будем использовать среднеквадратическую ошибку (MSE) в качестве нашей функции потерь, которая определяется формулой:

После расчета потерь мы выполняем метод оптимизации, такой как градиентный спуск для функции потерь. Застряв на градиентном спуске, не волнуйтесь, ради времени все, что вам нужно знать, это то, что градиентный спуск - это просто метод, выполняемый с функцией потерь, чтобы найти значения «w» и «b», которые минимизируют функцию потерь. Это предполагает использование скорости обучения, которую можно настроить для достижения лучших результатов. Чем меньше потеря, тем точнее наш прогноз.

То, что мы видели до сих пор, по сути, составляет лишь один шаг в тренировочном процессе. Этот цикл повторяется несколько раз, пока мы не придем к оптимальному значению «w» и «b», при котором функция потерь минимальна.

Хорошо, вы изучили основы линейной регрессии, теперь пора писать код.

Линейная регрессия, способ PyTorch

Для простоты мы рассмотрим одномерную линейную регрессию с двумя параметрами. Сначала мы импортируем torch для этой задачи.

import torch

Данные, которые мы будем рассматривать, будут действительно простыми, тензор факела от -3 до 3 с размером шага 0,1. Итак, давайте создадим наши данные.

# Create f(X) with a slope of 1 and a bias of -1
X = torch.arange(-3, 3, 0.1).view(-1, 1)
f = 1 * X - 1
# Add noise
Y = f + 0.1 * torch.randn(X.size())

Как вы могли заметить, уравнение, которое наша машина хочет изучить в этом случае, - это y = x -1, где w = 1 и b = -1. Кроме того, мы добавляем немного шума к нашим данным, чтобы они были похожи на данные реального мира.

График нашего обучающего набора и функции, которую наша машина хотела бы изучить, будет выглядеть так:

Теперь давайте создадим нашу модель и нашу функцию потерь (функцию стоимости).

# Define the forward function
def forward(x):
    return w * x + b
# Define the MSE Loss function
def criterion(yhat,y):
    return torch.mean((yhat-y)**2)

Поверхность ошибки для этого будет выглядеть, как на рисунке, приведенном ниже.

Теперь давайте создадим параметры модели w, b, установив для аргумента requires_grad значение True, потому что мы должны изучить его, используя данные.

# Define the parameters w, b for y = wx + b
w = torch.tensor(-15.0, requires_grad = True)
b = torch.tensor(-10.0, requires_grad = True)

Установите скорость обучения 0,1 и создайте пустой список LOSS для сохранения потерь для каждой итерации. Функцию ПОТЕРЯ можно использовать для построения графиков и анализа в будущем.

# Define learning rate and create an empty list for containing the loss for each iteration.
lr = 0.1
LOSS = []

Пришло время обучить нашу модель.

# The function for training the model
def train_model(iter):
    
    # Loop
    for epoch in range(iter):
        
        # make a prediction
        Yhat = forward(X)
        
        # calculate the loss 
        loss = criterion(Yhat, Y)
            
        # store the loss in the list LOSS
        LOSS.append(loss)
        
        # backward pass
        loss.backward()
        
        # update parameters slope and bias
        w.data = w.data - lr * w.grad.data
        b.data = b.data - lr * b.grad.data
        
        # zero the gradients before running the backward pass
        w.grad.data.zero_()
        b.grad.data.zero_()
train_model(15)

Здесь метод backward () вычисляет градиент потерь по всем обучаемым параметрам. Параметры обновляются в каждую эпоху путем вычитания из себя кратного градиента и скорости обучения. По сути, это составляет метод градиентного спуска. Не стесняйтесь настраивать скорость обучения, количество эпох и начальное значение параметров, чтобы получить лучшие результаты.

В этом случае наши результаты будут выглядеть так:

Теперь посмотрим, что предсказывает наша модель. Если мы дадим значение -3, на выходе будет y = -3-1 = -4.

x = torch.tensor(-3.)
print(forward(x))
#Output
tensor(-4.2857, grad_fn=<AddBackward0>)

Хорошо, мы достаточно близко. Попробуйте разные значения для гиперпараметров, и мы можем получить интересные результаты.

Заключение

Надеюсь, вы получили представление о том, как работает линейная регрессия. Удачи в изучении линейной регрессии и других алгоритмов машинного обучения. Оставайся голоден, оставайся в дураках.