三、神经网络(1980-1995)
文章目录
3.1 神经元与神经网络:通过学习算法得到神经网络解决问题所需的参数。(W,b)
感知机: 两层神经元组成的神经网络。(输入层、输出层)
前馈神经网络: 感知机是前馈神经网络的一种,包含输入层、隐含层、输出层。(隐含层的个数可以有0个或多个)
多层感知机: 含有一个或多个隐含层的前馈神经网络。
3.2 激活函数:加入非线性因素,解决线性模型所不能解决的问题
3.2.1 Sigmoid:将输入变量映射到(0,1)区间
3.2.2 Tanh:将输入变量映射到(-1,1)区间
3.2.3 Hard Tanh:给定阈值直接将输入变量映射到(-1,1)区间
3.2.4 ReLu:大于0的数原样输出,小于0的数输出0
3.2.5 Softmax:将k维向量每一个元素压缩到(0,1)区间,且所有元素的和为1
3.3 前向算法:通过神经网络计算每层输出,最终得到整个网络的输出
3.4 损失函数:量化训练过程中网络输出值和真实值得差距
3.4.1 回归问题:均方差损失(MSE),类似最小二乘法
L ( W , b ) = 1 N ∑ i = 1 N ( y ^ − y i ) 2 L(W,b)=\frac{1}{N}\sum_{i=1}^N(\hat{y}-y_i)^2 L(W,b)=N1i=1∑N(y^−yi)2
平均绝对误差(MAE):所有误差绝对值的平均值。
L
(
W
,
b
)
=
1
2
N
∑
i
=
1
N
∑
j
=
1
M
∣
y
i
j
^
−
y
i
j
∣
L(W,b)=\frac{1}{2N}\sum_{i=1}^{N}\sum_{j=1}^M|\hat{y_{ij}}-y_{ij}|
L(W,b)=2N1i=1∑Nj=1∑M∣yij^−yij∣
3.4.2 分类问题 :负对数似然损失函数,也叫交叉熵函数
L ( W , b ) = − ∑ i = 1 N ∑ j = 1 M 1 { Y i j = 1 } ∗ l o g ( y i , j ^ ) L(W,b)=-\sum_{i=1}^N\sum_{j=1}^M1\{{Y_i^j=1}\}*log(\hat{y_{i,j}}) L(W,b)=−i=1∑Nj=1∑M1{Yij=1}∗log(yi,j^)
3.4.3pytorch中常用的损失函数
-
MSELoss
class torch.nn.MSELoss(size_average=True, reduce=True)
-
L1Loss
前边提到的MAE
-
BCELoss
-
BCEWithLogitsLoss
-
NLLLoss
负对数似然函数
-
CrossEntropyLoss:用于多分类
交叉熵损失函数,LogSoftmax和NLLLoss的组合。
3.5 反向传播算法:以误差为主导的反向传播运动,使损失函数值取到最小,旨在得到最优的全局参数矩阵。
求偏导,用梯度下降进行更新。
梯度下降迭代更新,使损失函数达到最小,求得对应的
θ
\theta
θ系数。
3.6 数据的准备
class torch.utils.data.DataLoader(dataset,batch_size=1, shuffle=false, sampler=None, batch_sampler=None, num_workers=0, ...)
3.7 单层神经网络实现
torch.nn中大多数layer在torch.nn.funtional中都有一个与之对应的函数。二者的区别在于:torch. nn.Module中实现layer的都是一个特殊的类,可以去查阅,他们都是以class xxxx来定义的,会自动提取可学习的参数,而 nn.functional中的函数,更像是纯函数,由def function( )定义,只是进行简单的 数学运算而已。
'''
Pytorch实现iris数据集的分类
'''
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F #定义神经网络函数,不需要传参
#torch.nn中大多数layer在torch.nn.funtional中都有一个与之对应的函数
from sklearn.datasets import load_iris #导入iris数据集
from torch.autograd import Variable #对tensor的封装
from torch.optim import SGD #随机梯度下降优化算法
#GPU是否可用
use_cuda = torch.cuda.is_available()
print("use_cuda:", use_cuda)
#加载数据集
iris = load_iris()
print(iris.keys())
#数据预处理,把数据封装成Variable格式
x = iris['data']
y = iris['target']
print(x.shape)
print(y.shape)
print(y)
x = torch.FloatTensor(x)
y = torch.LongTensor(y)
#x, y = Variable(x), Variable(y)
#神经网络模型定义,需要继承nn.Module,并重写forward方法完成向前计算过程
class Net(torch.nn.Module):
#初始化函数,接受自定义输入特征维数,隐含层特征维数,输出层特征维数
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden) #一个线性隐含层
self.predict = torch.nn.Linear(n_hidden, n_output)
#前向传播过程
def forward(self, x):
x = torch.sigmoid(self.hidden(x))
x = self.predict(x)
out = F.log_softmax(x, dim=1) #激活函数log_softmax
return out
#网络结构实例化并打印查看网络结构
net = Net(n_feature=4, n_hidden=5, n_output=4)
print(net) #输出网络结构
#使用GPU训练模型,调用.cuda(),如果想放在CPU上,调用.cpu()即可
if use_cuda:
x = x.cuda()
y = y.cuda()
net = net.cuda()
#定义神经网络的优化器,学习率0.5
optimizer = SGD(net.parameters(), lr=0.5)
#print(net.parameters())
#print(list(net.parameters())) #迭代的参数W,b
#训练过程
px, py = [], [] #记录要绘制的数据
for i in range(1000):
#数据集传入网络前向计算
prediction = net(x)
#计算loss
loss = F.nll_loss(prediction, y)
#清除网络状态,把梯度置零
optimizer.zero_grad()
#loss反向传播
loss.backward()
#更新参数
optimizer.step()
#打印并记录当前的index和loss
print(i, "loss:", loss)
px.append(i)
py.append(loss)
#Loss变化示意图
if i % 10 == 0:
#动态画出loss结果走向图
plt.cla() #Clear axis即清除当前图形中的当前活动轴。其他轴不受影响。
plt.plot(px, py, 'r-', lw = 1) #红色实线,线宽为1
plt.text(0, 0, 'Loss=%.4f'%loss, fontdict={'size':20, 'color':'red'})
plt.pause(0.1) #如果有活动的图形,它将在暂停之前被更新和显示,GUI事件循环(如果有的话)将在暂停期间运行。
迭代过程中的:optimizer.zero_grad();loss.backward();optimizer.step()
这三个函数的作用是先将梯度归零(optimizer.zero_grad()),然后反向传播计算得到每个参数的梯度值(loss.backward()),最后通过梯度下降执行一步参数更新(optimizer.step())
输出结果: