『TensorFlow』网络操作API_上
卷积层
卷积操作是使用一个二维的卷积核在一个批处理的图片上进行不断扫描。具体操作是将一个卷积核在每张图片上按照一个合适的尺寸在每个通道上面进行扫描。为了达到好的卷积效率,需要在不同的通道和不同的卷积核之间进行权衡。
三个卷积函数:
conv2d: 任意的卷积核,能同时在不同的通道上面进行卷积操作。depthwise_conv2d: 卷积核能相互独立的在自己的通道上面进行卷积操作。separable_conv2d: 在纵深卷积depthwise filter之后进行逐点卷积separable filter。
卷积步长:
strides ,比如 strides = [1, 1, 1, 1] 表示卷积核对每个像素点进行卷积,即在二维屏幕上面,两个轴方向的步长都是1。strides = [1, 2, 2, 1] 表示卷积核对每隔一个像素点进行卷积,即在二维屏幕上面,两个轴方向的步长都是2。
输出shape:
padding = 'SAME': 向下取舍,仅适用于全尺寸操作,即输入数据维度和输出数据维度相同。padding = 'VALID: 向上取舍,适用于部分窗口,即输入数据维度和输出数据维度不同,输出维度如下。
shape(output) = [batch,
(in_height - filter_height + 1) / strides[1],
(in_width - filter_width + 1) / strides[2],
...]
conv2d
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)输入参数:
input: 一个Tensor。数据类型必须是float32或者float64。filter: 一个Tensor。数据类型必须是input相同。strides: 一个长度是4的一维整数类型数组,每一维度对应的是input中每一维的对应移动步数,比如,strides[1]对应input[1]的移动步数。padding: 一个字符串,取值为SAME或者VALID。use_cudnn_on_gpu: 一个可选布尔值,默认情况下是True。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型是input相同。
解释:这个函数的作用是对一个四维的输入数据 input 和四维的卷积核 filter 进行操作,然后对输入数据进行一个二维的卷积操作,最后得到卷积之后的结果。
给定的输入张量的维度是 [batch, in_height, in_width, in_channels] ,卷积核张量的维度是 [filter_height, filter_width, in_channels, out_channels] ,具体卷积操作如下:
- 将卷积核的维度转换成一个二维的矩阵形状
[filter_height * filter_width * in_channels, output_channels] - 对于每个批处理的图片,我们将输入张量转换成一个临时的数据维度
[batch, out_height, out_width, filter_height * filter_width * in_channels]。 - 对于每个批处理的图片,我们右乘以卷积核,得到最后的输出结果。
更加具体的表示细节为:
output[b, i, j, k] = sum_{di, dj, q}
input[b, strides[1] * i + di, strides[2] * j + dj, q] * filter[di, dj, q, k]
注意,必须有 strides[0] = strides[3] = 1。在大部分处理过程中,卷积核的水平移动步数和垂直移动步数是相同的,即 strides = [1, stride, stride, 1] 。
depthwise_conv2d
tf.nn.depthwise_conv2d(input, filter, strides, padding, name=None)输入参数:
input: 一个Tensor。数据维度是四维[batch, in_height, in_width, in_channels]。filter: 一个Tensor。数据维度是四维[filter_height, filter_width, in_channels, channel_multiplier]。strides: 一个长度是4的一维整数类型数组,每一维度对应的是input中每一维的对应移动步数,比如,strides[1]对应input[1]的移动步数。padding: 一个字符串,取值为SAME或者VALID。use_cudnn_on_gpu: 一个可选布尔值,默认情况下是True。name: (可选)为这个操作取一个名字。输出参数:
- 一个四维的
Tensor,数据维度为[batch, out_height, out_width, in_channels * channel_multiplier]。
解释:这个函数也是一个卷积操作。
给定一个输入张量,数据维度是 [batch, in_height, in_width, in_channels] ,一个卷积核的维度是 [filter_height, filter_width, in_channels, channel_multiplier] ,在通道 in_channels 上面的卷积深度是 1 (我的理解是在每个通道上单独进行卷积),depthwise_conv2d 函数将不同的卷积核独立的应用在 in_channels 的每个通道上(从通道 1 到通道 channel_multiplier ),然后把所有的结果进行汇总。最后输出通道的总数是 in_channels * channel_multiplier 。
更加具体公式如下:
output[b, i, j, k * channel_multiplier + q] =
sum_{di, dj} input[b, strides[1] * i + di, strides[2] * j + dj, k] *
filter[di, dj, k, q]
注意,必须有 strides[0] = strides[3] = 1。在大部分处理过程中,卷积核的水平移动步数和垂直移动步数是相同的,即 strides = [1, stride, stride,1]。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*- import numpy as np
import tensorflow as tf input_data = tf.Variable( np.random.rand(10, 6, 6, 3), dtype = np.float32 )
filter_data = tf.Variable( np.random.rand(2, 2, 3, 5), dtype = np.float32) y = tf.nn.depthwise_conv2d(input_data, filter_data, strides = [1, 1, 1, 1], padding = 'SAME') with tf.Session() as sess:
init = tf.initialize_all_variables()
sess.run(init)
print sess.run(y)
print sess.run(tf.shape(y))
separable_conv2d
tf.nn.separable_conv2d(input, depthwise_filter, pointwise_filter, strides, padding, name=None)输入参数:
input: 一个Tensor。数据维度是四维[batch, in_height, in_width, in_channels]。depthwise_filter: 一个Tensor。数据维度是四维[filter_height, filter_width, in_channels, channel_multiplier]。其中,in_channels的卷积深度等于input的in_channels。pointwise_filter: 一个Tensor。数据维度是四维[1, 1, channel_multiplier * in_channels, out_channels]。其中,pointwise_filter是在depthwise_filter卷积之后的混合卷积。strides: 一个长度是4的一维整数类型数组,每一维度对应的是input中每一维的对应移动步数,比如,strides[1]对应input[1]的移动步数。padding: 一个字符串,取值为SAME或者VALID。name: (可选)为这个操作取一个名字。输出参数:
- 一个四维的
Tensor,数据维度为[batch, out_height, out_width, out_channels]。异常:
数值异常: 如果channel_multiplier * in_channels > out_channels,那么将报错。
解释:这个函数的作用是利用几个分离的卷积核去做卷积,可以参考这个解释。
比如下图中,常规卷积和分离卷积的区别:


