Tensorflow AlexNetの巻き取り神経ネットワークを実現


論文の住所:http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf
Fashion-MNISTデータセットのダウンロード:https://github.com/zalandoresearch/fashion-mnist/tree/master/data/fashion
1.Fashion-MNISTデータ集の紹介
Fashion-MNISTの代わりに手書きのデジタルセットの画像データ集です.それはZalando(ドイツのファッション科学技術会社)傘下の研究部門によって提供されます.10種類の他の7万種類の商品からの正面写真をカバーしています.Fashion-MNISTのサイズ、フォーマット、トレーニングセット/テストセットの区分は元のMNISTと完全に一致しています.60000/10000のトレーニングテストデータの区分、28 x 28のグレースケール画像.直接にそれを使ってあなたのマシン学習と深さ学習アルゴリズムの性能をテストしてもいいです.コードを変更する必要はありません.
このデータセットの様子は大体以下の通りです.
Tensorflow实现AlexNet卷积神经网络——Fashion-MNIST数据集分类_第1张图片
Fashion-MNISTデータセット
 
MNISTデータセットの代わりに、以下のような理由があります.
  • MNISTは簡単すぎます. 多くの深さ学習アルゴリズムはテストセットでの精度は99.6%に達しました.私たちはscikit-learnに基づいて古典的な機械学習アルゴリズムの評価を見てみてください. このコードと: 「Most pairs of MNIST digits can be distinguished pretty well by just one pixel」
  • MNISTは壊れてしまいました. 参考:「Ian Goodfellows wants people to move away from m mnist」
  • MNIST数字認識の任務は現代機械学習を代表しない. 参考:「Fran c.ois Cholle:Ideas on MNIST do not transfer to real CV」
    1.1.データの取得
    git clone [email protected]:zalandoresearch/fashion-mnist.git
    1.2.カテゴリ表示
    各トレーニングとテストサンプルは以下の種類によって表示されています.
    Tensorflow实现AlexNet卷积神经网络——Fashion-MNIST数据集分类_第2张图片
    2.AlexNet深さ畳み込み神経ネットワーク
    AlexNetは2012年ImageNet競技優勝者ヒットンと彼の学生Alex Krizhevskyが設計したものです.また、その年以降、より深い神経ネットワークが提案されています.例えば優秀なvgg、GoogLeNet.これは従来の機械学習の分類アルゴリズムにとって,既にかなり優れている.
    2.1.モデル概要
    AlexNetにはいくつかの比較的新しい技術点が含まれており、ReLU、Dropout、LRNなどのTrickがCNNに初めて適用されました.また、AlexNetもGPUを使って演算を加速します.
    AlexNetはLeNetの思想を大いに発揚して、CNNの基本原理をとても深い広いネットに応用しました.AlexNetが主に使用している新技術ポイントは以下の通りです.
    (1)ReLUをCNNの活性化関数として成功的に使用し、その効果がより深いネットワークでSigmoidを超えていることを検証し、Sigmoidのネットワークが深い場合の勾配分散問題を解決した.ReLU活性化関数は昔から提案されていましたが、AlexNetの出現によって大きく発揚されました.
    (2)訓練の時にDropoutを使ってランダムに一部のニューロンを無視してモデルの過当フィットを避ける.Dropoutは独自の論文論述があるが、AlexNetはそれを実用化し、その効果を実践により確認した.AlexNetでは主に最後のいくつかの全接続層がDropoutを使用しています.
    (3)重なりの最大池化をCNNに使用する.これまでCNNでは平均的なプール化が一般的だったが、AlexNetは全て最大プール化され、平均的なプール化の曖昧化効果が避けられた.また、AlexNetでは、池核のサイズよりも歩幅を小さくすることが提案されており、池化層の出力の間に重なりと覆いがあり、特徴の豊かさが向上しています.
    (4)LRN層を提案し、局所ニューロンの活動に対する競合機構を作成し、応答が大きい値が相対的に大きくなり、他のフィードバックが小さいニューロンを抑制し、モデルの汎化能力を増強した.
    (5)CUDAを使用して深さ畳みネットワークの訓練を加速し、GPUの強力な並列計算能力を利用して、神経ネットワークトレーニング時の大量のマトリックス演算を処理する.AlexNetは2つのGTX 580 GPUを使ってトレーニングを行い、単一GTX 580は3 GBの現存しかなく、これは訓練可能なネットワークの最大規模を制限している.したがって,著者らは2つのGPUにAlexNetを分布し,各GPUの現存に半分のニューロンのパラメータを格納した.GPU間の通信は便利で、互いに現存にアクセスでき、ホストメモリを通過する必要がないので、複数のGPUを同時に使用するのも非常に効率的です.また、AlexNetの設計は、GPU間の通信をネットワークのある層だけで行い、通信の性能損失を制御した.湖南省にある地名
    (6)データが強化され、256*256の元の画像から224*224サイズの領域(および水平反転のミラー)をランダムに切り取ることは、2*(256−244)^2=2048倍のデータ量を増加させることに相当する.データの増強がなければ,元のデータ量だけで,パラメータの多いCNNは過当フィットに陥り,データの増強を用いて過当フィットを大幅に軽減し,汎化能力を向上させることができる.予測する時は、ピクチャの4つの角と中間の5つの位置を取って、左右の反転を行って、全部で10枚の写真を獲得して、彼らに対して予測して、10回の結果に対して平均値を求めます.一方、AlexNet論文では、画像のRGBデータに対してPCA処理を行い、主成分に対して標準偏差0.1のガウス擾乱を行い、ノイズを増加させ、このTrickはエラー率をさらに1%下げることができると述べた.
     
    Tensorflow实现AlexNet卷积神经网络——Fashion-MNIST数据集分类_第3张图片
    2.2.AlexNetの特徴
    2.2.1.Relu活性化関数を使用しています.
    Tensorflow实现AlexNet卷积神经网络——Fashion-MNIST数据集分类_第4张图片
    ReLUベースの深さ畳み込みネットワークは、tanhとsigmoidベースのネットワークトレーニングよりも数倍速い.
    2.2.2.標準化
    ReLUを使用すると、活性化関数の値がtanh、sigmoid関数のように値区間がないことが分かります.だから、ReLUの後にnormalizationを作ります.LRUは穏やかに一つの方法を提案します.神経科学には「Lateral inhibition」という概念があります.アクティブなニューロンがその周辺のニューロンに与える影響を言います.
    2.2.3.3 Dropout
    Dropoutもよく言われている概念で、神経網の過当フィットをより効果的に防ぐことができます.一般的に線形モデルのような正則法を用いてモデルのオーバーフィットを防止するのに対して,ニューラルネットワーク内のDropoutはニューラルネットワーク自体の構造を修正することにより実現した.ある階層のニューロンについては、入力層と出力層のニューロンの個人的な不変性を維持しながら、定義された確率でランダムにニューロンを削除し、その後、神経ネットワークの学習方法に従ってパラメータ更新を行い、次の反復において、トレーニングが終了するまで、ニューロンをランダムに削除します.
    3.AlexNetのTensorFlowを実現
    3.1.予備工作
    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    
    # 1.     
    mnist = input_data.read_data_sets('./data/MNIST_data/', one_hot=True)
    
    # 2.     (   、    、 (batch)  、      step)
    learning_rate = 0.001
    training_iters = 200000
    batch_size = 128
    display_step = 10
    
    # 3.      (    ,    ,dropout    )
    n_input = 784
    n_classes = 10
    dropout = 0.75
    
    # 4.     ,     
    x = tf.placeholder(tf.float32, [None, n_input])
    y = tf.placeholder(tf.float32, [None, n_classes])
    keep_prob = tf.placeholder(tf.float32)  # dropout      
    
    # 5.      
    def conv2d(name, x, W, b, strides=1):
        x = tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding='SAME')
        x = tf.nn.bias_add(x, b)
        return tf.nn.relu(x, name=name)
    
    # 6.      
    def maxpool2d(name, x, k=2):
        return tf.nn.max_pool(x, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding='SAME', name=name)
    
    # 7.     
    def norm(name, l_input, lsize=4):
        return tf.nn.lrn(l_input, lsize, bias=1.0, alpha=0.001/9.0, beta=0.75, name=name)
    3.2ネットワークパラメータを初期化する
    論文のネットワーク構造図(下図)に基づいて、ネットワークパラメータを定義します.
    Tensorflow实现AlexNet卷积神经网络——Fashion-MNIST数据集分类_第5张图片
    # 8.         
    weights = {
        'wc1':tf.Variable(tf.random_normal([11, 11, 1, 96])),#   mnist      channel 1,     11*11*1,   96
        'wc2':tf.Variable(tf.random_normal([5, 5, 96, 256])),#            GPU     ,       GPU,
        'wc3':tf.Variable(tf.random_normal([3, 3, 256, 384])),  #               2 。
        'wc4':tf.Variable(tf.random_normal([3, 3, 384, 384])),
        'wc5':tf.Variable(tf.random_normal([3, 3, 384, 256])),
        'wd1':tf.Variable(tf.random_normal([4*4*256, 4096])),      #              4096
        'wd2':tf.Variable(tf.random_normal([4096, 1024])),
        'out':tf.Variable(tf.random_normal([1024, 10]))        #     10    
    }
    biases = {
        'bc1':tf.Variable(tf.random_normal([96])),
        'bc2':tf.Variable(tf.random_normal([256])),
        'bc3':tf.Variable(tf.random_normal([384])),
        'bc4':tf.Variable(tf.random_normal([384])),
        'bc5':tf.Variable(tf.random_normal([256])),
        'bd1':tf.Variable(tf.random_normal([4096])),
        'bd2':tf.Variable(tf.random_normal([1024])),
        'out':tf.Variable(tf.random_normal([n_classes]))
    }
    Tensorflow实现AlexNet卷积神经网络——Fashion-MNIST数据集分类_第6张图片
    AlexNetを定義するネットワークモデル:
    #       
    def alex_net(x, weights, biases, dropout):
        x = tf.reshape(x, shape=[-1, 28, 28, 1])
        #      
        conv1 = conv2d('conv1', x, weights['wc1'], biases['bc1'])
        
        #     ——   
        pool1 = maxpool2d('pool1', conv1, k=2)
        
        #    ——     
        norm1 = norm('norm1', pool1, lsize=4)
        
        #      
        conv2 = conv2d('conv2', norm1, weights['wc2'], biases['bc2'])
        
        #     ——   
        pool2 = maxpool2d('pool2', conv2, k=2)
        
        #    ——     
        norm2 = norm('norm2', pool2, lsize=4)
        
        #      
        conv3 = conv2d('conv3', norm2, weights['wc3'], biases['bc3'])
        pool3 = maxpool2d('pool3', conv3, k=2)
        norm3 = norm('norm3', pool3, lsize=4)
        
        #      
        conv4 = conv2d('conv4', norm3, weights['wc4'], biases['bc4'])
        
        #      
        conv5 = conv2d('conv5', conv4, weights['wc5'], biases['bc5'])
        pool5 = maxpool2d('pool5', conv5, k=2)
        norm5 = norm('norm5', pool5, lsize=4)
        
        #      1
        fc1 = tf.reshape(norm5, [-1, weights['wd1'].get_shape().as_list()[0]])
        fc1 = tf.add(tf.matmul(fc1, weights['wd1']), biases['bd1'])
        fc1 = tf.nn.relu(fc1)
        
        #   Dropout  
        fc1 = tf.nn.dropout(fc1, dropout)
        
        #      2
        fc2 = tf.reshape(fc1, [-1, weights['wd2'].get_shape().as_list()[0]])
        fc2 = tf.add(tf.matmul(fc2, weights['wd2']), biases['bd2'])
        fc2 = tf.nn.relu(fc2)
        fc2 = tf.nn.dropout(fc2, dropout)
        
        #   
        out = tf.add(tf.matmul(fc2, weights['out']), biases['out'])
        return out
    モデルを構築し,損失関数と最適化器を定義し,評価関数を構築する.
    # 1.    
    pred = alex_net(x, weights, biases, keep_prob)
    
    # 2.          
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
    
    # 3.    
    correct_pred = tf.equal(tf.arg_max(pred, 1), tf.arg_max(y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
    トレーニングモデルと評価モデル
    #      
    init = tf.global_variables_initializer()
    
    with tf.Session() as sess:
        sess.run(init)
        step = 1
        while step * batch_size < training_iters:
            batch_x, batch_y = mnist.train.next_batch(batch_size)
            sess.run(optimizer, feed_dict={x: batch_x, y: batch_y, keep_prob: dropout})
            if step % display_step == 0:
                loss,acc = sess.run([cost,accuracy], feed_dict={x: batch_x, y: batch_y, keep_prob: 1.})
                print("Iter"+str(step*batch_size)+",Minibatch Loss="+"{:.6f}".format(loss)+",Training Accuracy="+"{:.5f}".format(acc))
            step += 1
        print('Optimization Finishion!')
        print("Testing Accuracy:",sess.run(accuracy, feed_dict={x: mnist.test.images[:256],y: mnist.test.labels[:256],keep_prob: 1.}))
    結果の表示:
    .......
    Iter 373760, Minibatch Loss= 7115.613770, Training Accuracy= 0.81641
    Iter 375040, Minibatch Loss= 5161.097656, Training Accuracy= 0.85547
    Iter 376320, Minibatch Loss= 8036.062988, Training Accuracy= 0.81250
    Iter 377600, Minibatch Loss= 5098.235352, Training Accuracy= 0.85547
    Iter 378880, Minibatch Loss= 6332.221680, Training Accuracy= 0.85547
    Iter 380160, Minibatch Loss= 8099.681641, Training Accuracy= 0.81641
    Iter 381440, Minibatch Loss= 7120.978516, Training Accuracy= 0.81250
    Iter 382720, Minibatch Loss= 8811.558594, Training Accuracy= 0.80469
    Iter 384000, Minibatch Loss= 7238.435547, Training Accuracy= 0.83594
    Iter 385280, Minibatch Loss= 6391.473633, Training Accuracy= 0.82812
    Iter 386560, Minibatch Loss= 5670.675781, Training Accuracy= 0.80859
    Iter 387840, Minibatch Loss= 4547.402832, Training Accuracy= 0.83984
    Iter 389120, Minibatch Loss= 8333.980469, Training Accuracy= 0.77734
    Iter 390400, Minibatch Loss= 5622.814453, Training Accuracy= 0.83203
    Iter 391680, Minibatch Loss= 6032.568359, Training Accuracy= 0.83594
    Iter 392960, Minibatch Loss= 7194.363770, Training Accuracy= 0.83203
    Iter 394240, Minibatch Loss= 5317.426270, Training Accuracy= 0.85938
    Iter 395520, Minibatch Loss= 6857.503418, Training Accuracy= 0.80078
    Iter 396800, Minibatch Loss= 6782.902344, Training Accuracy= 0.82031
    Iter 398080, Minibatch Loss= 6809.053711, Training Accuracy= 0.82812
    Iter 399360, Minibatch Loss= 6525.162109, Training Accuracy= 0.82031
    Optimization Finished!
    Testing Accuracy: 0.82421875
    
    完全コード:
    # -*- coding: utf-8 -*-
    # @Time    : 2019/3/11 13:12
    # @Author  : Chaucer_Gxm
    # @Email   : [email protected]
    # @File    : AlexNet.py
    # @GitHub  : https://github.com/Chaucergit/Code-and-Algorithm
    # @blog    : https://blog.csdn.net/qq_24819773
    # @Software: PyCharm
    import tensorflow as tf
    
    #     
    from tensorflow.examples.tutorials.mnist import input_data
    mnist = input_data.read_data_sets("./data/MNIST_data", one_hot=True)
    
    #         
    learning_rate = 0.0001
    training_iters = 400000
    batch_size = 256
    display_step = 5
    
    #        
    n_input = 784    #       (img shape: 28*28)
    n_classes = 10   #       (0-9 digits)
    dropout = 0.5   # Dropout   ,      
    
    #      
    x = tf.placeholder(tf.float32, [None, n_input])
    y = tf.placeholder(tf.float32, [None, n_classes])
    keep_prob = tf.placeholder(tf.float32)   # dropout (keep probability)
    
    
    #       
    def conv2d(name, x, W, b, strides=1):
        # Conv2D wrapper, with bias and relu activation
        x = tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding='SAME')
        x = tf.nn.bias_add(x, b)
        return tf.nn.relu(x, name=name)  #   relu    
    
    
    #        
    def maxpool2d(name, x, k=2):
        # MaxPool2D wrapper
        return tf.nn.max_pool(x, ksize=[1, k, k, 1], strides=[1, k, k, 1],
                              padding='SAME', name=name)
    
    
    #      
    def norm(name, l_input, lsize=4):
        return tf.nn.lrn(l_input, lsize, bias=1.0, alpha=0.001 / 9.0,
                         beta=0.75, name=name)
    
    #          
    weights = {
        'wc1': tf.Variable(tf.random_normal([11, 11, 1, 96])),
        'wc2': tf.Variable(tf.random_normal([5, 5, 96, 256])),
        'wc3': tf.Variable(tf.random_normal([3, 3, 256, 384])),
        'wc4': tf.Variable(tf.random_normal([3, 3, 384, 384])),
        'wc5': tf.Variable(tf.random_normal([3, 3, 384, 256])),
        'wd1': tf.Variable(tf.random_normal([4*4*256, 4096])),
        'wd2': tf.Variable(tf.random_normal([4096, 4096])),
        'out': tf.Variable(tf.random_normal([4096, n_classes]))
    }
    biases = {
        'bc1': tf.Variable(tf.random_normal([96])),
        'bc2': tf.Variable(tf.random_normal([256])),
        'bc3': tf.Variable(tf.random_normal([384])),
        'bc4': tf.Variable(tf.random_normal([384])),
        'bc5': tf.Variable(tf.random_normal([256])),
        'bd1': tf.Variable(tf.random_normal([4096])),
        'bd2': tf.Variable(tf.random_normal([4096])),
        'out': tf.Variable(tf.random_normal([n_classes]))
    }
    
    
    #       
    def alex_net(x, weights, biases, dropout):
        #        Reshape input picture
        x = tf.reshape(x, shape=[-1, 28, 28, 1])
    
        #      
        #   
        conv1 = conv2d('conv1', x, weights['wc1'], biases['bc1'])
        #    
        pool1 = maxpool2d('pool1', conv1, k=2)
        #    
        norm1 = norm('norm1', pool1, lsize=4)
    
        #      
        #   
        conv2 = conv2d('conv2', norm1, weights['wc2'], biases['bc2'])
        #     (    )
        pool2 = maxpool2d('pool2', conv2, k=2)
        #    
        norm2 = norm('norm2', pool2, lsize=4)
    
        #      
        #   
        conv3 = conv2d('conv3', norm2, weights['wc3'], biases['bc3'])
        #    
        norm3 = norm('norm3', conv3, lsize=4)
    
        #      
        conv4 = conv2d('conv4', norm3, weights['wc4'], biases['bc4'])
    
        #      
        conv5 = conv2d('conv5', conv4, weights['wc5'], biases['bc5'])
        #     (    )
        pool5 = maxpool2d('pool5', conv5, k=2)
        #    
        norm5 = norm('norm5', pool5, lsize=4)
    
        #     1
        fc1 = tf.reshape(norm5, [-1, weights['wd1'].get_shape().as_list()[0]])
        fc1 =tf.add(tf.matmul(fc1, weights['wd1']), biases['bd1'])
        fc1 = tf.nn.relu(fc1)
        # dropout
        fc1 = tf.nn.dropout(fc1, dropout)
    
        #     2
        fc2 = tf.reshape(fc1, [-1, weights['wd2'].get_shape().as_list()[0]])
        fc2 = tf.add(tf.matmul(fc2, weights['wd2']), biases['bd2'])
        fc2 = tf.nn.relu(fc2)
        # dropout
        fc2=tf.nn.dropout(fc2, dropout)
    
        #    
        out = tf.add(tf.matmul(fc2, weights['out']), biases['out'])
        return out
    
    #     
    pred = alex_net(x, weights, biases, keep_prob)
    
    #           
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
    
    #     
    correct_pred = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
    
    #      
    init = tf.global_variables_initializer()
    
    import os
    ckpt_dir = './tmp/ckpt_dir'
    if not os.path.exists(ckpt_dir):
        os.makedirs(ckpt_dir)
    #        
    saver = tf.train.Saver()
    
    #       
    with tf.Session() as sess:
        sess.run(init)
        step = 1
        #     ,    training_iters, 200000
        while step * batch_size < training_iters:
            #       
            batch_x, batch_y = mnist.train.next_batch(batch_size)
            sess.run(optimizer, feed_dict={x: batch_x, y: batch_y, keep_prob: dropout})
            if step % display_step == 0:
                #          ,  
                loss, acc = sess.run([cost, accuracy], feed_dict={x: batch_x, y: batch_y, keep_prob: 1.})
                print("Iter " + str(step*batch_size) + ", Minibatch Loss= " + "{:.6f}".format(loss) + ", Training Accuracy= " + "{:.5f}".format(acc))
            step += 1
        print("Optimization Finished!")
        #          
        print("Testing Accuracy:", sess.run(accuracy, feed_dict={x: mnist.test.images[:256], y: mnist.test.labels[:256], keep_prob: 1.}))
        saver.save(sess, './tmp/ckpt_dir/model.ckpt')
    
    参考文献:
    [1].Tensorflow実戦[M] 黄文堅、唐源
    [2].Tensorflow技術解析と実戦[M]李嘉セン
    [3]https://baike.baidu.com/item/AlexNet/22689612?fr=aladdin
    [4].Tensorflow実戦Google学習フレームワーク[M].鄭澤宇、梁博文、顧思宇