当前位置:   article > 正文

18.1:tensorflow分类模型mobilenetv2训练(数据增强,保存模型,衰减学习率,tensorboard),预测图像(单张,批量预测),导出为pb完整示例_使用的算法为mobilenetv2的模型怎么保存

使用的算法为mobilenetv2的模型怎么保存

    从前有个小孩子在学习tensorflow,于是他买了几本tensorflow书籍,他发现各种书籍里面讲的示例都是使用mnist数据集。由于框架已经封装好了,在使用数据时用一条命令就可以加载数据了,他也不知道这些数据是怎么被读取的。于是乎,他在训练自己的模型时碰到的数据都是一张张图像,仍然无从下手(一脸懵逼)。除此之外,他还想加一些其他功能,如怎么动态调节学习率,怎么使用tensorboard查看loss, accuracy, learningrate的变化,怎么显示训练过程中的图像,怎么可视化模型的结构,怎么保存模型。后来他把这些问题搞定了,但是他并不满足,他还想使用保存的模型(model.ckpt)对每张新的图像进行预测,后来发现自己需要预测的图像太多了,比较耗时,然后他想能不能使用批量数据一次输入多个同时预测。最后他还发现使用训练好的模型进行预测时还得重新定义网络结构(虽然也可使用.meta不用重新定义网络结构,但是这种方法每次必须输入一个批次数据),于是后来发现了可以使用保存的模型生成一个pb文件,调用pb文件时只需指定输入,输出节点而无需重新定义网络结构就可以预测图像。再后来他使用模型预测新图像时发现所有图像都预测为同一类,经过分析他发现在使用batch normal时出现了问题,因为bn层在训练时和测试时不一样。。。

一 、训练

