Tensorflow VGG网络构建手写数字识别系统设计--代码篇

Tensorflow VGG网络构建手写数字识别系统设计

 

 

1、建立VGG16模型

class VGG16_Mode():
    """ create vgg16 network use tensorflow
        VGG16 network structure:
        (conv 3x3 64)=>(conv 3x3 64, pool/2)
        (conv 3x3 128)=>(conv 3x3 128, pool/2)
        (conv 3x3 256)=>(conv 3x3 256)=>(conv 3x3 256)=>(conv 3x3 256, pool/2)
        (conv 3x3 512)=>(conv 3x3 512)=>(conv 3x3 512)=>(conv 3x3 512, pool/2)
        (fc 4096)=>(fc 4096)=>(fc classes)
    """
    
    def variable_summaries(self, var, name):
        with tf.name_scope('summaries'):
            tf.summary.histogram(name, var)
            mean = tf.reduce_mean(var)
            tf.summary.scalar('mean/' + name, mean)
            stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))
            tf.summary.scalar('stddev/' + name, stddev)  
            
            
    def conv_layer(self, data, ksize, stride, name, w_biases = False,padding = "SAME"):
        with tf.variable_scope(name) as scope:
            with tf.name_scope(name):
                with tf.name_scope("weights"):
                    w_init = tf.contrib.layers.xavier_initializer()
                    w = tf.get_variable(shape= ksize, initializer= w_init,name= 'w')
                    self.variable_summaries(w, name + "/weights")
                with tf.name_scope("biases"):
                    biases = tf.Variable(tf.constant(0.0, shape=[ksize[3]], dtype=tf.float32), 'biases')
                    self.variable_summaries(biases, name + "/biases")
                with tf.name_scope("Wx_plus_b"):
                    if w_biases == False:
                        cov = tf.nn.conv2d(input= data, filter= w, strides= stride, padding= padding)
                    else:
                        cov = tf.nn.conv2d(input= data,filter= w, stride= stride,padding= padding) + biases       
        
        # 记录神经网络节点输出在经过激活函数之后的分布。
        tf.summary.histogram(name + '/activations', cov)
        return cov

    def pool_layer(self, data, ksize, stride, name, padding= 'VALID'):
        with tf.variable_scope(name) as scope:
            max_pool =  tf.nn.max_pool(value= data, ksize= ksize, strides= stride,padding= padding)
        return max_pool

    def flatten(self,data):
        [a,b,c,d] = data.shape
        ft = tf.reshape(data,[-1,b*c*d])
        return ft

    def fc_layer(self,data,name,fc_dims):
        with tf.variable_scope(name) as scope:
            with tf.name_scope(name):
                with tf.name_scope("weights"):
                    w_init = tf.contrib.layers.xavier_initializer()
                    w = tf.get_variable(shape=[data.shape[1],fc_dims],name= 'w',initializer=w_init)
                    self.variable_summaries(w, name + "/weights")
                with tf.name_scope("biases"):
                    biases = tf.Variable(tf.constant(0.0, shape=[fc_dims], dtype=tf.float32), 'biases')
                    self.variable_summaries(biases, name + "/biases")
                with tf.name_scope("Wx_plus_b"):
                    fc = tf.nn.relu(tf.matmul(data,w)+ biases)
                    tf.summary.histogram(name + '/pre_activations', tf.matmul(data,w)+ biases)       
        
        # 记录神经网络节点输出在经过激活函数之后的分布。
        tf.summary.histogram(name + '/activations', fc)
        return fc

    def finlaout_layer(self,data,name,fc_dims):
        with tf.variable_scope(name, reuse=tf.AUTO_REUSE):
            with tf.name_scope(name):
                with tf.name_scope("weights"):
                    w_init = tf.contrib.layers.xavier_initializer()
                    w = tf.get_variable(shape=[data.shape[1],fc_dims],name= 'w',initializer=w_init)
                    self.variable_summaries(w, name + "/weights")
                with tf.name_scope("biases"):
                    biases = tf.Variable(tf.constant(0.0, shape=[fc_dims], dtype=tf.float32), 'biases')
                    self.variable_summaries(biases, name + "/biases")
                with tf.name_scope("Wx_plus_b"):
                    fc = tf.nn.softmax(tf.matmul(data,w)+ biases)
                    tf.summary.histogram(name + '/pre_activations', tf.matmul(data,w)+ biases)      
        
        # 记录神经网络节点输出在经过激活函数之后的分布。
        tf.summary.histogram(name + '/activations', fc)
        return fc

    def model_bulid(self, height, width, channel,classes):
        
        with tf.name_scope("input"):
            x = tf.placeholder(dtype= tf.float32, shape = [None,height,width,channel])
            y = tf.placeholder(dtype= tf.float32 ,shape=[None,classes])
            tf.summary.image("input", x, 50)
        # conv 1 ,if image Nx465x128x1 ,(conv 3x3 64)=>(conv 3x3 64, pool/2)
        with tf.name_scope("conv1"):
            conv1_1 = tf.nn.relu(self.conv_layer(x,ksize= [3,3,1,64],stride=[1,1,1,1],padding="SAME",name="conv1_1"))
            conv1_2 = tf.nn.relu(self.conv_layer(conv1_1,ksize=[3,3,64,64],stride=[1,1,1,1],padding="SAME",name="conv1_2")) # Nx465x128x1 ==>   Nx465x128x64
            pool1_1 = self.pool_layer(conv1_2,ksize=[1,2,2,1],stride=[1,2,2,1],name="pool1_1") # N*232x64x64

        # conv 2,(conv 3x3 128)=>(conv 3x3 128, pool/2)
        with tf.name_scope("conv2"):
            conv2_1 = tf.nn.relu(self.conv_layer(pool1_1,ksize=[3,3,64,128],stride=[1,1,1,1],padding="SAME",name="conv2_1"))
            conv2_2 = tf.nn.relu(self.conv_layer(conv2_1,ksize=[3,3,128,128],stride=[1,1,1,1],padding="SAME",name="conv2_2")) # Nx232x64x128
            pool2_1 = self.pool_layer(conv2_2,ksize=[1,2,2,1],stride=[1,2,2,1],name="pool2_1") # Nx116x32x128

        # conv 3,(conv 3x3 256)=>(conv 3x3 256)=>(conv 3x3 256)=>(conv 3x3 256, pool/2)
        with tf.name_scope("conv3"):
            conv3_1 = tf.nn.relu(self.conv_layer(pool2_1,ksize=[3,3,128,256],stride=[1,1,1,1],padding="SAME",name="conv3_1"))
            conv3_2 = tf.nn.relu(self.conv_layer(conv3_1,ksize=[3,3,256,256],stride=[1,1,1,1],padding="SAME",name="conv3_2"))
            conv3_3 = tf.nn.relu(self.conv_layer(conv3_2,ksize=[3,3,256,256],stride=[1,1,1,1],padding="SAME",name="conv3_3"))
            conv3_4 = tf.nn.relu(self.conv_layer(conv3_3,ksize=[3,3,256,256],stride=[1,1,1,1],padding="SAME",name="conv3_4")) # NX116X32X256
            pool3_1 = self.pool_layer(conv3_4,ksize=[1,2,2,1],stride=[1,2,2,1],name="pool3_1") # Nx58x16x256

        #conv 4,(conv 3x3 512) = > (conv 3x3 512) = > (conv 3x3 512) = > (conv 3x3 512, pool / 2)
        with tf.name_scope("conv4"):
            conv4_1 = tf.nn.relu(self.conv_layer(pool3_1,ksize=[3,3,256,512],stride=[1,1,1,1],padding="SAME",name="conv4_1"))
            conv4_2 = tf.nn.relu(self.conv_layer(conv4_1,ksize=[3,3,512,512],stride=[1,1,1,1],padding="SAME",name="conv4_2"))
            conv4_3 = tf.nn.relu(self.conv_layer(conv4_2,ksize=[3,3,512,512],stride=[1,1,1,1],padding="SAME",name="conv4_3"))
            conv4_4 = tf.nn.relu(self.conv_layer(conv4_3,ksize=[3,3,512,512],stride=[1,1,1,1],padding="SAME",name="conv4_4")) # Nx58x16x512
            pool4_1 = self.pool_layer(conv4_4,ksize=[1,2,2,1],stride=[1,2,2,1],name="pool4_1") # Nx29x8x512

        # Flatten
        with tf.name_scope("Flatten"):
            ft = self.flatten(pool4_1)

        # Dense layer,(fc 4096)=>(fc 4096)=>(fc classes)
        fc1 = self.fc_layer(ft,fc_dims=4096,name="fc1")
        fc2 = self.fc_layer(fc1,fc_dims=4096,name="fc2")
        # fc3 = self.fc_layer(fc2,fc_dims=10,name="fc3")

        with tf.name_scope("Final_Output"):
            finaloutput = self.finlaout_layer(fc2,fc_dims=10,name="final")

        # cost
        with tf.name_scope("cross_entropy"):
            cross_entropy = tf.losses.softmax_cross_entropy(y,finaloutput)
            tf.summary.scalar("cross_entropy", cross_entropy)

