介绍 Practical Deep Learning 课程和 fastai 框架,大幅降低深度学习学习门槛。
最近我开始学习《程序员实用深度学习》课程。这门课程非常优秀,如果你想深入了解这个话题,我强烈推荐。不过它也很耗时,因为每节课都是 1 小时以上的视频。
这就是为什么我决定创建这份指南,重点关注课程的核心部分。我会讲解如何:
我们将使用 fastai 来创建 AI。这是一个 Python 库,构建在 PyTorch 之上。别担心,你不需要知道如何编码 Python。我们会在学习过程中慢慢理解这些东西 :)
你可以自己安装和配置所有库来在 Python 文件中运行代码。但通常 AI 会在称为 Jupyter Notebook 的工具中编写。
使用 Jupyter Notebook 有两个选择:
Jupyter Notebook 包含 Python 代码或 markdown 的单元格。你可以在浏览器中直接运行代码,方法是点击顶部导航栏或单元格旁的"Run"按钮。代码的输出会显示在代码单元格下面。
现在让我们直接进入代码。本指南的其余部分也可以在这个 Kaggle notebook 中找到:https://www.kaggle.com/vincentwill/fastai-tutorial
在 Kaggle 上,为了让代码能够工作,你必须先在侧边栏菜单中激活"Internet"开关。要打开侧边栏,点击右下角的小箭头。只有当你已验证电话号码时,Internet 开关才可用。
在这个教程中,我们将写一个 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 知道什么不是霸王龙。我们使用同样的函数来获取三角龙的图片。
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
It might happen that downloads fail. That's why we need to verify the images and delete the invalid ones.
failed = verify_images(get_image_files(path))
failed.map(Path.unlink)
len(failed)
要训练 AI,我们首先需要一个 DataBlock。它就像一个关于如何组装你的数据的蓝图。通过这个 DataBlock,我们可以通过调用它的 .dataloader 函数来创建一个数据加载器。我会在下面的代码中解释不同的参数。你可以在这里找到更详细的解释。
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。首先,我们加载一个预训练模型。在这种情况下,预训练模型已经被训练来识别照片。之后,我们在我们的数据集上微调这个模型。我们将我们的数据加载器传递给 vision learner,然后是预训练模型,我们将使用它。在这种情况下,是 resnet18。
learn = vision_learner(dls, resnet18, metrics=error_rate)
learn.fine_tune(3)
现在我们的 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}")
如果我们对结果和准确度感到满意,我们可以部署该模型。我们通过简单地调用 learner 的 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。我们可以使用 Gradio 和 Hugging 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。然后我们已经可以通过定义一个 Interface 来启动它。我们将 predict 函数、输入和输出定义传递给这个 interface。然后我们可以调用 launch 函数,它将启动一个 interface 来与我们的模型交互。
!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)
这将创建一个用户界面来轻松与我们的模型交互。
在底部,你可以看到文本"Use via API"。如果你点击它,它会向你显示如何通过 API 与你的 AI 交互。你可以使用 Gradio 创建你自己的 Python 微服务。但最简单的托管方式是使用 Hugging Face。所以前往那里并创建一个账户。确认你的电子邮件后,你将能够创建一个"Space"。
点击右上角菜单,然后点击"New Space"。输入你的项目名称,选择 Gradio 作为 SDK。然后选择一个许可证,保持其他选项不变。现在你可以创建 Space。
之后,我们需要将我们的模型和代码添加到 Hugging Face 仓库。如果你在本地运行你的 notebook,你应该在你的工作目录中有导出的模型。如果你在 Kaggle 上,你需要点击右下角的小箭头。在那里你应该看到一个"Data"选项卡,其中包含你导出的 model.pkl 文件。
现在克隆你的 Hugging Face Space 仓库。然后将 model.pkl 文件添加到仓库中,并创建一个 app.py 文件。在那里我们添加我们已经使用过的代码来加载模型并创建一个 gradio interface。
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()
最后添加一个 requirements.txt 文件来提供运行我们的模型所需的库。
fastai
scikit-image
提交前我们需要先安装 git-lfs,因为我们的 model.pkl 文件太大了。访问链接并按照说明为你的操作系统安装它。现在我们能够为我们的 model.pkl 使用 git-lfs:
git lfs install
git lfs track "*.pkl"
之后,我们已经准备好提交和部署我们的模型。
git add .
git commit -m "initial commit"
git push
如果你返回你的 Hugging Face Space,你应该会看到你的应用程序正在构建。过一会儿,你应该能够看到与你的 jupyter notebook 中相同的 interface。
恭喜!你成功地创建和部署了你的 AI。你现在能够在你的应用程序中使用你的 Hugging Face Space 的 API。
首先,我建议你修改 jupyter notebook 中的代码。尝试不同的方法来更好地理解这些东西如何工作。
查阅 fastai 文档来了解如何:
如果你喜欢这份指南以及如何改进它,请在 Twitter 或通过电子邮件告诉我:info@wweb.dev