news 2026/4/15 14:44:39

ResNet18从零开始:没Linux经验?Windows也能轻松玩

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ResNet18从零开始:没Linux经验?Windows也能轻松玩

ResNet18从零开始:没Linux经验?Windows也能轻松玩

引言

作为一名Windows用户,当你想要学习深度学习中的经典模型ResNet18时,是不是经常被各种Linux命令和复杂的开发环境配置劝退?别担心,这篇文章就是为你量身定制的Windows友好方案。

ResNet18是深度学习领域最经典的图像分类模型之一,由微软研究院在2015年提出。它通过"残差连接"的创新设计,解决了深度神经网络训练中的梯度消失问题,使得训练更深的网络成为可能。虽然名字里有"18",但它其实只有18层(包含池化和全连接层),非常适合初学者学习和实践。

本文将带你从零开始,在Windows系统上完成ResNet18的完整训练流程,包括:

  • 无需Linux命令,纯Windows环境配置
  • 使用PyTorch框架的简化操作
  • 从数据准备到模型训练的全流程
  • 常见问题的解决方案

即使你没有任何Linux经验,也能跟着步骤轻松上手。让我们开始这段深度学习之旅吧!

1. 环境准备:Windows下的深度学习配置

1.1 安装Python和PyTorch

首先,我们需要在Windows上搭建Python开发环境:

  1. 访问Python官网下载最新版的Python安装包(推荐3.8-3.10版本)
  2. 安装时务必勾选"Add Python to PATH"选项
  3. 安装完成后,打开命令提示符(Win+R,输入cmd),验证安装:
python --version pip --version

接下来安装PyTorch,这是Facebook开源的深度学习框架:

pip install torch torchvision torchaudio

💡 提示

如果你的电脑有NVIDIA显卡,可以安装支持CUDA的PyTorch版本以加速训练。访问PyTorch官网获取适合你显卡的安装命令。

1.2 安装其他必要库

我们还需要一些辅助工具库:

pip install numpy matplotlib opencv-python tqdm

1.3 验证环境

创建一个Python脚本check_env.py,内容如下:

import torch print(f"PyTorch版本: {torch.__version__}") print(f"CUDA可用: {torch.cuda.is_available()}") print(f"GPU型号: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else '无'}")

运行后如果能看到PyTorch版本和CUDA状态,说明环境配置成功。

2. 数据准备:构建你的第一个图像数据集

2.1 选择数据集

为了快速上手,我们可以使用经典的CIFAR-10数据集,它包含10个类别的6万张32x32彩色图像:

from torchvision import datasets, transforms # 定义数据转换 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) # 下载并加载数据集 train_set = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) test_set = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)

2.2 自定义数据集(可选)

如果你想使用自己的图片进行分类,可以按照以下结构组织文件夹:

my_dataset/ train/ class1/ img1.jpg img2.jpg ... class2/ img1.jpg ... test/ class1/ img1.jpg ... class2/ img1.jpg ...

然后使用ImageFolder加载:

from torchvision.datasets import ImageFolder train_set = ImageFolder('my_dataset/train', transform=transform) test_set = ImageFolder('my_dataset/test', transform=transform)

2.3 创建数据加载器

数据加载器(DataLoader)可以帮助我们批量加载数据:

from torch.utils.data import DataLoader batch_size = 32 train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_set, batch_size=batch_size, shuffle=False)

3. 模型构建:理解并实现ResNet18

3.1 ResNet18结构解析

ResNet18的核心是"残差块"(Residual Block),它通过"跳跃连接"(skip connection)将输入直接加到输出上:

输入 → 卷积层1 → 卷积层2 → + → 输出 |________________|

这种设计解决了深度网络中的梯度消失问题,使得网络可以更深而不会影响训练效果。

3.2 使用预训练模型

PyTorch已经内置了ResNet18的实现,我们可以直接加载:

import torchvision.models as models model = models.resnet18(pretrained=True)

3.3 修改输出层

预训练模型是在ImageNet(1000类)上训练的,我们需要修改最后一层以适应我们的分类任务(如CIFAR-10的10类):

import torch.nn as nn num_classes = 10 # CIFAR-10有10个类别 model.fc = nn.Linear(model.fc.in_features, num_classes)

3.4 完整模型定义