2、设置训练参数

# optimize
        LEARNING_RATE_BASE = 0.0001
        LEARNING_RATE_DECAY = 0.000001
        LEARNING_RATE_STEP = 1000
        #MOVING_AVERAGE_DECAY = 0.99
        global_steps = tf.Variable(0, trainable=False)
        
        # 处理滑动平均的命名空间。
        #with tf.name_scope("moving_average"):
            #variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_steps)
            #variables_averages_op = variable_averages.apply(tf.trainable_variables())
        
        with tf.name_scope("train"):
            learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,
                                                   global_steps,
                                                   LEARNING_RATE_STEP,
                                                   LEARNING_RATE_DECAY,
                                                   staircase=True)
            
            with tf.variable_scope(tf.get_variable_scope(), reuse=tf.AUTO_REUSE):
                optimize = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cross_entropy,global_step=global_steps)

 

3、使用Tensorboard对训练过程进行监视

with tf.name_scope("Accuracy"):
            with tf.name_scope("prediction_label"):
                prediction_label = finaloutput
            with tf.name_scope("correct_prediction"):
                correct_prediction = tf.equal(tf.argmax(prediction_label, 1), tf.argmax(y, 1))
            with tf.name_scope("accurary"):
                accurary = tf.reduce_mean(tf.cast(correct_prediction, dtype=tf.float32))
            with tf.name_scope("correct_times_in_batch"):
                correct_times_in_batch = tf.reduce_mean(tf.cast(correct_prediction, dtype=tf.int32))
            tf.summary.scalar("Accuracy", accurary)

