【TensorFlow-AlexNet笔记1】基于TensorFlow实现AlexNet网络的构建、测试、微调过程

转载自:https://blog.csdn.net/jyy555555/article/details/80498275

本文主要参照博客中内容实现AlexNet网络的构建、测试过程,利用自己的方法制作训练集来进行微调过程。本文主要介绍在TensorFlow框架下AlexNet网络的实现程序。下图是AlexNet网络的网络结构:

1. AlexNet网络的构建过程:下面程序(注释)创建了一个类来定义AlexNet模型图,并带有加载预训练参数的函数

[python]  view plain  copy
  1. #定义AlexNet神经网络结构模型  
  2.   
  3. import tensorflow as tf  
  4. import numpy as np  
  5.   
  6. #建立模型图  
  7. class AlexNet(object):  
  8.       
  9.     #keep_prob:dropout概率,num_classes:数据类别数,skip_layer  
  10.     def __init__(self,x,keep_prob,num_classes,skip_layer,weights_path='DEFAULT'):  
  11.       
  12.         self.X=x  
  13.         self.NUM_CLASSES=num_classes  
  14.         self.KEEP_PROB=keep_prob  
  15.         self.SKIP_LAYER=skip_layer  
  16.         if weights_path=='DEFAULT':  
  17.             self.WEIGHTS_PATH='f:\\python程序\\AlexNet_Protect\\bvlc_alexnet.npy'  
  18.         else:  
  19.             self.WEIGHTS_PATH=weights_path  
  20.               
  21.         self.create()  
  22.           
  23.     def create(self):  
  24.         #第一层:卷积层-->最大池化层-->LRN  
  25.         conv1=conv_layer(self.X,11,11,96,4,4,padding='VALID',name='conv1')  
  26.         self.conv1=conv1  
  27.         pool1=max_pool(conv1,3,3,2,2,padding='VALID',name='pool1')  
  28.         norm1=lrn(pool1,2,2e-05,0.75,name='norml')  
  29.           
  30.         #第二层:卷积层-->最大池化层-->LRN  
  31.         conv2=conv_layer(norm1,5,5,256,1,1,groups=2,name='conv2')  
  32.         self.conv2=conv2  
  33.         pool2=max_pool(conv2,3,3,2,2,padding='VALID',name='pool2')  
  34.         norm2=lrn(pool2,2,2e-05,0.75,name='norm2')  
  35.           
  36.         #第三层:卷积层  
  37.         conv3=conv_layer(norm2,3,3,384,1,1,name='conv3')  
  38.         self.conv3=conv3  
  39.           
  40.         #第四层:卷积层  
  41.         conv4=conv_layer(conv3,3,3,384,1,1,groups=2,name='conv4')  
  42.         self.conv4=conv4  
  43.           
  44.         #第五层:卷积层-->最大池化层  
  45.         conv5=conv_layer(conv4,3,3,256,1,1,groups=2,name='conv5')  
  46.         self.conv5=conv5  
  47.         pool5=max_pool(conv5,3,3,2,2,padding='VALID',name='pool5')  
  48.           
  49.         #第六层:全连接层  
  50.         flattened=tf.reshape(pool5,[-1,6*6*256])  
  51.         fc6=fc_layer(flattened,6*6*256,4096,name='fc6')  
  52.         dropout6=dropout(fc6,self.KEEP_PROB)  
  53.           
  54.         #第七层:全连接层  
  55.         fc7=fc_layer(dropout6,4096,4096,name='fc7')  
  56.         dropout7=dropout(fc7,self.KEEP_PROB)  
  57.           
  58.         #第八层:全连接层,不带激活函数  
  59.         self.fc8=fc_layer(dropout7,4096,self.NUM_CLASSES,relu=False,name='fc8')  
  60.           
  61.     #加载神经网络预训练参数,将存储于self.WEIGHTS_PATH的预训练参数赋值给那些没有在self.SKIP_LAYER中指定的网络层的参数  
  62.     def load_initial_weights(self,session):  
  63.         #下载权重文件  
  64.         weights_dict=np.load(self.WEIGHTS_PATH,encoding='bytes').item()  
  65.           
  66.         for op_name in weights_dict:  
  67.             if op_name not in self.SKIP_LAYER:  
  68.                 with tf.variable_scope(op_name,reuse=True):  
  69.                     for data in weights_dict[op_name]:  
  70.                         #偏置项  
  71.                         if len(data.shape)==1:  
  72.                             var=tf.get_variable('biases',trainable=False)  
  73.                             session.run(var.assign(data))  
  74.                         #权重  
  75.                         else:  
  76.                             var=tf.get_variable('weights',trainable=False)  
  77.                             session.run(var.assign(data))  
  78.           
  79.   
  80.   
  81.   
  82. #定义卷积层,当groups=1时,AlexNet网络不拆分;当groups=2时,AlexNet网络拆分成上下两个部分。  
  83. def conv_layer(x,filter_height,filter_width,num_filters,stride_y,stride_x,name,padding='SAME',groups=1):  
  84.       
  85.     #获得输入图像的通道数  
  86.     input_channels=int(x.get_shape()[-1])  
  87.       
  88.     #创建lambda表达式  
  89.     convovle=lambda i,k:tf.nn.conv2d(i,k,strides=[1,stride_y,stride_x,1],padding=padding)  
  90.       
  91.     with tf.variable_scope(name) as scope:  
  92.         #创建卷积层所需的权重参数和偏置项参数  
  93.         weights=tf.get_variable("weights",shape=[filter_height,filter_width,input_channels/groups,num_filters])  
  94.         biases=tf.get_variable("biases",shape=[num_filters])  
  95.           
  96.     if groups==1:  
  97.         conv=convovle(x,weights)  
  98.       
  99.     #当groups不等于1时,拆分输入和权重     
  100.     else:  
  101.         input_groups=tf.split(axis=3,num_or_size_splits=groups,value=x)  
  102.         weight_groups=tf.split(axis=3,num_or_size_splits=groups,value=weights)  
  103.         output_groups=[convovle(i,k) for i,k in zip(input_groups,weight_groups)]  
  104.         #单独计算完后,再次根据深度连接两个网络  
  105.         conv=tf.concat(axis=3,values=output_groups)  
  106.           
  107.     #加上偏置项  
  108.     bias=tf.reshape(tf.nn.bias_add(conv,biases),conv.get_shape().as_list())  
  109.     #激活函数  
  110.     relu=tf.nn.relu(bias,name=scope.name)  
  111.       
  112.     return relu  
  113.       
  114. #定义全连接层  
  115. def fc_layer(x,num_in,num_out,name,relu=True):  
  116.     with tf.variable_scope(name) as scope:  
  117.         #创建权重参数和偏置项  
  118.         weights=tf.get_variable("weights",shape=[num_in,num_out],trainable=True)  
  119.         biases=tf.get_variable("biases",[num_out],trainable=True)  
  120.           
  121.         #计算  
  122.         act=tf.nn.xw_plus_b(x,weights,biases,name=scope.name)  
  123.           
  124.         if relu==True:  
  125.             relu=tf.nn.relu(act)  
  126.             return relu  
  127.         else:  
  128.             return act  
  129.       
  130. #定义最大池化层  
  131. def max_pool(x,filter_height,filter_width,stride_y,stride_x,name,padding='SAME'):  
  132.     return tf.nn.max_pool(x,ksize=[1,filter_height,filter_width,1],strides=[1,stride_y,stride_x,1],padding=padding,name=name)  
  133.   
  134. #定义局部响应归一化LPN  
  135. def lrn(x,radius,alpha,beta,name,bias=1.0):  
  136.     return tf.nn.local_response_normalization(x,depth_radius=radius,alpha=alpha,beta=beta,bias=bias,name=name)  
  137.       
  138. #定义dropout  
  139. def dropout(x,keep_prob):  
  140.     return tf.nn.dropout(x,keep_prob)  