首先使用一个二维的卷积核,在每个通道上,以深度 channel_multiplier 进行卷积。也就是先使用 depthwise_conv2d ,将 ID 的通道数映射到 ID * DM 的通道数上面,之后从 ID * DM 的通道数映射到 OD 的通道数上面,这也就是又进行了一次常规卷积。
具体公式如下:
output[b, i, j, k] = sum_{di, dj, q, r}
input[b, strides[1] * i + di, strides[2] * j + dj, q] *
depthwise_filter[di, dj, q, r] *
pointwise_filter[0, 0, q * channel_multiplier + r, k]
strides 只是仅仅控制 depthwise convolution 的卷积步长,因为 pointwise convolution 的卷积步长是确定的 [1, 1, 1, 1] 。注意,必须有 strides[0] = strides[3] = 1。在大部分处理过程中,卷积核的水平移动步数和垂直移动步数是相同的,即 strides = [1, stride, stride, 1]。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*- import numpy as np
import tensorflow as tf input_data = tf.Variable( np.random.rand(10, 6, 6, 3), dtype = np.float32 )
depthwise_filter = tf.Variable( np.random.rand(2, 2, 3, 5), dtype = np.float32) # 输入通道等于input的通道
pointwise_filter = tf.Variable( np.random.rand(1, 1, 15, 20), dtype = np.float32) # 卷积核两项必须是1
# out_channels >= channel_multiplier * in_channels
y = tf.nn.separable_conv2d(input_data, depthwise_filter,
pointwise_filter, strides = [1, 1, 1, 1], padding = 'SAME')
with tf.Session() as sess:
init = tf.initialize_all_variables()
sess.run(init)
print sess.run(y)
print sess.run(tf.shape(y))
池化层
最大汇聚效果优于平均汇聚
池化操作是利用一个矩阵窗口在输入张量上进行扫描,并且将每个矩阵窗口中的值通过取最大值,平均值或者XXXX来减少元素个数。每个池化操作的矩阵窗口大小是由 ksize 来指定的,并且根据步长参数 strides 来决定移动步长。比如,如果 strides 中的值都是1,那么每个矩阵窗口都将被使用。如果 strides 中的值都是2,那么每一维度上的矩阵窗口都是每隔一个被使用。以此类推。
输出数据维度是:
shape(output) = (shape(value) - ksize + 1) / strides
padding = 'SAME': 向下取舍,仅适用于全尺寸操作,即输入数据维度和输出数据维度相同。padding = 'VALID: 向上取舍,适用于部分窗口,即输入数据维度和输出数据维度不同,输出维度如上。
avg_pool
tf.nn.avg_pool(value, ksize, strides, padding, name=None)解释:这个函数的作用是计算池化区域中元素的平均值。
输入参数:
value: 一个四维的Tensor。数据维度是[batch, height, width, channels]。数据类型是float32,float64,qint8,quint8,qint32。ksize: 一个长度不小于4的整型数组。每一位上面的值对应于输入数据张量中每一维的窗口对应值。strides: 一个长度不小于4的整型数组。该参数指定滑动窗口在输入数据张量每一维上面的步长。padding: 一个字符串,取值为SAME或者VALID。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型和value相同。
max_pool
tf.nn.max_pool(value, ksize, strides, padding, name=None)解释:这个函数的作用是计算池化区域中元素的最大值。输入参数:
value: 一个四维的Tensor。数据维度是[batch, height, width, channels]。数据类型是float32,float64,qint8,quint8,qint32。ksize: 一个长度不小于4的整型数组。每一位上面的值对应于输入数据张量中每一维的窗口对应值。strides: 一个长度不小于4的整型数组。该参数指定滑动窗口在输入数据张量每一维上面的步长。padding: 一个字符串,取值为SAME或者VALID。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型和value相同。
激活函数
在神经网络中,我们有很多的非线性函数来作为激活函数,比如连续的平滑非线性函数(sigmoid,tanh和softplus),连续但不平滑的非线性函数(relu,relu6和relu_x)和随机正则化函数(dropout)。
所有的激活函数都是单独应用在每个元素上面的,并且输出张量的维度和输入张量的维
分类:
平滑非线性(sigmoid,tanh,elu,softplus,softsign)
连续但不是处处可导(relu,relu6,crelu,relu_x)
随机正则化(dropout)


