tensorflow学習,ボリューム深さ学習ネットワーク(CNN)の確立,captchaグラフィック検証コードの識別と解読(21)

11202 ワード

ひまわりのインテリジェント
pythonが検証コード小節をどのように生成するかについて,captchaライブラリを用いてone-hotラベル付きピクチャデータセットを生成できるグラフィック検証コード生成器を作製した.このセクションでは、このデータセットに基づいて、ボリューム深さ学習ネットワーク(CNN)を構築し、この検証コードデータセットを解読することを識別するように訓練します.
CNNボリューム深さ学習ネットワークの構造
5層ネットワークを構築する計画で、上位3層はボリューム層、4、5層は全接続層である.4階層の非表示レイヤをdropoutします.そこで、ネットワーク構造は以下のようになる.
input
——>conv——>pool——>dropout
——>conv——>pool——>dropout
——>conv——>pool——>dropout
——>fully connected layer——>dropout
——>fully connected layer——>
output

基本モジュールの初期化
CNNボリューム深さ学習ネットワークを構築する前に、まず使用した方法をカプセル化し、その後の呼び出しを便利にし、次にコードを直接放出します.
def conv2d(self,x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(self,x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

def weight_variable(self,shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)

def bias_variable(self,shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

Python
上記のコードのように,ボリュームの横方向ステップはいずれも1であり,プール化層のpaddingとSAMEに設定されている.プール・レイヤのサイズを2に設定×2,ステップも2×2.重み係数は遮断された正規分布を用いて初期化し,その後relu活性化関数を用いるので,バイアス係数はいずれも0.1に初期化し,死ニューロンの発生を防止した.
CNNボリューム深さ学習ネットワークモデルの構築
まず第1層のボリュームを確立し、コードは以下の通りです.
# first layer
w_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(tf.nn.bias_add(conv2d(x_images, w_conv1), b_conv1))
h_pool1 = max_pool_2x2(h_conv1)
h_dropout1 = tf.nn.dropout(h_pool1,keep_prob)
conv_width = math.ceil(width/2)
conv_height = math.ceil(height/2)

Python
使用しました×5のボリュームコアは,検証コードから32種類の特徴を抽出する.ReLUを使用して関数をアクティブ化し、次いで最大値プール化し、次いでdropoutを実行した.最大プールサイズとステップが2に設定されているため×2であるため,プール化後,検証コードピクチャの高さと幅はいずれも元の半分になる.
次の2層のボリュームは類似しており、重み係数の形状はやや異なりますので、調整に注意してください.
#second layer
w_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(tf.nn.bias_add(conv2d(h_dropout1, w_conv2), b_conv2))
h_pool2 = max_pool_2x2(h_conv2)
h_dropout2 = tf.nn.dropout(h_pool2,keep_prob)
conv_width = math.ceil(conv_width/2)
conv_height = math.ceil(conv_height/2)

#third layer
w_conv3 = weight_variable([5, 5, 64, 64])
b_conv3 = bias_variable([64])
h_conv3 = tf.nn.relu(tf.nn.bias_add(conv2d(h_dropout2, w_conv3), b_conv3))
h_pool3 = max_pool_2x2(h_conv3)
h_dropout3 = tf.nn.dropout(h_pool3,keep_prob)
conv_width = math.ceil(conv_width/2)
conv_height = math.ceil(conv_height/2)

Python
続いて全接続層であり,確立方法は前の節と類似している.いずれも、ボリューム化されたすべてのフィーチャーを1次元ベクトルに平らにし、カテゴリ数に徐々に次元を下げます.2層の全接続層を確立し,第1層は1024に次元を下げ,第2層は1024からchar_num * classesに次元を下げた.char_numclassesの意味私たちは前節で非常にはっきり言ったが、ここでは一言だけ言って、その2つの積は検証コードの総カテゴリ数を表している.
#first fully layer
conv_width = int(conv_width)
conv_height = int(conv_height)
w_fc1 = weight_variable([64*conv_width*conv_height,1024])
b_fc1 = bias_variable([1024])
h_dropout3_flat = tf.reshape(h_dropout3,[-1,64*conv_width*conv_height])
h_fc1 = tf.nn.relu(tf.nn.bias_add(tf.matmul(h_dropout3_flat, w_fc1), b_fc1))
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

#second fully layer
w_fc2 = weight_variable([1024,char_num*classes])
b_fc2 = bias_variable([char_num*classes])
y_conv = tf.add(tf.matmul(h_fc1_drop, w_fc2), b_fc2)

Python
次に、その後の呼び出しを容易にするために、上記のコードをクラスにカプセル化し、すべてのコードを以下のように組み合わせます( : captcha_model.py).
# -*- coding: utf-8 -*
import tensorflow as tf
import math

class captchaModel():
    def __init__(self,
                 width = 160,
                 height = 60,
                 char_num = 4,
                 classes = 62):
        self.width = width
        self.height = height
        self.char_num = char_num
        self.classes = classes

    def conv2d(self,x, W):
        return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

    def max_pool_2x2(self,x):
        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                              strides=[1, 2, 2, 1], padding='SAME')

    def weight_variable(self,shape):
        initial = tf.truncated_normal(shape, stddev=0.1)
        return tf.Variable(initial)

    def bias_variable(self,shape):
        initial = tf.constant(0.1, shape=shape)
        return tf.Variable(initial)

    def create_model(self,x_images,keep_prob):
        #first layer
        w_conv1 = self.weight_variable([5, 5, 1, 32])
        b_conv1 = self.bias_variable([32])
        h_conv1 = tf.nn.relu(tf.nn.bias_add(self.conv2d(x_images, w_conv1), b_conv1))
        h_pool1 = self.max_pool_2x2(h_conv1)
        h_dropout1 = tf.nn.dropout(h_pool1,keep_prob)
        conv_width = math.ceil(self.width/2)
        conv_height = math.ceil(self.height/2)

        #second layer
        w_conv2 = self.weight_variable([5, 5, 32, 64])
        b_conv2 = self.bias_variable([64])
        h_conv2 = tf.nn.relu(tf.nn.bias_add(self.conv2d(h_dropout1, w_conv2), b_conv2))
        h_pool2 = self.max_pool_2x2(h_conv2)
        h_dropout2 = tf.nn.dropout(h_pool2,keep_prob)
        conv_width = math.ceil(conv_width/2)
        conv_height = math.ceil(conv_height/2)

        #third layer
        w_conv3 = self.weight_variable([5, 5, 64, 64])
        b_conv3 = self.bias_variable([64])
        h_conv3 = tf.nn.relu(tf.nn.bias_add(self.conv2d(h_dropout2, w_conv3), b_conv3))
        h_pool3 = self.max_pool_2x2(h_conv3)
        h_dropout3 = tf.nn.dropout(h_pool3,keep_prob)
        conv_width = math.ceil(conv_width/2)
        conv_height = math.ceil(conv_height/2)

        #first fully layer
        conv_width = int(conv_width)
        conv_height = int(conv_height)
        w_fc1 = self.weight_variable([64*conv_width*conv_height,1024])
        b_fc1 = self.bias_variable([1024])
        h_dropout3_flat = tf.reshape(h_dropout3,[-1,64*conv_width*conv_height])
        h_fc1 = tf.nn.relu(tf.nn.bias_add(tf.matmul(h_dropout3_flat, w_fc1), b_fc1))
        h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

        #second fully layer
        w_fc2 = self.weight_variable([1024,self.char_num*self.classes])
        b_fc2 = self.bias_variable([self.char_num*self.classes])
        y_conv = tf.add(tf.matmul(h_fc1_drop, w_fc2), b_fc2)

        return y_conv

Python
CNNボリューム深さ学習ネットワークの訓練
この部分では,前節で確立した検証コード生成器が生成した画像batchを,主に前節で確立したCNNネットワークに送る.各ロットに64個の訓練サンプルを採用し、100回のサイクルごとに100個の試験サンプルを採用して識別精度を検査し、精度が99%より大きい場合、訓練は終了する予定である.
前のセクションで確立したクラスを使用してインスタンスを具体化し、使用するパラメータを取得します.
captcha = generate_captcha.generateCaptcha()
width,height,char_num,characters,classes = captcha.get_parameter()

Python
placeholderの作成
x = tf.placeholder(tf.float32, [None, height,width,1])
y_ = tf.placeholder(tf.float32, [None, char_num*classes])
keep_prob = tf.placeholder(tf.float32)

Python
次に、前の部分で確立されたcaptchaModelクラスを用いて一例を具体化し、CNN深さ学習ネットワークモデルを生成することができる.
model = captcha_model.captchaModel(width,height,char_num,classes)
y_conv = model.create_model(x,keep_prob)

Python
トレーニングネットワークは、まずloss関数を定義する必要があります.ここではsigmoid_cross_entropy_with_logitsを使用しています.16節を参照してください.
cross_entropy = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=y_,logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

predict = tf.reshape(y_conv, [-1,char_num, classes])
real = tf.reshape(y_,[-1,char_num, classes])
correct_prediction = tf.equal(tf.argmax(predict,2), tf.argmax(real,2))
correct_prediction = tf.cast(correct_prediction, tf.float32)
accuracy = tf.reduce_mean(correct_prediction)

Python
次にトレーニングです.ここではsaverも定義し、トレーニングネットワークが完了した後、結果を保存できます(13節参照).
saver = tf.train.Saver()
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        step = 1
        while True:
            batch_x,batch_y = next(captcha.gen_captcha(64))
            _,loss = sess.run([train_step,cross_entropy],feed_dict={x: batch_x, y_: batch_y, keep_prob: 0.75})
            print ('step:%d,loss:%f' % (step,loss))
            if step % 100 == 0:
                batch_x_test,batch_y_test = next(captcha.gen_captcha(100))
                acc = sess.run(accuracy, feed_dict={x: batch_x_test, y_: batch_y_test, keep_prob: 1.})
                print ('###############################################step:%d,accuracy:%f' % (step,acc))
                if acc > 0.99:
                    saver.save(sess,"./capcha_model.ckpt")
                    break
            step += 1

Python
すべてのコードは、train.pyというファイル名で統合されています.
#-*- coding:utf-8 -*-
import tensorflow as tf
import numpy as np
import string
import generate_captcha
import captcha_model

if __name__ == '__main__':
    captcha = generate_captcha.generateCaptcha()
    width,height,char_num,characters,classes = captcha.get_parameter()

    x = tf.placeholder(tf.float32, [None, height,width,1])
    y_ = tf.placeholder(tf.float32, [None, char_num*classes])
    keep_prob = tf.placeholder(tf.float32)

    model = captcha_model.captchaModel(width,height,char_num,classes)
    y_conv = model.create_model(x,keep_prob)
    cross_entropy = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=y_,logits=y_conv))
    train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

    predict = tf.reshape(y_conv, [-1,char_num, classes])
    real = tf.reshape(y_,[-1,char_num, classes])
    correct_prediction = tf.equal(tf.argmax(predict,2), tf.argmax(real,2))
    correct_prediction = tf.cast(correct_prediction, tf.float32)
    accuracy = tf.reduce_mean(correct_prediction)

    saver = tf.train.Saver()
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        step = 1
        while True:
            batch_x,batch_y = next(captcha.gen_captcha(64))
            _,loss = sess.run([train_step,cross_entropy],feed_dict={x: batch_x, y_: batch_y, keep_prob: 0.75})
            print ('step:%d,loss:%f' % (step,loss))
            if step % 100 == 0:
                batch_x_test,batch_y_test = next(captcha.gen_captcha(100))
                acc = sess.run(accuracy, feed_dict={x: batch_x_test, y_: batch_y_test, keep_prob: 1.})
                print ('###############################################step:%d,accuracy:%f' % (step,acc))
                if acc > 0.99:
                    saver.save(sess,"./capcha_model.ckpt")
                    break
            step += 1

Python
そして訓練ができます.
$ python train.py
...
step:17760, loss:0.083060
step:17761, loss:0.082030
step:17762, loss:0.083040
step:17763, loss:0.083019
step:17764, loss:0.082072
step:17765, loss:0.081089
...

Bash
このトレーニングサイクルは比較的長く,GPUを採用するのに4−5時間程度,CPUを採用するのに20時間程度かかる.次のセクションでは、トレーニングが完了したネットワークモデルを放出し、構築されたCNNボリューム深さ学習ネットワークが検証コードを識別し、解読できるかどうかをテストします.
転載先:https://www.xrkzn.cn/tensorflow/tensorflow-study-build-cnn-to-recognize-captcha/