训练 DNN





5.00/5 (3投票s)
在本文中,我们将讨论使用增强数据集训练我们的 DNN 分类器。
引言
不受控制的野生动物对于企业和房主来说都是一个难题。像鹿、驼鹿甚至猫这样的动物都会对花园、庄稼和财产造成破坏。
在本系列文章中,我们将演示如何在树莓派上实时(或接近实时)检测害虫(例如麋鹿),然后采取行动消灭害虫。由于我们不想造成任何伤害,我们将侧重于通过播放嘈杂的声音来吓跑害虫。
欢迎您下载项目的源代码。我们假设您熟悉 Python,并且对神经网络的工作原理有基本的了解。
在之前的文章中,我们组装了一个用于麋鹿检测的数据集,其中包含具有麋鹿类别和背景类别对象的图像。在本文中,我们将开发一个分类器 DNN 模型并在我们的数据集上对其进行训练。我们将使用Caffe来创建和训练 DNN。请在您的电脑上安装此框架以继续学习。
开发 DNN
DNN 开发始于创建模型结构。由于我们将在树莓派上使用我们的神经网络,因此该模型应该轻量级,以便它可以以足够的速度运行。
从头开始设计优化的 DNN 模型是一个相当复杂的任务,我们在这里不会详细描述。我们建议使用以下网络架构
这是一个使用免费在线编辑器可视化的 Caffe DNN 模型。它可能不是绝对最好的模型,但绝对足以满足我们的目的。
这源于AlexNet 架构,这是第一个(也是最简单的)成功应用于图像分类的网络。我们已经裁剪并优化了原始架构,用于对少量对象类别进行分类。生成的模型有四个卷积层,具有 64-128-128-64 个内核(卷积滤波器)。
还有两个池化层用于减小输入图像的尺寸,使其达到 128 x 128 像素。中间的全连接 (FC) 层有 256 个神经元,最后一个 FC 层有两个神经元(每个对象类别一个用于分类:背景和麋鹿)。
我们还需要一个组件,那就是训练模型,这是一个修改后的分类模型,它替换了输入和输出层。
训练模型的输入层必须指定用于训练和测试的带标签数据的来源。输出层必须指定在训练期间最小化的损失函数。
为了提供带标签的数据源,我们创建文本文件,其中包含指向我们所有带标签的样本图像的路径(图像的对象类别标识符)。让我们将我们的样本图像组织到以下文件夹中
PI_PEST
- 学习
- 0
- 1
- 测试
- 0
- 1
如您所见,我们有两个主要文件夹,Learning 和 Testing,分别用于训练和测试。0 子文件夹用于背景样本,1 子文件夹用于麋鹿样本。
首先,将每类 500 张样本图像移动到 Testing 目录,并将所有剩余图像移动到 Learning 目录。现在让我们编写一些 Python 代码来生成源文件
import os
import numpy as np
import cv2
class TrainFiler:
def get_labels(self, folder):
subfolders = os.scandir(folder)
labels = []
for classfolder in subfolders:
class_name = os.path.basename(classfolder)
files = FileUtils.get_files(classfolder)
for (i, fname) in enumerate(files):
label = fname + " " + class_name
labels.append(label)
return labels
def save_labels(self, labels, filename):
with open(filename, 'w') as f:
for label in labels:
f.write('%s\n' % label)
def gen_train_files(self, learn_folder, test_folder, learn_file, test_file):
labels = self.get_labels(learn_folder)
self.save_labels(labels, learn_file)
labels = self.get_labels(test_folder)
self.save_labels(labels, test_file)
我们可以像这样运行它
learn_folder = r"C:\PI_PEST\Learning"
test_folder = r"C:\PI_PEST\Testing"
learn_file = r"C:\PI_PEST\classeslearn.txt"
test_file = r"C:\PI_PEST\classestest.txt"
filer = TrainFiler()
filer.gen_train_files(learn_folder, test_folder, learn_file, test_file)
这将生成两个包含以下数据的源文件
…
C:\PI_PEST\Learning\0\vlcsnap-2020-10-26-16h13m39s332(x253,y219,w342,h342)fliprotate15.png 0
C:\PI_PEST\Learning\0\vlcsnap-2020-10-26-16h13m39s332(x253,y219,w342,h342)fliprotate_15.png 0
C:\PI_PEST\Learning\1\vlcsnap-2020-10-21-13h46m55s365(x106,y28,w633,h633).png 1
C:\PI_PEST\Learning\1\vlcsnap-2020-10-21-13h46m55s365(x106,y28,w633,h633)flip.png 1
…
…
C:\PI_PEST\Testing\0\vlcsnap-2020-10-26-16h16m22s719(x39,y36,w300,h300)smooth5rotate15.png 0
C:\PI_PEST\Testing\0\vlcsnap-2020-10-26-16h16m22s719(x39,y36,w300,h300)smooth5rotate_15.png 0
C:\PI_PEST\Testing\1\vlcsnap-2020-10-26-16h08m31s421(x276,y0,w566,h566)flipsharpen5.png 1
C:\PI_PEST\Testing\1\vlcsnap-2020-10-26-16h08m31s421(x276,y0,w566,h566)flipsharpen5rotate15.png 1
…
在开始训练过程之前,最后一件事是准备所谓的求解器规范。对于 Caffe 框架,这是一个包含训练过程参数的文本文件。
net: "classes_learn_test.prototxt"
test_iter: 1000
max_iter: 100000
base_lr: 0.001
solver_mode: CPU
net
参数指定“训练”模型的路径,test_iter
是精度测试的周期,max_iter
是要运行的最大迭代次数,base_lr
是学习率的起始值,solver_mode
参数定义训练过程是在 CPU 还是 GPU 上执行。
要启动 Caffe 进行模型训练,我们需要将以下数据文件复制到 Caffe 可执行文件夹:classes_learn_test.prototxt(训练文件)、classeslearn.txt 和 classestest.txt(生成的训练和测试数据文件)以及 classes_solver.prototxt(求解器规范文件)。
使用以下命令启动训练过程
caffe.exe train -solver=classes_solver.prototxt
在打开的控制台窗口中,您可以看到训练过程的进度
I1028 09:10:24.546773 32860 solver.cpp:330] Iteration 3000, Testing net (#0)
I1028 09:13:12.228042 32860 solver.cpp:397] Test net output #0: accuracy = 0.95
I1028 09:13:12.229039 32860 solver.cpp:397] Test net output #1: loss = 0.209061 (* 1 = 0.209061 loss)
I1028 09:13:12.605070 32860 solver.cpp:218] Iteration 3000 (1.83848 iter/s, 543.929s/1000 iters), loss = 0.0429298
I1028 09:13:12.605070 32860 solver.cpp:237] Train net output #0: loss = 0.00469132 (* 1 = 0.00469132 loss)
I1028 09:13:12.608062 32860 sgd_solver.cpp:105] Iteration 3000, lr = 0.000800107
I1028 09:19:11.598755 32860 solver.cpp:447] Snapshotting to binary proto file classes_iter_4000.caffemodel
I1028 09:19:11.641045 32860 sgd_solver.cpp:273] Snapshotting solver state to binary proto file classes_iter_4000.solverstate
I1028 09:19:11.661990 32860 solver.cpp:330] Iteration 4000, Testing net (#0)
I1028 09:21:51.567586 32860 solver.cpp:397] Test net output #0: accuracy = 0.971
I1028 09:21:51.568584 32860 solver.cpp:397] Test net output #1: loss = 0.0755974 (* 1 = 0.0755974 loss)
I1028 09:21:51.942620 32860 solver.cpp:218] Iteration 4000 (1.92553 iter/s, 519.337s/1000 iters), loss = 0.0283988
I1028 09:21:51.942620 32860 solver.cpp:237] Train net output #0: loss = 0.0119124 (* 1 = 0.0119124 loss)
I1028 09:21:51.942620 32860 sgd_solver.cpp:105] Iteration 4000, lr = 0.000751262
I1028 09:29:05.931291 32860 solver.cpp:447] Snapshotting to binary proto file classes_iter_5000.caffemodel
I1028 09:29:06.011082 32860 sgd_solver.cpp:273] Snapshotting solver state to binary proto file classes_iter_5000.solverstate
I1028 09:29:06.042008 32860 solver.cpp:330] Iteration 5000, Testing net (#0)
I1028 09:32:13.374222 32860 solver.cpp:397] Test net output #0: accuracy = 0.877
I1028 09:32:13.374222 32860 solver.cpp:397] Test net output #1: loss = 0.861016 (* 1 = 0.861016 loss)
I1028 09:32:13.743319 32860 solver.cpp:218] Iteration 5000 (1.60823 iter/s, 621.8s/1000 iters), loss = 0.000519958
I1028 09:32:13.743319 32860 solver.cpp:237] Train net output #0: loss = 0.000306881 (* 1 = 0.000306881 loss)
I1028 09:32:13.745313 32860 sgd_solver.cpp:105] Iteration 5000, lr = 0.000708472
我们应该监控的值是accuracy
。它在第 4000 次迭代时增加到 97.1%,然后开始下降。这可能是由于训练模型的过拟合。因此,我们应该停止该过程并从第 4000th 次迭代中获取模型文件。
后续步骤
在下一篇文章中,我们将向您展示如何开发一个简单的运动检测器,并将其与训练好的 DNN 模型结合起来以检测视频中的麋鹿。