[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

 

 

 

 

 

 

 

 

 

 

posted @ 2020-06-17 15:26  盛夏夜  阅读(704)  评论(0编辑  收藏  举报