Caffe实战之Python接口系列(一)Classification_Visualization

引言

记录学习官网的例程中的一些重要语句,遇到的问题等,内容分散,建议顺序查看。
主要是调用Caffe的Python接口
源文件就在{caffe_root}/examples中,安装sudo pip install jupyter打开即可运行,初学者最好是放在它指定的目录,如,否则要改很多路径。
注:eaxmples是用jupyter notebook写的,部分Cell中出现了一些特殊的用法:
1. 感叹号‘!’:用于执行系统命令,如 !pwd
2. 百分号‘%’:用法太多,如 %matplotlib inline 显示绘图窗口 详见Jupyter Notebook Viewer

图像分类和卷积核可视化

用一个预训练模型进行即时识别并通过访问网络接口来可视化特征和逐层参数。

  • 设置模式CPU or GPU(如果是多GPU,可指定设备号):
    caffe.set_mode_cpu() or caffe.set_device(0);caffe.set_mode_gpu()

  • 加载Caffe网络模型:net = caffe.Net(model_def, model_weights, caffe.TEST)

  • 输入数据预处理的配置(独立于Caffe的其他部分,可以用任何惯用的方法)

    1. 对输入数据’data’创建一个transformer:transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
    2. 配置各项参数
      • innermost dimension 到outermost dimension,即HxWxC-> CxHxW.:transformer.set_transpose('data', (2,0,1))
      • 每个通道减去图像均值:transformer.set_mean('data', mu)
      • 从[0, 1]区间映射回[0, 255]:transformer.set_raw_scale('data', 255)
      • 改变输入图像的通道顺序RGB->BGR:transformer.set_channel_swap('data', (2,1,0))
  • 单张图片预测

    1. 设置输入大小:net.blobs['data'].reshape(50,3,227,227)
    2. 利用Caffe加载一张图片并执行我们前面设置的数据预处理

    image = caffe.io.load_image(caffe_root + 'examples/images/cat.jpg')
    transformed_image = transformer.preprocess('data', image)
  • 复制图片数据到网络分配的内存中:net.blobs['data'].data[...] = transformed_image

  • 执行一次前向预测:output = net.forward()
  • 输出结果的处理:

    从输出中取出一个batch的第一幅图像的概率向量:output_prob = output['prob'][0]
    取出一幅图像概率向量中最大值对应的索引,对应到数据集的标签列表,可找到对应类别。

  • 查看中间输出

    扫描二维码关注公众号,回复: 1891705 查看本文章
    1. 先查看网络结构(activation and parameter shapes)

      
      # 每一层输出数据shape,(batch_size, channel_dim, height, width)
      
      for layer_name, blob in net.blobs.iteritems():
          print layer_name + '\t' + str(blob.data.shape)
      
      # 查看卷积核参数shape,(output_channels, input_channels, filter_height, filter_width)
      
      for layer_name, param in net.params.iteritems():
          print layer_name + '\t' + str(param[0].data.shape), str(param[1].data.shape)
    2. 定义辅助显示函数,用于可视化

      def vis_square(data):
          """Take an array of shape (n, height, width) or (n, height, width, 3)
             and visualize each (height, width) thing in a grid of size approx. sqrt(n) by sqrt(n)"""
      
          # normalize data for display 归一化
          data = (data - data.min()) / (data.max() - data.min())
      
          # force the number of filters to be square 方便显示为正方形小格
          n = int(np.ceil(np.sqrt(data.shape[0])))
          padding = (((0, n ** 2 - data.shape[0]),
                     (0, 1), (0, 1))                 # add some space between filters 填充图片的底部和右侧,隔离开来。
                     + ((0, 0),) * (data.ndim - 3))  # don't pad the last dimension (if there is one) 一个图片/核的各通道间不需要填充
          data = np.pad(data, padding, mode='constant', constant_values=1)  # pad with ones (white) 对整个大数组进行填充,padding对应四个维度的前后分别填多少个
      
          # tile the filters into an image 平铺成一幅图像
          data = data.reshape((n, n) + data.shape[1:]).transpose((0, 2, 1, 3) + tuple(range(4, data.ndim + 1))) #后面的元组,主要针对四维输入,平铺过程会出现五维的情况。
          data = data.reshape((n * data.shape[1], n * data.shape[3]) + data.shape[4:]) #reshape为正常图片格式
      
          plt.imshow(data); plt.axis('off')
    3. 绘制图像

      
      # the parameters are a list of [weights, biases] 可视化卷积核
      
      filters = net.params['conv1'][0].data
      vis_square(filters.transpose(0, 2, 3, 1)) # 注意需要对通道顺序进行转置
      
      # 可视化各层输出数据
      
      feat = net.blobs['conv1'].data[0, :36]
      vis_square(feat)
    4. 绘制全连接层的输出值

      feat = net.blobs['fc6'].data[0]
      plt.subplot(2, 1, 1)
      plt.plot(feat.flat) # np.flat 为数组一维迭代器
      plt.subplot(2, 1, 2)
      _ = plt.hist(feat.flat[feat.flat > 0], bins=100) # (大于零)的直方图,bins为柱数
    5. 绘制最终概率输出

      feat = net.blobs['prob'].data[0]
      plt.figure(figsize=(15, 3))
      plt.plot(feat.flat)

下一篇:Caffe实战之Python接口系列(二)Learning-LeNet

猜你喜欢

转载自blog.csdn.net/qq_38156052/article/details/80880713