Alex、Hinton等人在2012年的NIPS论文《ImageNet Classification with Deep Convolutional Neural Networks》中将LRN应用于深度神经网络中(AlexNet)。论文见:http://www.cs.toronto.edu/~hinton/absps/imagenet.pdf ,截图如下:

公式解释:

:ReLU处理后的神经元,作为LRN的输入;

:LRN的输出,LRN处理后的神经元;

N:kernal总数或通道数;

k、n、:为常量,是超参数,k类似于bias,n对应于Caffe中的local_size,在论文中这几个值分别为2、5、、0.75。

LRN(Local Response Normalization):局部响应归一化,此层实现了” lateral inhibition”(侧抑制),通过对局部输入区域进行归一化来执行一种”侧抑制”。在AlexNet中,处理ReLU神经元时,LRN很有用,因为ReLU的响应结果是无界的,可以非常大,所以需要归一化。当处理具有无限激活(unbounded activation)的神经元时(如ReLU),可以通过LRN对其归一化(normalize),因为它允许检测具有大神经元响应的高频特征(high-frequency features),同时衰减局部周围(local neighborhood)均匀大(uniformly large)的响应。它是一种正则化类型。一般应用在激活、池化后进行的一种处理方法。该层的输出维数始终等于输入维数。

在神经生物学有一个概念叫做侧抑制(lateral inhibition),指的是被激活的神经元抑制相邻的神经元。归一化的目的是”抑制”,局部响应归一化就是借鉴侧抑制的思想来实现局部抑制。LRN层模仿生物神经系统的侧抑制机制,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其它反馈较小的神经元,增强了模型泛化能力。

后来研究者发现LRN起不到太大作用,LRN的作用已被正则化技术(regularization techniques,例如dropout and batch normalization)、更好的初始化和训练方法所取代。

在Caffe的caffe.proto中,LRN参数内容如下:分为通道间归一化(local_size*1*1)和通道内归一化(1*local_size*local_size)

// Message that stores parameters used by LRNLayer
message LRNParameter {optional uint32 local_size = 1 [default = 5];optional float alpha = 2 [default = 1.];optional float beta = 3 [default = 0.75];enum NormRegion {ACROSS_CHANNELS = 0;WITHIN_CHANNEL = 1;}optional NormRegion norm_region = 4 [default = ACROSS_CHANNELS];optional float k = 5 [default = 1.];enum Engine {DEFAULT = 0;CAFFE = 1;CUDNN = 2;}optional Engine engine = 6 [default = DEFAULT];
}

各参数介绍见:http://caffe.berkeleyvision.org/tutorial/layers/lrn.html

注:以上内容主要来自网络整理。

以下是实现的测试代码,仅实现通道间归一化,包括C++和tensorflow:

tensorflow的实现如下:

import tensorflow as tf
import numpy as np
x = np.array([i for i in range(1, 33)]).reshape([2, 2, 2, 4])
y = tf.nn.lrn(input=x, depth_radius=2, bias=1, alpha=1, beta=0.75)
print("input:\n", x)
print("output:\n", y)

C++代码实现如下:

lrn.hpp:

#ifndef FBC_NN_LRN_HPP_
#define FBC_NN_LRN_HPP_namespace ANN {enum class NormRegion {ACROSS_CHANNEL = 0,WITHIN_CHANNEL
};template<typename T = float>
class LRN {
public:LRN() = default;LRN(unsigned int local_size, T alpha, T beta, T bias, NormRegion norm_region) :local_size_(local_size), alpha_(alpha), beta_(beta), bias_(bias), norm_region_(norm_region) {}int run(const T* input, int batch, int channel, int height, int width, T* output) const;private:int across_channel(const T* input, int batch, int channel, int height, int width, T* output) const;int within_channel(const T* input, int batch, int channel, int height, int width, T* output) const;unsigned int local_size_ = 5; // nT alpha_ = 1.;T beta_ = 0.75;T bias_ = 1.; // kNormRegion norm_region_ = NormRegion::ACROSS_CHANNEL;
};} // namespace ANN#endif // FBC_NN_LRN_HPP_

lrn.cpp:

#include "lrn.hpp"
#include <algorithm>
#include <cmath>namespace ANN {template<typename T>
int LRN<T>::run(const T* input, int batch, int channel, int height, int width, T* output) const
{if (norm_region_ == NormRegion::ACROSS_CHANNEL)return across_channel(input, batch, channel, height, width, output);elsereturn within_channel(input, batch, channel, height, width, output);
}template<typename T>
int LRN<T>::across_channel(const T* input, int batch, int channel, int height, int width, T* output) const
{int size = channel * height * width;for (int p = 0; p < batch; ++p) {const T* in = input + size * p;T* out = output + size * p;// N = channel; n = local_size_; k = bias_for (int i = 0; i < channel; ++i) {for (int y = 0; y < height; ++y) {for (int x = 0; x < width; ++x) {T tmp = 0;for (int j = std::max(0, static_cast<int>(i - local_size_ / 2)); j <= std::min(channel - 1, static_cast<int>(i + local_size_ / 2)); ++j) {tmp += std::pow(in[j * height * width + width * y + x], 2);}out[i * height * width + width * y + x] = in[i * height * width + width * y + x] / std::pow(bias_ + alpha_ * tmp, beta_);}}}}return 0;
}template<typename T>
int LRN<T>::within_channel(const T* input, int batch, int channel, int height, int width, T* output) const
{fprintf(stderr, "not implemented\n");return -1;
}template class LRN<float>;} // namespace ANN

test_lrn.cpp:

