1

我從一個簡單的線性迴歸式網絡開始,使用Tensorflow編寫,主要基於其MNIST初學者教程。有7個輸入變量和1個輸出變量,都是連續的。與這個模型中,輸出均爲左右徘徊1,這是有意義的,因爲目標輸出設定在很大程度上是由的一,本值是占主導地位的由測試數據生成輸出樣本:添加隱藏層使輸出收斂於一個值 - Tensorflow

[ 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%之間。當檢查所得到的y值,目標的y值,並且從在多個訓練數據的單列交叉熵穿過其中目標輸出爲1,將得到的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) 

回答

1

有你的代碼的多個問題,其中許多人可能會導致網絡無法正常訓練:

  • 要初始化的重量和偏見與零值。它應該用一個小的隨機值(統一的或正態分佈的)進行初始化。
  • 您的網絡中沒有激活功能,因此只能建模線性關係。
  • 學習率是固定的,這是一個你需要調整的超參數。您還必須在訓練期間監測損失函數的值,以確保它正在減少並且收斂到一個很小的值。如果它不是那麼你應該而不是看輸出,因爲網絡沒有學到什麼。

此外,如果你沒有正常化輸入和輸出,你也應該這樣做。

+0

我將權重初始化函數更改爲random_normal,使用0.35的stddev。分配的標準偏差是需要調整的另一個超參數還是存在一個通用的最優stddev?另外,爲什麼在某些情況下將權重初始化爲零的任何想法都可以使用,但其他情況下卻不行 我再次嘗試使用random_normal作爲隱藏單位的權重和relu激活函數。現在輸出空間明顯不同了,這要歸功於響應。 – mudstick