当前位置:   article > 正文

详解tensorflow训练自己的数据集实现CNN图像分类_tensorflow1.x训练自己的数据集resnet图像分类

tensorflow1.x训练自己的数据集resnet图像分类

     出处: https://www.jb51.net/article/134623.htm

利用卷积神经网络训练图像数据分为以下几个步骤

1.读取图片文件
2.产生用于训练的批次
3.定义训练的模型(包括初始化参数,卷积、池化层等参数、网络)

4.训练

1 读取图片文件


  1. def get_files(filename):
  2. class_train = []
  3. label_train = []
  4. for train_class in os.listdir(filename):
  5. for pic in os.listdir(filename+train_class):
  6. class_train.append(filename+train_class+'/'+pic)
  7. label_train.append(train_class)
  8. temp = np.array([class_train,label_train])
  9. temp = temp.transpose()
  10. #shuffle the samples
  11. np.random.shuffle(temp)
  12. #after transpose, images is in dimension 0 and label in dimension 1
  13. image_list = list(temp[:,0])
  14. label_list = list(temp[:,1])
  15. label_list = [int(i) for i in label_list]
  16. #print(label_list)
  17. return image_list,label_list

这里文件名作为标签,即类别(其数据类型要确定,后面要转为tensor类型数据)。

然后将image和label转为list格式数据,因为后边用到的的一些tensorflow函数接收的是list格式数据。

2 产生用于训练的批次

  1. def get_batches(image,label,resize_w,resize_h,batch_size,capacity):
  2. #convert the list of images and labels to tensor
  3. image = tf.cast(image,tf.string)
  4. label = tf.cast(label,tf.int64)
  5. queue = tf.train.slice_input_producer([image,label])
  6. label = queue[1]
  7. image_c = tf.read_file(queue[0])
  8. image = tf.image.decode_jpeg(image_c,channels = 3)
  9. #resize
  10. image = tf.image.resize_image_with_crop_or_pad(image,resize_w,resize_h)
  11. #(x - mean) / adjusted_stddev
  12. image = tf.image.per_image_standardization(image)
  13. image_batch,label_batch = tf.train.batch([image,label],
  14. batch_size = batch_size,
  15. num_threads = 64,
  16. capacity = capacity)
  17. images_batch = tf.cast(image_batch,tf.float32)
  18. labels_batch = tf.reshape(label_batch,[batch_size])
  19. return images_batch,labels_batch

首先使用tf.cast转化为tensorflow数据格式,使用tf.train.slice_input_producer实现一个输入的队列。

label不需要处理,image存储的是路径,需要读取为图片,接下来的几步就是读取路径转为图片,用于训练。

CNN对图像大小是敏感的,第10行图片resize处理为大小一致,12行将其标准化,即减去所有图片的均值,方便训练。

接下来使用tf.train.batch函数产生训练的批次。

最后将产生的批次做数据类型的转换和shape的处理即可产生用于训练的批次。

3 定义训练的模型

(1)训练参数的定义及初始化

  1. def init_weights(shape):
  2. return tf.Variable(tf.random_normal(shape,stddev = 0.01))
  3. #init weights
  4. weights = {
  5. "w1":init_weights([3,3,3,16]),
  6. "w2":init_weights([3,3,16,128]),
  7. "w3":init_weights([3,3,128,256]),
  8. "w4":init_weights([4096,4096]),
  9. "wo":init_weights([4096,2])
  10. }
  11. #init biases
  12. biases = {
  13. "b1":init_weights([16]),
  14. "b2":init_weights([128]),
  15. "b3":init_weights([256]),
  16. "b4":init_weights([4096]),
  17. "bo":init_weights([2])
  18. }

CNN的每层是y=wx+b的决策模型,卷积层产生特征向量,根据这些特征向量带入x进行计算,因此,需要定义卷积层的初始化参数,包括权重和偏置。其中第8行的参数形状后边再解释。

(2)定义不同层的操作

  1. def conv2d(x,w,b):
  2. x = tf.nn.conv2d(x,w,strides = [1,1,1,1],padding = "SAME")
  3. x = tf.nn.bias_add(x,b)
  4. return tf.nn.relu(x)
  5. def pooling(x):
  6. return tf.nn.max_pool(x,ksize = [1,2,2,1],strides = [1,2,2,1],padding = "SAME")
  7. def norm(x,lsize = 4):
  8. return tf.nn.lrn(x,depth_radius = lsize,bias = 1,alpha = 0.001/9.0,beta = 0.75)

这里只定义了三种层,即卷积层、池化层和正则化层

(3)定义训练模型

  1. def mmodel(images):
  2. l1 = conv2d(images,weights["w1"],biases["b1"])
  3. l2 = pooling(l1)
  4. l2 = norm(l2)
  5. l3 = conv2d(l2,weights["w2"],biases["b2"])
  6. l4 = pooling(l3)
  7. l4 = norm(l4)
  8. l5 = conv2d(l4,weights["w3"],biases["b3"])
  9. #same as the batch size
  10. l6 = pooling(l5)
  11. l6 = tf.reshape(l6,[-1,weights["w4"].get_shape().as_list()[0]])
  12. l7 = tf.nn.relu(tf.matmul(l6,weights["w4"])+biases["b4"])
  13. soft_max = tf.add(tf.matmul(l7,weights["wo"]),biases["bo"])
  14. return soft_max

