PyThorch自然语言处理(四)

本文介绍了神经网络的基础单元——感知器,包括其工作原理、激活函数和线性可分性限制。接着讲解了前馈神经网络的结构,包括输入、隐藏和输出层,以及信息的单向传递。多层感知器(MLP)作为前馈网络的扩展,能处理非线性函数。最后,探讨了卷积神经网络(CNN)的独特之处,如局部连接、权值共享和在图像处理中的应用。
摘要由CSDN通过智能技术生成

(本文参照网络公开的博文、笔记等内容学习的,如有侵权则删)

感知器(单个神经元)

神经网络中计算的基本单元是神经元,一般称作「节点」(node)或者「单元」(unit)。节点从其他节点接收输入,或者从外部源接收输入,然后计算输出。每个输入都辅有「权重」(weight,即 w),权重取决于其他输入的相对重要性。节点将函数 f(定义如下)应用到加权后的输入总和。
在这里插入图片描述
此网络接受 X1 和 X2 的数值输入,其权重分别为 w1 和 w2。另外,还有配有权重 b(称为「偏置(bias)」)的输入 1。(偏置的重要性:偏置的主要功能是为每一个节点提供可训练的常量值(在节点接收的正常输入以外))

神经元的输出 Y 如图 1 所示进行计算。函数 f 是非线性的,叫做激活函数。激活函数的作用是将非线性引入神经元的输出。因为大多数现实世界的数据都是非线性的,我们希望神经元能够学习非线性的函数表示。

每个(非线性)激活函数都接收一个数字,并进行特定、固定的数学计算。

感知器的缺点是不能适当学习存在于数据集中的非平常模式。下图里,在这种情况下,决策边界不能是一条直线(也称为线性可分)
在这里插入图片描述

前馈神经网络

前馈神经网络是最先发明也是最简单的人工神经网络 [3]。它包含了安排在多个层中的多个神经元(节点)。相邻层的节点有连接或者边(edge)。所有的连接都配有权重。
在这里插入图片描述

一个前馈神经网络可以包含三种节点:

  1. 输入节点(Input Nodes):输入节点从外部世界提供信息,总称为「输入层」。在输入节点中,不进行任何的计算——仅向隐藏节点传递信息。

  2. 隐藏节点(Hidden Nodes):隐藏节点和外部世界没有直接联系(由此得名)。这些节点进行计算,并将信息从输入节点传递到输出节点。隐藏节点总称为「隐藏层」。尽管一个前馈神经网络只有一个输入层和一个输出层,但网络里可以没有也可以有多个隐藏层。

  3. 输出节点(Output Nodes):输出节点总称为「输出层」,负责计算,并从网络向外部世界传递信息。

**在前馈网络中,信息只单向移动——从输入层开始前向移动,然后通过隐藏层(如果有的话),再到输出层。**在网络中没有循环或回路 (前馈神经网络的这个属性和递归神经网络不同,后者的节点连接构成循环)。

前馈神经网络与另一类神经网络——递归神经网络(RNNs)形成对比,递归神经网络(RNNs)允许反馈(或循环),这样每次计算都可以从之前的计算中获得信息。在第6章和第7章中,我们将介绍RNNs以及为什么允许网络结构中的循环是有益的。

正向传播

正向传播:输入样本->输入层->各隐层(处理)->输出层

反向传播

误差反向传播:输出误差(某种形式)->隐层(逐层)->输入层 其主要目的是通过将输出误差反传,将误差分摊给各层所有单元,从而获得各层单元的误差信号,进而修正各单元的权值(其过程,是一个权值调整的过程)。

对于所有训练数据集中的输入,人工神经网络都被激活,并且观察其输出。这些输出会和我们已知的、期望的输出进行比较,误差会「传播」回上一层。该误差会被标注,权重也会被相应的「调整」。该流程重复,直到输出误差低于制定的标准。




多层感知器(MLP)