如果你想从头实现ResNet18,可以参考以下代码:

import torch.nn as nn class BasicBlock(nn.Module): expansion = 1 def __init__(self, in_channels, out_channels, stride=1): super().__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(out_channels) self.relu = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(out_channels) self.shortcut = nn.Sequential() if stride != 1 or in_channels != self.expansion * out_channels: self.shortcut = nn.Sequential( nn.Conv2d(in_channels, self.expansion * out_channels, kernel_size=1, stride=stride, bias=False), nn.BatchNorm2d(self.expansion * out_channels) ) def forward(self, x): out = self.relu(self.bn1(self.conv1(x))) out = self.bn2(self.conv2(out)) out += self.shortcut(x) out = self.relu(out) return out class ResNet(nn.Module): def __init__(self, block, num_blocks, num_classes=10): super().__init__() self.in_channels = 64 self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(64) self.relu = nn.ReLU(inplace=True) self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1) self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2) self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2) self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2) self.avg_pool = nn.AdaptiveAvgPool2d((1, 1)) self.fc = nn.Linear(512 * block.expansion, num_classes) def _make_layer(self, block, out_channels, num_blocks, stride): strides = [stride] + [1]*(num_blocks-1) layers = [] for stride in strides: layers.append(block(self.in_channels, out_channels, stride)) self.in_channels = out_channels * block.expansion return nn.Sequential(*layers) def forward(self, x): out = self.relu(self.bn1(self.conv1(x))) out = self.layer1(out) out = self.layer2(out) out = self.layer3(out) out = self.layer4(out) out = self.avg_pool(out) out = out.view(out.size(0), -1) out = self.fc(out) return out def ResNet18(): return ResNet(BasicBlock, [2, 2, 2, 2]) model = ResNet18()

4. 模型训练与评估

4.1 定义损失函数和优化器

import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4) scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)

4.2 训练循环

def train(epoch): model.train() train_loss = 0 correct = 0 total = 0 for batch_idx, (inputs, targets) in enumerate(train_loader): optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, targets) loss.backward() optimizer.step() train_loss += loss.item() _, predicted = outputs.max(1) total += targets.size(0) correct += predicted.eq(targets).sum().item() if batch_idx % 100 == 0: print(f'Epoch: {epoch} | Batch: {batch_idx}/{len(train_loader)} | Loss: {loss.item():.3f} | Acc: {100.*correct/total:.1f}%') return train_loss/(batch_idx+1), 100.*correct/total

4.3 测试函数

def test(epoch): model.eval() test_loss = 0 correct = 0 total = 0 with torch.no_grad(): for batch_idx, (inputs, targets) in enumerate(test_loader): outputs = model(inputs) loss = criterion(outputs, targets) test_loss += loss.item() _, predicted = outputs.max(1) total += targets.size(0) correct += predicted.eq(targets).sum().item() print(f'Test Epoch: {epoch} | Loss: {test_loss/(batch_idx+1):.3f} | Acc: {100.*correct/total:.1f}%') return test_loss/(batch_idx+1), 100.*correct/total

4.4 开始训练

epochs = 100 best_acc = 0 for epoch in range(epochs): train_loss, train_acc = train(epoch) test_loss, test_acc = test(epoch) scheduler.step() if test_acc > best_acc: print('Saving best model..') torch.save(model.state_dict(), 'resnet18_best.pth') best_acc = test_acc

5. 常见问题与解决方案

5.1 训练速度慢

  • 原因:可能没有使用GPU加速
  • 解决:确保安装了CUDA版本的PyTorch,并将模型和数据移动到GPU:
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") model = model.to(device) # 在训练循环中 inputs, targets = inputs.to(device), targets.to(device)

5.2 内存不足

  • 原因:批量大小(batch_size)设置过大
  • 解决:减小batch_size(如从32降到16),或使用梯度累积:
accumulation_steps = 4 optimizer.zero_grad() for i, (inputs, targets) in enumerate(train_loader): outputs = model(inputs) loss = criterion(outputs, targets) loss = loss / accumulation_steps loss.backward() if (i+1) % accumulation_steps == 0: optimizer.step() optimizer.zero_grad()

5.3 过拟合

  • 原因:模型过于复杂或训练数据不足
  • 解决
  • 增加数据增强:

