В прошлой статье мы сравнивали массив Numpy с тензорами PyTorch. Теперь давайте построим простую модель линейной регрессии, используя как Numpy, так и PyTorch.

#Create dummy dataset
X = np.array([1,2,4,6,8,10,12,13,14,16,16,18,20,22,24])
Y = np.array([39,42,43,46,47,56,60,59,64,66,68,72,71,75,80])

Как мы видим, между X и Y существует линейная зависимость (подробнее о корреляции мы поговорим в другом посте). Здесь мы будем использовать линейную регрессию для построения модели прогнозирования.

Основы линейной регрессии:

Y = a * X + b - уравнение модели линейной / линейной регрессии.

Цель здесь - найти значения a и b.

Для этого есть несколько методов:

1. Матричные вычисления: поместите все данные в матрицы для выполнения оптимизации. Используется для небольших наборов данных из-за ограничений памяти.

2. Градиентный спуск: постарайтесь минимизировать ошибку / разницу между фактическими и прогнозируемыми значениями, используя производные.

3. Регуляризация: сводя к минимуму ошибки, также старайтесь уменьшить влияние ненужных функций.

4. Простая линейная регрессия: если есть одна входная переменная и одна выходная переменная, используйте ковариацию и дисперсию, чтобы найти a и b.

Более подробное объяснение вышеперечисленных методов здесь не входит. Мы реализуем метод 2, то есть градиентный спуск, здесь более конкретный - пакетный градиентный спуск.

Веса (a, b) обновляются в конце полной партии / всех строк следующим образом:

новый a = старый a- (скорость обучения * градиент_a)

новый b = старый b- (скорость_учения * градиент_b)

Линейная регрессия с использованием Numpy:

np.random.seed(2)
epochs=15
learning_rate = 0.001
w = np.random.randn()
b = np.random.randn()
y_pred = np.empty(len(Y))
for i in range(epochs):
   print("-----------epoch:{}--------".format(i))
   #prediction
   y_pred = w*X +b
   
   #Error/loss calculation is Mean Squared Error
   error = np.mean((Y - y_pred)**2)
   print('Total Error:{}'.format(error))
   
   #Gradient calculation
   gradient_a = np.mean(-2*X*(Y-y_pred))
   gradient_b = np.mean(-2*(Y-y_pred))
   
   #Update weights
   w -= learning_rate*gradient_a
   b -= learning_rate*gradient_b

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

Давайте не будем играть с этим и перейдем к эквиваленту PyTorch.

Линейная регрессия с использованием PyTorch:

#initialise data/features and target
X_tensor = torch.from_numpy(X)
Y_tensor = torch.from_numpy(Y)
#Initialise weights
'''Here unlike numpy we have to mention that these variables are trainable(need to calculate derivatives).This can be done using requires_grad'''

w_tensor = torch.randn(1,requires_grad=True,dtype=torch.float)
b_tensor = torch.randn(1,requires_grad=True,dtype=torch.float)
torch.random.seed = 2
epochs=15
learning_rate = 0.001

Сначала мы попытаемся построить модель, не прибегая к помощи встроенных методов PyTorch.

#Model without PyTorch in-built methods
for i in range(epochs):
  print("-----------epoch:{}--------".format(i))
  #prediction
  y_pred = w_tensor*X_tensor +b_tensor
  
  #Error/loss calculation is Mean Squared Error
  error = ((Y_tensor - y_pred)**2).mean()
  print('Total Error:{}'.format(error))
  '''Now no need to calculate gradients,PyTorch will do it if we     tell which function/variable needs gradient  calculation  using      backward()'''
  error.backward()
  '''Actual values of gradients can be seen using grad attribute'''
#print(w_tensor.grad,b_tensor.grad)
  '''We can not directly use gradients in normal calculation,so use  no_grad() method to get variables out of scope of computation graph   '''
  with torch.no_grad():
      w_tensor-= learning_rate*w_tensor.grad 
      b_tensor-= learning_rate*b_tensor.grad
  #After each step,Reinitialize gradients because PyTorch holds on   to gradients and we need to ask it to release it.
  w_tensor.grad.zero_()
  b_tensor.grad.zero_()

Теперь давайте воспользуемся встроенными методами PyTorch.

#Model with PyTorch in-built methods
optimizer = torch.optim.SGD([w_tensor, b_tensor], lr=learning_rate)
loss = torch.nn.MSELoss(reduction='mean')
for i in range(epochs):
   print("-----------epoch:{}--------".format(i))
   #prediction
   y_pred = w_tensor*X_tensor +b_tensor 
   
   #Error/loss calculation is Mean Squared Error
   error = loss(Y_tensor, y_pred)
   print('Total Error:{}'.format(error))
   error.backward()
 #Update weights using Optimizer
  optimizer.step()
 #After each step,Reinitialize gradients because PyTorch holds on to  gradients,reinitialize gradients using Optimizer
 optimizer.zero_grad()

До сих пор мы изучали расчет потерь и оптимизаторы. Давайте также удалим этот ручной шаг.

#Create Network by extending parent nn.Module.
'''We have to implement __init__ and forward methods '''
class Network(torch.nn.Module):
    def __init__(self):
       super().__init__()
     #Intialise parameters whcih should be trained. Note that parameters need to be wrapped under nn.Parameter
      self.w_tensor = torch.nn.Parameter(torch.randn(1,requires_grad=True,dtype=torch.float))
      self.b_tensor = torch.nn.Parameter(torch.randn(1,requires_grad=True,dtype=torch.float))
def forward(self,x):
#Output prediction calculation
return  w_tensor*x +b_tensor

Давайте использовать эту сеть для обучения:

#Model with PyTorch in-built methods
model = Network()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
loss = torch.nn.MSELoss(reduction='mean')
for i in range(epochs):
     print("-----------epoch:{}--------".format(i))
    #This will not do actual training but will set model in training       mode.
    model.train()
   #prediction
    y_pred = model(X_tensor)
   #Error/loss calculation is Mean Squared Error
    error = loss(Y_tensor, y_pred)
    print('Total Error:{}'.format(error))
    '''Now no need to calculate gradients,PyTorch will do it if we  tell which function/variable needs gradient calculation using backward()'''
    error.backward()
   
   #Update weights using Optimizer
   optimizer.step()
   #Reinitialize gradients using Optimizer
   optimizer.zero_grad()

Резюме:

Подводя итог, следующие шаги для создания модели PyTorch:

1.Создайте класс модели, в котором метод __init __ () содержит обучаемый параметр, а прямой метод содержит расчет прогноза.

2. Инициализировать оптимизатор и функцию потерь.

3. Цикл обучения:

model.train () - установить модель в обучающий режим.

pred = model (X) - Прогноз

loss = LossFunction (pred, actual) - Расчет убытка

loss.backward () - Расчет градиента

optimizer.step () - Обновляет веса / параметры

optimizer.zero_grad () - Сбрасывает градиенты

Полный блокнот доступен на git-repo.

Теперь мы знаем, как создать простую модель в PyTorch. В следующей статье мы создадим более сложную нейронную сеть для анализа настроений в PyTorch.

Если вам понравилась статья или у вас есть предложения / комментарии, поделитесь ими ниже!

LinkedIn