卷积神经网络、循环神经网络笔记

b站刘二大人《Pytorch深度学习实践》最后四讲

第十讲 卷积神经网络(基础)

先看了吴恩达机器学习中的讲解,
卷积是为了边缘检测,或者说是提取特征,一个矩阵与一个kernal(filter)作数乘。用不同的核作卷积可以提取不同的特征,这里的核就类似于线性回归中的w,是一个参数、

padding

为了使得边缘信息丢失的影响降低,可以在图像边缘增加p圈,可以使得卷积过后的结果不会变的太小,比如图像6×6,kernal3×3,可以令p=1,则,图像变为8×8,卷积后又会得到6×6的图像。
由此可将convolution分为两类,vaild and same
valid 意为不进行padding
same 意为输出的尺寸和输出的尺寸相同。n+2*p-f+1=n可得,p=(f-1)/2;

stride

n × n f × f    p a d d i n g     p       s t r i d e    s n\times n f\times f \ \ padding\ \ \ p\ \ \ \ \ stride\ \ s n×nf×f  padding   p     stride  s
图像n,核f,padding为p,stide为s,则得到的结果是
( n + 2 p − f s + 1 ) × ( n + 2 p − f s + 1 ) (\frac{n+2p-f}{s}+1)\times (\frac{n+2p-f}{s}+1) (sn+2pf+1)×(sn+2pf+1)向下取整。
吴恩达视频中一层中各中notation的总结
在这里插入图片描述
对于一个完整的例子,构建多层神经网络,此处明确一种趋势即,图像的尺寸是逐渐减小而filter的数量在不断增加,如图中绿色核紫色圈出的数值。对于参数的选取(f,p,s)是构建网络的繁琐的点。

典型的卷积神经网络有三层,
卷积层(Conv)、convolution
池化层(Pool)、pooling
全连接层(FC) fully connected

池化层

直观理解:分块计算max,最大化操作的目的是,在过滤器中提取到某个特征时保留其最大值,池化层同样是用一个filter,类似于卷积层的filter,计算输出尺寸的公式依然适用。
池化过程中没有参数需要学习。

全连接层

一个更完整的示例
在这里插入图片描述
将一个卷积层和一个池化层作为一个layer,最后得到的三维矩阵转化成一个一维很长的矩阵,然后就是全连接层,变成前面的内容了,通过参数w减小特征的数量,以识别数字为例,最后通过softmax得到10个输出。

回到pytorch的课程,在pytorch实现卷积层

import torch

in_channels, out_channels = 5, 10
#输出通道是kernel的数量

width, height = 100, 100
kernel_size = 3 #卷积核的尺寸
batch_size = 1

input = torch.randn(batch_size, in_channels, width, height)

conv_layer = torch.nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size)

output = conv_layer(input)

print(input.shape)
print(output.shape)
print(conv_layer.weight.shape)

因此MNIST手写识别中的net可以改写为卷积层+池化层+全连接层,只需改变Net的定义,其他不变可直接训练

class Net(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5) #卷积层1
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5) #卷积层2
        self.pooling = torch.nn.MaxPool2d(2) #池化
        self.fc = torch.nn.Linear(320, 10)  #全连接
        self.Relu = torch.nn.ReLU()    #relu

    def forward(self, x):
        batch_size = x.size(0)
        x = self.Relu(self.pooling(self.conv1(x)))
        x = self.Relu(self.pooling(self.conv2(x)))
        x = x.view(batch_size, -1)
        x = self.fc(x)
        return x


model = Net()

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)  #放到GPU上计算

第十一讲 卷积神经网络(高级)

卷积神经网络除了串联,也可以分支,如GoogleNet
在这里插入图片描述

依然来到吴恩达的机器学习

ResNet残差网络
在这里插入图片描述
可跳跃(skip)

完成一个多分支的inception,类代码如下:

class InceptionA(torch.nn.Module):
    def __init__(self, in_channels):
        super().__init__()
        self.branch1x1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1) #实现1x1的kernel
        self.branch5x5_1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)  #5x5的kernel
        self.branch5x5_2 = torch.nn.Conv2d(16, 24, kernel_size=5, padding=2)

        self.branch3x3_1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1) #3x3的kernel
        self.branch3x3_2 = torch.nn.Conv2d(16, 24, kernel_size=3, padding=1)
        self.branch3x3_3 = torch.nn.Conv2d(24, 24, kernel_size=3, padding=1)

        self.branch_pool = torch.nn.Conv2d(in_channels, 24, kernel_size=1)  #池化

    def forward(self, x):
        branch1x1 = self.branch1x1(x)

        branch5x5 = self.branch5x5_1(x)
        branch5x5 = self.branch5x5_2(branch5x5)

        branch3x3 = self.branch3x3_1(x)
        branch3x3 = self.branch3x3_2(branch3x3)
        branch3x3 = self.branch3x3_3(branch3x3)

        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
        branch_pool = self.branch_pool(branch_pool)

        outputs = [branch1x1, branch5x5, branch3x3, branch_pool]
        return torch.cat(outputs, dim=1) #按照第一个维度进行拼接

