機械学習のユニットテスト方法

機械学習のユニットテスト方法

過去 1 年間、私は仕事時間のほとんどをディープラーニングの研究とインターンシップに費やしてきました。その年、私は多くの大きなミスを犯しましたが、それによって ML だけでなく、これらのシステムを正しく堅牢に設計する方法も理解することができました。 Google Brain で私が学んだ主な原則の 1 つは、ユニット テストによってアルゴリズムが成功するか失敗するかが決まり、デバッグとトレーニングに要する数週間の時間を節約できるということです。

[[285889]]

しかし、ニューラル ネットワーク コードの単体テストの書き方に関するしっかりしたオンライン チュートリアルは存在しないようです。 OpenAI のような場所でも、コードのすべての行をじっくりと見て、なぜバグが発生するのかを考えるだけで、バグを見つけることができます。明らかに、ほとんどの人にはそんな時間はありません。ですから、このチュートリアルが、システムの健全なテストを始めるのに役立つことを願っています。

簡単な例から始めましょう。このコード内のエラーを見つけてみてください。

  1. def make_convnet(入力画像):
  2. ネット= slim.conv2d (入力画像、32、[11、11]、スコープ= "conv1_11x11" )
  3. ネット=スリム.conv2d(input_image, 64, [5, 5],スコープ= "conv2_5x5" )
  4. ネット=スリム.max_pool2d(ネット、[4, 4]、ストライド= 4 スコープ= 'pool1' )
  5. ネット= slim.conv2d (入力画像、64、[5、5]、スコープ= "conv3_5x5" )
  6. ネット= slim.conv2d (入力画像、128、[3、3]、スコープ= "conv4_3x3" )
  7. ネット=スリム.max_pool2d(ネット、[2, 2]、スコープ= 'pool2' )
  8. ネット= slim.conv2d (入力画像、128、[3、3]、スコープ= "conv5_3x3" )
  9. ネット=スリム.max_pool2d(ネット、[2, 2]、スコープ= 'pool3' )
  10. ネット= slim.conv2d (入力画像、32、[1、1]、スコープ= "conv6_1x1" )
  11. リターンネット

見ましたか? ネットワークは実際には機能していませんでした。このコードを書くとき、slim.conv2d(...) 行をコピーして貼り付け、実際の入力を変更せずにカーネル サイズのみを変更しました。

恥ずかしながら、これは 1 週間前に私に起こったことです... しかし、これは重要な教訓です。 これらのバグは、いくつかの理由から見つけるのが困難です。

  • このコードはクラッシュせず、エラーも発生せず、速度も低下しません。
  • ネットワークはまだ機能しており、損失は減少し続けています。
  • 数時間後には値は収束しますが、結果が非​​常に悪いため、何を修正する必要があるのか​​頭を悩ませることになるでしょう。

唯一のフィードバックが最終的な検証エラーである場合、検索する必要があるのはネットワーク アーキテクチャ全体だけです。言うまでもなく、より良いシステムが必要です。

では、複数日にわたるトレーニングを実行する前に、これを実際にどのように活用すればよいのでしょうか。これについて最も簡単に気付くのは、レイヤーの値が関数の外部にある他のテンソルに実際には到達しないということです。何らかのタイプの損失とオプティマイザーがあると仮定すると、これらのテンソルは最適化されることはなく、常にデフォルト値を持ちます。

