卷積神經網路簡單的應用(二):模型構建與訓練
阿新 • • 發佈:2019-01-08
- 模型構建
文中採用了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
- 模型訓練
模型訓練時主要是損失的定義以及優化器的定義,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)
- 其他函式
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
這是訓練好的模型,僅供參考:連結:https://pan.baidu.com/s/1uuzVMpG_PA_z8i77hS7wRA 密碼:t7s6def 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