relu
tf.nn.relu(features, name = None)解释:这个函数的作用是计算激活函数
relu,即max(features, 0)。输入参数:
features: 一个Tensor。数据类型必须是:float32,float64,int32,int64,uint8,int16,int8。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型和features相同。
relu6
tf.nn.relu6(features, name = None)解释:这个函数的作用是计算激活函数
relu6,即min(max(features, 0), 6)。输入参数:
features: 一个Tensor。数据类型必须是:float,double,int32,int64,uint8,int16或者int8。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型和features相同。
crelu
tf.nn.crelu(features, name = None)
解释:这个函数会倍增通道,一个是relu,一个是relu关于y轴对称的形状。
输入参数:
features: 一个Tensor。数据类型必须是:float32,float64,int32,int64,uint8,int16,int8。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型和features相同,通道加倍。
elu
tf.nn.elu(features, name = None)
解释:x小于0时,y = a*(exp(x)-1),x大于0时同relu。
features: 一个Tensor。数据类型必须是:float32,float64,int32,int64,uint8,int16,int8。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型和features相同。
softplus
tf.nn.softplus(features, name = None)解释:这个函数的作用是计算激活函数
softplus,即log( exp( features ) + 1)。输入参数:
features: 一个Tensor。数据类型必须是:float32,float64,int32,int64,uint8,int16或者int8。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型和features相同。
softsign
softsign
tf.nn.soft(features, name = None)sign解释:这个函数的作用是计算激活函数
softsign,即features / (abs(features) + 1)。输入参数:
features: 一个Tensor。数据类型必须是:float32,float64,int32,int64,uint8,int16或者int8。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型和features相同。
sigmoid
sigmoid
tf.sigmoid(x, name = None)解释:这个函数的作用是计算
x的 sigmoid 函数。具体计算公式为y = 1 / (1 + exp(-x))。输入参数:
x: 一个Tensor。数据类型必须是float,double,int32,complex64,int64或者qint32。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,如果x.dtype != qint32,那么返回的数据类型和x相同,否则返回的数据类型是quint8。
sigmoid输出恒大于零,相当于加了偏置分量。
tanh
tf.tanh(x, name = None)解释:这个函数的作用是计算
x的 tanh 函数。具体计算公式为( exp(x) - exp(-x) ) / ( exp(x) + exp(-x) )。
x: 一个Tensor。数据类型必须是float,double,int32,complex64,int64或者qint32。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,如果x.dtype != qint32,那么返回的数据类型和x相同,否则返回的数据类型是quint8。
[-2,2]之间tanh最敏感
[-8,-2]之间tanh不敏感

