如何在Tensorflow中拥有可变数量的隐藏层?

时间:2017-08-18 16:45:24

标签: tensorflow neural-network

假设我们想尝试一些隐藏的图层编号及其大小。我们怎样才能在Tensorflow中做到?

请考虑以下示例以明确说明:

# Create a  Neural Network Layer

def fc_layer(input, size_in, size_out):
        w = tf.Variable(tf.truncated_normal([None, size_in, size_out]), name="W")
        b = tf.Variable(tf.constant(0.1, shape=[size_out]))
        act = tf.matmul(input, w) + b
        return act
n_hiddenlayers=3 #number of hidden layers
hidden_layer=tf.placeholder(tf.float32,[n_hiddenlayers, None, None])
#considering 4 as size of inputs and outputs of all layers
sizeInpOut=4
for i in range(n_hiddenlayers):
    hidden_layer(i,:,:)= tf.nn.sigmoid(fc_layer(X, sizeInpOut, sizeInpOut))

导致 hidden_​​layer(i,:,:) = ... 出错 换句话说,我需要张量张量。

2 个答案:

答案 0 :(得分:1)

我这样做只是使用一个列表来保存不同的层,如下所示,似乎工作正常。

    # inputs
    x_size=2 # first layer nodes
    y_size=1 # final layer nodes
    h_size=[3,4,3] # variable length list of hidden layer nodes

    # set up input and output
    X = tf.placeholder(tf.float32, [None,x_size])
    y_true = tf.placeholder(tf.float32, [None,y_size])

    # set up parameters
    W = []
    b = []
    layer = []

    # first layer
    W.append(tf.Variable(tf.random_normal([x_size, h_size[0]], stddev=0.1)))
    b.append(tf.Variable(tf.zeros([h_size[0]])))

    # add hidden layers (variable number)
    for i in range(1,len(h_size)):
        W.append(tf.Variable(tf.random_normal([h_size[i-1], h_size[i]], stddev=0.1)))
        b.append(tf.Variable(tf.zeros([h_size[i]])))

    # add final layer
    W.append(tf.Variable(tf.random_normal([h_size[-1], y_size], stddev=0.1)))
    b.append(tf.Variable(tf.zeros([y_size])))

    # define model
    layer.append(tf.nn.relu(tf.matmul(X, W[0]) + b[0]))

    for i in range(1,len(h_size)):
        layer.append(tf.nn.relu(tf.matmul(layer[i-1], W[i]) + b[i]))

    if self.type_in == "classification":
        y_pred = tf.nn.sigmoid(tf.matmul(layer[-1], W[-1]) + b[-1])
        loss = tf.reduce_mean(-1. * ((y_true * tf.log(y_pred)) + ((1.-y_true) * tf.log(1.-y_pred))))
        correct_prediction = tf.equal(tf.round(y_pred), tf.round(y_true))
        metric = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        metric_name = "accuracy"

答案 1 :(得分:0)

不是直接答案,但您可以考虑使用tensorflow-slim。它是作为tensorflow的一部分分发的众多API之一。它是轻量级的,并且与您手动定义所有变量兼容。如果您查看我链接的网页,slim.repeatslim.stack允许您在一行中创建多个不同宽度的图层。为了使事情变得更复杂:我认为slim的一部分现在是tensorflow中名为layers的模块。

但也许您只想直接使用tf变量来理解它是如何工作的,而不是在以后使用更高级别的API。

在您发布的代码中,由于您要创建三个图层,因此您应该调用fc_layer三次,但只调用一次。顺便说一下,这意味着wb将被创建三个不同的时间,作为具有不同内部tf名称的不同变量。这就是你想要的。

你应该有一些for - 循环或while - 循环,它会迭代三次。请注意,循环结束时的输出张量将成为下一次迭代中的输入张量。初始输入是真输入,最后一个输出是真输出。

您的代码的另一个问题是非线性(sigmoid)应该在fc_layer的末尾。您希望在所有图层之间进行非线性操作。

