CNN迁移学习

迁移学习

迁移学习就是将一个问题上训练好的模型通过简单的调整使其适用于一个新的问题。
由于大型网络很复杂,训练一个复杂的卷积神经网络需要非常多的标注数据,而且需要比较长的时间。迁移学习就是为了解决大量标注数据和训练时间问题的一种变通处理方式。
在数据量足够的情况下,迁移学习的效果不如完全重新训练。但是迁移学习所需要的训练时间和训练样本数要远远小于训练完整的模型。而且可以得到不错的准确率。
下面利用ImageNet 数据集上训练好的Inception-v3 模型来解决一个新的图像分类问题。

完整代码

数据处理代码

import glob
import os.path
import numpy as np
import tensorflow as tf
from tensorflow.python.platform import gfile

# 原始输入数据的目录,这个目录下有5个子目录,每个子目录底下保存这属于该
# 类别的所有图片。
#下载链接:http://download.tensorflow.org/example_images/flower_photos.tgz
INPUT_DATA = '../../datasets/flower_photos'
# 输出文件地址。我们将整理后的图片数据通过numpy的格式保存。
OUTPUT_FILE = '../../datasets/flower_processed_data.npy'

# 测试数据和验证数据比例。
VALIDATION_PERCENTAGE = 10
TEST_PERCENTAGE = 10

# 读取数据并将数据分割成训练数据、验证数据和测试数据。
def create_image_lists(sess, testing_percentage, validation_percentage):
    '''
        os.walk() 方法用于通过在目录树中游走输出在目录中的文件名,向上或者向下。
        os.walk() 方法是一个简单易用的文件、目录遍历器,可以帮助我们高效的处理文件、目录方面的事情。
        在Unix,Windows中有效。
        
    '''
    sub_dirs = [x[0] for x in os.walk(INPUT_DATA)]
    is_root_dir = True
    
    # 初始化各个数据集。
    training_images = []
    training_labels = []
    testing_images = []
    testing_labels = []
    validation_images = []
    validation_labels = []
    current_label = 0
    
    # 读取所有的子目录。
    for sub_dir in sub_dirs:
        print ("sub_dir:", sub_dir)
        if is_root_dir:
            is_root_dir = False
            continue

        # 获取一个子目录中所有的图片文件。
        extensions = ['jpg', 'jpeg', 'JPG', 'JPEG']
        file_list = []
        dir_name = os.path.basename(sub_dir)
        for extension in extensions:
            #os.path.join就是获取INPUT_DATA目录,并组合成新目录
            file_glob = os.path.join(INPUT_DATA, dir_name, '*.' + extension)
            #使用glob.glob获得文件路径
            file_list.extend(glob.glob(file_glob))
        if not file_list: continue
        print ("processing:", dir_name)
        
        i = 0
        # 处理图片数据。
        for file_name in file_list:
            i += 1
            # 读取并解析图片,将图片转化为299*299以方便inception-v3模型来处理。
            image_raw_data = gfile.FastGFile(file_name, 'rb').read()
       
<think>好的,我需要回答用户关于如何在CNN中应用迁移学习以及与残差网络相关的实现方法和教程的问题。首先,我得回顾一下用户提供的引用内容,看看哪些信息可以直接使用。 用户提到了引用[1]和[2],里面讲到了迁移学习的基本概念和ResNet的结构,特别是残差结构和批次归一化。引用[3]和[4]讨论了ResNet在医学检测中的应用和Batch Normalization的细节。我需要将这些信息整合起来,分步骤解释实现方法。 首先,应该解释迁移学习CNN中的一般步骤,比如预训练模型、微调等。然后,结合残差网络,比如ResNet的结构,说明如何利用其解决梯度问题。接着,可能需要给出一个具体的代码示例,比如使用PyTorch加载预训练的ResNet模型,并修改最后的全连接层进行微调。 同时,用户要求生成相关问题,我需要想几个相关的问题,比如迁移学习的优势、ResNet的核心结构、Batch Normalization的作用等。确保问题覆盖用户可能感兴趣的方面。 在写作过程中要注意使用正确的中文表达,数学公式用$$...$$,行内公式用$...$。比如提到残差结构时,公式$F(x) = H(x) - x$需要用正确的LaTeX格式。代码部分要使用代码块,并确保语法正确。 还需要检查引用标记是否正确添加,比如在提到批次归一化时引用[4],在讨论残差结构时引用[2]和[3]。确保每个引用都对应正确的内容,并且自然地融入回答中。 最后,保持结构清晰,分步骤讲解实现方法,让用户能够逐步理解和应用。可能需要分成几个部分,如迁移学习步骤、残差网络实现、代码示例等,每个部分下再详细说明。</think>### CNN迁移学习与残差网络实现方法分步解析 #### 一、迁移学习CNN中的应用步骤 1. **预训练模型选择** 选择与目标任务相近的ImageNet预训练模型(如ResNet18/50),其底层特征提取能力已通过大规模数据验证[^2]。数学表达式描述特征映射过程: $$F(x) = W \ast x + b$$ 其中$\ast$表示卷积操作,$W$为卷积核权重。 2. **特征提取器复用** 冻结前N层卷积层参数(通过`requires_grad=False`实现),保留其通用特征提取能力。例如ResNet18包含17个卷积层+1个全连接层,可冻结前10层[^3]。 3. **分类器改造** 替换原全连接层,新结构需匹配当前任务类别数。示例代码(PyTorch): ```python import torchvision.models as models model = models.resnet18(pretrained=True) for param in model.parameters(): # 冻结所有层 param.requires_grad = False model.fc = nn.Sequential( # 修改最后一层 nn.Linear(512, 256), nn.ReLU(), nn.Dropout(0.5), nn.Linear(256, num_classes) ) ``` 4. **微调策略** - 初始阶段:仅训练新添加的分类层(学习率0.001-0.01) - 中期解冻:逐步解冻部分卷积层(如后3层)参与训练 - 参数更新:使用更小的学习率(原1/10)优化解冻层[^1] #### 二、残差网络核心实现 1. **残差结构数学表达** 基础残差单元满足: $$H(x) = F(x) + x$$ 其中$F(x)$为残差映射,通过两个3×3卷积实现[^2]。 2. **批次归一化实现** 每个卷积层后插入BN层,标准化公式: $$\hat{x}_i = \frac{x_i - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}$$ $$y_i = \gamma \hat{x}_i + \beta$$ 其中$\mu_B$为批次均值,$\sigma_B^2$为批次方差[^4]。 3. **残差模块代码实现** ```python class BasicBlock(nn.Module): def __init__(self, in_channels, out_channels, stride=1): super().__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, 3, stride, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(out_channels) self.conv2 = nn.Conv2d(out_channels, out_channels, 3, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(out_channels) self.shortcut = nn.Sequential() if stride != 1 or in_channels != out_channels: self.shortcut = nn.Sequential( nn.Conv2d(in_channels, out_channels, 1, stride, bias=False), nn.BatchNorm2d(out_channels) ) def forward(self, x): out = F.relu(self.bn1(self.conv1(x))) out = self.bn2(self.conv2(out)) out += self.shortcut(x) return F.relu(out) ``` #### 三、完整训练流程示例 ```python # 数据准备 from torchvision import transforms train_transforms = transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]) # 模型训练配置 import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD([ {'params': model.fc.parameters(), 'lr': 0.01}, {'params': model.layer4.parameters(), 'lr': 0.001} ], momentum=0.9) # 训练循环 for epoch in range(10): for inputs, labels in train_loader: outputs = model(inputs) loss = criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值