开发第一个深度学习应用

我从事数据分析工作已经近十年了。我时不时地会使用机器学习技术从数据中获取见解,而且我习惯使用经典机器学习。

虽然我通过了一些关于神经网络和深度学习的 MOOC,但我从未在工作中使用过它们,而且这个领域对我来说似乎相当具有挑战性。我有这些偏见:

  • 你需要学习很多东西才能开始使用深度学习:数学、不同的框架(我至少听说过其中三个:PyTorch、TensorFlow 和 Keras)和网络架构。
  • 需要大量数据集才能拟合模型。
  • 如果没有强大的计算机(它们还必须有 Nvidia GPU),就不可能获得不错的结果,因此很难进行设置。
  • 要启动和运行由机器学习驱动的服务,需要很多样板:你需要处理前端和后端。

我认为分析的主要目标是帮助产品团队根据数据做出正确的决策。如今,神经网络绝对可以改善我们的分析,即 NLP 有助于从文本中获得更多见解。因此,我决定再次尝试利用深度学习的力量会很有帮助。

这就是我开始学习 Fast.AI 课程的方式(该课程于 2022 年初更新,因此我认为自 TDS 上之前的评测以来内容已经发生了变化)。我意识到使用深度学习解决您的任务并不那么困难。

本课程遵循自上而下的方法。因此,你从构建一个工作系统开始,然后才能深入了解所有必要的基础知识和细微差别。

我在第二周制作了我的第一个由 ML 驱动的应用程序(你可以在此处尝试)。这是一个可以识别我最喜欢的狗品种的图像分类模型。令人惊讶的是,即使我的数据集中只有几千张图像,它也能很好地工作。这让我很受启发,我们现在可以多么轻松地构建一项十年前完全神奇的服务。

因此,在本文中,你将找到有关构建和部署由机器学习提供支持的第一个服务的初学者级教程。

1、什么是深度学习?

当我们使用多层神经网络作为模型时,深度学习是机器学习的一个特定用例。

神经网络非常强大。根据通用近似定理,神经网络可以近似任何函数,这意味着它们能够解决任何任务。

现在,你可以将此模型视为一个黑匣子,它接受输入(在我们的例子中是狗图像)并返回输出(在我们的例子中是标签):

2、构建模型

你可以在 Kaggle 上找到此阶段的完整代码。

我们将使用 Kaggle Notebooks 来构建我们的深度学习模型。如果你还没有 Kaggle 帐户,则值得完成注册过程。 Kaggle 是一个受数据科学家欢迎的平台,您可以在其中找到数据集、参加比赛并运行和共享代码。

你可以在 Kaggle 上创建一个 Notebook,并在此处执行代码,就像在本地 Jupyter Notebook 中一样。Kaggle 甚至提供 GPU,因此我们将能够非常快速地训练 NN 模型。

让我们从导入所有包开始,因为我们将使用许多 Fast.AI 工具:

from fastcore.all import *
from fastai.vision.all import *
from fastai.vision.widgets import *
from fastdownload import download_url

3、加载数据

不用说,我们需要一个数据集来训练我们的模型。获取一组图像的最简单方法是使用搜索引擎。

DuckDuckGo 搜索引擎有一个易于使用的 API 和方便的 Python 包 duckduckgo_search更多信息),所以我们将使用它。

让我们尝试搜索狗的图像。我们已指定 license_image = any 以仅使用具有知识共享许可的图像:

from duckduckgo_search import DDGS
import itertools
with DDGS() as ddgs:
    res = list(itertools.islice(ddgs.images('photo samoyed happy', 
                                license_image = 'any'), 1))

在输出中,我们获得了有关图像的所有信息:名称、URL 和大小:

{
   "title": "Happy Samoyed dog photo and wallpaper. Beautiful Happy Samoyed dog picture", 
   "image": "http://www.dogwallpapers.net/wallpapers/happy-samoyed-dog-wallpaper.jpg", 
   "thumbnail": "https://tse2.mm.bing.net/th?id=OIP.BqTE8dYqO-W9qcCXdGcF6QHaFL&pid=Api", 
   "url": "http://www.dogwallpapers.net/samoyed-dog/happy-samoyed-dog-wallpaper.html", 
   "height": 834, "width": 1193, "source": "Bing"
}

现在我们可以使用 Fast.AI 工具下载图像并显示缩略图:

我们看到一只快乐的萨摩耶犬,这意味着它正在工作。所以让我们加载更多照片。

我的目标是识别五种不同的狗品种(我最喜欢的品种)。我将为每个品种加载图片并将它们存储在单独的目录中:

