TensorFlow CNN教程:如何编辑顶层以进行本地连接?

时间:2017-01-19 05:44:44

标签: python tensorflow conv-neural-network

我有一些机器学习和python的背景,但我只是学习TensorFlow。我正在通过this Eclipse bug report教自己如何使用它进行图像分类。一路上有一个练习,我很难完成练习。

练习:inference()中的模型体系结构与cuda-convnet中指定的CIFAR-10模型略有不同。特别是,Alex的原始模型的顶层是本地连接的,并没有完全连接。尝试编辑体系结构以在顶层完全重现本地连接的体系结构。

练习引用tutorial on deep convolutional neural nets中的inference()函数。第二层到最后一层(称为local4)的形状为[384,192],顶层的形状为[192,NUM_CLASSES],其中NUM_CLASSES = 10。我认为我们要编辑的代码位于定义顶层的代码中的某个位置:

with tf.variable_scope('softmax_linear') as scope:
    weights = _variable_with_weight_decay('weights', [192, NUM_CLASSES],
                                      stddev=1/192.0, wd=0.0)
    biases = _variable_on_cpu('biases', [NUM_CLASSES],
                          tf.constant_initializer(0.0))
    softmax_linear = tf.add(tf.matmul(local4, weights), biases,name=scope.name
    _activation_summary(softmax_linear)

但我没有看到任何代码确定层之间连接的可能性,因此我不知道如何将模型从完全连接更改为本地连接。有人知道怎么做吗?

2 个答案:

答案 0 :(得分:3)

我也正在做这个练习。我会尝试正确地解释我的方法,而不是仅仅给出解决方案。值得回顾完全连接层(https://www.tensorflow.org/get_started/mnist/beginners)的数学。

因此,完全连接层的线性代数是:

y = W * x + b

其中 x 是n维输入向量, b 是偏差的 n 维向量, W 是一个 n -by- n 权重矩阵。 y i 元素是W的 i 行的总和,与 x 的元素相乘

所以....如果你只想 y [i] 连接到 x [i-1] x [i] x [i + 1] ,您只需将 W i 行中的所有值设置为零,除了(i-1) th, i th和(i + 1)该行的第列。因此,要创建一个本地连接的图层,您只需将 W 强制为带状矩阵(https://en.wikipedia.org/wiki/Band_matrix),其中波段的大小等于您想要的本地连接的邻域的大小。 Tensorflow具有设置要绑定的矩阵的功能(tf.batch_matrix_band_part(input, num_lower, num_upper, name=None))。

在我看来,这是练习中最简单的数学解决方案。

答案 1 :(得分:2)

我会尝试回答你的问题,虽然我不是100%我也是正确的。

查看cuda-convnet architecture,我们可以看到TensorFlow和cuda-convnet实现在第二个池层之后开始有所不同。

TensorFlow实现实现了两个完全连接的层和s​​oftmax分类器。

cuda-convnet实现了两个本地连接的层,一个完全连接的层和s​​oftmax分类器。

您包含的代码段仅指softmax分类器,实际上是在两个实现之间共享。要使用TensorFlow重现cuda-convnet实现,我们必须用两个本地连接的层和一个完全连接的层替换现有的完全连接的层。

由于Tensor没有将本地连接的图层作为SDK的一部分,因此我们必须找到使用现有工具实现它的方法。以下是我尝试实现第一个本地连接的图层:

  with tf.variable_scope('local3') as scope:
    shape = pool2.get_shape()
    h = shape[1].value
    w = shape[2].value

    sz_local = 3 # kernel size
    sz_patch = (sz_local**2)*shape[3].value
    n_channels = 64

    # Extract 3x3 tensor patches
    patches = tf.extract_image_patches(pool2, [1,sz_local,sz_local,1], [1,1,1,1], [1,1,1,1], 'SAME')
    weights = _variable_with_weight_decay('weights', shape=[1,h,w,sz_patch, n_channels], stddev=5e-2, wd=0.0)
    biases = _variable_on_cpu('biases', [h,w,n_channels], tf.constant_initializer(0.1))

    # "Filter" each patch with its own kernel 
    mul = tf.multiply(tf.expand_dims(patches, axis=-1), weights)
    ssum = tf.reduce_sum(mul, axis=3)
    pre_activation = tf.add(ssum, biases)
    local3 = tf.nn.relu(pre_activation, name=scope.name)