先週、私たちは PaddlePaddle と Tensorflow を使用して画像分類を実装し、自分たちで作成したシンプルな CNN ネットワーク simple_cnn と LeNet-5 CNN ネットワークを使用して cifar-10 データセットを認識しました。先週の実験パフォーマンスでは、200回の反復後のLeNet-5の精度は約60%で、満足できるものではありませんでした。結局のところ、それは20年前に書かれたネットワーク構造であり、結果がシンプルで層が少ないものです。このセクションでは、2012年の画像コンテストで素晴らしいパフォーマンスを発揮したAlexNetについて説明し、AlexNetを使用してcifar-10データを分類し、先週のLeNet-5の結果と比較します。 AlexNetとは何ですか? AlexNet は、ILSVRC-2012 コンテストでトップ 5 エラー率が 15.3% という画期的な成績を達成しました (2 位は 26.2%)。この背後にある原理は、Alex の 2012 年の論文「ImageNet Classification with Deep Convolutional Neural Networks」から派生したものです。この論文は、ディープラーニングの爆発的な発展における画期的な出来事であり、分岐点でした。ハードウェア技術の発展と相まって、ディープラーニングは今後も人気が続くでしょう。 AlexNetネットワーク構造 当時のハードウェア機器の制限により、AlexNet は GPU 粒度で設計されました。当時、GTX 580 には 3G のビデオ メモリしかありませんでした。モデルを大量のデータで実行できるようにするために、著者は 2 つの GPU を並列に使用し、ネットワーク構造を次のように分割しました。 ネットワーク構造 入力層
C1畳み込み層
C2畳み込み層
C3畳み込み層
C4畳み込み層
C5畳み込み層
F6完全結合層
F7 完全結合層
出力層
AlexNetの利点 1. ReLu活性化関数が使用される ----オリジナルRelu----- AlexNet は ReLU 活性化関数を導入しました。これは、神経科学者の Dayan と Abott が著書「Theoretical Neuroscience」で提案した、より正確な活性化モデルです。我々は、オリジナルの Relu 活性化関数 (Hinton の論文「Rectified Linear Units Improve Restricted Boltzmann Machines」を参照) 、つまりmax ( 0 , x )のほうがよく知られています。この活性化関数は、すべての負の活性化をゼロにクリアします (上記のスパース性をシミュレートします)。実際には、このアプローチはニューラル ネットワークの非線形機能を保持し、トレーニングを高速化します。
----リーキーReLu---- 上記の過度なスパース性により多数のニューロンが活性化されない問題を解決するために、Leaky ReLu が提案されました。 f ( x ) = { a x ( x < 0 ) x ( x >= 0 ) (2) (2)f(x)={ax(x<0)x(x>=0)ここで、 α αは人工的に小さい値(0.1 など)であり、負の活性化情報をある程度保持します。 ReLu 関数には、パラメトリック ReLu、ランダム化 ReLu など、他にも多くの改良点がありますが、ここでは説明しません。 2. ローカル応答の正規化 LRN は、特徴の顕著性を判断するために隣接する特徴マップを使用します。この論文の実験では、エラー率を削減できることが示されています。式は次のとおりです。 b i x , y = a i x , y ( k + α ⋅ ∑ m i n ( N − 1 , i + n / 2 ) j = max ( 0 , i − n / 2 ) ( a i x , y ) 2 ) β bx , yi=ax,yi(k+α⋅∑j=max(0,i−n/2)min(N−1,i+n/2)(ax,yi)2)βこの式の直感的な説明は次のとおりです。 α αは RELU の出力なので、0 より大きくなければなりません。関数1 ( k + α ∑ x 2 ) β 1(k+α∑x2)β は、テキスト内のパラメータの次のイメージを取得します (水平軸は∑ x 2 ∑x2です)。
3.ドロップアウト ドロップアウトはこの記事のハイライトの 1 つです。これは、モデルの一般化を向上させる方法です。操作は比較的単純です。これは、一定の確率で一部のニューロンの出力をランダムに 0 に設定します。これは、順方向伝播にも逆方向伝播にも関与しません。また、正規化の観点から見ることもできます。 (年初にディープラーニングの正則化について発表しました。次回はPDFを直接公開します。) モデル統合の観点から:
ドロップアウトのないネットワーク: Yn = WnXn − 1Xn = F ( Yn ) ドロップアウトネットワークがあります: Yn = WnXn − 1dn − 1∼ベルヌーイ( p ) Xn = dn − 1⊙F ( Yn ) ここで、 p pはドロップアウトの確率(たとえば、p = 0.5 はニューロンの 50% がランダムに非アクティブになることを意味します)、 n nはレイヤーです。 これは極端なケースのバギングです。トレーニングの各ステップで、ニューロンは一定の確率でランダムに無効化されます。これは、パラメータを共有する新しいネットワーク構造に相当します。損失を減らすために、各モデルは可能な限り最も「本質的な」特徴を学習します。「本質」とは、他のニューロンとの相関が弱く、一般化能力が強い、より独立したニューロンによって抽出された特徴として理解できます。同様の SGD トレーニング方法を使用する場合、各反復で異なるデータセットが選択されるため、ネットワーク全体は、異なるデータセットで学習された複数のモデルの統合された組み合わせに相当します。 PaddlePaddle を使用した AlexNet の実装 1.ネットワーク構造 (alexnet.py) 今回は、ローカル平均正規化 LRN を使用したものと LRN を使用しないものの 2 つの alextnet を作成しました。比較するとどうでしょうか? 1 #コーディング:utf-8 2 ''' 3 作成者: huxiaoman 2017.12.5 4 alexnet.py:alexnet ネットワーク構造 5 ''' 6 7 paddle.v2をpaddleとしてインポートする 8 インポート OS 9 10 with_gpu = os.getenv('WITH_GPU', '0') != '1' 11 12 定義alexnet_lrn(画像): 13 conv1 = パドル.レイヤー.img_conv( 14 入力=画像、 15 フィルターサイズ=11、 16 チャンネル数=3, 17 フィルター数=96, 18 ストライド=4、 19 パディング=1) 20 cmrnorm1 = パドル.レイヤー.img_cmrnorm( 21 入力=conv1、サイズ=5、スケール=0.0001、パワー=0.75) 22 プール1 = paddle.layer.img_pool(入力=cmrnorm1、プールサイズ=3、ストライド=2) 23 24 conv2 = パドル.レイヤー.img_conv( 25 入力=プール1、 26 フィルターサイズ=5、 27 フィルター数=256, 28 ストライド=1、 29 パディング=2、 30グループ=1) 31 cmrnorm2 = パドル.レイヤー.img_cmrnorm( 32 入力=conv2、サイズ=5、スケール=0.0001、パワー=0.75) 33 プール2 = paddle.layer.img_pool(入力=cmrnorm2、プールサイズ=3、ストライド=2) 34 35 プール3 = paddle.networks.img_conv_group( 36 入力=プール2、 37 プールサイズ=3、 38 プールストライド=2、 39 変換数フィルター=[384, 384, 256], 40 変換フィルタサイズ=3、 41 プールタイプ = paddle.pooling.Max()) 42 43 fc1 = パドル.レイヤー.fc( 44 入力=プール3、 45サイズ=4096、 46 act=paddle.activation.Relu(), 47 レイヤー属性 = パドル属性.Extra(ドロップ率=0.5)) 48 fc2 = パドル.レイヤー.fc( 49 入力=fc1、 50サイズ=4096、 51 act=paddle.activation.Relu(), 52 レイヤー属性 = パドル属性.Extra(ドロップ率=0.5)) 53 戻る fc2 54 55 定義 alexnet(画像): 56 conv1 = パドル.レイヤー.img_conv( 57 入力=画像、 58 フィルターサイズ=11、 59 チャンネル数=3, 60 フィルター数=96, 61 歩幅=4、 62パディング=1) 63 cmrnorm1 = パドル.レイヤー.img_cmrnorm( 64 入力=conv1、サイズ=5、スケール=0.0001、パワー=0.75) 65 プール1 = paddle.layer.img_pool(入力=cmrnorm1、プールサイズ=3、ストライド=2) 66 67 conv2 = パドル.レイヤー.img_conv( 68 入力=プール1、 69 フィルターサイズ=5、 70 フィルター数=256、 71 ストライド=1、 72 パディング=2、 73グループ=1) 74 cmrnorm2 = パドル.レイヤー.img_cmrnorm( 75 入力=conv2、サイズ=5、スケール=0.0001、パワー=0.75) 76 プール2 = paddle.layer.img_pool(入力=cmrnorm2、プールサイズ=3、ストライド=2) 77 78 プール3 = paddle.networks.img_conv_group( 79 入力=プール2、 80 プールサイズ=3、 81 プールストライド=2、 82 変換数フィルター=[384, 384, 256], 83 変換フィルタサイズ=3、 84 プールタイプ = paddle.pooling.Max()) 85 86 fc1 = パドル.レイヤー.fc( 87 入力=プール3、 88サイズ=4096、 89 act=paddle.activation.Relu(), 90 レイヤー属性 = パドル.属性.Extra(ドロップ率 = 0.5)) 91 fc2 = パドル.レイヤー.fc( 92 入力=fc1、 93 サイズ=4096、 94 act=paddle.activation.Relu(), 95 レイヤー属性 = パドル属性.Extra(ドロップ率=0.5)) 96 リターン fc3 2. トレーニングコード (train_alexnet.py) 1 #コーディング:utf-8 2 ''' 3 作成者: huxiaoman 2017.12.5 4 train_alexnet.py: alexnet をトレーニングして cifar10 データセットを分類する 5 ''' 6 7 sys、osをインポート 8 paddle.v2をpaddleとしてインポートする 9 10 LRNなしの#alexモデル 11 alexnetからalexnetをインポート 12 #alexnet_lrn は lrn と一緒にあります 13 #from alextnet import alexnet_lrn 14 with_gpu = os.getenv('WITH_GPU', '0') != '1' 15 16 17 定義main(): 18 データ次元 = 3 * 32 * 32 19 クラス次元 = 10 20 21 # パドルパドルの初期化 22 パドル.init(use_gpu=with_gpu、trainer_count=7) 23 24 イメージ = paddle.layer.data( 25 名前 = "画像"、タイプ = paddle.data_type.dense_vector(datadim)) 26 27 # ニューラルネットワーク設定を追加する 28 # オプション 1. resnet 29 # ネット = resnet_cifar10(画像、深さ=32) 30 # オプション2.vgg 31 #net = alexnet_lrn(イメージ) 32 ネット = alexnet(画像) 33 アウト = パドル.レイヤー.fc( 34 入力=ネット、サイズ=classdim、動作=paddle.activation.Softmax()) 35 36 lbl = パドル.レイヤー.データ( 37 名前 = "ラベル"、タイプ = paddle.data_type.integer_value(classdim)) 38 コスト = paddle.layer.classification_cost(入力 = out、ラベル = lbl) 39 40 # パラメータを作成する 41 パラメータ = paddle.parameters.create(cost) 42 43 # オプティマイザを作成する 44 momentum_optimizer = paddle.optimizer.Momentum( 45 運動量=0.9、 46 正規化 = paddle.optimizer.L2Regularization(レート = 0.0002 * 128)、 47 学習率=0.1 / 128.0、 48 学習率減衰率=0.1、 49 学習率減衰率b=50000 * 100、 50 学習率スケジュール = 'discexp') 51 52 # バッチを終了し、イベント ハンドラーを終了します 53 defevent_handler(イベント): 54 インスタンスの場合(イベント、paddle.event.EndIteration): 55 event.batch_id % 100 == 0の場合: 56 print "\nパス %d、バッチ %d、コスト %f、%s" % ( 57 イベント.pass_id、イベント.batch_id、イベント.cost、イベント.metrics) 58 その他: 59 sys.stdout.write('.') 60 sys.stdout.flush() 61 インスタンスの場合(イベント、paddle.event.EndPass): 62 # パラメータを保存 63 open('params_pass_%d.tar' % event.pass_id, 'w') を f として実行: 64 パラメータ.to_tar(f) 65 66 結果 = trainer.test( 67 リーダー = paddle.batch( 68 paddle.dataset.cifar.test10()、バッチサイズ=128)、 69 給餌={'画像': 0, 70 'ラベル': 1}) 71 印刷 "\n合格したテスト %d、%s" % (event.pass_id、result.metrics) 72 73 # トレーナーを作成する 74 トレーナー = paddle.trainer.SGD( 75 コスト = コスト、パラメータ = パラメータ、update_equation = モメンタム オプティマイザ) 76 77 # 推論トポロジをprotobufに保存します。 78 推論トポロジー = paddle.topology.Topology(レイヤー = 出力) 79 を open("inference_topology.pkl", 'wb') として f として実行します: 80 推論トポロジー.シリアル化_for_inference(f) 81 82 トレーナー.train( 83 リーダー = paddle.batch( 84 パドル.リーダー.シャッフル( 85 paddle.dataset.cifar.train10()、buf_size=50000)、 86 バッチサイズ=128)、 87 num_passes=200、 88 イベントハンドラ=イベントハンドラ、 89 給餌={'画像': 0, 90 'ラベル': 1}) 91 92 # 推論 93 PILインポート画像 94 numpyをnpとしてインポートする 95 インポート OS 96 97 def load_image(ファイル): 98 im = Image.open(ファイル) 99 im = im.resize((32, 32), Image.ANTIALIAS) 100 im = np.array(im).astype(np.float32) 101 im = im.transpose((2, 0, 1)) # CHW 102 im = im[(2, 1, 0), :, :] # BGR 103 im = im.flatten() 104 イム = イム / 255.0 105 戻る 106 107 テストデータ = [] 108 cur_dir = os.path.dirname(os.path.realpath(__file__)) 109 test_data.append((load_image(cur_dir + '/image/dog.png'), )) 110 111 問題 = paddle.infer( 112 出力レイヤー=out、パラメータ=parameters、入力=test_data) 113 lab = np.argsort(-probs) # probs と lab は 1 つのバッチデータの結果です 114 print "image/dog.png のラベルは: %d" % lab[0][0] 115 116 117 __name__ == '__main__' の場合: 118 メイン() Tensorflow で AlexNet を実装する 1. ネットワーク構造 1 定義推論(画像): 2 ''' 3 Alexnetモデル 4 入力: 画像のテンソル 5 戻る: Alexnet の最後の畳み込み層 6 ''' 7 パラメータ = [] 8 # 変換1 9 スコープとしてtf.name_scope('conv1')を使用: 10 カーネル = tf.Variable(tf.truncated_normal([11, 11, 3, 64], dtype=tf.float32, 11 stddev=1e-1)、名前='重み') 12 conv = tf.nn.conv2d(画像、カーネル、[1, 4, 4, 1]、パディング='SAME') 13 バイアス = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32), 14 訓練可能=True、名前='バイアス') 15 バイアス = tf.nn.bias_add(conv, バイアス) 16 conv1 = tf.nn.relu(バイアス、名前=スコープ) 17 print_activations(conv1) 18 パラメータ += [カーネル、バイアス] 19 20 # lrn1 21 スコープとしてtf.name_scope('lrn1')を使用: 22 lrn1 = tf.nn.local_response_normalization(conv1, 23 アルファ=1e-4、 24 ベータ=0.75、 25 深さ半径=2、 26バイアス=2.0) 27 28#プール1 29 プール1 = tf.nn.max_pool(lrn1, 30 ksize=[1, 3, 3, 1], 31歩=[1, 2, 2, 1], 32 パディング='有効'、 33 名前 = 'pool1') 34 print_activations(プール1) 35 36 # 変換2 37 スコープとして tf.name_scope('conv2') を使用: 38 カーネル = tf.Variable(tf.truncated_normal([5, 5, 64, 192], dtype=tf.float32, 39 stddev=1e-1)、名前='重み') 40 conv = tf.nn.conv2d(pool1, カーネル, [1, 1, 1, 1], パディング='SAME') 41 バイアス = tf.Variable(tf.constant(0.0, shape=[192], dtype=tf.float32), 42 トレーニング可能 = True、名前 = 'バイアス') 43 バイアス = tf.nn.bias_add(conv, バイアス) 44 conv2 = tf.nn.relu(バイアス、名前=スコープ) 45 パラメータ += [カーネル、バイアス] 46 print_activations(conv2) 47 48 # lrn2 49 スコープとして tf.name_scope('lrn2') を使用: 50 lrn2 = tf.nn.local_response_normalization(conv2, 51 アルファ=1e-4、 52 ベータ=0.75、 53 深さ半径=2、 54 バイアス=2.0) 55 56#プール2 57 プール2 = tf.nn.max_pool(lrn2, 58 ksize=[1, 3, 3, 1], 59歩=[1, 2, 2, 1], 60 パディング='有効'、 61 名前 = 'プール2') 62 プリントアクティベーション(プール2) 63 64 # 変換3 65 スコープとして tf.name_scope('conv3') を使用: 66 カーネル = tf.Variable(tf.truncated_normal([3, 3, 192, 384], 67 dtype=tf.float32, 68 stddev=1e-1)、名前='重み') 69 conv = tf.nn.conv2d(pool2, カーネル, [1, 1, 1, 1], パディング='SAME') 70 バイアス = tf.Variable(tf.constant(0.0, shape=[384], dtype=tf.float32), 71 トレーニング可能 = True、名前 = 'バイアス') 72 バイアス = tf.nn.bias_add(conv, バイアス) 73 conv3 = tf.nn.relu(バイアス、名前=スコープ) 74 パラメータ += [カーネル、バイアス] 75 プリントアクティベーション(conv3) 76 77 # 変換4 78 スコープとして tf.name_scope('conv4') を使用: 79 カーネル = tf.Variable(tf.truncated_normal([3, 3, 384, 256], 80 dtype=tf.float32, 81 stddev=1e-1)、名前='重み') 82 conv = tf.nn.conv2d(conv3, カーネル, [1, 1, 1, 1], パディング='SAME') 83 バイアス = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32), 84 トレーニング可能 = True、名前 = 'バイアス') 85 バイアス = tf.nn.bias_add(conv, バイアス) 86 conv4 = tf.nn.relu(バイアス、名前=スコープ) 87 パラメータ += [カーネル、バイアス] 88 print_activations(conv4) 89 90 # 変換5 91 スコープとして tf.name_scope('conv5') を使用: 92 カーネル = tf.Variable(tf.truncated_normal([3, 3, 256, 256], 93 dtype=tf.float32, 94 stddev=1e-1)、名前='重み') 95 conv = tf.nn.conv2d(conv4, カーネル, [1, 1, 1, 1], パディング='SAME') 96 バイアス = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32), 97 訓練可能 = True、名前 = 'バイアス') 98 バイアス = tf.nn.bias_add(conv, バイアス) 99 conv5 = tf.nn.relu(バイアス、名前=スコープ) 100 パラメータ += [カーネル、バイアス] 101 プリントアクティベーション(conv5) 102 103#プール5 104 プール5 = tf.nn.max_pool(conv5, 105 ksize=[1, 3, 3, 1], 106歩=[1, 2, 2, 1], 107 パディング='有効'、 108 名前 = 'プール5') 109 print_activations(プール5) 110 111 プール5、パラメータを返す 完全なコードは、alexnet_tf.py にあります。 実験結果の比較 3 つのコードを実行した後、図に示すように実験結果を比較しました。 batch_size、num_epochs、デバイス、スレッド数が同じ条件の場合、LRN 付きの alexnet の paddlepaddle バージョンが最も良い結果を示し、LRN なしの alexnet が最も短い時間であることがわかります。Tensorflow バージョンの alexnet は、時間と精度の点で比較的平均的です。もちろん、tf バージョンにも LRN があるため、LRN は依然として実験結果に対して一定の改善を示しています。 要約する AlexNet は画像分類において比較的重要なネットワークです。学習プロセスでは、ネットワーク構造の書き方を学び、各層の構造を知るだけでなく、なぜこのように設計されているのか、このような設計の利点は何なのか、いくつかのパラメータを調整するとどのような変化が起こるのかを知る必要があります。なぜこのような変化が起こったのでしょうか?実際のアプリケーションでは、ネットワーク構造に何らかの調整を加える必要がある場合、ネットワークを実際のデータに適したものにするためにどのように調整すればよいでしょうか?これらこそが私たちが大切にしていることです。これも面接でよく聞かれるポイントです。昨日、5年間働いているアルゴリズムエンジニアにインタビューしました。プロジェクトで使用したAlexnetモデルについて尋ねたところ、Alexnetのネットワーク構造がよくわからず、ネットワーク構造を変更する方法もわからないと答えました。これは実際には良い考えではありません。単にモデルを動作させることは最初のステップに過ぎず、その後もやるべきことがたくさんあります。これも、アルゴリズムエンジニアであることの価値の現れの1つです。この記事は、私の前リーダーがAlexnetのネットワーク構造について書いた記事を参考にしています。ご質問があれば、メッセージを残してください。 追伸:皆さんが私の更新情報をタイムリーに確認しやすくするために、公開アカウントを設定しました。今後は、記事は公開アカウントと Blog Garden に同時に公開され、皆さんがタイムリーに通知を受け取ることができるようになります。ご質問がある場合は、公開アカウントにメッセージを残していただければ、私がタイムリーに確認して返信することができます。 (公式アカウントは始まったばかりなので、割と荒っぽくて何も入ってないです==。後ほど徐々に改善していきます〜〜) 下のQRコードをスキャンするか、公式アカウントCharlotteDataMiningを直接検索してください。ご清聴ありがとうございました^_^
参考文献 1.AlexNet: http://www.cs.toronto.edu/~fritz/absps/imagenet.pdf 私のブログはまもなく Tencent Cloud+ コミュニティに同期される予定なので、皆さんもぜひ参加してください。 |
>>: 新居ネットワークの程永馨氏:AIの助けを借りて、運用保守プラットフォームは新たな活力を得ました
買い物のときに顔で支払いをしたり、顔で携帯電話のロックを解除したり、コミュニティに入るときにドアを開...
[[432064]]長い間、多くの学者は、ディープラーニングと人工ニューラルネットワークのインスピレ...
BlackBerry が発表した新しい調査によると、世界中の組織の 75% が現在、職場での Ch...
設置環境Gym は、強化学習アルゴリズムの開発と比較のためのツールキットです。gym ライブラリとそ...
この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...
今年初め以来、ChatGPT のような生成型人工知能 (AI) ツールが世界を席巻しています。それは...
人工知能は長い間、小売業から農業に至るまで、さまざまな業界で主要な技術的焦点となってきており、大手企...
この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...
先月、Meta FAIR の Tian Yuandong が参加した研究が大きな称賛を受けました。彼...
想像してみてください。あなたはずっと夢見てきた機械学習の職種の面接を受けに行こうとしています。すべて...
この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...
たったこれだけで、携帯電話を交換したいですか?最近話題になっている新しいAIデバイス「AI Pin」...