6

私は機械学習の初心者であり、テンソルフローのチュートリアルに従って、MNIST データを学習するいくつかの単純なニューラル ネットワークを作成しています。

私は(チュートリアルに従って)単層ネットワークを構築しました。精度は約0.92で、私にとっては問題ありません。しかし、もう 1 つのレイヤーを追加したところ、精度が 0.113 に低下しました。これは非常に悪い結果です。

以下は、2 つのレイヤー間の関係です。

import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])

#layer 1
W1 = tf.Variable(tf.zeros([784, 100]))
b1 = tf.Variable(tf.zeros([100]))
y1 = tf.nn.softmax(tf.matmul(x, W1) + b1)

#layer 2
W2 = tf.Variable(tf.zeros([100, 10]))
b2 = tf.Variable(tf.zeros([10]))
y2 = tf.nn.softmax(tf.matmul(y1, W2) + b2)

#output
y = y2
y_ = tf.placeholder(tf.float32, [None, 10])

私の構造は大丈夫ですか?パフォーマンスが悪い理由は何ですか?ネットワークを変更するにはどうすればよいですか?

4

3 に答える 3

10

第 2 層の入力は、第softmax1 層の出力です。あなたはそれをしたくありません。

これらの値の合計を強制的に 1 にしています。ある値tf.matmul(x, W1) + b1が約 0 の場合 (そして、いくつかは確かにそうです)、softmax 操作はこの値を 0 に下げています。結果: 勾配を殺していて、何も流れません。これらのニューロン。

レイヤー間のソフトマックスを削除すると(ただし、値を確率と見なしたい場合は、出力レイヤーのソフトマックスのままにしておきます)、ネットワークは正常に機能します。

概要:

import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])

#layer 1
W1 = tf.Variable(tf.zeros([784, 100]))
b1 = tf.Variable(tf.zeros([100]))
y1 = tf.matmul(x, W1) + b1 #remove softmax

#layer 2
W2 = tf.Variable(tf.zeros([100, 10]))
b2 = tf.Variable(tf.zeros([10]))
y2 = tf.nn.softmax(tf.matmul(y1, W2) + b2)

#output
y = y2
y_ = tf.placeholder(tf.float32, [None, 10])
于 2016-07-01T07:43:56.573 に答える
0

まったく同じ問題に陥り、勾配が発散しnan、予測されyた . nessuno によって提案されたものを実装しましたが、残念ながら、発散する勾配はまだ修正されていません。

sigmoid代わりに、レイヤー1のアクティベーション関数として試してみましたが、うまくいきました! しかし、初期化され、ゼロ行列としてrelu機能しなかった場合、精度はわずか 0.1135 です。と の両方を機能させるには、との初期化をより適切にランダム化します。ここに変更されたコードがありますW1W2relusigmoidW1W2

import tensorflow as tf

x = tf.placeholder(tf.float32, [None, 784])

# layer 1
with tf.variable_scope('layer1'):
    W1 = tf.get_variable('w1',[784,200],
                         initializer=tf.random_normal_initializer())
    b1 = tf.get_variable('b1',[1,],
                         initializer=tf.constant_initializer(0.0))
    y1 = tf.nn.sigmoid(tf.matmul(x, W1) + b1)
#   y1 = tf.nn.relu(tf.matmul(x, W1) + b1) # alternative choice for activation

# layer 2
with tf.variable_scope('layer2'):
    W2 = tf.get_variable('w2',[200,10],
                     initializer= tf.random_normal_nitializer())
    b2 = tf.get_variable('b2',[1,],
                         initializer=tf.constant_initializer(0.0))
    y2 = tf.nn.softmax(tf.matmul(y1, W2) + b2)

# output
y = y2
y_ = tf.placeholder(tf.float32, [None, 10])

このリンクが役立つことがわかりました。質問 2 のパート (c) を参照してください。基本的な 2 層ニューラル ネットワークのバックプロパゲーション導関数が得られます。私の意見では、ユーザーがアクティベーション関数を指定しなかった場合、レイヤー 1 に線形フローを適用するだけで、最終的に のような勾配が逆伝播さ(sth)*W2^T*W1^Tれ、 と の両方を初期W1W2してゼロになると、それらの積は非常に大きくなる可能性がありますゼロに近く、勾配が消失します。

アップデート

これは、ニューラル ネットワークの適切な初期重みについてOfirが投稿した Quora の回答からのものです。

最も一般的な初期化は、ランダム初期化と Xavier 初期化です。ランダムな初期化では、標準分布 (通常は正規分布) から各重みを低い偏差でサンプリングするだけです。偏差が低いと、実際に重みを 0 に初期化することによる悪影響を与えることなく、ネットワークを「単純な」0 ソリューションに偏らせることができます。

于 2016-12-15T05:34:14.597 に答える