在论文Girshick, R Fast-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 = U 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...
}
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
,它们的乘积和权重都远小于原始网络。关于machine-learning - 如何使用截断的SVD减少完全连接的(`“InnerProduct”`)层,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40480827/