1. 程式人生 > >『TensorFlow』徒手裝高達_初號機_添加訓練模組並整合為可用分類網絡

『TensorFlow』徒手裝高達_初號機_添加訓練模組並整合為可用分類網絡

正則 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] for
x 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,網絡主幹

優化方式:

  1. 全連接層Weights進行了dropout
  2. 全連接層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』徒手裝高達_初號機_添加訓練模組並整合為可用分類網絡