2. 输入一张图片对AlexNet网络进行测试,可以查看卷积层提取的特征图

[python]  view plain  copy
  1. import tensorflow as tf  
  2. import AlexNet_model  
  3. import numpy as np  
  4. import cv2  
  5. import caffe_classes  
  6. import matplotlib.pyplot as plt  
  7.   
  8. keep_prob=0.5  
  9. num_classes=1000  
  10. skip_layer=[]  
  11. #测试图片读取路径  
  12. image = cv2.imread("f:\\tmp\\data\\zebra.jpeg")  
  13. img_resized = cv2.resize(image, (227227))  
  14.   
  15. x=tf.placeholder(tf.float32,[1,227,227,3],name='x-input')  
  16. #定义神经网络结构,初始化模型  
  17. model=AlexNet_model.AlexNet(x,keep_prob,num_classes,skip_layer)  
  18. conv1=model.conv1  
  19. conv5=model.conv5  
  20. score=model.fc8  
  21. #获得神经网络前向传播的softmax层输出  
  22. softmax=tf.nn.softmax(score)  
  23.   
  24. with tf.Session() as sess:  
  25.     sess.run(tf.global_variables_initializer())  
  26.     model.load_initial_weights(sess)  
  27.       
  28.     test=np.reshape(img_resized,(1,227,227,3))  
  29.     #sess.run()函数运行张量返回的是就是对应的数组  
  30.     soft,con1,con5=sess.run([softmax,conv1,conv5],feed_dict={x:test})  
  31.     #显示第五层卷积层提取的前6个特征图  
  32.     for i in range(6):  
  33.         plt.matshow(con5[0,:,:,0],cmap=plt.cm.gray)  
  34.         plt.show()  
  35.     #获取其中最大值所在的索引  
  36.     maxx=np.argmax(soft)  
  37.     #找到目标所属的类别  
  38.     ress=caffe_classes.class_names[maxx]  
  39.     text='Predicted class:'+str(maxx)+'('+ress+')'  
  40.     #显示测试类别  
  41.     cv2.putText(image,text, (20,20), cv2.FONT_HERSHEY_SIMPLEX, 1, (02550), 2)  
  42.     #显示属于该类别的概率  
  43.     cv2.putText(image,'with probability:'+str(soft[0][maxx]), (20,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (02550), 2)  
  44.     cv2.imshow('test_image', image)  
  45.     #显示10秒  
  46.     cv2.waitKey(10000)  

测试结果如图所示:


3. 直接读取本地图片制作自己的数据集,用的是猫狗大战图片,链接:http://pan.baidu.com/s/1dFd8kmt 密码:psor

[python]  view plain  copy
  1. import tensorflow as tf    
  2. import os    
  3. import numpy as np    
  4.     
  5. #生成训练图片的路径    
  6. train_dir='f:\\cat_dog_image\\train\\'    
  7.     
  8.     
  9. #获取图片,存放到对应的列表中,同时贴上标签,存放到label列表中    
  10. def get_files(file_dir):    
  11.     
  12.     cats =[]    
  13.     label_cats =[]    
  14.     dogs =[]    
  15.     label_dogs =[]    
  16.     for file in os.listdir(file_dir):    
  17.         name = file.split(sep='.')    
  18.         if name[0]=='cat':    
  19.             cats.append(file_dir + file)    
  20.             label_cats.append(0)    
  21.         else:    
  22.             dogs.append(file_dir + file)    
  23.             label_dogs.append(1)    
  24.     #合并数据    
  25.     image_list = np.hstack((cats, dogs))    
  26.     label_list = np.hstack((label_cats, label_dogs))    
  27.     #利用shuffle打乱数据    
  28.     temp = np.array([image_list, label_list])    
  29.     temp = temp.transpose()  # 转置    
  30.     np.random.shuffle(temp)    
  31.             
  32.     #将所有的image和label转换成list    
  33.     image_list = list(temp[:, 0])    
  34.     label_list = list(temp[:, 1])    
  35.     label_list = [int(i) for i in label_list]    
  36.     
  37.     return image_list, label_list    
  38.             
  39. #将上面生成的List传入get_batch() ,转换类型,产生一个输入队列queue,因为img和lab      
  40. #是分开的,所以使用tf.train.slice_input_producer(),然后用tf.read_file()从队列中读取图像    
  41. def get_batch(image,label,image_W,image_H,batch_size,capacity):    
  42.     
  43.     #将python.list类型转换成tf能够识别的格式    
  44.     image=tf.cast(image,tf.string)    
  45.     label=tf.cast(label,tf.int32)    
  46.         
  47.     #产生一个输入队列queue    
  48.     input_queue=tf.train.slice_input_producer([image,label])    
  49.         
  50.     label=input_queue[1]    
  51.     image_contents=tf.read_file(input_queue[0])    
  52.     #将图像解码,不同类型的图像不能混在一起,要么只用jpeg,要么只用png等。      
  53.     image=tf.image.decode_jpeg(image_contents,channels=3)    
  54.         
  55.     #将数据预处理,对图像进行旋转、缩放、裁剪、归一化等操作,让计算出的模型更健壮。    
  56.     image=tf.image.resize_image_with_crop_or_pad(image,image_W,image_H)    
  57.     image=tf.image.per_image_standardization(image)    
  58.         
  59.     #生成batch    
  60.     image_batch,label_batch=tf.train.batch([image,label],batch_size=batch_size,num_threads=64,capacity=capacity)    
  61.         
  62.     #重新排列标签,行数为[batch_size]    
  63.     #label_batch=tf.reshape(label_batch,[batch_size])    
  64.     image_batch=tf.cast(image_batch,tf.float32)    
  65.         
  66.     return image_batch,label_batch    

4. 利用自己的训练集对AlexNet网络进行微调,这里对AlexNet网络中第六、七、八全连接层进行重新训练

[python]  view plain  copy
  1. #利用Tensorflow对预训练的AlexNet网络进行微调  
  2.   
  3. import tensorflow as tf  
  4. import numpy as np  
  5. import os  
  6. from AlexNet_model import AlexNet  
  7. #from datagenerator import ImageDataGenerator  
  8. #from datetime import datetime  
  9. #from tensorflow.contrib.data import Iterator  
  10. import input_selfdata  
  11.   
  12. #模型保存的路径和文件名。  
  13. MODEL_SAVE_PATH="/model/"  
  14. MODEL_NAME="alexnet_model.ckpt"  
  15.   
  16. #训练集图片所在路径  
  17. train_dir='f:\\cat_dog_image\\train\\'  
  18. #训练图片的尺寸  
  19. image_size=227  
  20. #训练集中图片总数  
  21. total_size=250000  
  22.   
  23. #学习率  
  24. learning_rate=0.001  
  25. #训练完整数据集迭代轮数  
  26. num_epochs=10  
  27. #数据块大小  
  28. batch_size=128  
  29.   
  30. #执行Dropout操作所需的概率值  
  31. dropout_rate=0.5  
  32. #类别数目  
  33. num_classes=2  
  34. #需要重新训练的层  
  35. train_layers=['fc8','fc7','fc6']  
  36.   
  37. #读取本地图片,制作自己的训练集,返回image_batch,label_batch  
  38. train, train_label = input_selfdata.get_files(train_dir)  
  39. x,y=input_selfdata.get_batch(train,train_label,image_size,image_size,batch_size,2000)  
  40.   
  41. #用于计算图输入和输出的TF占位符,每次读取一小部分数据作为当前的训练数据来执行反向传播算法  
  42. #x =tf.placeholder(tf.float32,[batch_size,227,227,3],name='x-input')  
  43. #y =tf.placeholder(tf.float32,[batch_size,num_classes])  
  44. keep_prob=tf.placeholder(tf.float32)  
  45.   
  46. #定义神经网络结构,初始化模型  
  47. model =AlexNet(x,keep_prob,num_classes,train_layers)  
  48. #获得神经网络前向传播的输出  
  49. score=model.fc8  
  50.   
  51. #获得想要训练的层的可训练变量列表  
  52. var_list = [v for v in tf.trainable_variables() if v.name.split('/')[0in train_layers]  
  53.   
  54. #定义损失函数,获得loss  
  55. with tf.name_scope("cross_ent"):  
  56.     loss=tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=score,labels=y))  
  57.       
  58. #定义反向传播算法(优化算法)  
  59. with tf.name_scope("train"):  
  60.     # 获得所有可训练变量的梯度  
  61.     gradients = tf.gradients(loss, var_list)  
  62.     gradients = list(zip(gradients, var_list))  
  63.   
  64.     # 选择优化算法,对可训练变量应用梯度下降算法更新变量  
  65.     optimizer = tf.train.GradientDescentOptimizer(learning_rate)  
  66.     train_op = optimizer.apply_gradients(grads_and_vars=gradients)  
  67.       
  68. #使用前向传播的结果计算正确率  
  69. with tf.name_scope("accuracy"):  
  70.     correct_pred=tf.equal(tf.cast(tf.argmax(score,1),tf.int32),y)  
  71.     accuracy=tf.reduce_mean(tf.cast(correct_pred,tf.float32))  
  72.   
  73. #Initialize an saver for store model checkpoints 加载模型  
  74. saver=tf.train.Saver()  
  75.   
  76. # 每个epoch中验证集/测试集需要训练迭代的轮数  
  77. train_batches_per_epoch = int(np.floor(total_size/batch_size))  
  78.   
  79. with tf.Session() as sess:  
  80.     #变量初始化  
  81.     tf.global_variables_initializer().run()  
  82.           
  83.     coord = tf.train.Coordinator()  
  84.     threads = tf.train.start_queue_runners(coord=coord)  
  85.     try:  
  86.         for epoch in range(num_epochs):  
  87.             for step in range(train_batches_per_epoch):  
  88.                 #while not coord.should_stop():  
  89.                 if coord.should_stop():  
  90.                     break  
  91.                 _,loss_value,accu=sess.run([train_op,loss,accuracy],feed_dict={keep_prob: 1.})    
  92.                 if step%50==0:  
  93.                     print("Afetr %d training step(s),loss on training batch is %g,accuracy is %g." % (step,loss_value,accu))  
  94.                       
  95.         saver.save(sess,os.path.join(MODEL_SAVE_PATH,MODEL_NAME))     
  96.               
  97.     except tf.errors.OutOfRangeError:  
  98.         print('done!')  
  99.     finally:  
  100.         coord.request_stop()  
  101.     coord.join(threads)  

猜你喜欢

转载自blog.csdn.net/maweifei/article/details/80724865