dropout
tf.nn.dropout(x, keep_prob, noise_shape = None, seed = None, name = None)解释:这个函数的作用是计算神经网络层的
dropout。一个神经元将以概率
keep_prob决定是否放电,如果不放电,那么该神经元的输出将是0,如果该神经元放电,那么该神经元的输出值将被放大到原来的1/keep_prob倍。这里的放大操作是为了保持神经元输出总个数不变。比如,神经元的值为[1, 2],keep_prob的值是0.5,并且是第一个神经元是放电的,第二个神经元不放电,那么神经元输出的结果是[2, 0],也就是相当于,第一个神经元被当做了1/keep_prob个输出,即2个。这样保证了总和2个神经元保持不变。默认情况下,每个神经元是否放电是相互独立的。但是,如果
noise_shape被修改了,那么他对于变量x就是一个广播形式,而且当且仅当noise_shape[i] == shape(x)[i],x中的元素是相互独立的。比如,如果shape(x) = [k, l, m, n], noise_shape = [k, 1, 1, n],那么每个批和通道都是相互独立的,但是每行和每列的数据都是关联的,即要不都为0,要不都还是原来的值。输入参数:
x: 一个Tensor。keep_prob: 一个 Python 的 float 类型。表示元素是否放电的概率。noise_shape: 一个一维的Tensor,数据类型是int32。代表元素是否独立的标志。seed: 一个Python的整数类型。设置随机种子。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据维度和x相同。异常:
输入异常: 如果keep_prob不是在(0, 1]区间,那么会提示错误。
bias_add
tf.nn.bias_add(value, bias, name = None)解释:这个函数的作用是将偏差项
bias加到value上面。这个操作你可以看做是
tf.add的一个特例,其中bias必须是一维的。该API支持广播形式,因此value可以有任何维度。但是,该API又不像tf.add可以让bias的维度和value的最后一维不同,tf.nn.bias_add中bias的维度和value最后一维必须相同。输入参数:
value: 一个Tensor。数据类型必须是float,double,int64,int32,uint8,int16,int8或者complex64。bias: 一个一维的Tensor,数据维度和value的最后一维相同。数据类型必须和value相同。name: (可选)为这个操作取一个名字。输出参数:
- 一个
Tensor,数据类型和value相同。
范例:
#!/usr/bin/env python
# -*- coding: utf-8 -*- import tensorflow as tf a = tf.constant([[1.0, 2.0],[1.0, 2.0],[1.0, 2.0]])
b = tf.constant([2.0,1.0])
c = tf.constant([1.0])
sess = tf.Session()
print sess.run(tf.nn.bias_add(a, b))
# 因为 a 最后一维的维度是 2 ,但是 c 的维度是 1,所以以下语句将发生错误
print sess.run(tf.nn.bias_add(a, c))
# 但是 tf.add() 可以正确运行
print sess.run(tf.add(a, c))
『TensorFlow』网络操作API_上的更多相关文章
- 『TensorFlow』网络操作API_下
一.优化器基类介绍 标注一点,优化器中的学习率可以是tensor,这意味着它可以feed, learning_rate: A Tensor or a floating point value. 正常使 ...
- 『TensorFlow』网络操作API_中_损失函数及分类器
一.误差值 度量两个张量或者一个张量和零之间的损失误差,这个可用于在一个回归任务或者用于正则的目的(权重衰减). l2_loss tf.nn.l2_loss(t, name=None) 解释:这个函数 ...
- 『TensorFlow』读书笔记_Inception_V3_上
1.网络背景 自2012年Alexnet提出以来,图像分类.目标检测等一系列领域都被卷积神经网络CNN统治着.接下来的时间里,人们不断设计新的深度学习网络模型来获得更好的训练效果.一般而言,许多网络结 ...
- 『TensorFlow』专题汇总
TensorFlow:官方文档 TensorFlow:项目地址 本篇列出文章对于全零新手不太合适,可以尝试TensorFlow入门系列博客,搭配其他资料进行学习. Keras使用tf.Session训 ...
- 『TensorFlow』梯度优化相关
tf.trainable_variables可以得到整个模型中所有trainable=True的Variable,也是自由处理梯度的基础 基础梯度操作方法: tf.gradients 用来计算导数.该 ...
- 『TensorFlow』模型保存和载入方法汇总
『TensorFlow』第七弹_保存&载入会话_霸王回马 一.TensorFlow常规模型加载方法 保存模型 tf.train.Saver()类,.save(sess, ckpt文件目录)方法 ...
- 『TensorFlow』分布式训练_其三_多机分布式
本节中的代码大量使用『TensorFlow』分布式训练_其一_逻辑梳理中介绍的概念,是成熟的多机分布式训练样例 一.基本概念 Cluster.Job.task概念:三者可以简单的看成是层次关系,tas ...
- 『TensorFlow』滑动平均
滑动平均会为目标变量维护一个影子变量,影子变量不影响原变量的更新维护,但是在测试或者实际预测过程中(非训练时),使用影子变量代替原变量. 1.滑动平均求解对象初始化 ema = tf.train.Ex ...
- 『TensorFlow』读书笔记_降噪自编码器
『TensorFlow』降噪自编码器设计 之前学习过的代码,又敲了一遍,新的收获也还是有的,因为这次注释写的比较详尽,所以再次记录一下,具体的相关知识查阅之前写的文章即可(见上面链接). # Aut ...
随机推荐
- LeetCode 206 Reverse Linked List 解题报告
题目要求 Reverse a singly linked list. Example: Input: 1->2->3->4->5->NULL Output: 5-> ...
- (转)spring中的拦截器(HandlerInterceptor+MethodInterceptor)
1. 过滤器跟拦截器的区别 在说拦截器之前,不得不说一下过滤器,有时候往往被这两个词搞的头大. 其实我们最先接触的就是过滤器,还记得web.xml中配置的<filter>吗~ 你应该知道 ...
- 剑指offer-复杂链表的复制
题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的节点引用,否 ...
- [js]js中类的继承
凡事总有个开端,也有个tag节点(里程碑).阶段性的划分总结,是一种对精神的慰藉,否则精神就像野马一样,会放弃,会累死. 继承: 子类原型指向父类一个实例 类的继承-模拟系统类 Object -> ...
- [py]GTM和UTC及python的时间戳
时间戳是一串字符串 time.time() 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数.通俗的讲, 时间戳是一 ...
- sublime----------快捷键的记录
1.鼠标选中多行,按下 Ctrl Shift L (Command Shift L) 即可同时编辑这些行: 2.鼠标选中自定义的多行,ctrl+鼠标左键
- PowerShell 语法备忘
1.挡可能出现 .0 的时候需要加上引号 2.使用 -Join 或者 + 进行字符串拼接 3.在cmd 命令下可以使用 set /a s=1+2 表示需要进行计算,而不是拼接
- jmeter如何玩之badboy + jmeter并发性能测试
今天下班时公司安排了一个同事来对项目做集群性能测试,怀着对性能测试的好奇心,下班后没有着急离开,而是等待 那位同事的到来,然后在旁边学习了下如何使用Badboy和jmeter做性能测试. 1. 软件介 ...
- JavaScript Dom 事件
JavaScript Dom 事件 对于事件需要注意的要点: // this标签当前正在操作的标签. this // event封装了当前事件的内容. even 常用事件 // 鼠标单击.触发事件 ...
- IP白名单的实现(PHP)
有些项目可能会用到一个IP地址的白名单黑名单之类的验证. 比如,只有IP地址在白名单中,才可以访问该系统. 那么此时,白名单的维护,一般是一个文件,里边是一些IP地址(每行一个IP),当然也有的可能是 ...





