libtorch搭建Resnet网络笔记

torch::Device device = torch::Device(torch::kCPU)

int gpu_num = torch::getNumGPUs();

if (gpu_id >= 0) device = torch::Device(torch::kCUDA, gpu_id);

二维卷积

// 设置二维卷积函数的参数列表。
inline torch::nn::Conv2dOptions conv_options(int64_t in_planes, int64_t out_planes, int64_t kerner_size,
    int64_t stride = 1, int64_t padding = 0, int groups = 1, bool with_bias = true, int dilation = 1) {
    torch::nn::Conv2dOptions conv_options = torch::nn::Conv2dOptions(in_planes, out_planes, kerner_size);
    conv_options.stride(stride);
    conv_options.padding(padding);
    conv_options.bias(with_bias);
	conv_options.groups(groups);
	conv_options.dilation(dilation);
    return conv_options;
}

// 输入3通道,输出64通道,卷积核大小是7,步长是2,padding是3,groups是1,不设置bias.
conv1 = torch::nn::Conv2d(conv_options(3, 64, 7, 2, 3, 1, false));

上采样        

upsample = torch::nn::Upsample(torch::nn::UpsampleOptions().scale_factor(std::vector<double>({2,2})).mode(torch::kNearest));

bachnorm

// 其中如果图像是64通道。
bn1 = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(64));

resnet的layer

conv1 = torch::nn::Conv2d(conv_options(3, 64, 7, 2, 3, 1, false));
bn1 = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(64));
layer1 = torch::nn::Sequential(_make_layer(64, layers[0]));  // 步长是1
layer2 = torch::nn::Sequential(_make_layer(128, layers[1], 2));  // 步长是2
layer3 = torch::nn::Sequential(_make_layer(256, layers[2], 2));  // layers存放的是不同layer输出的通道数。
layer4 = torch::nn::Sequential(_make_layer(512, layers[3], 2));

fc = torch::nn::Linear(512 * expansion, num_classes);
register_module("conv1", conv1);
register_module("bn1", bn1);
register_module("layer1", layer1);
register_module("layer2", layer2);
register_module("layer3", layer3);
register_module("layer4", layer4);
register_module("fc", fc);


// planes: 每一个block输出的通道数。
// blocks: 每个layer包含的blocks数。
torch::nn::Sequential ResNetImpl::_make_layer(int64_t planes, int64_t blocks, int64_t stride) {
    // 每个layer层可能会有一个下采样层(平面维度或者通道维度)。
    torch::nn::Sequential downsample;
    if (stride != 1 || inplanes != planes * expansion) {  // 步长不等于1,则追加一个downsamle层。
        downsample = torch::nn::Sequential(
            torch::nn::Conv2d(conv_options(inplanes, planes *  expansion, 1, stride, 0, 1, false)),
            torch::nn::BatchNorm2d(planes *  expansion)
        );
    }
    // 
    torch::nn::Sequential layers;
    layers->push_back(Block(inplanes, planes, stride, downsample, groups, base_width, is_basic));  // 第一个block.
    inplanes = planes *  expansion;  // inplanes:记录输入通道数,初始值为64.
    for (int64_t i = 1; i < blocks; i++) {  // 剩余的blocks. 每个block的输入和输出通道都是固定的不变的,步长是1。
        layers->push_back(Block(inplanes, planes, 1, torch::nn::Sequential(), groups, base_width,is_basic));
    }

    return layers;
}

resnet的block

两个conv+bn组成,卷积核大小都是3。

// is_basic: BasicBlock: 3x3 conv + 3x3 conv; BottleNeck 1x1 conv + 3x3 conv + 1x1 conv
BlockImpl::BlockImpl(int64_t inplanes, int64_t planes, int64_t stride_,
    torch::nn::Sequential downsample_, int groups, int base_width, bool _is_basic)
{
    downsample = downsample_;
    stride = stride_;
	int width = int(planes * (base_width / 64.)) * groups;
    
    // BasicBlock: 3x3 conv + 3x3 conv
    conv1 = torch::nn::Conv2d(conv_options(inplanes, width, 3, stride_, 1, groups, false));
    bn1 = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(width));
    conv2 = torch::nn::Conv2d(conv_options(width, width, 3, 1, 1, groups, false));
    bn2 = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(width));
    is_basic = _is_basic;
    if (!is_basic) {  // BottleNeck: 1x1 conv + 3x3 conv + 1x1 conv
        conv1 = torch::nn::Conv2d(conv_options(inplanes, width, 1, 1, 0, 1, false));
        conv2 = torch::nn::Conv2d(conv_options(width, width, 3, stride_, 1, groups, false));
        conv3 = torch::nn::Conv2d(conv_options(width, planes * 4, 1, 1, 0, 1, false));
        bn3 = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(planes * 4));
    }

    register_module("conv1", conv1);
    register_module("bn1", bn1);
    register_module("conv2", conv2);
    register_module("bn2", bn2);
    if (!is_basic) {  // 如果不是basic,则block里面再增加一个conv3
        register_module("conv3", conv3);
        register_module("bn3", bn3);
    }

    if (!downsample->is_empty()) {
        register_module("downsample", downsample);
    }
}

