SimpleHumanPose代码及原理分析(三)-- loss损失函数

SimpleHumanPose代码及原理分析(三)-- loss损失函数

在上一篇blog中,已经把SimpleHumanPose的数据前处理部分给搞定了,具体可参见:SimpleHumanPose代码及原理分析(二)-- data与label前处理
简单的进行总结一下:
首先,默认输入的图片大小为256*256的,然后backbone为resnet。图片首先从256的shape一直进行下卷积到16,然后从16通过上卷积(这个上卷积才是SimpleHumanPose的核心)到64。就比如说,输入的shape为(16,3,256,256)(16表示的是batch_size,3表示的是图片的维度,256表示的是resize之后图片的长宽大小,这里由于是用caffe框架的,所以形式为bcwh,而不是通常tf中的bwhc形式),通过网络结构(网络结构可参见:Resnet网络实现)最终得到的feature map的shape为(16,points,64,64),这里第二个维度就是你要预测关键点的个数,该数要与生成的heatmap label的channels保持一致,不然后续进行损失函数计算的时候会报错。
代码:

#include <vector>
#include "caffe/layers/keypoint_L2_loss_layer.hpp"
#include "caffe/util/math_functions.hpp"

namespace caffe {
    template<typename Dtype>
    void KeypointL2LossLayer<Dtype>::Reshape(
            const vector<Blob<Dtype> *> &bottom, const vector<Blob<Dtype> *> &top) {
        LossLayer<Dtype>::Reshape(bottom, top);
		//对输入的两个向量:模型生成的heatmap与我们自主制作的label的heatmap  进行维度比较判断
        CHECK_EQ(bottom[0]->num(),bottom[1]->num())<<"Inputs must have the same num.";
        CHECK_EQ(bottom[0]->channels(),bottom[1]->channels())<<"Inputs must have the same channels.";
        CHECK_EQ(bottom[0]->height(),bottom[1]->height())<<"Inputs must have the same height.";
        CHECK_EQ(bottom[0]->width(),bottom[1]->width())<<"Inputs must have the same width.";
        diff_.ReshapeLike(*bottom[0]);
    }
	//改写前向处理
    template<typename Dtype>
    void KeypointL2LossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype> *> &bottom,
                                                 const vector<Blob<Dtype> *> &top) {
        int count = bottom[0]->count(); //表示第一路输入进来的heatmap的总维度乘积:B * C * H * W
        int n = bottom[0]->num(); //表示的是batchsize
        int c = bottom[0]->channels(); //表示的是c
        int dim = bottom[0]->count(2); //表示的是h
        caffe_sub(
                count,
                bottom[0]->cpu_data(),
                bottom[1]->cpu_data(),
                diff_.mutable_cpu_data());//两个(b,c,h,w)的向量进行逐位相减,生成的diff_的shape也是(b,c,h,w)
        Dtype* diff_data=diff_.mutable_cpu_data();//将相减之后所得到的结果diff存放到cpu中
        const Dtype* label_data=bottom[1]->cpu_data(); //将label生成的heatmap存放到cpu中
        Dtype loss=0; //定义每个channels总损失变量
        for(int j=0;j<c;++j) //遍历每个channels维度
        {
            Dtype joint_loss=0; //定义单个关键点的loss变量
            for(int i=0;i<n;++i) //遍历每个batchsize
            {
                if(label_data[(i*c+j)*dim] < 0)
                {
                    for(int k=0;k<dim;++k)
                    {
                        diff_data[(i*c+j)*dim+k]=0;
                    }
                }
                else
                {
                    for(int k=0;k<dim;++k)
                    {
                        joint_loss+=diff_data[(i*c+j)*dim+k]*diff_data[(i*c+j)*dim+k]; //均方差计算
                    }
                }
            }
            loss+=joint_loss/n/dim; //每个channels的平均损失
        }
    //改写反向传播函数
    template<typename Dtype>
    void KeypointL2LossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype> *> &top,
                                                  const vector<bool> &propagate_down,
                                                  const vector<Blob<Dtype> *> &bottom) {
        int n = bottom[0]->num();
        int c = bottom[0]->channels();
        int dim = bottom[0]->count(2);
        Dtype* diff_data=diff_.mutable_cpu_data();
        for (int id = 0; id < 2; ++id)
        {
            if (propagate_down[id])
            {
                const Dtype sign = (id == 0) ? 1 : -1;
                const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[id]->count();
                Dtype *bottom_diff=bottom[id]->mutable_cpu_data();
                for(int j=0;j<c;++j)
                {
                    for(int i=0;i<n;++i)
                    {
                        for(int k=0;k<dim;++k)
                        {
                            bottom_diff[(i*c+j)*dim+k]=diff_data[(i*c+j)*dim+k]*alpha;
                        }
                    }
                }
            }
        }
#ifdef CPU_ONLY
    STUB_GPU(KeypointL2LossLayer);
#endif

    INSTANTIATE_CLASS(KeypointL2LossLayer);

    REGISTER_LAYER_CLASS(KeypointL2Loss);

}  // namespace caffe
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进我的收藏吃灰吧~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值