簡単なトレーニング手順と前後の比較で検出できます。

  1. test_convnet() を定義します:
  2. 画像= tf.placeholder (tf.float32, (なし, 100, 100, 3)
  3. model =モデル(画像)
  4. sess = tf .セッション()
  5. sess.run(tf.global_variables_initializer())
  6. before = sess .run(tf.trainable_variables())
  7. _ = sess.run (model.train、 feed_dict = {
  8. 画像: np.ones((1, 100, 100, 3)),
  9. })
  10. after = sess .run(tf.trainable_variables())
  11. zip 内の b、a、n の場合(前、後):
  12. # 何か変更があったか確認してください。
  13. アサート (b != a).any()

15 行未満のコードで、少なくとも作成したすべての変数がトレーニングされることが確認できました。

このテストは非常に簡単で非常に便利です。以前の問題を修正したと仮定すると、バッチ正規化の追加を開始できます。バグを見つけられるかどうか確認してください。

  1. def make_convnet(image_input):
  2. # 畳み込みを行う前に入力を正規化してみる
  3. ネット= slim.batch_norm (画像入力)
  4. ネット= slim.conv2d (ネット、32、[11、11]、スコープ= "conv1_11x11" )
  5. ネット=スリム.conv2d(ネット, 64, [5, 5],スコープ= "conv2_5x5" )
  6. ネット=スリム.max_pool2d(ネット、[4, 4]、ストライド= 4 スコープ= 'pool1' )
  7. ネット=スリム.conv2d(ネット, 64, [5, 5],スコープ= "conv3_5x5" )
  8. ネット=スリム.conv2d(ネット, 128, [3, 3],スコープ= "conv4_3x3" )
  9. ネット=スリム.max_pool2d(ネット、[2, 2]、スコープ= 'pool2' )
  10. ネット= slim.conv2d (ネット、128、[3、3]、スコープ= "conv5_3x3" )
  11. ネット=スリム.max_pool2d(ネット、[2, 2]、スコープ= 'pool3' )
  12. ネット= slim.conv2d (ネット、32、[1、1]、スコープ= "conv6_1x1" )
  13. リターンネット

見ましたか?これは非常に微妙です。 tensorflow batch_norm では is_training のデフォルト値が False になっているため、このコード行を追加してもトレーニング中に入力が正規化されないことがわかります。ありがたいことに、最後に書いた単体テストでこの問題はすぐに検出されます。(3 日前に私に起こったことなので、私は知っています。)

別の例を見てみましょう。これは先日読んだ記事から来ています

(https://www.reddit.com/r/MachineLearning/comments/6qyvvg/p_tensorflow_response_is_making_no_sense/)。あまり詳しく説明しませんが、基本的にこの人は (0,1) の範囲の値を出力する分類器を作成したいと考えています。

  1. クラスモデル:
  2. def __init__(自己、入力、ラベル):
  3. 「分類器モデル」
  4. 引数:
  5. input: サイズの入力テンソル (None, input_dims)
  6. label: サイズのラベルテンソル (なし、1)。
  7. tf.int32 型である必要があります。
  8. 「」
  9. 予測= self.make_network (入力)
  10. # 予測サイズは (なし、1) です。
  11. 自己損失= tf.nn.softmax_cross_entropy_with_logits (
  12. logits =予測 labels labels = ラベル)
  13. self.train_op = tf .train.AdamOptimizer().minimize(self.loss)

この間違いに気づきましたか? これを事前に見つけるのは非常に難しく、非常に混乱した結果につながる可能性があります。基本的に、ここで起こっていることは、予測には出力が 1 つだけあり、それにソフトマックス クロス エントロピーを適用すると、その損失は常に 0 になるということです。

これをテストする簡単な方法は、損失が 0 でないことを確認することです。

  1. テスト損失()を定義します:
  2. in_tensor = tf .placeholder(tf.float32, (なし、3))
  3. ラベル= tf .placeholder(tf.int32, None, 1))
  4. model =モデル(in_tensor, ラベル)
  5. sess = tf .セッション()
  6. 損失= sess.run (model.loss, feed_dict = {
  7. in_tensor:np.ones(1, 3)、
  8. ラベル:[[1]]
  9. })
  10. 損失が 0 ではないと主張

もう 1 つの優れたテストは、最初のテストと似ていますが、逆の順序です。トレーニングしたい変数だけがトレーニングされるようにすることができます。 GAN を例に挙げてみましょう。よくある間違いは、最適化を行う際にトレーニングする変数を誤って設定し忘れてしまうことです。このようなコードは頻繁に発生します。

  1. クラスGAN:
  2. def __init__(self, z_vector, true_images):
  3. # これらが実装されていると仮定します。
  4. tf.variable_scope("gen") を使用する場合:
  5. 自己ジェネレーターの作成(z_vector)
  6. tf.variable_scope("des") の場合:
  7. 自己.make_descriminator(true_images)
  8. opt = tf .AdamOptimizer()
  9. train_descrim = opt .minimize(self.descrim_loss)
  10. train_gen = opt .minimize(self.gen_loss)

ここでの最大の問題は、オプティマイザーがすべての変数を最適化するというデフォルト設定を持っていることです。 GAN のような高度なアーキテクチャでは、これはすべてのトレーニング時間の死刑宣告に相当します。ただし、次のようなテストを記述することで、これらのエラーを簡単に検出できます。

  1. test_gen_training() を定義します:
  2. モデル=モデル 
  3. sess = tf .セッション()
  4. gen_vars = tf .get_collection(tf.GraphKeys.VARIABLES、スコープ= 'gen' )
  5. des_vars = tf .get_collection(tf.GraphKeys.VARIABLES、スコープ= 'des' )
  6. before_gen = sess.run (gen_vars)
  7. before_des = sess .run(des_vars)
  8. # ジェネレータをトレーニングします。
  9. セッションを実行します(model.train_gen)
  10. after_gen = sess.run (gen_vars)
  11. after_des = sess .run(des_vars)
  12. # ジェネレータ変数が変更されたことを確認します。
  13. zip(before_gen, after_gen)内のb、aの場合:
  14. アサート (a != b).any()
  15. # 識別子が変更されていないことを確認してください。
  16. zip(before_des, after_des)内のb、aの場合:
  17. アサート ( a == b ).all()

非常によく似たテストを識別子に対しても記述できます。同じテストを多くの強化学習アルゴリズムに適用できます。多くのアクター・クリティック・モデルには、さまざまな損失に基づいて最適化する必要がある個別のネットワークがあります。

テストすることをお勧めするパターンをいくつか紹介します。

  • テストを決定論的にします。テストが奇妙な形で失敗し、バグを再現できない場合は最悪です。本当にランダムな入力が必要な場合は、テストを簡単に再実行できるように、シードされた乱数を使用してください。
  • テストは短くしてください。収束をトレーニングし、検証セットをチェックするためにユニット テストを使用しないでください。そんなことをして時間を無駄にしていることになります。
  • 各テスト間で計算グラフを必ずリセットしてください。

まとめると、これらのブラックボックス アルゴリズムをテストする方法はまだたくさんあります。1 時間かけてテストを作成すると、トレーニング済みのモデルを再実行する時間が節約され、研究の効率が大幅に向上します。実装に欠陥があるために完璧さというアイデアを諦めなければならないのは残念ではないでしょうか?

このリストは明らかに包括的なものではありませんが、確かなスタートとなります。

<<:  「中国製チップ」の20年と新たな時代

>>:  初心者の機械学習エンジニアが犯しがちな6つの間違い

ブログ    
ブログ    
ブログ    

推薦する

ロボットは人工知能技術に基づいて人間の表情を作る

信頼関係を築く上で、私たちの表情が果たす役割は非常に大きいにもかかわらず、ほとんどのロボットの顔はプ...

人工知能が伝統文化に新たな命を吹き込む。パンダ型ロボット「Youyou」が国境を越えて「新年クロストーク会議」に参加

「パンダはトークができる、パンダはジョークを言うことができる、パンダは書道を書ける、そしてパンダはチ...

...

7つの機械学習アルゴリズムの7つの重要なポイント

さまざまなライブラリとフレームワークの助けを借りて、たった 1 行のコードで機械学習アルゴリズムを実...

新技術により大規模人工知能モデルの処理性能が効果的に向上

MIT と Nvidia の研究者は、高性能コンピューティング タスクで使用されるデータ構造であるス...

GPTモデルが人間のように聞こえるのはそのためです

翻訳者 | 劉涛レビュー | Chonglou AIがなぜ機能するのか誰も知らないですよね?はい、そ...

...

清華大学とハルビン工業大学は大規模なモデルを 1 ビットに圧縮し、携帯電話で大規模なモデルを実行するという夢が実現しつつあります。

ビッグモデルが普及して以来、ビッグモデルを圧縮したいという人々の欲求は減ることはありません。大規模モ...

フィードフォワードネットワーク + 線形相互作用層 = 残差 MLP、Facebook の純粋な MLP 画像分類アーキテクチャが市場に参入

[[398872]]最近では、多層パーセプトロン (MLP) が CV 分野の重要な研究テーマとなっ...

AIとIoTの長所と短所

モノのインターネットは、私たちがテクノロジーや周囲の世界と関わる方法に革命をもたらしました。 データ...

人工知能への恐怖とその対処法5つ

AI テクノロジーを導入する IT リーダーは、ある程度の不安を感じるかもしれませんが、それには十分...

...

3Dタスク(知覚、推論、計画、行動)に精通した初の具現化されたジェネラリストエージェント

汎用人工知能へと進むには、人間の生活の現実世界を理解し、豊富なスキルを習得できる具現化された汎用イン...

ガートナー: 高等教育における人工知能

人工知能 (AI) は高等教育に大きな進歩を遂げており、何らかの形で AI を導入した教育機関は、学...

江長建、世界初のサイボーグと対談 - JD Smart Community 2.0 全国ローンチカンファレンス ライブプレビュー

[[374688]] 「半オーク」「半魚」… SF映画、漫画、おとぎ話では、それは驚くことではありま...