breeds = ['siberian husky', 'corgi', 'pomeranian', 'retriever', 'samoyed']
path = Path('dogs_breeds') # defining path

for b in tqdm.tqdm(breeds):
    dest = (path/b)
    dest.mkdir(exist_ok=True, parents=True) 
    
    download_images(dest, urls=search_images(f'photo {b}'))
    sleep(10) 
    download_images(dest, urls=search_images(f'photo {b} puppy'))
    sleep(10) 
    download_images(dest, urls=search_images(f'photo {b} sleep'))
    sleep(10) 
    resize_images(path/b, max_size=400, dest=path/b)

运行此代码后,你将在 Kaggle 的右侧面板上看到所有已加载的照片:

下一步是将数据转换为适合 Fast.AI 模型的格式 — DataBlock

你需要为此对象指定一些参数,但我将仅强调最重要的参数:

  • splitter=RandomSplitter(valid_pct=0.2, seed=18):Fast.AI 要求您选择一个验证集。验证集是用于估计模型质量的保留数据。训练期间不使用验证数据以防止过度拟合。在我们的例子中,验证集是数据集的随机 20%。我们指定了种子参数以便下次能够重现完全相同的分割。
  • item_tfms=[Resize(256, method='squish')]: 神经网络批量处理图像。这就是为什么我们必须有相同大小的图片。调整图像大小的方法有很多种,我们现在使用 squish,但稍后我们会更详细地讨论它。

我们定义了一个数据块。函数 show_batch 可以向我们显示一组带有标签的随机图像。

数据看起来不错,所以让我们继续训练。

4、训练模型

你可能会感到惊讶,但下面的两行代码将完成所有工作:

我们使用了预先训练的模型(具有 18 个深层的卷积神经网络 - Resnet18)。这就是我们将函数称为 fine_tune 的原因。

我们对模型进行了三个时期的训练,这意味着模型查看了整个数据集 3 次。

我们还指定了指标 - 准确度(正确标记图片的份额)。你可以在每个时期后的结果中看到此指标(它仅使用验证集计算,以免歪曲结果)。但是,它不会用于优化过程,仅供您参考。

整个过程大约需要 30 分钟,现在我们的模型可以以 94.45% 的准确率预测狗的品种。干得好!但是我们可以改进这个结果吗?

5、改进模型:数据清理和增强

如果你想尽快看到第一个模型运行,请随意将本节留到以后再讨论,然后转到模型的部署。

首先,让我们看看模型的错误:它是否无法区分柯基犬和哈士奇犬,或者博美犬和猎犬。我们可以使用 confusion_matrix。请注意,混淆矩阵也仅使用验证集计算。

Fast.AI课程中分享的另一个生活技巧是,可以使用模型来清理我们的数据。为此,我们可以看到损失最高的图像:可能是模型错误但置信度高,或者正确但置信度低的情况。

显然,第一张图片的标签不正确,而第二张图片同时包含哈士奇犬和柯基犬。所以还有一些改进的空间。

幸运的是,Fast.AI提供了一个方便的 ImageClassifierCleaner小部件,可以帮助我们快速修复数据问题。你可以在笔记本中初始化它,然后就可以更改数据集中的标签:

cleaner = ImageClassifierCleaner(learn)
cleaner

每个类别之后,你可以运行以下代码来解决问题:删除图像或将其移动到正确的文件夹:

for idx in cleaner.delete(): cleaner.fns[idx].unlink()
for idx,breed in cleaner.change(): shutil.move(str(cleaner.fns[idx]), path/breed)

现在我们可以再次训练我们的模型,并看到准确率有所提高:95.4% vs 94.5%。

正确识别的柯基犬比例从 88% 增加到 96%。太棒了!

改进模型的另一种方法是改变调整大小的方法。我们使用了挤压方法,但正如你所见,它可以改变自然物体的比例。让我们尝试更具想象力并使用增强功能。

增强是对图像的更改(例如,对比度改进、旋转或裁剪)。它将为我们的模型提供更多可变数据,并有望提高其质量。

与 Fast.AI 一样,你只需更改几个参数即可添加增强功能。

此外,由于增强模型在每个时期都会看到略有不同的图片,我们可以增加时期数。经过六个时期后,我们实现了 95.65% 的准确率——结果稍好一些。整个过程大约需要一个小时。

6、下载模型

最后一步是下载我们的模型。这很简单:

learn.export('cuttest_dogs_model.pkl')

