周日休息

2018/07/01 休息

Posted by WangXiaoDong on July 1, 2018
    今天周日,因为宿舍的屋子快没有电了,因此我就在实验室凉快,顺便还把这个消息告诉了师兄和师弟,结果
他们今天一天也没怎么用电,好有负罪感。
    今天准备整理一下最近关于TensorFlow的使用经验。今天肖老师过来加班了!

TensorFlow的使用经验

形状变化函数的使用

TensorFlow进行卷积层神经网络的使用时,需要用到函数tf.reshape(tensor, shape, name=None),函数的作用是将tensor变换为参数shape的形式。 其中shape为一个列表形式,特殊的一点是列表中可以存在-1。-1代表的含义是不用我们自己指定这一维的大小,函数会自动计算,但列表中只能存在一个-1。(当然如果存在多个-1,就是一个存在多解的方程了)

重点还有一个就是根据shape如何变换矩阵。其实简单的想就是,

reshape(t, shape) => reshape(t, [-1]) => reshape(t, shape)

首先将矩阵t变为一维矩阵,然后再对矩阵的形式更改就可以了。

官方的例子:

# tensor 't' is [1, 2, 3, 4, 5, 6, 7, 8, 9]
# tensor 't' has shape [9]
reshape(t, [3, 3]) ==> [[1, 2, 3],
                        [4, 5, 6],
                        [7, 8, 9]]

# tensor 't' is [[[1, 1], [2, 2]],
#                [[3, 3], [4, 4]]]
# tensor 't' has shape [2, 2, 2]
reshape(t, [2, 4]) ==> [[1, 1, 2, 2],
                        [3, 3, 4, 4]]

# tensor 't' is [[[1, 1, 1],
#                 [2, 2, 2]],
#                [[3, 3, 3],
#                 [4, 4, 4]],
#                [[5, 5, 5],
#                 [6, 6, 6]]]
# tensor 't' has shape [3, 2, 3]
# pass '[-1]' to flatten 't'
reshape(t, [-1]) ==> [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6]

# -1 can also be used to infer the shape

# -1 is inferred to be 9:
reshape(t, [2, -1]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],
                         [4, 4, 4, 5, 5, 5, 6, 6, 6]]
# -1 is inferred to be 2:
reshape(t, [-1, 9]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],
                         [4, 4, 4, 5, 5, 5, 6, 6, 6]]
# -1 is inferred to be 3:
reshape(t, [ 2, -1, 3]) ==> [[[1, 1, 1],
                              [2, 2, 2],
                              [3, 3, 3]],
                             [[4, 4, 4],
                              [5, 5, 5],
                              [6, 6, 6]]]

# tensor 't' is [7]
# shape `[]` reshapes to a scalar
reshape(t, []) ==> 7

结论:

  • -1只能出现一次,代表对应位置级别括号里面的数字由整体的数量来推断
  • reshape后第一个数字代表变化后最外面括号对应里面数据的个数,第二个数字代表变化后次外面括号对应里面数据的个数,以此类推

卷积层函数的使用

TensorFlow进行卷积层神经网络的使用时,需要用到函数tf.nn.conv2d

举个例子,比如如下的输入图片矩阵和对应的卷积核:

进行编程的代码如下:

import tensorflow as tf
k = tf.constant([
    [1, 0, 1],
    [2, 1, 0],
    [0, 0, 1]
], dtype=tf.float32, name='k')
i = tf.constant([
    [4, 3, 1, 0],
    [2, 1, 0, 1],
    [1, 2, 4, 1],
    [3, 1, 0, 2]
], dtype=tf.float32, name='i')
kernel = tf.reshape(k, [3, 3, 1, 1], name='kernel')
image  = tf.reshape(i, [1, 4, 4, 1], name='image')

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 1, 1, 1], "VALID"))
# VALID means no padding
with tf.Session() as sess:
   print sess.run(res)

结论:可以看出,输入图片矩阵矩阵和卷积核进行输入之前需要进行性状改变,对应改变的规则如下:

  • 输入图片矩阵矩阵:[batch, out_height, out_width, in_channels]
  • 卷积核:[filter_height , filter_width , in_channels, output_channels]

池化函数的使用

池化

tf.nn.max_pool

池化后的全连接

池化后的全连接之前一定要reshape成:

h_pool_flat = [batch,out_height * out_width * in_channels]形状,这样才能进行

tf.nn.relu(tf.matmul(h_pool_flat, W) + b) 其中:

W = [out_height * out_width * in_channels, 全连接数] b = [全连接数]

比如如下两个例子:

# 全连接层,输出为1024维的向量
W_fc1 = weight_variable([7 * 7 * 64, 1024])   #这里根据前面的池化层后自己计算尺寸:
#[池化后size * 池化后size * 池化后通道数]

b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

# local3
  with tf.variable_scope('local3') as scope:
    # Move everything into depth so we can perform a single matrix multiply.
    reshape = tf.reshape(pool2, [FLAGS.batch_size, -1])
    dim = reshape.get_shape()[1].value       #这一步想法很棒!根据程序自己推断维的大小!
    weights = _variable_with_weight_decay('weights', shape=[dim, 384],
                                          stddev=0.04, wd=0.004)
    biases = _variable_on_cpu('biases', [384], tf.constant_initializer(0.1))
    local3 = tf.nn.relu(tf.matmul(reshape, weights) + biases, name=scope.name)
    _activation_summary(local3)