[Paddle学习笔记][04][图像分类]
说明:
本例程使用vggnet-16来进行cifar10图像分类。
实验代码:
1 import paddle 2 import paddle.fluid as fluid 3 import numpy 4 from paddle.utils.plot import Ploter 5 from PIL import Image 6 import matplotlib.pyplot as plt 7 %matplotlib inline 8 9 # 全局变量 10 use_cuda = 1 # 是否使用GPU 11 batch_size = 128 # 每批读取数据 12 epoch_num = 50 # 训练迭代周期 13 save_dirname = "./model/Image_Classification.vggnet.model" # 模型保存路径 14 file_dirname = "./image/dog.png" # 预测图像路径 15 16 # vggnet 17 def conv_block(input, num_filter, groups, dropouts): 18 return fluid.nets.img_conv_group( 19 input=input, 20 conv_num_filter=[num_filter]*groups, 21 conv_filter_size=3, 22 conv_with_batchnorm=True, 23 conv_batchnorm_drop_rate=dropouts, 24 conv_act='relu', 25 pool_size=2, 26 pool_stride=2, 27 pool_type='max') 28 29 def vggnet(image): 30 # 输入图像: N*C*H*W=N*3*32*32, H/W=(H/W-F+2*P)/S+1, 网络层数: 16=13+1+1+1 31 conv1 = conv_block(input=image, num_filter=64, groups=2, dropouts=[0.3, 0]) # 输出:N*64*16*16 32 conv2 = conv_block(input=conv1, num_filter=128, groups=2, dropouts=[0.4, 0]) # 输出:N*128*8*8 33 conv3 = conv_block(input=conv2, num_filter=256, groups=3, dropouts=[0.4, 0.4, 0]) # 输出:N*256*4*4 34 conv4 = conv_block(input=conv3, num_filter=512, groups=3, dropouts=[0.4, 0.4, 0]) # 输出:N*512*2*2 35 conv5 = conv_block(input=conv4, num_filter=512, groups=3, dropouts=[0.4, 0.4, 0]) # 输出:N*512*1*1 36 37 drop1 = fluid.layers.dropout(x=conv5, dropout_prob=0.5) 38 fc1 = fluid.layers.fc(input=drop1, size=512, act=None) # 输出: N*512*1*1 39 bn1 = fluid.layers.batch_norm(input=fc1, act='relu') 40 drop2 = fluid.layers.dropout(x=bn1, dropout_prob=0.5) 41 fc2 = fluid.layers.fc(input=drop2, size=512, act=None) # 输出: N*512*1*1 42 43 # 输出概率: N*L=N*10 44 prediction = fluid.layers.fc(input=fc2, size=10, act='softmax') 45 46 return prediction 47 48 # 预测网络 49 def infer_network(): 50 image = fluid.layers.data(name='image', shape=[None, 3, 32, 32], dtype='float32') 51 prediction = vggnet(image) 52 return prediction 53 54 # 训练网络 55 def train_network(prediction): 56 label = fluid.layers.data(name='label', shape=[None, 1], dtype='int64') 57 58 loss = fluid.layers.cross_entropy(input=prediction, label=label) 59 avg_loss = fluid.layers.mean(loss) 60 accuracy = fluid.layers.accuracy(input=prediction, label=label) 61 62 return [avg_loss, accuracy] 63 64 # 测试模型 65 def test(executor, program, reader, feeder, fetch_list): 66 avg_loss_set = [] # 平均损失值集 67 accuracy_set = [] # 分类准确率集 68 for test_data in reader(): # 将测试数据输出的每一个数据传入网络进行训练 69 metrics = executor.run( 70 program=program, 71 feed=feeder.feed(test_data), 72 fetch_list=fetch_list) 73 avg_loss_set.append(float(metrics[0])) 74 accuracy_set.append(float(metrics[1])) 75 avg_loss_mean = numpy.array(avg_loss_set).mean() # 计算平均损失值 76 accuracy_mean = numpy.array(accuracy_set).mean() # 计算平均准确率 77 return avg_loss_mean, accuracy_mean # 返回平均损失值和平均准确率 78 79 # 训练模型 80 def train(): 81 # 读取数据 82 train_reader = paddle.batch( 83 paddle.reader.shuffle(paddle.dataset.cifar.train10(), buf_size=50000), 84 batch_size=batch_size) # 读取训练数据 85 test_reader = paddle.batch( 86 paddle.dataset.cifar.test10(), 87 batch_size=batch_size) # 读取测试数据 88 89 # 配置网络 90 prediction = infer_network() # 配置预测网络 91 avg_loss, accuracy = train_network(prediction) # 配置训练网络 92 93 # 获取网络 94 main_program = fluid.default_main_program() # 获取默认主程序 95 startup_program = fluid.default_startup_program() # 获取默认启动程序 96 test_program = main_program.clone(for_test=True) # 克隆测试主程序 97 98 # 优化方法 99 optimizer = fluid.optimizer.Adam(learning_rate=0.001) #Adam算法 100 optimizer.minimize(avg_loss) # 最小化平均损失值 101 102 # 启动程序 103 place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() # 获取执行器设备 104 train_exe = fluid.Executor(place) # 获取训练执行器 105 train_exe.run(startup_program) # 运行启动程序 106 test_exe =fluid.Executor(place) # 获取测试执行器 107 108 # 训练模型 109 step = 0 # 周期计数器 110 feed_order = ['image', 'label'] 111 feed_var_list_loop = [main_program.global_block().var(var_name) for var_name in feed_order] 112 feeder = fluid.DataFeeder(feed_list=feed_var_list_loop, place=place) # 获取数据读取器 113 114 train_prompt = "Train loss" 115 test_prompt = "Test loss" 116 loss_ploter = Ploter(train_prompt, test_prompt) # 绘制损失值图 117 118 for epoch in range(epoch_num): 119 # 训练模型 120 for train_data in train_reader(): 121 train_metrics = train_exe.run( 122 program=main_program, 123 feed=feeder.feed(train_data), 124 fetch_list=[avg_loss, accuracy]) 125 126 if step % 100 == 0: 127 loss_ploter.append(train_prompt, step, train_metrics[0]) 128 loss_ploter.plot() 129 print("Pass %d, Epoch %d, avg_loss: %f" % (step, epoch, train_metrics[0])) 130 step += 1 131 132 # 测试模型 133 test_metrics = test( 134 executor=test_exe, 135 program=test_program, 136 reader=test_reader, 137 feeder=feeder, 138 fetch_list=[avg_loss, accuracy]) 139 140 loss_ploter.append(test_prompt, step, test_metrics[0]) 141 loss_ploter.plot() 142 print("Test with Epoch %d, avg_loss: %f, accuracy: %f" % (epoch, test_metrics[0], test_metrics[1])) 143 144 # 保存模型 145 if save_dirname is not None: 146 fluid.io.save_inference_model(save_dirname, ['image'], [prediction], train_exe) 147 148 if test_metrics[0] < 0.4: # 如果平均损失值达到要求,停止训练 149 break 150 151 # 加载图像 152 def load_image(file): 153 im = Image.open(file) # 打开图像文件 154 im = im.resize((32, 32), Image.ANTIALIAS) # 调整图像大小 155 im = numpy.array(im).astype(numpy.float32) # 转换数据类型 156 im = im.transpose((2, 0, 1)) # WHC转为CWH 157 im = im / 255.0 # 归一化处理(0,1) 158 im = numpy.expand_dims(im, axis=0) # 增加数据维度 159 return im 160 161 # 预测图像 162 def infer(): 163 # 加载图像 164 image = load_image(file_dirname) 165 166 # 预测图像 167 place = fluid.CUDAPlace(0) # 获取GPU设备 168 infer_exe = fluid.Executor(place) # 获取预测执行器 169 inference_scope = fluid.core.Scope() # 获取预测作用域 170 171 with fluid.scope_guard(inference_scope): 172 # 加载模型 173 [inference_program, feed_target_names, fetch_targets 174 ] = fluid.io.load_inference_model(save_dirname, infer_exe) 175 176 # 预测图像 177 results = infer_exe.run( 178 program=inference_program, 179 feed={feed_target_names[0]: image}, 180 fetch_list=fetch_targets) 181 182 # 显示结果 183 infer_label = ["ariplane", "automobile", "bird", "cat", "deer", 184 "dog", "frog", "horse", "ship", "truck"] # 预测图像标签 185 print("Infer image: %s" % infer_label[numpy.argmax(results[0])] ) 186 infer_image = Image.open(file_dirname) # 打开预测图像 187 plt.imshow(infer_image) # 显示预测图像 188 189 # 主函数 190 def main(): 191 # 训练模型 192 train() 193 194 # 预测图像 195 infer() 196 197 # 主函数 198 if __name__ == '__main__': 199 main()
实验结果:
Test with Epoch 49, avg_loss: 0.560539, accuracy: 0.870996
Infer image: dog
参考资料:
https://www.paddlepaddle.org.cn/documentation/docs/zh/user_guides/cv_case/image_classification/README.cn.html