动物界的福尔摩斯:基于 EfficientNetB6 的高精度100种动物识别

动物界的福尔摩斯:基于 EfficientNetB6 的高精度100种动物识别

代码详见:https://github.com/xiaozhou-alt/Animals_Recognition



一、项目介绍

本项目是一个功能完整的动物识别系统,包含模型训练与交互应用两大部分。系统基于深度学习技术,能够对 100 种不同类别的动物进行准确识别,并通过精心设计的图形用户界面(GUI)提供友好的交互体验,同时包含一个动物认识的小游戏,以及动物图鉴功能。

该系统主要特点包括:

  • 采用高效的 EfficientNetB6 模型作为基础架构,结合数据增强和正则化技术,实现高精度动物识别
  • 提供三种核心功能:动物图片识别、动物认识小游戏和动物园图鉴
  • 支持动物分类浏览(陆地、海洋、空中动物)
  • 包含用户进度跟踪,记录解锁动物数量和游戏得分
  • 采用现代化 UI 设计,具有动画效果和视觉反馈,提升用户体验

二、文件夹结构

Animals_Recognition/
├── Animal/                         # 核心动物图片资源目录(按动物种类分类存储)
    ├── antelope/                   # 羚羊图片子目录
    └── ...                         # 其他动物子目录(共100种动物)
├── README-data.md                  # 数据相关说明文档
├── README.md
├── assets/                         # 静态资源目录
├── class.txt                       # 动物类别名称文件
├── data.ipynb
├── demo.mp4                        # 项目演示视频
├── demo.py                         # 主应用程序文件
├── log/
├── output/                         # 模型与输出结果目录
    ├── model/                      # 模型存储子目录
    └── pic/                        # 输出图片子目录
├── predict.py                      # 模型预测脚本
├── test/                           # 测试图片目录
├── train.py                        # 模型训练脚本
└── zoo_icons/                      # 动物园图鉴图标目录

三、数据集介绍

本项目使用的动物数据集包含 100 100 100 个不同类别的动物图片,因为使用网页图片提取下载,清洗由我一个人完全进行,数据集数据量较大,所以部分动物文件夹存在 1 % − 1.5 % 1\%-1.5\% 1%1.5% 的噪声图片,数据集组织结构如下:

  • 总类别数 100 100 100 种动物
  • 数据划分:采用 80 % 80\% 80% 作为训练集, 20 % 20\% 20% 作为验证集
  • 图片格式 p n g png png

在模型训练过程中,通过数据增强技术扩充了训练样本,包括旋转、平移、缩放、亮度调整等操作,以提高模型的泛化能力

动物的类别信息请查看class.txt

antelope
badger

woodpecker
zebra

数据集下载:100种动物识别数据集(ScienceDB)

关于数据集的制作和来源请查看:当库里遇上卷积神经网络:基于 EfficientNetV2 的NBA球星分类数据集制作 部分,此文与其使用相同方法制作,只不过图片种类和数量都是翻了一番。。。点个赞,支持一下手艺周吧 orz

四、EfficientNetB6 模型介绍

1. 核心思想:复合模型缩放 (Compound Model Scaling)

E f f i c i e n t N e t EfficientNet EfficientNet 的核心创新在于提出了一个系统化的 模型缩放方法,它不再像传统方法那样单独缩放网络的深度、宽度或输入图像分辨率,而是通过一个复合系数 ϕ ϕ ϕ 来统一缩放这三个维度:
{ 深度 : d = α ϕ 宽度 : w = β ϕ 分辨率 : r = γ ϕ 分辨率 : α ⋅ β 2 ⋅ γ 2 ≈ 2 α ≥ 1 , β ≥ 1 , γ ≥ 1 \left\{ \begin{array}{lr} \textbf{深度}:d = \alpha^{\phi} & \\ \textbf{宽度}:w = \beta^{\phi} & \\ \textbf{分辨率}:r = \gamma^{\phi} & \\ \textbf{分辨率}:\alpha \cdot \beta^{2} \cdot \gamma^{2} \approx 2 & \\ \alpha \geq 1,\quad \beta \geq 1,\quad \gamma \geq 1 \end{array} \right. 深度:d=αϕ宽度:w=βϕ分辨率:r=γϕ分辨率:αβ2γ22α1,β1,γ1
其中 α α α, β β β, γ γ γ 是通过神经架构搜索确定的基础缩放系数, ϕ ϕ ϕ 是用户控制的复合系数。对于 E f f i c i e n t N e t − B 6 EfficientNet-B6 EfficientNetB6 ϕ = 6 ϕ=6 ϕ=6,这意味着它在 B 0 B0 B0 基础版本上进行了大幅度的均衡放大

🤓🤓🤓小周有话说
想象一下你要设计一个高效的 物流系统

  • 深度d):就像仓库的层数,层数越多能存放的货物越多(特征提取能力越强)
  • 宽度w):就像每层仓库的货架数量,货架越多能处理的货物越多(同时处理更多特征)
  • 分辨率r):就像每个货物的检查精细度,检查得越仔细信息越丰富(图像细节越多)