删除resnet最后的全链接层

torch::OrderedDict<std::string, at::Tensor> pretrained_dict = net_pretrained->named_parameters();  // 获取resnet网络每一层的key和value字典
torch::OrderedDict<std::string, at::Tensor> model_dict = this->named_parameters(); 

for (auto n = pretrained_dict.begin(); n != pretrained_dict.end(); n++)
{
	if (strstr((*n).key().data(), "fc.")) {  // key字符串中是否存在字串“fc.”
		continue;
	}
	model_dict[(*n).key()] = (*n).value();
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: ResNet深度学习网络可以通过在卷积神经网络(CNN)中使用残差块,每一层的输入会添加到输出上来构建。残差块的主要目的是解决深层网络训练中的梯度消失问题,它可以减少训练数据集大小,提高准确率和模型效率。 ### 回答2: 搭建ResNet深度学习网络可以通过以下步骤实现。 1.导入必要的库和模块:首先,需要导入深度学习框架的库,例如TensorFlow或PyTorch,并且还要导入其他必要的库,例如numpy用于数值计算和matplotlib用于可视化。 2.定义ResNet网络的基本块:ResNet网络的基本单位是残差模块(Residual Block)。一个残差模块由两个卷积层和一个跳跃连接组成。这个跳跃连接将输入直接添加到卷积层的输出,以便于梯度的流动,避免梯度消失的问题。根据网络深度的不同,可以定义多个残差模块。 3.定义ResNet网络结构:根据需要的深度,将多个残差模块按顺序连接起来,组成整个ResNet网络结构。在实践中,通常使用层数较少的ResNet-18或ResNet-34进行快速训练和调试,或者使用层数较多的ResNet-50、ResNet-101或ResNet-152等进行更复杂的任务。 4.定义前向传播函数:根据ResNet网络结构,定义前向传播函数。这个函数将输入数据作为输入,并通过每个残差模块向前传播,直到最后一层输出预测结果。 5.定义损失函数和优化器:根据任务的特点,选择适当的损失函数,例如均方误差损失函数(Mean Squared Error)或交叉熵损失函数(Cross Entropy)。然后,选择适当的优化器,例如随机梯度下降(SGD)或Adam优化器等。 6.训练模型:将数据集分为训练集和验证集,通过模型的前向传播计算预测值,并与真实值进行比较,计算损失函数并反向传播更新参数。重复这个过程多次,直到模型收敛。 7.评估和调优模型:通过验证集对模型进行评估,可以计算准确率、精确率、召回率等指标。根据评估结果,对模型进行调优,例如调整学习率、增加训练数据或调整网络结构等。 8.使用模型进行预测:对于未知的输入数据,使用训练好的模型进行预测,并获取预测结果。 综上所述,搭建ResNet深度学习网络包括导入库和模块、定义基本块和网络结构、定义前向传播函数、定义损失函数和优化器、训练模型、评估和调优模型以及使用模型进行预测。 ### 回答3: 搭建一个 ResNet 深度学习网络可以分为以下几个步骤: 1. 数据预处理:收集和准备用于训练的图像数据集。对图像进行预处理,如大小调整、归一化、裁剪等操作,以便于网络的训练和测试。 2. 构建残差块(Residual Block):ResNet 的核心是残差学习,通过添加残差块来增加网络的深度。残差块由两个或三个卷积层组成,其中包含一个跳跃连接(shortcut connection),可以绕过一部分网络层直接连到后续层。 3. 构建 ResNet 模型:使用多个残差块构建 ResNet 模型。根据任务的复杂度和要求,可以选择不同深度的 ResNet(如 ResNet-18、ResNet-34、ResNet-50 等)。 4. 添加全局平均池化层:在 ResNet 的最后一部分添加一个全局平均池化层,将特征图转换为一个固定长度的向量。 5. 添加全连接层和输出层:在全局平均池化层后添加一个全连接层和一个输出层,用于对输入进行分类或回归等任务。 6. 模型训练:使用训练数据对搭建好的 ResNet 模型进行训练。选择合适的损失函数和优化算法,并根据训练集的大小和模型的复杂度设置适当的训练参数。 7. 模型评估:在测试数据上对训练好的模型进行评估,计算模型的准确率、精度、召回率等指标,判断模型的性能。 8. 模型优化:根据评估结果对模型进行优化,可以调整网络结构、调整超参数、增加正则化等方法来提高模型性能。 9. 模型应用:将优化后的模型用于实际场景,进行图像分类、对象检测、图像生成等各种深度学习任务。 总之,搭建 ResNet 深度学习网络是一个多步骤的过程,需要根据具体任务和数据集进行选择和调整。通过不断优化和训练,可以得到性能较好的深度学习模型。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mr.Q

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

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

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

打赏作者

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

抵扣说明:

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

余额充值