В прошлой статье мы сравнивали массив 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.
Если вам понравилась статья или у вас есть предложения / комментарии, поделитесь ими ниже!