其实我前面四篇实现了三种残差:
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--) {
layersi->backward(grad);
grad = layersi->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));
昨天是初恋生日,送出了祝福!初恋是人生中最美好的!人生中应保持这种美好!今天骑车,突然明白,王安石游褒禅山记,只可远观不可亵玩也!初中真是初中!过了几十年,还是那样美好!
徐志摩也说:轻轻我,来了,正如我轻轻的走,我挥一挥衣袖,不带走一片云彩!
早上经过五门堰,看着河中那招摇的水草!美了几十年!颇有感慨!
一种得不到的美好,谁说你没得到呢?!