3. 手势识别(LeNet、Vgg16、ResNet50)

Show me your code

1. 模型 model.py

import torch
from torch import nn


class ConvBlock(nn.Module):
    """
        一层卷积:
            - 卷积层
            - 批规范化层
            - 激活层
    """
    def __init__(self, in_channels, out_channels, 
                 kernel_size=3, stride=1, padding=1):
        super().__init__()
        self.conv = nn.Conv2d(in_channels=in_channels, out_channels=out_channels,
                             kernel_size=kernel_size, stride=stride,padding=padding)
        self.bn = nn.BatchNorm2d(num_features=out_channels)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        x = self.conv(x)
        x = self.bn(x)
        x = self.relu(x)
        return x

class LeNet(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        # 1, 特征抽取部分
        self.feature_extractor = nn.Sequential(
            # 卷积层1
            ConvBlock(in_channels=3, 
                      out_channels=6, 
                      kernel_size=5,
                      stride=1,
                      padding=0),
            
            # 亚采样(池化)
            nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
            
            # 卷积层2
            ConvBlock(in_channels=6, 
                      out_channels=16, 
                      kernel_size=5,
                      stride=1,
                      padding=0),
            
            # 亚采样(池化)
            nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
            
        )
        
        # 2, 分类
        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(in_features=400, out_features=120),
            nn.ReLU(),
            nn.Linear(in_features=120, out_features=84),
            nn.ReLU(),
            nn.Linear(in_features=84, out_features=num_classes)
        )
        
    def forward(self, x):
        # 1, 提取特征
        x = self.feature_extractor(x)
        # 2, 分类输出
        x = self.classifier(x)
        return x
    
