海思3559AV100上运行自己训练的yolov3

1、简介

现在海思芯片上只支持将caffemodel转成wk文件,然而网上也没有caffe-yolov3,只能使用darknet-yolov3进行训练,然后将模型文件转换成caffemodel文件,再使用ruyistdio转成指令集的wk文件,就可以在板子上运行了。期间遇到的坑做一下记录。

遇到了一个是段错误(Segmentation fault)和精度损失问题,下面提供了解决方法

2、遇到的问题(价值所在)

2.1 出现Segmentation fault

将自己训练的darknet模型转成wk文件,在海思芯片上运行,只修改了SAMPLE_SVP_NNIE_Yolov3_SoftwareInit里面的 pstSoftWareParam->u32ClassNum,会出现下面的错误

解决方法

还要修改sample_svp_nnie_software.h中关于yolov3的参数设置,修改为5+classnum(自己类别的个数)

2.2 yolov3出现精度损失问题

主要原因是生成的wk参数没有设置对,在ruyistdio中将image_type中的RGB_order设置为RGB,如下图

2.3 在仿真需要修改prototxt文件

input: "data"
input_dim: 1
input_dim: 3
input_dim: 416
input_dim: 416

修改为

input: "data"
input_shape {
	dim: 1
	dim: 3
	dim: 416
	dim: 416
}

3、Darknet训练自己的数据集

4、将darknet模型转成caffemodel

在darknet训练完以后需要将模型转变成caffemodel文件。这个过程需要安装 pycaffe环境,同时还需要给caffe环境添加不支持层 upsample。

4.1 pycaffe环境的安装

https://blog.csdn.net/pursuit_zhangyu/article/details/104770610

4.2 添加不支持层upsample重新编译

下面的文件我提供了下载

链接:https://pan.baidu.com/s/1z07aqFuUpkFYPHmEf9TWtA 
提取码:yykw

增加include/caffe/layers/upsample_layer.hpp

#ifndef CAFFE_UPSAMPLE_LAYER_HPP_
#define CAFFE_UPSAMPLE_LAYER_HPP_
 
#include <vector>
 
#include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"
 
namespace caffe {
 
template <typename Dtype>
class UpsampleLayer : public Layer<Dtype> {
 public:
  explicit UpsampleLayer(const LayerParameter& param)
      : Layer<Dtype>(param) {}
  virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);
  virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);
 
  virtual inline const char* type() const { return "Upsample"; }
  virtual inline int MinBottomBlobs() const { return 1; }
  virtual inline int MaxBottomBlobs() const { return 1; }
  virtual inline int ExactNumTopBlobs() const { return 1; }
 
  virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);
  virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);
  virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
  virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
 
 private:
  int scale_;
};
 
 
 
}  // namespace caffe
 
#endif  // CAFFE_UPSAMPLE_LAYER_HPP_

增加src/caffe/layers/upsample_layer.cpp

#include <vector>
#include "caffe/layers/upsample_layer.hpp"
 
namespace caffe {
 
template <typename Dtype>
void UpsampleLayer<Dtype>::LayerSetUp(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  UpsampleParameter upsample_param = this->layer_param_.upsample_param();
  scale_ = upsample_param.scale();
}
 
template <typename Dtype>
void UpsampleLayer<Dtype>::Reshape(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  vector<int> out_shape;
  for (int i = 0; i < bottom[0]->num_axes(); i++) {
    out_shape.push_back(bottom[0]->shape(i));
  }
 
  out_shape[bottom[0]->num_axes() - 1] *= scale_;
  out_shape[bottom[0]->num_axes() - 2] *= scale_;
  top[0]->Reshape(out_shape);
}
 
template <typename Dtype>
void UpsampleLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
 
  int N = top[0]->shape(0);
  int C = top[0]->shape(1);
  int H = top[0]->shape(2);
  int W = top[0]->shape(3);
 
  const Dtype *input = bottom[0]->cpu_data();
  Dtype *output = top[0]->mutable_cpu_data();
  for (int n = 0; n < N; n++) {
    for (int c = 0; c < C; c++) {
      for (int h = 0; h < H; h++) {
        for (int w = 0; w < W; w++) {
          int nw = w/scale_;
          int nh = h/scale_;
          int out_idx = (((n * C + c) * H) + h) * W + w;
          int in_idx = (((n * C + c) * (H / scale_)) + nh) * (W / scale_) + nw;
          output[out_idx] = input[in_idx];
        }
      }
    }
  }
}
 
template <typename Dtype>
void UpsampleLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
  int N = bottom[0]->shape(0);
  int C = bottom[0]->shape(1);
  int H = bottom[0]->shape(2);
  int W = bottom[0]->shape(3);
  const Dtype *output_grad = top[0]->cpu_diff();
  Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
  caffe_set(bottom[0]->count(), Dtype(0), bottom_diff);
  for (int n = 0; n < N; n++) {
    for (int c = 0; c < C; c++) {
      for (int h = 0; h < H; h++) {
        for (int w = 0; w < W; w++) {
          for (int i = 0; i < scale_; i++) {
            for (int j = 0; j < scale_; j++) {
              int nw = w * scale_ + i;
              int nh = h * scale_ + j;
              int out_idx = (((n * C + c) * H) + h) * W + w;
              int in_idx = (((n * C + c) * (H * scale_))
                  + nh) * (W * scale_) + nw;
              bottom_diff[out_idx] += output_grad[in_idx];
            }
          }
        }
      }
    }
  }
}
 
