使用的是 1.11 版本的 PyTorch
回归
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1) # -1到1之间取100个点,unsqueeze 增加一个维度,PyTorch不能训练单维度的数据
y = x.pow(2) + 0.2 * torch.rand(x.size()) # 生成目标
class Net(nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = nn.Linear(n_feature, n_hidden)
self.predict = nn.Linear(n_hidden, n_output)
def forward(self, x):
x = F.relu(self.hidden(x))
x = self.predict(x)
return x
net = Net(1, 10, 1)
optimizer = torch.optim.SGD(net.parameters(), lr=0.2) # 优化器
loss_func = nn.MSELoss() # 损失函数,均方差损失
plt.ion() # 开启动态显示
for t in range(100):
x, y = Variable(x), Variable(y)
prediction = net(x)
loss = loss_func(prediction, y) # 预测在前,真实在后
optimizer.zero_grad() # 清空上次计算的梯度
loss.backward() # 误差反向传播
optimizer.step() # 更新优化器中的参数
if t % 5 == 0:
plt.cla() # 动态图绘制
plt.scatter(x, y) # 散点图
plt.plot(x, prediction.detach().numpy(), 'r-', lw=5)
plt.text(0.5, 0, 'loss=%.4f' % loss, fontdict={'size': 20, 'color': 'red'})
plt.pause(0.1) # 暂停0.1s显示
plt.ioff() # 关闭动态显示
plt.show() # 显示
如果使用的是 Pycharm 编辑器,动态图显示的话,要将设置中的在工具窗口中显示绘图
取消勾选
分类
数据集太小,学习得太快,效果不是很明显。
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt
n_data = torch.ones(100, 2)
x0 = torch.normal(2 * n_data, 1) # class 0
y0 = torch.zeros(100) # class 0
x1 = torch.normal(-2 * n_data, 1) # class1
y1 = torch.ones(100) # class 1
x = torch.cat((x0, x1), 0).type(torch.FloatTensor) # FloatTensor = 32-bit floating
y = torch.cat((y0, y1), ).type(torch.LongTensor) # LongTensor = 64-bit integer
x, y = Variable(x), Variable(y)
# plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy(), s=100, lw=0, cmap='RdYlGn')
# plt.show()
class Net(nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = nn.Linear(n_feature, n_hidden)
self.predict = nn.Linear(n_hidden, n_output)
def forward(self, x):
x = F.relu(self.hidden(x))
x = self.predict(x)
return x
net = Net(2, 10, 2)
"""
输出结果
[1, 0] 分类为 class0
[0, 1] 分类为 class1
"""
plt.ion()
optimizer = torch.optim.SGD(net.parameters(), lr=0.02)
loss_func = nn.CrossEntropyLoss()
"""
softmax 输出为概率
[0.2 0.8] = 1
class0 概率为0.2 class1 概率为0.8
"""
for t in range(100):
out = net(x) # [-2 -.12 20] F.softmax(out) [0.1, 0.2, .7]
loss = loss_func(out, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if t % 2 == 0:
plt.cla()
prediction = torch.max(F.softmax(out), 1)[1] # 索引为1的地方为预测值最大的那个位置 索引为0时,返回最大值
pred_y = prediction.data.numpy().squeeze() # squeeze 降维度
target_y = y.data.numpy()
plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy(), s=100, lw=0, cmap='RdYlGn')
accuracy = sum(pred_y == target_y) / 200
plt.text(1.5, -4, 'Accuracy=%.2f' % accuracy, fontdict={'size': 20, 'color': 'red'})
plt.pause(0.1)
plt.ioff()
plt.show()
在中间的隐藏层,激活函数可以是多样化的。但是对于结果输出层,一般用于分类的是 sigmoid 或者 softmax
如不需要得到具体分类的概率直接torch.max()
回归和分类的网络结构基本是一样的,最重要的不同点在于所用的损失函数不同。