Линейная регрессия в PyTorch
еще одно простое понимание градиентного спуска
Помимо логистической регрессии, наш единственный нейрон может выполнять еще один трюк: линейную регрессию. Наилучшее соответствие линии набору точек, определяемому по формуле:
получается из условия, что сумма квадратов отклонений (остатков) этих точек от линии должна быть минимальной, что дает нам простую систему уравнений и, наконец, приведенное выше решение.
Сумма минимальна, когда градиенты равны нулю:
Полный список математических доказательств приведен по адресу: линейно-регрессионно-доказательство.
Возьмем простой набор точек:
data = np.array([ [1, 2], [1,10], [2, 3], [3, 6], [5, 8], [7, 14] ])
и просто примените формулу выше в pytorch:
points = torch.from_numpy(data) X = points[:,0:1].float() Y = points[:,1:2].float() m = (torch.mean(X*Y)-torch.mean(X)*torch.mean(Y))/(torch.mean(X*X)-torch.mean(X)*torch.mean(X)).float() b = torch.mean(Y) - m* torch.mean(X).float() print("m(slope)=",m.data.numpy(),"n(y-intercept)=",n.data.numpy()[0][0])
Результат будет:
m(slope)= 1.312139 n(y-intercept)= 3.0030644
Затем пришло время запустить нейрон и найти решение методом градиентного спуска.
Набор данных для обучения нейронов имеет вид: x,y,(mx+n=y), где:
- x,y ввод данных
- mx+n=y — это цель (мы должны найти m и n так, чтобы mx+n было как можно ближе к y), которая показывает:
- формула потери (ошибки-стоимости): сумма квадратов (y-(mx+n))
#making result predictable torch.manual_seed(1) m = Variable(torch.randn(1, 1,), requires_grad=True) n = Variable(torch.randn(1, 1,), requires_grad=True) X = points[:,0:1].float() Y = points[:,1:2].float() alpha = 0.01 epochs = 150 for i in range(epochs): prediction = m*X + n loss = torch.sum((prediction - Y)**2) #calculate dSSE/dm, dSSE/dn loss.backward() with torch.no_grad(): m -= alpha * m.grad n -= alpha * n.grad # Manually zero the gradients after updating weights m.grad.zero_() n.grad.zero_() print("loss=",loss.data.numpy()) print("m(slope)=",m[0][0].data.numpy(),"n(y-intercept)=",n[0][0].data.numpy())
Мы получим:
loss= 51.190907 m(slope)= 1.3139911 n(y-intercept)= 3.0030644
Наконец, мы можем определить «впечатляющую» нейронную сеть (очевидно) только из одного нейрона, используя предопределенные методы pytorch:
class LinearRegressionModel(torch.nn.Module): def __init__(self, input_dim, output_dim): super(LinearRegressionModel, self).__init__() self.linear = torch.nn.Linear(input_dim, output_dim) def forward(self, x): out = self.linear(x) return out model = LinearRegressionModel(input_dim=1, output_dim=1) criterion = torch.nn.MSELoss() optimizer = torch.optim.SGD(model.parameters(),lr=0.01) inputs = Variable(torch.from_numpy(x)).float() labels = Variable(torch.from_numpy(y)).float() for epoch in range(450): #1. clear gradients w.r.t. parameters optimizer.zero_grad() #2. forward to get output outputs = model(inputs) #3 calculate loss (scalar value) loss = criterion(outputs, labels) #4 calculate gradients w.r.t. parameters loss.backward() #5 updating parameters optimizer.step() print("loss:",loss.data.numpy()) m = model.linear.weight.data.numpy()[0][0] b = model.linear.bias.data.numpy()[0] print("m(slope)=",m,"n(y-intercept)=",b)
И получить примерно такой же результат:
loss: 8.531794 m(slope)= 1.3125678 n(y-intercept)= 3.0095923
Вышеприведенный код в формате Jupyter Notebook доступен на странице линейная регрессия.