AnyMath 文档
Notebook

使用卷积神经网络进行图像分类

在这个项目中,我们正在训练一个卷积神经网络来对几个类的图像进行分类。 在输出端,我们得到一个训练有素的算法,该算法将图像作为输入,并返回它可能属于的类的预测。

让我们准备环境

我们将安装必要的软件包并配置环境以显示静态图形。 如果库出现问题,请运行命令 EngeePkg.purge(),这将从您的系统中消除除系统软件包之外的所有软件包,并允许您在没有兼容性问题的情况下安装必要的软件包。

In [ ]:
# 安装必要的软件包
Pkg.add(["Flux", "BSON", "ImageTransformations"])
gr();

训练数据位于"训练数据"目录中的几个文件夹中。 文件夹名称从文件系统中读取并成为类名。 我们还指出了分类示例(带有未知标签)的位置。

In [ ]:
DATA_DIR = "$(@__DIR__)/учебные данные";
UNKNOWN_DIR = "$(@__DIR__)/неизвестно";

模型训练和验证

在这个项目中,我们将从头开始训练以下类型的卷积模型:

default_neuralnet_architecture.svg

在脚本中 train.jl 进行的功能进行收集:

  1. 上传图片从类文件夹,调整大小为128x128,规范化
  2. 计算类的不平衡(多少叉,多少汤匙)
  3. 数据划分为列车/测试(分层,75%/25%)
  4. *模型组装—-卷积网络与BatchNorm和Dropout
  5. 平衡批次-所以在每个屠夫有两个类平等
  6. *增强—-通过反射和突出显示使数据集中的样本加倍
  7. 学习周期-前进传球,损失计算,后退传球,体重更新
  8. 质量评估-准确性,精度,召回测试
  9. 提前停止-停止,如果没有改善8个时代
  10. 保存最佳模型
In [ ]:
include("$(@__DIR__)/_scripts/train.jl")
model, classes = train_model(DATA_DIR; epochs=25, batch_size=16, lr=0.0005, test_split=0.25);
Размер батча: 16, Скорость обучения: 0.0005
Доля тестовой выборки: 25.0%
Найдено классов: 2: ["вилка", "ложка"]

=== Распределение классов ===

Всего изображений: 335 (128×128)
  вилка: 189 изображений (56.4%)
  ложка: 146 изображений (43.6%)

=== Разделение данных ===
  Тренировочных: 252 (75.2%)
  Тестовых: 83 (24.8%)
Параметров модели: 607810

=== Обучение ===
  Эпоха  1/25, Train Loss: 1.3937, Train Acc: 44.4%, Test Acc: 44.6% ★  (precision/recall по классам: вилка: 65.2%/31.9%, ложка: 46.7%/77.8%)
  Эпоха  2/25, Train Loss: 1.3289, Train Acc: 48.0%, Test Acc: 42.2%    (precision/recall по классам: вилка: 75.0%/12.8%, ложка: 45.3%/94.4%)
  Эпоха  3/25, Train Loss: 1.3427, Train Acc: 66.3%, Test Acc: 61.4% ★  (precision/recall по классам: вилка: 63.8%/78.7%, ложка: 60.0%/41.7%)
  Эпоха  4/25, Train Loss: 1.1816, Train Acc: 57.1%, Test Acc: 49.4%    (precision/recall по классам: вилка: 72.7%/17.0%, ложка: 45.8%/91.7%)
  Эпоха  5/25, Train Loss: 1.1303, Train Acc: 79.0%, Test Acc: 75.9% ★  (precision/recall по классам: вилка: 71.7%/80.9%, ложка: 70.0%/58.3%)
  Эпоха  6/25, Train Loss: 1.0433, Train Acc: 73.4%, Test Acc: 68.7%    (precision/recall по классам: вилка: 77.8%/74.5%, ложка: 68.4%/72.2%)
  Эпоха  7/25, Train Loss: 0.9447, Train Acc: 78.2%, Test Acc: 67.5%    (precision/recall по классам: вилка: 78.0%/68.1%, ложка: 64.3%/75.0%)
  Эпоха  8/25, Train Loss: 0.9592, Train Acc: 79.4%, Test Acc: 73.5%    (precision/recall по классам: вилка: 90.6%/61.7%, ложка: 64.7%/91.7%)
  Эпоха  9/25, Train Loss: 1.0558, Train Acc: 84.1%, Test Acc: 75.9%    (precision/recall по классам: вилка: 93.8%/63.8%, ложка: 66.7%/94.4%)
  Эпоха 10/25, Train Loss: 0.8999, Train Acc: 81.3%, Test Acc: 67.5%    (precision/recall по классам: вилка: 78.9%/63.8%, ложка: 62.2%/77.8%)
  Эпоха 11/25, Train Loss: 0.97, Train Acc: 86.5%, Test Acc: 75.9%    (precision/recall по классам: вилка: 78.3%/76.6%, ложка: 70.3%/72.2%)
  Эпоха 12/25, Train Loss: 0.8364, Train Acc: 89.3%, Test Acc: 75.9%    (precision/recall по классам: вилка: 82.9%/72.3%, ложка: 69.0%/80.6%)
  Эпоха 13/25, Train Loss: 0.7675, Train Acc: 79.4%, Test Acc: 66.3%    (precision/recall по классам: вилка: 67.7%/89.4%, ложка: 76.2%/44.4%)

  ⏹ Ранний останов после 13 эпох (нет улучшения 8 эпох)

