本文为PyTorch神经网络的学习笔记。欢迎批评指正。
- 神经网络可能会得出局部最优解而并非全局最优解,但有时局部最优解已经足够解决问题。
1. PyTorch用法
1.1 导入
- 导入PyTorch,numpy与torch数据转换
import torch
import numpy as np
np_data=np.arange(6).reshape((2,3))
torch_data=torch.from_numpy(np_data)# numpy转换为torch
tensor2array=torch_data.numpy()# torch数据转换为numpy
data=[-1,-2,1,2]
tensor=torch.FloatTensor(data) # 32-bit floating point
np.abs(data)
torch.abs(tensor)
np.mean(data)
torch.abs(data)
- torch的tensor相乘输出结果为对应数字相乘再相加,output只有一个数字,而并非矩阵。
data.dot(data)
tensor.dot(tensor)
1.2 Variable 变量
import torch
from torch.autograd import Variable
tensor=torch.FloatTensor([[1,2],[3,4]])
variable=Variable(tensor,requires_grad=True)
t_out=torch.mean(tensor*tensor) # x^2
v_out=torch.mean(variable*variable)
print(t_out)# tensor 不能反向传播
print(v_out)# variable 可以反向传播,variable containing相当于tensor放入variable中
v_out.backward()
print(variable.grad)# variable也会受影响,因为是逐步搭建的
# 解释:
# v_out=1/4*sum(var*var), 因为是mean
# d(v_out)/d(var)=1/4*2*variable=variable/2
print(variable)
print(variable.data)
print(variable.data.numpy())#将variable先转换为data,即tensor形式,再numpy
2. 激励函数(Activation Function)
2.1 定义
线性问题形式 y = W x y=Wx y=Wx
非线性问题形式
y = A F ( W x ) y=AF(Wx) y=AF(Wx)
其中 A F AF AF为激励函数,相当于在原有线性结果上把方程掰弯,使得 y y y具有非线性特征。激励函数通常的形式有 s i g m o i d , r e l u , t a n h , s o f t p l u s sigmoid, relu, tanh, softplus sigmoid,relu,tanh,softplus等等,如下图所示:
(资料来源:bilibili 莫烦Python,链接见参考资料)
同时激励函数必须为可微分的,这样才能保证backpropagation可以把误差顺利传递回去。
对于只有两三层的神经网络,激励函数一般可以随意选取。但当神经网络层数较多时,由于涉及到梯度爆炸和梯度消失的问题,激励函数需要慎重选取。
少量神经层激励函数选取
- 卷积神经网络(Convolutional Neural Networks, CNN):relu
- 循环神经网络(Recurrent Neural Network, RNN):relu或tanh
2.2 激励函数画图
import torch
import numpy as np
import torch.nn.functional as F # 有些功能已经deprecated
from torch.autograd import Variable
import matplotlib.pyplot as plt
# 给出x
x=torch.linspace(-5,5,200)
x=Variable(x)
x_np=x.data.numpy()
# 得到四个激励函数对应的y
y_relu=F.relu(x).data.numpy()
y_sigmoid=torch.sigmoid(x).data.numpy() # 原视频写的是F.sigmoid(x).data.numpy() 但由于原视频是2017年的,我这里运行的时候显示这一写法已经deprecated。可以使用torch.sigmoid(x)调用该激励函数。下面的tanh同理
y_tanh=torch.tanh(x).data.numpy()
y_softplus=F.softplus(x).data.numpy()
# y_softmax=F.softmax(x).data.numpy() # softmax用于做概率图,可以计算分类问题的概率,无法画出线型图
# 画出四张图
plt.figure(1,figsize=(8,6))
plt.subplot(221)
plt.plot(x_np,y_relu,c='red',label='relu')
plt.ylim(-1,5)
plt.legend(loc='best')
plt.figure(1,figsize=(8,6))
plt.subplot(222)
plt.plot(x_np,y_sigmoid,c='red',label='sigmoid')
plt.ylim(-1,5)
plt.legend(loc='best')
plt.figure(1,figsize=(8,6))
plt.subplot(223)
plt.plot(x_np,y_tanh,c='red',label='tanh')
plt.ylim(-1,5)
plt.legend(loc='best')
plt.figure(1,figsize=(8,6))
plt.subplot(224)
plt.plot(x_np,y_softplus,c='red',label='softplus')
plt.ylim(-1,5)
plt.legend(loc='best')
应该得到下面的图片
3. 神经网络构建
3.1 Regression回归
跟着up主写了下代码。但预测误差先减小后变大,请教了一下大佬发现是过拟合了。而且这里属于老版本的torch,新版本实现过程有很大差别。看个思路就行。
import torch
import numpy as np
import torch.nn.functional as F # 有些功能已经deprecated
from torch.autograd import Variable
import matplotlib.pyplot as plt
x=torch.unsqueeze(torch.linspace(-1,1,100),dim=1) # x data tensor, shape=(100,1). 由于torch只会处理二位数据,需要用torch.unsqueeze把一维数据转换为二维
y=x.pow(2)+0.2*torch.rand(x.size()) # x^2+噪点影响
x,y=Variable(x),Variable(y)
plt.scatter(x.data.numpy(),y.data.numpy())
plt.show() # 散点图
画了一下散点图,是这个样子的。
# class定义神经网络
class Net(torch.nn.Module): # 继承该模块
def __init__(self, n_features, n_hidden, n_output):
# n_features: 输入变量个数
# n_hidden: 隐藏层神经元个数
# n_hident: 输出变量个数
super(Net,self).__init__() #继承
self.hidden=torch.nn.Linear(n_features,n_hidden) # 一层隐藏层。n_features表示该层输入变量个数
self.predict=torch.nn.Linear(n_hidden,1)# 只预测一个y值,因此只有一个输出个数
# Tips:
# torch.nn.Linear(in_features,out_features,bias)有三个参数
# in_features--每个输入样本的大小
# out_features--每个输出样本的大小
# bias--默认为True。如果设置为False,则图层不会学习附件偏差
def forward(self,x): # torch中搭流程图
x=F.relu(self.hidden(x)) # 激励函数,嵌套隐藏层输入信息
x=self.predict(x) # 输出层输出结果。
# 这里预测的时候不需要用激励函数,因为激励函数可能会截断预测结果(如relu)。一般可以不用activation function.
return x
# 搭建神经网络
net=Net(1,10,1) # 输入变量为1,隐藏神经元个数为10,输出变量个数为1
print(net) # 看下本仙女搭的神经网络长啥样。hidden是1-->10,predict是10-->1。
#结果显示
# Net(
# (hidden): Linear(in_features=1, out_features=10, bias=True)
# (predict): Linear(in_features=10, out_features=1, bias=True)
# )
# 可视化(1)
plt.ion() # 让plt生成一个实时打印的过程
plt.show()
loss_list=[] # 用来观察loss数值变化
# 优化神经网络
optimizer=torch.optim.SGD(net.parameters(),lr=0.5)
# SGD--Stochastic Gradient Descent随机梯度下降法
# net.parameters()--传入神经网络参数
# lr--learning rate 学习率。一般小于1。越高学习越快可能遗漏知识点
loss_func=torch.nn.MSELoss()
# Mean-Square error loss--均方差,用于处理回归问题误差。分类问题需要另一种
for t in range(100):
prediction=net(x) # 每一步的prediction
loss=loss_func(prediction,y) # 预测值和真实值误差。前后顺序不要反,结果不太一样。
optimizer.zero_grad() # 先让net.parameters()里梯度降为0,后续每一步计算会将梯度存放在optimizer里
loss.backward() # 反向传递,计算grad梯度
optimizer.step() # 以学习效率lr优化grad梯度
loss_list.append(loss.data.item())
# 可视化(2)
if t%5==0: # 每学习5步打印一次
plt.cla()
plt.scatter(x.data.numpy()</