Caffe实战之Python接口系列(六)Net Surgery(Editing model parameters)

引言

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

目录

编辑模型参数

  • 通过编辑模型参数,可以将Caffe网络转换为您的特定需求。 网络的数据(data),梯度(diff)和参数(params)都在pycaffe中暴露。

1. 设计卷积核

  • 为了展示如何加载,操作和保存参数,将卷积核设计到一个只有单个卷积层的简单网络中。 该网络有两个blob,用于输入的data和用于卷积输出的conv以及用于卷积核权重和偏置的一个参数conv

    
    # Load the net, list its data and params, and filter an example image.
    
    caffe.set_mode_cpu()
    net = caffe.Net('net_surgery/conv.prototxt', caffe.TEST)
    print("blobs {}\nparams {}".format(net.blobs.keys(), net.params.keys()))
    
    
    # load image and prepare as a single input batch for Caffe
    
    im = np.array(caffe.io.load_image('images/cat_gray.jpg', color=False)).squeeze()
    plt.title("original image")
    plt.imshow(im)
    plt.axis('off')
    
    im_input = im[np.newaxis, np.newaxis, :, :]
    net.blobs['data'].reshape(*im_input.shape)
    net.blobs['data'].data[...] = im_input
  • 用高斯噪声初始化卷积权重,同时将偏置初始化为零。 这些随机卷积核的输出有点像边缘检测。
  • 提高卷积核的偏置将相应地提高其输出

    
    # pick first filter output
    
    conv0 = net.blobs['conv'].data[0, 0]
    print("pre-surgery output mean {:.2f}".format(conv0.mean()))
    
    # set first filter bias to 1
    
    net.params['conv'][1].data[0] = 1.
    net.forward()
    print("post-surgery output mean {:.2f}".format(conv0.mean()))
  • 改变卷积核权重更令人兴奋,因为我们可以分配任何的核,如高斯模糊,边缘的Sobel算子等等。 下面将第0个卷积核转换为高斯模糊,将第1和第2卷积核转换为Sobel算子的水平和垂直梯度。

    ksize = net.params['conv'][0].data.shape[2:]
    
    # make Gaussian blur
    
    sigma = 1.
    y, x = np.mgrid[-ksize[0]//2 + 1:ksize[0]//2 + 1, -ksize[1]//2 + 1:ksize[1]//2 + 1]
    g = np.exp(-((x**2 + y**2)/(2.0*sigma**2)))
    gaussian = (g / g.sum()).astype(np.float32)
    net.params['conv'][0].data[0] = gaussian
    
    # make Sobel operator for edge detection
    
    net.params['conv'][0].data[1:] = 0.
    sobel = np.array((-1, -2, -1, 0, 0, 0, 1, 2, 1), dtype=np.float32).reshape((3,3))
    net.params['conv'][0].data[1, 0, 1:-1, 1:-1] = sobel  # horizontal
    net.params['conv'][0].data[2, 0, 1:-1, 1:-1] = sobel.T  # vertical
    show_filters(net)

2. 将分类器转换为全卷积网络

  • 采用标准的Caffe Reference ImageNet模型“CaffeNet”并将其转换为完全卷积网,以便在大输入上进行高效,密集的推理。 该模型生成的分类图覆盖给定的输入大小而不是单个分类。 特别是451×451输入上的8×8分类图仅在3倍的时间内提供64倍的输出。 该计算通过分摊重叠感受域的计算来利用卷积网络(convnet)结构的内在效率。
  • 为此,我们将CaffeNet的InnerProduct矩阵乘法层转换为卷积层。 这是唯一的变化:其他层类型与空间大小无关。 卷积是平移不变的,激活是逐元素操作,等等。 通过在pool5上加上一个步幅为1的6×6卷积核,fc6内积变为卷积fc6-conv。 回到图像空间,这给出了每个227×227框的分类,其中步长为32像素。 请记住输出图/感受野大小的等式,output =(input - kernel_size)/ stride + 1,并计算索引详细信息以便清楚地理解。
  • 该架构的唯一改变是将全连接的分类器内积层更改为卷积层且卷积核大小是 6 x 6,因为参考模型分类器将pool5的36个元素作为输入且步长设置为1来密集分类。 请注意,这些层已重命名,以便Caffe在将层名称映射到预训练模型时不会尝试盲目加载旧参数。

    
    # Load the original network and extract the fully connected layers' parameters.
    
    net = caffe.Net('../models/bvlc_reference_caffenet/deploy.prototxt', 
                    '../models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel', 
                    caffe.TEST)
    params = ['fc6', 'fc7', 'fc8']
    
    # fc_params = {name: (weights, biases)}
    
    fc_params = {pr: (net.params[pr][0].data, net.params[pr][1].data) for pr in params}
    
    for fc in params:
        print '{} weights are {} dimensional and biases are {} dimensional'.format(fc, fc_params[fc][0].shape, fc_params[fc][1].shape)
  • 考虑内积参数的形状。 权重尺寸是输出和输入尺寸,而偏置尺寸是输出尺寸。

    
    # Load the fully convolutional network to transplant the parameters.
    
    net_full_conv = caffe.Net('net_surgery/bvlc_caffenet_full_conv.prototxt', 
                              '../models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel',
                              caffe.TEST)
    params_full_conv = ['fc6-conv', 'fc7-conv', 'fc8-conv']
    
    # conv_params = {name: (weights, biases)}
    
    conv_params = {pr: (net_full_conv.params[pr][0].data, net_full_conv.params[pr][1].data) for pr in params_full_conv}
    
    for conv in params_full_conv:
        print '{} weights are {} dimensional and biases are {} dimensional'.format(conv, conv_params[conv][0].shape, conv_params[conv][1].shape)
  • 卷积权重维度为output × input × height × width。 要将内积权重映射到卷积核,可以将平铺的内积矢量卷成channel × height × width卷积核矩阵中,但实际上它们在内存中是相同的(如row major数组),因此我们可以直接分配它们。 偏置与内积完全相同
  • 下面开始移植

    for pr, pr_conv in zip(params, params_full_conv):
        conv_params[pr_conv][0].flat = fc_params[pr][0].flat  # flat unrolls the arrays
        conv_params[pr_conv][1][...] = fc_params[pr][1]
  • 保存新的模型权重

    net_full_conv.save('net_surgery/bvlc_caffenet_full_conv.caffemodel')
  • 最后,让我们从示例猫图像中制作分类图,并将“虎猫”的置信度可视化为概率热图。 这给出了451×451输入的重叠区域的8x8预测。

    import numpy as np
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    
    # load input and configure preprocessing
    
    im = caffe.io.load_image('images/cat.jpg')
    transformer = caffe.io.Transformer({'data': net_full_conv.blobs['data'].data.shape})
    transformer.set_mean('data', np.load('../python/caffe/imagenet/ilsvrc_2012_mean.npy').mean(1).mean(1))
    transformer.set_transpose('data', (2,0,1))
    transformer.set_channel_swap('data', (2,1,0))
    transformer.set_raw_scale('data', 255.0)
    
    # make classification map by forward and print prediction indices at each location
    
    out = net_full_conv.forward_all(data=np.asarray([transformer.preprocess('data', im)]))
    print out['prob'][0].argmax(axis=0)
    
    # show net input and confidence map (probability of the top prediction at each location)
    
    plt.subplot(1, 2, 1)
    plt.imshow(transformer.deprocess('data', net_full_conv.blobs['data'].data[0]))
    plt.subplot(1, 2, 2)
    plt.imshow(out['prob'][0,281])
  • 分类包括各种猫 - 282 =虎猫,281 =虎斑猫,283 =波斯猫 - 以及狐狸和其他哺乳动物。
  • 通过这种方式,可以被提取为图像上的密集特征(例如,参见net_full_conv.blobs['fc6'].data),这可能比分类图本身更有用。
  • 请注意,此模型并不完全适用于滑动窗口检测,因为它是针对整个图像分类进行训练的。 不过它可以正常工作。 滑动窗口训练和微调可以通过定义滑动窗口的GT和损失来完成,以便为每个位置制作损失图并像往常一样解决。 (这是读者的练习。)

上一篇:Caffe实战之Python接口系列(五)Multilabel classification on PASCAL using python data-layers

下一篇:Caffe实战之Python接口系列(七)R-CNN detection

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值