Загружена лучшая модель (Test Acc: 75.9%)

=== Результаты ===
  Лучшая точность на тесте: 75.9%
  Точность train/test: 78.2% / 72.3%
  ✓ Нет переобучения (разрыв 5.9%)
Обучение завершено! 🚀
Модель сохранена в model.bson

训练后,我们将改变模型的行为方式。 该脚本执行以下步骤:

  1. *加载模型、元数据和未知图像—-从BSON文件中提取训练集每个类中的网络架构、权重、类名和示例数,并将模型切换到评估模式。 扫描指定的文件夹,每个图像缩小到128×128的大小,归一化到范围[-1,1]并转换为张量格式W×H×C

  2. *每个图像的分类—-张量馈送到模型的输入,输出logits通过softmax转换为概率,确定具有最大概率和相应置信度的类,并按类进行分组

  3. 按置信度和统计输出排序-在每个类中,图像从最自信的预测到最不自信的预测进行排序。 预测图像的数量,总数的百分比,平均值,最大和最小置信度

  4. 偏倚分析-每个类的预测百分比与该类在训练集中的百分比的比较,指标输出

In [ ]:
include("$(@__DIR__)/_scripts/visualize.jl")
results = classify_and_visualize(UNKNOWN_DIR);
=== Статистика обучающего набора ===
  вилка: 189 изображений
  ложка: 146 изображений

=== Результаты классификации ===
  вилка:
    Количество: 5 (50.0%)
    Средняя уверенность: 0.902
    Макс/мин уверенность: 1.0 / 0.752
  ложка:
    Количество: 5 (50.0%)
    Средняя уверенность: 0.626
    Макс/мин уверенность: 0.692 / 0.578

=== Анализ смещения ===
  вилка: 50.0% предсказано vs 56.4% обучено ✓
  ложка: 50.0% предсказано vs 43.6% обучено ✓

我们将对"未知"文件夹中的所有图像进行分类,并为每个类输出最多10个图像。

In [ ]:
include("$(@__DIR__)/_scripts/simple_mosaic.jl")
plot(create_simple_mosaic(UNKNOWN_DIR))
Out[0]:
No description has been provided for this image

下面的脚本允许您重新打开训练好的模型,从未标记的示例目录中预测所有文件的类,并将结果输出到表中。

In [ ]:
include("$(@__DIR__)/_scripts/predict_to_csv.jl")
predict_to_csv(UNKNOWN_DIR, confidence_threshold=0.6, output_csv="$(@__DIR__)/predictions.csv")
Обработано файлов: 10
  вилка: 5
  ложка: 4
  неизвестно: 1

Сохранено в /user/_retrain_resnet/predictions.csv
Out[0]:
10×5 DataFrame
RowФайлПредсказанный_классУверенностьВероятность_вилкаВероятность_ложка
StringStringFloat32Float32Float32
100000495.jpgвилка0.9997570.9997570.000242674
200000496.pngвилка0.9958160.9958160.00418395
300000494.jpgвилка0.9363420.9363420.0636576
400000497.jpgвилка0.8243740.8243740.175625
500000498.jpgвилка0.7522250.7522250.247775
600000194.jpgложка0.6923430.3076570.692343
700000193.pngложка0.620940.379060.62094
800000196.jpgложка0.6184810.3815190.618481
900000195.jpgложка0.6182840.3817160.618284
1000000192.jpgнеизвестно0.5779280.4220720.577928

结论

该项目为一个简单的任务奠定了基础:将图像排列在多个文件夹中,并训练一个分类器,该分类器将允许您将具有未知对象的第二个文件夹中的图像分

示例中呈现的结果是使用经过数十次学习过程迭代的神经网络获得的。 为了获得一个好的分类算法,你需要改变超参数,研究数据集,改变训练的持续时间,神经网络的拓扑结构(更多层,打开或关闭批量归一化等。),批次或优化器的大小,消除过早关闭的障碍,或简单地改变随机数发生器的设置。