编辑:通常会做的一些代码:

import tensorflow as tf

input_size = 10
output_size = 4
layer_sizes  = [7, 6, 5]

def fc_layer(input, size, layer_name):
    in_size = input.shape.as_list()[1]
    w = tf.Variable(tf.truncated_normal([in_size, size]),
                    name="W" + layer_name)
    b = tf.Variable(tf.constant(0.1, shape=[size]),
                    name="b" + layer_name)
    act = tf.nn.sigmoid(tf.matmul(input, w) + b)
    return act

input = tf.placeholder(tf.float32, [None, input_size])
# output will be the intermediate activations successively and in the end the
# final activations (output).
output = input
for i, size in enumerate(layer_sizes + [output_size]):
    output = fc_layer(output , size, layer_name=str(i + 1))

print("final output var: " + str(output))
print("All vars in the tensorflow graph:")
for var in tf.global_variables():
    print(var)

输出:

final output: Tensor("Sigmoid_3:0", shape=(?, 4), dtype=float32)

<tf.Variable 'W1:0' shape=(10, 7) dtype=float32_ref>
<tf.Variable 'b1:0' shape=(7,) dtype=float32_ref>
<tf.Variable 'W2:0' shape=(7, 6) dtype=float32_ref>
<tf.Variable 'b2:0' shape=(6,) dtype=float32_ref>
<tf.Variable 'W3:0' shape=(6, 5) dtype=float32_ref>
<tf.Variable 'b3:0' shape=(5,) dtype=float32_ref>
<tf.Variable 'W4:0' shape=(5, 4) dtype=float32_ref>
<tf.Variable 'b4:0' shape=(4,) dtype=float32_ref>

在您的代码中,您使用w的相同名称,这会产生冲突,因为会创建具有相同名称的不同变量。我在我的代码中修复了它,但即使你使用相同的名称,tensorflow也足够智能,并通过添加下划线和数字将每个变量重命名为唯一的名称。

编辑:这是我认为您想要做的事情:

import tensorflow as tf

hidden_size = 4
input_size = hidden_size  # equality required!
output_size = hidden_size # equality required!
n_hidden = 3

meta_tensor = tf.Variable(tf.truncated_normal([n_hidden, hidden_size, hidden_size]),
                    name="meta")

def fc_layer(input, i_layer):
    w = meta_tensor[i_layer]
    # more verbose: w = tf.slice(meta_tensor, begin=[i_layer, 0, 0], size=[1, hidden_size, hidden_size])[0]

    b = tf.Variable(tf.constant(0.1, shape=[hidden_size]),
                    name="b" + str(i_layer))
    act = tf.nn.sigmoid(tf.matmul(input, w) + b)
    return act

input = tf.placeholder(tf.float32, [None, input_size])
# output will be the intermediate activations successively and in the end the
# final activations (output).
output = input
for i_layer in range(0, n_hidden):
    output = fc_layer(output, i_layer)

print("final output var: " + str(output))
print("All vars in the tensorflow graph:")
for var in tf.global_variables():
    print(var)

输出:

final output var: Tensor("Sigmoid_2:0", shape=(?, 4), dtype=float32)

All vars in the tensorflow graph:
<tf.Variable 'meta:0' shape=(3, 4, 4) dtype=float32_ref>
<tf.Variable 'b0:0' shape=(4,) dtype=float32_ref>
<tf.Variable 'b1:0' shape=(4,) dtype=float32_ref>
<tf.Variable 'b2:0' shape=(4,) dtype=float32_ref>

正如我所说,这不是标准。编码时我也意识到它是非常有限的,因为所有隐藏层必须具有相同的大小。元张量可用于存储许多矩阵,但这些矩阵必须具有相同的维度。所以你不能像我在上面的例子中那样做,隐藏的第一层的大小为7,下一个大小为6,最后一个大小为5,在输出大小为4之前。