模型比较简单,使用三层卷积,第11行使用全连接,需要对特征向量进行reshape,其中l6的形状为[-1,w4的第1维的参数],因此,将其按照“w4”reshape的时候,要使得-1位置的大小为batch_size,这样,最终再乘以“wo”时,最终的输出大小为[batch_size,class_num]

(4)定义评估量

  1. def loss(logits,label_batches):
  2. cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits,labels=label_batches)
  3. cost = tf.reduce_mean(cross_entropy)
  4. return cost
  5.  首先定义损失函数,这是用于训练最小化损失的必需量
  6. def get_accuracy(logits,labels):
  7. acc = tf.nn.in_top_k(logits,labels,1)
  8. acc = tf.cast(acc,tf.float32)
  9. acc = tf.reduce_mean(acc)
  10. return acc

评价分类准确率的量,训练时,需要loss值减小,准确率增加,这样的训练才是收敛的。

(5)定义训练方式

  1. def training(loss,lr):
  2. train_op = tf.train.RMSPropOptimizer(lr,0.9).minimize(loss)
  3. return train_op

有很多种训练方式,可以自行去官网查看,但是不同的训练方式可能对应前面的参数定义不一样,需要另行处理,否则可能报错。

 4 训练

  1. def run_training():
  2. data_dir = 'C:/Users/wk/Desktop/bky/dataSet/'
  3. image,label = inputData.get_files(data_dir)
  4. image_batches,label_batches = inputData.get_batches(image,label,32,32,16,20)
  5. p = model.mmodel(image_batches)
  6. cost = model.loss(p,label_batches)
  7. train_op = model.training(cost,0.001)
  8. acc = model.get_accuracy(p,label_batches)
  9. sess = tf.Session()
  10. init = tf.global_variables_initializer()
  11. sess.run(init)
  12. coord = tf.train.Coordinator()
  13. threads = tf.train.start_queue_runners(sess = sess,coord = coord)
  14. try:
  15. for step in np.arange(1000):
  16. print(step)
  17. if coord.should_stop():
  18. break
  19. _,train_acc,train_loss = sess.run([train_op,acc,cost])
  20. print("loss:{} accuracy:{}".format(train_loss,train_acc))
  21. except tf.errors.OutOfRangeError:
  22. print("Done!!!")
  23. finally:
  24. coord.request_stop()
  25. coord.join(threads)
  26. sess.close()

神经网络训练的时候,我们需要将模型保存下来,方便后面继续训练或者用训练好的模型进行测试。因此,我们需要创建一个saver保存模型。

  1. def run_training():
  2. data_dir = 'C:/Users/wk/Desktop/bky/dataSet/'
  3. log_dir = 'C:/Users/wk/Desktop/bky/log/'
  4. image,label = inputData.get_files(data_dir)
  5. image_batches,label_batches = inputData.get_batches(image,label,32,32,16,20)
  6. print(image_batches.shape)
  7. p = model.mmodel(image_batches,16)
  8. cost = model.loss(p,label_batches)
  9. train_op = model.training(cost,0.001)
  10. acc = model.get_accuracy(p,label_batches)
  11. sess = tf.Session()
  12. init = tf.global_variables_initializer()
  13. sess.run(init)
  14. saver = tf.train.Saver()
  15. coord = tf.train.Coordinator()
  16. threads = tf.train.start_queue_runners(sess = sess,coord = coord)
  17. try:
  18. for step in np.arange(1000):
  19. print(step)
  20. if coord.should_stop():
  21. break
  22. _,train_acc,train_loss = sess.run([train_op,acc,cost])
  23. print("loss:{} accuracy:{}".format(train_loss,train_acc))
  24. if step % 100 == 0:
  25. check = os.path.join(log_dir,"model.ckpt")
  26. saver.save(sess,check,global_step = step)
  27. except tf.errors.OutOfRangeError:
  28. print("Done!!!")
  29. finally:
  30. coord.request_stop()
  31. coord.join(threads)
  32. sess.close()

训练好的模型信息会记录在checkpoint文件中,大致如下: 

model_checkpoint_path: "C:/Users/wk/Desktop/bky/log/model.ckpt-100"
all_model_checkpoint_paths: "C:/Users/wk/Desktop/bky/log/model.ckpt-0"
all_model_checkpoint_paths: "C:/Users/wk/Desktop/bky/log/model.ckpt-100"

其余还会生成一些文件,分别记录了模型参数等信息,后边测试的时候程序会读取checkpoint文件去加载这些真正的数据文件


构建好神经网络进行训练完成后,如果用之前的代码直接进行测试,会报shape不符合的错误,大致是卷积层的输入与图像的shape不一致,这是因为上篇的代码,将weights和biases定义在了模型的外面,调用模型的时候,出现valueError的错误。


