如何在PaddlePaddle中使用VisualDL

下面我们演示一下如何在PaddlePaddle中使用VisualDL,从而可以把PaddlePaddle的训练过程可视化出来。我们将以PaddlePaddle用卷积神经网络(CNN, Convolutional Neural Network)来训练Cifar10 数据集作为例子。

以下范例是在官方Paddle Book Example的基础上用PaddlePaddle’s Fluid API修改。

完整的演示程序可以在这里下载。

这程序是在Paddle v2 0.11版本上开发。可以用pip install paddlepaddledocker pull paddlepaddle/paddle:0.11.0来安装。注意Paddle还没支持Python3和protobuf需要3.5+。如果出现TypeError: init() got an unexpected keyword argument 'file', 是因为protobuf不是3.5以上,运行pip install —upgrade protobuf就能解决。安装详细流程请看这里

首先我们创建Loggers来记录不同种类的数据:

  1. # create VisualDL logger and directory
  2. logdir = "./tmp"
  3. logwriter = LogWriter(logdir, sync_cycle=10)
  4.  
  5. # create 'train' run
  6. with logwriter.mode("train") as writer:
  7. # create 'loss' scalar tag to keep track of loss function
  8. loss_scalar = writer.scalar("loss")
  9.  
  10. with logwriter.mode("train") as writer:
  11. acc_scalar = writer.scalar("acc")
  12.  
  13. num_samples = 4
  14. with logwriter.mode("train") as writer:
  15. conv_image = writer.image("conv_image", num_samples, 1) #show 4 samples for every 1 step
  16. input_image = writer.image("input_image", num_samples, 1)
  17.  
  18. with logwriter.mode("train") as writer:
  19. param1_histgram = writer.histogram("param1", 100) #100 buckets, e.g 100 data sets in a histograms
  20.  

我们再来用Paddle v2 Fluid APIs创建VGG CNN模型:

  1. def vgg16_bn_drop(input):
  2. def conv_block(input, num_filter, groups, dropouts):
  3. return fluid.nets.img_conv_group(
  4. input=input,
  5. pool_size=2,
  6. pool_stride=2,
  7. conv_num_filter=[num_filter] * groups,
  8. conv_filter_size=3,
  9. conv_act='relu',
  10. conv_with_batchnorm=True,
  11. conv_batchnorm_drop_rate=dropouts,
  12. pool_type='max')
  13.  
  14. conv1 = conv_block(input, 64, 2, [0.3, 0])
  15. conv2 = conv_block(conv1, 128, 2, [0.4, 0])
  16. conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0])
  17. conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0])
  18. conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0])
  19.  
  20. drop = fluid.layers.dropout(x=conv5, dropout_prob=0.5)
  21. fc1 = fluid.layers.fc(input=drop, size=512, act=None)
  22. bn = fluid.layers.batch_norm(input=fc1, act='relu')
  23. drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.5)
  24. fc2 = fluid.layers.fc(input=drop2, size=512, act=None)
  25. return fc2, conv1
  26.  
  27.  
  28. classdim = 10
  29. data_shape = [3, 32, 32]
  30.  
  31. images = fluid.layers.data(name='pixel', shape=data_shape, dtype='float32')
  32. label = fluid.layers.data(name='label', shape=[1], dtype='int64')
  33.  
  34. net, conv1 = vgg16_bn_drop(images)
  35.  
  36. predict = fluid.layers.fc(
  37. input=net,
  38. size=classdim,
  39. act='softmax',
  40. param_attr=ParamAttr(name="param1", initializer=NormalInitializer()))
  41. cost = fluid.layers.cross_entropy(input=predict, label=label)
  42. avg_cost = fluid.layers.mean(x=cost)
  43.  
  44. optimizer = fluid.optimizer.Adam(learning_rate=0.001)
  45. opts = optimizer.minimize(avg_cost)
  46.  
  47. accuracy = fluid.evaluator.Accuracy(input=predict, label=label)
  48.  
  49. BATCH_SIZE = 16
  50. PASS_NUM = 1
  51.  
  52. train_reader = paddle.batch(
  53. paddle.reader.shuffle(paddle.dataset.cifar.train10(), buf_size=128 * 10),
  54. batch_size=BATCH_SIZE)
  55.  
  56. place = fluid.CPUPlace()
  57. exe = fluid.Executor(place)
  58. feeder = fluid.DataFeeder(place=place, feed_list=[images, label])
  59. exe.run(fluid.default_startup_program())

接下来我们开始训练并且同时用 VisualDL 来采集相关数据

  1. for pass_id in range(PASS_NUM):
  2. accuracy.reset(exe)
  3. for data in train_reader():
  4. loss, conv1_out, param1, acc = exe.run(
  5. fluid.default_main_program(),
  6. feed=feeder.feed(data),
  7. fetch_list=[avg_cost, conv1, param1_var] + accuracy.metrics)
  8. pass_acc = accuracy.eval(exe)
  9.  
  10. # all code below is for VisualDL
  11.  
  12. # start picking sample from beginning
  13. if sample_num == 0:
  14. input_image.start_sampling()
  15. conv_image.start_sampling()
  16.  
  17. idx1 = input_image.is_sample_taken()
  18. idx2 = conv_image.is_sample_taken()
  19. assert idx1 == idx2
  20. idx = idx1
  21. if idx != -1:
  22. image_data = data[0][0]
  23. # reshape the image to 32x32 and 3 channels
  24. input_image_data = np.transpose(
  25. image_data.reshape(data_shape), axes=[1, 2, 0])
  26. # add sample to VisualDL Image Writer to view input image
  27. input_image.set_sample(idx, input_image_data.shape,
  28. input_image_data.flatten())
  29.  
  30.  
  31. conv_image_data = conv1_out[0][0]
  32. # add sample to view conv image
  33. conv_image.set_sample(idx, conv_image_data.shape,
  34. conv_image_data.flatten())
  35.  
  36. sample_num += 1
  37. # when we have enough samples, call finish sampling()
  38. if sample_num % num_samples == 0:
  39. input_image.finish_sampling()
  40. conv_image.finish_sampling()
  41. sample_num = 0
  42.  
  43. # add record for loss and accuracy to scalar
  44. loss_scalar.add_record(step, loss)
  45. acc_scalar.add_record(step, acc)
  46. param1_histgram.add_record(step, param1.flatten())
  47.  
  48. print("loss:" + str(loss) + " acc:" + str(acc) + " pass_acc:" + str(
  49. pass_acc))
  50. step += 1

训练结束后,各个组件的可视化结果如下:

关于accuracy和loss的数值图的如下:

如何在PaddlePaddle中使用VisualDL - 图1

训练过后的来源图和卷积权重图的各四个样本如下:

如何在PaddlePaddle中使用VisualDL - 图2