『TensorFlow』徒手裝高達_初號機_添加訓練模組並整合為可用分類網絡
阿新 • • 發佈:2017-05-30
正則 basename eth enum 結構 __name__ 第一個 sce 選擇
摘要:
本次整合了前面兩節的模組,並添加向前傳播&反饋訓練部分,使之成為一個包含訓練&驗證&測試的分類網絡。
文件架構:
代碼整合:
image_info.py,圖片讀取部分
1 import glob 2 import os.path 3 import random 4 import numpy as np 5 import tensorflow as tf 6 7 def creat_image_lists(validation_percentage,testing_percentage,INPUT_DATA): 8 ‘‘‘9 將圖片(無路徑文件名)信息保存在字典中 10 :param validation_percentage: 驗證數據百分比 11 :param testing_percentage: 測試數據百分比 12 :param INPUT_DATA: 最外層數據路徑(到達類目錄上層) 13 :return: 字典{標簽:{文件夾:str,訓練:[],驗證:[],測試:[]},...} 14 ‘‘‘ 15 result = {} 16 sub_dirs = [x[0] forx in os.walk(INPUT_DATA)] 17 # 由於os.walk()列表第一個是‘./‘,所以排除 18 is_root_dir = True #<----- 19 # 遍歷各個label文件夾 20 for sub_dir in sub_dirs: 21 if is_root_dir: #<----- 22 is_root_dir = False 23 continue 24 25 extensions = [‘jpg‘, ‘jpeg‘, ‘JPG‘, ‘JPEG‘] 26 file_list = [] 27 dir_name = os.path.basename(sub_dir) 28 # 遍歷各個可能的文件尾綴 29 for extension in extensions: 30 # file_glob = os.path.join(INPUT_DATA,dir_name,‘*.‘+extension) 31 file_glob = os.path.join(sub_dir, ‘*.‘ + extension) 32 file_list.extend(glob.glob(file_glob)) # 匹配並收集路徑&文件名 33 # print(file_glob,‘\n‘,glob.glob(file_glob)) 34 if not file_list: continue 35 36 label_name = dir_name.lower() # 生成label,實際就是小寫文件夾名 37 38 # 初始化各個路徑&文件收集list 39 training_images = [] 40 testing_images = [] 41 validation_images = [] 42 43 # 去路徑,只保留文件名 44 for file_name in file_list: 45 base_name = os.path.basename(file_name) 46 47 # 隨機劃分數據給驗證和測試 48 chance = np.random.randint(100) 49 if chance < validation_percentage: 50 validation_images.append(base_name) 51 elif chance < (validation_percentage + testing_percentage): 52 testing_images.append(base_name) 53 else: 54 training_images.append(base_name) 55 # 本標簽字典項生成 56 result[label_name] = { 57 ‘dir‘ : dir_name, 58 ‘training‘ : training_images, 59 ‘testing‘ : testing_images, 60 ‘validation‘ : validation_images 61 } 62 return result 63 64 def get_image_path(image_lists, image_dir, label_name, index, category): 65 ‘‘‘ 66 獲取單張圖片的存儲地址 67 :param image_lists: 全圖片字典 68 :param image_dir: 外層文件夾(內部是標簽文件夾) 69 :param label_name: 標簽名 70 :param index: 隨機數索引 71 :param category: training or validation 72 :return: 圖片中間變量地址 73 ‘‘‘ 74 label_lists = image_lists[label_name] 75 category_list = label_lists[category] # 獲取目標category圖片列表 76 mod_index = index % len(category_list) # 隨機獲取一張圖片的索引 77 base_name = category_list[mod_index] # 通過索引獲取圖片名 78 return os.path.join(image_dir,label_lists[‘dir‘],base_name) 79 80 81 def get_random_cached_inputs(sess,n_class,image_lists,batch,category,INPUT_DATA,shape=[299,299]): 82 ‘‘‘ 83 函數隨機獲取一個batch的圖片作為訓練數據,並調整大小至輸入層大小 84 調用get_image_path 85 :param sess: 會話句柄 86 :param n_class: 分類數目 87 :param image_lists: 圖片字典 88 :param batch: batch大小 89 :param category: training or validation 90 :param INPUT_DATA: 最外層圖片文件夾 91 :param shape: 輸入層size 92 :return: image & label數組 93 ‘‘‘ 94 images = [] 95 labels = [] 96 for i in range(batch): 97 label_index = random.randrange(n_class) # 標簽索引隨機生成 98 label_name = list(image_lists.keys())[label_index] # 標簽名獲取 99 image_index = random.randrange(65536) # 標簽內圖片索引隨機種子 100 101 image_path = get_image_path(image_lists, INPUT_DATA, label_name, image_index, category) 102 image_raw = tf.gfile.FastGFile(image_path, ‘rb‘).read() 103 image_data = sess.run(tf.image.resize_images(tf.image.decode_jpeg(image_raw), 104 shape,method=random.randint(0,3))) 105 106 ground_truth = np.zeros(n_class,dtype=np.float32) 107 ground_truth[label_index] = 1.0 # 標準結果[0,0,1,0...] 108 # 收集瓶頸張量和label 109 images.append(image_data) 110 labels.append(ground_truth) 111 return images,labels 112 113 114 def get_test_images(sess,image_lists,n_class,shape=[299,299]): 115 ‘‘‘ 116 獲取所有test數據 117 調用get_image_path 118 :param sess: 會話句柄 119 :param image_lists: 圖片字典 120 :param n_class: 分類數目 121 :param shape: 輸入層size 122 :return: 123 ‘‘‘ 124 test_images = [] 125 ground_truths = [] 126 label_name_list = list(image_lists.keys()) 127 for label_index,label_name in enumerate(image_lists[label_name_list]): 128 category = ‘testing‘ 129 for image_index, unused_base_name in enumerate(image_lists[label_name][category]): # 索引, {文件名} 130 131 image_path = get_image_path(image_lists, INPUT_DATA, label_name, image_index, category) 132 image_raw = tf.gfile.FastGFile(image_path, ‘rb‘).read() 133 image_data = sess.run(tf.image.resize_images(tf.image.decode_jpeg(image_raw), 134 shape, method=random.randint(0, 3))) 135 136 ground_truth = np.zeros(n_class, dtype=np.float32) 137 ground_truth[label_index] = 1.0 138 test_images.append(image_data) 139 ground_truths.append(ground_truth) 140 return test_images, ground_truths 141 142 143 if __name__==‘__main__‘: 144 145 INPUT_DATA = ‘./flower_photos‘ # 數據文件夾 146 VALIDATION_PERCENTAGE = 10 # 驗證用數據百分比 147 TEST_PERCENTAGE = 10 # 測試用數據百分比 148 BATCH_SIZE = 128 # 數據包大小 149 INPUT_SIZE = [224, 224] # 標準輸入尺寸 150 151 image_dict = creat_image_lists(VALIDATION_PERCENTAGE,TEST_PERCENTAGE,INPUT_DATA) 152 n_class = len(image_dict.keys()) 153 sess = tf.Session() 154 category = ‘training‘ 155 image_list, label_list = get_random_cached_inputs( 156 sess, n_class, image_dict, BATCH_SIZE, category,INPUT_DATA,INPUT_SIZE) 157 # exit()
AlexNet.py,網絡主幹
優化方式:
- 全連接層Weights進行了dropout
- 全連接層Weights進行了l2正則化
由於l2正則化結果收集進‘losses‘中,所以主函數計算loss時應該註意
更新:
由於training和validation一次傳入1batch的數據量,而test一次傳入所有數據,所以修改了fc1層代碼,使網絡不再需要固定長度的數據量。
1 import tensorflow as tf 2 3 ‘‘‘ 4 AlwxNet網絡結構主體,會接受batch圖片返回數組label, 5 且會在全連接Weights上l2正則化並收集進‘losses‘集合內部 6 ‘‘‘ 7 8 def print_activations(t): 9 """ 10 打印卷積層&池化層的尺寸 11 :param t: tensor 12 :return: 13 """ 14 print(t.op.name, ‘ ‘, t.get_shape().as_list()) 15 16 def inference(images,regularizer,N_CLASS=10,train=True): 17 ‘‘‘ 18 AlexNex網絡主體 19 :param images: 圖片batch,4-D:array 20 :param regularizer: 正則化函數選擇,eg:regularizer = tf.contrib.layers.l2_regularizer(0.0001) 21 :param N_CLASS: 分類數目 22 :param train: True or False,是否是在訓練,引入FC層的dropout 23 :return: logits,01型list;parameters,全訓練參數(歷史遺留問題,一般用不到) 24 ‘‘‘ 25 26 parameters = [] 27 28 # conv1 29 with tf.name_scope(‘conv1‘) as scope: 30 kernel = tf.Variable(tf.truncated_normal([11, 11, 3, 64], dtype=tf.float32, 31 stddev=1e-1), name=‘Weights‘) 32 conv = tf.nn.conv2d(images, kernel, [1, 4, 4, 1], padding=‘SAME‘) 33 biases = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32), 34 trainable=True, name=‘biases‘) 35 bias = tf.nn.bias_add(conv, biases) 36 conv1 = tf.nn.relu(bias, name=scope) 37 print_activations(conv1) 38 parameters += [kernel, biases] 39 40 # pool1 41 pool1 = tf.nn.max_pool(conv1, 42 ksize=[1, 3, 3, 1], 43 strides=[1, 2, 2, 1], 44 padding=‘VALID‘, 45 name=‘pool1‘) 46 print_activations(pool1) 47 48 # conv2 49 with tf.name_scope(‘conv2‘) as scope: 50 kernel = tf.Variable(tf.truncated_normal([5, 5, 64, 192], dtype=tf.float32, 51 stddev=1e-1), name=‘Weights‘) 52 conv = tf.nn.conv2d(pool1, kernel, [1, 1, 1, 1], padding=‘SAME‘) 53 biases = tf.Variable(tf.constant(0.0, shape=[192], dtype=tf.float32), 54 trainable=True, name=‘biases‘) 55 bias = tf.nn.bias_add(conv, biases) 56 conv2 = tf.nn.relu(bias, name=scope) 57 parameters += [kernel, biases] 58 print_activations(conv2) 59 60 # pool2 61 pool2 = tf.nn.max_pool(conv2, 62 ksize=[1, 3, 3, 1], 63 strides=[1, 2, 2, 1], 64 padding=‘VALID‘, 65 name=‘pool2‘) 66 print_activations(pool2) 67 68 # conv3 69 with tf.name_scope(‘conv3‘) as scope: 70 kernel = tf.Variable(tf.truncated_normal([3, 3, 192, 384], 71 dtype=tf.float32, 72 stddev=1e-1), name=‘Weights‘) 73 conv = tf.nn.conv2d(pool2, kernel, [1, 1, 1, 1], padding=‘SAME‘) 74 biases = tf.Variable(tf.constant(0.0, shape=[384], dtype=tf.float32), 75 trainable=True, name=‘biases‘) 76 bias = tf.nn.bias_add(conv, biases) 77 conv3 = tf.nn.relu(bias, name=scope) 78 parameters += [kernel, biases] 79 print_activations(conv3) 80 81 # conv4 82 with tf.name_scope(‘conv4‘) as scope: 83 kernel = tf.Variable(tf.truncated_normal([3, 3, 384, 256], 84 dtype=tf.float32, 85 stddev=1e-1), name=‘Weights‘) 86 conv = tf.nn.conv2d(conv3, kernel, [1, 1, 1, 1], padding=‘SAME‘) 87 biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32), 88 trainable=True, name=‘biases‘) 89 bias = tf.nn.bias_add(conv, biases) 90 conv4 = tf.nn.relu(bias, name=scope) 91 parameters += [kernel, biases] 92 print_activations(conv4) 93 94 # conv5 95 with tf.name_scope(‘conv5‘) as scope: 96 kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 256], 97 dtype=tf.float32, 98 stddev=1e-1), name=‘Weights‘) 99 conv = tf.nn.conv2d(conv4, kernel, [1, 1, 1, 1], padding=‘SAME‘) 100 biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32), 101 trainable=True, name=‘biases‘) 102 bias = tf.nn.bias_add(conv, biases) 103 conv5 = tf.nn.relu(bias, name=scope) 104 parameters += [kernel, biases] 105 print_activations(conv5) 106 107 # pool5 108 pool5 = tf.nn.max_pool(conv5, 109 ksize=[1, 3, 3, 1], 110 strides=[1, 2, 2, 1], 111 padding=‘VALID‘, 112 name=‘pool5‘) 113 print_activations(pool5) 114 115 # fc1 116 with tf.name_scope(‘fc1‘) as scope: 117 reshape = tf.reshape(pool5,[images.get_shape().as_list()[0],-1]) # [BATCH_SIZE,-1] <------- 118 dim = reshape.get_shape()[1].value 119 Weight = tf.Variable(tf.truncated_normal([dim,4096], stddev=0.01),name=‘Weights‘) 120 bias = tf.Variable(tf.constant(0.1,shape=[4096]),name=‘biases‘) 121 fc1 = tf.nn.relu(tf.matmul(reshape,Weight) + bias,name=scope) 122 tf.add_to_collection(‘losses‘, regularizer(Weight)) 123 if train : fc1 = tf.nn.dropout(fc1,0.5) 124 parameters += [Weight, biases] 125 print_activations(fc1) 126 127 # fc2 128 with tf.name_scope(‘fc2‘) as scope: 129 Weight = tf.Variable(tf.truncated_normal([4096, 4096], stddev=0.01),name=‘Weights‘) 130 bias = tf.Variable(tf.constant(0.1, shape=[4096]),name=‘biases‘) 131 fc2 = tf.nn.relu(tf.matmul(fc1, Weight) + bias,name=scope) 132 tf.add_to_collection(‘losses‘, regularizer(Weight)) 133 if train: fc2 = tf.nn.dropout(fc2, 0.5) 134 parameters += [Weight, biases] 135 print_activations(fc2) 136 137 # fc3 138 with tf.name_scope(‘fc3‘) as scope: 139 Weight = tf.Variable(tf.truncated_normal([4096, N_CLASS], stddev=0.01),name=‘Weights‘) 140 bias = tf.Variable(tf.constant(0.1, shape=[N_CLASS]),name=‘biases‘) 141 logits = tf.add(tf.matmul(fc2, Weight),bias,name=scope) 142 tf.add_to_collection(‘losses‘, regularizer(Weight)) 143 parameters += [Weight, biases] 144 print_activations(logits) 145 146 return logits, parameters
AlexNet_train.py,訓練部分
接收了L2正則化優化
數據有測試&驗證兩個隨機抽取圖片過程和一次性全部加載的test過程
1 import AlexNet as Net 2 import tensorflow as tf 3 import image_info as img_io 4 5 6 ‘‘‘訓練參數‘‘‘ 7 8 INPUT_DATA = ‘./flower_photos‘ # 數據文件夾 9 VALIDATION_PERCENTAGE = 10 # 驗證用數據百分比 10 TEST_PERCENTAGE = 10 # 測試用數據百分比 11 BATCH_SIZE = 128 # 數據包大小 12 INPUT_SIZE = [224, 224] # 標準輸入尺寸 13 MAX_STEP = 5000 # 最大叠代輪數 14 15 def loss(logits, labels): 16 """ 17 Add L2Loss to all the trainable variables. 18 Args: 19 logits: Logits from inference(). 20 labels: Labels from distorted_inputs or inputs(). 1-D tensor 21 of shape [batch_size] 22 Returns: 23 Loss tensor of type float. 24 """ 25 cross_entropy_mean = tf.reduce_mean( 26 tf.nn.sparse_softmax_cross_entropy_with_logits( 27 labels=tf.argmax(labels,1), logits=logits), name=‘cross_entropy‘) 28 tf.add_to_collection(‘losses‘, cross_entropy_mean) 29 return tf.add_n(tf.get_collection(‘losses‘), name=‘total_loss‘) 30 31 if __name__==‘__main__‘: 32 33 image_dict = img_io.creat_image_lists(VALIDATION_PERCENTAGE, TEST_PERCENTAGE, INPUT_DATA) 34 n_class = len(image_dict.keys()) 35 36 image_holder = tf.placeholder(tf.float32,[BATCH_SIZE, INPUT_SIZE[0], INPUT_SIZE[1], 3]) 37 label_holder = tf.placeholder(tf.float32,[BATCH_SIZE, n_class]) 38 39 # 正則化函數選擇並向前傳播 40 regularizer = tf.contrib.layers.l2_regularizer(0.0001) 41 logits, _ = Net.inference(image_holder, regularizer, n_class) 42 43 # loss計算並反向傳播 44 loss = loss(logits, label_holder) 45 train_step = tf.train.GradientDescentOptimizer(1e-3).minimize(loss) 46 47 # 正確率計算 48 with tf.name_scope(‘evaluation‘): 49 correct_prediction = tf.equal(tf.argmax(logits,1),tf.argmax(label_holder,1)) 50 evaluation_step = tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) 51 52 53 with tf.Session() as sess: 54 55 # 確保在變量生成在最後 56 init = tf.global_variables_initializer().run() 57 58 for step in range(MAX_STEP): 59 print(step) 60 # 訓練 61 image_batch, label_batch = img_io.get_random_cached_inputs( 62 sess, n_class, image_dict, BATCH_SIZE, ‘training‘, INPUT_DATA, INPUT_SIZE) 63 sess.run(train_step,feed_dict={ 64 image_holder:image_batch,label_holder:label_batch}) 65 66 # 驗證 67 if (step % 100 == 0) or (step + 1 == MAX_STEP): 68 image_batch_val, label_batch_val = img_io.get_random_cached_inputs( 69 sess, n_class, image_dict, BATCH_SIZE, ‘validation‘, INPUT_DATA, INPUT_SIZE) 70 validation_accuracy = sess.run(evaluation_step, feed_dict={ 71 image_holder:image_batch_val,label_holder:label_batch_val}) 72 print(‘Step %d: Validation accuracy on random sampled %d examples = %.1f%%‘ % 73 (step, BATCH_SIZE, validation_accuracy * 100)) 74 75 # 測試 76 image_batch_test, label_batch_test = 77 img_io.get_test_images(sess,image_dict,n_class,INPUT_SIZE) 78 test_accuracy = sess.run(evaluation_step, feed_dict={ 79 image_holder: image_batch_test, label_holder: label_batch_test}) 80 print(‘Final test accuracy = %.1f%%‘ % (test_accuracy * 100))
『TensorFlow』徒手裝高達_初號機_添加訓練模組並整合為可用分類網絡