なぜ15分でスーパーメガプロの機械学習がならないのか

昨日、機械学習とNVIDIA DIGITSに関する記事を公​​開しまし 。 約束されたように、今日の記事はすべてがそれほど良くない理由+ DIGITSのフレーム内のオブジェクトを選択する例です。



NVIDIAは、DIGITSで開発および実装されたDetectNetグリッドに関するPRを開始しました。 グリッドは、画像内の同じ/類似したオブジェクトを見つけるためのソリューションとして配置されます。







これは何ですか



年の初めに、私何度か面白いネットYolo について言及しました。 一般に、私が話したすべての人々は、Faster-RCNNの方がはるかに速くて簡単であるという言葉で彼女にかなり否定的に反応しました。 しかし、NVIDIAのエンジニアはこれに触発され、グリッドをCaffeで組み立ててDetectNetと呼びました。

グリッドの原理は、Yoloと同じです。 画像のネットワーク出力(N * a * N * a)は配列N * N * 5であり、サイズa * aの元の画像の各領域に対して、5つのパラメーターが入力されます:オブジェクトの存在とサイズ:



画像






プラスメッシュ:





1つマイナス:より良い検出のソリューションがあります。



話を始める前の一般的な言葉



昨日書いたカテゴリ認識とは異なり、オブジェクトの検出は不十分です。 ユーザーフレンドリーではありません。 記事のほとんどは、この奇跡を起こす方法に関するものです。 残念ながら、このアプローチは、システムとその数学のロジックを理解せずに何かを行うことができるというDIGITSの当初のアイデアを殺します。

ただし、まだ開始している場合は、使用すると便利です。



何を認識しますか



数年前、私たちは車の番号について完全にクレイジーなアイデアを持っていました。 その結果、一連の記事が作成されました。 私たちが投稿した写真のまともなデータベースが含まれていました。



私は開発の一部を使用し、DIGITSを通じて数字を検出することにしました。 したがって、それらを使用します。



正しい方法でマークアップされたベースは、他の目的には非常に小さかったです。 しかし、訓練するのに十分。



行こう



メインメニューで[新しいデータセット]-> [画像]-> [オブジェクト検出]を選択すると、データセットを作成するためのメニューが表示されます。 ここで指定する必要があります:





困難があります。 説明付きの画像にテキスト署名を作成する方法は? 公式のDIGITSリポジトリにあるNVIDIA Github の例では、これについては控えめに言及していますが、kittiデータセットの場合と同じであるとのみ言及しています。 すぐに使えるフレームワークのユーザーに対するこのアプローチには、多少驚きました。 しかし、約 私は行って、ベースをダウンロードし、そこにドッキングし、それを読みました。 ファイル形式:



Car 0.00 0 1.95 96.59 181.90 405.06 371.40 1.52 1.61 3.59 -3.49 1.62 7.68 1.53 Car 0.00 0 1.24 730.55 186.66 1028.77 371.36 1.51 1.65 4.28 2.61 1.69 8.27 1.53 Car 0.00 0 1.77 401.35 177.13 508.22 249.68 1.48 1.64 3.95 -3.52 1.59 16.82 1.57
      
      





ファイルの説明:



 #Values Name Description ---------------------------------------------------------------------------- 1 type Describes the type of object: 'Car', 'Van', 'Truck', 'Pedestrian', 'Person_sitting', 'Cyclist', 'Tram', 'Misc' or 'DontCare' 1 truncated Float from 0 (non-truncated) to 1 (truncated), where truncated refers to the object leaving image boundaries 1 occluded Integer (0,1,2,3) indicating occlusion state: 0 = fully visible, 1 = partly occluded 2 = largely occluded, 3 = unknown 1 alpha Observation angle of object, ranging [-pi..pi] 4 bbox 2D bounding box of object in the image (0-based index): contains left, top, right, bottom pixel coordinates 3 dimensions 3D object dimensions: height, width, length (in meters) 3 location 3D object location x,y,z in camera coordinates (in meters) 1 rotation_y Rotation ry around Y-axis in camera coordinates [-pi..pi] 1 score Only for results: Float, indicating confidence in detection, needed for p/r curves, higher is better.
      
      





当然、ここではほとんどのパラメーターは不要です。 実際には、「bbox」パラメータのみを残すことができ、残りはまだ使用されません。



後で判明したように、ファイル形式がまだ署名されているDIGITSの別のチュートリアルがありました。 しかし、彼はリポジトリにありませんでしたDIGITS¯\ _(ツ)_ /¯



使用するものについての私の推測が正しいことを確認しました:



画像



教え始める



クラス。 ベースが完成し、トレーニングを開始します。 トレーニングのために、 例で指定されているのと同じ設定を設定する必要があります。