python transform_train = transforms.Compose([ transforms.RandomHorizontalFlip(), transforms.RandomCrop(32, padding=4), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ])

  • 添加正则化(如Dropout)
  • 使用早停(early stopping)

6. 模型应用:使用训练好的模型进行预测

训练完成后,我们可以使用模型对新图像进行分类:

from PIL import Image def predict(image_path): # 加载图像 image = Image.open(image_path) # 预处理 transform = transforms.Compose([ transforms.Resize(32), transforms.CenterCrop(32), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) image = transform(image).unsqueeze(0) # 预测 model.eval() with torch.no_grad(): output = model(image) _, predicted = torch.max(output, 1) # CIFAR-10类别 classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') return classes[predicted[0]] # 使用示例 print(predict('test_image.jpg'))

7. 总结

通过本文的学习,你应该已经掌握了在Windows系统上使用PyTorch训练ResNet18模型的完整流程。让我们回顾一下核心要点:

  • 环境配置简单:只需安装Python和PyTorch,无需复杂的Linux环境
  • 数据准备灵活:可以使用标准数据集如CIFAR-10,也可以轻松加载自定义数据集
  • 模型构建清晰:理解了ResNet18的核心结构,并学会了如何修改预训练模型
  • 训练流程完整:从损失函数定义到训练循环,掌握了深度学习的核心训练方法
  • 问题解决全面:针对常见问题提供了实用的解决方案

现在,你可以尝试使用自己的数据集来训练ResNet18模型了。深度学习的世界充满可能,ResNet18只是开始,期待你探索更多精彩的模型和应用!


💡获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 14:43:39

科技感拉满!用AI单目深度估计-MiDaS生成Inferno热力可视化图

科技感拉满!用AI单目深度估计-MiDaS生成Inferno热力可视化图 [toc] 引言:让二维照片“感知”三维空间 在计算机视觉领域,从单张图像中恢复场景的深度信息是一项极具挑战但又极具价值的任务。传统方法依赖双目立体匹配或多帧运动视差&#x…

作者头像 李华
网站建设 2026/4/15 3:30:06

如何实现3D空间感知?用AI单目深度估计-MiDaS镜像轻松搞定

如何实现3D空间感知?用AI单目深度估计-MiDaS镜像轻松搞定 在自动驾驶、增强现实(AR)、机器人导航等前沿技术中,3D空间感知是构建环境理解能力的核心。然而,传统依赖双目相机或激光雷达的深度感知方案成本高、部署复杂…

作者头像 李华
网站建设 2026/4/15 14:43:19

【khbox补环境-3】原型链与 Illegal Invocation 保护机制

khbox 的项目已放gitee, https://gitee.com/sugarysp/khbox_pro ,欢迎各位大佬使用测试。 目前完成的有 调用链追踪 document.all 原型保护以及toString c层调用链日志保存 illegal 保护机制 ps:可能有bug 待做: 异步 console.log 业务代码…

作者头像 李华
网站建设 2026/4/9 1:40:39

计算机毕业设计springboot旅游信息交流网站的设计与实现 基于SpringBoot的“行走圈”旅游分享与商品交易平台 SpringBoot+Vue 全域旅游互动门户的设计与实现

计算机毕业设计springboot旅游信息交流网站的设计与实现29fsewmo (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。 疫情之后,国内旅游出现“短途、高频、个性化”新趋…

作者头像 李华
网站建设 2026/4/12 4:02:27

Rembg API文档生成:Swagger集成最佳实践

Rembg API文档生成:Swagger集成最佳实践 1. 背景与需求分析 1.1 智能万能抠图 - Rembg 在图像处理领域,自动去背景是一项高频且关键的需求,广泛应用于电商商品展示、证件照制作、设计素材提取等场景。传统方法依赖人工标注或简单阈值分割&…

作者头像 李华
网站建设 2026/4/12 3:30:44

Rembg模型部署:Docker容器化方案

Rembg模型部署:Docker容器化方案 1. 智能万能抠图 - Rembg 在图像处理与内容创作领域,自动去背景是一项高频且关键的需求。无论是电商商品图精修、社交媒体素材制作,还是AI绘画中的角色提取,传统手动抠图效率低下,而…

作者头像 李华