gpt4 book ai didi

machine-learning - 如何使用截断的 SVD 减少全连接 (`"InnerProduct"`) 层

转载 作者:行者123 更新时间:2023-11-30 08:26:22 24 4
gpt4 key购买 nike

论文中Girshick, R Fast-RCNN (ICCV 2015) ,“3.1 Truncated SVD for FasterDetection”一节,作者建议使用SVD减少全连接层的大小和计算时间的技巧。

给定一个经过训练的模型(deploy.prototxtweights.caffemodel),我如何使用这个技巧来替换全连接层有一个被截断的吗?

最佳答案

一些线性代数背景
奇异值分解 ( SVD ) 是将任意矩阵 W 分解为三个矩阵:

W = U S V*

其中 UV 是正交矩阵,S 是对角线,对角线上元素的量值递减。SVD 的有趣特性之一是它允许使用较低秩矩阵轻松逼近 W:假设您截断 S 使其仅具有其 k > 前导元素(而不是对角线上的所有元素)然后

W_app = U S_trunc V*

W的等级k近似值。

使用 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 模型的训练参数。

  1. 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...
    }
  2. 在Python中,一点net surgery :

    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.prototxttrained_weights_svd.caffemodel,它可以用更少的乘法和权重来近似原始网络。

关于machine-learning - 如何使用截断的 SVD 减少全连接 (`"InnerProduct"`) 层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40480827/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com