在Net类里就要增加Inception的操作

class Net(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
        self.incep1 = InceptionA(in_channels=10)  #

        self.conv2 = torch.nn.Conv2d(88, 20, kernel_size=5)  #这里88是由incep1输出的tensor的长度
        self.incep2 = InceptionA(in_channels=20)

        self.pooling = torch.nn.MaxPool2d(2)
        self.fc = torch.nn.Linear(1408, 10)  #1408是最后输出的长度
        self.Relu = torch.nn.ReLU()

    def forward(self, x):
        batch_size = x.size(0)
        x = self.Relu(self.pooling(self.conv1(x)))
        x = self.incep1(x)
        x = self.Relu(self.pooling(self.conv2(x)))
        x = self.incep2(x)
        x = x.view(batch_size, -1)
        x = self.fc(x)
        return x

最后优化后准确率达到98%
在这里插入图片描述
对于ResNetBlock,可以用来避免梯度消失的问题。

class ResidualBlock(torch.nn.Module):
    def __init__(self, channels):    #Res需要保证输入输出的通道数相同,可将其作为参数传入
        super().__init__()
        self.channels = channels
        self.conv1 = torch.nn.Conv2d(channels, channels, kernel_size=3, padding=1)
        self.conv2 = torch.nn.Conv2d(channels, channels, kernel_size=3, padding=1)
        self.Relu = torch.nn.ReLU()

    def forward(self, x):
        y = self.Relu(self.conv1(x))
        y = self.conv2(y)
        return self.Relu(x+y)  #将x和经过两层之后的结果相加


使用ResNet后可将准确率提升到99%
在这里插入图片描述

第十二讲 循环神经网络(RNN)

处理带有序列模式的数据
某个数据依赖于前一个数据
如:自然语言
o = 1 4 ∑ i = 1 4 z i = 1 4 ∑ i = 1 4 3 ( x i + 2 ) 2 o=\frac14\sum_{i=1}^4z_i=\frac14\sum_{i=1}^43(x_i+2)^2 o=41i=14zi=41i=143(xi+2)2 所以 ∂ o ∂ x i ∣ x i = 1 = 9 2 = 4.5 \frac{\partial{o}}{\partial{x_i}}\bigr\rvert_{x_i=1}=\frac{9}{2}=4.5 xio xi=1=29=4.5

数学上,如果有一个函数值和自变量都为向量的函数
, 那么
关于
的梯度就是一个雅可比矩阵(Jacobian matrix): J = ( ∂ y 1 ∂ x 1 ⋯ ∂ y 1 ∂ x n   ⋮ ⋱ ⋮   ∂ y m ∂ x 1 ⋯ ∂ y m ∂ x n ) J=\left(\begin{array}{ccc} \frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{1}}{\partial x_{n}}\ \vdots & \ddots & \vdots\ \frac{\partial y_{m}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}} \end{array}\right) J=(x1y1xny1  x1ymxnym) 而torch.autograd这个包就是用来计算一些雅克比矩阵的乘积的。例如,如果
是一个标量函数的
的梯度: v = ( ∂ l ∂ y 1 ⋯ ∂ l ∂ y m ) v=\left(\begin{array}{ccc}\frac{\partial l}{\partial y_{1}} & \cdots & \frac{\partial l}{\partial y_{m}}\end{array}\right) v=(y1lyml) 那么根据链式法则我们有
关于
的雅克比矩阵就为: v J = ( ∂ l ∂ y 1 ⋯ ∂ l ∂ y m ) ( ∂ y 1 ∂ x 1 ⋯ ∂ y 1 ∂ x n   ⋮ ⋱ ⋮   ∂ y m ∂ x 1 ⋯ ∂ y m ∂ x n ) = ( ∂ l ∂ x 1 ⋯ ∂ l ∂ x n ) v J=\left(\begin{array}{ccc}\frac{\partial l}{\partial y_{1}} & \cdots & \frac{\partial l}{\partial y_{m}}\end{array}\right) \left(\begin{array}{ccc} \frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{1}}{\partial x_{n}}\ \vdots & \ddots & \vdots\ \frac{\partial y_{m}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}} \end{array}\right)=\left(\begin{array}{ccc}\frac{\partial l}{\partial x_{1}} & \cdots & \frac{\partial l}{\partial x_{n}}\end{array}\right) vJ=(y1lyml)(x1y1xny1  x1ymxnym)=(x1lxnl)
让我们再次回到本节的房价预测问题。如果我们对训练数据集里的3个房屋样本(索引分别为1、2和3)逐一预测价格,将得到 y ^ ( 1 ) = x 1 ( 1 ) w 1 + x 2 ( 1 ) w 2 + b ,   y ^ ( 2 ) = x 1 ( 2 ) w 1 + x 2 ( 2 ) w 2 + b ,   y ^ ( 3 ) = x 1 ( 3 ) w 1 + x 2 ( 3 ) w 2 + b . \begin{aligned} \hat{y}^{(1)} &= x_1^{(1)} w_1 + x_2^{(1)} w_2 + b,\ \hat{y}^{(2)} &= x_1^{(2)} w_1 + x_2^{(2)} w_2 + b,\ \hat{y}^{(3)} &= x_1^{(3)} w_1 + x_2^{(3)} w_2 + b. \end{aligned} y^(1)=x1(1)w1+x2(1)w2+b, y^(2)=x1(2)w1+x2(2)w2+b, y^(3)=x1(3)w1+x2(3)w2+b.

