总结了些网上的好文链接,同时将个人觉得最重要的记录了下。
《半小时学会卷积神经网络》:先读这篇文章,里面不懂的可以单独查资料,也可以用下方心得中的链接。
- 局部连接(1x1的卷积核可以看作特殊的全连接;全连接也可以看作特殊的卷积)+权值共享。 两者的目的都是减少参数量。
- 一定要深刻理解卷积核的概念(其实就是卷积层尺寸计算中的权重矩阵,经过不同卷积核卷积后效果也不一样),同时理解卷积层尺寸的计算原理以及特殊的1x1卷积核(1x1卷积一般只改变输出通道数(channels),而不改变输出的宽度和高度)。
具体参考1、《CNN中卷积层的计算例子》:写得非常简洁明了,卷积层尺寸的计算原理、标准卷积计算举例、1 x 1 卷积计算举例、全连接层计算举例、TensorFlow 中卷积层的简单实现。 2、《卷积核的基本原理》:公众号文章,也很细致。 3、《一文读懂卷积神经网络中的1x1卷积核》:里面有例子为什么说“1x1的卷积核可以看作特殊的全连接”。
1、作用?逐渐降低网络的空间尺寸,达到减少网络中参数的数量,减少计算资源的使用的目的,同时也能有效地控制过拟合。
2、池化层为什么有效?图片特征具有局部不变性,也就是说,即便通过下采样也不会丢失图片拥有的特征。由于这种特性,可以将图片缩小再进行卷积处理,这样能够大大地降低卷积计算的时间。最常用的池化层尺寸是2x2,滑动步长为2,对图像进行下采样,将其中75%的信息丢弃,选择其中最大的保留下来,这样也达到去除一些噪声信息的目的。
1、作用?卷积与池化只提取到了局部特征,全连接层就是将局部特征进行融合。
2、例子?通过卷积和池化层提取出来的特征有眼睛鼻子和嘴巴,那我们能单独通过这三个特征来判断出这是一只猫吗?显然不能,因为拥有眼睛鼻子嘴巴这三个特征的动物太多了吧,所以我们需要对这三个特征进行特征融合,从而最终判断出这个东东是一只猫猫而不是修狗。
3、卷积和全连接在算法上是可以转换的。通常情况下,在进行全连接的计算时,可以把它等效于卷积核为1x1的卷积运算。
参考:《全连接层与softmax》
1、作用?分类。
1、如何分类?分类不是根据分数,而是概率。
2、概率怎么来?Softmax把得分转换为概率。
3、得分怎么来?神经网络经过了几十层卷积运算计算出来的。
4、Softmax为何选取e为底? 扩大差距
参考: 《全连接层与softmax》
5、Softmax其实就是激活函数。Softmax函数通常被描述为多个sigmoid的组合。我们知道sigmoid返回0到1之间的值,可将函数值视为数据点属于特定类的概率。因此,sigmoid被广泛应用于二分类问题,softmax函数可用于多类分类问题。激活函数分线性函数和非线性函数,非线性激活函数主要作用是提供网络的非线性建模能力。如果没有激活函数,那么该网络仅能够表达线性映射,此时即便有再多的隐藏层,其整个网络跟单层神经网络也是等价的。
关于激活函数可以参考《深度学习-为什么用激活函数》:解释得很直白,尤其是为何要用非线性的激活函数。《独家 | 深度学习基础——激活函数以及什么时候使用它们?(附代码)》:解释了大部分激活函数,以及为啥要衍生出这么多激活函数。《神经网络前向和反向传播的可视化》:有前向和反向传播的可视化部分。
参考文见上面的“Softmax”即可。
《深度学习中正则化的理解》:比较直白、宽泛地讲了正则化,框架清晰。下方心得均来自此篇文章。
《深度学习中Dropout层作用》:讲清了Dropout为啥能防止过拟合,同时说明了其过程,附有相应代码。
1、其实就是正则化的一种。正则化的英文为Regularization,直译为“规则化”,即通过给模型增加“规则、限制”,从而使模型具有较强的泛化能力,防止过拟合。
2、在深层神经网络中,理论上只要层数够大,每一层的神经元数量够多,则该深层神经网络完美拟合任意数据集。但是如果深层神经网络模型真的完全拟合了训练集的所有数据,则必然对测试集导致过拟合。正则化的目的是避免过拟合,因此正则化的思路可以概括为:通过一定手段使神经网络中的部分神经元关闭,从而降低神经网络的复杂程度,进而避免过拟合。
3、常见的正则化方法包括:L0正则化、L1正则化、L2正则化(最常用)、dropout正则化。
除此之外,还有数据扩增、早停法(early stopping)等,由于也可以起到防止过拟合的作用,也被归类为正则化方法
4、Dropout是一个超参,需要根据具体的网路,具体的应用领域进行尝试。
1、《深度学习入门-反向传播(一)推导》:从计算图的角度解释了,如何进行反向传播推导的,从最初简单的+和*,再到后面的Relu、Sigmoid的推导。
2、《《深度学习入门》第5章实战:手写数字识别——误差反向传播》:与上面那篇区别就是多了个代码实践。
3、《前向传播、反向传播——通俗易懂》:在读完1、2基础上再去理解,就很好理解了。注意一次完整的权重更新时,用到的还是上次的数据。例如更新w1时,用到的是原来的w5的数据。还要注意为什么更新权重的公式长那样,因为梯度方向为上升最快的方向,那要下降最快,自然要用“——”。同时附上自己对应的手推图。
4、《梯度下降、反向传播、学习率 α 、优化器、神经网络一般流程代码实践》:此篇文章力荐,现附在下面:
1、反向传播 是 求解损失函数关于各个参数的梯度的一种方法。(求梯度【偏导数】)
2、梯度下降 是 根据反向传播计算得到的梯度(偏导)来更新各个权重W,使损失函数极小值的一种方法。(使权重W更好)
学习率 α 是梯度下降中权重更新公式的一部分。
备注:我认为:学习率 == 步长
梯度下降属于优化器的一种,优化器就是使使损失函数极小值的一种方法,它里面也包含学习率。
在机器学习、深度学习中使用的优化算法除了常见的梯度下降,还有 Adam,Adagrad,RMSProp 等几种优化器
理解了上面的内容后,我们便知道了整个神经网络的训练实现过程分为5步:
前向传播得到预测值 --> 求预测值与真实值的损失 --> 优化器梯度清零(可选操作) --> 利用反向传播求所有参数的梯度(导数) --> 优化器更新权重W
# Gradient Descent
for epoch in range(50):
# Forward pass: Compute predicted y by passing x to the model
y_pred = model(x)
# Compute and print loss
loss = criterion(y_pred, y)
print('epoch: ', epoch,' loss: ', loss.item())
# Zero gradients, perform a backward pass, and update the weights.
optimizer.zero_grad()
# perform a backward pass (backpropagation)
loss.backward()
# Update the parameters
optimizer.step()
备注
:这里的 optimizer.zero_grad() 是梯度清零操作,需要的内存较大,如果使用“梯度累加”操作的话:在内存大小不够的情况下叠加多个batch的grad作为一个大batch进行迭代,因为这个和大batch_size得到的梯度是等价的,但是效果自然是差一些,这个可以说是增大batch-size减少内存”的一个小trick吧。
Keras:
PyTorch:
关于两者更详细介绍及优缺点对比,参考:《Keras与PyTorch全方位比较 哪一个深度学习框架更适合初学者?》
储备知识:全连接层在keras中叫做Dense层,正在pytorch中交Linear层
这里以定义一个简单的CNN为例:
# Keras
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3))) # 第一层卷积+激活
model.add(MaxPool2D()) # 第二层池化
model.add(Conv2D(16, (3, 3), activation='relu')) # 第三层卷积+激活
model.add(MaxPool2D()) # 第四层池化
model.add(Flatten()) # Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡
model.add(Dense(10, activation='softmax')) # Dense层,即全连接层,同时有个softmax
# Pytorch
import torch
import numpy
from torchvision import transforms #处理图像
from torchvision import datasets #处理数据集
from torch.utils.data import DataLoader #加载数据集
import torch.nn.functional as F #导入激活函数
import matplotlib.pyplot as plt
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 32, 3) # 卷积
self.conv2 = nn.Conv2d(32, 16, 3) # 卷积
self.pool = nn.MaxPool2d(2, 2) # 池化
self.fc1 = nn.Linear(16 * 6 * 6, 10) # Linear层,即全连接层
def forward(self, x):
x = self.pool(F.relu(self.conv1(x))) # 第一层的卷积+激活+池化
x = self.pool(F.relu(self.conv2(x))) # 第二次的卷积+激活+池化
x = x.view(-1, 16 * 6 * 6) # 将数据平展成一维
x = F.log_softmax(self.fc1(x), dim=-1) # 全连接+softmax
return x
model = Net()
备注:上述pytorch代码定义得一般般,看不懂地6.4的推荐文章。
用Keras训练模特超级简单!只需一个简单的.fit(),你就可以直接去跑步了。
history = model.fit_generator(
generator=train_generator,
epochs=10,
validation_data=validation_generator)
在Pytorch中训练模型包括以下几个步骤:
# 在数据集上循环多次、梯度下降
for epoch in range(2):
for i, data in enumerate(trainloader, 0):
# 获取输入; data是列表[inputs, labels]
inputs, labels = data
# (1) 初始化梯度,清零
optimizer.zero_grad()
'''
# Compute and print loss
loss = criterion(y_pred, y)
print('epoch: ', epoch,' loss: ', loss.item())
'''
# (2) 前向传播
outputs = net(inputs)
loss = criterion(outputs, labels)
# (3) 反向传播
loss.backward()
# (4) 计算损失并更新权重
optimizer.step()
光是训练就需要很多步骤!
1、pytorch:《CNN实现手写数字识别》:代码逻辑定义得非常好。
2、pytorch:《用MNIST数据集搭建简单卷积神经网络》:注意与上述代码的小不同。
3、keras:《【深度学习】运用mnist数据集实例化一个简单的卷积神经网络》:用keras实现,代码逻辑也蛮好。
4、tensorfolw:《在minst数据集上定义和训练CNN卷积神经网络,代码+原理+模型更改》:不推荐小白看。
参考:《机器学习中常见的评价指标总结》
评价指标是建立在不同的机器学习任务上的,主要分为三大类:分类、回归和无监督。
学习中遇到的分类任务中的评价指标有准确率(Accuracy)、TPR、FPR、Recall、Precision、F-score、MAP、ROC曲线和AUC等,回归任务中的指标有MSE、MAE等。
《一文搞懂RNN(循环神经网络)基础篇》
《RNN、DNN、LSTM》
RNN:
1.更好处理时间序列问题;
2.与全连接的区别,其实就多了个上一层传入的;
3.实现的是短期的记忆(由于RNN模型如果需要实现长期记忆的话需要将当前的隐含态的计算与前n次的计算挂钩,计算量会呈指数式增长,导致模型训练的时间大幅增加。在神经网络参数更新的时候容易出现梯度消失或者梯度爆炸的情况,当梯度消失时权重都没法更新了就相当于没法学习了,这样会导致神经网络不能很好的学习较长序列中的信息,因此RNN神经网络只具有短时的记忆)
4.为什么会梯度消失和爆炸。《RNN的梯度消失和梯度爆炸》:从深层网络和激活函数两个角度分别解释,力荐力荐力荐!!!
5.CNN的梯度消失与RNN不一样,RNN更容易梯度消失。因为RNN时权重共享,但CNN的权重可以每层不一样,当反向传播时,即便出现了连乘,CNN可能出现抵消的情况。
循环神经网络中的隐状态h存储了历史信息,可以看做一种记忆。在简单的RNN模型中,h在每一个时刻都是改变的,都会被重写,因此可看作一种短期记忆。而在LSTM中,记忆单元c可以在某个时刻捕捉到某个关键信息,并有能力将此关键信息保存一定的时间间隔。记忆单元c中保存信息的生命周期要长于短期记忆,但又远远短于长期记忆,因此将LSTM称为长短期记忆(Long Short-Term Memory)
四个阶段:
1.遗忘门:决定丢弃信息
2. 输入门: 确定更新的信息
3. 将过去与现在的记忆进行合并
4. 输出门
RNN的多种结构:
1.one-to-one
2.n-to-n
3.one-to-n
4.n-to-one
5.Encoder-Decoder (n-to-m)
《一幅图真正理解LSTM、BiLSTM》:看了很多资料,这篇里面的图可以说是画得最清晰的,必看!!!
《深度学习笔记 9 循环神经网络(RNN、LSTM)》
《一文读懂长短期记忆网络(LSTM)》
RNN、LSTM、GRU的动图对比,一定要看:《超生动图解LSTM和GRU,一文读懂循环神经网络!》!!!
《Transformer 模型详解》
《https://blog.csdn.net/weixin_42118657/article/details/120164994》
但是前置知识要有:
1、RNN
2、seq2seq 、Encoder/Decoder
提出:
- Encoder-Decoder的提出——2014年(Bengio 团队):Cho et al., Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine
Translation- Seq2Seq的提出——2014年(谷歌):Sutskever et al., Sequence to Sequence Learning with Neural Networks
- attention在Encoder-Decoder中的应用——2014年(Bengio 团队):Bahdanau et al.,Neural Machine Translation by Jointly Learning to Align and
Translate
Encoder-Decoder 和 Seq2Seq的区别:
- Seq2seq是应用层面的概念,即序列到序列,强调应用场景。
- Encoder-decoder是网络架构层面的概念,特指同时具有encoder模块和decode模块的结构。
- encoder-decoder模型是一种应用于seq2seq问题的模型。 目前,Seq2Seq
- 使用的具体方法基本都属于Encoder-Decoder 模型的范畴。
《什么是Encoder-Decoder、Seq2Seq、Attention?》:总结了不少,最重要的是图画得很好,且里面提到了篇微信文章《动画图解Attention机制,让你一看就明白》
《深度学习三:SeqtoSeq》:本质上注意力机制是计算权重的过程!!!
3、注意力机制
《一文读懂注意力机制》:非常详细的一篇教程,必看!!!
《注意力机制详述》:软性注意力(Soft Attention)机制是指在选择信息的时候,不是从N个信息中只选择1个,而是计算N个输入信息的加权平均(雨露均沾),再输入到神经网络中计算。相对的,硬性注意力(Hard Attention)就是指选择输入序列某一个位置上的信息,比如随机选择一个信息或者选择概率最高的信息。但一般还是用软性注意力机制来处理神经网络的问题。
在软注意力Encoder-Decoder模型中,更具体地来说,在英-中机器翻译模型中,输入序列和输出序列的内容甚至长度都是不一样的,注意力机制是发生在编码器和解码器之间,也可以说是发生在输入句子和生成句子之间。而自注意力模型中的自注意力机制则发生在输入序列内部,或者输出序列内部,可以抽取到同一个句子内间隔较远的单词之间的联系,比如句法特征(短语结构)
残差连接,residual connection、skip connection、shortcut connection。。。。这类词汇实际上含义基本是一样的,很多时候是互相使用的,就类似于一个人的身份证姓名和他的小名,不用太过严格的去做区分,所以下文统一使用residual connection来描述。
《Skip Connection——提高深度神经网络性能的利器》
一、Skip Connection是什么?
Skip Connection(跳跃连接),是一种在深度神经网络中连接不同层次之间节点的方法。在传统的神经网络中,信号从输入层传输到输出层,每个隐藏层的输出都需要经过激活函数处理后再传输到下一层,而Skip Connection会将当前层的信号同时向后传输到更深层次的下一层,也就是“跳过”了中间的层次。而这种跨层的连接方式,可以加速信息传输、避免梯度消失,并且保留更多的信息。
二、Skip Connection的优点
对于深度神经网络而言,Skip Connection的优点如下:
1、解决梯度消失问题
随着神经网络层数的增加,梯度消失的问题更加严重,导致深层次的节点很难得到有效的更新,甚至训练过程会完全停滞。而Skip Connection可以保留更多的信息,使得梯度可以通过跨层连接在不同的层次之间传播,从而有效地解决梯度消失问题。
2、加速模型训练
由于Skip Connection允许信号直接传输到更深层次的下一层,而不必经过中间的层次,从而可以缩短神经网络的传输路径,加速信息的传输速度以及整个神经网络的训练速度。
3、提高模型的泛化能力
在一些深度神经网络的训练中,由于训练集与测试集的差异,造成了过拟合的现象。通过加入Skip Connection,可以让更多的信息有机会被保留下来,从而增强模型的泛化能力,降低过拟合的风险。
三、如何使用Skip Connection?
下面是一个使用Skip Connection的例子:
import tensorflow as tf
def conv_block(input_tensor, filters, strides=(2, 2), activation='relu'):
x = tf.keras.layers.Conv2D(filters, (3, 3), strides=strides, padding='same')(input_tensor)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.Activation(activation)(x)
x = tf.keras.layers.Conv2D(filters, (3, 3), padding='same')(x)
x = tf.keras.layers.BatchNormalization()(x)
skip = tf.keras.layers.Conv2D(filters, (1, 1), strides=strides, padding='same')(input_tensor)
skip = tf.keras.layers.BatchNormalization()(skip)
x = tf.keras.layers.Add()([x, skip])
x = tf.keras.layers.Activation(activation)(x)
return x
inputs = tf.keras.layers.Input(shape=(32, 32, 3))
x = conv_block(inputs, 32)
x = conv_block(x, 64)
x = conv_block(x, 128)
x = conv_block(x, 256)
x = tf.keras.layers.GlobalAveragePooling2D()(x)
outputs = tf.keras.layers.Dense(10, activation='softmax')(x)
model = tf.keras.models.Model(inputs, outputs)
model.summary()
四、Skip Connection的变种
Skip Connection还有一些变种,主要有以下两种:
1、Residual Connection
Residual Connection是Skip Connection的一种专用形式,由He等人在ResNet中首次提出。这种方法是为了解决深度神经网络训练中的退化问题(训练越深,准确率反而下降),它利用残差连接(residual connection)来构建深度网络。Residual Connection通过向前或向后输出残差(即当前特征图减去之前的特征图)实现信息的跨层传递,从而保持更多的信息,提高网络的准确率。
2、Dense Connection
Dense Connection是一种在DenseNet中提出的连接方式,即每个层都连接到所有后续层。Dense Connection强制前后两层强制建立全连接,使得前一层的特征全部被保留下来,加入当前层的输出中,从而更好地维持特征中的信息,避免特征的丢失,从而提高模型的精度。
五、总结
Skip Connection作为现代深度学习领域中一个重要的技术创新,可以帮助神经网络更好地学习特征和提高性能。通过合理地运用Skip Connection及其变种,我们可以获得更高的准确率、更快的训练速度和更强的泛化能力,为深度神经网络在各个领域的应用提供了更加坚实的基础。
参考链接《为什么残差连接的网络结构更容易学习?》:从“可解释性”说明了原因,最清楚的一版,力荐!
加入残差连接后:
残差连接residual connection,假设神经网络某一层对input x进行了一个F操作,变为F(x),那么正常的神经网络输出为F(x),而加入残差连接以后,输出为x+F(x)
那么残差结构有什么好处呢?显而易见:因为增加了一项,那么该层网络对x求偏导的时候,多了一个常数项,所以在反向传播过程中,梯度连乘,也不会造成梯度消失。除此,还能增加训练的深度,提高模型的泛化能力。
具体可参考《bn层,skip/residual connection》
自编码器可以理解为一个试图去还原其原始输入的系统。
《【机器学习】自动编码器 - Autoencoder》
《生成式对抗网络的原理和实现方法》