在纸Girshick,R 快速RCNN(ICCV 2015) ,章节“3.1截断SVD为更快的检测”中,作者提出了使用SVD特技减少完全连接层的尺寸和计算时间。
给定一个训练模型( deploy.prototxt
和weights.caffemodel
),我该如何使用这一招用截短一个更换一个完全连接层?
在纸Girshick,R 快速RCNN(ICCV 2015) ,章节“3.1截断SVD为更快的检测”中,作者提出了使用SVD特技减少完全连接层的尺寸和计算时间。
给定一个训练模型( deploy.prototxt
和weights.caffemodel
),我该如何使用这一招用截短一个更换一个完全连接层?
一些线性代数的背景
奇异值分解( SVD )是任何基质的分解W
分成三个矩阵:
W = U S V*
其中U
和V
均为邻位正常矩阵, S
是对角线与在降低对角大小的元件。 一个SVD有趣的特性是,它可以轻松地近似W
以较低的秩矩阵:假设您截断S
只具有其k
领先的元素(而不是在对角线上的所有元素),那么
W_app = W S_trunc V*
是秩k
的近似W
。
使用SVD来近似完全连接层
假设我们有一个模型deploy_full.prototxt
具有完全连接层
# ... some layers here
layer {
name: "fc_orig"
type: "InnerProduct"
bottom: "in"
top: "out"
inner_product_param {
num_output: 1000
# more params...
}
# some more...
}
# more layers...
此外,我们有trained_weights_full.caffemodel
-对训练有素的参数deploy_full.prototxt
模型。
复制deploy_full.protoxt
到deploy_svd.protoxt
和您选择的编辑器打开它。 用这些两层的完全连接层:
layer { name: "fc_svd_U" type: "InnerProduct" bottom: "in" # same input top: "svd_interim" inner_product_param { num_output: 20 # approximate with k = 20 rank matrix bias_term: false # more params... } # some more... } # NO activation layer here! layer { name: "fc_svd_V" type: "InnerProduct" bottom: "svd_interim" top: "out" # same output inner_product_param { num_output: 1000 # original number of outputs # more params... } # some more... }
在Python中,小净的手术 :
import caffe import numpy as np orig_net = caffe.Net('deploy_full.prototxt', 'trained_weights_full.caffemodel', caffe.TEST) svd_net = caffe.Net('deploy_svd.prototxt', 'trained_weights_full.caffemodel', caffe.TEST) # get the original weight matrix W = np.array( orig_net.params['fc_orig'][0].data ) # SVD decomposition k = 20 # same as num_ouput of fc_svd_U U, s, V = np.linalg.svd(W) S = np.zeros((U.shape[0], k), dtype='f4') S[:k,:k] = s[:k] # taking only leading k singular values # assign weight to svd net svd_net.params['fc_svd_U'][0].data[...] = np.dot(U,S) svd_net.params['fc_svd_V'][0].data[...] = V[:k,:] svd_net.params['fc_svd_V'][1].data[...] = orig_net.params['fc_orig'][1].data # same bias # save the new weights svd_net.save('trained_weights_svd.caffemodel')
现在,我们已经deploy_svd.prototxt
与trained_weights_svd.caffemodel
与远不如乘法,和权重接近原净。
事实上,罗斯Girshick的PY-快rcnn回购包括SVD的步骤实现: compress_net.py
。
顺便说一句,你通常需要微调压缩模式恢复精度(或更复杂的方式来压缩,例如参见“ 加快了分类和检测非常深卷积网络 ”,张某等人)。
另外,我scipy.linalg.svd工作比numpy的的SVD更快。