传统方法是只增加层数(导致货物上下运输效率低)或只增加货架(导致管理混乱)。 E f f i c i e n t N e t EfficientNet EfficientNet 的巧妙之处在于同时、均衡地扩大这三个方面,就像设计一个既增加层数、又增加每层货架、还提升检查精细度的智能物流系统,让整体效率最大化

2. 基础构建块:MBConv (Mobile Inverted Bottleneck Conv)

E f f i c i e n t N e t − B 6 EfficientNet-B6 EfficientNetB6 的基本构建单元是 M B C o n v MBConv MBConv 模块,其数学表达可以简化为:
MBConv ( x ) = SE ( DepthwiseConv ( PointwiseConv up ( x ) ) ) × ExpansionRatio + x \text{MBConv}(x) = \text{SE}\left( \text{DepthwiseConv}\left( \text{PointwiseConv}_{\text{up}}(x) \right) \right) \times \text{ExpansionRatio} + x MBConv(x)=SE(DepthwiseConv(PointwiseConvup(x)))×ExpansionRatio+x

具体计算过程为:

  1. 扩展层(1×1卷积):将输入通道数扩展为原来的 t t t 倍( t t t 为扩展系数)
    x expanded = W expand ⋅ x x_{\text{expanded}} = W_{\text{expand}} \cdot x xexpanded=Wexpandx
  2. 深度可分离卷积(3×35×5):
    x dw = DepthwiseConv ( x expanded ) x_{\text{dw}} = \text{DepthwiseConv}\left( x_{\text{expanded}} \right) xdw=DepthwiseConv(xexpanded)
  3. S q u e e z e − a n d − E x c i t a t i o n Squeeze-and-Excitation SqueezeandExcitation 注意力机制:
    x se = x dw ⋅ σ ( W 2 ⋅ ReLU ( W 1 ⋅ GAP ( x dw ) ) ) x_{\text{se}} = x_{\text{dw}} \cdot \sigma\left( W_{2} \cdot \text{ReLU}\left( W_{1} \cdot \text{GAP}\left( x_{\text{dw}} \right) \right) \right) xse=xdwσ(W2ReLU(W1GAP(xdw)))
  4. 投影层(1×1卷积):将通道数压缩回原始维度
    x projected = W project ⋅ x se x_{\text{projected}} = W_{\text{project}} \cdot x_{\text{se}} xprojected=Wprojectxse
  5. 残差连接(如果输入输出维度匹配):
    Output = x projected + x \text{Output} = x_{\text{projected}} + x Output=xprojected+x

EfficientNetB6 的模型架构示意图如下:
在这里插入图片描述