int test_lrn()
{int batch = 2, channel = 4, height = 2, width = 2;std::vector<float> input{ 1., 5., 9., 13., 2., 6., 10., 14., 3., 7., 11., 15., 4., 8., 12., 16.,17., 21., 25., 29., 18., 22., 26., 30., 19., 23., 27., 31., 20., 24., 28., 32.};CHECK(batch * channel * height * width == input.size());std::unique_ptr<float[]> output(new float[input.size()]);ANN::LRN<> lrn;lrn.run(input.data(), batch, channel, height, width, output.get());auto print = [height, width](const float* data, int length) {int size = height * width;for (int i = 0; i < length / size; ++i) {const float* p = data + i * size;for (int j = 0; j < size; ++j) {fprintf(stdout, "  %f", p[j]);}fprintf(stdout, "\n");}};fprintf(stdout, "input:\n"); print(input.data(), input.size());fprintf(stdout, "output:\n"); print(output.get(), input.size());return 0;
}

执行结果如下图所示:由结果可知,C++实现与tensorflow一致

tensorflow执行结果如下:

C++执行结果如下:

GitHub:https://github.com/fengbingchun/NN_Test

深度神经网络中的局部响应归一化LRN简介及实现相关推荐

  1. AlexNet中的局部响应归一化(LRN)

    1,简介 局部响应归一化(Local Response Normalization,LRN),提出于2012年的AlexNet中.首先要引入一个神经生物学的概念:侧抑制(lateral inhibit ...

  2. 深度学习饱受争议的局部响应归一化(LRN)详解

    前言:Local Response Normalization(LRN)技术主要是深度学习训练时的一种提高准确度的技术方法.其中caffe.tensorflow等里面是很常见的方法,其跟激活函数是有区 ...

  3. 局部响应归一化LRN (Local Response Normalization)

    一.LRN技术介绍: LRN(Local Response Normalization) 是一种提高深度学习准确度的技术方法. LRN 一般是在激活. 池化函数后的一种方法.在 ALexNet 中, ...

  4. 局部响应归一化LRN(Local Response Normalization)

    LRN一般是在激活.池化后进行的一中处理方法. 其主要思想是:对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力. 更加详细可看:ht ...

  5. 局部响应归一化(Local Response Normalization,LRN)和批量归一化(Batch Normalization,BN)的区别

    为什么要归一化? 归一化已成为深度神经网络中的一个重要步骤,它可以弥补ReLU.ELU等激活函数无界性的问题.有了这些激活函数,输出层就不会被限制在一个有限的范围内(比如tanh的[−1,1][-1, ...

  6. LRN (Local Response Normalization,即局部响应归一化层)

    LRN (Local Response Normalization,即局部响应归一化层) (一)先看看归一化吧 什么是归一化? 归一化化是归纳统一样本的统计分布性.就是要把你需要处理的数据经过处理后( ...

  7. LRN 局部响应归一化详解

    1.其中LRN就是局部响应归一化: 这个技术主要是深度学习训练时的一种提高准确度的技术方法.其中caffe.tensorflow等里面是很常见的方法,其跟激活函数是有区别的,LRN一般是在激活.池化后 ...

  8. tf.nn.lrn() 局部响应归一化函数

    背景文档 1.首先先了解一下 什么是过拟合和欠拟合?by Panda.X 2.下面简单说一下LRN,全称Local Response Normalization (局部响应归一化函数),是一种防止过拟 ...

  9. 深度神经网络中的Batch Normalization介绍及实现

    之前在经典网络DenseNet介绍_fengbingchun的博客-CSDN博客_densenet中介绍DenseNet时,网络中会有BN层,即Batch Normalization,在每个Dense ...

最新文章

  1. 我要回家软件_这个中秋节,我也要回家
  2. jdk自带的反编译在那个包下_求教JDK中的反编译命令
  3. 史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)
  4. 17电大计算机网考模拟题,2017年电大 201717统考电大计算机应用基础网考试题.doc...
  5. 矩阵快速幂(教主传授)
  6. Hibernate JPA中@Transient、@JsonIgnoreProperties、@JsonIgnore、@JsonFormat、@JsonSerialize等注解解释
  7. ue4蓝图和ai的区别_UE4 AI基础
  8. 订单状态 css_CSS状态2019
  9. css不继承上级样式_这个笔记《CSS基本概念》,让菜鸟轻松学会给网页穿外衣
  10. 数据结构与算法JavaScript描述——队列
  11. 利用fnd_flex_keyval包轻松获取关键性弹性域组合描述字段
  12. html语言标记说明,HTML中注释标签的使用方法
  13. windows ping 端口
  14. 安卓原生辅助功能应用实战——趣头条
  15. 动作频频,BAT欲瓜分10万亿互联网医疗市场蛋糕?
  16. 2022吴恩达机器学习课程——第一课
  17. 多重比较和多重比较陷阱
  18. jquery实现输入框实时统计字数和设置字数限制功能
  19. Pytorch的骚操作
  20. VIM 中使用 Ctrl-A 和 Ctrl-X 控制数字增减

热门文章

  1. LabVIEW读写各类格式图像的方法(基础篇—1)
  2. 竞赛|数据竞赛Top解决方案开源整理
  3. C语言实现bmp图像对比度扩展
  4. laravel carbon 格式化日期_Laravel 编码实践分享
  5. CvMat,Mat和IplImage之间的转化和拷贝
  6. Windows7无法自动将IP协议堆栈绑定到网络适配器的办法
  7. 避开移入移出事件内部div干扰事件,e是function(e)的e
  8. 强哥原创管理方法论之“粉丝经济管理学”
  9. Vue 监听路由变化的三种方式
  10. 人类的思维方式有哪些?【达克效应】