1. 程式人生 > >卷積神經網路簡單的應用(二):模型構建與訓練

卷積神經網路簡單的應用(二):模型構建與訓練

  1. 模型構建
    文中採用了Tensorflow框架進行模型的構建,這裡簡單介紹下Tensorflow的安裝(在Anaconda上安裝):
    ⑴Anaconda安裝:https://www.anaconda.com/download/,選擇支援py36的版本;
    ⑵直接在命令列中安裝Tensorflow:pip install tensorflow;
    ⑶測試是否已經安裝好Tensorflow:import tensorflow as tf,是否報錯。
    由於自己電腦比較low,卷積神經網路的引數以及深度都不是很多,其結構如下圖所示。圖中Cov為卷積操作,Pool為池化操作。

    建立該模型結構的程式碼如下:
    def create_cnn(out_size,w_alpha = 0.01,b_alpha = 0.01):#out_size:輸出類別個數
        x = tf.reshape(X,shape=[-1,200,150,3])    
        #第一層
        w_c1_1 = tf.Variable(w_alpha*tf.random_normal([3,3,1,32]))
        b_c1_1 = tf.Variable(b_alpha*tf.random_normal([32]))
        conv1_1 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(x,w_c1_1,strides=[1,1,1,1],padding='SAME'),b_c1_1))
                    
        conv1 = tf.nn.max_pool(conv1_1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        conv1 = tf.nn.dropout(conv1,keep_prob)
        print(conv1.get_shape().as_list())
        #第二層
        w_c2_1 = tf.Variable(w_alpha*tf.random_normal([3,3,32,64]))
        b_c2_1 = tf.Variable(b_alpha*tf.random_normal([64]))
        conv2_1 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv1,w_c2_1,strides=[1,1,1,1],padding='SAME'),b_c2_1))
          
        conv2 = tf.nn.max_pool(conv2_1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        conv2 = tf.nn.dropout(conv2,keep_prob)
        print(conv2.get_shape().as_list())
        #第三層
        w_c3_1 = tf.Variable(w_alpha*tf.random_normal([3,3,64,128]))
        b_c3_1 = tf.Variable(b_alpha*tf.random_normal([128]))
        conv3_1 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv2,w_c3_1,strides=[1,1,1,1],padding='SAME'),b_c3_1))        
        
        conv3 = tf.nn.max_pool(conv3_1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        conv3 = tf.nn.dropout(conv3,keep_prob)
        print(conv3.get_shape().as_list())
        #第四層
        w_c4_1 = tf.Variable(w_alpha*tf.random_normal([3,3,128,128]))
        b_c4_1 = tf.Variable(b_alpha*tf.random_normal([128]))
        conv4_1 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv3,w_c4_1,strides=[1,1,1,1],padding='SAME'),b_c4_1))        
        
        conv4 = tf.nn.max_pool(conv4_1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        conv4 = tf.nn.dropout(conv4,keep_prob)
        print(conv4.get_shape().as_list())
        
        #第五層    
        #fully connect layer    
        shp = conv4.get_shape()
        flattened_shape = shp[1].value * shp[2].value * shp[3].value
        dense = tf.reshape(conv4,[-1,flattened_shape])
        
        w_d = tf.Variable(w_alpha*tf.random_normal([flattened_shape,256]))
        b_d = tf.Variable(b_alpha*tf.random_normal([256]))
        
        dense = tf.nn.relu(tf.add(tf.matmul(dense,w_d),b_d))
        dense = tf.nn.dropout(dense,keep_prob)
        print(dense.get_shape().as_list())
        
        w_out = tf.Variable(w_alpha*tf.random_normal([256,out_size]))
        b_out = tf.Variable(b_alpha*tf.random_normal([out_size]))
        out = tf.add(tf.matmul(dense,w_out),b_out)
        print(out.get_shape().as_list())
        
        return out
  2. 模型訓練
    模型訓練時主要是損失的定義以及優化器的定義,Tensorflow中已經定義好了一些損失函式和優化器,這裡採用的損失函式為:tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits()),優化器選擇的是:AdadeltaOptimizer;在訓練的同時計算其識別率,達到給定的識別率時,模型就停止訓練;相關程式碼如所示:
    def train_cnn(x_data,y_data):
        output = create_cnn(4)
        print("create cnn end!")
        #損失
        loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=Y,logits=output))
        #優化器
        optimizer = tf.train.AdadeltaOptimizer(learning_rate=0.1).minimize(loss)
        #分別獲取輸出和實際最大值的index
        max_idx_p = tf.argmax(output,1)
        max_idx_l = tf.argmax(Y,1)    
        
        correct_pred = tf.equal(max_idx_p,max_idx_l)
        accuracy = tf.reduce_mean(tf.cast(correct_pred,tf.float32))
        
        saver = tf.train.Saver(max_to_keep=3)
        with tf.Session() as sess:
            sess.run(tf.global_variables_initializer())
            
            step = 0
            while True:
                #獲取檔案中的相關圖片為一個batch
                batch_x,batch_y = get_next_batch_from_file()
                _,loss_ = sess.run([optimizer,loss],feed_dict = {X:batch_x,Y:batch_y,keep_prob:0.75})
                print(step,loss_)
                if step % 10 == 0 and step != 0:
                    batch_x_test,batch_y_test = get_next_batch_from_file()
                    acc = sess.run(accuracy,feed_dict={X:batch_x_test,Y:batch_y_test,keep_prob:1.0})
                    print(step,acc)
                    if acc > 0.7:
                        saver.save(sess,"./model/cnn.model",global_step=step)
                    if acc > 0.8:
                        saver.save(sess,"./model/cnn.model",global_step=step)
                        #break
                    if acc > 0.9:
                        saver.save(sess,"./model/cnn.model",global_step=step)
                        break
                step += 1
    #在main中呼叫
    if __name__ == '__main__':
        isTrain = 1
        if 1 == isTrain:
            X = tf.placeholder(tf.float32,[None,200,150,1])
            Y = tf.placeholder(tf.float32,[None,4])
            
            keep_prob = tf.placeholder(tf.float32)
            train_cnn(xdata,ydata)
    
  3. 其他函式
    get_next_batch_from_file函式的實現
    def get_next_batch_from_file(batch_size = 128):    
        each_batch = batch_size // 4
        x_batch_data,y_batch_data = read_random_data('./f_a/data',each_batch,0)
        
        x,y = read_random_data('./f_b/data',each_batch,1)
        x_batch_data.extend(x)
        y_batch_data.extend(y)
        
        x,y = read_random_data('./m_a/data',each_batch,2)
        x_batch_data.extend(x)
        y_batch_data.extend(y)
        
        x,y = read_random_data('./m_b/data',each_batch,3)
        x_batch_data.extend(x)
        y_batch_data.extend(y)
        
        x_batch_data = np.array(x_batch_data,dtype = np.float32)
        y_batch_data = np.array(y_batch_data,dtype = np.float32)
        
        return x_batch_data,y_batch_data
    def read_random_data(file_path,each_batch,t):
        flist = os.listdir(file_path)
        low = np.random.randint(len(flist))
        
        x_batch_file = None
        x_rdata = []
        y_rdata = []
        
        #print(low)
        if low + each_batch > len(flist) - 1:
            x_batch_file = flist[low:len(flist)]
            x_batch_file.extend(flist[:each_batch - len(flist) + low])
            #print(len(x_batch_file),'1',low,'=>',len(flist),'|','0=>',each_batch - len(flist) + low)
        else:       
            x_batch_file = flist[low:low + each_batch]
            #print(len(x_batch_file),'2')
        # read data
        for f in x_batch_file:
            img = cv2.imread(file_path+'/'+f)
            x_rdata.append(img)
            if 0 == t:
                y_rdata.append([1,0,0,0])
            if 1 == t:
                y_rdata.append([0,1,0,0])
            if 2 == t:
                y_rdata.append([0,0,1,0])
            if 3 == t:
                y_rdata.append([0,0,0,1])
        
        return x_rdata,y_rdata
    這是訓練好的模型,僅供參考:連結:https://pan.baidu.com/s/1uuzVMpG_PA_z8i77hS7wRA 密碼:t7s6