在Python多维列表中存储TensorFlow网络权重

时间:2018-03-15 18:13:35

标签: python tensorflow machine-learning neural-network

我对TensorFlow和Python都很陌生,所以请原谅我发布这样一个基本问题,但我有点不知所措,一次学习这两件事。 编辑:我自己找到了一个解决方案并将其发布在下面,然而,更有效的解决方案很受欢迎

问题的简短版本:如何使用TensorFlow从神经网络中提取每个权重和偏差,并将其存储到形状为[layers] [neurons-previous-layer] [[]]的Python数组中神经元电流层。目标不是存储在硬盘上,而是存储在与最后一个代码snipet下面解释的形状和类型相同的变量中。我也想知道,这是最有效的方法。

我想要执行的任务是创建一个具有预先训练的权重和偏差的神经网络(不是从Tensor获得,而是从完全不同的来源获得),使用Tensor优化训练,然后将精确的权重返回给程序。

我已经研究了如何在Tensor Flow中创建NN,以及根据一些Tensor教程和一些不相关的内容,使用以前在Python中创建的列表来初始化网络权重的方法。来自StackOverflow的问题。

所以,我的问题是,如果在TensorFlow中有一个训练有素的网络,我怎样才能以尽可能最快的方式提取变量(我的网络有大约2800万个权重和偏差)的每个权重和偏差?(请记住,此操作将一遍又一遍地重复)

为了澄清这个问题,请参阅以下代码:

首先,整个网络创建和培训过程(网络布局除外)基于这篇文章: Autoencoder Example

此示例代码的相关部分如下(我剪切输出部分,因为没有必要解释我创建网络的方式):

num_hidden_1 = 256 # 1st layer num features
num_hidden_2 = 128 # 2nd layer num features (the latent dim)
num_input = 784 # MNIST data input (img shape: 28*28)
X = tf.placeholder("float", [None, num_input])

weights = {
    'encoder_h1': tf.Variable(tf.random_normal([num_input, num_hidden_1])),
    'encoder_h2': tf.Variable(tf.random_normal([num_hidden_1, num_hidden_2])),
}
biases = {
    'encoder_b1': tf.Variable(tf.random_normal([num_hidden_1])),
    'encoder_b2': tf.Variable(tf.random_normal([num_hidden_2])),
}

# Building the encoder
def encoder(x):
    # Encoder Hidden layer with sigmoid activation #1
    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']),
                                   biases['encoder_b1']))
    # Encoder Hidden layer with sigmoid activation #2
    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']),
                                   biases['encoder_b2']))
return layer_2

我为生成神经网络而创建的代码如下:

def create_network(layout, funciones, pesos, biases):
    capas = [tf.placeholder("float", [None, layout[0]])]
    for i in range(0, len(pesos)):
        #There's an element already, so capas[i] is the previous layer
        capas.append(tf.layers.dense(capas[i], layout[i+1], activation=funciones[i],
                                            kernel_initializer=tf.constant_initializer(pesos[i], dtype=tf.float32),
                                            bias_initializer=tf.constant_initializer(biases[i], dtype=tf.float32)))

    return capas

代码说明: 比索和偏差三维列表包含权重("比索")和TensorFlow格式的偏差可以接受。 Capas是一个包含网络所有层的数组。 " funcciones []",它是ATM一个测试全局变量来调整NN的激活功能,它应该是" layout"的一部分,但我只是测试现在。布局是一个数组,包含网络中每个图层的大小。 Layout [0]包含输入图层上的神经元数量,第一个隐藏图层上的布局1,依此类推。

比索和偏差格式:第一级元素与网络层-1一样多(输入不需要权重或偏差)。在第二级,它具有与PREVIOUS层中存在的神经元一样多的元素,第三级具有与此列表中的神经元一样多的元素。第2级和第3级的形状与示例中tf.random_normal([num_input, num_hidden_1])

生成的形状相同

我的问题是: 假设我使用相同的结构来执行我的NN而不是上面提供的示例中使用的NN,我怎样才能将训练好的权重和偏差存储在两个三维列表中,其结构与结果相同在我的代码中提供,这是最快的方法

副问题:有没有比上面提到的更有效的方法来构建/执行我的NN?这个的好参考也被接受作为答案。

2 个答案:

答案 0 :(得分:1)

如何使用tf.trainable_variables()

这将返回所有可训练参数的列表,因为它是张量流模型,我认为它已经过优化。

您可以通过tensorname访问此列表中的特定权重:

variable = [weight for weights in tf.trainable_variables() if weight.name == name_my_var]

答案 1 :(得分:0)

我找到了解决方案并构建了一个工作功能。命名约定与我自己的问题相同。我必须手动命名图层,否则它会在前一层上放置权重和偏差(我检查了图形,最后它连接正确,但脚本无法正确提取它们)

def extraer_pesos(red, session):
    pesos = []
    biases = []
    for i in range(1, len(red)):
        pesos.append(session.run(tf.get_default_graph().get_tensor_by_name(
            os.path.split(red[i].name)[0] + '/kernel:0')).tolist())
        biases.append(session.run(tf.get_default_graph().get_tensor_by_name(
            os.path.split(red[i].name)[0] + '/bias:0')).tolist())
    return pesos, biases


def create_network(layout, funciones, pesos,biases):
    capas = [(tf.placeholder("float", [None, layout[0]])]
    for i in range(0, len(pesos)):
        #There's an element already, so capas[i] is the previous layer
        capas.append(tf.layers.dense(capas[i], layout[i+1], activation=funciones[i],
                                            kernel_initializer=tf.constant_initializer(pesos[i], dtype=tf.float32),
                                            bias_initializer=tf.constant_initializer(biases[i], dtype=tf.float32),
                                             name="layer"+str(i)))

    return capas

请记住,必须初始化变量。如果您在培训网络后提取他们,那么就不应该有任何问题。