广义上讲,当数据样本数为 n
,特征数为 d
时,线性回归的矢量计算表达式为 y ^ = X w + b \boldsymbol{\hat{y}} = \boldsymbol{X} \boldsymbol{w} + b y^=Xw+b 其中模型输出
批量数据样本特征
,权重
, 偏差
。相应地,批量数据样本标签
。设模型参数
,我们可以重写损失函数为 ℓ ( θ ) = 1 2 n ( y ^ − y ) ⊤ ( y ^ − y ) \ell(\boldsymbol{\theta})=\frac{1}{2n}(\boldsymbol{\hat{y}}-\boldsymbol{y})^\top(\boldsymbol{\hat{y}}-\boldsymbol{y}) (θ)=2n1(y^y)(y^y)

小批量随机梯度下降的迭代步骤将相应地改写为 θ ← θ − η ∣ B ∣ ∑ i ∈ B ∇ θ ℓ ( i ) ( θ ) , \boldsymbol{\theta} \leftarrow \boldsymbol{\theta} - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \nabla_{\boldsymbol{\theta}} \ell^{(i)}(\boldsymbol{\theta}), θθBηiBθ(i)(θ),

其中梯度是损失有关3个为标量的模型参数的偏导数组成的向量: ∇ θ ℓ ( i ) ( θ ) = [ ∂ ℓ ( i ) ( w 1 , w 2 , b ) ∂ w 1   ∂ ℓ ( i ) ( w 1 , w 2 , b ) ∂ w 2   ∂ ℓ ( i ) ( w 1 , w 2 , b ) ∂ b ] = [ x 1 ( i ) ( x 1 ( i ) w 1 + x 2 ( i ) w 2 + b − y ( i ) )   x 2 ( i ) ( x 1 ( i ) w 1 + x 2 ( i ) w 2 + b − y ( i ) )   x 1 ( i ) w 1 + x 2 ( i ) w 2 + b − y ( i ) ] = [ x 1 ( i )   x 2 ( i )   1 ] ( y ^ ( i ) − y ( i ) ) \nabla_{\boldsymbol{\theta}} \ell^{(i)}(\boldsymbol{\theta})= \begin{bmatrix} \frac{ \partial \ell^{(i)}(w_1, w_2, b) }{\partial w_1} \ \frac{ \partial \ell^{(i)}(w_1, w_2, b) }{\partial w_2} \ \frac{ \partial \ell^{(i)}(w_1, w_2, b) }{\partial b} \end{bmatrix} = \begin{bmatrix} x_1^{(i)} (x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}) \ x_2^{(i)} (x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}) \ x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)} \end{bmatrix}= \begin{bmatrix} x_1^{(i)} \ x_2^{(i)} \ 1 \end{bmatrix} (\hat{y}^{(i)} - y^{(i)}) θ(i)(θ)=[w1(i)(w1,w2,b) w2(i)(w1,w2,b) b(i)(w1,w2,b)]=[x1(i)(x1(i)w1+x2(i)w2+by(i)) x2(i)(x1(i)w1+x2(i)w2+by(i)) x1(i)w1+x2(i)w2+by(i)]=[x1(i) x2(i) 1](y^(i)y(i))

为了进一步提升计算效率,我们通常对小批量数据做矢量计算。广义上讲,给定一个小批量样本,其批量大小为 n n n,输入个数(特征数)为 d d d,输出个数(类别数)为 q q q。设批量特征为 X ∈ R n × d \boldsymbol{X} \in \mathbb{R}^{n \times d} XRn×d。假设softmax回归的权重和偏差参数分别为 W ∈ R d × q \boldsymbol{W} \in \mathbb{R}^{d \times q} WRd×q b ∈ R 1 × q \boldsymbol{b} \in \mathbb{R}^{1 \times q} bR1×q。softmax回归的矢量计算表达式为

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值