【问题标题】:Trained neural network produces different predictions with same data (TensorFlow)经过训练的神经网络使用相同的数据产生不同的预测(TensorFlow)
【发布时间】:2018-11-15 07:54:36
【问题描述】:

我已经使用 TensorFlow 训练了一个神经网络。训练后,我保存它并再次将其加载到新的 '. py' 文件以避免意外再培训。当我用一些额外的数据对其进行测试时,我发现它为相同的数据预测了不同的事情。理论上不应该为相同的数据计算相同的东西吗?

一些信息 前馈网络
4 个隐藏层,每个隐藏层 900 个神经元
5000 个训练周期
达到约 80% 的准确度
使用来自 sklearn 的 normalize 对数据进行标准化。预处理
成本函数:tensorflow.nn.softmax_cross_entropy_with_logits
优化器:tf.train.AdamOptimizer
我将数据作为矩阵提供给我的网络,就像我用于训练的方式一样。 (每行包含一个数据样本,列与输入神经元一样多)

在十个具有相同数据的预测周期中,我的网络在至少 2 个周期内产生不同的结果(到目前为止最多观察到 4 个) 怎么会这样。从理论上讲,所有发生的事情都是 W_i*x_i + b_i 形式的数据处理计算。由于我的 x_i、W_i 和 b_i 不再变化,为什么预测会发生变化?模型重新加载例程可能有错误吗?

with tf.Session() as sess:  
    saver = tf.train.import_meta_graph('path to .meta')  
    saver.restore(sess, tf.train.latest_checkpoint('path to checkpoints'))  
    result = (sess.run(tf.argmax(prediction.eval(feed_dict=x:input_data}),1)))  
    print(result)  

【问题讨论】:

  • 可能在某处使用了一些您未定义但随机初始化的权重?
  • 检查两件事。 .pb 文件的行为是否相同?如何生成 input_data?
  • 我使用 tf train Saver。这将我的网络保存为 xy ckpt。标准例程保存几个文件:xy ckpt 数据、xy ckpt 元数据、xy ckpt 索引和检查点。我将尝试使用 .pb 并讲述我的观察结果。我使用 matplotlib pyplot 读取我的图像,使用来自 sklearn 的 normalize 对其进行标准化,将其分解为一维数组并将其打包到一个列表中,然后使用 dtype float32 转换为 numpy 数组。
  • 我用 .pb 文件格式测试过。 -> 没有变化我尝试逐行输入我的数据 -> 没有变化最奇怪的是,它要么将所有给定的数据正确分类,要么将所有给定的数据分类错误,预测中没有变化(比如 80 个正确的 100 个)

标签: python tensorflow machine-learning neural-network


【解决方案1】:

所以这对我来说是一个非常愚蠢的错误。现在它可以很好地从保存中加载模型。问题是由全局变量初始化程序引起的。如果你把它排除在外,它会工作得很好。以前找到的信息可能对某人有用,所以我将其留在这里。现在的解决方案是:

saver = tf.train.Saver()
with tf.Session() as sess:
    saver.restore(sess, 'path to your saved file C:x/y/z/model/model.ckpt')

在此之后,您可以照常进行。我真的不知道为什么变量初始化程序会阻止它工作。正如我所看到的,它应该是这样的:初始化所有变量以存在并使用随机值,然后进入该保存的文件并使用那里的值,但显然还有其他事情发生......

【讨论】:

    【解决方案2】:

    所以我一直在做一些测试,并发现了关于这个问题的以下内容。 因为我一直在尝试重用我创建的模型,所以我不得不使用 tf.global_variables_initializer()。通过这样做,它覆盖了我导入的图表,并且所有值都是随机的,这解释了不同的网络输出。这仍然给我留下了一个需要解决的问题:我如何加载我的网络?到目前为止,我目前使用的解决方法并不是最佳的,但它至少允许我使用我保存的模型。张量流允许为使用的函数和张量赋予唯一的名称。通过这样做,我可以通过图表访问它们:

    with tf.Session() as sess:
        saver = tf.train.import_meta_graph('path to .meta')  
        saver.restore(sess, tf.train.latest_checkpoint('path to checkpoints'))
        graph = tf.get_default_graph()
        graph.get_tensor_by_name('name:0')
    

    使用这种方法我可以访问我保存的所有值,但它们是分开的!这意味着每次使用的操作我有 1 倍的权重和 1 倍的偏差,这导致了一堆新的变量。如果您不知道名称,请使用以下内容:

    print(graph.get_all_collection_keys())
    

    这会打印集合名称(我们的变量存储在集合中)

    print(graph.get_collection('name'))
    

    这使我们可以访问集合,以查看变量的名称/键。

    这导致了另一个问题。我不能再使用我的模型,因为全局变量初始化程序已经覆盖了所有内容。因此,我不得不用我之前得到的权重和偏差手动重新定义整个模型。

    不幸的是,这是我唯一能想到的。如果有人有更好的想法,请告诉我。

    有错误的整个事情看起来像这样:

    imports...
    placeholders for data...
    
    def my_network(data):
        ## network definition with tf functions ##
    return output
    
    def train_my_net():
        prediction = my_network(data)
        cost function
        optimizer
        with tf.Session() as sess:
            for i in how many epochs i want:
                training routine
                save
    
    def use_my_net():
        prediction = my_network(data)
        with tf.Session() as sess:
            sess.run(tf.global_variables_initializer())
            saver = tf.train.import_meta_graph('path to .meta')  
            saver.restore(sess, tf.train.latest_checkpoint('path to checkpoints'))
            print(sess.run(prediction.eval(feed_dict={placeholder:data})))
    graph = tf.get_default_graph()
    

    【讨论】:

      猜你喜欢
      • 2019-05-19
      • 1970-01-01
      • 2017-05-23
      • 2020-03-15
      • 1970-01-01
      • 2017-08-14
      • 2017-09-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多