2023年与Fastai编码自己的AI
#初学者 #python #ai #deeplearning

最近,我已经开始了Practical Deep Learning for Coders课程。本课程很棒,如果您想更深入地了解这个话题,我建议它。但这也很耗时,因为本课程中的每一堂课都是1H+长的视频。

这就是为什么我决定创建本指南的原因,该指南重点关注课程的关键部分。我将介绍如何

  • 设置开发AI
  • 的生态系统
  • fastai创建并训练AI模型
  • 部署模型并将其在您的项目中使用

创建Jupyter笔记本

为了创建AI,我们将使用fastai。这是一个Python库,它建在pytorch上。不用担心,您不需要知道如何编码Python。我们将学习这些东西在一路上的工作方式:)

您可以自己安装并设置所有库以在Python文件中运行代码。但是通常AIS会用称为Jupyter Notebooks的东西编码。

使用jupyter笔记本有两个选项。

  1. 使用像Kaggle这样的免费托管服务
  2. 本地运行笔记本。您可以找到有关如何在其documentation上设置Jupyter的指南

jupyter笔记本具有Python代码或Markdown的单元格。您可以通过按顶部导航中的“运行”按钮或旁边的“运行”按钮直接在浏览器中运行代码。它将为您提供代码单元下方的代码的输出。

screenshot of a demo notebook

现在让我们直接跳入代码。本指南的其余部分也将在此Kaggle笔记本中提供:

https://www.kaggle.com/vincentwill/fastai-tutorial

在Kaggle上,要使代码工作,您必须先在侧栏菜单中激活“ Internet”开关。要打开侧边栏,请单击右下方的小箭头。仅当您已验证您的电话号码时,Internet Switch才可用。

准备数据以训练AI

在本教程中,我们将写一个AI,可以识别图片中的内容。

为此,我们需要一些图片才能先训练AI。

以下功能是快速从DuckDuckgo下载图片的助手。我不会在这里详细介绍,因为这对于培训我们的AI并不重要。您也可以手动下载图片或使用其他任何刮板获取数据。

# import libraries | imports will be available in all following cells as well
from fastcore.all import *
from fastai.vision.all import *
import time
import json

def search_images(term, max_images=100): # define search_images function
    url = 'https://duckduckgo.com/'
    res = urlread(url,data={'q':term})
    time.sleep(2)
    searchObj = re.search(r'vqd=([d-]+)&', res)
    requestUrl = url + 'i.js' # the duckduck go api url
    params = dict(l='us-en', o='json', q=term, vqd=searchObj.group(1), f=',,,', p='1', v7exp='a')
    headers = dict( referer='https://duckduckgo.com/' )
    urls,data = set(),{'next':1}
    # loop through pages until we have enough images
    while len(urls)<max_images and 'next' in data:
        res = urlread(requestUrl, data=params, headers=headers)
        data = json.loads(res) if res else {}
        urls.update(L(data['results']).itemgot('image'))
        requestUrl = url + data['next']
        time.sleep(4)
    return L(urls)[:max_images]`

我建议先遵循本指南,然后尝试用不同的图像训练AI。我们将从测试我们的search_images函数开始。输出将显示一个链接。

对于本教程,我将创建一个识别不同类型恐龙的AI。

# "search_images" depends on duckduckgo.com, which doesn't always return correct responses.
#  If you get a JSON error, just try running it again (it may take a couple of tries).
urls = search_images('t-rex', max_images=1)
urls[0] # 'https://preview.redd.it/dwthh8wdl9k21.jpg?auto=webp&s=e0af431550ed710c2ffb11eae6ca325806c9f46b'`

现在我们验证了该功能是否正常工作,我们可以使用它下载和显示图片。

from fastdownload import download_url
dest = 't-rex.jpg'
download_url(urls[0], dest, show_progress=False)

im = Image.open(dest) # open the downloaded image
im.to_thumb(256,256) # display the image in a 256x256 thumbnail

现在,我们需要获取不同的图片,以让AI知道什么不是T-Rex。我们将使用相同的功能获取三角尾图的图像。

download_url(search_images('triceratops', max_images=1)[0], 'triceratops.jpg', show_progress=False)
Image.open('triceratops.jpg').to_thumb(256,256)

现在,我们确保搜索和保存正常工作,我们可以使用它们下载我们的数据集。下一个功能将遍历我们的类别,并下载每张图片的100张图片。

searches = 't-rex','triceratops' # define search terms
path = Path('images')

for o in searches:
    dest = (path/o)
    dest.mkdir(exist_ok=True, parents=True) # create folder for categories
    download_images(dest, urls=search_images(f'{o}'))
    time.sleep(5)
    resize_images(path/o, max_size=400, dest=path/o) # resize to save time training the AI

下载失败可能会发生。这就是为什么我们需要验证图像并删除无效图像的原因。

failed = verify_images(get_image_files(path))
failed.map(Path.unlink)
len(failed)

训练AI

要训练AI,我们首先需要Data block。这就像关于如何组装数据的蓝图。然后,使用此DataBlock,我们可以通过调用其.dataloader函数来创建一个Data loader。我将在下面的代码中解释不同的参数。您可以找到对here的所有内容的更详细说明。