多层感知器(Multi Layer Perceptron)是一个特定的人工神经网络。是一种前馈架构。

多层感知器(Multi Layer Perceptron,即 MLP)包括至少一个隐藏层(除了一个输入层和一个输出层以外,隐藏节点个数不限)。单层感知器只能学习线性函数,而多层感知器也可以学习非线性函数

最简单的MLP是对感知器的扩展。感知器将数据向量作为输入,计算出一个输出值。在MLP中,许多感知器被分组,以便单个层的输出是一个新的向量,而不是单个输出值。

MLP的力量来自于添加第二个线性层和允许模型学习一个线性分割的的中间表示——该属性的能表示一个直线(或更一般的,一个超平面)可以用来区分数据点落在线(或超平面)的哪一边的。学习具有特定属性的中间表示,如分类任务是线性可分的,这是使用神经网络的典型问题之一。

在这里插入图片描述

输入层:输入层有三个节点。偏置节点值为 1。其他两个节点从 X1 和 X2 取外部输入(皆为根据输入数据集取的数字值)。和上文讨论的一样,在输入层不进行任何计算,所以输入层节点的输出是 1、X1 和 X2 三个值被传入隐藏层。
隐藏层:隐藏层也有三个节点,偏置节点输出为 1。隐藏层其他两个节点的输出取决于输入层的输出(1,X1,X2)以及连接(边界)所附的权重。图 4 显示了隐藏层(高亮)中一个输出的计算。其他隐藏节点的输出计算同理。需留意 *f *指代激活函数。这些输出被传入输出层的节点。
输出层:输出层有两个节点,从隐藏层接收输入,并执行类似高亮出的隐藏层的计算。这些作为计算结果的计算值(Y1 和 Y2)就是多层感知器的输出。


MLP的实现只实现反向传播的前向传递。这是因为PyTorch根据模型的定义和向前传递的实现,自动计算出如何进行向后传递和梯度更新。

import torch.nn as nn
import torch.nn.functional as F
import torch as t

class MultilayerPerceptron(nn.Module):
    def __init__(self,input_dim,hidden_dim,output_dim):
        """
        Args:
            input_dim(int):the size of input vectors
            hidden_dim(int):the output size of first Linear layer
            output_dim(int):the output size of the second Linear layer
        """
        super(MultilayerPerceptron, self).__init__()
        self.fc1 = nn.Linear(input_dim,hidden_dim)
        self.fc2 = nn.Linear(hidden_dim,output_dim)
        #nn.Linear()函数用于设置网络的全连接层,全连接层的额输入和输出都是二维张量
        #torch.nn.Linear(in_feature,out_feature,blas = True)
        #in_features指的是输入的二维张量的大小,即输入的[batch_size, size]中的size
        #out_features指的是输出的二维张量的大小,即输出的二维张量的形状为[batch_size,output_size],当然,它也代表了该全连接层的神经元个数。
        #从输入输出的张量的shape角度来理解,相当于一个输入为[batch_size, in_features]的张量变换成了[batch_size, out_features]的输出张量。
        
    def forward(self,x_in,apply_softmax = False):
        """The forward pass of the MLP
        Args:
            x_in (torch.Tensor): an input data tensor.
                x_in.shape should be (batch, input_dim)
            apply_softmax (bool): a flag for the softmax activation
                should be false if used with the Cross Entropy losses
        Returns:
            the resulting tensor. tensor.shape should be (batch, output_dim)
        """
        intermediate = F.relu(self.fc1(x_in))#激活函数relu
        output = self.fc2(intermediate)
        
        if apply_softmax:
            output = F.softmax(output,dim=1)
            
        return output

#实例化模型Initialize model
batch_size = 2 #一次性输入的样本数number of sanples input at once
input_dim =3
hidden_dim = 100
output_dim = 4

mlp = MultilayerPerceptron(input_dim,hidden_dim,output_dim)
print(mlp)
#输出MultilayerPerceptron(
#  (fc1): Linear(in_features=3, out_features=100, bias=True)
#  (fc2): Linear(in_features=100, out_features=4, bias=True))

