基于caffe的量化模型训练与部署——训练篇

2023-05-16

为什么需要量化?

我们知道,cnn网络的前向计算瓶颈主要集中在卷积层,而卷积层的实质是大量的浮点数相乘、相加等运算操作,大量的浮点数计算限制了模型在低处理器或移动端等设备中的部署。如果能将浮点运算转换为整形运算,则cnn模型的前向处理速度将达到质的提升。

为什么量化有用?

关于深度神经网络的一个非常有意思的发现是:即使输入中包含大量的噪声,神经网络依然能处理的很好。深度网络的一个神奇特质是它们倾向于很好地应对输入中的高噪声。如果您考虑识别您刚拍摄的照片中的物体,网络必须忽略所有CCD噪音,光照变化以及它与之前看到的训练样例之间的其他非本质差异,并关注重要事项相似之处。这种能力意味着它们似乎将低精度计算视为另一种噪声源,并且即使使用包含较少信息的数字格式仍能产生准确的结果。

如何量化?

由于网络中主要的计算集中在卷积层,这里主要以卷积层的量化为例讲解。
量化需要完成的是将浮点型的输入值和网络参数值分别映射到一定范围内的整型数。假设我们要将网络参数和输入值量化为kbit,即对应的整型数值表述范围为 2 k 2^k 2k个。一种最常用的量化方法就是线性量化,即将一定范围内的浮点型数均匀量化成 2 k 2^k 2k个区间,每个区间对应一个整形数值,如下表为将[-1, 1]范围内的浮点数线性量化为2比特4个区间:

------------------------------
input         |        output
------------------------------
[-1.0,-0.5)   |          -2
[-0.5,0)      |          -1
[0,0.5)       |          0
[0.5,1.0]      |          1
------------------------------	

均匀量化需要明确被量化的浮点型数值的范围,通过对卷积层的输入和参数特性分析发现,这一数值范围其实是可以大致确定的:

  • 卷积层输入范围
    对于卷积层,其输入为上一层的输出,通常包含两种情况,一种是输入图像,另一种是经过激活函数的前一层卷积结果,所以卷积层的输入值的取值范围通常为非负数,故对应的量化到[0, 2 k 2^k 2k-1]中。
    I ∈ [ 0 , + ∞ ] I\in[0,+∞] I[0,+] ——> I q ∈ { 0 , 1 , 2 , . . . 2 k − 1 } Iq\in\{0,1,2,...2^k-1\} Iq{0,1,2,...2k1}
  • 卷积层参数范围
    而通过对常见网络的卷积层参数的可视化发现,卷积层参数基本呈现以0为中心轴,对称分布的状态,且最大值和最小值的绝对值基本接近,如下图所示,因此可以将参数量化到[-( 2 k / 2 2^k/2 2k/2), 2 k / 2 − 1 2^k/2-1 2k/21]中。
    W ∈ [ − m i n , + m a x ] W\in[-min,+max] W[min,+max] ——> W q ∈ { − ( 2 k / 2 ) , − ( 2 k / 2 ) + 1 , . . . 2 k / 2 − 1 } Wq\in\{-(2^k/2),-(2^k/2)+1,...2^k/2-1\} Wq{(2k/2),(2k/2)+1,...2k/21}
    在这里插入图片描述

通过统计大量的网络参数和输入的数值分布,在量化时我们可以确定输入和参数的大致正负边界(如网络参数基本落在[-1,1]区间,输入值基本落在[0,5]之间,对于大多数网络基本满足这一情况),对于落在边界外的少数数值,直接进行截断即可,这带来的噪声值是相对微弱的。

量化公式

