layernorm,为什么layernorm在深度学习NLP下有效,batchnorm则不是?
layernorm,为什么layernorm在深度学习NLP下有效,batchnorm则不是?详细介绍
本文目录一览: 为什么layernorm在深度学习NLP下有效,batchnorm则不是?
Layer normalization (layernorm) 和 batch normalization (batchnorm) 都是用来解决神经网络训练时的梯度爆炸和消失问题的一种技术。在这两种方法中,layernorm 通常更适合在深度学习中自然语言处理(NLP)的任务中使用。这是因为,在 NLP 任务中,每个样本的长度通常都不一样,因此使用 layernorm 来对每个神经元的输入进行标准化(即,使输入的均值为0,方差为1)可能更有效。而在使用 batchnorm 时,由于每个 mini-batch 中的样本数量通常是固定的,因此如果在 NLP 任务中使用 batchnorm 的话,那么就会有一些样本会被忽略,从而导致效果不佳。
batch norm和layer norm
https://zhuanlan.zhihu.com/p/86765356
计算batch个μ和batch个σ
我以前一直以为是对seq轴上做类似于batch norm的操作,结果是hidden轴上。
例如,input是[ batch × seq_len × hidden ],则layer norm首先在hidden维度求出batch × seq_len个标准差和均值,再使用它们进行归一化,但γ和β只有hidden个,因此LayerNorm归一化之后的缩放是再特征维度上进行。
Batch Normalization,它去除了不同特征之间的大小关系,但是保留了不同样本间的大小关系,所以在CV领域用的多。
Layer Normalization,它去除了不同样本间的大小关系,但是保留了一个样本内不同特征之间的大小关系,所以在NLP领域用的多。
1)layer normalization 有助于得到一个球体空间中符合0均值1方差高斯分布的 embedding, batch normalization不具备这个功能。
理解Bert
在圈内,Bert是指喜欢挑战主人的sub,这类sub是喜欢用不顺从的方式吸引到S的注意,从而获得更多的关注。印聊
离开深度学习瞎折腾了一段时间后,我终于又回来了。
于是赶紧回顾了下18年之后NLP的发展,基本就是将迁移学习更广泛的用于NLP领域,以及把17年年底的《Attention is all you need》里的思想给发扬光大了,ELMO弥补了传统word2vec多义词表示的不足,GPT使用更强大的特征提取器Transformer取代LSTM,Bert使用双向Transformer进一步改进了GPT成为这两年发展的集大成者。
从Bert模型所带来的NLP界里程碑式的影响和所取得的成就来看,无疑Bert将会是未来两三年NLP应用发展的基石,于是有必要仔细的看看其模型的结构,数据是如何流动的,训练的和测试的。
不得不说现在的学习环境相对几年前好太多了,本文主要参考了以下几篇文章,然后加了点自己的理解:
Dissecting BERT Part 1: The Encoder
The Illustrated Transformer
Dissecting BERT Appendix: The Decoder
它的总体框架同lstm时代的MNT或者是attention is all you need中的 transformer 一样的 encoder-decoder 结构:
我们先来介绍一下Encoder部分。
为了理解这个架构,我们使用一个简单的具体的例子,来看一下 输入 的数据是怎么通过 encoder 一步一步变化让后到 输出 的。
bert的词嵌入由三个嵌入token embedding、segment embedding,和position embedding叠加而成。
这个过程跟以往的RNNs没什么区别,比如给定一个句子:
第一步是先将其标记化:
然后是数字化,将每个标记映射到语料词汇表中的唯一整数编号:
接下来就是得到序列中每个词的词嵌入,也就是将整数映射到一个 维的向量,这个向量是模型在训练时学习的,你可以将其视为一个查表的过程,这些向量的元素作为模型的参数,像其他权重一样通过反向传播进行了优化。
在论文中是使用WordPiece tokenization 来将英文单词转换成768( )维的向量,转化的过程类似这样:
把每个词的向量放到一起,就得到了一个 句子长度x向量维度 ( ) 尺寸的矩阵 Z :
说明一点,我们通常使用 填充 的方式来让输入序列具有相同的长度,比如通过添加"
" 标记来增加某些序列的长度,还是前面的例子,填充后可能变为:
如果设定 设定为9,那我们就把句子从5填充到了9。
但是,上面的embedding并没有包含词的位置信息。于是,我们的目标是能够根据词在句子中的位置适当调整这个向量,使它带上位置信息。
作者选择的方法是使用预定的(非学习的)正余弦函数将 之间的数字加到前面的embedding中,即通过正余弦函数将位置表示为彼此的线性组合,从而实现网络学习中标记位置之间的相对关系。在Token embedding 获得的矩阵 的基础上加上位置矩阵 。
数学上,用 表示序列中标记的位置,用 表示token embedding特征向量中的位置:
具体来说,对于给定的句子 ,其位置嵌入矩阵为:
作者解释说,使用这种确定性方法的结果和学习位置表示(就像我们对词嵌入那样)的结果差不多,因此这样反而会有一些优势:
因此,添加了位置信息之后的矩阵是:
它是第一个encoder块的输入,尺寸是
共有N个编码器块连接在一起直到生成编码器的输出,特定的块负责查找输入表示之间的关系并将编码在其输出中。
直观地,通过这些块的迭代过程将帮助神经网络捕获输入序列中的词之间的更加复杂的关系,你可以把它理解成一个整体用来捕捉输入序列的语义。
encoder中使用Transformer的多头注意力机制,这意味着它将计算 份不同权重矩阵的自注意力,然后将结果连接在一起。
这些并行注意力计算的结果称之为Head,我们用下标 来表示一个特定的head和相关的权重矩阵。
如上图所示,一旦计算了所有head,它们将被连接起来,得到一个尺寸为 的矩阵,然后将它乘以一个尺寸为 的权重矩阵 进行线性变换,就得到了一个尺寸为 的最终结果,用数学公式表示就是:
其中的 通过 乘以相应权重矩阵 获得,我们通过一个简单的例子来可视化的看一下这个过程。
这图描绘了输入标记通过 token embedding 和 positional encoding ,再输入到Encoder:
接下来,我们再来看下Encoder中的操作过程,先看一下单头的self-attention:
上图描绘了一个Head的 是怎么来的,其中的 的尺寸是 , 因为Q和K需要计算相似性,所以维度应当是相同的, 的尺寸是 , 的维度可以相同也可以不同,在论文中 .
所谓的自注意力,就是 与 的点积进行 的缩放之后通过softmax获得一个概率权重,然后用这些权重分别乘以各自的 即可:
为了加深理解,我们选择其中一个头,通过图形继续可视化的看一下这个变化过程:
然后计算self-attention,
多头的话就是同时有多个上述计算过程在进行:
假设我们有8个Head,那么我们就获得8个 :
但是,显然前馈层只需要一个矩阵 ,怎么处理呢?类似多卷积核的处理,把这8个矩阵连起来,乘以一个权重矩阵 压缩到一个矩阵。
为了有一个更加全面直观的认识,我们把上面整个过程放到一个图里,
显然,第二个encoder块是不需要embedding过程的,只要把第一个encoder块的输出作为输入即可。
经过上面的介绍,你应该对这个过程已经有了足够的了解,但是,为什么可以利用向量点积来计算注意力概率呢?
于是让我们进一步深入来了解其中的原理。
这个结构体系的关键在于:
也就是每个词的q向量与每个词的k向量的点积,套用点积公式:
这意味着 和 的方向越相似,长度越大,点积就越大。词与此之间关联越大,对于理解这个词时得到的关注越大,跟我们的本意是相同的。
我们再看一下最开头的结构示意图,每个encoder块在Multi-Head Attention之后经过一个 Add & Norm层才进入下一个块。于是我们来看一下这一层做了些什么。
Add 实际就是一个残差连接,将输出加上输入,这个在每一块的self-attenton以及FFN之后都会有,然后跟随一个Layer Norm 。
Norm 是一个Layer Normlization,将 正则化,就是把它缩放到一个均值为0方差为1的域里。因为
不过一般在这一层之前,就会有一个dropout层。
每个encoder块都由 mulit-head atteion add & Norm feed forword network add & Norm 这样一个过程,下面来介绍一下这个Feed-Forward Network。
这是一个全连接层,包含两个线性变化和一个非线性函数(实际一般就是ReLu),
对于输入的 (尺寸为 ) ,通过权重矩阵 (尺寸为 )和偏置 线性变换到隐藏层 (尺寸为 ) ,然后**ReLu **激活 ,记下来再用权重矩阵 (尺寸为 ) 和偏置 的线性变换到输出层(尺寸为 ) ,表示成数学公式就是:
在最后一个encoder块输出之后连接到decoder。
Decoder和Encoder的结构是类似的,但是因为可视信息的不同,又有所差别。
Transformer解决的是翻译的问题,将一个句子翻译成另一种语言,我们希望模型能够捕捉到输入句子中词之间的关系,并且将输入句子中包含的信息与每一步已翻译的内容结合起来。继续上面的例子,我们的目标是把一个句子从英文翻译为西班牙文,这是我们获得的序列标记:
我们同之前一样来看看输入到输出数据是如何流动的。
这是我们的解码器的输入标记:
然后这是解码器的期望输出:
但是,这里存在一个问题,比如输入这边我们已经看到了'como' 的后面是'estas', 然后再用它来预测'estas' ,这显然是不合理的,因为模型在测试的时候是看不到后面的词的。
因此,我们需要修改注意力层,防止模型可以看到预测词右边的信息,与此同时,它能利用已经预测的词,即左边的信息。
继续上面的例子,我们将输入标记转换成矩阵的形式,并添加位置信息:
和encoder一样,decoder块的输出也将是大小为 的矩阵,在逐行线性变换+softmax激活后,将生成一个举证,其中每行的最大元素表示下一个单词。也就是说,分配"
" 的行负责预测“Hola”, 分配"Hola"的行负责预测"," ...以此类推。比如,为了预测"estas", 我们将允许该行直接和下图中绿色区域互动,而不能和红色区域互动:
但是,在我们使用多头注意力机制的时候,所有的行都会产生交互,因此需要在输入的时候添加遮罩,这个遮罩会在注意力计算之后进行:
这是 self-attention 的计算结果:
然后我们在此基础上添加遮掩,就是把矩阵上三角的位置全部设置为 :
于是,在进行softmax激活之后,矩阵就变成了:
恰好达到了我们的要求,那些需要在训练时忽略的右侧的词的注意力全部变成了0。
当将这个注意力矩阵与 相乘时,预测的词就是模型可以访问元素右边的元素。注意,这里的多头注意力输出将是 维的,因为它的序列长度是 。
这个就是 Decoder 从 target序列 的输入,并经过 Masked Multi-Head Attention 的一个变化得到了 ,decoder的还有一部分输入来自于源语句经过 Encoder 的最终输出 (尺寸是 )。
接下来,就是与encoder一样的 Multi-Head Attention Add and Layer Norm -> FFN 的过程。
只不过,现在的 来自于 ,而 来自于 :
计算每个query相对于key的注意力之后,得到的是一个 的矩阵, 继续咱们的例子,比如注意力矩阵为:
如上图所见,这个注意力是当前Decoder输入与Encoder输出的每个词之间的注意力,咱们用这个矩阵再乘以 ,就得到了一个 的矩阵,每一行代表了源语句相对于当前输入词汇的特征:
h个Head连接起来,尺寸变为 ,它通过 的权重矩阵 线性变换到一个 的输出。
这在多个Decoder之后,最后输出的矩阵通过乘以权重矩阵 ( ) 进行线性变换,变换之后再对每一行的向量softmax, 其中选择值最大位置对应词表索引的词就是预测的词。
损失的话只需要用预测的每个词向量与真实的词的one-hot词表示计算交叉熵即可。
SurfaceFlinger
SurfaceFlinger服务是在System进程中启动的,并且负责统一管理设备的帧缓冲区。SurfaceFlinger服务在启动的过程中,会创建两个线程,其中一个线程用来监控控制台事件,而另外一个线程用来渲染系统的UI。在本文中,我们就将详细分析SurfaceFlinger服务的启动过程。
1、生成Vsync信号并分发
2、将app发来的buffer(界面数据)进行合成:根据各个界面的layer(就是Z值,由WindowManagerService来确定),把这些排序后的整体buffer传递给HardwareComposer(后简称HWC)。
3、提供图像绘制buffer,让APP可以有buffer进行图像绘制,通过gralloc模块向ashmen申请内存得到文件句柄fd,将fd通过binder机制传递给对应的app,app再执行mmap操作即可获得 对应的buffer。
4、APP对应一个client,一个SurfaceControl对应一个Layer,每个Surface都对应一个mslots数组(mslots数组中共有64个元素,每个元素中包含一个GraphicBuffer 和一个handle,包含fd 和 mmap的映射地址)。Surface获得Buffer的过程如下:
首先执行dequeueBuffer。若Surface无Buffer,则向生产者producer(GraphicBufferProducer类对象,最终通过SF操作)申请,查看mslots有无余项,若有直接返回,若无 则向Gralloc HAL申请,得到一个handle(要申请的Buffer的 句柄fd 和mmap的首地址的集合)
其次执行requestBuffer,APP(Client端)通过该方法将SF获得的handle 转移到Client端的handle中
APP获得fd,mmap获得地址(通过Gralloc HAL来执行mmap),接下来 向Buffer中写入内容即可
5、Slot数组的组成
Buffer fd
它要把各个surface 组合(compose/merge) 成一个main Surface ,最后将Main Surface 的内容发送给FB/V4l2 Output ,这样屏幕上就能看到我们想要的效果。 在实际中对这些Surface 进行merge 可以采用两种方式,一种就是采用软件的形式来merge ,还一种就是采用硬件的方式,软件的方式就是我们的SurfaceFlinger ,而硬件的方式就是Overlay 。
用于描述客户端,每个来请求服务的应用都对应一个Client
SurfaceFlinger为每个Client提供8m空间
提供了对窗口控制信息的操作,以及内容的处理SurfaceFlinger只是控制什么时候应该进程这些信息的处理以及处理的过程,所有实际的处理都是Layer中进程,可以理解为创建了一个Surface就是创建了一个Layer
创建 Layer 的过程,首先是由这个应用程序的 Client 根据应用程序的 pid 生成一个唯一的 layer ID ,然后根据大小,位置,格式啊之类的信息创建出 Layer 。在 Layer 里面有一个嵌套的 Surface 类,它主要包含一个 ISurfaceFlingerClient::Surface_data_t ,包含了这个 Surace 的统一标识符以及 buffer信息等,提供给应用程序使用。最后应用程序会根据返回来的 ISurface 信息等创建自己的一个 Surface 。
Android 提供了 4 种类型的 layer 供选择,每个 layer 对应一种类型的窗口,并对应这种窗口相应的操作:
Layer , LayerBlur , LayerBuffer ,LayerDim 。
Norm Layer 是 Android 种使用最多的一种 Layer ,一般的应用程序在创建 surface 的时候都是采用的这样的 layer ,了解 Normal Layer 可以让我们知道 Android 进行 display 过程中的一些基础原理。 Normal Layer 为每个 Surface 分配两个 buffer : front buffer 和 back buffer ,这个前后是相对的概念,他们是可以进行 Flip 的。 Front buffer 用于 SurfaceFlinger 进行显示,而 Back buffer 用于应用程序进行画图,当 Back buffer 填满数据 (dirty) 以后,就会 flip, back buffer 就变成了 front buffer 用于显示,而 front buffer 就变成了 back buffer 用来画图,这两个 buffer 的大小是根据 surface 的大小格式动态变化的
Android 实际上是通过计算每一个窗口的可见区域,就是我们在屏幕上可见的窗口区域 ( 用 Android的词汇来说就是 visibleRegionScreen ) ,然后将各个窗口的可见区域画到一个主 layer 的相应部分,最后就拼接成了一个完整的屏幕,然后将主 layer 输送到 FB 显示。
参考
https://blog.csdn.net/haigand/article/details/90489336
https://blog.n0texpecterr0r.cn/2019/07/26/%E3%80%90android%E3%80%91framework%E7%AC%94%E8%AE%B0-bufferqueue/
https://blog.csdn.net/vviccc/article/details/104466960
https://zhuanlan.zhihu.com/p/62813895
BufferQueue详解 原理
网上看到一个有问题的matlab神经网络程序,自己找不出错误,请大神帮忙看一下
程序没有明显问题。P、T均经过归一化,建立双隐层网络,训练(我认为没必要反复训练10次),最后用测试的p归一化,输出结果反归一化。过程没问题。我认为样本可能少了点,至少做10组吧,再试试。其实这就是一个最简单的BP神经网络的训练过程,你可以试试其他的函数拟合例子。我传的附件里的第二个案例,就是一个BP神经网络拟合的例子。
如何在Caffe中配置每一个层的结构
如何在Caffe中配置每一个层的结构
最近刚在电脑上装好Caffe,由于神经网络中有不同的层结构,不同类型的层又有不同的参数,所有就根据Caffe官网的说明文档做了一个简单的总结。
1. Vision Layers
1.1 卷积层(Convolution)
类型:CONVOLUTION
例子
layers {
name: "conv1"
type: CONVOLUTION
bottom: "data"
top: "conv1"
blobs_lr: 1 # learning rate multiplier for the filters
blobs_lr: 2 # learning rate multiplier for the biases
weight_decay: 1 # weight decay multiplier for the filters
weight_decay: 0 # weight decay multiplier for the biases
convolution_param {
num_output: 96 # learn 96 filters
kernel_size: 11 # each filter is 11x11
stride: 4 # step 4 pixels between each filter application
weight_filler {
type: "gaussian" # initialize the filters from a Gaussian
std: 0.01 # distribution with stdev 0.01 (default mean: 0)
}
bias_filler {
type: "constant" # initialize the biases to zero (0)
value: 0
}
}
}
blobs_lr: 学习率调整的参数,在上面的例子中设置权重学习率和运行中求解器给出的学习率一样,同时是偏置学习率为权重的两倍。
weight_decay:
卷积层的重要参数
必须参数:
num_output (c_o):过滤器的个数
kernel_size (or kernel_h and kernel_w):过滤器的大小
可选参数:
weight_filler [default type: 'constant' value: 0]:参数的初始化方法
bias_filler:偏置的初始化方法
bias_term [default true]:指定是否是否开启偏置项
pad (or pad_h and pad_w) [default 0]:指定在输入的每一边加上多少个像素
stride (or stride_h and stride_w) [default 1]:指定过滤器的步长
group (g) [default 1]: If g > 1, we restrict the connectivityof each filter to a subset of the input. Specifically, the input and outputchannels are separated into g groups, and the ith output group channels will beonly connected to the ith input group channels.
通过卷积后的大小变化:
输入:n * c_i * h_i * w_i
输出:n * c_o * h_o * w_o,其中h_o = (h_i + 2 * pad_h - kernel_h) /stride_h + 1,w_o通过同样的方法计算。
1.2 池化层(Pooling)
类型:POOLING
例子
layers {
name: "pool1"
type: POOLING
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 3 # pool over a 3x3 region
stride: 2 # step two pixels (in the bottom blob) between pooling regions
}
}
卷积层的重要参数
必需参数:
kernel_size (or kernel_h and kernel_w):过滤器的大小
可选参数:
pool [default MAX]:pooling的方法,目前有MAX, AVE, 和STOCHASTIC三种方法
pad (or pad_h and pad_w) [default 0]:指定在输入的每一遍加上多少个像素
stride (or stride_h and stride_w) [default1]:指定过滤器的步长
通过池化后的大小变化:
输入:n * c_i * h_i * w_i
输出:n * c_o * h_o * w_o,其中h_o = (h_i + 2 * pad_h - kernel_h) /stride_h + 1,w_o通过同样的方法计算。
1.3 Local Response Normalization (LRN)
类型:LRN
Local ResponseNormalization是对一个局部的输入区域进行的归一化(激活a被加一个归一化权重(分母部分)生成了新的激活b),有两种不同的形式,一种的输入区域为相邻的channels(cross channel LRN),另一种是为同一个channel内的空间区域(within channel LRN)
计算公式:对每一个输入除以
可选参数:
local_size [default 5]:对于cross channel LRN为需要求和的邻近channel的数量;对于within channel LRN为需要求和的空间区域的边长
alpha [default 1]:scaling参数
beta [default 5]:指数
norm_region [default ACROSS_CHANNELS]: 选择哪种LRN的方法ACROSS_CHANNELS 或者WITHIN_CHANNEL
2. Loss Layers
深度学习是通过最小化输出和目标的Loss来驱动学习。
2.1 Softmax
类型: SOFTMAX_LOSS
2.2 Sum-of-Squares / Euclidean
类型: EUCLIDEAN_LOSS
2.3 Hinge / Margin
类型: HINGE_LOSS
例子:
# L1 Norm
layers {
name: "loss"
type: HINGE_LOSS
bottom: "pred"
bottom: "label"
}
# L2 Norm
layers {
name: "loss"
type: HINGE_LOSS
bottom: "pred"
bottom: "label"
top: "loss"
hinge_loss_param {
norm: L2
}
}
可选参数:
norm [default L1]: 选择L1或者 L2范数
输入:
n * c * h * wPredictions
n * 1 * 1 * 1Labels
输出
1 * 1 * 1 * 1Computed Loss
2.4 Sigmoid Cross-Entropy
类型:SIGMOID_CROSS_ENTROPY_LOSS
2.5 Infogain
类型:INFOGAIN_LOSS
2.6 Accuracy and Top-k
类型:ACCURACY
用来计算输出和目标的正确率,事实上这不是一个loss,而且没有backward这一步。
3. 激励层(Activation / Neuron Layers)
一般来说,激励层是element-wise的操作,输入和输出的大小相同,一般情况下就是一个非线性函数。
3.1 ReLU / Rectified-Linear and Leaky-ReLU
类型: RELU
例子:
layers {
name: "relu1"
type: RELU
bottom: "conv1"
top: "conv1"
}
可选参数:
negative_slope [default 0]:指定输入值小于零时的输出。
ReLU是目前使用做多的激励函数,主要因为其收敛更快,并且能保持同样效果。
标准的ReLU函数为max(x, 0),而一般为当x > 0时输出x,但x <= 0时输出negative_slope。RELU层支持in-place计算,这意味着bottom的输出和输入相同以避免内存的消耗。
3.2 Sigmoid
类型: SIGMOID
例子:
layers {
name: "encode1neuron"
bottom: "encode1"
top: "encode1neuron"
type: SIGMOID
}
SIGMOID 层通过 sigmoid(x) 计算每一个输入x的输出,函数如下图。
3.3 TanH / Hyperbolic Tangent
类型: TANH
例子:
layers {
name: "encode1neuron"
bottom: "encode1"
top: "encode1neuron"
type: SIGMOID
}
TANH层通过 tanh(x) 计算每一个输入x的输出,函数如下图。
3.3 Absolute Value
类型: ABSVAL
例子:
layers {
name: "layer"
bottom: "in"
top: "out"
type: ABSVAL
}
ABSVAL层通过 abs(x) 计算每一个输入x的输出。
3.4 Power
类型: POWER
例子:
layers {
name: "layer"
bottom: "in"
top: "out"
type: POWER
power_param {
power: 1
scale: 1
shift: 0
}
}
可选参数:
power [default 1]
scale [default 1]
shift [default 0]
POWER层通过 (shift + scale * x) ^ power计算每一个输入x的输出。
3.5 BNLL
类型: BNLL
例子:
layers {
name: "layer"
bottom: "in"
top: "out"
type: BNLL
}
BNLL (binomial normal log likelihood) 层通过 log(1 + exp(x)) 计算每一个输入x的输出。
4. 数据层(Data Layers)
数据通过数据层进入Caffe,数据层在整个网络的底部。数据可以来自高效的数据库(LevelDB 或者 LMDB),直接来自内存。如果不追求高效性,可以以HDF5或者一般图像的格式从硬盘读取数据。
4.1 Database
类型:DATA
必须参数:
source:包含数据的目录名称
batch_size:一次处理的输入的数量
可选参数:
rand_skip:在开始的时候从输入中跳过这个数值,这在异步随机梯度下降(SGD)的时候非常有用
backend [default LEVELDB]: 选择使用 LEVELDB 或者 LMDB
4.2 In-Memory
类型: MEMORY_DATA
必需参数:
batch_size, channels, height, width: 指定从内存读取数据的大小
The memory data layer reads data directly from memory, without copying it. In order to use it, one must call MemoryDataLayer::Reset (from C++) or Net.set_input_arrays (from Python) in order to specify a source of contiguous data (as 4D row major array), which is read one batch-sized chunk at a time.
4.3 HDF5 Input
类型: HDF5_DATA
必要参数:
source:需要读取的文件名
batch_size:一次处理的输入的数量
4.4 HDF5 Output
类型: HDF5_OUTPUT
必要参数:
file_name: 输出的文件名
HDF5的作用和这节中的其他的层不一样,它是把输入的blobs写到硬盘
4.5 Images
类型: IMAGE_DATA
必要参数:
source: text文件的名字,每一行给出一张图片的文件名和label
batch_size: 一个batch中图片的数量
可选参数:
rand_skip:在开始的时候从输入中跳过这个数值,这在异步随机梯度下降(SGD)的时候非常有用
shuffle [default false]
new_height, new_width: 把所有的图像resize到这个大小
4.6 Windows
类型:WINDOW_DATA
4.7 Dummy
类型:DUMMY_DATA
Dummy 层用于development 和debugging。具体参数DummyDataParameter。
5. 一般层(Common Layers)
5.1 全连接层Inner Product
类型:INNER_PRODUCT
例子:
layers {
name: "fc8"
type: INNER_PRODUCT
blobs_lr: 1 # learning rate multiplier for the filters
blobs_lr: 2 # learning rate multiplier for the biases
weight_decay: 1 # weight decay multiplier for the filters
weight_decay: 0 # weight decay multiplier for the biases
inner_product_param {
num_output: 1000
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
bottom: "fc7"
top: "fc8"
}
必要参数:
num_output (c_o):过滤器的个数
可选参数:
weight_filler [default type: 'constant' value: 0]:参数的初始化方法
bias_filler:偏置的初始化方法
bias_term [default true]:指定是否是否开启偏置项
通过全连接层后的大小变化:
输入:n * c_i * h_i * w_i
输出:n * c_o * 1 *1
5.2 Splitting
类型:SPLIT
Splitting层可以把一个输入blob分离成多个输出blobs。这个用在当需要把一个blob输入到多个输出层的时候。
5.3 Flattening
类型:FLATTEN
Flattening是把一个输入的大小为n * c * h * w变成一个简单的向量,其大小为 n * (c*h*w) * 1 * 1。
5.4 Concatenation
类型:CONCAT
例子:
layers {
name: "concat"
bottom: "in1"
bottom: "in2"
top: "out"
type: CONCAT
concat_param {
concat_dim: 1
}
}
可选参数:
concat_dim [default 1]:0代表链接num,1代表链接channels
通过全连接层后的大小变化:
输入:从1到K的每一个blob的大小n_i * c_i * h * w
输出:
如果concat_dim = 0: (n_1 + n_2 + ... + n_K) *c_1 * h * w,需要保证所有输入的c_i 相同。
如果concat_dim = 1: n_1 * (c_1 + c_2 + ... +c_K) * h * w,需要保证所有输入的n_i 相同。
通过Concatenation层,可以把多个的blobs链接成一个blob。
5.5 Slicing
The SLICE layer is a utility layer that slices an input layer to multiple output layers along a given dimension (currently num or channel only) with given slice indices.
5.6 Elementwise Operations
类型:ELTWISE
5.7 Argmax
类型:ARGMAX
5.8 Softmax
类型:SOFTMAX
5.9 Mean-Variance Normalization
类型:MVN
6. 参考
Caffe
CNN推理优化系列之一:Filters pruning
CNN模型简化以减少参数数量及增加计算效率可分为两种主要方法:一类是设计参数更少、所需计算更少的CNN结构像MobileNet/SqueezeNet/ShuffleNet等;另一类则是在常规CNN模型(如VGG/Resnet/Inception v3 etc.) 之上进行参数Quantization,Binarization,以及filters或weights pruning以来减少原生CNN模型所需的参数数目及计算量,从而加快其计算速度,减少模型体积。
Filters pruning属于上面说的第二类方法。
下图是filters pruning的本质方法。一目了然,就是将每一个Weight tensor中不重要的output filters set去掉,并去掉与其相关联的下一层输入filters。
上述filters pruning方法可归纳为以下四个步骤:
上面也大致说明了我们是通过计算每组输入filter之上的L1-norm,然后来将那些具有较小L1-norm值的filters pruning掉。这么做看似说得过去,毕竟小的参数对最终其输出影响肯定愈小,所谓人微了自然言轻, 因此在选择时,忽略掉小人物的声音而重点听取大人物的看法确实能对我们正确决策某件事情提供捷径。
文章中,也有试着在算出所有的filters的L1-norm后pruning掉那些L1-norm值大的filters,或者随机地裁filters,而不论其L1-norm值大小,不过最终结果却表明还是如我们经验所假定的那样即裁L1-norm最小的 filters,最终所获得的accuracy loss最小。
显然这里无法逃避,我们肯定要有一个meta variable用来表明裁多少filters比较合适,而且最好是layer-wise的一个参数,毕竟每一层上面filters的L1-norm分布不同,有些层是某些寡头说了算,实行中央集权制管理, 而有些则是西方民主型,必须得每个filter都发光发热、建言献策决定下一层才行。
下图可表明VGG-16在CIFAR10上训练得到的模型不同层filters L1-norm分布及其可被裁filters份量而不过分减少整个模型accuracy loss之间的关系。
总结一下那就是不同的layer(模型的不同阶段,输入、输出feature maps大小不同,网络位置不同)具有迥然不同的filters L1-norm分布,需要特殊情况特殊处理。
有些Layers上的filters L1-norm分布非常不均(贫富差距大,大佬说了算),这时我们prun掉那些L1-norm小的filters,对最终的model accuracy影响并不大,有些还反而会有所提升(汗),当然是在pruning后再进行re-training得到的。 而有些layers上的filters L1-norm分布则非常平均(理想的大同社会吗?或者是当下日本所谓的橄榄球式社会财富结构?),这时若prun掉其中任意一些filters,都会使得整体模型的accuracy受到影响,有些甚至是大受影响。。
Okay..
有了以上信息后,我们的对策如下,(没错就是党一直告诉我们的办法,不同问题不同解决,实事求是。)
对那些分布不均的layers狠劲儿裁,反正那些L1-norm小的没啥用,不值得过多的资源耗在它们身上。 而对分布均匀的layer则小心裁,甚至不裁。有些layer我们裁了可能对model accuracy loss会有显著影响,但若影响尚能接受,而且裁后带来的计算效率明显提升,那么我们也可狠心将其裁掉。而有些layer则是硬骨头,我们稍动下它们,就翻脸无情地 将model accuracy给我们搞到最低,对这些狠角色,我们还是躲着点走好了,少动它们为妙。。
单个layer裁减时,我们要考虑是否应该考虑上一层被pruning layer对本layer的影响呢?其实有两种选择,要么考虑,要么就不考虑。 可由下图来看得出,无非就是在计算第j个输出filter set L1-norm S j 时是否考虑上个layer的pruning而已。
另外对于Residual block这种特殊结构,我们同样要具体问题具体分析。
对于residual模块有多个conv layer的情况,第一个conv layer无所谓,可以正常pruning,而第二个的oc数目多少则需要保证跟identity mapping出来的数目一致,同时也要保证它们裁减相同的filters(不然残差的表示就无法跟自已本家对得上了。。请 仔细考虑residual learning的含意。。)
共有两种方式:一种是将整个network的每一层layer都prun后再整体进行re-train;另外一种则是每prun一层layer或者一个stage的layers组合,就进行一轮retrain。 其优点缺点显而易见,第一种比较省时省力,第二种更加精耕细作,但也麻烦不少。
一般如果一个模型中要裁的layers大多是那种对model accuracy loss不敏感的那么可以使用第一种方法,不然若想裁得比较多(狠),而且想动那些对accuracy敏感的层,那么就得使用第二种方法了。
下面为作者使用Resnet56/Resnet-110/VGG16(在CIFAR10上)以及Resnet-34(在Imagenet上)分别使用pruning及re-training后得到的结果。
类不能支持Automation操作
下载一个kb2781514安装包,一切搞定!!
重新注册下以下文件,问题便解决了:
msscript.ocx
dispex.dll
vbscript.dll
scrrun.dll
urlmon.dll
注册方法为,在开始运行里面运行 regsvr32 msscript.ocx 以此类推,注册完后清理一下浏览器缓存之类的。
如何在Caffe中配置每一个层的结构
何Caffe配置每层结构 近刚电脑装Caffe由于神经中国络同层结构同类型层同参数所根据Caffe官中国说明文档做简单总结 1. Vision Layers 1.1 卷积层(Convolution) 类型:CONVOLUTION 例 layers { name: "conv1" type: CONVOLUTION bottom: "data" top: "conv1" blobs_lr: 1 # learning rate multiplier for the filters blobs_lr: 2 # learning rate multiplier for the biases weight_decay: 1 # weight decay multiplier for the filters weight_decay: 0 # weight decay multiplier for the biases convolution_param { num_output: 96 # learn 96 filters kernel_size: 11 # each filter is 11x11 stride: 4 # step 4 pixels between each filter application weight_filler { type: "gaussian" # initialize the filters from a Gaussian std: 0.01 # distribution with stdev 0.01 (default mean: 0) } bias_filler { type: "constant" # initialize the biases to zero (0) value: 0 } } } blobs_lr: 习率调整参数面例设置权重习率运行求解器给习率同偏置习率权重两倍 weight_decay: 卷积层重要参数 必须参数: num_output (c_o):滤器数 kernel_size (or kernel_h and kernel_w):滤器 选参数: weight_filler [default type: 'constant' value: 0]:参数初始化 bias_filler:偏置初始化 bias_term [default true]:指定否否启偏置项 pad (or pad_h and pad_w) [default 0]:指定输入每边加少像素 stride (or stride_h and stride_w) [default 1]:指定滤器步 group (g) [default 1]: If g > 1, we restrict the connectivityof each filter to a subset of the input. Specifically, the input and outputchannels are separated into g groups, and the ith output group channels will beonly connected to the ith input group channels. 通卷积变化: 输入:n * c_i * h_i * w_i 输:n * c_o * h_o * w_o其h_o = (h_i + 2 * pad_h - kernel_h) /stride_h + 1w_o通同计算 1.2 池化层(Pooling) 类型:POOLING 例 layers { name: "pool1" type: POOLING bottom: "conv1" top: "pool1" pooling_param { pool: MAX kernel_size: 3 # pool over a 3x3 region stride: 2 # step two pixels (in the bottom blob) between pooling regions } } 卷积层重要参数 必需参数: kernel_size (or kernel_h and kernel_w):滤器 选参数: pool [default MAX]:pooling目前MAX, AVE, STOCHASTIC三种 pad (or pad_h and pad_w) [default 0]:指定输入每遍加少像素 stride (or stride_h and stride_w) [default1]:指定滤器步 通池化变化: 输入:n * c_i * h_i * w_i 输:n * c_o * h_o * w_o其h_o = (h_i + 2 * pad_h - kernel_h) /stride_h + 1w_o通同计算 1.3 Local Response Normalization (LRN) 类型:LRN Local ResponseNormalization局部输入区域进行归化(激a加归化权重(母部)新激b)两种同形式种输入区域相邻channels(cross channel LRN)另种同channel内空间区域(within channel LRN) 计算公式:每输入除 选参数: local_size [default 5]:于cross channel LRN需要求邻近channel数量;于within channel LRN需要求空间区域边 alpha [default 1]:scaling参数 beta [default 5]:指数 norm_region [default ACROSS_CHANNELS]: 选择哪种LRNACROSS_CHANNELS 或者WITHIN_CHANNEL 2. Loss Layers 深度习通化输目标Loss驱习 2.1 Softmax 类型: SOFTMAX_LOSS 2.2 Sum-of-Squares / Euclidean 类型: EUCLIDEAN_LOSS 2.3 Hinge / Margin 类型: HINGE_LOSS 例: # L1 Norm layers { name: "loss" type: HINGE_LOSS bottom: "pred" bottom: "label" } # L2 Norm layers { name: "loss" type: HINGE_LOSS bottom: "pred" bottom: "label" top: "loss" hinge_loss_param { norm: L2 } } 选参数: norm [default L1]: 选择L1或者 L2范数 输入: n * c * h * wPredictions n * 1 * 1 * 1Labels 输 1 * 1 * 1 * 1Computed Loss 2.4 Sigmoid Cross-Entropy 类型:SIGMOID_CROSS_ENTROPY_LOSS 2.5 Infogain 类型:INFOGAIN_LOSS 2.6 Accuracy and Top-k 类型:ACCURACY 用计算输目标确率事实loss且没backward步 3. 激励层(Activation / Neuron Layers) 般说激励层element-wise操作输入输相同般情况非线性函数 3.1 ReLU / Rectified-Linear and Leaky-ReLU 类型: RELU 例: layers { name: "relu1" type: RELU bottom: "conv1" top: "conv1" } 选参数: negative_slope [default 0]:指定输入值于零输 ReLU目前使用做激励函数主要其收敛更快并且能保持同效 标准ReLU函数max(x, 0)般x > 0输xx <= 0输negative_slopeRELU层支持in-place计算意味着bottom输输入相同避免内存消耗 3.2 Sigmoid 类型: SIGMOID 例: layers { name: "encode1neuron" bottom: "encode1" top: "encode1neuron" type: SIGMOID } SIGMOID 层通 sigmoid(x) 计算每输入x输函数图 3.3 TanH / Hyperbolic Tangent 类型: TANH 例: layers { name: "encode1neuron" bottom: "encode1" top: "encode1neuron" type: SIGMOID } TANH层通 tanh(x) 计算每输入x输函数图 3.3 Absolute Value 类型: ABSVAL 例: layers { name: "layer" bottom: "in" top: "out" type: ABSVAL } ABSVAL层通 abs(x) 计算每输入x输 3.4 Power 类型: POWER 例: layers { name: "layer" bottom: "in" top: "out" type: POWER power_param { power: 1 scale: 1 shift: 0 } } 选参数: power [default 1] scale [default 1] shift [default 0] POWER层通 (shift + scale * x) ^ power计算每输入x输 3.5 BNLL 类型: BNLL 例: layers { name: "layer" bottom: "in" top: "out" type: BNLL } BNLL (binomial normal log likelihood) 层通 log(1 + exp(x)) 计算每输入x输 4. 数据层(Data Layers) 数据通数据层进入Caffe数据层整中国络底部数据自高效数据库(LevelDB 或者 LMDB)直接自内存追求高效性HDF5或者般图像格式硬盘读取数据 4.1 Database 类型:DATA 必须参数: source:包含数据目录名称 batch_size:处理输入数量 选参数: rand_skip:始候输入跳数值异步随机梯度降(SGD)候非用 backend [default LEVELDB]: 选择使用 LEVELDB 或者 LMDB 4.2 In-Memory 类型: MEMORY_DATA 必需参数: batch_size, channels, height, width: 指定内存读取数据 The memory data layer reads data directly from memory, without copying it. In order to use it, one must call MemoryDataLayer::Reset (from C++) or Net.set_input_arrays (from Python) in order to specify a source of contiguous data (as 4D row major array), which is read one batch-sized chunk at a time. 4.3 HDF5 Input 类型: HDF5_DATA 必要参数: source:需要读取文件名 batch_size:处理输入数量 4.4 HDF5 Output 类型: HDF5_OUTPUT 必要参数: file_name: 输文件名 HDF5作用节其层输入blobs写硬盘 4.5 Images 类型: IMAGE_DATA 必要参数: source: text文件名字每行给张图片文件名label batch_size: batch图片数量 选参数: rand_skip:始候输入跳数值异步随机梯度降(SGD)候非用 shuffle [default false] new_height, new_width: 所图像resize 4.6 Windows 类型:WINDOW_DATA 4.7 Dummy 类型:DUMMY_DATA Dummy 层用于development debugging具体参数DummyDataParameter 5. 般层(Common Layers) 5.1 全连接层Inner Product 类型:INNER_PRODUCT 例: layers { name: "fc8" type: INNER_PRODUCT blobs_lr: 1 # learning rate multiplier for the filters blobs_lr: 2 # learning rate multiplier for the biases weight_decay: 1 # weight decay multiplier for the filters weight_decay: 0 # weight decay multiplier for the biases inner_product_param { num_output: 1000 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" value: 0 } } bottom: "fc7" top: "fc8" } 必要参数: num_output (c_o):滤器数 选参数: weight_filler [default type: 'constant' value: 0]:参数初始化 bias_filler:偏置初始化 bias_term [default true]:指定否否启偏置项 通全连接层变化: 输入:n * c_i * h_i * w_i 输:n * c_o * 1 *1 5.2 Splitting 类型:SPLIT Splitting层输入blob离输blobs用需要blob输入输层候 5.3 Flattening 类型:FLATTEN Flattening输入n * c * h * w变简单向量其 n * (c*h*w) * 1 * 1 5.4 Concatenation 类型:CONCAT 例: layers { name: "concat" bottom: "in1" bottom: "in2" top: "out" type: CONCAT concat_param { concat_dim: 1 } } 选参数: concat_dim [default 1]:0代表链接num1代表链接channels 通全连接层变化: 输入:1K每blobn_i * c_i * h * w 输: concat_dim = 0: (n_1 + n_2 + + n_K) *c_1 * h * w需要保证所输入c_i 相同 concat_dim = 1: n_1 * (c_1 + c_2 + +c_K) * h * w需要保证所输入n_i 相同 通Concatenation层blobs链接blob 5.5 Slicing The SLICE layer is a utility layer that slices an input layer to multiple output layers along a given dimension (currently num or channel only) with given slice indices. 5.6 Elementwise Operations 类型:ELTWISE 5.7 Argmax 类型:ARGMAX 5.8 Softmax 类型:SOFTMAX 5.9 Mean-Variance Normalization 类型:MVN 6. 参考 Caffe