我们可以通过传递一些随机输入来快速测试模型的“连接”。因为模型还没有经过训练,所以输出是随机的。在花费时间训练模型之前,这样做是一个有用的完整性检查。

MLP模型的输出是一个有两行四列的张量。张量中的行与批处理维数对应,批处理维数是小批处理中的数据点的数量。列是每个数据点的最终特征向量。

例如在分类设置中,特征向量是一个预测向量。名称为“预测向量”表示它对应于一个概率分布。

预测向量会发生什么取决于我们当前是在进行训练还是在执行推理。在训练期间,输出按原样使用,带有一个损失函数和目标类标签的表示。

如果需要将预测向量转化为概率,需要额外的步骤。比如softmax函数将值转化为概率使得大的正值有更高的概率,小的负值导致更小的概率。

def describe(x):
    print("Type: {}".format(x.type()))
    print("Shape/size: {}".format(x.shape))
    print("Values: \n{}".format(x))
    
import torch 
x_input = torch.rand(batch_size, input_dim)
describe(x_input)
#Type: torch.FloatTensor
#Shape/size: torch.Size([2, 3])
#Values: 
#tensor([[0.1264, 0.9323, 0.1486],
#        [0.6897, 0.9471, 0.2259]])
y_output =  mlp(x_input,apply_softmax = False)
describe(y_output)
#Type: torch.FloatTensor
#Shape/size: torch.Size([2, 4])
#Values: 
#tensor([[ 0.0285, -0.1123,  0.0967,  0.4626],
#        [ 0.0621, -0.0778,  0.0619,  0.4000]], grad_fn=<AddmmBackward>)


#多层感知器分类器产生的概率输出
y_output1 = mlp(x_input, apply_softmax=True)
describe(y_output1)
#多层感知器分类器产生的概率输出
y_output1 = mlp(x_input, apply_softmax=True)
describe(y_output1)
#Type: torch.FloatTensor
#Shape/size: torch.Size([2, 4])
#Values: 
#tensor([[0.2231, 0.1938, 0.2388, 0.3443],
#        [0.2341, 0.2036, 0.2341, 0.3282]], grad_fn=<SoftmaxBackward>)

mlp是将张量映射到其他张量的线性层。在每一对线性层之间使用非线性来打破线性关系,并允许模型扭曲向量空间。在分类设置中,这种扭曲应该导致类之间的线性可分性。




卷积神经网络

卷积神经网络是一种前馈架构,其成功的原因关键在于它所采用的局部连接和共享权值的方式,一方面减少了的权值的数量使得网络易于优化,另一方面降低了过拟合的风险。
卷积神经网络依旧是层级网络,只是层的功能和形式做了变化。CNN保持层级网络结构,不同层级有不同运算和功能。卷积神经网络的层次结构如下

  • 数据输入层 input layer
  • 卷积计算层 CONV layer
  • ReUU激励层 ReUU layer
  • 池化层 Pooling layer
  • 全连接层 FC layer

一般情况下,CNN的结构形式是:输入层–> Conv层 --> Pooling层 --> (重复Conv、Pooling层) … --> FC(Full-connected)层 --> 输出结果。

CNN具有一些传统技术所没有的优点:良好的容错能力、并行处理能力和自学习能力,可处理环境信息复杂,背景知识不清楚,推理规则不明确情况下的问题,允许样品有较大的缺损、畸变,运行速度快,自适应性能好,具有较高的分辨率。它是通过结构重组和减少权值将特征抽取功能融合进多层感知器,省略识别前复杂的图像特征抽取过程。
CNN是一种深度的监督学习下的机器学习模型,具有极强的适应性,善于挖掘数据局部特征,提取全局训练特征和分类,它的权值共享结构网络使之更类似于生物神经网络,在模式识别各个领域都取得了很好的成果。


