大多数机器学习开发起源于学术界,这通常是非常技术性的,对于外行来说很难理解。就个人而言,我喜欢能够通过自己的输入与最终结果进行交互,而无需在以后了解模型的技术细节。写这篇文章的另一个动机是,我没有看到很多公开文章或示例使用 Gradio 和 HuggingFace 托管来演示具有图像输入和输出的计算机视觉模型,因为 HuggingFace 传统上是自然语言处理 (NLP) 知识的中心(但它们'正在转变以合并更多其他 ML 领域,例如计算机视觉)。

什么是HuggingFace和Gradio

Gradio 和 HuggingFace 标志

不,HuggingFace 不是电影[外星人](https://en.wikipedia.org/wiki/Aliens_(film)中的那些面部抓取器(尽管我最初认为是这样)。实际上,拥抱的表情符号现在在我最常用的表情符号键盘列表的顶部! HuggingFace 不仅是 ML 模型和演示的中心,而且还是一个 Python 库,允许任何人创建和训练选择的模型架构,而无需从头开始编写(例如转换器)。对于我们的案例,HuggingFace Spaces 允许我们免费托管我们的模型以进行公共部署,而无需任何额外费用、全栈开发知识或使用其他平台的麻烦。请注意,使用 GPU 进行演示确实需要额外费用,因此我将展示一个仅使用 CPU 的示例。

另一方面,Gradio 是 Python 库,它允许使用单行代码进行用户友好的功能和前端开发。该界面可用于创建像我这样的简单可视演示(下一段中的链接)到像这个这样的复杂界面。

演示我的研究项目

在本教程中,我将向您展示如何快速部署一个模型演示,该模型接受图像输入并输出叠加到图像上的实例分割图。该演示与我的研究项目的一部分有关,该项目旨在检测由湿器官表面反射的光产生的镜面反射区域,并使相机无法识别该区域的真实颜色和特征。生成的分割图稍后用于使用来自内窥镜视频的相邻帧的信息来恢复该区域。 触发警告:血液、生物组织。你可以在这里查看我的演示。

创建代码骨架

对于我处理的任何代码,我喜欢先写评论并创建一个版本控制系统来使用,例如 Github(在这种情况下,HuggingFace 有自己的 Git 版本,托管在他们的平台上)。首先,在 HuggingFace 上创建一个帐户并创建一个空间。从那里,您可以指定存储库名称和许可证类型,然后选择 Gradio 作为显示选项。

制作空格

然后,您可以使用 git bash 将 repo 克隆到本地存储,也可以直接在 HuggingFace 上修改您的代码。接下来,要创建两个重要文件:requirements.txt 和 app.py。需求文本文件将存储所有需要安装在 HuggingFace 托管环境中的 pip 库依赖项,以运行您在代码中使用的所有 Python 库。 app.py 文件将定义您希望界面的外观和功能。您可以首先制作的最基本的应用程序有点像使用 Gradio 的“hello world”程序,它们会在您创建存储库后向您展示。

import gradio as gr

def greet(name):
    return "Hello " + name + "!!"

iface = gr.Interface(fn=greet, inputs="text", outputs="text")
iface.launch()

进入全屏模式 退出全屏模式

让我们稍微剖析一下这段代码。 import 语句告诉 Python 您想使用 Gradio 的所有功能(假设您已将其放入 requirements.txt)。函数“greet”是您将所有机器学习模型逻辑用于处理输入并从模型返回预测或输出以显示的地方。界面是定义您希望演示外观的主要功能 - 我们将在本文后面深入探讨这些选项。然后,您需要做的就是启动演示,HuggingFace 会自动为您部署所有这些代码。就这么简单!

定义模型行为

现在我们有了想要编写的代码的骨架,我们将用所需的功能填充它。我们希望创建一个函数来接受图像(Gradio 将其读取为 NumPy 或 PIL 图像),而不是使用 greet 函数,对其进行预处理以输入模型,并通过前向传递在模型中运行以进行预测,并输出叠加到原始图像上的分割图。

def speclab(img):

    # initialize the model
    model = torch.hub.load('Nano1337/SpecLab', 'srdetect', force_reload=True) # for some reasons loads the model in src rather than demo
    model.eval()

    # preprocess image to be used as input
    transforms = A.Compose([
        A.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)),
        ToTensorV2()
    ])
    input = transforms(image=img)['image']
    input = input.unsqueeze(0)

    # model prediction
    output = model(input)

    # overlay output onto original image
    img[output==255] = [0, 255, 0]

    return img

