TensroFlow学习——第三章(三)

卷积神经网络迁移学习

基于训练好的Inception-v3的模型,对flower_photos数据集进行分类

训练结果如下,测试集的准确率为91.0082%

在这里插入图片描述
算法如下:

import os
import random
import numpy as np
import tensorflow as tf
from tensorflow.python.platform import gfile
import matplotlib.pyplot as plt
# Inception-v3模型瓶颈层的极点个数
BOTTLENECK_TENSOR_SIZE=2048

# Inceotion-v3模型中代表瓶颈层结果的张量名称
# 在谷歌提供的Inception-v3模型中,这个张量名称为‘pool_3/_reshape:0’
BOTTLENECK_TENSOR_NAME='pool_3/_reshape:0'

# 图像输入张量所对应的名称
JPEG_DATA_TENSOR_NAME='DecodeJpeg/contents:0'

# 下载好的谷歌训练好的模型
MODEL_PATH='./data/classify_image_graph_def.pb'

# 将通过Inception_v3提取的特征保存在文件中
Feature_path='./image.txt'

# 训练样本路径
Input_path='./data/flower_photos'

# 验证、测试数据百分比
VALIDATION_PERCENTAGE=0.1
TEST_PERCENTAGE=0.1

# 设置神经网络参数
LEARNING_RATE=0.01
STEPS=4000
BATCHSIZE=100

# 类别
LABELS={'daisy':0, 'dandelion':1, 'roses':2, 'sunflowers':3, 'tulips':4}

# 提取图片数据,并分为训练集、验证集和测试集
def create_image_list():
	all_images,all_labels=[],[]
	label_list=os.listdir(Input_path)
	for file_name in label_list:
		image_dir=os.path.join(Input_path,file_name)
		image_list=os.listdir(image_dir)
		for name in image_list:
			image_name=os.path.join(image_dir,name)
			labels=np.zeros(len(LABELS),dtype=np.float32)
			labels[LABELS[file_name]]=1.0
			all_images.append(image_name)
			all_labels.append(labels)
	return all_images,all_labels

# 读取提取的特征向量作为训练数据
def get_features(test_percentage,vaildation_percentage):
	# 读取特征数据
	images,labels=[],[]
	with open(Feature_path,'r') as file:
		string=file.readlines()
	for one_line in string:
		one_line=one_line.split('|')
		images.append([float(x) for x in one_line[0].split(',')])
		labels.append([float(x) for x in one_line[1].split(',')])
	# 分为训练集、验证集和测试集
	sum=list(zip(images,labels))
	random.shuffle(sum)
	images[:],labels[:]=zip(*sum)
	LEN1=int(test_percentage*len(images))
	LEN2=int(vaildation_percentage*len(images))
	# 返回的顺序分别为test,valid,train
	return images[:LEN1],labels[:LEN1],images[LEN1:LEN1+LEN2],labels[LEN1:LEN1+LEN2],images[LEN1+LEN2:],labels[LEN1+LEN2:]

# 从训练数据中批量取出数据
def random_get_batch_data(batch_size,images,labels):
	batch_image,batch_label=[],[]
	for i in range(batch_size):
		index=random.randint(0,len(images)-1)
		batch_image.append(images[index])
		batch_label.append(labels[index])
	return batch_image,batch_label