数据输入层

数据输入层作用是对输入的数据进行预处理,如去均值,归一化,PCA、白化等。

  • 去均值:把输入数据的各个维度都中心化为0
  • 归一化:幅度归一化到同样的范围
  • PCA:用PCA降维
  • 白化:对数据每个特征轴上的幅度归一化
卷积计算层

卷积层有两个关键步骤:

  • 局部关联:每个神经元看成一个滤波器(filter)
  • 窗口(receptive field)滑动,filter对局部数据计算

卷积层的名词解释

  • 深度 depth
  • 步长 stride 窗口一次滑动的长度
    在这里插入图片描述
  • 填充值 zero-padding
    一个5 * 5的图片(一个格子一个像素),我们滑动窗口取22,步长取2,那么我们发现还剩下1个像素没法滑完。我们在原先的矩阵加了一层填充值,使得变成66的矩阵,那么窗口就可以刚好把所有像素遍历完。这就是填充值的作用。
    在这里插入图片描述
    蓝色矩阵周围有一圈灰色的框,那些就是上面所说到的填充值,蓝色矩阵就是输入的图像,粉色矩阵就是卷积层的神经元,这里表示了有两个神经元(w0,w1)。绿色矩阵就是经过卷积运算后的输出矩阵,这里的步长设置为2。
    在这里插入图片描述
    在这里插入图片描述

如何理解CNN里的权值共享
权值共享这个词最开始其实是由LeNet5模型提出来。1988年LeCun发布的模型。
在这里插入图片描述
这里运用了一种思想,我们称之局部关联,或者说是参数共享机制。每个神经元看做一个卷积核(又称之感受野,receptive field),卷积核对局部数据进行计算。所谓参数共享,就是共享卷积核。不管你原来的数据长啥样,我就用这一组卷积核,一直移动计算。



激励层

把卷积层输出结果做非线性映射,一般采样的集里函数为ReUU(ReUU函数特点是收敛快,求梯度简单)

在这里插入图片描述

池化层

池化层夹在连续的卷积层中间, 用于压缩数据和参数的量,减小过拟合。简而言之,如果输入是图像的话,那么池化层的最主要作用就是压缩图像。
池化的作用如下:

  • 特征不变性,比如一张图像被缩小了一倍但是图内的额信息的特征仍然不变。
  • 特征降维,去除冗余信息
  • 一定程度上防止过拟合

池化的常见方法有max pooling(取最大值保留),average pooling(取平均值保留),L2池化 L2 pooling:(即取均方值保留)。
例max pooling 的思想如下所示,对于每个2 * 2的窗口选出最大的数作为输出矩阵的相应元素的值,比如输入矩阵第一个2 * 2窗口中最大的数是6,那么输出矩阵的第一个元素就是6,如此类推。
在这里插入图片描述

全连接层

两层之间所有神经元都有权重连接,通常全连接层在卷积神经网络尾部。也就是跟传统的神经网络神经元的连接方式是一样的:
在这里插入图片描述




PyTorch的CNN的超参数

卷积运算的维数

PyTorch里卷积可以是一维、二维、三维,分贝是Conv1d、Conv2d、Conv3d模块实现。一维卷积对每个时间步上有一个特征向量的时间序列很有用,二维卷积在数据的两个方向上进行捕获,常用于图像处理。三维卷积在数据的三个维度捕获模式,可用于视频处理。

通道 channel