#ifdef CPU_ONLY
STUB_GPU(UpsampleLayer);
#endif
 
INSTANTIATE_CLASS(UpsampleLayer);
REGISTER_LAYER_CLASS(Upsample);
 
}  // namespace caffe

增加src/caffe/layers/upsample_layer.cu

#include <vector>
 
#include "caffe/filler.hpp"
#include "caffe/layers/upsample_layer.hpp"
#include "caffe/util/math_functions.hpp"
 
namespace caffe {
 
__device__ int translate_idx(int ii, int d1, int d2, int d3, int scale_factor) {
  int x, y, z, w;
  w = ii % d3;
  ii = ii/d3;
  z = ii % d2;
  ii = ii/d2;
  y = ii % d1;
  ii = ii/d1;
  x = ii;
  w = w/scale_factor;
  z = z/scale_factor;
  d2 /= scale_factor;
  d3 /= scale_factor;
  return (((x*d1+y)*d2)+z)*d3+w;
}
 
__device__ int translate_idx_inv(
    int ii, int d1, int d2, int d3, int scale_factor, int off_x, int off_y) {
  int x, y, z, w;
  w = ii % d3;
  ii = ii/d3;
  z = ii % d2;
  ii = ii/d2;
  y = ii % d1;
  ii = ii/d1;
  x = ii;
  w = w*scale_factor+off_x;
  z = z*scale_factor+off_y;
  d2 *= scale_factor;
  d3 *= scale_factor;
  return (((x*d1+y)*d2)+z)*d3+w;
}
 
template <typename Dtype>
__global__ void upscale(const Dtype *input, Dtype *output,
        int no_elements, int scale_factor, int d1, int d2, int d3) {
  int ii = threadIdx.x + blockDim.x * blockIdx.x;
  if (ii >= no_elements) return;
  int ipidx = translate_idx(ii, d1, d2, d3, scale_factor);
  output[ii]=input[ipidx];
}
 
template <typename Dtype>
__global__ void downscale(Dtype *gradInput_data, const Dtype *gradOutput_data,
                          int no_elements, int scale_factor, int d1, int d2,
                          int d3) {
  int ii = threadIdx.x + blockDim.x * blockIdx.x;
  if (ii >= no_elements) return;
  for (int i = 0; i < scale_factor; i++) {
    for (int j = 0; j < scale_factor; j++) {
      int ipidx = translate_idx_inv(ii, d1, d2, d3, scale_factor, i, j);
      gradInput_data[ii] += gradOutput_data[ipidx];
    }
  }
}
 
 
 
template <typename Dtype>
void UpsampleLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  int d1, d2, d3;
 
  d1 = top[0]->shape(1);
  d2 = top[0]->shape(2);
  d3 = top[0]->shape(3);
 
  int no_elements = top[0]->count();
 
  upscale<Dtype>  // NOLINT_NEXT_LINE(whitespace/operators)
      <<<CAFFE_GET_BLOCKS(no_elements), CAFFE_CUDA_NUM_THREADS>>>(
      bottom[0]->gpu_data(),
      top[0]->mutable_gpu_data(), no_elements, scale_, d1, d2, d3);
}
 
template <typename Dtype>
void UpsampleLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
  int d1, d2, d3;
  Dtype* bottom_diff = bottom[0]->mutable_gpu_diff();
  d1 = bottom[0]->shape(1);
  d2 = bottom[0]->shape(2);
  d3 = bottom[0]->shape(3);
  int no_elements = bottom[0]->count();
  caffe_gpu_set(bottom[0]->count(), Dtype(0), bottom_diff);
  downscale<Dtype>  // NOLINT_NEXT_LINE(whitespace/operators)
      <<<CAFFE_GET_BLOCKS(no_elements), CAFFE_CUDA_NUM_THREADS>>>(
      bottom_diff, top[0]->gpu_diff(), no_elements, scale_, d1, d2, d3);
}
 
INSTANTIATE_LAYER_GPU_FUNCS(UpsampleLayer);
 
}  // namespace caffe

最后在src/caffe/proto/caffe.proto中增加

message LayerParameter {
 
           ……
 
  optional UpsampleParameter upsample_param = 148;
}
 
 
message UpsampleParameter {
  optional int32 scale = 1 [default = 1];
}

重新编译

make clean
make all -j
make py -j

4.3 转换工具

我将python2的代码改成了python3的了,下面我提供百度下载链接

链接:https://pan.baidu.com/s/1D133dWqyc71ZvXVGtOnKrA 
提取码:bzvb

python yolov3_2caffe.py darknet_model/yolov3_coco_416.cfg darknet_model/yolov3_coco_416.weights caffemodel/yolov3.prototxt caffemodel/yolov3.caffemodel

注意:我设置的是使用第2个gpu

4.4 可以测试转到caffe有没有精度损失

我测过没有任何损失问题

5、生成wk文件

 

6、仿真

如果需要仿真的话,如果是两个类别的话,作如下修改

仿真的步骤

1.首先build clean

2.release 编译

3.仿真

7、在板子上进行测试

代码修改,主要修改三个方面:

SAMPLE_SVP_NNIE_YOLOV3_EACH_BBOX_INFER_RESULT_NUM 是5+2(classnum)=7

如果是部分类别检测不出来sample_svp_nnie_software.c中找到static HI_S32 SVP_NNIE_Yolov3_GetResult,修改里面的

 

使用的SDK下载地址

链接:https://pan.baidu.com/s/1i3AjsZp_YfvyC2sQxRbSDQ 
提取码:ciei

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值