4、打开会话session,对模型进行训练

self.merged = tf.summary.merge_all()
        self.init_sess()
        self.writer = tf.summary.FileWriter("log", self.sess.graph)
        return dict(
            x=x,
            y=y,
            optimize=optimize,
            prediction_label=prediction_label,
            correct_times_in_batch=correct_times_in_batch,
            cross_entropy=cross_entropy,
            accurary=accurary,
            global_steps=global_steps,
            Flatten=ft
        )

    def init_sess(self):
        init = tf.group(tf.global_variables_initializer(),tf.local_variables_initializer())
        self.sess = tf.Session()
        self.sess.run(init)

    def train_network(self,graph,x_train,y_train):
        # Tensorfolw Adding more and more nodes to the previous graph results in a larger and larger memory footprint
        # reset graph
        tf.reset_default_graph()
        self.sess.run(graph['optimize'],feed_dict={graph['x']:x_train, graph['y']:y_train})

    def load_data(self):
        self.mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
    
    def train(self, n_epcho=1000, imgsize=[28,28], chnnels=1, n_classes=10,batch_size=500):
        imgsize1, imgsize2 = imgsize
        
        #self.init_sess()
        g = self.model_bulid(28, 28, 1, 10)
        #writer = g["writer"]
        for i in range(n_epcho):
            batch_xs, batch_ys = self.mnist.train.next_batch(500)
            batch_xs = np.reshape(batch_xs,[-1,28,28,1])
            #self.train_network(g, batch_xs, batch_ys)
            if i % 1000 == 0:
                # 配置运行时需要记录的信息。
                #run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
                # 运行时记录运行信息的proto。
                #run_metadata = tf.RunMetadata()
                summary, _, cross_entropy, step, accuracy = self.sess.run([self.merged,
                                                              g["optimize"], 
                                                              g["cross_entropy"], 
                                                              g["global_steps"],
                                                              g["accurary"]], 
                                                              feed_dict={g["x"]: batch_xs, g["y"]: batch_ys}
                                                              )
                #options=run_options, 
                       #                                       run_metadata=run_metadata
                #self.writer.add_run_metadata(run_metadata=run_metadata, tag=("tag%d" % i), global_step=i)
                print("After %d training step(s), loss on training batch is %g." % (int(step/100), cross_entropy))
            else:
                summary, _, cross_entropy, step, accuracy = self.sess.run([self.merged,
                                                              g["optimize"], 
                                                              g["cross_entropy"], 
                                                              g["global_steps"],
                                                              g["accurary"]], 
                                                              feed_dict={g["x"]: batch_xs, g["y"]: batch_ys})
            self.writer.add_summary(summary, i)
        
        
        self.save_model(g)
        self.close()
            
        
                
    def close(self):
        self.sess.close()
        self.writer.close()

    def save_model(self, graph):
        
        export_path = "pb_model/1"
        if os.path.exists(export_path):
            os.system("rm -rf "+ export_path)
        print("Export the model to {}".format(export_path))
        
        # 构建需要在新会话中恢复的变量的 TensorInfo protobuf
        X_TensorInfo = sm.utils.build_tensor_info(graph["x"])
        y_true_TensorInfo = sm.utils.build_tensor_info(graph["y"])

        features_TensorInfo = sm.utils.build_tensor_info(graph["Flatten"])
        y_pred_cls_TensorInfo = sm.utils.build_tensor_info(graph["prediction_label"])
        accu_TensorInfo = sm.utils.build_tensor_info(graph["accurary"])
        # 构建 SignatureDef protobuf
        model_signature = sm.signature_def_utils.build_signature_def(
                                        inputs={'input_1': X_TensorInfo,
                                                'input_2': y_true_TensorInfo},
                                        outputs={'output_1': features_TensorInfo, 
                                                 'output_2': y_pred_cls_TensorInfo,
                                                 'output_3': accu_TensorInfo},method_name=signature_constants.PREDICT_METHOD_NAME)

        
        try:
            legacy_init_op = tf.group(
                tf.tables_initializer(), name='legacy_init_op')
            builder = saved_model_builder.SavedModelBuilder(export_path)
            builder.add_meta_graph_and_variables(
                self.sess, [tag_constants.SERVING],
                clear_devices=True,
                signature_def_map={
                    signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
                        model_signature,
                },
                legacy_init_op=legacy_init_op)

            builder.save()
        except Exception as e:
            print("Fail to export saved model, exception: {}".format(e))

