[Pytorch --- 11] 简单线性回归的实现
程序员文章站
2022-05-26 20:46:05
...
一. 定义
1. 单变量线性回归
定义一个简单的线性回归函数,y = 2x+0,我们希望模型能够预测出正确的输出。
模型仅采用一个Linear层,损失函数采用均方差MSE。
import torch
import numpy as np
import torch.nn as nn
from torch.nn.functional import mse_loss
from torch.nn.functional import sigmoid
criterion = nn.MSELoss(reduction="mean")
# criterion = nn.MSELoss(reduction="sum")
# criterion = nn.BCELoss(reduction='mean')
# criterion = nn.BCELoss(reduction='sum')
class NN(nn.Module):
def __init__(self):
super().__init__()
self.linear = nn.Linear(1, 1)
def forward(self, x, y):
x = self.linear(x)
print("self.linear.weight = ", self.linear.weight.item())
print("self.linear.bias = ", self.linear.bias.item())
loss = criterion(x, y)
return loss
def train(x_data, y_data):
epochs = 1000
learning_rate = 0.01
model = NN()
model.train()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
for epoch in range(epochs):
global_loss = 0
global_step = 0
for x, y in zip(x_data, y_data):
x = torch.FloatTensor(x)
y = torch.FloatTensor(y)
loss = model(x, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
global_loss += loss.item()
global_step += 1
if epoch % 10 == 0:
avg_loss = global_loss / global_step
print("Epoch %d: loss: %.3f" % (epoch, avg_loss))
x_data = np.array([[1.0], [2.0], [3.0], [4.0], [5.0]], dtype=np.float32)
y_data = np.array([[2.0], [4.0], [6.0], [8.0], [10.0]], dtype=np.float32)
train(x_data, y_data)
我们输出模型的最终的参数,可发现与我们最终的参数 y = 2x+0非常接近:
self.linear.weight = 2.000000476837158
self.linear.bias = -1.4234631180443102e-06
同时,训练过程中模型最终的loss也会无限接近于0。
如果稍微改变以下原始的输入,我们发现模型参数仍然非常接近于我们的结果。
x_data = np.array([[1.0], [2.0], [3.0], [4.0], [5.0]], dtype=np.float32)
y_data = np.array([[2.0], [4.0], [5.8], [8.1], [10.0]], dtype=np.float32)
最终的参数输出为:
self.linear.weight = 2.0142741203308105
self.linear.bias = -0.05234277620911598
2. 多变量线性回归
多元线性回归,我们采用波士顿房价预测数据集,测试了线性和非线性两种模型,最终结果差距不大。
import torch
import json
import random
import numpy as np
import torch.nn as nn
import sklearn.datasets as datasets
criterion = nn.MSELoss()
# criterion = nn.MSELoss(reduction="mean")
# criterion = nn.MSELoss(reduction="sum")
# criterion = nn.BCELoss(reduction='mean')
# criterion = nn.BCELoss(reduction='sum')
# class NN(nn.Module):
# def __init__(self):
# super().__init__()
# self.linear1 = nn.Linear(13, 14)
# self.relu = nn.ReLU()
# self.linear2 = nn.Linear(14, 1)
# self.sigmoid = nn.Sigmoid()
#
# def forward(self, x, y=None):
# x = self.linear1(x)
# x = self.relu(x)
# x = self.linear2(x)
# x = self.sigmoid(x)
# if y is not None:
# loss = criterion(x, y)
# return loss
# else:
# return x
class NN(nn.Module):
def __init__(self):
super().__init__()
self.linear = nn.Linear(13, 1)
def forward(self, x, y=None):
x = self.linear(x)
if y is not None:
loss = criterion(x, y)
return loss
else:
return x
# 设置随机种子
seed = 5233
torch.manual_seed(seed)
# torch.cuda.manual_seed_all(seed)
np.random.seed(seed)
random.seed(seed)
epochs = 500
learning_rate = 0.01
model = NN()
model.train()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# optimizer = torch.optim.RMSprop(model.parameters(), lr=learning_rate)
def train(x_data, y_data):
for epoch in range(epochs):
global_loss = 0
global_step = 0
for x, y in zip(x_data, y_data):
x = torch.FloatTensor(x)
y = torch.FloatTensor([y])
loss = model(x, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
global_loss += loss.item()
global_step += 1
if epoch % 10 == 0:
avg_loss = global_loss / global_step
print("Epoch %d: loss: %.3f" % (epoch, avg_loss))
def test(x_data, y_data):
model.eval()
res = []
for x, y in zip(x_data, y_data):
x = torch.FloatTensor(x)
with torch.no_grad():
output = model(x)
res.append({"ground_truth": y[0], "prediction": output.item()})
with open("result.json", "w", encoding="utf-8") as writer:
json.dump(res, writer, ensure_ascii=False, indent=4)
# 载入数据集
Boston = datasets.load_boston()
# 数据预处理: 特征缩放,均值归一化
from sklearn.preprocessing import MinMaxScaler
ss_input = MinMaxScaler()
ss_output = MinMaxScaler()
data_set_input = ss_input.fit_transform(Boston['data'])
data_set_output = ss_output.fit_transform(Boston['target'][:, np.newaxis])
# train(x_data, y_data)
# 划分数据集
train_set_input = data_set_input[ 0:350, :]
train_set_output = data_set_output[0:350, :]
test_set_input = data_set_input[ 351:506, :]
test_set_output = data_set_output[351:506, :]
train(train_set_input, train_set_output)
test(test_set_input, test_set_output)
其余情况下,我们也可以导入糖尿病数据集,完成简单的分类任务
import torch
import json
import random
import numpy as np
import torch.nn as nn
import sklearn.datasets as datasets
criterion = nn.MSELoss()
# criterion = nn.MSELoss(reduction="mean")
# criterion = nn.MSELoss(reduction="sum")
# criterion = nn.BCELoss(reduction='mean')
# criterion = nn.BCELoss(reduction='sum')
class NN(nn.Module):
def __init__(self):
super().__init__()
self.linear1 = nn.Linear(10, 12)
self.relu = nn.ReLU()
self.linear2 = nn.Linear(12, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x, y=None):
x = self.linear1(x)
x = self.relu(x)
x = self.linear2(x)
x = self.sigmoid(x)
if y is not None:
loss = criterion(x, y)
return loss
else:
return x
# class NN(nn.Module):
# def __init__(self):
# super().__init__()
# self.linear = nn.Linear(10, 1)
#
# def forward(self, x, y=None):
# x = self.linear(x)
# if y is not None:
# loss = criterion(x, y)
# return loss
# else:
# return x
# 设置随机种子
seed = 5233
torch.manual_seed(seed)
# torch.cuda.manual_seed_all(seed)
np.random.seed(seed)
random.seed(seed)
epochs = 500
learning_rate = 0.01
model = NN()
model.train()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# optimizer = torch.optim.RMSprop(model.parameters(), lr=learning_rate)
def train(x_data, y_data):
for epoch in range(epochs):
global_loss = 0
global_step = 0
for x, y in zip(x_data, y_data):
x = torch.FloatTensor(x)
y = torch.FloatTensor(y)
loss = model(x, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
global_loss += loss.item()
global_step += 1
if epoch % 10 == 0:
avg_loss = global_loss / global_step
print("Epoch %d: loss: %.3f" % (epoch, avg_loss))
def test(x_data, y_data):
model.eval()
res = []
for x, y in zip(x_data, y_data):
x = torch.FloatTensor(x)
with torch.no_grad():
output = model(x)
res.append({"ground_truth": y[0], "prediction": output.item()})
with open("result.json", "w", encoding="utf-8") as writer:
json.dump(res, writer, ensure_ascii=False, indent=4)
# 载入数据集
diabetes = datasets.load_diabetes()
# 数据预处理: 特征缩放,均值归一化
from sklearn.preprocessing import MinMaxScaler
ss_input = MinMaxScaler()
ss_output = MinMaxScaler()
data_set_input = ss_input.fit_transform(diabetes['data'])
data_set_output = ss_output.fit_transform(diabetes['target'][:, np.newaxis])
# train(x_data, y_data)
# 划分数据集
train_set_input = data_set_input[ :380, :]
train_set_output = data_set_output[:380, :]
test_set_input = data_set_input[ 380:, :]
test_set_output = data_set_output[380:, :]
train(train_set_input, train_set_output)
test(test_set_input, test_set_output)
上一篇: PuTTY用户手册(十)
下一篇: pytorch简单的线性回归