通过前面两篇笔记的学习已经基本了解了PyTorch里面的基本处理对象、运算操作、自动求导、以及数据处理方法、模型的保存和加载等基础知识。下来就是实战部分了。
一. 线性回归
1. 一维线性回归
给定数据集
,线性回归希望能够优化出一个好的函数 f(x),使得
能够与
尽可能接近。
# 一维线性回归
运行结果:
2. 多维线性回归
更一般的情况是多维线性回归,比如像前文描述的,我们有d个属性,试图学得最优的函数f(x)。
对于线性回归求解最优参数,有两种方法,一种是利用正规方程组,另一种是利用梯度下降算法,具体推导可以在我以前的博客中学习:
blog.csdn.net
1中的线性回归模型的拟合能力很明显不够强,我们需要提高模型的拟合能力,使用更复杂的模型,这里我们尝试用高次多项式而不是简单的一次线性多项式。
不妨设置参数方程:
那么就相当于原来一维的训练数据x_train变成了三维,原来的每一个数据x变成了
。
import torch
from torch import nn, optim
from torch.autograd import Variable
# 构造特征
def make_features(x):
x = x.unsqueeze(1)
return torch.cat([x**i for i in range(1, 4)], 1)
# 定义好真实的函数
W_target = torch.FloatTensor([0.5, 3, 2.4]).unsqueeze(1) # 将原来的tensor大小由3变成(3, 1)
b_target = torch.FloatTensor([0.9])
print(W_target)
def f(x):
return x.mm(W_target) + b_target
# 得到训练集合
def get_batch(batch_size=1):
random = torch.randn(batch_size)
x = make_features(random)
y = f(x)
if torch.cuda.is_available():
return Variable(x).cuda(), Variable(y).cuda()
else:
return Variable(x), Variable(y)
# 构建模型
class poly_model(nn.Module):
def __init__(self):
super(poly_model, self).__init__()
self.poly = nn.Linear(3, 1)
def forward(self, x):
out = self.poly(x)
return out
if torch.cuda.is_available():
model = poly_model().cuda()
else:
model = poly_model()
# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=1e-3)
# 开始训练
epoch = 0
while True:
# get data
batch_x, batch_y = get_batch()
# forward
output = model(batch_x)
loss = criterion(output, batch_y)
print(loss)
print_loss = loss.data.float()
# Reset gradients
optimizer.zero_grad()
# backward
loss.backward()
# update parameters
optimizer.step()
epoch += 1
if print_loss < 1e-3:
print("Loss: {} after {} batches".format(print_loss, epoch))
print("Actual function: y = 0.90 + 0.50x + 3.00*x^2 + 2.40*x^3")
for name,param in model.named_parameters():
print(name, param)
break
运行结果:
二. 逻辑斯蒂(Logistic)回归
Logistic回归不仅可以解决二分类问题,也可以解决多分类问题,但是二分类问题最为常见同时也具有良好的解释性。对于二分类问题,Logistic回归的目标是希望找到一个区分度足够好的决策边界,能够将两类很好的分开。
关于Logistic的具体推导详情请见:
blog.csdn.net
import torch
import matplotlib.pyplot as plt
from torch import nn, optim
from torch.autograd import Variable
import numpy as np
def get_dataset():
with open('data.txt', 'r') as f:
data_list = f.readlines()
data_list = [i.split('n')[0] for i in data_list]
data_list = [i.split(',') for i in data_list]
x_train = [[float(i[0]), float(i[1])] for i in data_list]
y_train = [float(i[2]) for i in data_list]
return x_train, y_train
def plot_data(x, y):
pos = np.where(y == 1.0)
neg = np.where(y == 0.0)
# 分别用红色和蓝色对两种类的数据点做出标记
plt.plot(x[pos, 0], x[pos, 1], 'ro', label='x_0')
plt.plot(x[neg, 0], x[neg, 1], 'bo', label='x_1')
class LogisticRegression(nn.Module):
def __init__(self):
super(LogisticRegression, self).__init__()
self.lr = nn.Linear(2, 1)
self.sm = nn.Sigmoid()
def forward(self, x):
out = self.lr(x)
#print(x)
out = self.sm(out)
return out
if __name__ == "__main__":
# 从'data.txt’文件夹中获取训练数据和标签
x_train, y_train = get_dataset()
# 将其转换为numpy.array类型,这里一定是np.float32,否则默认是np.float64,后面就会报错
x_train = np.array(x_train, dtype=np.float32)
y_train = np.array(y_train, dtype=np.float32)
# 可视化原始数据
plot_data(x_train, y_train)
# 将array的数据转换为Tensor类型
x_train = torch.from_numpy(x_train)
y_train = torch.from_numpy(y_train).unsqueeze(1)
#print(x_train)
if torch.cuda.is_available():
logistic_model = LogisticRegression().cuda()
else:
logistic_model = LogisticRegression()
# 定义损失函数和优化器
criterion = nn.BCELoss() # nn.BCELoss是二分类的损失函数
optimizer = optim.SGD(logistic_model.parameters(), lr=1e-3, momentum=0.9)
# 训练模型
for epoch in range(50000):
# 转换为Variable
if torch.cuda.is_available():
x_train = Variable(x_train).cuda()
y_train = Variable(y_train).cuda()
else:
x_train = Variable(x_train)
y_train = Variable(y_train)
# forward
out = logistic_model(x_train)
loss = criterion(out, y_train)
# 计算准确率
mask = out.ge(0.5).float()
correct = (mask == y_train).sum().float()
acc = correct/x_train.size(0)
# backward
optimizer.zero_grad()
loss.backward()
optimizer.step()
#print(loss.data)
if (epoch+1) % 1000 == 0:
print('*'*10)
print("eopch {}, loss is {:.4f}, acc is {:.4f}".format(epoch+1, loss, acc))
# 将训练得到的参数可视化
w0, w1 = logistic_model.lr.weight.data.numpy()[0]
print(w0, w1)
b = logistic_model.lr.bias.data.numpy()[0]
print(b)
plot_x = np.arange(30, 100, 0.1)
plot_y = (-w0 * plot_x - b) / w1
plt.plot(plot_x, plot_y)
plt.show()
运行,可以看到,找到了一条线将两类样本分开:
以上内容皆为廖星宇编著的《深度学习入门之PyTorch》这本书上的内容,代码部分略有改动。