添加隐藏层使输出值趋于一个值 — Tensorflow

我从一个简单的线性回归风格的神经网络开始,使用Tensorflow编写,主要基于他们的MNIST初学者教程。这个网络有7个输入变量和1个输出变量,所有的变量都是连续的。使用这个模型,所有的输出值都徘徊在1左右,这在情理之中,因为目标输出集主要由1的值主导。这是测试数据生成的输出样本:

[ 0.95340264][ 0.94097006][ 0.96644485][ 0.95954728][ 0.93524933][ 0.94564033][ 0.94379318][ 0.92746377][ 0.94073343][ 0.98421943]

然而准确率从未超过84%,所以我决定添加一个隐藏层。现在输出值完全趋于一个单一的值,例如:

[ 0.96631247][ 0.96631247][ 0.96631247][ 0.96631247][ 0.96631247][ 0.96631247][ 0.96631247][ 0.96631247][ 0.96631247][ 0.96631247]

准确率保持在82-84%之间。在检查目标输出为1时,经过多次训练过程,获取的y值、目标y值和交叉熵从单行数据来看,获取的y值逐渐接近1:

[ 0.][ 1.]0.843537[ 0.03999992][ 1.]0.803543[ 0.07999983][ 1.]0.763534[ 0.11999975][ 1.]0.723541[ 0.15999967][ 1.]0.683544

然后在达到目标后,值徘徊在1左右:

[ 0.99136335][ 1.]0.15912[ 1.00366712][ 1.]0.16013[ 0.96366721][ 1.]0.167638[ 0.97597092][ 1.]0.163856[ 0.98827463][ 1.]0.160069

然而,当目标y值为0.5时,它表现得好像目标是1,接近0.5然后超过:

[ 0.47648361][ 0.5]0.378556[ 0.51296818][ 0.5]0.350674[ 0.53279752][ 0.5]0.340844[ 0.55262685][ 0.5]0.331016[ 0.57245618][ 0.5]0.321187

而交叉熵继续减少,好像实际上达到了目标:

[ 0.94733644][ 0.5]0.168714[ 0.96027154][ 0.5]0.164533[ 0.97320664][ 0.5]0.16035[ 0.98614174][ 0.5]0.156166[ 0.99907684][ 0.5]0.151983

打印测试数据的获取值、目标值和与目标的距离显示,无论目标y值如何,获取的y值都是相同的:

5[ 0.98564607][ 0.5][ 0.48564607]6[ 0.98564607][ 0.60000002][ 0.38564605]7[ 0.98564607][ 1.][ 0.01435393]8[ 0.98564607][ 1.][ 0.01435393]9[ 0.98564607][ 1.][ 0.01435393]

代码如下。a) 为什么在训练部分,算法将目标y值视为始终为1?b) 为什么在测试部分它产生相同的输出?即使它“认为”目标始终是1,测试输出也应该至少有一些变化,就像在训练输出中看到的那样。


import argparse
import dataset
import numpy as np
import os
import sys
import tensorflow as tf
FLAGS = None
def main(_):
    num_fields = 7
    batch_size = 100
    rating_field = 7
    outputs = 1
    hidden_units = 7
    train_data = dataset.Dataset("REPPED_RATING_TRAINING.txt", "    ", num_fields, rating_field)
    td_len = len(train_data.data)
    test_data = dataset.Dataset("REPPED_RATING_TEST.txt", " ", num_fields, rating_field)
    test_len = len(test_data.data)
    test_input = test_data.data[:, :num_fields].reshape(test_len, num_fields)
    test_target = test_data.fulldata[:, rating_field ].reshape(test_len, 1)
    graph = tf.Graph()
    with graph.as_default():
            x = tf.placeholder(tf.float32, [None, num_fields], name="x")
            W1 = tf.Variable(tf.zeros([num_fields, hidden_units]))
            b1 = tf.Variable(tf.zeros([hidden_units]))
            W2 = tf.Variable(tf.zeros([hidden_units, outputs]))
            b2 = tf.Variable(tf.zeros([outputs]))
            H = tf.add(tf.matmul(x, W1), b1, name="H")
            y = tf.add(tf.matmul(H, W2), b2, name="y")
            y_ = tf.placeholder(tf.float32, [None, outputs])
            yd = tf.abs(y_ - y)
            cross_entropy = tf.reduce_mean(yd)
            train_step = tf.train.GradientDescentOptimizer(0.04).minimize(cross_entropy)
            init = tf.global_variables_initializer()
            saver = tf.train.Saver()
    with tf.Session(graph=graph) as sess:
            sess.run(init)
            train_input, train_target = train_data.batch(td_len)
            for _ in range(FLAGS.times):
                    ts, yo, yt, ce = sess.run([train_step, y, y_, cross_entropy], feed_dict={x: train_input, y_:train_target})
                    #print obtained y, target y, and cross entropy from a given row over 10 training instances
                    print(yo[3])
                    print(yt[3])
                    print(ce)
                    print()
            checkpoint_file = os.path.join(FLAGS.model_dir, 'saved-checkpoint')
            print("\nWriting checkpoint file: " + checkpoint_file)
            saver.save(sess, checkpoint_file)
            test_input, test_target = test_data.batch(test_len)
            ty, ty_, tce, tyd = sess.run(
                    [y, y_, cross_entropy, yd],
                    feed_dict={x : test_input, y_: test_target})
            #print obtained y, target y, and distance to target for 10 random test rows
            for ix in range(10):
                    print(ix)
                    print(ty[ix])
                    print(ty_[ix])
                    print(tyd[ix])
            print()
            print('Ran times: ' + str(FLAGS.times))
            print('Acc: ' + str(1-tce))
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--times', type=int, default=100,
                    help='Number of passes to train')
    parser.add_argument('--model_dir', type=str,
            default=os.path.join('.', 'tmp'),
            help='Directory for storing model info')
    FLAGS, unparsed = parser.parse_known_args()
    tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

回答:

你的代码中存在多个问题,其中许多问题可能导致网络无法正确训练:

  • 你用零值初始化了权重和偏置。应该用一个小的随机值(均匀分布或正态分布)来初始化。
  • 你的网络中没有激活函数,这使得它只能建模线性关系。
  • 学习率是固定的,这是一个你需要调整的超参数。你还需要在训练过程中监控损失函数的值,以确保它在减少并收敛到一个较小的值。如果没有,那么你就不应该查看输出,因为网络没有学到任何东西。

另外,如果你没有对输入和输出进行归一化,你也应该这样做。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注