在这个 keras 教程中, 您将发现开始使用深度学习和 Python 是多么容易. 您将使用 Keras 深度学习库来在自定义图像数据集上训练您的第一个神经网络, 并且您也将实现第一个卷积神经网络(CNN).
这个指南的灵感来自 PyImageSearch https://www.pyimagesearch.com/ 读者 Igor, 他几周前给我发了电子邮件这样问到:
嘿, Adrian, 谢谢 PyImageSearch https://www.pyimagesearch.com/ 上的精彩博客. 我发现几乎每个 Keras 或图像分类 "入门指南" 都使用内置在 Keras 的 MNIST 或 CIFAR-10 数据集. 我只需调用这些函数中的一个, 数据就自动加载.
但是我该如何在 Keras 上使用自己的图像数据集呢? 我必须采取什么步骤?
Igor 是对的 -- 您遇到的大多数 Keras 教程都试图使用图像分类数据集 (如 MNIST(手写识别) 或 CIFAR-10(基本对象识别)来教您库的基本知识.
这些图像数据集是计算机视觉和深度学习文献中的标准基准, 当然, 它们绝对会让你开始使用 Keras......
... 但它们不一定实用, 因为它们没有教你如何处理磁盘上的一组图像. 相反, 您只是调用助手函数来加载预编译数据集.
我将给大家带来一个全新的与众不同的 Keras 教程.
我将教你如何利用这些预先编译的数据集, 而不是教你如何使用定制的数据集来训练你的第一个神经网络和卷积神经网络, 说实话, 你的目标是将深度学习应用到你自己的数据集, 而不是内置的 Keras, 我说的对吗?
学习如何开始 Keras, 深度学习, 和 Python, 继续阅读!
引言
今天的 Keras 教程是针对实践人员设计的 -- 这是实践人员应用深度学习的方法.
这意味着我们用实践学习, 并亲手编写一些 Keras 代码, 然后在我们的自定义数据集上训练我们的网络.
本教程并不意味着深入学习围绕深度学习的理论.
如果您想深入地研究深度学习, 包括动手实现和理论讨论, 我建议您看看我的书《使用 Python 进行计算机视觉的深度学习》.
概述: 包括什么内容呢
用 Keras 训练第一个简单的神经网络不需要很多代码, 但是我们将慢慢开始, 逐步进行, 确保您理解如何在自己的自定义数据集上训练网络.
我们今天要讨论的步骤包括:
在系统上安装 Keras 和其他依赖项
从磁盘加载数据
创建训练和测试分支
定义您的 Keras 模型体系结构
编译你的 Keras 模型
训练你的训练数据模型
在测试数据上评估模型
用训练的 Keras 模型进行预测
我还增加了一个训练你的第一个卷积神经网络的部分.
这看起来像是很多步骤, 但我向你保证, 一旦我们开始进入示例, 您将看到示例是线性的, 具有直观的意义, 并且将帮助您理解用 Keras 训练神经网络的基本原理.
我们的示例数据集
图 1: 在这个 KARAS 教程中, 我们不会使用 CiFoE10 或 MNIST 用于我们的数据集. 相反, 我将向您展示如何组织自己的图像数据集, 并使用 Keras 的深度学习训练神经网络
大多数你遇到的解决图像分类问题的 Keras 教程都会使用 MNIST 或 CIFAR-10-- 我不打算这样做.
首先, MNIST 和 CIFAR-10 已经不是什么新鲜的例子了.
这些教程实际上不涉及如何使用自己的自定义图像数据集. 相反, 他们简单地调用内置的 Keras 实用程序, 奇迹般地返回 MNIST 和 CIFAR-10 数据集作为 Numpy 数组. 事实上, 你的训练和测试分裂已经为你预分了!
其次, 如果你想使用你自己的自定义数据集但又真的不知道该从哪里入手, 你或许已经抓狂并有如下疑问:
帮助函数从何处加载数据?
磁盘上的数据集应该是什么格式?
如何将数据集加载到内存中?
我需要执行哪些预处理步骤?
老实说, 你在学习 Keras 和深入学习的目标不是与这些预焙的数据集一起工作.
相反, 您希望使用自己的自定义数据集.
你所遇到的介绍性教程只会带你走这么远.
这就是为什么在这个 Keras 教程中, 我们将使用一个名为 "Animals Dataset" 的自定义数据集, 我为我的书《使用 Python 进行计算机视觉的深度学习》创建了这个数据集:
图 2: 在这个 Keras 教程中, 我们将从我的深度学习书中直接使用一个示例动物数据集. 数据集由狗, 猫和熊猫组成
该数据集的目的是正确地分类图像包含:
cats
dogs
panda
只包含 3000 个图像, 动物数据集意味着是一个介绍性数据集, 我们可以快速训练一个深入的学习模型使用我们的 CPU 或 GPU(并仍然获得合理的准确性).
此外, 使用此自定义数据集使您能够理解:
如何在磁盘上分配数据集
如何从磁盘加载图像和类标签
如何将数据划分为训练和测试分支
如何在训练数据上训练第一个 Keras 神经网络
如何评价测试数据的模型
如何将你的训练模型重用于全新的数据, 并在训练和测试之外进行分割
通过遵循此 Keras 教程中的步骤, 您将能够用任何数据集来代替我的动物数据集, 前提是您可以使用下面详细描述的项目 / 目录结构.
需要数据吗? 如果你需要从网上苦苦搜寻图像来创建一个数据集, 可以看看 the easy way with Bing Image Search 它, 或者 slightly more involved way with Google Images..
项目结构
有许多与此项目关联的文件. 从 "下载" 部分抓取 zip, 然后使用 tree 命令显示终端中的项目结构(我已经为 tree 提供了两条命令行参数标志, 以使输出美观和整洁):
- $ tree --dirsfirst --filelimit 10
- .
├── animals
│ ├── cats [1000 entries exceeds filelimit, not opening dir]
│ ├── dogs [1000 entries exceeds filelimit, not opening dir]
│ └── panda [1000 entries exceeds filelimit, not opening dir]
├── images
│ ├── cat.jpg
│ ├── dog.jpg
│ └── panda.jpg
├── output
│ ├── simple_nn.model
│ ├── simple_nn_lb.pickle
│ ├── simple_nn_plot.PNG
│ ├── smallvggnet.model
│ ├── smallvggnet_lb.pickle
│ └── smallvggnet_plot.PNG
├── pyimagesearch
│ ├── __init__.py
│ └── smallvggnet.py
├── predict.py
├── train_simple_nn.py
└── train_vgg.py
7 directories, 14 files
如前所述, 今天我们将使用的是动物数据集. 注意如何在项目树中分配 animals. 在 animals 内部, 有三个类目录: cat/,dogs/,panda/. 这些目录中的每一个都是对应于相应类的 1000 个图像.
如果你使用你自己的数据集, 就用同样的方式分配它! 理想情况下, 每类你至少需要收集 1000 个图像. 这并不总是可能的, 但你至少应该有类别平衡. 一个类文件夹中的图像偏多可能会导致模型偏差.
接下来是 image/ 目录. 这个目录包含三个用于测试目的的图像, 我们将用它们演示如何从磁盘加载经过训练的模型, 然后对不属于原始数据集的输入图像进行分类.
output / 文件夹包含三种类型的文件, 这些文件是通过训练生成的:
.model : 训练后生成一个序列化的 Keras 模型文件, 可以用于将来的推理脚本.
.packle : 序列化的标签二值化文件. 这个文件包含一个包含类名的对象. 它伴随着一个模型文件.
.PNG : 我总是把我的训练 / 验证绘图图像放在输出文件夹中, 因为它是训练过程的输出.
Pyimagesearch 目录是一个模块. 与我收到的许多问题相反, Pyimagesearch 不是一个可安装的 pip 程序包. 相反, 它驻留在项目文件夹中, 包含在其中的类可以导入到您的脚本中. 它在 Keras 教程的 "下载" 部分提供.
今天我们将回顾四个. py 文件:
在博客文章的前半部分, 我们将训练一个简单的模型. 训练脚本是 train_simple_nn.py.
我们将使用 train_vgg.py 脚本来培训 SmallVGGNET.
smallvggnet.py 文件包含我们的 SmallVGGNET 类和一个卷积神经网络.
序列化模型有什么好处, 除非我们可以部署它? 在 predict.py 中, 我为您提供了一个示例代码, 用于加载一个序列化的 "模型 + 标签" 文件并对图像进行推理. 预测脚本是有用的, 我们已经成功地训练了一个模型, 具有合理的准确性. 运行此脚本以测试不包含在数据集内的图像总是有用的.
1. 在系统上安装 Keras
图 3: 我们将使用 Kras 和 TysFLOW 后端来介绍 KRAS 的深度学习博客文章
对于今天的教程, 您需要安装 Keras,TensorFlow 和 OpenCV.
如果你的系统还没有这个软件, 就先不要莽撞行事! 我已经编写了一些易于遵循的安装指南. 我也在定期更新它们. 以下是你需要的:
OpenCV 安装指南 -- 这个启动板链接到帮助您在 Ubuntu,MacOS 或 Raspberry Pi 上安装 OpenCV 的教程.
安装 Keras 与 TensorFlow - 你将与 Keras 和 TensorFlow 运行不到两分钟, 感谢 pip . 你可以在 Raspberry Pi 上安装这些软件包, 但是, 我建议不要用你的 Pi 来训练. 预先训练和适当大小的模型 (比如我们今天介绍的两个模型) 可以很容易地在 Pi 上运行, 但是请确保首先训练它们!
安装 https://github.com/jrosebr1/imutils ,scikit-learning http://scikit-learn.org/stable/ 和 https://matplotlib.org/ -- 确保也安装这些包(理想情况下是在虚拟环境中). 安装 pip 很容易:
- $ workon <your_env_name> # optional
- $ pip install --upgrade imutils
- $ pip install --upgrade scikit-learn
- $ pip install --upgrade matplotlib
2. 从磁盘加载数据
图 4: 我们的 Keras 教程的步骤第 2 步是将图像从磁盘加载到内存中
现在, 我们系统上已经安装好了 Keras, 我们可以开始使用 Keras 来实现我们的第一个简单的神经网络训练脚本. 我们稍后将实现一个完整的卷积神经网络, 但让我们轻松地开始实现吧.
打开 train_simple_nn.py 并插入以下代码:
- # set the matplotlib backend so figures can be saved in the background
- import matplotlib
- matplotlib.use("Agg")
- # import the necessary packages
- from sklearn.preprocessing import LabelBinarizer
- from sklearn.model_selection import train_test_split
- from sklearn.metrics import classification_report
- from keras.models import Sequential
- from keras.layers.core import Dense
- from keras.optimizers import SGD
- from imutils import paths
- import matplotlib.pyplot as plt
- import numpy as np
- import argparse
- import random
- import pickle
- import cv2
- import os
第 2-19 行导入我们需要的包. 正如你所看到的, 这个脚本有很多工具在利用. 让我们回顾一下重要的事情:
matplotlib : 这是 Python 的绘图程序包. 也就是说, 它确实有它的细微差别, 如果你遇到问题, 请参阅这篇博客文章. 在第 3 行, 我们指示 matplotlib 使用 "agg" 后端使我们能够将绘图保存到磁盘 -- 这是您的第一个细微差别!
sk learn:scikit-learning 库将帮助我们将标签二值化, 将用于训练 / 测试的数据分割, 并在我们的终端中生成训练报告.
keras: 您正在阅读本教程以了解 Keras-- 它是我们进入 TensorFlow 和其他深度学习后端的高级前端.
imutils: 我的一套函数扩展包. 我们将使用路径模块来生成用于训练的图像文件路径列表.
Numpy: 用 Python 进行数值处理. 这是另一种包装方式. 如果你已经安装了 Python 和 skiti-learn 的 OpenCV, 那么你就有了 Numpy, 因为它是一个依赖项.
cv2: 也就是 OpenCV. 一般老说是用 2, 但是你也很有可能使用 OpenCV 3 或更高.
剩余的导入被内置到 Python 的安装中!
额, 这的确很多, 但是当我们浏览这些脚本时, 对每个导入用于什么有一个概念将有助于您理解.
让我们用 argparse 模块解析命令行参数:
- # construct the argument parser and parse the arguments
- ap = argparse.ArgumentParser()
- ap.add_argument("-d", "--dataset", required=True,
- help="path to input dataset of images")
- ap.add_argument("-m", "--model", required=True,
- help="path to output trained model")
- ap.add_argument("-l", "--label-bin", required=True,
- help="path to output label binarizer")
- ap.add_argument("-p", "--plot", required=True,
- help="path to output accuracy/loss plot")
- args = vars(ap.parse_args())
当执行脚本时, 我们的脚本将动态处理通过命令行提供的附加信息. 附加信息以命令行参数的形式出现. 将 argparse 模块内置到 Python 中, 并将处理解析您在命令字符串中提供的信息. 如需进一步解释, 请参阅此博客文章.
我们有四个命令行参数解析:
dataset: 磁盘上的图像数据集的路径.
model : 我们的模型将被序列化并输出到磁盘. 此参数包含输出模型文件的路径.
label-bin:Dataset 标签被序列化到磁盘, 以便于在其他脚本中进行回溯. 这是输出标签二值化器文件的路径.
plot: 输出训练绘图图像文件的路径. 我们将检查这个图以检查数据是否过 / 欠拟合.
- # initialize the data and labels
- print("[INFO] loading images...")
- data = []
- labels = []
- # grab the image paths and randomly shuffle them
- imagePaths = sorted(list(paths.list_images(args["dataset"])))
- random.seed(42)
- random.shuffle(imagePaths)
- # loop over the input images
- for imagePath in imagePaths:
- # load the image, resize the image to be 32x32 pixels (ignoring
- # aspect ratio), flatten the image into 32x32x3=3072 pixel image
- # into a list, and store the image in the data list
- image = cv2.imread(imagePath)
- image = cv2.resize(image, (32, 32)).flatten()
- data.append(image)
- # extract the class label from the image path and update the
- # labels list
- label = imagePath.split(os.path.sep)[-2]
- labels.append(label)
- # scale the raw pixel intensities to the range [0, 1]
- data = np.array(data, dtype="float") / 255.0
- labels = np.array(labels)
- # partition the data into training and testing splits using 75% of
- # the data for training and the remaining 25% for testing
- (trainX, testX, trainY, testY) = train_test_split(data,
- labels, test_size=0.25, random_state=42)
- # convert the labels from integers to vectors (for 2-class, binary
- # classification you should use Keras' to_categorical function
- # instead as the scikit-learn's LabelBinarizer will not return a
- # vector)
- lb = LabelBinarizer()
- trainY = lb.fit_transform(trainY)
- testY = lb.transform(testY)
- [1, 0, 0] # corresponds to cats
- [0, 1, 0] # corresponds to dogs
- [0, 0, 1] # corresponds to panda
- # define the 3072-1024-512-3 architecture using Keras
- model = Sequential()
- model.add(Dense(1024, input_shape=(3072,), activation="sigmoid"))
- model.add(Dense(512, activation="sigmoid"))
- model.add(Dense(len(lb.classes_), activation="softmax"))
- # initialize our initial learning rate and # of epochs to train for
- INIT_LR = 0.01
- EPOCHS = 75
- # compile the model using SGD as our optimizer and categorical
- # cross-entropy loss (you'll want to use binary_crossentropy
- # for 2-class classification)
- print("[INFO] training network...")
- opt = SGD(lr=INIT_LR)
- model.compile(loss="categorical_crossentropy", optimizer=opt,
- metrics=["accuracy"])
来源: https://juejin.im/entry/5bc545d75188255c372f829b