また、私は次のことをしました。 コピーしたグリッド「detectnet_network.prototxt」について、すべての画像サイズの値「1248、352」をデータベースの画像のサイズに置き換えました。 これがなければ、学習は落ちました。 まあ、もちろん、チュートリアルのどれもこれを持っていません...¯\ _(ツ)_ /¯



損失チャートはダウンし、学習は終了しました。 しかし...精度チャートはゼロです。 なに?

私が見つけた2つのチュートリアルのいずれも、この質問に答えていません。 グリッドの説明を詳しく調べに行きました。 掘る場所は、すぐに明らかになりました。 損失が減ると、トレーニングが続きます。 検証パイプラインのエラー。 そして本当に。 ネットワーク構成にブロックがあります:



 layer { name: "cluster" type: "Python" bottom: "coverage" bottom: "bboxes" top: "bbox-list" python_param { module: "caffe.layers.detectnet.clustering" layer: "ClusterDetections" param_str: "1024, 640, 16, 0.05, 1, 0.02, 5, 1" } }
      
      





疑わしいようです。 クラスタリング層の説明を開くと、コメントを見つけることができます。



 # parameters - img_size_x, img_size_y, stride, # gridbox_cvg_threshold,gridbox_rect_threshold,gridbox_rect_eps,min_height,num_classes
      
      





これらが急流であることが明らかになります。 そこでエッセンスを掘り下げずに3つの数字をランダム化しました。 学習が進み、検証が成長し始めました。 約5時間でいくつかの妥当なしきい値に達しました。







しかし、これは残念です。 トレーニングが成功すると、100%の画像が露出しませんでした。 この層の意味を掘り下げて理解する必要がありました。



レイヤーは、取得した仮説のコレクションを単一のソリューションに実装します。 メインツールとして、OpenCVモジュール「cv.groupRectangles」がここで使用されます。 これは、長方形のグループを1つの長方形に関連付ける関数です。 ご存知のように、ネットワークはオブジェクトの近くに多くのポジティブがあるべき構造を持っています。 それらを単一のソリューションにまとめる必要があります。 収集アルゴリズムには多数のパラメーターがあります。





今では、それらを拾い上げて機能させるだけで十分です。 そして今、ユーモア。 Takiは3番目のチュートリアルでもあり、全体の一部が説明されています。

しかし、すべてではありません¯\ _(ツ)_ /¯



結果は何ですか



その結果、グリッドが強調表示したものを確認できます。









かなりうまくいきます。 一見、使用したHaarよりも優れています。 しかし、小さなトレーニングベース(〜1,500フレーム)が感じられることがすぐに明らかになりました。 汚れた数字はデータベースで考慮されませんでした=>検出されません。 データベースは、数の強力な見通しを考慮しませんでした=>検出されません。 大きすぎても小さすぎても考慮されません。 さて、あなたはポイントを得る。 要するに、あなたはあまりに怠zyである必要はなく、通常5000個の数字をマークアップします。



認識機能を使用すると、アクティベーションカード( 1、2、3 )でクールな写真を見ることができます。 次の各レベルで、数字がよりはっきりと見えることがわかります。



実行方法



楽しい瞬間-結果は20行までのコードで開始できます。 そして、それは既製の番号検出器になります:



 import numpy as np import sys caffe_root = '../' #     sys.path.insert(0, caffe_root + 'python') import caffe caffe.set_mode_cpu() #   . : #caffe.set_device(0) #caffe.set_mode_gpu() model_def = caffe_root + 'models/DetectNet/deploy.prototxt' #  model_weights = caffe_root + 'models/DetectNet/DetectNet.caffemodel' #  net = caffe.Net(model_def, # defines the structure of the model model_weights, # contains the trained weights caffe.TEST) # use test mode (eg, don't perform dropout) #       mean=np.array([128.0,128.0,128.0]) transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) transformer.set_transpose('data', (2,0,1)) # move image channels to outermost dimension transformer.set_mean('data', mean) # subtract the dataset-mean value in each channel transformer.set_raw_scale('data', 255) # rescale from [0, 1] to [0, 255] transformer.set_channel_swap('data', (2,1,0)) # swap channels from RGB to BGR #        net.blobs['data'].reshape(1, # batch size 3, # 3-channel (BGR) images 640, 1024) # image size is 227x227 image = caffe.io.load_image('/media/anton/Bazes/ReInspect/CARS/test/0.jpg')#    transformed_image = transformer.preprocess('data', image)#      output = net.forward() #  output_prob = output['bbox-list'][0] #       print output_prob[0]
      
      





ここに、グリッド用のデプロイファイルと、トレーニングされたネットワークの重みを配置します(必要な場合)。



All Articles