def main(argv=None):
	images,labels=create_image_list()
	train_datas=[]
	# 读取训练好的Inception-v3模型
	with gfile.FastGFile(MODEL_PATH,'rb') as f:
		graph_def=tf.GraphDef()
		graph_def.ParseFromString(f.read())
	# 加载读取的Inception-v3模型,并返回数据输入所对应的张量以及计算瓶颈层结果对应的张量
	bottle_tensor,jpeg_data_tensor=tf.import_graph_def(graph_def,return_elements=[BOTTLENECK_TENSOR_NAME,JPEG_DATA_TENSOR_NAME])
	if 0:#此部分备注掉是因为,用Inception-v3模型提取特征后,会写入文件,因此在调整全连接层的参数时,可以不用再进行提取特征操作
		# 提取特征向量
		with tf.Session() as sess:
			for img in images:
				image=gfile.FastGFile(img,'rb').read()
				bottleneck_value=sess.run(bottle_tensor,feed_dict={jpeg_data_tensor:image})
				# 将四维张量转化成以为数组
				bottleneck_value=np.squeeze(bottleneck_value)
				train_datas.append(bottleneck_value)
		# 写入文件
		with open('./image.txt', 'w') as file:
			for i in range(len(train_datas)):
				string=','.join(str(x) for x in train_datas[i])+'|'+','.join(str(x) for x in labels[i])+'\n'
				file.write(string)

	# 读取特征量
	test_image,test_label,valid_image,valid_label,train_image,train_label=get_features(TEST_PERCENTAGE,VALIDATION_PERCENTAGE)
	n_classes=len(LABELS)

	# 定义新的神经网络输入,这输入是新的图片经过Inception-v3模型向前传播到达瓶颈层时的节点取值
	bottle_input=tf.placeholder(tf.float32,[None,BOTTLENECK_TENSOR_SIZE],name='BottleneckInputPlaceholder')
	ground_truth_input=tf.placeholder(tf.float32,[None,n_classes],name='GroundTruthInput')

	# 定义全连接层,用于将特征分类
	with tf.name_scope('Final_training_ops'):
		weights=tf.Variable(tf.truncated_normal([BOTTLENECK_TENSOR_SIZE,n_classes],stddev=0.001))
		biases=tf.Variable(tf.zeros([n_classes]))
		logits=tf.matmul(bottle_input,weights)+biases
		final_tensor=tf.nn.softmax(logits)

	# 交叉熵损失函数
	cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=final_tensor,labels=ground_truth_input)
	cross_entropy_mean=tf.reduce_mean(cross_entropy)
	train_step=tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cross_entropy_mean)

	# 计算正确率
	with tf.name_scope('evalution'):
		correct_prediction=tf.equal(tf.arg_max(final_tensor,1),tf.arg_max(ground_truth_input,1))
		accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

	train_loss,train_acc=[],[]
	val_loss,val_acc=[],[]
	with tf.Session() as sess:
		init=tf.initialize_all_variables()
		sess.run(init)

		for epoch in range(STEPS):
			batch_image,batch_label=random_get_batch_data(BATCHSIZE,train_image,train_label)
			_,loss,acc=sess.run([train_step,cross_entropy_mean,accuracy],feed_dict={bottle_input:batch_image,ground_truth_input:batch_label})
			if (epoch+1)%100==0:
				print('<=%d=>,loss:%g,acc:%g%%'%(epoch+1,loss,acc*100.0))
				train_loss.append(loss)
				train_acc.append(acc)
				loss,acc=sess.run([cross_entropy_mean,accuracy],feed_dict={bottle_input:valid_image,ground_truth_input:valid_label})
				val_loss.append(loss)
				val_acc.append(acc)
			loss,acc=sess.run([cross_entropy_mean, accuracy],feed_dict={bottle_input:test_image,ground_truth_input:test_label})
		print('Test loss:%g,acc:%g%%'%(loss,acc*100.0))

	epochs=[i for i in range(len(train_acc))]
	plt.figure(1)
	plt.grid(True)
	plt.plot(epochs,train_loss,color='red',label='train_loss')
	plt.plot(epochs,val_loss,color='blue',label='valid_loss')
	plt.plot(epochs,train_acc,color='black',label='train_acc')
	plt.plot(epochs,val_acc,color='green',label='valid_acc')
	plt.legend()
	plt.xlabel('Epochs',fontsize=15)
	plt.ylabel('Y',fontsize=15)
	plt.title('LOSS AND ACC',fontsize=15)
	plt.show()

if __name__=='__main__':
	tf.app.run()

猜你喜欢

转载自blog.csdn.net/m0_38120677/article/details/84669055