进入全屏模式 退出全屏模式

您可能注意到的一个小细节是,我使用 torch.hub 从我个人 Github 帐户中保存的位置加载我的模型。你可以看到我是如何在那里制作一个hubconf.py 文件来指定我想如何加载我的模型以供外部使用。

导入示例图像

由于我正在研究的主题非常小众,因此用户不会总是将适当的数据输入到演示中。我们可以定义现成的示例来展示。我将图像存储在同一个个人 Github 存储库中,如下所示,我导入了原始图像地址,如下所示。

from urllib.request import urlretrieve

# get image examples from github
urlretrieve("https://github.com/Nano1337/SpecLab/blob/main/examples/05829.png?raw=true", "05829.png") # make sure to use "copy image address when copying image from Github"
urlretrieve("https://github.com/Nano1337/SpecLab/blob/main/examples/10384.png?raw=true", "10384.png")
examples = [ # need to manually delete cache everytime new examples are added
    ['05829.png'], 
    ["10384.png"]

进入全屏模式 退出全屏模式

您可能会注意到的另一个小细节是,我稍后在代码中指定我希望缓存这些示例及其输出,以便用户不必等待示例图像通过模型运行(这可能需要花费大量时间)更多时间,因为模型仅在 CPU 上运行)。

创建接口

现在是前端工作,谢天谢地,对于像我这样的菜鸟 webdev 来说,这真的很容易。下面是我使用 Interface 函数定义演示外观的代码,但如果您希望在文档中获得更多前端灵活性,Gradio 还具有更多可定制和高级功能。

# define app features and run
title = "SpecLab Demo"
description = "<p style='text-align: center'>Gradio demo for an ASPP model architecture trained on the SpecLab dataset. To use it, simply add your image, or click one of the examples to load them. Since this demo is run on CPU only, please allow additional time for processing. </p>"
article = "<p style='text-align: center'><a href='https://github.com/Nano1337/SpecLab'>Github Repo</a></p>"
css = "#0 {object-fit: contain;} #1 {object-fit: contain;}"
demo = gr.Interface(fn=speclab, 
                    title=title, 
                    description=description,
                    article=article,
                    inputs=gr.Image(elem_id=0, show_label=False), 
                    outputs=gr.Image(elem_id=1, show_label=False),
                    css=css, 
                    examples=examples, 
                    cache_examples=True,
                    allow_flagging='never')
demo.launch()

进入全屏模式 退出全屏模式

让我们一起来看看这段代码。标题和描述是不言自明的,文章在屏幕底部显示了更多文本。如果您精通前端(我绝对不是),您还可以定义自定义 CSS 来美化您的界面。我们将输入和输出组件都指定为 Gradio 图像,但它们可以是 Gradio 支持的组件中的任何一个(如果您熟悉该框架,则类似于 React.js 组件中的各种组件)。其他参数只是不错的选择,可以在接口文档中找到。

最终结果

恭喜

你有它!在大约 50 行代码(甚至更少)之后,您就有了一个运行良好的演示,无需任何部署成本。随意分享这篇文章,如果你喜欢这个内容,让我知道你接下来想从我这里看到什么!快乐的深度学习我的朋友们:))

Logo

华为、百度、京东云现已入驻,来创建你的专属开发者社区吧!

更多推荐