class Vgg16(nn.Module):
    def __init__(self, n_classes=1000):
        super().__init__()
        # 1, 特征抽取部分
        self.feature_extractor = nn.Sequential(
            
            # stage1
            
            # 卷积1
            ConvBlock(in_channels=3, 
                      out_channels=64, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 卷积2
            ConvBlock(in_channels=64, 
                      out_channels=64, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 池化
            nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
            
            # stage2
            
            # 卷积1
            ConvBlock(in_channels=64, 
                      out_channels=128, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 卷积2
            ConvBlock(in_channels=128, 
                      out_channels=128, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 池化
            nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
            
            # stage3
            
            # 卷积1
            ConvBlock(in_channels=128, 
                      out_channels=256, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 卷积2
            ConvBlock(in_channels=256, 
                      out_channels=256, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 卷积3
            ConvBlock(in_channels=256, 
                      out_channels=256, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 池化
            nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
            
            # stage4
            
            # 卷积1
            ConvBlock(in_channels=256, 
                      out_channels=512, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 卷积2
            ConvBlock(in_channels=512, 
                      out_channels=512, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 卷积3
            ConvBlock(in_channels=512, 
                      out_channels=512, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 池化
            nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
            
            
            # stage5
            
            # 卷积1
            ConvBlock(in_channels=512, 
                      out_channels=512, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 卷积2
            ConvBlock(in_channels=512, 
                      out_channels=512, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 卷积3
            ConvBlock(in_channels=512, 
                      out_channels=512, 
                      kernel_size=3,
                      stride=1,
                      padding=1),
            # 池化
            nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
        )
        
        # 2, 分类
        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(in_features=7 * 7 * 512, out_features=4096),
            nn.ReLU(),
            nn.Linear(in_features=4096, out_features=4096),
            nn.ReLU(),
            nn.Linear(in_features=4096, out_features=n_classes)
        )
        
    def forward(self, x):
        # 1, 提取特征
        x = self.feature_extractor(x)
        # 2, 分类输出
        x = self.classifier(x)
        return x


"""
    ResBlock
"""

class ResConvBlock(nn.Module):
    """
        虚线块,每一个大的重复逻辑块前面,第一个短接块就是这个
        实现逻辑:
            y = F(x) + Conv(x)
    """
    def __init__(self, in_channels, out_channels, stride):
        # 调用父类初始化方法
        super().__init__()
                
        # 1,核心处理逻辑
        self.stage = nn.Sequential(
            # 1  1 * 1
            nn.Conv2d(in_channels=in_channels,
                     out_channels=out_channels[0],
                     kernel_size=1,
                     stride=stride,
                     padding=0,
                     bias=False),
            nn.BatchNorm2d(num_features=out_channels[0]),
            nn.ReLU(),
            # 2  3 * 3
            nn.Conv2d(in_channels=out_channels[0],
                     out_channels=out_channels[1],
                     kernel_size=3,
                     padding=1<
<think>嗯,用户想知道如何从TensorFlow Keras Applications中正确导入和使用VGG16ResNet50、MobileNetV2这些预训练模型。首先,我需要回忆一下这些模型的导入方式,确保语法正确。记得Keras Applications模块提供了这些模型的接口,每个模型都有对应的函数,比如VGG16ResNet50、MobileNetV2等。 用户提到的参考引用[1]和[2]中已经展示了ResNet50和InceptionResNetV2的例子,但用户可能希望更系统地了解不同模型的通用方法。需要确认是否需要加载预训练权重,比如使用weights=&#39;imagenet&#39;,这样模型会下载并缓存权重文件。同时,可能需要注意include_top参数的作用,决定是否包含顶部的全连接层,这对于迁移学习很重要。 接下来,用户可能需要知道如何预处理输入数据,不同模型可能有不同的预处理要求,比如VGG16需要BGR格式的均值减法,而MobileNetV2使用Inception的预处理。需要指出正确的预处理函数,比如preprocess_input,以及如何调整图像尺寸到模型所需的输入大小,比如224x224或299x299。 另外,用户可能关心如何用这些模型进行预测,比如使用decode_predictions来解析输出结果。同时,可能还需要说明如何将模型用于特征提取,通过设置include_top=False来获取中间层的特征。 需要检查是否有常见的错误需要注意,比如输入图像的形状是否正确,预处理步骤是否遗漏,或者模型结构是否与任务匹配。例如,如果用户想进行迁移学习,冻结基础模型并添加自定义层是常见的做法,但用户的问题可能暂时不需要这部分内容,不过可以简要提及。 最后,生成相关问题时,需要考虑用户可能进一步的需求,比如如何微调模型、预处理的不同方法、模型性能比较或者应用场景,以及如何处理缓存问题。这些相关问题可以帮助用户深入理解模型的使用和优化。 总结步骤应该是:导入模型、加载预训练权重、预处理输入、进行预测或特征提取。确保每个步骤都有代码示例,并解释关键参数的作用。同时,引用提供的参考资料来支持回答的正确性。</think>### 从TensorFlow Keras Applications中导入和使用预训练模型 #### 1. 导入模型 从`tensorflow.keras.applications`模块导入所需模型,并指定预训练权重`weights=&#39;imagenet&#39;`。`include_top`参数控制是否包含顶部分类层(适用于迁移学习时需设为`False`): ```python from tensorflow.keras.applications import VGG16, ResNet50, MobileNetV2 # 加载VGG16(默认输入尺寸224x224) vgg_model = VGG16(weights=&#39;imagenet&#39;, include_top=True) # 加载ResNet50(默认输入尺寸224x224) resnet_model = ResNet50(weights=&#39;imagenet&#39;, include_top=False) # 加载MobileNetV2(默认输入尺寸224x224) mobilenet_model = MobileNetV2(weights=&#39;imagenet&#39;, include_top=True) ``` [^1]: 权重文件会自动下载并缓存在`~/.keras/models/`目录。 --- #### 2. 数据预处理 不同模型需使用对应的预处理函数(如`preprocess_input`)和输入尺寸: ```python from tensorflow.keras.preprocessing import image from tensorflow.keras.applications.vgg16 import preprocess_input as vgg_preprocess from tensorflow.keras.applications.mobilenet_v2 import preprocess_input as mobilenet_preprocess # 加载图像并调整尺寸 img_path = &#39;example.jpg&#39; img = image.load_img(img_path, target_size=(224, 224)) # VGG/ResNet/MobileNetV2通用尺寸 # 转换为数组并扩展维度 x = image.img_to_array(img) x = np.expand_dims(x, axis=0) # 使用模型对应的预处理 x_vgg = vgg_preprocess(x) # VGG16需做RGB→BGR通道转换和均值减法 x_mobilenet = mobilenet_preprocess(x) # MobileNetV2使用Inception式缩放 ``` --- #### 3. 模型推理 通过`model.predict()`获取预测结果,并用`decode_predictions`解析: ```python from tensorflow.keras.applications.imagenet_utils import decode_predictions # 使用VGG16预测 vgg_preds = vgg_model.predict(x_vgg) print("VGG16预测结果:", decode_predictions(vgg_preds, top=3)[0]) # 使用MobileNetV2预测(若include_top=True) mobilenet_preds = mobilenet_model.predict(x_mobilenet) print("MobileNetV2预测结果:", decode_predictions(mobilenet_preds)[0]) ``` [^2]: `decode_predictions`默认返回ImageNet类别标签和置信度。 --- #### 4. 特征提取(迁移学习) 冻结基础模型,添加自定义层: ```python from tensorflow.keras.layers import Dense, GlobalAveragePooling2D from tensorflow.keras.models import Model # 加载不带顶层的ResNet50 base_model = ResNet50(weights=&#39;imagenet&#39;, include_top=False, input_shape=(224,224,3)) # 冻结基础模型权重 base_model.trainable = False # 添加自定义层 x = base_model.output x = GlobalAveragePooling2D()(x) x = Dense(1024, activation=&#39;relu&#39;)(x) predictions = Dense(10, activation=&#39;softmax&#39;)(x) # 假设10分类任务 # 构建新模型 custom_model = Model(inputs=base_model.input, outputs=predictions) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

MechMaster

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

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

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

打赏作者

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

抵扣说明:

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

余额充值