前馈神经网络

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前馈神经网络相关的知识,希望对你有一定的参考价值。

参考技术A

   前馈神经网络,又称 FNN(Feedforward Neural Network) ,是一种最简单的神经网络结构, FNN 结构是由最基本的神经元( neuron )堆叠而成;在每个神经元会做两步操作:1.与对应权重相乘累加,称为神经元状态。2.累加后的结果传入激活函数 。激活函数的值即为一个神经元的输出。

   总的来说, FNN 的模型可以描述成: 每经过一个隐含层就再给其增加一个中间函数,而每个隐含层所代表的具体的中间函数形式,是比较难解释。

   与其他机器模型一样, FNN 也需要模型训练时需要的目标 cost function ,也叫做 loss function 。常用的 loss function 有:

linear regression logistic regression 有些不同,模型的 cost function 可以通过极大似然估计这个角度切入,而前馈神经网络的 cost function ,笔者暂时还未深入了解,为何是如此设置。
   而当有了 cost function ,则模型训练的目标变成最小化损失函数,变成了一个无约束优化问题。

    FNN 参数的训练,可以使用反向传播算法,其基本思想是:1. 计算每一层的状态值和激活值,直至最后一层(前向传播);2. 从最后一层开始,计算每一层的误差,不断地向前推进(反向传播);3. 利用误差迭代参数,直至满足相应条件(达到迭代次数或误差得到满足)
   以下图的3层前馈神经网络为例:

   第二层神经元的状态值和激活值为:

而第三层神经元的状态值和激活值则为:

如果若以矩阵形式来描述,则前向传播可以写成如下:

先对 cost function 进行扩展

     
 

因此,若对输出层的神经元求偏导,则有:

若写成矩阵形式,则为:

继续对 cost function 进行进一步扩展

对隐含层的神经元求偏导有:

设 ,则上式可写成:
这里 是指,与第 层的第 个神经元连接的第 层的神经元所组成的集合。由于上述的 FNN 各层之间是一种全连接方式,因此上述 写成矩阵形式为: 而 写成矩阵形式则为:

   针对上述前馈神经网络,BP算法最后可以总结为四条公式:

选用不同的 cost funtion ,最后公式的形式可能会有所不同,但整个BP算法的流程是一样的。使用BP算法训练的神经网络,也被称为BP神经网络。深度学习中很多网络都可以使用BP算法来进行参数训练。

   这里使用的是吴恩达在Coursera中machine learning的一个实验例子;在实验中,是通过搭建一个简单的神经网络,做到手写体数字识别的效果。

激活函数:

神经网络结构规格:

BP算法:

最后网络在数据集上训练了300次,在训练集上的准确率达到了96%,与在Coursera里的实验相比,上述该例子的实现中并没有进行正则化,并且在训练次数较多;上述仅用最简的方法实现BP算法,较为粗糙。

   前馈神经网络是最为简单的神经网络结构,是神经网络中的基础知识。当隐含层层数增加时,神经网络则可称之为深度网络。上述也对训练神经网络的BP算法做了简单介绍,也进行了较为粗略地实现。

神经网络架构PYTORCH-前馈神经网络

   首先要熟悉一下怎么使用PyTorch来实现前馈神经网络吧.为了方便理解,我们这里只拿只有一个隐藏层的前馈神经网络来举例:

一个前馈神经网络的源码和注释如下:比较简单,这里就不多介绍了.

 1 class NeuralNet(nn.Module):
 2     def __init__(self, input_size, hidden_size, num_classes):
 3         super(NeuralNet, self).__init__()
 4         self.fc1 = nn.Linear(input_size, hidden_size) //输入层
 5         self.relu = nn.ReLU() //隐藏网络:elu的功能是将输入的feature的tensor所有的元素中如果小于零的就取零。
 6         self.fc2 = nn.Linear(hidden_size, num_classes) //输出层
 7 
 8     def forward(self, x):
 9         out = self.fc1(x)
10         out = self.relu(out)
11         out = self.fc2(out)
12         return out

  下面要看一下怎么调用和使用前馈神经网络的:为了提高运算效率,要把该网络优先使用GPU来进行运算.这里的输入尺寸和隐藏尺寸要和训练的图片保持一致的.

# Device configuration
device = torch.device(cuda if torch.cuda.is_available() else cpu)

model = NeuralNet(input_size, hidden_size, num_classes).to(device)

  为了训练网络,都需要定义一个loss function来描述模型对问题的求解精度。loss越小,代表模型的结果和真实值偏差越小,这里使用CrossEntropyLoss()来计算.Adam,这是一种基于一阶梯度来优化随机目标函数的算法。详细的概念和推导我们后续再专门做分析.

criterion = nn.CrossEntropyLoss() //针对单目标分类问题, 结合了 nn.LogSoftmax() 和 nn.NLLLoss() 来计算 loss.
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) //优化器,设置学习的速度和使用的模型

  接下来就是训练模型了,训练模型这部分是有点绕的,首先我们来看代码,后面再针对各个函数做说明:

 1 total_step = len(train_loader)
 2 for epoch in range(num_epochs):
 3     for i, (images, labels) in enumerate(train_loader):
 4         # Move tensors to the configured device
 5         images = images.reshape(-1, 28*28).to(device)
 6         labels = labels.to(device)
 7 
 8         # Forward pass
 9         outputs = model(images)
