深度学习模型入门:从XOR模型到CNN图像分类器
立即解锁
发布时间: 2025-08-29 09:57:18 阅读量: 5 订阅数: 6 

# 深度学习模型入门:从XOR模型到CNN图像分类器
## 1. 第一个深度学习模型的训练与使用
### 1.1 训练模型
在PyTorch Lightning中,所有模型都可以使用`Trainer`类进行训练。`Trainer`类是对一些关键操作的抽象,例如遍历数据集、反向传播、清除梯度和优化器步骤等。它还支持许多其他功能,如各种回调、模型检查点、提前停止、单元测试的开发运行、对GPU和TPU的支持、记录器、日志、轮次等。
以下是训练XOR模型的代码:
```python
from pytorch_lightning.utilities.types import TRAIN_DATALOADERS
checkpoint_callback = ModelCheckpoint()
model = XORModel()
trainer = pl.Trainer(max_epochs=100, callbacks=[checkpoint_callback])
trainer.fit(model, train_dataloaders=train_loader)
```
在上述代码中,我们创建了一个`Trainer`对象,将模型训练100个轮次,并将模型检查点作为回调传递。最后,调用`fit`方法传入模型和输入数据进行训练。
训练模型时,我们可以观察到损失值会显示在进度条上。PyTorch Lightning提供了一种灵活的方式来配置进度条上显示的值。
在PyTorch Lightning中,每次训练模型时,不同版本的模型都会保存在默认的`lightning_logs`文件夹中。我们可以从这些文件中加载不同版本的模型并比较结果。例如,运行XOR模型两次后,查看`lightning_logs`文件夹,会看到两个版本的XOR模型。
### 1.2 加载模型
训练好模型后,下一步是加载模型。可以使用之前创建的`checkpoint_callback`来确定最新版本的模型路径:
```python
print(checkpoint_callback.best_model_path)
```
上述代码会显示最新模型的文件路径,然后使用`load_from_checkpoint`方法从检查点加载模型:
```python
train_model = model.load_from_checkpoint(checkpoint_callback.best_model_path)
```
### 1.3 进行预测
模型加载完成后,就可以进行预测了。以下是一个简单的预测示例:
```python
test = torch.utils.data.DataLoader(xor_input, batch_size=1)
for val in xor_input:
_ = train_model(val)
print([int(val[0]),int(val[1])], int(_.round()))
```
从输出结果可以看出,模型预测的结果是正确的。
### 1.4 深度学习模型的深度奥秘
构建基本的神经网络后,我们可以利用多层感知器(MLP)的知识来构建深度学习(DL)模型。很多人误以为深度学习只是涉及具有数百或数千层的大型神经网络模型,但实际上,深度学习的真正秘诀是反向传播。
多层感知器等神经网络虽然可以解决一些分类问题,但在处理图像等大型非结构化数据时并不准确。反向传播通过给系统提供反馈,让模型学习预测的好坏,并在每次迭代中对错误进行惩罚。通过多次迭代和优化方法,系统可以学习最小化错误并实现收敛。常见的损失函数有对数损失和余弦损失函数。
结合大量数据和云计算提供的计算能力,反向传播可以创造奇迹,这也是近年来机器学习复兴的原因。自2012年卷积神经网络(CNN)架构在ImageNet竞赛中取得接近人类的准确率以来,深度学习不断发展。
### 1.5 CNN架构概述
计算机只能理解数字形式的输入,那么如何将图像转换为数字呢?CNN架构由多个卷积层组成,其主要目标是将高维对象(如图像)转换为低维实体(如矩阵形式的数字,即张量)。
CNN不仅可以将图像转换为张量,还可以使用反向传播和优化方法学习识别图像中的对象。经过大量图像训练后,CNN可以准确识别未见过的图像。CNN的成功在于其可扩展性,通过添加更多硬件,其准确性会更高。
以下是一个简单的CNN架构流程图:
```mermaid
graph LR
A[96x96图像] --> B[裁剪为32x32]
B --> C[第一次卷积(核大小3,步长1)]
C --> D[MaxPool层(转换为16x16)]
D --> E[第二次卷积(6通道)]
E --> F[全连接层(1000)]
F --> G[全连接层(500)]
G --> H[全连接层(250)]
H --> I[全连接层(120)]
I --> J[全连接层(60)]
J --> K[SoftMax层(最终预测)]
```
我们将使用这个简单的CNN架构为组织病理学癌症检测数据集构建模型,以识别从大型数字病理扫描中提取的小图像补丁中的转移性癌症。
### 1.6 构建CNN模型的步骤
构建基于CNN的图像分类器的步骤如下:
1. 导入包
2. 收集数据
3. 准备数据
4. 构建模型
5. 训练模型
6. 评估模型的准确性
## 2. 构建CNN模型进行图像识别
### 2.1 导入包
首先,安装并加载必要的包:
```python
!pip install pytorch-lightning==1.5.2 --quiet
!pip install opendatasets --upgrade --quiet
```
然后导入所需的包:
```python
import os
import shutil
import opendatasets as od
import pandas as pd
import numpy as np
from PIL import Image
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import torch
from torch import nn, optim
from torch.utils.data import DataLoader, Dataset
from torch.utils.data.sampler import SubsetRandomSampler
from torchvision.datasets import ImageFolder
import torchvision.transforms as T
from torchvision.utils import make_grid
from torchmetrics.functional import accuracy
import pytorch_lightning as pl
```
最后,检查包的版本:
```python
print("pandas version:",pd.__version__)
print("numpy version:",np.__version__)
print("torch version:",torch.__version__)
print("pytorch ligthening version:",pl.__version__)
```
### 2.2 收集数据
我们将使用Google Drive来存储数据集和保存检查点。首先,从Kaggle下载PCam数据集:
```python
dataset_url = 'https://www.kaggle.com/c/histopathologic-cancer-detection'
od.download(dataset_url)
```
下载数据集时,需要输入Kaggle的用户名和密钥。可以在Kaggle网站上创建API密钥,下载`Kaggle.json`文件,从中获取用户名和密钥,或者直接将`Kaggle.json`文件上传到Google Colab文件夹中使用。
此外,还有一个`train_labels.csv`文件,包含图像标识符(ID)和对应的标签。我们将其读取到pandas DataFrame中:
```python
df_labels = pd.read_csv('train_labels.csv')
```
从输出可以看出,图像有两个标签0和1,这是一个二分类任务。
### 2.3 下采样数据集
原始数据集包含大量图像,为了便于学习第一个图像分类模型,我们将训练文件夹中的220,000张图像下采样到10,000张,并将其分为训练集和测试集:
```python
np.random.seed(0)
train_imgs_orig = os.listdir("histopathologic-cancer-detection/train")
selected_image_list = []
for img in np.random.choice(train_imgs_orig, 10000):
selected_image_list.append(img)
np.random.seed(0)
np.random.shuffle(selected_image_list)
cancer_train_idx = selected_image_list[:8000]
cancer_test_idx = selected_image_list[8000:]
print("Number of images in the downsampled training dataset: ", len(cancer_train_idx))
print("Number of images in the downsampled testing dataset: ", len(cancer_test_idx))
```
将训练和测试图像的名称分别存储在`cancer_train_idx`和`cancer_test_idx`中后,我们将这些图像保存到Google Drive的持久存储中,避免后续重复操作:
```python
from google.colab import drive
drive.mount('/content/gdrive')
os.mkdir('/content/gdrive/My Drive/Colab Notebooks/histopathologic-cancer-detection/train_dataset/')
for fname in cancer_train_idx:
src = os.path.join('histopathologic-cancer-detection/train', fname)
dst = os.path.join('/content/gdrive/My Drive/Colab Notebooks/histopathologic-cancer-detection/train_dataset/', fname)
shutil.copyfile(src, dst)
os.mkdir('/content/histopathologic-cancer-detection/test_dataset/')
for fname in test_idx:
src = os.path.join('histopathologic-cancer-detection/train', fname)
dst = os.path.join('/content/histopathologic-cancer-detection/test_dataset/', fname)
shutil.copyfile(src, dst)
print('No. of images in downsampled testing dataset: ', len(os.listdir("/content/histopathologic-cancer-detection/test_dataset/")))
```
### 2.4 提取标签
下采样数据中选择的图像标签将被提取到一个列表中,用于训练和评估图像分类模型:
```python
selected_image_labels = pd.DataFrame()
id_list = []
label_list = []
for img in selected_image_list:
label_tuple = df_labels.loc[df_labels['id'] == img.split('.')[0]]
id_list.append(label_tuple['id'].values[0])
label_list.append(label_tuple['label'].values[0])
```
### 2.5 加载数据集
PyTorch Lightning期望数据按类别存放在文件夹中,因此我们需要编写自定义类来加载数据:
```python
class LoadCancerDataset(Dataset):
def __init__(self, data_folder,
transform = T.Compose([T.CenterCrop(32),T.ToTensor()]), dict_labels={}):
self.data_folder = data_folder
self.list_image_files = [s for s in os.listdir(data_folder)]
self.transform = transform
self.dict_labels = dict_labels
self.labels = [dict_labels[i.split('.')[0]] for i in self.list_image_files]
def __len__(self):
return len(self.list_image_files)
def __getitem__(self, idx):
img_name = os.path.join(self.data_folder, self.list_image_files[idx])
image = Image.open(img_name)
image = self.transform(image)
img_name_short = self.list_image_files[idx].split('.')[0]
label = self.dict_labels[img_name_short]
return image, label
```
### 2.6 数据增强
加载数据后,我们开始进行数据预处理,对图像进行增强:
```python
data_T_train = T.Compose([
T.CenterCrop(32),
T.RandomHorizontalFlip(),
T.RandomVerticalFlip(),
T.ToTensor(),
])
data_T_test = T.Compose([
T.CenterCrop(32),
T.ToTensor(),
])
```
使用Torchvision的内置库将图像裁剪为32x32,并通过水平和垂直翻转进行数据增强。
最后,调用自定义类`LoadCancerDataset`创建训练集和测试集,并使用`DataLoader`创建数据加载器:
```python
train_set = LoadCancerDataset(data_folder='/content/gdrive/My Drive/Colab Notebooks/histopathologic-cancer-detection/train_dataset/',
transform=data_T_train, dict_labels=img_label_dict)
test_set = LoadCancerDataset(data_folder='/content/histopathologic-cancer-detection/test_dataset/',
transform=data_T_test, dict_labels=img_label_dict)
batch_size = 256
train_dataloader = DataLoader(train_set, batch_size, num_workers=2, pin_memory=True, shuffle=True)
test_dataloader = DataLoader(test_set, batch_size, num_workers=2, pin_memory=True)
```
通过以上步骤,我们完成了从数据收集、预处理到构建数据加载器的过程,为后续训练CNN图像分类模型做好了准备。
## 2.7 构建CNN模型
接下来,我们要构建一个用于图像分类的CNN模型。以下是一个简单的CNN模型示例:
```python
import torch.nn as nn
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1)
self.relu1 = nn.ReLU()
self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)
self.relu2 = nn.ReLU()
self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.fc1 = nn.Linear(32 * 8 * 8, 128)
self.relu3 = nn.ReLU()
self.fc2 = nn.Linear(128, 2)
def forward(self, x):
x = self.pool1(self.relu1(self.conv1(x)))
x = self.pool2(self.relu2(self.conv2(x)))
x = x.view(-1, 32 * 8 * 8)
x = self.relu3(self.fc1(x))
x = self.fc2(x)
return x
model = SimpleCNN()
```
这个模型包含两个卷积层、两个池化层和两个全连接层。具体流程如下:
1. 第一个卷积层`conv1`将输入的3通道图像转换为16通道特征图。
2. 使用ReLU激活函数`relu1`增加模型的非线性。
3. 第一个池化层`pool1`将特征图的尺寸减半。
4. 第二个卷积层`conv2`将16通道特征图转换为32通道特征图。
5. 再次使用ReLU激活函数`relu2`。
6. 第二个池化层`pool2`再次将特征图的尺寸减半。
7. 将特征图展平为一维向量,输入到第一个全连接层`fc1`。
8. 经过ReLU激活函数`relu3`。
9. 最后通过第二个全连接层`fc2`输出2个类别。
### 2.8 训练模型
有了模型和数据加载器,我们就可以开始训练模型了。训练过程通常包括定义损失函数、优化器,然后进行多个轮次的训练。以下是训练代码示例:
```python
import torch.optim as optim
import pytorch_lightning as pl
class CancerClassifier(pl.LightningModule):
def __init__(self):
super(CancerClassifier, self).__init__()
self.model = SimpleCNN()
self.criterion = nn.CrossEntropyLoss()
def forward(self, x):
return self.model(x)
def training_step(self, batch, batch_idx):
x, y = batch
logits = self(x)
loss = self.criterion(logits, y)
self.log('train_loss', loss)
return loss
def configure_optimizers(self):
optimizer = optim.Adam(self.parameters(), lr=1e-3)
return optimizer
model = CancerClassifier()
trainer = pl.Trainer(max_epochs=10, gpus=1 if torch.cuda.is_available() else 0)
trainer.fit(model, train_dataloader)
```
在这个代码中:
1. 定义了一个`CancerClassifier`类,继承自`pl.LightningModule`。
2. 在`__init__`方法中初始化模型和损失函数。
3. `forward`方法定义了模型的前向传播。
4. `training_step`方法定义了每个训练步骤的操作,计算损失并记录日志。
5. `configure_optimizers`方法定义了优化器。
6. 创建`CancerClassifier`实例和`Trainer`实例,调用`fit`方法开始训练。
### 2.9 评估模型的准确性
训练完成后,我们需要评估模型的准确性。可以使用测试数据加载器对模型进行评估:
```python
def evaluate_model(model, test_dataloader):
model.eval()
correct = 0
total = 0
with torch.no_grad():
for batch in test_dataloader:
x, y = batch
logits = model(x)
_, predicted = torch.max(logits.data, 1)
total += y.size(0)
correct += (predicted == y).sum().item()
accuracy = correct / total
print(f'Accuracy of the model on the test images: {accuracy * 100}%')
evaluate_model(model, test_dataloader)
```
在这个代码中:
1. 将模型设置为评估模式。
2. 遍历测试数据加载器,计算预测结果。
3. 统计正确预测的数量和总样本数量。
4. 计算准确率并打印结果。
### 2.10 总结
本文从简单的XOR模型训练开始,逐步介绍了深度学习模型的训练、加载、预测过程,深入探讨了CNN架构和原理,并详细阐述了使用PyTorch Lightning构建图像分类器的完整流程,包括导入包、收集数据、下采样数据集、加载数据、数据增强、构建模型、训练模型和评估模型等步骤。
整个流程可以总结为以下表格:
|步骤|操作|
|----|----|
|导入包|安装并导入必要的Python包|
|收集数据|从Kaggle下载数据集,读取标签文件|
|下采样数据集|将大量图像下采样到合适的数量,并分为训练集和测试集|
|加载数据集|编写自定义类加载数据|
|数据增强|使用Torchvision的转换函数对图像进行增强|
|构建模型|定义CNN模型的结构|
|训练模型|定义损失函数、优化器,进行多个轮次的训练|
|评估模型|使用测试数据评估模型的准确性|
通过这些步骤,我们可以构建一个有效的图像分类器,用于识别组织病理学癌症检测数据集中的癌症图像。同时,我们也了解了深度学习中反向传播、损失函数、优化器等重要概念的作用。希望本文能帮助你更好地理解和应用深度学习技术。
以下是整个流程的mermaid流程图:
```mermaid
graph LR
A[导入包] --> B[收集数据]
B --> C[下采样数据集]
C --> D[加载数据集]
D --> E[数据增强]
E --> F[构建模型]
F --> G[训练模型]
G --> H[评估模型]
```
深度学习是一个不断发展的领域,还有许多其他的技术和方法可以进一步提高模型的性能,如调整模型架构、使用更复杂的数据增强方法、尝试不同的优化器和损失函数等。在实际应用中,可以根据具体问题和数据集的特点进行调整和优化。
0
0
复制全文
相关推荐