5、开始训练

vgg_model = VGG16_Mode()  # 创建模型
vgg_model.load_data()  # 加载数据
vgg_model.train(n_epcho=20000)  # 训练模型

6、加载模型

#加载pb模型
def load_pb(data, labels):
    session = tf.Session(graph=tf.Graph())
    model_file_path = "model"
    meta_graph = tf.saved_model.loader.load(session, [tf.saved_model.tag_constants.SERVING], model_file_path)

    model_graph_signature = list(meta_graph.signature_def.items())[0][1]
    output_tensor_names = []
    output_op_names = []
    for output_item in model_graph_signature.outputs.items():
        output_op_name = output_item[0]
        output_op_names.append(output_op_name)
        output_tensor_name = output_item[1].name
        output_tensor_names.append(output_tensor_name)
    print("load model finish!")
    sentences = {}
    # 测试pb模型
    sentences["input_1"] = data
    sentences["input_2"] = labels
    feed_dict_map = {}
    for input_item in model_graph_signature.inputs.items():
        input_op_name = input_item[0]
        input_tensor_name = input_item[1].name
        feed_dict_map[input_tensor_name] = sentences[input_op_name]
        
    result = session.run(output_tensor_names, feed_dict=feed_dict_map)
    return result

7、模型评估

show_function = ShowResult()
show_example = show_function.show(img_data=mnist.test.images, 
                                  img_labels=mnist.test.labels, 
                                  y_pred=result[1], 
                                  show_example_errors=True, 
                                  show_confusion_matrix=True, 
                                  show_exmaple_random=True)

from performace_evaluation import chswn
evaluation = chswn()
classes=[0,1,2,3,4,5,6,7,8,9]
y_predict = evaluation.label_binarize_convert(np.argmax(result[1],axis=1), classes)
evaluation.Average_precision_score(mnist.test.labels, y_predict, classes)
evaluation.Precision_Recall_curve_to_multi_class(classes=classes)

8、实验结果

Tensorflow VGG网络构建手写数字识别系统设计--代码篇_第1张图片Tensorflow VGG网络构建手写数字识别系统设计--代码篇_第2张图片

Tensorflow VGG网络构建手写数字识别系统设计--代码篇_第3张图片

你可能感兴趣的:(技术交流)