因此,我们需要将参数定义在模型里面,加载训练好的模型参数时,训练好的参数才能够真正初始化模型。重写模型函数如下

  1. def mmodel(images,batch_size):
  2. with tf.variable_scope('conv1') as scope:
  3. weights = tf.get_variable('weights',
  4. shape = [3,3,3, 16],
  5. dtype = tf.float32,
  6. initializer=tf.truncated_normal_initializer(stddev=0.1,dtype=tf.float32))
  7. biases = tf.get_variable('biases',
  8. shape=[16],
  9. dtype=tf.float32,
  10. initializer=tf.constant_initializer(0.1))
  11. conv = tf.nn.conv2d(images, weights, strides=[1,1,1,1], padding='SAME')
  12. pre_activation = tf.nn.bias_add(conv, biases)
  13. conv1 = tf.nn.relu(pre_activation, name= scope.name)
  14. with tf.variable_scope('pooling1_lrn') as scope:
  15. pool1 = tf.nn.max_pool(conv1, ksize=[1,2,2,1],strides=[1,2,2,1],
  16. padding='SAME', name='pooling1')
  17. norm1 = tf.nn.lrn(pool1, depth_radius=4, bias=1.0, alpha=0.001/9.0,
  18. beta=0.75,name='norm1')
  19. with tf.variable_scope('conv2') as scope:
  20. weights = tf.get_variable('weights',
  21. shape=[3,3,16,128],
  22. dtype=tf.float32,
  23. initializer=tf.truncated_normal_initializer(stddev=0.1,dtype=tf.float32))
  24. biases = tf.get_variable('biases',
  25. shape=[128],
  26. dtype=tf.float32,
  27. initializer=tf.constant_initializer(0.1))
  28. conv = tf.nn.conv2d(norm1, weights, strides=[1,1,1,1],padding='SAME')
  29. pre_activation = tf.nn.bias_add(conv, biases)
  30. conv2 = tf.nn.relu(pre_activation, name='conv2')
  31. with tf.variable_scope('pooling2_lrn') as scope:
  32. norm2 = tf.nn.lrn(conv2, depth_radius=4, bias=1.0, alpha=0.001/9.0,
  33. beta=0.75,name='norm2')
  34. pool2 = tf.nn.max_pool(norm2, ksize=[1,2,2,1], strides=[1,1,1,1],
  35. padding='SAME',name='pooling2')
  36. with tf.variable_scope('local3') as scope:
  37. reshape = tf.reshape(pool2, shape=[batch_size, -1])
  38. dim = reshape.get_shape()[1].value
  39. weights = tf.get_variable('weights',
  40. shape=[dim,4096],
  41. dtype=tf.float32,
  42. initializer=tf.truncated_normal_initializer(stddev=0.005,dtype=tf.float32))
  43. biases = tf.get_variable('biases',
  44. shape=[4096],
  45. dtype=tf.float32,
  46. initializer=tf.constant_initializer(0.1))
  47. local3 = tf.nn.relu(tf.matmul(reshape, weights) + biases, name=scope.name)
  48. with tf.variable_scope('softmax_linear') as scope:
  49. weights = tf.get_variable('softmax_linear',
  50. shape=[4096, 2],
  51. dtype=tf.float32,
  52. initializer=tf.truncated_normal_initializer(stddev=0.005,dtype=tf.float32))
  53. biases = tf.get_variable('biases',
  54. shape=[2],
  55. dtype=tf.float32,
  56. initializer=tf.constant_initializer(0.1))
  57. softmax_linear = tf.add(tf.matmul(local3, weights), biases, name='softmax_linear')
  58. return softmax_linear

测试训练好的模型

首先获取一张测试图像

  1. def get_one_image(img_dir):
  2. image = Image.open(img_dir)
  3. plt.imshow(image)
  4. image = image.resize([32, 32])
  5. image_arr = np.array(image)
  6. return image_arr

加载模型,计算测试结果

  1. def test(test_file):
  2. log_dir = 'C:/Users/wk/Desktop/bky/log/'
  3. image_arr = get_one_image(test_file)
  4. with tf.Graph().as_default():
  5. image = tf.cast(image_arr, tf.float32)
  6. image = tf.image.per_image_standardization(image)
  7. image = tf.reshape(image, [1,32, 32, 3])
  8. print(image.shape)
  9. p = model.mmodel(image,1)
  10. logits = tf.nn.softmax(p)
  11. x = tf.placeholder(tf.float32,shape = [32,32,3])
  12. saver = tf.train.Saver()
  13. with tf.Session() as sess:
  14. ckpt = tf.train.get_checkpoint_state(log_dir)
  15. if ckpt and ckpt.model_checkpoint_path:
  16. global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
  17. saver.restore(sess, ckpt.model_checkpoint_path)
  18. print('Loading success)
  19. else:
  20. print('No checkpoint')
  21. prediction = sess.run(logits, feed_dict={x: image_arr})
  22. max_index = np.argmax(prediction)
  23. print(max_index)
前面主要是将测试图片标准化为网络的输入图像,15-19是加载模型文件,然后将图像输入到模型里即可


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

闽ICP备14008679号