其实我前面四篇实现了三种残差:

1,out +=x,out =relu(out)

2,out =relu(out),out +=x

3,pytorch版本:(c++ cudnn替代实现)

class ResidualBlock(nn.Module):
    def __init__(self, inchannel, outchannel, stride=1):
        super(ResidualBlock, self).__init__()
        self.left = nn.Sequential(
            nn.Conv2d(inchannel, outchannel, kernel_size=3, stride=stride, padding=1, bias=False),
            nn.BatchNorm2d(outchannel),
            nn.ReLU(inplace=True),
            nn.Conv2d(outchannel, outchannel, kernel_size=3, stride=1, padding=1, bias=False),
            nn.BatchNorm2d(outchannel)
        )
        self.shortcut = nn.Sequential()
        if stride != 1 or inchannel != outchannel:
            self.shortcut = nn.Sequential(
                nn.Conv2d(inchannel, outchannel, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(outchannel)
            )

    def forward(self, x):
        out = self.left(x)
        out += self.shortcut(x)
        out = F.relu(out)
        return out
————————————————

其实今天早上,我顺便在虚线残差yolov3版本上,改了一个yolov3实线残差版本,测试可以用!成绩略有下降!(或许是几种残差类混在一起用的缘故,或者是yolo有问题,这是我的直觉,反向传播中他用output,我用input,根据数学推导和查看cpu走过来的版本,应该是ds(s2.data))没关系,神经网络最有魅力的就是如此,只要不是致命错误,他是会出成绩,而且不会崩溃!学习优秀,保持自我,难度很大!神经网络和人的意识一样,轻易不会崩溃!这也是人生精髓所在!最难也在此,逻辑和情感在人生中处处熠熠生辉!享受这样的过程吧!能说清楚,就说清楚,说不清楚,就保持探索的乐趣!

轮次:15
learn rate:0.0001
时间: 32458.498047 ms
train Classification result: 35.89% ok (used 49984 images)
时间: 2491.056885 ms
Test Classification result: 9.99% ok (used 9984 images)
轮次:16
learn rate:0.0001
时间: 32208.925781 ms
train Classification result: 38.80% ok (used 49984 images)
时间: 2488.377930 ms
Test Classification result: 10.02% ok (used 9984 images)
轮次:17
learn rate:0.0001
时间: 32884.285156 ms
train Classification result: 40.47% ok (used 49984 images)
时间: 2713.406982 ms
Test Classification result: 10.01% ok (used 9984 images)
轮次:18
learn rate:0.0001
时间: 32369.666016 ms
train Classification result: 42.47% ok (used 49984 images)
时间: 2754.810059 ms
Test Classification result: 9.99% ok (used 9984 images)
轮次:19
learn rate:0.0001
时间: 32076.615234 ms
train Classification result: 43.46% ok (used 49984 images)
时间: 2479.541016 ms
Test Classification result: 10.00% ok (used 9984 images)
轮次:20
learn rate:1e-05
时间: 32186.339844 ms
train Classification result: 45.74% ok (used 49984 images)
时间: 2490.629883 ms
Test Classification result: 65.30% ok (used 9984 images)
轮次:21
learn rate:1e-05
时间: 32510.169922 ms
train Classification result: 46.01% ok (used 49984 images)
时间: 2530.877930 ms
Test Classification result:
65.53% ok (used 9984 images)
轮次:22
learn rate:1e-05
时间: 32729.812500 ms
train Classification result: 46.20% ok (used 49984 images)
时间: 2713.955078 ms
Test Classification result:
65.52% ok (used 9984 images)
轮次:23
learn rate:1e-05
时间: 32674.888672 ms
train Classification result: 46.23% ok (used 49984 images)
时间: 2521.415039 ms
Test Classification result: 64.38% ok (used 9984 images)

class ShixianResidualyolo :public Layer {
public:
    ShixianResidualyolo(cudnnHandle_t& cudnn_, int batch_, int c, int h, int w) : cudnn(cudnn_), batch(batch_)
        , _c(c), _h(h), _w(w) {

        layers.emplace_back(std::make_shared<Conv2D>(cudnn, batch, _c,  _c, _h, _w, 3, 1, 1));
        layers.emplace_back(std::make_shared<BN>(cudnn, batch,  _c, _h , _w ));
        layers.emplace_back(std::make_shared<LeakyRL>(cudnn, batch,  _c, _h , _w ));        
        layers.emplace_back(std::make_shared<Conv2D>(cudnn, batch,  _c,  _c, _h , _w , 3, 1, 1));
        layers.emplace_back(std::make_shared<BN>(cudnn, batch, _c, _h, _w));
        layers.emplace_back(std::make_shared<LeakyRL>(cudnn, batch, _c, _h, _w));//20260710收到darknet的启发1506

        cudaMalloc(&output, batch * _c * _h * _w  * sizeof(float));
        cudaMalloc(&input2, batch * _c * _h * _w * sizeof(float));

        
        cudaMalloc(&d_residual, batch * _c * _h * _w * sizeof(float));
    
        cudaMalloc(&grad_input, batch * _c * _h * _w * sizeof(float));

    
    }
    void forward(float* input_)override {
        

        input = input_;
        input2 = input_;

    
        for (const auto& l : layers) {
            l->forward(input);
            input = l->get_output();//这里的input与input2的nchw相同
        }

        int    NN = batch * _c * _h * _w;
    
        shortcut_gpu(batch, _w, _h, _c, input2, _w , _h , _c , input);
        cudaMemcpy(output, input, sizeof(float) * NN, cudaMemcpyDeviceToDevice);
        error_handling(cudaGetLastError());

    }
    void forward2(float* input_)override {//这里的虚线残差比lenet中复杂,w,h不一样,c也不一样!202609110724

    
        input = input_;
        input2 = input_;
        
        for (const auto& l : layers) {
            l->forward2(input);
            input = l->get_output();
        }
        int    NN = batch * _c * _h * _w ;

        
        shortcut_gpu(batch, _w, _h, _c, input2, _w , _h , _c , input);
        cudaMemcpy(output, input, sizeof(float) * NN, cudaMemcpyDeviceToDevice);
        error_handling(cudaGetLastError());
    }

    void backward(float* grad_output)override {//虚线反向传播明天继续!202609101937,虚线和实线yolo v3残差块都已经实现202609130729
        float* grad = grad_output;
        float* grad备用 = grad_output;
    

        for (int i = layers.size() - 1; i >= 0; i--) {
            layers[i]->backward(grad);
            grad = layers[i]->get_grad_input();
        }// batch, _c, _h , _w ,正路已经到达,


        int    NN = batch * _c * _h * _w ;


        int threads = 256;
        int blocks = (NN + threads - 1) / threads;

        
        mul << <blocks, threads >> > (grad备用, output, d_residual, NN);//略有不同202609130730
        error_handling(cudaGetLastError());
        
        shortcut_gpu(batch, _w , _h , _c , d_residual, _w, _h, _c, grad);
        cudaMemcpy(grad_input, grad, sizeof(float) * NN, cudaMemcpyDeviceToDevice);
        error_handling(cudaGetLastError());
    }
    int    getname() override { return 46; }
    float* get_output() override { return output; }
    float* get_grad_input() override { return grad_input; }
    void update(float lr) {
        for (const auto& l : layers) {
            l->update(lr);

        }
    }


    ~ShixianResidualyolo() {
        cudaFree(output);
        cudaFree(grad_input);
    }


private:
    //    cublasHandle_t &cublas;
    int  _c, _h, _w;
    cudnnHandle_t& cudnn;
    int batch;
    float* input, * output, * grad_input;
    float* input2; 
    float* d_residual;
public:
    std::vector<std::shared_ptr<Layer>> layers;

    

};

架构如下:

layers.emplace_back(std::make_shared<Conv2D>(cudnn, batch, 5, 32, 32, 32, 3, 1, 1));
        //第一残差开始
        layers.emplace_back(std::make_shared<residualExt22>(cudnn, batch, 32, 32, 32));
        //第二残差开始
        layers.emplace_back(std::make_shared<Conv2D>(cudnn, batch, 32, 64, 32, 32, 3, 1, 1));
        layers.emplace_back(std::make_shared<residualExt22>(cudnn, batch, 64, 32, 32));
        //第三残差开始,yolo虚线残差
        //xuxianResidual
         layers.emplace_back(std::make_shared<xuxianResidual2>(cudnn, batch, 64, 32, 32));

     layers.emplace_back(std::make_shared<ShixianResidualyolo>(cudnn, batch, 128, 16, 16));//yolo实线残差

 layers.emplace_back(std::make_shared<Conv2D>(cudnn, batch, 128, 256, 16, 16, 3, 1, 1));

layers.emplace_back(std::make_shared<residualExt22>(cudnn, batch, 256, 16, 16));

 layers.emplace_back(std::make_shared<averPool2D>(cudnn, batch, 256, 16,16, 2, 2, 0, 2));
         
          layers.emplace_back(std::make_shared<Linear>(cublas, batch, 256 * 64, 384));
          layers.emplace_back(std::make_shared<BN>(cudnn, batch, 384, 1, 1));
          layers.emplace_back(std::make_shared<LeakyRL>(cudnn, batch, 384, 1, 1));
          layers.emplace_back(std::make_shared<Dropout>(cudnn, batch, 384, 1, 1));//=0.5

          layers.emplace_back(std::make_shared<Linear>(cublas, batch, 384, 10));

昨天是初恋生日,送出了祝福!初恋是人生中最美好的!人生中应保持这种美好!今天骑车,突然明白,王安石游褒禅山记,只可远观不可亵玩也!初中真是初中!过了几十年,还是那样美好!

徐志摩也说:轻轻我,来了,正如我轻轻的走,我挥一挥衣袖,不带走一片云彩!

早上经过五门堰,看着河中那招摇的水草!美了几十年!颇有感慨!

一种得不到的美好,谁说你没得到呢?!

更多推荐