🤓🤓🤓小周有话说
M B C o n v MBConv MBConv 模块想象成一个高效的 信息处理工厂

  1. 扩展层:就像把产品拆分成更小的零部件(扩展通道数),方便后续精细加工
  2. 深度可分离卷积:就像让不同的专家小组同时处理不同的零部件(深度卷积),大大提高了工作效率
  3. SE注意力机制:就像有个智能总监,时刻关注哪些零部件最重要(通道注意力),然后给重要的零部件分配更多资源
  4. 投影层:就像把处理好的零部件重新组装成最终产品(压缩回原始通道数
  5. 残差连接:就像保留原材料的样本,确保最终产品不会在加工过程中失去原有优点

这种设计让模型既保持了强大的特征提取能力,又极大减少了计算量和参数数量。

3. 在项目中的应用

在动物分类项目中, E f f i c i e n t N e t − B 6 EfficientNet-B6 EfficientNetB6 作为 特征提取器,其预训练的权重提供了强大的图像表示能力,采用了迁移学习策略,具体表现为:

  1. 冻结底层权重:保留预训练模型的前 200 200 200 层权重不变,仅训练顶层
    L total = L CE + λ ⋅ L reg \mathcal{L}_{\text{total}} = \mathcal{L}_{\text{CE}} + \lambda \cdot \mathcal{L}_{\text{reg}} Ltotal=LCE+λLreg
    其中交叉熵损失 L CE = − ∑ i = 1 N y i log ⁡ ( y ^ i ) \mathcal{L}{\text{CE}} = -\sum{i=1}^{N} y_i \log(\hat{y}i) LCE=i=1Nyilog(y^i),正则化损失 L reg = ∣ W ∣ 2 2 \mathcal{L}{\text{reg}} = |\mathbf{W}|_2^2 Lreg=W22

  2. 自定义分类头:添加了包含批量归一化、 D r o p o u t Dropout Dropout L 2 L2 L2 正则化的自定义层,以适应 100 100 100 类动物分类任务
    Output = Softmax ( W ⋅ Dropout ( B N ( ReLU ( W h ⋅ x ) ) ) ) \text{Output} = \text{Softmax}(\mathbf{W} \cdot \text{Dropout}(\mathbf{BN}(\text{ReLU}(\mathbf{W}_h \cdot \mathbf{x})))) Output=Softmax(WDropout(BN(ReLU(Whx))))

  3. 混合精度训练:使用 f l o a t 16 float16 float16 进行计算,减少内存使用并加速训练过程,同时使用 f l o a t 32 float32 float32 进行 s o f t m a x softmax softmax 计算以保证数值稳定性

五、项目实现

1. 自定义学习率跟踪回调

  • 创建一个自定义回调类LRTracker,继承自Callback
  • 在初始化方法中创建一个空列表lr_history用于存储学习率历史
  • 重写on_epoch_end方法,在每个训练周期结束时获取当前学习率并保存
  • 同时将学习率添加到日志中,确保它被记录到训练历史中
# 自定义回调用于记录学习率
class LRTracker(Callback):
    def __init__(self):
        super(LRTracker, self).__init__()
        self.lr_history = []
    
    def on_epoch_end(self, epoch, logs=None):
        current_lr = tf.keras.backend.get_value(self.model.optimizer.lr)
        self.lr_history.append(current_lr)
        logs = logs or {}
        logs['lr'] = current_lr  # 确保学习率被记录到history中

2. 参数配置

  • 设置所有重要的超参数和路径
  • data_dir指定数据集所在目录
  • num_classes设置为 100 100 100,表示有 100 100 100 种动物类别
  • img_size设置为 (456,   456) \textbf{(456, 456)} (456, 456),这是 EfficientNetB6 模型推荐的输入尺寸
  • batch_size设置为 12 12 12,平衡内存使用和训练效率
  • epochs设置为 20 20 20,限制训练时间
  • 其他参数包括早停耐心值、 L 2 L2 L2 正则化系数、 D r o p o u t Dropout Dropout 比率和初始学习率
# 参数配置
data_dir = '/kaggle/input/animals/Animal/Animal'  # 数据集路径
num_classes = 100
img_size = (456, 456)  # B6模型推荐尺寸
batch_size = 12  # 增加批次大小以提高GPU利用率
epochs = 20  # 减少轮数以适应12小时限制
patience = 5  # 早停等待轮数
l2_reg = 1e-4  # L2正则化系数
dropout_rate = 0.3  # Dropout比率
initial_lr = 1e-4  # 初始学习率

3. 数据增强和生成器设置

  • 使用ImageDataGenerator创建数据增强管道,包括多种图像变换技术:
    • 像素值归一化(rescale = 1. / 255 =1./255 =1./255
    • 随机旋转(rotation_range = 30 =30 =30
    • 水平和垂直平移(width_shift_rangeheight_shift_range
    • 剪切变换(shear_range
    • 缩放变换(zoom_range
    • 亮度调整(brightness_range
    • 水平和垂直翻转
    • 设置 20 % 20\% 20% 的数据作为验证集(validation_split = 0.2 =0.2 =0.2
  • 创建训练和验证数据生成器,从目录中加载图像
  • 获取类别名称并打印训练和验证样本数量
# 创建数据增强
train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range=30,
    width_shift_range=0.25,
    height_shift_range=0.25,
    shear_range=0.2,
    zoom_range=0.3,
    brightness_range=[0.7, 1.3],
    horizontal_flip=True,
    vertical_flip=True,
    fill_mode='nearest',
    validation_split=0.2  # 80%训练,20%验证
)
# 训练集生成器
train_generator = train_datagen.flow_from_directory(
    data_dir,
    target_size=img_size,
    batch_size=batch_size,
    class_mode='categorical',
    subset='training',
    shuffle=True,
    seed=42
)
# 验证集生成器
val_generator = train_datagen.flow_from_directory(
    data_dir,
    target_size=img_size,
    batch_size=batch_size,
    class_mode='categorical',
    subset='validation',
    shuffle=False,  # 验证集不洗牌,确保一致性
    seed=42
)

终端划分完毕的数据集信息:

Found 31803 images belonging to 100 classes.
Found 7901 images belonging to 100 classes.
训练样本数: 31803, 验证样本数: 7901

4. 学习率调度函数

  • 定义一个自定义学习率调度函数accelerated_lr_schedule
  • 使用 预热策略:前 3 3 3 个周期逐步增加学习率到初始值
  • 4 4 4 到第 10 10 10 个周期保持初始学习率
  • 10 10 10 个周期后开始 指数衰减学习率
  • 这种策略有助于模型快速收敛并 防止过拟合
# 加速学习率调度
def accelerated_lr_schedule(epoch):
    """更激进的学习率调度以快速收敛"""
    warmup_epochs = 3
    decay_start = 10
    if epoch < warmup_epochs:
        # 学习率预热
        return initial_lr * (epoch + 1) / warmup_epochs
    elif epoch < decay_start:
        # 保持高学习率
        return initial_lr
    else:
        # 指数衰减
        return initial_lr * math.exp(0.1 * (decay_start - epoch))

5. 模型构建函数

  • 使用 EfficientNetB6 作为基础模型,加载在 I m a g e N e t ImageNet ImageNet 上预训练的权重
  • 冻结前 200 200 200 层,只训练后面的层(迁移学习 策略)
  • 添加自定义顶层:
    • 全局平均池化层
    • 全连接层( 1024 1024 1024 个神经元, R e L U ReLU ReLU 激活, L 2 L2 L2 正则化)
    • 批归一化层
    • D r o p o u t Dropout Dropout 层(防止过拟合)
    • 另一个全连接层( 512 512 512 个神经元)
    • 另一个批归一化和 D r o p o u t Dropout Dropout
  • 使用 L a m b d a Lambda Lambda 层将数据类型转换为 f l o a t 32 float32 float32,确保与混合精度训练兼容
  • 最后添加输出层( 100 100 100 个神经元, s o f t m a x softmax softmax 激活)
  • 编译模型,使用 A d a m Adam Adam 优化器和分类交叉熵损失函数
# 构建模型
def create_model():
    base_model = EfficientNetB6(
        include_top=False,
        weights='imagenet',
        input_shape=(img_size[0], img_size[1], 3),
        pooling=None
    )
    # 冻结底层,微调上层
    base_model.trainable = True
    for layer in base_model.layers[:200]:
        layer.trainable = False
    # 添加自定义顶层
    x = base_model.output
    x = GlobalAveragePooling2D()(x)
    x = Dense(1024, activation='relu', kernel_regularizer=l2(l2_reg))(x)
    x = BatchNormalization()(x)
    x = Dropout(dropout_rate)(x)
    x = Dense(512, activation='relu', kernel_regularizer=l2(l2_reg))(x)
    x = BatchNormalization()(x)
    x = Dropout(dropout_rate/2)(x)
    
    # 修复:使用Lambda层进行类型转换
    x = Lambda(lambda t: tf.cast(t, tf.float32))(x)
    predictions = Dense(num_classes, activation='softmax', dtype=tf.float32)(x)
    model = Model(inputs=base_model.input, outputs=predictions)
    model.compile(
        optimizer=Adam(learning_rate=initial_lr),
        loss='categorical_crossentropy',
        metrics=['accuracy']
    )
    return model

6. 回调函数设置

  • 创建多个回调函数以增强训练过程:
    • EarlyStopping: 当验证损失不再改善时停止训练,防止过拟合
    • ReduceLROnPlateau: 当验证损失停滞时降低学习率
    • ModelCheckpoint: 保存验证损失最低的模型
    • LearningRateScheduler: 使用自定义学习率调度函数
    • LRTracker: 自定义学习率跟踪回调
# 创建学习率跟踪器
lr_tracker = LRTracker()
# 回调函数
callbacks = [
    EarlyStopping(
        monitor='val_loss', 
        patience=patience, 
        verbose=1, 
        restore_best_weights=True,
        min_delta=0.001
    ),
    ReduceLROnPlateau(
        monitor='val_loss', 
        factor=0.5, 
        patience=2, 
        min_lr=1e-6, 
        verbose=1
    ),
    ModelCheckpoint(
        '/kaggle/working/best_model.keras', 
        monitor='val_loss', 
        save_best_only=True, 
        verbose=1
    ),
    LearningRateScheduler(accelerated_lr_schedule, verbose=1),
    lr_tracker  # 添加学习率跟踪器
]

7. 开始训练!

  • 使用model.fit()方法训练模型
  • 指定训练和验证数据生成器
  • 计算每个周期的步骤数(样本数除以批次大小)
  • 训练完成后,确保学习率历史被正确记录
  • 将训练历史保存到 Excel 文件中,便于后续分析
# 训练模型
print("开始训练模型...")
history = model.fit(
    train_generator,
    steps_per_epoch=train_generator.samples // batch_size,
    validation_data=val_generator,
    validation_steps=val_generator.samples // batch_size,
    epochs=epochs,
    callbacks=callbacks,
    verbose=1
)
# 确保学习率被记录到历史中
if 'lr' not in history.history:
    history.history['lr'] = lr_tracker.lr_history
# 保存训练历史
history_df = pd.DataFrame(history.history)
history_df.to_excel('/kaggle/working/training_history.xlsx', index=False)

训练输出示例如下:

开始训练模型…
Epoch 1: LearningRateScheduler setting learning rate to 3.3333333333333335e-05.
Epoch 1/25
2650/2650 ━━━━━━━━━━━━━━━━━━━━ 0s 845ms/step - accuracy: 0.0342 - loss: 5.2547
Epoch 1: val_loss improved from inf to 3.71864, saving model to /kaggle/working/best_model.keras
2650/2650 ━━━━━━━━━━━━━━━━━━━━ 2982s 1s/step - accuracy: 0.0342 - loss: 5.2546 - val_accuracy: 0.2088 - val_loss: 3.7186 - learning_rate: 3.3333e-05 - lr: 3.3333e-05
Epoch 2: LearningRateScheduler setting learning rate to 6.666666666666667e-05.

Epoch 25: val_loss improved from 0.68474 to 0.65006, saving model to /kaggle/working/best_model.keras
2650/2650 ━━━━━━━━━━━━━━━━━━━━ 2277s 859ms/step - accuracy: 0.9122 - loss: 0.5337 - val_accuracy: 0.9007 - val_loss: 0.6501 - learning_rate: 2.4660e-05 - lr: 2.4660e-05
Restoring model weights from the end of the best epoch: 25.
在验证集上评估模型…
659/659 ━━━━━━━━━━━━━━━━━━━━ 430s 613ms/step - accuracy: 0.8823 - loss: 0.7223
验证集准确率: 0.8946
生成预测结果…
659/659 ━━━━━━━━━━━━━━━━━━━━ 420s 612ms/step
随机抽取验证样本可视化…
==================================================
所有操作已完成!
最佳模型已保存为: best_model.keras
训练历史已保存为: training_history.xlsx
类别准确率报告已保存为: class_accuracy_report.xlsx
验证集准确率: 0.8946
总训练时间: 9小时 49分钟 18秒
==================================================

ps:模型虽有设置早停机制,最优模型的保存仍是设置的上限(epoch = 25 =25 =25),受限于 kaggle 的 GPU 单次使用时间上限,小周没有进一步训练,有条件的 UU 可以设置更大的训练轮数和早停耐心值

8. 模型评估和预测

  • 在验证集上评估模型性能,计算 损失准确率
  • 生成预测结果,获取真实标签和预测标签
  • 计算 混淆矩阵,显示模型在 每个类别 上的预测情况
  • 使用分类报告获取每个类别的精确率、召回率和 F 1 F1 F1 分数
  • 分析每个类别的主要错误类型和错误比例
  • 将所有类别级别的指标保存到 Excel 文件中
# 加载最佳模型
model = load_model('/kaggle/working/best_model.keras')
# 在验证集上评估
print("\n在验证集上评估模型...")
val_loss, val_acc = model.evaluate(val_generator)
print(f"验证集准确率: {val_acc:.4f}")
# 生成预测结果
print("\n生成预测结果...")
y_true = val_generator.classes
y_pred = model.predict(val_generator, verbose=1).argmax(axis=1)

# 计算混淆矩阵
cm = confusion_matrix(y_true, y_pred)
# 分析每个类别的准确率和错误情况
class_report = classification_report(y_true, y_pred, target_names=class_names, output_dict=True)
class_metrics = []
for i, class_name in enumerate(class_names):
    # 类别准确率
    precision = class_report[class_name]['precision']
    recall = class_report[class_name]['recall']
    f1 = class_report[class_name]['f1-score']
    support = class_report[class_name]['support']
    # 主要错误类别
    class_errors = cm[i].copy()
    class_errors[i] = 0  # 忽略正确预测
    if np.sum(class_errors) > 0:
        main_error_idx = np.argmax(class_errors)
        main_error_class = class_names[main_error_idx]
        error_count = class_errors[main_error_idx]
        error_percent = error_count / np.sum(class_errors) * 100
    else:
        main_error_class = "无错误"
        error_count = 0
        error_percent = 0
    class_metrics.append({
        '类别': class_name,
        '精确率': precision,
        '召回率': recall,
        'F1分数': f1,
        '样本数': support,
        '主要误判类别': main_error_class,
        '误判数量': error_count,
        '误判占比(%)': error_percent
    })
# 保存类别准确率结果
metrics_df = pd.DataFrame(class_metrics)
metrics_df.to_excel('/kaggle/working/class_accuracy_report.xlsx', index=False)

9. 样本预测可视化

  • 随机选择 12 12 12 个验证样本进行可视化
  • 对每个样本进行预测,获取预测标签和置信度
  • 创建3×4的子图布局,显示每个样本图像、真实标签、预测标签和置信度
  • 正确预测用绿色标题,错误预测用红色标题
# 随机抽取12个验证样本可视化(节省空间)
print("\n随机抽取验证样本可视化...")
sample_indices = random.sample(range(len(val_generator.filepaths)), 12)
sample_images = []
sample_true_labels = []
sample_pred_labels = []
sample_probs = []

for idx in sample_indices:
    img_path = val_generator.filepaths[idx]
    img = tf.keras.preprocessing.image.load_img(img_path, target_size=img_size)
    img_array = tf.keras.preprocessing.image.img_to_array(img) / 255.0
    sample_images.append(img_array)
    sample_true_labels.append(class_names[y_true[idx]])
    # 获取预测概率
    pred_probs = model.predict(np.expand_dims(img_array, axis=0), verbose=0)[0]
    pred_idx = np.argmax(pred_probs)
    sample_pred_labels.append(class_names[pred_idx])
    sample_probs.append(pred_probs[pred_idx])

# 可视化结果
plt.figure(figsize=(15, 12))
for i in range(12):
    plt.subplot(3, 4, i+1)
    plt.imshow(sample_images[i])
    color = 'green' if sample_true_labels[i] == sample_pred_labels[i] else 'red'
    title = f"True: {sample_true_labels[i]}\nPred: {sample_pred_labels[i]}\nProb: {sample_probs[i]:.2f}"
    plt.title(title, fontsize=10, color=color)
    plt.axis('off')
plt.tight_layout()
plt.savefig('/kaggle/working/sample_predictions.png', dpi=150)
plt.close()

六、结果展示

训练过程中记录的关键指标包括:

  1. 损失与准确率曲线
    • 训练损失与验证损失的变化趋势
    • 训练准确率与验证准确率的提升过程

在这里插入图片描述
2. 混淆矩阵

展示模型在验证集上的分类结果,对角线元素表示正确分类的样本数,非对角线元素表示分类错误的样本数

在这里插入图片描述
3. 类别性能分析

每个动物类别的精确率、召回率和 F1 分数,帮助识别模型表现较好和较差的类别

在这里插入图片描述
模型在验证集抽取的样本预测展示如下所示:

在这里插入图片描述

Reference

[1] EfficientNet 模型的完整细节

如果你喜欢我的文章,不妨给小周一个免费的点赞和关注吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值