我们知道,卷积层的前向计算公式可以表示为输入和卷积层参数的卷积运算,简化为:
O = I ∗ W O=I*W O=IW对于量化计算,我们希望找到一组对应的量化值 I q I^q Iq W q W^q Wq,使其满足:
O = I ∗ W ≈ α I q ∗ β W q = α β ( I q ∗ W q ) O=I*W≈\alpha I^q*\beta W^q=\alpha \beta (I^q*W^q) O=IWαIqβWq=αβ(IqWq)上式中, α \alpha α β \beta β是浮点型标量系数。
因此浮点型的卷积操作可以退化成对应量化值 I q I^q Iq W q W^q Wq的整型卷积操作,大大提升计算的效率。

  • 卷积层输入量化
    前面已经说过,我们可以采用最简单的线性均匀量化来确定上面所说的量化值,输入 I I I被量化到[0, 2 k 2^k 2k-1]区间,由均匀量化公式可得重建公式为:
    I ≈ I ~ = [ I ‾ − I m i n Q s I ] ∗ Q s I + I m i n (1) I≈ \widetilde{I}=[\cfrac{\overline{I}-I_{min}}{Qs_I}]*Qs_I+I_{min} \tag 1 II =[QsIIImin]QsI+Imin(1) 式中, Q s I Qs_I QsI为量化区间步长,[.]为取整公式 Q s I = I m a x − I m i n 2 k − 1 Qs_I = \cfrac{I_{max}-I_{min}}{2^k-1} QsI=2k1ImaxImin I ‾ \overline{I} I为截断的输入值
    I m i n i f   I < I m i n I ‾ = { I o t h e r s I m a x i f   I > I m a x \qquad \qquad \qquad I_{min} \qquad if \, I<I_{min} \\ \overline{I}=\{ I \qquad others \\ \qquad \qquad \qquad I_{max} \qquad if \, I>I_{max} IminifI<IminI={IothersImaxifI>Imax
    特别的,上面提到,通常卷积层的输入为非负数,因此有 I m i n = 0 I_{min}=0 Imin=0,上面的重建公式简化为
    I ≈ I ~ = [ I ‾ Q s I ] ∗ Q s I = I q ∗ Q s I I≈ \widetilde{I}=[\cfrac{\overline{I}}{Qs_I}]*Qs_I=I^q*Qs_I II =[QsII]QsI=IqQsI
    则有,输入 I I I对应的量化值为
    I q = [ I ‾ Q s I ] , α = Q s I (2) I^q=[\cfrac{\overline{I}}{Qs_I}],\alpha=Qs_I \tag 2 Iq=[QsII]α=QsI(2)

  • 卷积层参数量化
    同样的,对于每个 C ∗ K ∗ K C*K*K CKK维的卷积核参数,被均匀量化到[-( 2 k / 2 2^k/2 2k/2), 2 k / 2 − 1 2^k/2-1 2k/21]区间中,其量化后到重建公式为:
    W n ≈ W n ~ = [ W n ‾ Q s W n ] ∗ Q s W n (3) W_n≈\widetilde{W_n}=[\cfrac{\overline{W_n}}{Qs_Wn}]*Qs_Wn \tag 3 WnWn =[QsWnWn]QsWn(3) 式中, n ∈ { 1 , 2 , . . . N } n \in\{1,2,...N \} n{1,2,...N},N为输出通道数。 Q s W n Qs_Wn QsWn为量化区间步长,[.]为取整公式 Q s W n = 2 ∗ W n m a x 2 k − 2 Qs_Wn = \cfrac{2*Wn_{max}}{2^k-2} QsWn=2k22Wnmax W n m a x = ∣ W n ∣ m a x Wn_{max}=|W_n|_{max} Wnmax=Wnmax , W n ‾ \overline{W_n} Wn为截断的参数值
    − W n m a x i f   W n < − W n m a x W n ‾ = { W n o t h e r s W n m a x i f   W n > W n m a x \qquad \qquad \qquad \qquad \qquad-Wn_{max} \qquad if \, W_n<-Wn_{max} \\ \overline{W_n}=\{ W_n \qquad others \\ \qquad \qquad \qquad \qquad \qquad Wn_{max} \qquad if \, W_n>Wn_{max} WnmaxifWn<WnmaxWn={WnothersWnmaxifWn>Wnmax
    参数 W n Wn Wn对应的量化值为
    W n q = [ W n ‾ Q s W n ] , β = Q s W n (4) W_n^q=[\cfrac{\overline{W_n}}{Qs_Wn}],\beta=Qs_Wn \tag 4 Wnq=[QsWnWn]β=QsWn(4)

训练算法

量化训练的卷积层前向和后向计算基本改动不大,唯一的差别是用量化重建后的输入值和参数值代替原始值做计算,从而在训练的过程中最小化量化引起的误差,

  • 前向计算

:1.根据量化重建公式(1)将输入 I I I表示为量化后的重建值 I ~ \widetilde{I} I

:2. for each n in N:
根据量化重建公式(3)将卷积层参数 W n W_n Wn表示为量化后的重建值 W n ~ \widetilde{W_n} Wn

:3.用重建后的输入值和参数进行值卷积计算 O = I ~ ∗ W n ~ O=\widetilde{I}*\widetilde{W_n} O=I Wn


  • 反向传播

: 1.计算 ∂ L ∂ b i a s \cfrac{\partial L}{\partial bias} biasL
: 2.通过 I ~ \widetilde{I} I 计算 ∂ L ∂ W ~ \cfrac{\partial L}{\partial\widetilde{W}} W L,同时将被截断的 W ~ \widetilde{W} W 对应的梯度置零,避免其梯度传播
: 3.通过 W ~ \widetilde{W} W 计算 ∂ L ∂ I ~ \cfrac{\partial L}{\partial\widetilde{I}} I L,同时将被截断的 I ~ \widetilde{I} I 对应的梯度置零,避免其梯度传播


在caffe中实现量化

新增加conv_quantized_layer.cu/cpp/hpp
主要函数:
量化输入值

template <typename Dtype>
__global__ void binarize_kernel(const Dtype *x, int n, float maxcutoff, float mincutoff, float quantStep, Dtype *binary)
{
    int i = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
    if (i >= n) return;

      binary[i] = (x[i] >= maxcutoff) ? maxcutoff: ((x[i] < mincutoff) ? mincutoff : x[i]);
      Dtype temp = binary[i] - mincutoff;
      binary[i] = (round(temp / quantStep)) * quantStep + mincutoff;
}

template <typename Dtype>
void binarize_input_gpu(const Dtype *input, int n, int size, float maxcutoff, float mincutoff, int bit, Dtype *binary)
{
    //float maxcutoff = MAXCUTOFF_A;
    //float mincutoff = MINCUTOFF_A;
    float bitNum = pow(2,bit);
    float quantStep =  (maxcutoff - mincutoff) / (bitNum - 1);

      binarize_kernel<<<cuda_gridsize(n * size), BLOCK>>>(input, n * size, maxcutoff, mincutoff, quantStep, binary);
    
    check_error(cudaPeekAtLastError());
}

量化参数值

template <typename Dtype>
__global__ void binarize_weights_kernel(const Dtype *weights, int n, int size, float maxcutoff, float bitNum, Dtype *binary)
{
    int f = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
    if (f >= n) return;
    int i = 0;

    Dtype weight_temp;
    Dtype weight_max = -1.0f;
    Dtype quantStep = 0.0f;
    //float cutoffNew = 0.0f;
    for(i = 0; i < size; ++i)
    {
        weight_temp = fabs(weights[f*size + i]);
        weight_max = (weight_temp > weight_max) ? weight_temp : weight_max;
    }
    weight_max = (weight_max > maxcutoff) ? maxcutoff : weight_max;
    quantStep = 2 * weight_max / (bitNum - 2);
    //cutoffNew = weight_max - quantStep;

    for(i = 0; i < size; ++i)
    {
       weight_temp = weights[f*size + i];
       weight_temp = (weight_temp >= weight_max) ? (weight_max): ((weight_temp < -weight_max) ? -weight_max : weight_temp);
       binary[f*size + i] = round(weight_temp / quantStep) * quantStep;
    }
}

template <typename Dtype>
void binarize_weights_gpu(const Dtype *weights, int n, int size, float maxcutoff, float mincutoff, int bit, Dtype *binary)//n:kernel number size:c*kh*kw
{
    //printf("BLOCK = %d\n",BLOCK);
    //float maxcutoff = MAXCUTOFF_W;
    //float mincutoff = MINCUTOFF_W;
    float bitNum = pow(2,bit);

     binarize_weights_kernel<<<cuda_gridsize(n), BLOCK>>>(weights, n, size, maxcutoff, bitNum, binary);
    
    check_error(cudaPeekAtLastError());
}

前向计算

template <typename Dtype>
void ConvQuantizedLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top)
{


    //quantized weight
    const Dtype* weight = this->blobs_[0]->gpu_data();
    Dtype* xnor_weight = this->xnor_blobs_[0]->mutable_gpu_data();
    binarize_weights_gpu(weight, conv_out_channels_, kernel_dim_, MAXCUTOFF_W, MINCUTOFF_W, WBIT, xnor_weight);

    for (int i = 0; i < bottom.size(); ++i) {
        const Dtype* bottom_data = bottom[i]->gpu_data();

        //quantizing input
        Dtype* xnor_bottom_data = this->xnor_bottom_[i]->mutable_gpu_data();
        binarize_input_gpu(bottom_data, num_, bottom_dim_, MAXCUTOFF_A, MINCUTOFF_A, ABIT, xnor_bottom_data);

        Dtype* top_data = top[i]->mutable_gpu_data();
        for (int n = 0; n < this->num_; ++n) {
            this->forward_gpu_gemm(xnor_bottom_data + n * this->bottom_dim_,
                    xnor_weight, top_data + n * this->top_dim_);
            if (this->bias_term_) {
                const Dtype* bias = this->blobs_[1]->gpu_data();
                this->forward_gpu_bias(top_data + n * this->top_dim_, bias);
            }
        }
    }
}

后向传播

template <typename Dtype>
void ConvQuantizedLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom)
{
  const Dtype* weight = this->blobs_[0]->gpu_data();
  Dtype* weight_diff = this->blobs_[0]->mutable_gpu_diff();
  const Dtype* xnor_weight = this->xnor_blobs_[0]->gpu_data();

  for (int i = 0; i < top.size(); ++i)
  {
    const Dtype* top_diff = top[i]->gpu_diff();
    // d(loss)/d(bias)
    if (this->bias_term_ && this->param_propagate_down_[1])
    {
      Dtype* bias_diff = this->blobs_[1]->mutable_gpu_diff();
      for (int n = 0; n < this->num_; ++n)
      {
        this->backward_gpu_bias(bias_diff, top_diff + n * this->top_dim_);
      }
    }
    //d(loss)/d(weight) and d(loss)/d(input)
    if (this->param_propagate_down_[0] || propagate_down[i])
    {
      const Dtype* bottom_data = bottom[i]->gpu_data();
      Dtype* bottom_diff = bottom[i]->mutable_gpu_diff();

      const Dtype* xnor_bottom_data = this->xnor_bottom_[i]->gpu_data();

      for (int n = 0; n < this->num_; ++n)  //for each batchSize
      {
        // gradient w.r.t. weight. Note that we will accumulate diffs.
        if (this->param_propagate_down_[0])
        {
            //d(loss)/d(weight_xnor)
            this->weight_gpu_gemm(xnor_bottom_data + n * this->bottom_dim_,
                top_diff + n * this->top_dim_, weight_diff);

            //d(loss)/d(weight) cut diff
            gradient_array_ongpu_xnor(weight,conv_out_channels_*kernel_dim_,weight_diff,MAXCUTOFF_W,MINCUTOFF_W);

        }
        // gradient w.r.t. bottom data.
        if (propagate_down[i])
        {
            //d(loss)/d(input_xnor)
            this->backward_gpu_gemm(top_diff + n * this->top_dim_, xnor_weight,
                bottom_diff + n * this->bottom_dim_);

            //d(loss)/d(input)
            gradient_array_ongpu_xnor(bottom_data,num_*bottom_dim_,bottom_diff,MAXCUTOFF_A,MINCUTOFF_A);
        }
      }
    }
  }// top.size
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于caffe的量化模型训练与部署——训练篇 的相关文章

  • mnist example for lstm in caffe

    下面给出在caffe中使用lstm的一个例子 其中数据集采用mnist 为了实现mnist数据的序列话 将mnist的每一行看成一帧 每一列则就是该帧的特征矢量 在使用lstm时 一定要注意clip markers 每个序列以0开始 后面接
  • Windows7 64bit VS2013 Caffe test MNIST操作步骤

    在http blog csdn net fengbingchun article details 49849225中用Caffe对MNIST数据库进行训练 产生了model 下面介绍下如何将产生的model应用在实际的数字图像识别中 用到的
  • Window下用caffe实现MNIST训练

    本博包含MNIST原始数据的格式转化 以及分类训练 1 数据转化 Caffe源码中src caffe caffe examples mnist convert mnist data cpp提供的实现代码并不能直接在Windows下运行 这里
  • Caffe可以直接对图像的像素进行分类吗?

    我想将图像的像素分类为 是街道 或 不是街道 我有一些训练数据KITTI数据集我看到 Caffe 有一个IMAGE DATA图层类型 标签以与输入图像大小相同的图像形式存在 除了 Caffe 之外 我解决这个问题的第一个想法是在应该分类的像
  • 如何验证 CuDNN 安装?

    我搜索了很多地方 但我得到的只是如何安装它 而不是如何验证它是否已安装 我可以验证我的 NVIDIA 驱动程序是否已安装 并且 CUDA 是否已安装 但我不知道如何验证 CuDNN 是否已安装 非常感谢您的帮助 谢谢 PS 这是用于咖啡实现
  • 检查失败:mdb_status == 0 (2 vs. 0) 没有这样的文件或目录

    我在训练数据时收到以下错误 我已经尝试了互联网上给出的所有解决方案 但似乎没有一个对我有用 我已检查 lmdb 文件的路径和大小不为零 但问题仍然存在 我不知道如何解决这个问题 pooling I0411 12 42 53 114141 2
  • 咖啡 | solver.prototxt值设置策略

    在 Caffe 上 我正在尝试实现一个用于语义分割的全卷积网络 我想知道是否有一个具体的策略来设置你的 solver prototxt 以下超参数的值 测试迭代器 测试间隔 迭代大小 max iter 这是否取决于您的训练集的图像数量 如果
  • 如何修改Imagenet Caffe模型?

    我想修改 ImageNet caffe 模型 如下所述 由于时间网络的输入通道数与此不同 空间网络 20 vs 3 我们对 ImageNet 模型滤波器进行平均 先跨过通道一层 然后复制平均结果 20 时间网络的初始化 我的问题是如何才能达
  • 如何在caffe中将多个N维数组输入到网络中?

    我想在 caffe 中创建一个用于语义分割的自定义损失层 需要多个输入 我希望这个损失函数有一个额外的输入因子 以惩罚小物体的漏检 为此 我创建了一个图像 GT 其中每个像素都包含一个权重 如果像素属于小物体 则权重较高 我是 caffe
  • CNN 上的快速损失收敛意味着什么?

    我正在两个不同的深度学习库 Caffe e Tensorflow 中训练两个 CNN AlexNet e GoogLeNet 该网络由每个图书馆的开发团队实施 here https github com BVLC caffe tree ma
  • 在 Python 中未安装 caffe 的情况下从 .caffemodel 中提取权重

    有没有一种相对简单的方法可以从 Caffe Zoo 中的众多预训练模型之一中提取 Python 中的权重没有咖啡 也不是 pyCaffe 即解析 caffemodel转换为 hdf5 numpy 或任何 Python 可以读取的格式 我找到
  • 未知的底部 blob“数据”(层“conv1”,底部索引 0)

    尝试在我自己的数据集上训练 LeNet 我从长一维矢量数据集生成了 HD F5 文件 并创建了 HDF5 数据层 如下所示 我对顶部 blob 的命名与生成 HDF5 时的命名相同 name Test net layer name data
  • Caffe 中的欧几里得损失层

    我目前正在尝试在 caffe 中实现我自己的损失层 在尝试这样做的同时 我使用其他层作为参考 然而 让我困惑的一件事是使用top 0 gt cpu diff in Backward cpu 我将使用EuclideanLossLayer作为参
  • 如何在非 NVIDIA 设置上加速深度学习?

    由于我只有 AMD A10 7850 APU 并且没有资金购买 800 1200 美元的 NVIDIA 显卡 因此我正在尝试利用我拥有的资源通过 TensorFlow Keras 加速深度学习 最初 我使用了 Tensorflow 的预编译
  • Caffe的Python接口:“导入caffe”时出错

    我正在尝试在 Caffe 的 Python 界面中运行它 我已经运行了命令make pycaffe在 caffe 目录中并且运行良好 现在 当我运行命令时import caffe在终端的 python 环境中 Ubuntu 14 04 我收
  • Caffe 快照:.solverstate 与 .caffemodel

    训练网络时 每 N 次迭代拍摄的快照有两种形式 一个是 solverstate 文件 我想它就像它听起来的那样 存储损失函数和梯度的状态等 另一个是 caffemodel 文件 我知道它存储训练后的参数 如果您想要预训练的模型 caffem
  • 在 ubuntu 16.04 中安装 Caffe 时遇到困难

    操作系统 ubuntu 16 04 CUDA 7 5 库德恩 5 我正在关注this https github com BVLC caffe wiki Ubuntu 16 04 or 15 10 OpenCV 3 1 Installatio
  • 如何更改CUDA版本

    我在编译修改后的caffe版本时遇到了这个错误 OpenCV static library was compiled with CUDA 7 5 support Please use the same version or rebuild
  • Caffe/pyCaffe:设置所有 GPU

    是否可以为Caffe 尤其是pyCaffe 设置所有GPU 就像是 caffe train solver examples mnist lenet solver prototxt gpu all 这两个分支现在都支持多 GPU 一段时间了
  • 如何在 CAFFE 的新网络中重复使用同一网络两次

    我有一个预训练的网络 我们称之为N 我想在新网络中使用两次 有人知道如何复制吗 然后我想为每个副本分配不同的学习率 例如 N1是第一个副本N N2是第二个副本N 新网络可能如下所示 N1 gt joint ip N2 gt layer 我知

随机推荐

  • [Ubuntu] 可用云盘-尝试记录

    Ubuntu可用云盘 xff1a https github com Aruelius cloud189 说明 xff1a 这是一个调用天翼云API的开源命令行工具 xff0c 基于Python编写 xff1b 天翼云官方没有客户端支持Lin
  • 【无人机】基于遗传算法实现无人机编队位置规划附matlab代码

    1 内容介绍 现代社会的无人机成本造价低 不易损耗 轻巧灵便 易躲藏 能精确打击 目标这些特点 xff0c 使其在一些高危任务中发挥了不可替代的作用 5 无人机的用处主要有两种 xff1a 民用和军事 在民用方面 xff0c 我们可以运用无
  • 【路径规划】基于DWA实现机器人动态避障附matlab代码

    1 内容介绍 DWA 算法是基于机器人运动学与动力学理论的一种局部避障算法 xff0c 它将对机器人的位置控制转换为对机器人的速度控制 DWA 算法可以概括为三步 一是根据机器人自身的限制以及环境制约将速度的采样空间约束在一定范围内 二是根
  • 飞控pixhawk硬件框架

    本文转载于 xff1a https blog csdn net csshuke article details 78952026 xfeff xfeff 1 Phxhawk连接线路 2 Phxhawk硬件芯片列表 处理器 STM32F427
  • PCB_layout_misc

    AD的规则设置参考 https blog csdn net geek monkey article details 80249217 一些PCB厂家的工艺 嘉立创https www jlc com portal vtechnology ht
  • 怎样把经纬度坐标转换为空间直角坐标

    怎样把经纬度坐标转换为空间直角坐标 假设你的空间直角坐标以地球球心为原点 原点到北极为正z轴 原点到经纬度 0 0 为正x轴 那么纬度a 北正南负 经度b 东正西负 的空间直角坐标为 x 61 Rcos a cos b y 61 Rcos
  • APM添加参数

    APM添加参数 参考 https ardupilot org dev docs code overview adding a new parameter html 添加应用参数模块 例如 battery Parameters h k par
  • pixhawk6x/5x 电源插座/插头的型号

    型号 xff1a molex CLIK Mate 5024430670 5024390600
  • intellij idea: git tag操作 及 master branch相互合并操作

    git tag和git branches区别 xff1f tag就像是里程碑标志的一个点 branch是一个新的征程的一条线 tag是静态的 是只读的 不能修改 而branch是要往前走的 稳定版本备份用tag 新功能开发多人用branch
  • C++之STL和Boost

    最近一年我电话面试了数十位 C 43 43 应聘者 xff0c 惯用的暖场问题是 工作中使用过 STL 的哪些组件 xff1f 使用过 Boost 的哪些组件 xff1f 得到的答案大多集中在 vector map 和 shared ptr
  • ubuntu 下安装intel realsense驱动

    在安装之前一定要确保系统是ubuntu 14 04 3 64位 xff01 在安装之前一定要确保系统是ubuntu 14 04 3 64位 xff01 在安装之前一定要确保系统是ubuntu 14 04 3 64位 xff01 重要的事情说
  • windows下安装numpy,scipy遇到的问题总结

    最近开始研究3D手势识别 xff0c 下载的源码包是基于python的 xff0c 需要用到扩展包numpy scipy等 xff0c 安装过程汇总遇到的问题总结如下 xff1a 1 安装numpy 下载numpy编译包 xff0c 进入该
  • Linux大数据处理踩坑实录

    最近开发需要在linux服务器上做大数据处理 xff0c 由于对Linux开发并不是很熟悉 xff0c 因此踩了很多坑 xff0c 先作如下记录 xff1a 1 bash shell实现多进程 背景如下 需要从hadoop的hdfs上向服务
  • Deep Compression阅读理解及Caffe源码修改

    更新 xff1a 没想到这篇文章写出后有这么多人关注和索要源码 xff0c 有点受宠若惊 说来惭愧 xff0c 这个工作当时做的很粗糙 xff0c 源码修改的比较乱 xff0c 所以一直不太好拿出手 最近终于有时间整理了一下代码并开源出来了
  • Tensorflow 离线安装跳坑总结

    TensorFlow作为目前最被看好的深度学习开源框架 xff0c 又顶着Google爸爸的光环 xff0c 使得很多CNN网络的部署都基于此框架 最近开始研究GAN xff08 生成对抗网络 xff09 xff0c 鉴于大部分源码都基于T
  • ARM NEON常用函数总结

    NEON 技术是 ARM Cortex A 系列处理器的 128 位 SIMD xff08 单指令 xff0c 多数据 xff09 架构扩展 xff0c 旨在为消费性多媒体应用程序提供灵活 强大的加速功能 xff0c 从而显著改善用户体验
  • TensorRT cuda8.0 cudnn 7.0.5 tar包安装

    总体步骤参考这篇文章 https zhuanlan zhihu com p 35468450 1 准备环境 TensorRT 依赖cuda和cudnn xff0c 且根据下载的TensorRT版本 xff0c 需要严格保证cuda和cudn
  • caffe模型TensorRT部署实践(一)

    参考代码 TensorRT安装包下的samples sampleMNIST sampleMNIST cpp 1 设置使用的gpu id xff0c 如果不设置 xff0c 默认使用第0块 cudaSetDevice 3 set device
  • Ubuntu关于串口的操作(查看串口信息、串口助手、串口权限)

    一 查看本机串口信息 1 串口是否在使用 串口在 dev 目录中 xff0c 查看串口是否在使用 xff0c 可以用命令 ls l dev ttyUSB0 说明 xff1a ls l xff1a 是查看目录的命令 xff0c 直接用ls或l
  • 基于caffe的量化模型训练与部署——训练篇

    为什么需要量化 xff1f 我们知道 xff0c cnn网络的前向计算瓶颈主要集中在卷积层 xff0c 而卷积层的实质是大量的浮点数相乘 相加等运算操作 xff0c 大量的浮点数计算限制了模型在低处理器或移动端等设备中的部署 如果能将浮点运