10         loss = criterion(outputs, labels) 
11 
12         # Backward and optimize
13         optimizer.zero_grad() //把梯度置零,也就是把loss关于weight的导数变成0.
14         loss.backward()
15         optimizer.step()

  训练模型,首先把图片矩阵变换成25*25的矩阵单元.其次,把运算参数绑定到特定设备上.

  然后就是网络的前向传播了:

outputs = model(inputs)

  然后将输出的outputs和原来导入的labels作为loss函数的输入就可以得到损失了:

loss = criterion(outputs, labels)

  计算得到loss后就要回传损失。要注意的是这是在训练的时候才会有的操作,测试时候只有forward过程。

loss.backward()

  回传损失过程中会计算梯度,然后需要根据这些梯度更新参数,optimizer.step()就是用来更新参数的。optimizer.step()后,你就可以从optimizer.param_groups[0][‘params’]里面看到各个层的梯度和权值信息。

optimizer.step()

  测试这个模型,没有梯度的模型,这样就大大大额减少了内存的使用量和运算效率,这个测试模型,其实只有一个关键的语句就可以预测模型了,那就是:_, predicted = torch.max(outputs.data, 1).

with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
images = images.reshape(-1, 28*28).to(device)
labels = labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
print(labels.size(0))
correct += (predicted == labels).sum().item()

  这里有个问题.训练好的数据怎么和预测联系起来呢?
训练输出的outputs也是torch.autograd.Variable格式,得到输出后(网络的全连接层的输出)还希望能到到模型预测该样本属于哪个类别的信息,这里采用torch.max。torch.max()的第一个输入是tensor格式,所以用outputs.data而不是outputs作为输入;第二个参数1是代表dim的意思,也就是取每一行的最大值,其实就是我们常见的取概率最大的那个index;第三个参数loss也是torch.autograd.Variable格式。
  总体源码:

 1 import torch
 2 import torch.nn as nn
 3 import torchvision
 4 import torchvision.transforms as transforms
 5 
 6 
 7 # Device configuration
 8 device = torch.device(cuda if torch.cuda.is_available() else cpu)
 9 
10 # Hyper-parameters 
11 input_size = 784
12 hidden_size = 500
13 num_classes = 10
14 #input_size = 84
15 #hidden_size = 50
16 #num_classes = 2
17 num_epochs = 5
18 batch_size = 100
19 learning_rate = 0.001
20 
21 # MNIST dataset 
22 train_dataset = torchvision.datasets.MNIST(root=../../data,
23                                            train=True,
24                                            transform=transforms.ToTensor(),
25                                            download=True)
26 
27 test_dataset = torchvision.datasets.MNIST(root=../../data,
28                                           train=False,
29                                           transform=transforms.ToTensor())
30 
31 # Data loader
32 train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
33                                            batch_size=batch_size,
34                                            shuffle=True)
35 
36 test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
37                                           batch_size=batch_size,
38                                           shuffle=False)
39 
40 # Fully connected neural network with one hidden layer
41 class NeuralNet(nn.Module):
42     def __init__(self, input_size, hidden_size, num_classes):
43         super(NeuralNet, self).__init__()
44         self.fc1 = nn.Linear(input_size, hidden_size)
45         self.relu = nn.ReLU()
46         self.fc2 = nn.Linear(hidden_size, num_classes)
47 
48     def forward(self, x):
49         out = self.fc1(x)
50         out = self.relu(out)
51         out = self.fc2(out)
52         return out
53 
54 model = NeuralNet(input_size, hidden_size, num_classes).to(device)
55 
56 # Loss and optimizer
57 criterion = nn.CrossEntropyLoss()
58 optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
59 
60 # Train the model
61 total_step = len(train_loader)
62 for epoch in range(num_epochs):
63     for i, (images, labels) in enumerate(train_loader):
64         # Move tensors to the configured device
65         images = images.reshape(-1, 28*28).to(device)
66         labels = labels.to(device)
67 
68         # Forward pass
69         outputs = model(images)
70         loss = criterion(outputs, labels)
71 
72         # Backward and optimize
73         optimizer.zero_grad()
74         loss.backward()
75         optimizer.step()
76 
77         if (i+1) % 100 == 0:
78             print (Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}
79                    .format(epoch+1, num_epochs, i+1, total_step, loss.item()))
80 # Test the model
81 # In test phase, we don‘t need to compute gradients (for memory efficiency)
82 with torch.no_grad():
83     correct = 0
84     total = 0
85     for images, labels in test_loader:
86         images = images.reshape(-1, 28*28).to(device)
87         labels = labels.to(device)
88         outputs = model(images)
89         _, predicted = torch.max(outputs.data, 1)
90         total += labels.size(0)
91         #print(predicted)
92         correct += (predicted == labels).sum().item()
93 
94     print(Accuracy of the network on the 10000 test images: {} %.format(100 * correct / total))
95 
96 # Save the model checkpoint
97 torch.save(model.state_dict(), model.ckpt)

  每日一言:人之所畏,不可不畏。

  参考文档:

1 https://blog.csdn.net/fireflychh/article/details/75516165

2 https://blog.csdn.net/kgzhang/article/details/77479737

 

3 https://github.com/pytorch/tutorials

以上是关于前馈神经网络的主要内容,如果未能解决你的问题,请参考以下文章

常见神经网络类型之前馈型神经网络

神经网络架构PYTORCH-前馈神经网络

深度学习之前馈神经网络(前向传播和误差方向传播)

前馈全连接神经网络| matlab

Matlab中的前馈神经网络分类

水很深的深度学习-Task03前馈神经网络