赞
踩
本文是学习博客,转载自百度paddle框架的学习文档,代码自己敲了一遍,(由于python2和python3 的区别)会有一点改动。
代码:
from PIL import Image import matplotlib.pyplot as plt import numpy as np import paddle import paddle.fluid as fluid """ 我们需要设置 inference_program 函数。我们想用这个程序来演示三个不同的分类器,每个分类器都定义为 Python 函数。 我们需要将图像数据输入到分类器中。Paddle 为读取数据提供了一个特殊的层 layer.data 层。 让我们创建一个数据层来读取图像并将其连接到分类网络。 """ def softmax_regression(img,label): """ 定义softmax分类器: 一个一softmax为激活函数的全链接层 :return: predict_image --分类结果 """ predict_img = fluid.layers.fc(input = img,size = 10,act = 'softmax') return predict_img,label def multilayer_perception(img,label): """ 定义多层感知机分类器 含有两个隐藏层(全连接层)的多层感知机 其中钱两个隐藏层的激活函数是RULU,输出层的激活函数是softmax :return: predict_img --分类结果 """ # 建立第一个隐层(全链接层) ,激活函数为relu hidden_1 = fluid.layers.fc(input=img,size=200,act='relu') # 建立第二个隐层(全连接层) , 激活函数为relu hidden_2 = fluid.layers.fc(input=hidden_1,size=200,act='relu') # # 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10 prediction = fluid.layers.fc(input=hidden_2,size=10,act='softmax') return prediction , label def converlutional_neural_network(img,label): """ 定义卷积神经网络分类器: 输入的二维图像经过两个卷积-池化层,使用softmax为激活函数的全连接层作为输出层 :return: predict --分类结果 """ #第一个卷积-池化层,使用20个5*5的滤波器,池化大小为2,池化步长为2,激活函数为RELU conv_pool_1 = fluid.nets.simple_img_conv_pool( input = img, # 输入数据的名称 filter_size = 5 , #滤波器尺寸 num_filters = 20 , #滤波器数量 pool_size = 2, #池化大小 pool_stride = 2, #池化步长 act = 'relu' ) conv_pool_1 = fluid.layers.batch_norm(conv_pool_1) #第二个卷积-池化层,使用50个5*5的滤波器,池化大小为2,池化步长为2,激活函数为relu conv_pool_2 = fluid.nets.simple_img_conv_pool( input = conv_pool_1, #输入数据 filter_size = 5, num_filters = 50, pool_size = 2, pool_stride = 2, act = 'relu' ) prediction = fluid.layers.fc(input=conv_pool_2,size=10,act='softmax') return prediction ,label def train_progam(img,label): """ 配置 train_program :return: predict --分类结果 avg_cost --平均损失 acc --准确率 """ # predict,label = softmax_regression(img,label) #取消注释将使用softmax回归 # predict,label = multilayer_perception(img,label) #取消注释将使用多层感知机 predict ,label = converlutional_neural_network(img,label) #取消注释将使用卷据-池化网络 #使用交叉熵计算predit和label之间的损失函数 cost = fluid.layers.cross_entropy(input = predict,label=label) avg_cost = fluid.layers.mean(cost) #计算分类准确率 acc = fluid.layers.accuracy(input=predict,label=label) return predict, [avg_cost, acc] def optimizer_funtion(): """ 优化函数: Adam optimizer ,神经网络中常用的优化函数 learning_rate 是学习率,它的大小与网络的训练收敛速度有关 """ return fluid.optimizer.Adam(learning_rate=0.001) def set_Feeder(): """ 下一步,我们开始训练过程。paddle.dataset.mnist.train()和paddle.dataset.mnist.test()分别做训练和测试数据集。这两个函数各自返回一个reader——PaddlePaddle中的reader是一个Python函数,每次调用的时候返回一个Python yield generator(生成器)。 下面shuffle是一个reader decorator,它接受一个reader A,返回另一个reader B。reader B 每次读入buffer_size条训练数据到一个buffer里,然后随机打乱其顺序,并且逐条输出。 batch是一个特殊的decorator,它的输入是一个reader,输出是一个batched reader。在PaddlePaddle里,一个reader每次yield一条训练数据,而一个batched reader每次yield一个minibatch。 :return: """ #一个minibatch中有64个数据 BATCH_SIZE = 64 train_reader = paddle.batch( paddle.reader.shuffle( reader=paddle.dataset.mnist.train(), #下载训练集,一个一次只能yield一条数的生成器 buf_size= 500 #读取500条数据后打乱顺序再《逐条》输出 ), batch_size = BATCH_SIZE #把逐条得到的数据,每64个作为以后minibatch输出 ) test_reader = paddle.batch( reader=paddle.dataset.mnist.test(), # 下载训练集,一个一次只能yield一条数的生成器, batch_size = BATCH_SIZE # 把逐条得到的数据,每64个作为以后minibatch输出 ) return train_reader ,test_reader def event_haddle(pass_id,batch_id,cost): # 打印训练的中间结果,训练轮次,batch数,损失函数 print("Pass_id: %d, Batch_id_ %d, Cost: %f" % (pass_id, batch_id, cost)) def event_haddle_plot(): #将训练过程绘图表示 from paddle.utils.plot import Ploter train_prompt = "Train cost" test_prompt = "Test cost" cost_ploter = Ploter(train_prompt, test_prompt) # cost_ploter.append(ploter_title, step, cost) # cost_ploter.plot() # pass def train_test(train_test_program,train_test_feed,train_test_reader,exe,avg_cost,acc): #将分类准确率存在acc_set中 acc_set = [] # 将平均损失存储在avg_loss_set中 avg_loss_set = [] # 将测试 reader yield 出的每一个数据传入网络中进行训练 for test_data in train_test_reader(): avg_loss_np ,acc_np= exe.run( program = train_test_program, feed = train_test_feed.feed(test_data), fetch_list = [avg_cost,acc] ) acc_set.append(float(acc_np)) avg_loss_set.append(float(avg_loss_np)) # 获得测试数据上的准确率和损失值 acc_val_mean = np.array(acc_set).mean() avg_loss_val_mean = np.array(avg_loss_set).mean() # 返回平均损失值,平均准确率 return avg_loss_val_mean, acc_val_mean def main(save_dirname): # 获取数据 train_reader, test_reader = set_Feeder() # 输入原始图像数据,大小为28*28*1 img = fluid.layers.data(name='img', shape=[1, 28, 28], dtype='float32') # 标签层,名称为label,对应输入图片的类别标签 label = fluid.layers.data(name='label', shape=[1], dtype='int64') #定义损失函数、准确率、和预测算法 predict, [avg_cost, acc] = train_progam(img,label) #定义优化函数,传入损失 optimizer = optimizer_funtion() optimizer.minimize(avg_cost) #初始化参数 place = fluid.CPUPlace() exe = fluid.Executor(place) exe.run(fluid.default_startup_program()) main_program = fluid.default_main_program() # test_program = main_program.clone(for_test=True) # 设置数据输入器 feeder = fluid.DataFeeder(feed_list=[img, label], place=place) #设置训练过程的超参 PASS_NUM = 5 epochs = [epoch_id for epoch_id in range(PASS_NUM)] #创建执行器 lists = [] step = 0 for epoch_id in epochs: for step_id , data in enumerate(train_reader()): metrics = exe.run( program = main_program, feed = feeder.feed(data), fetch_list=[avg_cost,acc] ) if step % 100 ==0: #每训练100次打印一次log print("step = %d ; epoch_num = %d ; Cost = %f ; acc = %f" % (step, epoch_id, metrics[0] , metrics[1])) step += 1 # 测试每个epoch的分类效果 avg_loss_val, acc_val = train_test(train_test_program = main_program, train_test_reader = test_reader, train_test_feed = feeder, exe = exe, avg_cost = avg_cost, acc=acc) print("Test with Epoch %d, avg_cost: %s, acc: %s" % (epoch_id, avg_loss_val, acc_val)) # event_handler_plot(test_prompt, step, metrics[0]) lists.append((epoch_id, avg_loss_val, acc_val)) #保存训练好的模型进行预测 if save_dirname is not None: fluid.io.save_inference_model( dirname=save_dirname, feeded_var_names=['img'], target_vars = [predict], executor = exe, ) def inference(save_dirname,im): place = fluid.CPUPlace() exe = fluid.Executor(place) inference_scope = fluid.core.Scope() with fluid.scope_guard(inference_scope): """ 使用 fluid.io.load_inference_model 获取 inference program desc, feed_target_names 用于指定需要传入网络的变量名 fetch_targets 指定希望从网络中fetch出的变量名 """ [inference_program, feed_target_names, fetch_targets] = fluid.io.load_inference_model( save_dirname, exe, None, None) # 将feed构建成字典 {feed_target_name: feed_target_data} # 结果将包含一个与fetch_targets对应的数据列表 print("feed_target_names:",feed_target_names) results = exe.run( program = inference_program, feed = {feed_target_names[0]:im}, fetch_list = fetch_targets ) print("results:",results) lab = np.argsort(results) print("lab = ",lab) return lab def load_test_image(file): """读取自己手写数字的图片""" im = Image.open(file).convert('L') im = im.resize((28, 28), Image.ANTIALIAS) im = np.array(im).reshape(1, 1, 28, 28).astype(np.float32) im = im / 255.0 * 2.0 - 1.0 return im if __name__ == '__main__': save_dirname = r"result_train\recognize_digits.inference.model" #训练模型,储存model # main(save_dirname) #读取自己手写的数字图片 file_im = r'traindata\image_cecognition\infer_8.png' im = load_test_image(file_im) # 对手写图片进行预测 lab = inference(save_dirname,im) print("Inference result of image/infer_{}.png is: {}".format(file_im[-11:],lab[0][0][0]) ) #这里原文是[0][0][-1]是错的,选出来交叉熵最大的数,应该用[0][0][0]选交叉熵最小的数是预测结构。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。