layer融合的过程中,如果layer是相加的,则直接传递导数;如果是相乘,则相互交换导数。
卷积层由多个卷积核组合形成,每个卷积核同输入数据进行卷积运算,形成新的特征图。
卷积神经网络需要的一些额外功能:
* 非线性激励:卷积是线性运算,增加非线性描述的能力;
* 降维:特征图稀疏,减少数据运算量,保持精度;
* 归一化:特征的scale保持一致;
* 区域分割:不同区域进行独立学习;
* 区域融合:对分开的区域进行合并,方便信息融合;
* 增维:增加图片生成或探测任务中空间信息。
在输入的特征图和卷积核卷积的过程中,每一次卷积计算都会生成特征图的一个值,卷积计算为线性运算,需要将所得结果输入非线性激励函数中,得到一个非线性值,增加非线性描述的能力。
一般会使用ReLU函数,相当于选取 XW 和 0 两者之间的最大值。
在计算的过程中,中间层部分激励不平等,则对数据进行归一化。某种程度上可以减少梯度衰减。
在某些应用中,希望独立对某些区域单独学习。
其好处是,学习多套参数,其具有更强的特征描述能力。
对独立进行特征学习的分支进行融合,构建高效且精简的特征组合。
例如:GoogleLeNet 的基本模块用多种分辨率对目标特征进行学习,之后进行多分辨率特征的融合。
下面还是利用mnist数据集,利用卷积神经网络进行手写字体的识别。
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
import tensorflow as tf
# Parameters
learning_rate = 0.001
training_epochs = 30
batch_size = 100
display_step = 1
# Network Parameters
n_input = 784 # MNIST data input (img shape: 28*28)
n_classes = 10 # MNIST total classes (0-9 digits)
# tf Graph input
x = tf.placeholder("float", [None, n_input])
y = tf.placeholder("float", [None, n_classes])
#pre-define the
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
strides=[1, 2, 2, 1], padding='SAME')
# Create model
def multilayer_perceptron(x, weights, biases):
#now, we want to change this to a CNN network
#first reshape the data to 4-D
x_image = tf.reshape(x, [-1,28,28,1])
#then apply cnn layers
h_conv1 = tf.nn.relu(conv2d(x_image, weights['conv1']) + biases['conv_b1'])
h_pool1 = max_pool_2x2(h_conv1)
h_conv2 = tf.nn.relu(conv2d(h_pool1, weights['conv2']) + biases['conv_b2'])
h_pool2 = max_pool_2x2(h_conv2)
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, weights['fc1']) + biases['fc1_b'])
# Output layer with linear activation
out_layer = tf.matmul(h_fc1, weights['out']) + biases['out_b']
return out_layer
# Store layers weight & biases
weights = {
'conv1': tf.Variable(tf.random_normal([5, 5, 1, 32])),
'conv2': tf.Variable(tf.random_normal([5, 5, 32, 64])),
'fc1' : tf.Variable(tf.random_normal([7*7*64,256])),
'out': tf.Variable(tf.random_normal([256,n_classes]))
}
biases = {
'conv_b1': tf.Variable(tf.random_normal([32])),
'conv_b2': tf.Variable(tf.random_normal([64])),
'fc1_b': tf.Variable(tf.random_normal([256])),
'out_b': tf.Variable(tf.random_normal([n_classes]))
}
# Construct model
pred = multilayer_perceptron(x, weights, biases)
# Define loss and optimizer
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
# Initializing the variables
init = tf.global_variables_initializer()
# Launch the graph
with tf.Session() as sess:
sess.run(init)
# Training cycle
for epoch in range(training_epochs):
avg_cost = 0.
total_batch = int(mnist.train.num_examples/batch_size)
# Loop over all batches
for i in range(total_batch):
batch_x, batch_y = mnist.train.next_batch(batch_size)
# Run optimization op (backprop) and cost op (to get loss value)
_, c = sess.run([optimizer, cost], feed_dict={x: batch_x,
y: batch_y})
# Compute average loss
avg_cost += c / total_batch
# Display logs per epoch step
if epoch % display_step == 0:
print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(avg_cost))
print("Optimization Finished!")
# Test model
correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
# Calculate accuracy
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}))
1.:tf.nn.conv2d
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)
除去name
参数用以指定该操作的name
,与方法有关的一共五个参数:
input
:指需要做卷积的输入图像,它要求是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数],注意这是一个4维的Tensor,要求类型为float32和float64其中之一;filter
:相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, filter_width, in_channels, out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels,就是参数input的第四维;strides
:卷积时在图像每一维的步长,这是一个一维的向量,长度4;对于图片,因为只有两维,通常strides取[1,stride,stride,1];padding
:string类型的量,只能是”SAME”,”VALID”其中之一,这个值决定了不同的卷积方式。’SAME’时,表示卷积核可以停留在图像边缘,即图片的大小不会因为卷积运算而变小;’VALID’时,表示卷积核不能停留在图像边缘,即会因为卷积运算图片的大小会缩小;use_cudnn_on_gpu
:bool类型,是否使用cudnn加速,默认为true。 2.:tf.nn.max_pool
tf.nn.max_pool(value, ksize, strides, padding, name=None)
value
:需要池化的输入,一般池化层接在卷积层后面,所以输入通常是feature map,依然是[batch, height, width, channels]这样的shape;ksize
:池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],因为我们不想在batch和channels上做池化,所以这两个维度设为了1;strides
:和卷积类似,窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1];padding
:和卷积类似,可以取’VALID’ 或者’SAME’。 3.:tf.reshape
tf.reshape(tensor, shape, name=None)
函数的作用是将tensor变换为参数shape的形式。
其中shape为一个列表形式,特殊的一点是列表中可以存在-1。-1代表的含义是不用我们自己指定这一维的大小,函数会自动计算,但列表中只能存在一个-1。
版权声明:本博客为博主学习网课《深度学习》课程总结,博文图片均为课程PPT图片。
同时,本文为博主原创文章,博客地址:http://blog.csdn.net/koala_tree,未经博主允许不得转载。