1. 数据集,批量数据的读取,数据增强

    他使用的是自己的.jpg数据,不过和flower data的结构一样(http://download.tensorflow.org/example_images/flower_photos.tgz),一个大文件夹下分为各个小文件夹(flow photos的文件夹内有一个readme文件,得把它删掉),每个小文件夹名字为该图像的标签,小文件夹内是该类图像。在训练模型时他想到的第一件事是获取这些图像的路径及对应标签吧,因此他写了个函数,该函数可以返回所有图像的路径及标签(标签是各个小文件夹的名字):

  1. def get_files(file_dir):
  2. image_list, label_list = [], []
  3. for label in os.listdir(file_dir):
  4. for img in glob.glob(os.path.join(file_dir, label, "*.jpg")):
  5. image_list.append(img)
  6. label_list.append(int(label_dict[label]))
  7. print('There are %d data' %(len(image_list)))
  8. temp = np.array([image_list, label_list])
  9. temp = temp.transpose()
  10. np.random.shuffle(temp)
  11. image_list = list(temp[:, 0])
  12. label_list = list(temp[:, 1])
  13. label_list = [int(i) for i in label_list]
  14. return image_list, label_list

他发现数据集的标签都是一个字符串,在模型训练时label需要为0,1,2,3,4...的整数,因此他自己对标签及label做了一个映射。

他建立了一个label.txt,里面为每一行为一个标签对映射,分别为:daisy:0, dandelion:1, roses:2, sunflowers:3, tulips:4。为了把标签和label对应起来他写了这几行代码:

  1. label_dict, label_dict_res = {}, {}
  2. # 手动指定一个从类别到label的映射关系
  3. with open("label.txt", 'r') as f:
  4. for line in f.readlines():
  5. folder, label = line.strip().split(':')[0], line.strip().split(':')[1]
  6. label_dict[folder] = label
  7. label_dict_res[label] = folder
  8. print(label_dict)

他之前使用过caffe,他知道caffe可以直接读取图像也可以把图像转为lmbd再读。他发现tensorfow得先把数据转为tf-record文件再读取,他嫌先转文件格式这种方法有点麻烦(虽然在训练速度上和消耗资源上有优势),也想直接读取图像进行训练,于是后来他发现了tf.train.batch这个函数能解决这个问题。此外,他的数据不是很多,还想再对数据随机做一些变换来进行数据增强,后来他发了tf.image.random_flip_left_righ,tf.image.random_flip_up_down, tf.image.random_brightness, tf.image.random_contrast, tf.image.random_hue, tf.image.random_saturation这些函数。他还想用tensorboard查看训练过程中通过数据增强的图像是怎样的,于是他发现了tf.summary.image这个函数。最后他定义了获取批量数据的函数:

  1. def get_batch(image, label, image_W, image_H, batch_size, capacity):
  2. image = tf.cast(image, tf.string)
  3. label = tf.cast(label, tf.int32)
  4. # make an input queue
  5. input_queue = tf.train.slice_input_producer([image, label], shuffle=False)
  6. label = input_queue[1]
  7. image_contents = tf.read_file(input_queue[0])
  8. image = tf.image.decode_jpeg(image_contents, channels=3)
  9. # 数据增强
  10. #image = tf.image.resize_image_with_pad(image, target_height=image_W, target_width=image_H)
  11. image = tf.image.resize_images(image, (image_W, image_H))
  12. # 随机左右翻转
  13. image = tf.image.random_flip_left_right(image)
  14. # 随机上下翻转
  15. image = tf.image.random_flip_up_down(image)
  16. # 随机设置图片的亮度
  17. image = tf.image.random_brightness(image, max_delta=32/255.0)
  18. # 随机设置图片的对比度
  19. #image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
  20. # 随机设置图片的色度
  21. image = tf.image.random_hue(image, max_delta=0.05)
  22. # 随机设置图片的饱和度
  23. #image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
  24. # 标准化,使图片的均值为0,方差为1
  25. image = tf.image.per_image_standardization(image)
  26. image_batch, label_batch = tf.train.batch([image, label],
  27. batch_size= batch_size,
  28. num_threads= 64,
  29. capacity = capacity)
  30. tf.summary.image("input_img", image_batch, max_outputs=5)
  31. label_batch = tf.reshape(label_batch, [batch_size])
  32. image_batch = tf.cast(image_batch, tf.float32)
  33. return image_batch, label_batch

2. mobilenetv2网络

    他在网上找到了一个mobilenetv2的网络,并建立了一个新的model.py文件,把该网络粘贴进去了(名字为class MobileNetV2)。这里他只是用了mobilenetv2,他也可以在网上找一个其他网络(resnet, vgg, inception, shufflenet...)前向传播的代码粘贴到这里,就可以训练其他的网络了。

  1. #coding:utf-8
  2. import tensorflow as tf
  3. import tensorflow.contrib.slim as slim
  4. from tensorflow.contrib.layers.python.layers import batch_norm
  5. import tensorflow as tf
  6. import tensorflow as tf
  7. import tensorflow.contrib as tc
  8. import numpy as np
  9. import time
  10. class MobileNetV1(object):
  11. def __init__(self, is_training=True, input_size=224):
  12. self.input_size = input_size
  13. self.is_training = is_training
  14. self.normalizer = tc.layers.batch_norm
  15. self.bn_params = {'is_training': self.is_training}
  16. with tf.variable_scope('MobileNetV1'):
  17. self._create_placeholders()
  18. self._build_model()
  19. def _create_placeholders(self):
  20. self.input = tf.placeholder(dtype=tf.float32, shape=[None, self.input_size, self.input_size, 3])
  21. def _build_model(self):
  22. i = 0
  23. with tf.variable_scope('init_conv'):
  24. self.conv1 = tc.layers.conv2d(self.input, num_outputs=32, kernel_size=3, stride=2,
  25. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  26. # 1
  27. with tf.variable_scope('dconv_block{}'.format(i)):
  28. i += 1
  29. self.dconv1 = tc.layers.separable_conv2d(self.conv1, num_outputs=None, kernel_size=3, depth_multiplier=1,
  30. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  31. self.pconv1 = tc.layers.conv2d(self.dconv1, 64, 1, normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  32. # 2
  33. with tf.variable_scope('dconv_block{}'.format(i)):
  34. i += 1
  35. self.dconv2 = tc.layers.separable_conv2d(self.pconv1, None, 3, 1, 2,
  36. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  37. self.pconv2 = tc.layers.conv2d(self.dconv2, 128, 1, normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  38. # 3
  39. with tf.variable_scope('dconv_block{}'.format(i)):
  40. i += 1
  41. self.dconv3 = tc.layers.separable_conv2d(self.pconv2, None, 3, 1, 1,
  42. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  43. self.pconv3 = tc.layers.conv2d(self.dconv3, 128, 1, normalizer_fn=self.normalizer,
  44. normalizer_params=self.bn_params)
  45. # 4
  46. with tf.variable_scope('dconv_block{}'.format(i)):
  47. i += 1
  48. self.dconv4 = tc.layers.separable_conv2d(self.pconv3, None, 3, 1, 2,
  49. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  50. self.pconv4 = tc.layers.conv2d(self.dconv4, 256, 1, normalizer_fn=self.normalizer,
  51. normalizer_params=self.bn_params)
  52. # 5
  53. with tf.variable_scope('dconv_block{}'.format(i)):
  54. i += 1
  55. self.dconv5 = tc.layers.separable_conv2d(self.pconv4, None, 3, 1, 1,
  56. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  57. self.pconv5 = tc.layers.conv2d(self.dconv5, 256, 1, normalizer_fn=self.normalizer,
  58. normalizer_params=self.bn_params)
  59. # 6
  60. with tf.variable_scope('dconv_block{}'.format(i)):
  61. i += 1
  62. self.dconv6 = tc.layers.separable_conv2d(self.pconv5, None, 3, 1, 2,
  63. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  64. self.pconv6 = tc.layers.conv2d(self.dconv6, 512, 1, normalizer_fn=self.normalizer,
  65. normalizer_params=self.bn_params)
  66. # 7_1
  67. with tf.variable_scope('dconv_block{}'.format(i)):
  68. i += 1
  69. self.dconv71 = tc.layers.separable_conv2d(self.pconv6, None, 3, 1, 1,
  70. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  71. self.pconv71 = tc.layers.conv2d(self.dconv71, 512, 1, normalizer_fn=self.normalizer,
  72. normalizer_params=self.bn_params)
  73. # 7_2
  74. with tf.variable_scope('dconv_block{}'.format(i)):
  75. i += 1
  76. self.dconv72 = tc.layers.separable_conv2d(self.pconv71, None, 3, 1, 1,
  77. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  78. self.pconv72 = tc.layers.conv2d(self.dconv72, 512, 1, normalizer_fn=self.normalizer,
  79. normalizer_params=self.bn_params)
  80. # 7_3
  81. with tf.variable_scope('dconv_block{}'.format(i)):
  82. i += 1
  83. self.dconv73 = tc.layers.separable_conv2d(self.pconv72, None, 3, 1, 1,
  84. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  85. self.pconv73 = tc.layers.conv2d(self.dconv73, 512, 1, normalizer_fn=self.normalizer,
  86. normalizer_params=self.bn_params)
  87. # 7_4
  88. with tf.variable_scope('dconv_block{}'.format(i)):
  89. i += 1
  90. self.dconv74 = tc.layers.separable_conv2d(self.pconv73, None, 3, 1, 1,
  91. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  92. self.pconv74 = tc.layers.conv2d(self.dconv74, 512, 1, normalizer_fn=self.normalizer,
  93. normalizer_params=self.bn_params)
  94. # 7_5
  95. with tf.variable_scope('dconv_block{}'.format(i)):
  96. i += 1
  97. self.dconv75 = tc.layers.separable_conv2d(self.pconv74, None, 3, 1, 1,
  98. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  99. self.pconv75 = tc.layers.conv2d(self.dconv75, 512, 1, normalizer_fn=self.normalizer,
  100. normalizer_params=self.bn_params)
  101. # 8
  102. with tf.variable_scope('dconv_block{}'.format(i)):
  103. i += 1
  104. self.dconv8 = tc.layers.separable_conv2d(self.pconv75, None, 3, 1, 2,
  105. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  106. self.pconv8 = tc.layers.conv2d(self.dconv8, 1024, 1, normalizer_fn=self.normalizer,
  107. normalizer_params=self.bn_params)
  108. # 9
  109. with tf.variable_scope('dconv_block{}'.format(i)):
  110. i += 1
  111. self.dconv9 = tc.layers.separable_conv2d(self.pconv8, None, 3, 1, 1,
  112. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  113. self.pconv9 = tc.layers.conv2d(self.dconv9, 1024, 1, normalizer_fn=self.normalizer,
  114. normalizer_params=self.bn_params)
  115. with tf.variable_scope('global_max_pooling'):
  116. self.pool = tc.layers.max_pool2d(self.pconv9, kernel_size=7, stride=1)
  117. with tf.variable_scope('prediction'):
  118. self.output = tc.layers.conv2d(self.pool, 1000, 1, activation_fn=None)
  119. class MobileNetV2(object):
  120. def __init__(self, input, num_classes=1000, is_training=True):
  121. self.input = input
  122. self.num_classes = num_classes
  123. self.is_training = is_training
  124. self.normalizer = tc.layers.batch_norm
  125. self.bn_params = {'is_training': self.is_training}
  126. with tf.variable_scope('MobileNetV2'):
  127. self._build_model()
  128. def _build_model(self):
  129. self.i = 0
  130. with tf.variable_scope('init_conv'):
  131. output = tc.layers.conv2d(self.input, 32, 3, 2,
  132. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  133. # print(output.get_shape())
  134. self.output = self._inverted_bottleneck(output, 1, 16, 0)
  135. self.output = self._inverted_bottleneck(self.output, 6, 24, 1)
  136. self.output = self._inverted_bottleneck(self.output, 6, 24, 0)
  137. self.output = self._inverted_bottleneck(self.output, 6, 32, 1)
  138. self.output = self._inverted_bottleneck(self.output, 6, 32, 0)
  139. self.output = self._inverted_bottleneck(self.output, 6, 32, 0)
  140. self.output = self._inverted_bottleneck(self.output, 6, 64, 1)
  141. self.output = self._inverted_bottleneck(self.output, 6, 64, 0)
  142. self.output = self._inverted_bottleneck(self.output, 6, 64, 0)
  143. self.output = self._inverted_bottleneck(self.output, 6, 64, 0)
  144. self.output = self._inverted_bottleneck(self.output, 6, 96, 0)
  145. self.output = self._inverted_bottleneck(self.output, 6, 96, 0)
  146. self.output = self._inverted_bottleneck(self.output, 6, 96, 0)
  147. self.output = self._inverted_bottleneck(self.output, 6, 160, 1)
  148. self.output = self._inverted_bottleneck(self.output, 6, 160, 0)
  149. self.output = self._inverted_bottleneck(self.output, 6, 160, 0)
  150. self.output = self._inverted_bottleneck(self.output, 6, 320, 0)
  151. self.output = tc.layers.conv2d(self.output, 1280, 1, normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  152. self.output = tc.layers.avg_pool2d(self.output, 7)
  153. self.output = tc.layers.conv2d(self.output, self.num_classes, 1, activation_fn=None)
  154. self.output = tf.reshape(self.output, shape=[-1, self.num_classes], name="logit")
  155. def _inverted_bottleneck(self, input, up_sample_rate, channels, subsample):
  156. with tf.variable_scope('inverted_bottleneck{}_{}_{}'.format(self.i, up_sample_rate, subsample)):
  157. self.i += 1
  158. stride = 2 if subsample else 1
  159. output = tc.layers.conv2d(input, up_sample_rate*input.get_shape().as_list()[-1], 1,
  160. activation_fn=tf.nn.relu6,
  161. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  162. output = tc.layers.separable_conv2d(output, None, 3, 1, stride=stride,
  163. activation_fn=tf.nn.relu6,
  164. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  165. output = tc.layers.conv2d(output, channels, 1, activation_fn=None,
  166. normalizer_fn=self.normalizer, normalizer_params=self.bn_params)
  167. if input.get_shape().as_list()[-1] == channels:
  168. output = tf.add(input, output)
  169. return output
  170. # small inception
  171. def model4(x, N_CLASSES, is_trian = False):
  172. x = tf.contrib.layers.conv2d(x, 64, [5, 5], 1, 'SAME', activation_fn=tf.nn.relu)
  173. x = batch_norm(x, decay=0.9, updates_collections=None, is_training=is_trian) # 训练阶段is_trainging设置为true,训练完毕后使用模型时设置为false
  174. x = tf.contrib.layers.max_pool2d(x, [2, 2], stride=2, padding='SAME')
  175. x1_1 = tf.contrib.layers.conv2d(x, 64, [1, 1], 1, 'SAME', activation_fn=tf.nn.relu) # 1X1 核
  176. x1_1 = batch_norm(x1_1, decay=0.9, updates_collections=None, is_training=is_trian)
  177. x3_3 = tf.contrib.layers.conv2d(x, 64, [3, 3], 1, 'SAME', activation_fn=tf.nn.relu) # 3x3 核
  178. x3_3 = batch_norm(x3_3, decay=0.9, updates_collections=None, is_training=is_trian)
  179. x5_5 = tf.contrib.layers.conv2d(x, 64, [5, 5], 1, 'SAME', activation_fn=tf.nn.relu) # 5x5 核
  180. x5_5 = batch_norm(x5_5, decay=0.9, updates_collections=None, is_training=is_trian)
  181. x = tf.concat([x1_1, x3_3, x5_5], axis=-1) # 连接在一起,得到64*3=192个通道
  182. x = tf.contrib.layers.max_pool2d(x, [2, 2], stride=2, padding='SAME')
  183. x1_1 = tf.contrib.layers.conv2d(x, 128, [1, 1], 1, 'SAME', activation_fn=tf.nn.relu)
  184. x1_1 = batch_norm(x1_1, decay=0.9, updates_collections=None, is_training=is_trian)
  185. x3_3 = tf.contrib.layers.conv2d(x, 128, [3, 3], 1, 'SAME', activation_fn=tf.nn.relu)
  186. x3_3 = batch_norm(x3_3, decay=0.9, updates_collections=None, is_training=is_trian)
  187. x5_5 = tf.contrib.layers.conv2d(x, 128, [5, 5], 1, 'SAME', activation_fn=tf.nn.relu)
  188. x5_5 = batch_norm(x5_5, decay=0.9, updates_collections=None, is_training=is_trian)
  189. x = tf.concat([x1_1, x3_3, x5_5], axis=-1)
  190. x = tf.contrib.layers.max_pool2d(x, [2, 2], stride=2, padding='SAME')
  191. shp = x.get_shape()
  192. x = tf.reshape(x, [-1, shp[1]*shp[2]*shp[3]]) # flatten
  193. logits = tf.contrib.layers.fully_connected(x, N_CLASSES, activation_fn=None) # output logist without softmax
  194. return logits
  195. # 2conv + 3fc
  196. def model2(images, batch_size, n_classes):
  197. '''Build the model
  198. Args:
  199. images: image batch, 4D tensor, tf.float32, [batch_size, width, height, channels]
  200. Returns:
  201. output tensor with the computed logits, float, [batch_size, n_classes]
  202. '''
  203. #conv1, shape = [kernel size, kernel size, channels, kernel numbers]
  204. with tf.variable_scope('conv1') as scope:
  205. weights = tf.get_variable('weights',
  206. shape = [3,3,3, 16],
  207. dtype = tf.float32,
  208. initializer=tf.truncated_normal_initializer(stddev=0.1,dtype=tf.float32))
  209. biases = tf.get_variable('biases',
  210. shape=[16],
  211. dtype=tf.float32,
  212. initializer=tf.constant_initializer(0.1))
  213. conv = tf.nn.conv2d(images, weights, strides=[1,1,1,1], padding='SAME')
  214. pre_activation = tf.nn.bias_add(conv, biases)
  215. conv1 = tf.nn.relu(pre_activation, name= scope.name)
  216. #pool1 and norm1
  217. with tf.variable_scope('pooling1_lrn') as scope:
  218. pool1 = tf.nn.max_pool(conv1, ksize=[1,3,3,1],strides=[1,2,2,1],
  219. padding='SAME', name='pooling1')
  220. norm1 = tf.nn.lrn(pool1, depth_radius=4, bias=1.0, alpha=0.001/9.0,
  221. beta=0.75,name='norm1')
  222. #conv2
  223. with tf.variable_scope('conv2') as scope:
  224. weights = tf.get_variable('weights',
  225. shape=[3,3,16,16],
  226. dtype=tf.float32,
  227. initializer=tf.truncated_normal_initializer(stddev=0.1,dtype=tf.float32))
  228. biases = tf.get_variable('biases',
  229. shape=[16],
  230. dtype=tf.float32,
  231. initializer=tf.constant_initializer(0.1))
  232. conv = tf.nn.conv2d(norm1, weights, strides=[1,1,1,1],padding='SAME')
  233. pre_activation = tf.nn.bias_add(conv, biases)
  234. conv2 = tf.nn.relu(pre_activation, name='conv2')
  235. #pool2 and norm2
  236. with tf.variable_scope('pooling2_lrn') as scope:
  237. norm2 = tf.nn.lrn(conv2, depth_radius=4, bias=1.0, alpha=0.001/9.0,
  238. beta=0.75,name='norm2')
  239. pool2 = tf.nn.max_pool(norm2, ksize=[1,3,3,1], strides=[1,1,1,1],
  240. padding='SAME',name='pooling2')
  241. #local3
  242. with tf.variable_scope('local3') as scope:
  243. reshape = tf.reshape(pool2, shape=[batch_size, -1])
  244. dim = reshape.get_shape()[1].value
  245. weights = tf.get_variable('weights',
  246. shape=[dim,128],
  247. dtype=tf.float32,
  248. initializer=tf.truncated_normal_initializer(stddev=0.005,dtype=tf.float32))
  249. biases = tf.get_variable('biases',
  250. shape=[128],
  251. dtype=tf.float32,
  252. initializer=tf.constant_initializer(0.1))
  253. local3 = tf.nn.relu(tf.matmul(reshape, weights) + biases, name=scope.name)
  254. #local4
  255. with tf.variable_scope('local4') as scope:
  256. weights = tf.get_variable('weights',
  257. shape=[128,128],
  258. dtype=tf.float32,
  259. initializer=tf.truncated_normal_initializer(stddev=0.005,dtype=tf.float32))
  260. biases = tf.get_variable('biases',
  261. shape=[128],
  262. dtype=tf.float32,
  263. initializer=tf.constant_initializer(0.1))
  264. local4 = tf.nn.relu(tf.matmul(local3, weights) + biases, name='local4')
  265. # full connect
  266. with tf.variable_scope('softmax_linear') as scope:
  267. weights = tf.get_variable('softmax_linear',
  268. shape=[128, n_classes],
  269. dtype=tf.float32,
  270. initializer=tf.truncated_normal_initializer(stddev=0.005,dtype=tf.float32))
  271. biases = tf.get_variable('biases',
  272. shape=[n_classes],
  273. dtype=tf.float32,
  274. initializer=tf.constant_initializer(0.1))
  275. logits = tf.add(tf.matmul(local4, weights), biases, name='softmax_linear')
  276. return logits
  277. if __name__ == '__main__':
  278. x = tf.placeholder(tf.float32, shape=[None, 224, 224, 3])
  279. model = MobileNetV2(x, num_classes=5, is_training=True)
  280. print "output size:"
  281. print model.output.get_shape()
  282. board_writer = tf.summary.FileWriter(logdir='./', graph=tf.get_default_graph())
  283. fake_data = np.ones(shape=(1, 224, 224, 3))
  284. sess_config = tf.ConfigProto(device_count={'GPU':0})
  285. with tf.Session(config=sess_config) as sess:
  286. sess.run(tf.global_variables_initializer())
  287. cnt = 0
  288. for i in range(101):
  289. t1 = time.time()
  290. output = sess.run(model.output, feed_dict={x: fake_data})
  291. if i != 0:
  292. cnt += time.time() - t1
  293. print(cnt / 100)

3. 训练

    他的训练文件train.py如下。tf.summary.*相关的为保存各个变量值的变化情况,便于在tensorboard中查看。  lr = tf.train.exponential_decay(learning_rate=init_lr, global_step=global_step, decay_steps=decay_steps, decay_rate=0.1) 为学习率随着迭代此时指数下降。

    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)

    以及后面的:

    var_list = tf.trainable_variables() 
    g_list = tf.global_variables()
    bn_moving_vars = [g for g in g_list if 'moving_mean' in g.name]
    bn_moving_vars += [g for g in g_list if 'moving_variance' in g.name]
    var_list += bn_moving_vars
    saver = tf.train.Saver(var_list=var_list, max_to_keep=10)

表示更新mobilenetv2中batchnormal的移动平均和标准差,如果没有则训练时很好而预测时完全错误!!!

saver.save(sess, checkpoint_path, global_step=step)表示保存模型

  1. #coding:utf-8
  2. import os
  3. import numpy as np
  4. import tensorflow as tf
  5. import glob
  6. import model
  7. def get_files(file_dir):
  8. image_list, label_list = [], []
  9. for label in os.listdir(file_dir):
  10. for img in glob.glob(os.path.join(file_dir, label, "*.jpg")):
  11. image_list.append(img)
  12. label_list.append(int(label_dict[label]))
  13. print('There are %d data' %(len(image_list)))
  14. temp = np.array([image_list, label_list])
  15. temp = temp.transpose()
  16. np.random.shuffle(temp)
  17. image_list = list(temp[:, 0])
  18. label_list = list(temp[:, 1])
  19. label_list = [int(i) for i in label_list]
  20. return image_list, label_list
  21. label_dict, label_dict_res = {}, {}
  22. # 手动指定一个从类别到label的映射关系
  23. with open("label.txt", 'r') as f:
  24. for line in f.readlines():
  25. folder, label = line.strip().split(':')[0], line.strip().split(':')[1]
  26. label_dict[folder] = label
  27. label_dict_res[label] = folder
  28. print(label_dict)
  29. train_dir = "/media/DATA2/sku_train"
  30. logs_train_dir = './model_save'
  31. init_lr = 0.1
  32. BATCH_SIZE = 64
  33. train, train_label = get_files(train_dir)
  34. one_epoch_step = len(train) / BATCH_SIZE
  35. decay_steps = 20*one_epoch_step
  36. MAX_STEP = 100*one_epoch_step
  37. N_CLASSES = len(label_dict)
  38. IMG_W = 224
  39. IMG_H = 224
  40. CAPACITY = 1000
  41. os.environ["CUDA_VISIBLE_DEVICES"] = "0" # gpu编号
  42. config = tf.ConfigProto()
  43. config.gpu_options.allow_growth = True # 设置最小gpu使用量
  44. def get_batch(image, label, image_W, image_H, batch_size, capacity):
  45. image = tf.cast(image, tf.string)
  46. label = tf.cast(label, tf.int32)
  47. # make an input queue
  48. input_queue = tf.train.slice_input_producer([image, label], shuffle=False)
  49. label = input_queue[1]
  50. image_contents = tf.read_file(input_queue[0])
  51. image = tf.image.decode_jpeg(image_contents, channels=3)
  52. # 数据增强
  53. #image = tf.image.resize_image_with_pad(image, target_height=image_W, target_width=image_H)
  54. image = tf.image.resize_images(image, (image_W, image_H))
  55. # 随机左右翻转
  56. image = tf.image.random_flip_left_right(image)
  57. # 随机上下翻转
  58. image = tf.image.random_flip_up_down(image)
  59. # 随机设置图片的亮度
  60. image = tf.image.random_brightness(image, max_delta=32/255.0)
  61. # 随机设置图片的对比度
  62. #image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
  63. # 随机设置图片的色度
  64. image = tf.image.random_hue(image, max_delta=0.05)
  65. # 随机设置图片的饱和度
  66. #image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
  67. # 标准化,使图片的均值为0,方差为1
  68. image = tf.image.per_image_standardization(image)
  69. image_batch, label_batch = tf.train.batch([image, label],
  70. batch_size= batch_size,
  71. num_threads= 64,
  72. capacity = capacity)
  73. tf.summary.image("input_img", image_batch, max_outputs=5)
  74. label_batch = tf.reshape(label_batch, [batch_size])
  75. image_batch = tf.cast(image_batch, tf.float32)
  76. return image_batch, label_batch
  77. def main():
  78. global_step = tf.Variable(0, name='global_step', trainable=False)
  79. # label without one-hot
  80. batch_train, batch_labels = get_batch(train,
  81. train_label,
  82. IMG_W,
  83. IMG_H,
  84. BATCH_SIZE,
  85. CAPACITY)
  86. # network
  87. logits = model.MobileNetV2(batch_train, num_classes=N_CLASSES, is_training=True).output
  88. #logits = model.model2(batch_train, BATCH_SIZE, N_CLASSES)
  89. #logits = model.model4(batch_train, N_CLASSES, is_trian=True)
  90. print logits.get_shape()
  91. # loss
  92. cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=batch_labels)
  93. loss = tf.reduce_mean(cross_entropy, name='loss')
  94. tf.summary.scalar('train_loss', loss)
  95. # optimizer
  96. lr = tf.train.exponential_decay(learning_rate=init_lr, global_step=global_step, decay_steps=decay_steps, decay_rate=0.1)
  97. tf.summary.scalar('learning_rate', lr)
  98. update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
  99. with tf.control_dependencies(update_ops):
  100. optimizer = tf.train.AdamOptimizer(learning_rate=lr).minimize(loss, global_step=global_step)
  101. # accuracy
  102. correct = tf.nn.in_top_k(logits, batch_labels, 1)
  103. correct = tf.cast(correct, tf.float16)
  104. accuracy = tf.reduce_mean(correct)
  105. tf.summary.scalar('train_acc', accuracy)
  106. summary_op = tf.summary.merge_all()
  107. sess = tf.Session(config=config)
  108. train_writer = tf.summary.FileWriter(logs_train_dir, sess.graph)
  109. #saver = tf.train.Saver()
  110. var_list = tf.trainable_variables()
  111. g_list = tf.global_variables()
  112. bn_moving_vars = [g for g in g_list if 'moving_mean' in g.name]
  113. bn_moving_vars += [g for g in g_list if 'moving_variance' in g.name]
  114. var_list += bn_moving_vars
  115. saver = tf.train.Saver(var_list=var_list, max_to_keep=10)
  116. sess.run(tf.global_variables_initializer())
  117. coord = tf.train.Coordinator()
  118. threads = tf.train.start_queue_runners(sess=sess, coord=coord)
  119. #saver.restore(sess, logs_train_dir+'/model.ckpt-174000')
  120. try:
  121. for step in range(MAX_STEP):
  122. if coord.should_stop():
  123. break
  124. _, learning_rate, tra_loss, tra_acc = sess.run([optimizer, lr, loss, accuracy])
  125. if step % 100 == 0:
  126. print('Epoch %3d/%d, Step %6d/%d, lr %f, train loss = %.2f, train accuracy = %.2f%%' %(step/one_epoch_step, MAX_STEP/one_epoch_step, step, MAX_STEP, learning_rate, tra_loss, tra_acc*100.0))
  127. summary_str = sess.run(summary_op)
  128. train_writer.add_summary(summary_str, step)
  129. if step % 2000 == 0 or (step + 1) == MAX_STEP:
  130. checkpoint_path = os.path.join(logs_train_dir, 'model.ckpt')
  131. saver.save(sess, checkpoint_path, global_step=step)
  132. except tf.errors.OutOfRangeError:
  133. print('Done training -- epoch limit reached')
  134. finally:
  135. coord.request_stop()
  136. coord.join(threads)
  137. sess.close()
  138. if __name__ == '__main__':
  139. main()

开始训练后,他在model_save文件夹下输入了:tensorboard --logdir=model_save

然后打开:http://localhost:6006/

他发现能看到,learning rate, accuracy, loss的变化情况了,也能看到训练过程中的图像及网络结构了。

 

下一篇:用训练的模型预测图像https://blog.csdn.net/u010397980/article/details/84932383

或者:用官方的slim定义网络结构进行训练https://blog.csdn.net/u010397980/article/details/89439714

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/672840
推荐阅读
相关标签
  

闽ICP备14008679号