然后,你将保存一个标准的 pickle 文件(用于存储对象的常见 Python 格式)。只需在 Kaggle Notebook 右侧面板中选择文件旁边的更多操作,即可在你的计算机上获得模型。

现在我们有了训练好的模型,让我们部署它,这样就可以与世界分享结果。

7、部署模型

我们将使用 HuggingFace Spaces 和 Gradio 来构建我们的 Web 应用程序。

7.1 设置 HuggingFace Space

HuggingFace 是一家提供机器学习便捷工具的公司,例如,一个流行的转换器库或用于共享模型和数据集的工具。今天我们将使用他们的 Spaces 来托管我们的应用程序。

首先,如果你尚未注册,则需要创建一个帐户。只需几分钟。点击此链接

现在是时候创建一个新的 Space 了。前往 Spaces 选项卡并按下“创建”按钮。您可以在文档中找到包含更多详细信息的说明。

然后需要指定以下参数:

  • 名称(它将用于您的应用程序 URL,因此请明智选择),
  • 许可证(我选择了开源 Apache 2.0 许可证)
  • SDK(我将在此示例中使用 Gradio)。

然后,用户友好的 HuggingFace 会向你显示说明。TL;DR 现在你有一个 Git 存储库,你需要在那里提交代码。

Git 有一个细微差别。由于你的模型可能非常大,最好设置 Git LFS(大文件存储),然后 Git 将不会跟踪此文件的所有更改。对于安装,请按照网站上的说明进行操作:

-- cloning repo
git clone https://huggingface.co/spaces/<your_login>/<your_app_name>
cd <your_app_name>

-- setting up git-lfs
git lfs install
git lfs track "*.pkl"
git add .gitattributes
git commit -m "update gitattributes to use lfs for pkl files"

7.2 Gradio

Gradio 是一个框架,允许你仅使用 Python 构建令人愉快且友好的 Web 应用程序。这就是为什么它是一种非常有价值的原型设计工具(特别是对于像我这样没有深厚 JavaScript 知识的人来说)。

在 Gradio 中,我们将定义我们的界面,指定以下参数:

  • 输入 — 图像,
  • 输出 — 具有五个可能类别的标签,
  • 标题、描述和一组示例图像(我们还必须将它们提交到 repo),
  • 如果应用程序变得非常流行, enable_queue=True 将帮助应用程序处理大量流量,
  • 要为输入图像执行的函数。

为了获得输入图像的标签,我们需要定义预测函数来加载我们的模型并返回一个包含每个类的概率的字典。

最后,我们将为 app.py 提供以下代码:

import gradio as gr
from fastai.vision.all import *

learn = load_learner('cuttest_dogs_model.pkl')

labels = learn.dls.vocab # list of model classes
def predict(img):
    img = PILImage.create(img)
    pred,pred_idx,probs = learn.predict(img)
    return {labels[i]: float(probs[i]) for i in range(len(labels))}

gr.Interface(
    fn=predict,
    inputs=gr.inputs.Image(shape=(512, 512)),
    outputs=gr.outputs.Label(num_top_classes=5),
    title="The Cuttest Dogs Classifier 🐶🐕🦮🐕‍🦺",
    description="Classifier trainded on images of huskies, retrievers, pomeranians, corgis and samoyeds. Created as a demo for Deep Learning app using HuggingFace Spaces & Gradio.",
    examples=['husky.jpg', 'retriever.jpg', 'corgi.jpg', 'pomeranian.jpg', 'samoyed.jpg'],
    enable_queue=True).launch()

如果你想了解有关 Gradio 的更多信息,请阅读文档

我们还将使用 fastai 创建 requirements.txt 文件,然后该库将安装在我们的服务器上。

所以剩下的唯一一点就是将所有内容推送到 HuggingFace Git 存储库:

git add * 
git commit -am 'First version of Cuttest Dogs app'
git push

你可以在 GitHub 上找到完整的代码。

推送文件后,返回 HuggingFace Space,你将看到一张类似的图片,显示构建过程。如果一切正常,你的应用将在几分钟内运行。

如果有任何问题,你将看到栈回溯信息。然后,你必须返回到代码,修复错误,推送新版本,并等待几分钟。

8、它正在工作

现在我们可以将此模型与真实照片一起使用,例如,验证我家的狗实际上是柯基犬:

今天,我们经历了构建深度学习应用程序的整个过程:从获取数据集和拟合模型到编写和部署 Web 应用程序。希望你能够完成本教程,现在正在生产中测试你的出色模型。


原文链接:Build your first Deep Learning app within an hour

汇智网翻译整理,转载请标明出处