2017-09-11 70 views
2

私は、Udacityディープラーニングコースの課題の一部である10クラスの画像分類タスクに対して、単純な多層パーセプトロンを訓練しようとしています。より正確には、さまざまなフォントからレンダリングされた文字を分類することです(データセットはnotMNISTと呼ばれます)。Tensorflowでのトレーニング中のGPU使用量が非常に低い

私が結んだコードはかなりシンプルですが、トレーニング中にGPUの使用量が非常に少なくなっても問題はありません。 GPU-Zで負荷を測定したところ、わずか25-30%に過ぎません。

ここ

は私の現在のコードです:

graph = tf.Graph() 
with graph.as_default(): 
    tf.set_random_seed(52) 

    # dataset definition 
    dataset = Dataset.from_tensor_slices({'x': train_data, 'y': train_labels}) 
    dataset = dataset.shuffle(buffer_size=20000) 
    dataset = dataset.batch(128) 
    iterator = dataset.make_initializable_iterator() 
    sample = iterator.get_next() 
    x = sample['x'] 
    y = sample['y'] 

    # actual computation graph 
    keep_prob = tf.placeholder(tf.float32) 
    is_training = tf.placeholder(tf.bool, name='is_training') 

    fc1 = dense_batch_relu_dropout(x, 1024, is_training, keep_prob, 'fc1') 
    fc2 = dense_batch_relu_dropout(fc1, 300, is_training, keep_prob, 'fc2') 
    fc3 = dense_batch_relu_dropout(fc2, 50, is_training, keep_prob, 'fc3') 
    logits = dense(fc3, NUM_CLASSES, 'logits') 

    with tf.name_scope('accuracy'): 
     accuracy = tf.reduce_mean(
      tf.cast(tf.equal(tf.argmax(y, 1), tf.argmax(logits, 1)), tf.float32), 
     ) 
     accuracy_percent = 100 * accuracy 

    with tf.name_scope('loss'): 
     loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y)) 

    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) 
    with tf.control_dependencies(update_ops): 
     # ensures that we execute the update_ops before performing the train_op 
     # needed for batch normalization (apparently) 
     train_op = tf.train.AdamOptimizer(learning_rate=1e-3, epsilon=1e-3).minimize(loss) 

with tf.Session(graph=graph) as sess: 
    tf.global_variables_initializer().run() 
    step = 0 
    epoch = 0 
    while True: 
     sess.run(iterator.initializer, feed_dict={}) 
     while True: 
      step += 1 
      try: 
       sess.run(train_op, feed_dict={keep_prob: 0.5, is_training: True}) 
      except tf.errors.OutOfRangeError: 
       logger.info('End of epoch #%d', epoch) 
       break 

     # end of epoch 
     train_l, train_ac = sess.run(
      [loss, accuracy_percent], 
      feed_dict={x: train_data, y: train_labels, keep_prob: 1, is_training: False}, 
     ) 
     test_l, test_ac = sess.run(
      [loss, accuracy_percent], 
      feed_dict={x: test_data, y: test_labels, keep_prob: 1, is_training: False}, 
     ) 
     logger.info('Train loss: %f, train accuracy: %.2f%%', train_l, train_ac) 
     logger.info('Test loss: %f, test accuracy: %.2f%%', test_l, test_ac) 

     epoch += 1 

ここで私はこれまで試したものです:

  1. 私はシンプルfeed_dictからtensorflow.contrib.data.Datasetに入力パイプラインを変更しました。私が理解する限り、それは入力の効率を処理することになっています。データを別のスレッドにロードします。したがって、入力に関連したボトルネックはないはずです。

  2. ここに示唆したようにトレースを収集しました:https://github.com/tensorflow/tensorflow/issues/1824#issuecomment-225754659 しかし、これらのトレースは実際には何も興味深いものを表示しませんでした。列車のステップの90%以上がマットル操作です。

  3. 変更されたバッチサイズ。私がそれを128から512に変更すると、負荷は〜30%から〜38%に増加し、さらに2048に増加すると負荷は〜45%になります。私は6GbのGPUメモリを持っており、データセットは1チャンネルの28x28画像です。私は本当にそのような大きなバッチサイズを使用するはずですか?私はそれをさらに増やすべきですか?

一般的に、低負荷について心配する必要がありますか、それは実際に私が非効率的にトレーニングしているという兆候ですか?

ここには、128個の画像が入ったGPU-Zスクリーンショットがあります。各エポック後にデータセット全体の精度を測定すると、時折スパイクが100%になる低負荷が確認できます。

GPU load

答えて

4

MNISTサイズのネットワークが小さなであり、それが彼らのために高いGPU(またはCPU)の効率を達成するのは難しい、私は30%があなたのアプリケーションのために珍しいことではないと思います。バッチサイズが大きいほど計算効率が向上し、1秒あたりのサンプル数を増やすことができますが、統計効率は低くなります。つまり、目標を達成するためにさらに多くのサンプルを処理する必要があります。それはトレードオフです。あなたのような小さなキャラクターモデルの場合、統計効率は100回後に急速に低下しますので、トレーニング用にバッチサイズを大きくすることは価値がないでしょう。推論のために、可能な限り大きなバッチサイズを使用する必要があります。

+0

非常に速い返信をありがとう!ヤロスラフ、なぜこれが起こるのかヒントを教えてもらえますか?私の前提は次の通りです。その時点で1つのトレーニングステップが実行されている限り、すべてのGPUコアを飽和させるだけの計算が不十分です。だから、私が128イメージのバッチをフィードすると、それはできるだけ平行して実行されますが、それ以上のことができます。 –

+1

はい、コアを飽和させるのに十分な計算がありません。また、必要なメモリ帯域幅やカーネル起動のオーバーヘッドに比べて計算量が少ない場合は、効率が悪いです。注目すべきより重要なことは、GPU占有率よりも​​全体的な効率性です。 TitanXの大きなmatmulは毎秒10Topを得ますが、多くのアプリケーションでは1Top /秒以下で動作するため、ピーク効率の10%未満です –

0

私のnVidia GTX 1080では、畳み込みニューラルネットワークをMNISTデータベースで使用すると、GPUの負荷は約68%です。

単純な非畳み込みネットワークに切り替えると、GPUの負荷は約20%です。

チュートリアルBuilding Autoencoders in Keras by Francis Cholletでより高度なモデルを連続して構築することで、これらの結果を再現できます。

関連する問題