# cifar10_classification **Repository Path**: linghu6p/cifar10_classification ## Basic Information - **Project Name**: cifar10_classification - **Description**: 用于cifar10分类的教学项目, - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2025-08-01 - **Last Updated**: 2026-02-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # cifar10_classification #### 介绍 用于cifar10 分类的教学项目。 说明: 1、数据集使用:cifar10 2、网络架构:自定义的浅层CNN网络 MyCnnNet 3、代码保存期限:2024 0801-2025 0801 #### 环境准备 1. cuda 11.8 python 3.9 (可根据自己的环境进行实现) module load miniforge3/24.11 2. 依赖包安装 pip install torch -i https://mirrors.aliyun.com/pypi/simple/ pip install torchvision -i https://mirrors.aliyun.com/pypi/simple/ pip install tqdm -i https://mirrors.aliyun.com/pypi/simple/ pip install matplotlib -i https://mirrors.aliyun.com/pypi/simple/ 3. 代码文件说明 train.py 主实验流程 models/mycnn.py 自己定义的模型 4、数据集下载 https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz mkdir -p ./data tar -xvzf cifar-10-python.tar.gz -C ./data ## 使用说明 ### mycnn的构造 #### 模型基本模块构造 首先是构造了四层 每一层都是一个 卷积层+池化层构成 前三层都是采用的最大池化层 而 第四层采用 平均池化层 示例: ```python # 第1层:输入通道数为3(RGB),输出通道数为32 # 卷积核大小3×3,padding=1保持输出尺寸不变 self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1) self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2) # 2×2最大池化,尺寸减半 ``` ```python # 第4层:输入128 -> 输出256通道 self.conv4 = nn.Conv2d(128, 256, kernel_size=3, padding=1) # 使用全局平均池化将空间维度压缩为1×1(即每通道一个数) self.pool4 = nn.AdaptiveAvgPool2d((1, 1)) ``` 其次是利用全连接层 将最后一层的特征图映射到 10个类别上 ```python self.classifier = nn.Linear(256, num_classes) ``` #### 前向过程 先卷积一次 再利用激活函数 relu进行激活 最后池化 按照这个流程往前走 一直到分类器输出 ```python x = F.relu(self.conv1(x)) # [B, 32, H, W] x = self.pool1(x) # [B, 32, H/2, W/2] ``` ```python x = x.view(x.size(0), -1) # 展平成向量 [B, 256] x = self.classifier(x) # 输出类别 logits: [256, 10] ``` ### train 主函数 #### 数据处理 第一步先是数据增强 在训练集和验证集上进行 ```python transform_train = transforms.Compose([ transforms.RandomCrop(32, padding=4), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), ]) transform_test = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), ]) ``` 第二部 数据集下载 这里使用的是公开数据集 根据自己需要指定在哪个文件夹下 同时构造dataloader ```python trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train) trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True, num_workers=2) testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test) testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=2) ``` #### 模型构造 损失函数与优化器 ```python model = MyCnnNet().to(device) criterion = nn.CrossEntropyLoss() # 交叉熵损失 optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum) ``` #### 训练 ```python for inputs, targets in loop: inputs, targets = inputs.to(device), targets.to(device) # 返回当前批次的图像和对应的标签 optimizer.zero_grad() # 清空历史梯度 outputs = model(inputs) loss = criterion(outputs, targets) # 计算loss loss.backward() # 反向传播 optimizer.step() # 更新梯度 _, predicted = outputs.max(1) #返回最大的值 和 位置 total += targets.size(0) # 累计这一轮的样本数 correct += predicted.eq(targets).sum().item() # predicted.eq(targets) 会生成一个布尔向量,例如 [True, False, True, ...] loop.set_postfix(loss=loss.item(), acc=100. * correct / total) # 利用 tqdm 的 set_postfix 方法,实时在进度条上显示 loss 和 acc ``` #### 测试 ```python def evaluate(model, loader): model.eval() correct = 0 total = 0 with torch.no_grad(): # 不需要梯度计算 for inputs, targets in loader: inputs, targets = inputs.to(device), targets.to(device) outputs = model(inputs) _, predicted = outputs.max(1) total += targets.size(0) correct += predicted.eq(targets).sum().item() return correct / total ``` #### 结果输出 ```python train_acc = correct / total test_acc = evaluate(model, testloader) train_acc_list.append(train_acc) test_acc_list.append(test_acc) print(f"[Epoch {epoch+1}] Train Acc: {train_acc:.4f} | Test Acc: {test_acc:.4f}") ``` #### 绘制loss 图 ```python # ------- 绘制准确率曲线图 ------- plt.figure() plt.plot(range(1, epochs+1), [a * 100 for a in train_acc_list], label='Train Acc') plt.plot(range(1, epochs+1), [a * 100 for a in test_acc_list], label='Test Acc') plt.xlabel("Epoch") plt.ylabel("Accuracy (%)") plt.title("Train/Test Accuracy Curve") plt.legend() plt.grid(True) plt.savefig("acc_curve.png") plt.close() ```