比如RGB图片,通道 数量是 3 (红、绿、蓝)。如下图(图片使用自吴恩达老师的深度学习课程 )。假设现有一个为 6×6×36×6×3 的图片样本,使用 3×3×33×3×3 的卷积核(filter)进行卷积操作。此时输入图片的 channels 为 33 ,而卷积核中的 in_channels 与 需要进行卷积操作的数据的 channels 一致(这里就是图片样本,为3)。进行卷积操作,卷积核中的27个数字与分别与样本对应相乘后,再进行求和,得到第一个结果。依次进行,最终得到 4×4 的结果。由于只有一个卷积核,所以最终得到的结果为 4×4×1 , out_channels 为 1
在这里插入图片描述
在这里插入图片描述

  1. 最初输入的图片样本的 channels ,取决于图片类型,比如RGB;
  2. 卷积操作完成后输出的 out_channels ,取决于卷积核的数量。此时的 out_channels 也会作为下一次卷积时的卷积核的 in_channels;
  3. 卷积核中的 in_channels ,刚刚2中已经说了,就是上一次卷积的 out_channels ,如果是第一次做卷积,就是1中样本图片的 channels 。

**使用卷积的时候,文本数据也可以有类似的概念,**常见的通道从一个卷积层缩减到下一个卷积层,缩减的幅度不超过原来的两倍。

核大小 kernel_size

卷积核的大小

步长 stride

控制卷积之间的步长,如果步长和核大小一样,那核计算不会重叠。
如果步长为1,则核函数最大部分重叠。

填充 padding

在不影响所需内核大小、步长或膨胀的情况下对输出型状进行控制。

膨胀 Dilation

在这里插入图片描述

import torch
import torch.nn as nn
#如果对字符序列里每个字符使用one-hot向量序列,每个one-hot序列是一个矩阵,一个one-hot矩阵的小批量是一个三维向量
#one-hot向量大小(通常是字符表大小)是通道的数量,字符序列的长度是宽度
batch_size = 2
one_hot_size = 10
sequence_width = 7
data = torch.randn(batch_size,one_hot_size,sequence_width)
conv1 = nn.Conv1d(in_channels = one_hot_size,out_channels = 16,kernel_size = 3)
intermediate1 = conv1(data)
print(data.size())
print(intermediate1.size())
#输出torch.Size([2, 10, 7]) torch.Size([2, 16, 5])
'''
Pytorch中的Conv1d()函数参数
in_channels (int) – 输入通道个数。在文本应用中,即为词向量的维度
out_channels (int) – 输出通道个数 。有多少个out_channels,就需要多少个一维卷积(也就是卷积核的数量)
kernel_size(int or tuple) – 卷积核的尺寸;卷积核的第二个维度由in_channels决定,所以实际上卷积核的大小为kernel_size * in_channels
stride (int or tuple, optional) – 卷积操作的步长。 默认:1
padding (int or tuple, optional) – 输入数据各维度各边上要补齐0的层数。 默认: 0
dilation (int or tuple, optional) – 卷积核各元素之间的距离。 默认: 1
groups (int, optional) – 输入通道与输出通道之间相互隔离的连接的个数。 默认:1
bias (bool, optional) – 如果被置为True,向输出增加一个偏差量,此偏差是可学习参数。 默认:True
'''
'''
 创建额外的卷积并按顺序应用进一步减小输出张量的方法   
'''
conv2 = nn.Conv1d(in_channels=16, out_channels=32, kernel_size=3)
conv3 = nn.Conv1d(in_channels=32, out_channels=64, kernel_size=3)
intermediate2 = conv2(intermediate1)
intermediate3 = conv3(intermediate2)
print(intermediate2.size())
print(intermediate3.size())#输出 torch.Size([2, 32, 3]) torch.Size([2, 64, 1])
y_output = intermediate3.squeeze()
print(y_output.size())
#输出 torch.Size([2, 64])


参考文献

  1. https://zhuanlan.zhihu.com/p/23937778
  2. https://www.bookstack.cn/read/nlp-pytorch-zh/fc8befa68043babe.md#Pooling%20Operation
  3. https://www.zhihu.com/topic/20043586/intro
  4. https://www.jianshu.com/p/1ea2949c0056
  5. https://blog.csdn.net/fengbingchun/article/details/50529500
  6. https://www.cnblogs.com/kongweisi/p/10987870.html
  7. https://blog.csdn.net/sscc_learning/article/details/79814146
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值