目的:
研究神经网络是如何进行事物的分类。
步骤1:建立数据集
首先创建一些假数据来模拟真实的情况,例如用两个均值不同的二次分布的数据。
import torch
import matplotlib.pyplot as plt
# 假数据
n_data = torch.ones(100, 2) # 数据的基本形态
x0 = torch.normal(2*n_data, 1) # 第一组数据的横纵坐标都包含在x0中
y0 = torch.zeros(100) # 第一组数据所对应的标签都是0
x1 = torch.normal(-2*n_data, 1) # 第二组数据的横纵坐标都包含在x1中
y1 = torch.ones(100) # 第二组数据所对应的标签都是1
# 合并数据
x = torch.cat((x0, x1), 0).type(torch.FloatTensor) # FloatTensor = 32-bit floating
y = torch.cat((y0, y1), 0).type(torch.LongTensor) # LongTensor = 64-bit integer
# 呈现数据的分布
plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy(), s=100, lw=0, cmap='RdYlGn')
plt.show()
- torch.normal(measn,std,out=None) :返回一个张量,张量里面的随机数是从相互独立的正态分布中随机生成的。
- means (Tensor) – 均值:包含每个输出元素相关的正态分布的均值。
- std (Tensor) – 标准差:包含每个输出元素相关的正态分布的标准差。
- out (Tensor) – 可选的输出张量
- 例如:x0 = torch.normal(2*n_data, 1) ,均值是2,标准差是1;
x1 = torch.normal(n_data, 1) ,均值是1,标准差是1;
- torch.cat():合并两个矩阵
- torch.cat( (A,B),0 ) #按维数0拼接(竖着拼) 例如torch.cat( (4,2),0 ),拼接后是8行2列
- torch.cat( (A,B),1 ) #按维数1拼接(横着拼) 例如torch.cat( (4,2),1 ),拼接后是4行4列
输出结果:
步骤2:建立神经网络
这个步骤和 【2.1 Regression】 用到的神经网络相差不大,运用 torch 中的体系来建立一个神经网络:
1)__ init__():定义所有层的属性。
2)forward(x):再一层层搭建层与层的关系连接,过程中会使用到激励函数。
import torch
import torch.nn.functional as F
class Net(torch.nn.Module): # 继承 torch 的 Module
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__() # 继承 __init__ 功能
self.hidden = torch.nn.Linear(n_feature, n_hidden) # 隐藏层--线性输出
self.out = torch.nn.Linear(n_hidden, n_output) # 输出层--线性输出
def forward(self, x):
# 正向传播输入值, 神经网络分析出输出值
x = F.relu(self.hidden(x)) # 激励函数relu
x = self.out(x) # 输出值, 但是这个不是预测值, 预测值还需要再另外计算
return x
net = Net(n_feature=2, n_hidden=10, n_output=2) # n_hidden代表隐藏层节点数,n_output代表最终类别数
print(net) # 输出此网络的结构
输出结果:
Net(
(hidden): Linear(in_features=2, out_features=10, bias=True)
(out): Linear(in_features=10, out_features=2, bias=True)
)
Process finished with exit code 0
步骤3:训练网络
训练过程很简单,如下:
# optimizer 是训练的工具,目的为了优化神经网络
optimizer = torch.optim.SGD(net.parameters(), lr=0.02) # 传入 net 的所有参数, 学习率设为0.2
loss_func = torch.nn.CrossEntropyLoss() # 计算出预测值与标签的误差
for t in range(100):
out = net(x) # 在net中训练数据 x, 输出预测值
loss = loss_func(out, y) # 计算预测值与实际y的误差,(预测值写在前面)
optimizer.zero_grad() # 把net中参数的梯度都将为0,为了下面的优化神经网络
loss.backward() # 误差反向传播, 计算参数更新值
optimizer.step() # 将参数更新值施加到 net 的 parameters 上,优化梯度
步骤4:可视化训练过程
整合代码并加入可视化:
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
# 假数据
n_data = torch.ones(100, 2) # 数据的基本形态
x0 = torch.normal(2*n_data, 1) # 第一组数据的横纵坐标都包含在x0中
y0 = torch.zeros(100) # 第一组数据所对应的标签都是0
x1 = torch.normal(-2*n_data, 1) # 第二组数据的横纵坐标都包含在x1中
y1 = torch.ones(100) # 第二组数据所对应的标签都是1
# 合并数据
x = torch.cat((x0, x1), 0).type(torch.FloatTensor) # FloatTensor = 32-bit floating
y = torch.cat((y0, y1), 0).type(torch.LongTensor) # LongTensor = 64-bit integer
class Net(torch.nn.Module): # 继承 torch 的 Module
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__() # 继承 __init__ 功能
self.hidden = torch.nn.Linear(n_feature, n_hidden) # 隐藏层--线性输出
self.out = torch.nn.Linear(n_hidden, n_output) # 输出层--线性输出
def forward(self, x):
# 正向传播输入值, 神经网络分析出输出值
x = F.relu(self.hidden(x)) # 激励函数relu
x = self.out(x) # 输出值, 但是这个不是预测值, 预测值还需要再另外计算
return x
net = Net(2, 10, 2)
optimizer = torch.optim.SGD(net.parameters(), lr=0.02) # 传入 net 的所有参数, 学习率设为0.2
loss_func = torch.nn.CrossEntropyLoss() # 计算出预测值与标签的误差
plt.ioff() # 停止画图
plt.show()
for t in range(100):
out = net(x)
loss = loss_func(out, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if t % 2 == 0:
plt.cla()
# 过了一道 softmax 的激励函数后的最大概率才是预测值
prediction = torch.max(F.softmax(out), 1)[1]
pred_y = prediction.data.numpy().squeeze()
target_y = y.data.numpy()
plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=pred_y, 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()
输出结果(录屏):
根据可视化界面可以很好的看出训练过程,大家可以直接复制代码,即可运行。