dls = DataBlock(
  blocks=(ImageBlock, CategoryBlock), # input = images, output = categories
  get_items=get_image_files, # Get image files in path recursive
  splitter=RandomSplitter(valid_pct=0.2, seed=42), # split data into training / validation set randomly
  get_y=parent_label, # label the items - in this case take the parent (folder) as label
  item_tfms=[Resize(192, method='squish')] # method to transform the items - in this case resize
).dataloaders(path, bs=32) # bs = size of batch

# show an example batch of the items we loaded
dls.show_batch(max_n=6)

现在,我们已经准备好使用此数据来培训我们的AI。首先,我们加载了预训练的模型。在这种情况下,对预培训的模型进行了训练以识别照片。之后,我们在数据集中微调了此模型。我们将数据加载程序传递给视觉学习者,然后将其使用的预训练模型传递给我们将使用的预训练模型。在这种情况下,是resnet18

learn = vision_learner(dls, resnet18, metrics=error_rate)
learn.fine_tune(3)

测试和部署AI

现在我们的AI准备好进行测试。为此,我们可以使用最初下载的照片来测试下载功能。

prediction,_,probs = learn.predict('t-rex.jpg') # run a prediction
print(f"This is a: {prediction}.")
print(f"Probability it's a t-rex: {probs[0]:.4f}")
print(f"Probability it's a triceratops: {probs[1]:.4f}")

如果我们对结果和可以部署模型的准确性感到满意。我们通过简单地调用学习者的export函数来做到这一点。

learn.export('model.pkl')

您现在能够加载和使用导出的模型。这意味着您可以将其导入任何Python应用程序并使用.predict函数。

path = Path()
path.ls(file_exts='.pkl') # double check if model exists

learn_inf = load_learner('model.pkl')
learn_inf.predict('t-rex.jpg')

但是,使用模型的方法比实施自己的Python API更容易。我们可以使用GradioHugging Face轻松创建API并使用我们的模型。为此,我们需要编写一个可以告诉Gradio如何使用我们的模型的函数。

labels = learn.dls.vocab # read labels from Data Loader
def predict(img):
    pred,pred_idx,probs = learn.predict(img) # use passed image for prediction
    return {labels[i]: float(probs[i]) for i in range(len(labels))} # return all results

现在我们需要安装Gradio。然后,我们已经可以通过定义接口来启动它。对于此界面,我们传递了预测功能以及输入和输出定义。然后我们可以调用启动功能,该功能将启动一个接口与我们的模型交互。

!pip install -Uqq gradio

import gradio as gr
gradio_interface = gr.Interface(fn=predict, inputs=gr.inputs.Image(shape=(512, 512)), outputs=gr.outputs.Label(num_top_classes=3))
gradio_interface.launch(share=True)

这将创建一个UI,以轻松与我们的模型交互

screenshot of a gradio UI

在底部,您可以通过API看到文本使用。

如果您单击它,它将向您展示如何通过API与AI互动。您可以使用Gradio创建自己的Python微服务。但是,最简单的托管方法是使用拥抱的脸。因此,前往那里并创建一个帐户。确认电子邮件后,您可以创建一个“空间”。

单击右上角菜单,然后在“新空间”上。输入项目的名称,然后选择Gradio作为SDK。然后选择许可证并保留其他选项。现在您可以创建空间。

screenshot of a hugging face new space creation

之后,我们需要将我们的模型和代码添加到拥抱面孔存储库中。如果您在本地运行笔记本电脑,则应在工作目录中具有导出的型号。如果您在Kaggle上,则必须单击右下方的小箭头。在那里,您应该看到带有导出型号的“数据”选项卡。pkl文件。

现在克隆您的拥抱面孔空间的存储库。然后将model.pkl文件添加到存储库中并创建一个文件app.py。在那里,我们添加了上面已经使用的代码来加载模型并创建Gradio接口。

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

path = Path()
learn = load_learner('model.pkl')

labels = learn.dls.vocab # read labels from Data Loader
def predict(img):
    pred,pred_idx,probs = learn.predict(img) # use passed image for prediction
    return {labels[i]: float(probs[i]) for i in range(len(labels))} # return all results

gradio_interface = gr.Interface(fn=predict, inputs=gr.inputs.Image(shape=(512, 512)), outputs=gr.outputs.Label(num_top_classes=3))
gradio_interface.launch()

,最后添加了一个要求。txt文件以提供运行我们的模型所需的库。

fastai
scikit-image

提交之前,我们需要首先安装git-lfs,因为我们的model.pkl文件太大了。请按照链接和指令为您的操作系统安装。

现在,我们能够将git-lfs用于我们的model.pkl:

git lfs install
git lfs track "*.pkl"

之后,我们准备提交和部署我们的模型。

git add .
git commit -m "initial commit"
git push

如果您回到拥抱的面部空间,则应该看到您的应用程序正在构建。一段时间后,您应该能够看到与Jupyter笔记本中相同的界面。

恭喜!您成功创建并部署了您的AI。您现在可以在应用程序中使用拥抱面孔的API。

接下来是什么?