教程:在 Azure Functions 中使用 Python 和 TensorFlow 应用机器学习模型Tutorial: Apply machine learning models in Azure Functions with Python and TensorFlow

本文介绍如何在机器学习模型中使用 Python、TensorFlow 和 Azure Functions,以根据图像内容对图像进行分类。In this article, you learn how to use Python, TensorFlow, and Azure Functions with a machine learning model to classify an image based on its contents. 由于你是在本地完成所有操作,而不会在云中创建任何 Azure 资源,因此,完成本教程不会产生任何费用。Because you do all work locally and create no Azure resources in the cloud, there is no cost to complete this tutorial.

  • 初始化用于在 Python 中开发 Azure Functions 的本地环境。Initialize a local environment for developing Azure Functions in Python.
  • 将自定义 TensorFlow 机器学习模型导入函数应用。Import a custom TensorFlow machine learning model into a function app.
  • 生成一个无服务器 HTTP API,用于分类包含狗或猫的图像。Build a serverless HTTP API for classifying an image as containing a dog or a cat.
  • 从 Web 应用使用该 API。Consume the API from a web app.

先决条件Prerequisites

先决条件检查Prerequisite check

  1. 在终端或命令窗口中,运行 func --version 检查 Azure Functions Core Tools 的版本是否为 2.7.1846 或以上。In a terminal or command window, run func --version to check that the Azure Functions Core Tools are version 2.7.1846 or later.
  2. 运行 python --version (Linux/MacOS) 或 py --version (Windows),检查报告的 Python 版本是否为 3.7.x。Run python --version (Linux/MacOS) or py --version (Windows) to check your Python version reports 3.7.x.

克隆教程存储库Clone the tutorial repository

  1. 在终端或命令窗口中,使用 Git 克隆以下存储库:In a terminal or command window, clone the following repository using Git:

    git clone https://github.com/Azure-Samples/functions-python-tensorflow-tutorial.git
    
  2. 导航到该文件夹并检查其内容。Navigate into the folder and examine its contents.

    cd functions-python-tensorflow-tutorial
    
    • start 是本教程的工作文件夹。start is your working folder for the tutorial.
    • end 是供你参考的最终结果和完整实现。end is the final result and full implementation for your reference.
    • resources 包含机器学习模型和帮助器库。resources contains the machine learning model and helper libraries.
    • frontend 是调用函数应用的网站。frontend is a website that calls the function app.

创建并激活 Python 虚拟环境Create and activate a Python virtual environment

导航到 start 文件夹,运行以下命令以创建并激活名为 .venv 的虚拟环境。Navigate to the start folder and run the following commands to create and activate a virtual environment named .venv. 请务必使用受 Azure Functions 支持的 Python 3.7。Be sure to use Python 3.7, which is supported by Azure Functions.

cd start
python -m venv .venv
source .venv/bin/activate

如果 Python 未在 Linux 分发版中安装 venv 包,请运行以下命令:If Python didn't install the venv package on your Linux distribution, run the following command:

sudo apt-get install python3-venv

所有后续命令将在这个已激活的虚拟环境中运行。You run all subsequent commands in this activated virtual environment. (若要退出虚拟环境,请运行 deactivate。)(To exit the virtual environment, run deactivate.)

创建本地函数项目Create a local functions project

在 Azure Functions 中,有一个函数项目是一个或多个单独函数(每个函数响应特定的触发器)的容器。In Azure Functions, a function project is a container for one or more individual functions that each responds to a specific trigger. 项目中的所有函数共享相同的本地和宿主配置。All functions in a project share the same local and hosting configurations. 在本部分中,你将创建一个函数项目,其中包含单个名为 classify 的、提供 HTTP 终结点的样板函数。In this section, you create a function project that contains a single boilerplate function named classify that provides an HTTP endpoint. 在稍后的部分,你将添加更具体的代码。You add more specific code in a later section.

  1. start 文件夹中,使用 Azure Functions Core Tools 初始化 Python 函数应用:In the start folder, use the Azure Functions Core Tools to initialize a Python function app:

    func init --worker-runtime python
    

    初始化后,start 文件夹包含项目的各个文件,其中包括名为 local.settings.jsonhost.json 的配置文件。After initialization, the start folder contains various files for the project, including configurations files named local.settings.json and host.json. 由于 local.settings.json 可以包含从 Azure 下载的机密,因此,默认情况下,该文件会从 .gitignore 文件的源代码管理中排除。Because local.settings.json can contain secrets downloaded from Azure, the file is excluded from source control by default in the .gitignore file.

    提示

    由于函数项目绑定到特定的运行时,因此必须使用相同的语言编写项目中的所有函数。Because a function project is tied to a specific runtime, all the functions in the project must be written with the same language.

  2. 使用以下命令将一个函数添加到项目,其中,--name 参数是该函数的唯一名称,--template 参数指定该函数的触发器。Add a function to your project by using the following command, where the --name argument is the unique name of your function and the --template argument specifies the function's trigger. func new 创建一个与函数名称匹配的、包含项目所选语言适用的代码文件的子文件夹,以及一个名为 function.json 的配置文件。func new create a subfolder matching the function name that contains a code file appropriate to the project's chosen language and a configuration file named function.json.

    func new --name classify --template "HTTP trigger"
    

    此命令创建与函数名称匹配的文件夹 classifyThis command creates a folder matching the name of the function, classify. 该文件夹中有两个文件: __init__.py,其中包含函数代码;function.json,描述函数的触发器及其输入和输出绑定。In that folder are two files: __init__.py, which contains the function code, and function.json, which describes the function's trigger and its input and output bindings.

在本地运行函数Run the function locally

  1. 通过启动 start 文件夹中的本地 Azure Functions 运行时主机来启动函数:Start the function by starting the local Azure Functions runtime host in the start folder:

    func start
    
  2. 看到输出中显示了 classify 终结点后,请导航到 URL http://localhost:7071/api/classify?name=AzureOnce you see the classify endpoint appear in the output, navigate to the URL, http://localhost:7071/api/classify?name=Azure. 消息“Hello Azure!”The message "Hello Azure!" 应会显示在输出中。should appear in the output.

  3. Ctrl-C 停止主机。Use Ctrl-C to stop the host.

导入 TensorFlow 模型并添加帮助器代码Import the TensorFlow model and add helper code

若要修改 classify 函数以根据图像内容对图像进行分类,请使用一个已通过 Azure 自定义视觉服务进行训练并已从中导出的预生成 TensorFlow 模型。To modify the classify function to classify an image based on its contents, you use a pre-built TensorFlow model that was trained with and exported from Azure Custom Vision Service. 该模型已包含在前面克隆的示例的 resources 文件夹中,它可以根据图像是包含狗还是猫来分类图像。The model, which is contained in the resources folder of the sample you cloned earlier, classifies an image based on whether it contains a dog or a cat. 然后,将一些帮助器代码和依赖项添加到项目。You then add some helper code and dependencies to your project.

  1. start 文件夹中,运行以下命令将模型文件复制到 classify 文件夹中。In the start folder, run following command to copy the model files into the classify folder. 请务必在命令中包含 \*Be sure to include \* in the command.

    cp ../resources/model/* classify
    
  2. 验证 classify 文件夹是否包含名为 model.pblabels.txt 的文件。Verify that the classify folder contains files named model.pb and labels.txt. 如果不包含,请检查是否在 start 文件夹中运行了该命令。If not, check that you ran the command in the start folder.

  3. start 文件夹中运行以下命令,将包含帮助器代码的文件复制到 classify 文件夹中:In the start folder, run the following command to copy a file with helper code into the classify folder:

    cp ../resources/predict.py classify
    
  4. 验证 classify 文件夹现在是否包含名为 predict.py 的文件。Verify that the classify folder now contains a file named predict.py.

  5. 在文本编辑器中打开 start/requirements.txt,添加帮助器代码所需的以下依赖项:Open start/requirements.txt in a text editor and add the following dependencies required by the helper code:

    tensorflow==1.14
    Pillow
    requests
    
  6. 保存 requirements.txtSave requirements.txt.

  7. start 文件夹中运行以下命令来安装依赖项。Install the dependencies by running the following command in the start folder. 安装可能需要几分钟时间,在此过程中,你可以转到下一部分来修改函数。Installation may take a few minutes, during which time you can proceed with modifying the function in the next section.

    pip install --no-cache-dir -r requirements.txt
    

    在 Windows 上,可能会遇到“由于 EnvironmentError: [Errno 2],无法安装包。没有此类文件或目录:”,后接类似于 sharded_mutable_dense_hashtable.cpython-37.pyc 的文件的长路径名。On Windows, you may encounter the error, "Could not install packages due to an EnvironmentError: [Errno 2] No such file or directory:" followed by a long pathname to a file like sharded_mutable_dense_hashtable.cpython-37.pyc. 通常,发生此错误的原因是文件夹路径的深度太长。Typically, this error happens because the depth of the folder path becomes too long. 在这种情况下,请将注册表项 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem@LongPathsEnabled 设置为 1,以启用长路径。In this case, set the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem@LongPathsEnabled to 1 to enable long paths. 或者检查 Python 解释器的安装位置。Alternately, check where your Python interpreter is installed. 如果该位置的路径很长,请尝试在路径较短的文件夹中重新安装。If that location has a long path, try reinstalling in a folder with a shorter path.

提示

在调用 predict.py 使其做出第一次预测时,名为 _initialize 的函数会从磁盘中加载 TensorFlow 模型,并将其缓存在全局变量中。When calling upon predict.py to make its first prediction, a function named _initialize loads the TensorFlow model from disk and caches it in global variables. 这种缓存可以提高后续预测的速度。This caching speeds up subsequent predictions.

更新函数以运行预测Update the function to run predictions

  1. 在文本编辑器中打开 classify/__init__.py,并在现有的 import 语句后面添加以下行,以导入标准 JSON 库和 predict 帮助器:Open classify/__init__.py in a text editor and add the following lines after the existing import statements to import the standard JSON library and the predict helpers:

    import logging
    import azure.functions as func
    import json
    
    # Import helper script
    from .predict import predict_image_from_url
    
  2. 请将 main 函数的整个内容替换为以下代码:Replace the entire contents of the main function with the following code:

    def main(req: func.HttpRequest) -> func.HttpResponse:
        image_url = req.params.get('img')
        logging.info('Image URL received: ' + image_url)
    
        results = predict_image_from_url(image_url)
    
        headers = {
            "Content-type": "application/json",
            "Access-Control-Allow-Origin": "*"
        }
    
        return func.HttpResponse(json.dumps(results), headers = headers)
    

    此函数接收名为 img 的查询字符串参数中的图像 URL。This function receives an image URL in a query string parameter named img. 然后,它从帮助器库调用 predict_image_from_url,以使用 TensorFlow 模型下载并分类图像。It then calls predict_image_from_url from the helper library to download and classify the image using the TensorFlow model. 然后,该函数返回包含结果的 HTTP 响应。The function then returns an HTTP response with the results.

    重要

    由于此 HTTP 终结点是由另一个域中托管的网页调用的,因此响应包含 Access-Control-Allow-Origin 标头,以满足浏览器的跨源资源共享 (CORS) 要求。Because this HTTP endpoint is called by a web page hosted on another domain, the response includes an Access-Control-Allow-Origin header to satisfy the browser's Cross-Origin Resource Sharing (CORS) requirements.

    在生产应用程序中,请将 * 更改为网页的特定源,以提高安全性。In a production application, change * to the web page's specific origin for added security.

  3. 保存更改,然后在假设依赖项已完成安装的条件下,再次使用 func start 启动本地函数宿主。Save your changes, then assuming that dependencies have finished installing, start the local function host again with func start. 请务必在已激活虚拟环境的情况下运行 start 文件夹中的宿主。Be sure to run the host in the start folder with the virtual environment activated. 否则,宿主将会启动,但在调用函数时会出现错误。Otherwise the host will start, but you will see errors when invoking the function.

    func start
    
  4. 在浏览器中打开以下 URL,以使用猫图像的 URL 调用该函数,并确认返回的 JSON 是否将图像分类为猫。In a browser, open the following URL to invoke the function with the URL of a cat image and confirm that the returned JSON classifies the image as a cat.

    http://localhost:7071/api/classify?img=https://raw.githubusercontent.com/Azure-Samples/functions-python-tensorflow-tutorial/master/resources/assets/samples/cat1.png
    
  5. 让宿主保持运行,因为在下一步骤中需要使用它。Keep the host running because you use it in the next step.

运行本地 Web 应用前端来测试函数Run the local web app front end to test the function

存储库的 frontend 文件夹中提供了一个简单的应用,让你从另一 Web 应用测试函数终结点的调用。To test invoking the function endpoint from another web app, there's a simple app in the repository's frontend folder.

  1. 打开新的终端或命令提示符,并激活虚拟环境(根据前文的创建并激活 Python 虚拟环境中所述)。Open a new terminal or command prompt and activate the virtual environment (as described earlier under Create and activate a Python virtual environment).

  2. 导航到存储库的 frontend 文件夹。Navigate to the repository's frontend folder.

  3. 使用 Python 启动一个 HTTP 服务器:Start an HTTP server with Python:

    python -m http.server
    
  4. 在浏览器中导航到 localhost:8000,然后在文本框中输入以下照片 URL 之一,或使用任何可公开访问的图像的 URL。In a browser, navigate to localhost:8000, then enter one of the following photo URLs into the textbox, or use the URL of any publicly accessible image.

    • https://raw.githubusercontent.com/Azure-Samples/functions-python-tensorflow-tutorial/master/resources/assets/samples/cat1.png
    • https://raw.githubusercontent.com/Azure-Samples/functions-python-tensorflow-tutorial/master/resources/assets/samples/cat2.png
    • https://raw.githubusercontent.com/Azure-Samples/functions-python-tensorflow-tutorial/master/resources/assets/samples/dog1.png
    • https://raw.githubusercontent.com/Azure-Samples/functions-python-tensorflow-tutorial/master/resources/assets/samples/dog2.png
  5. 选择“提交”以调用函数终结点来对图像进行分类。 Select Submit to invoke the function endpoint to classify the image.

    已完成项目的屏幕截图

    如果在提交图像 URL 时浏览器报告错误,请检查运行函数应用的终端。If the browser reports an error when you submit the image URL, check the terminal in which you're running the function app. 如果出现类似于“找不到模块 'PIL'”的错误,原因可能是在 start 文件夹中启动了函数应用,但未事先激活先前创建的虚拟环境。If you see an error like "No module found 'PIL'", you may have started the function app in the start folder without first activating the virtual environment you created earlier. 如果仍出现错误,请在已激活虚拟环境的情况下再次运行 pip install -r requirements.txt,并查看错误。If you still see errors, run pip install -r requirements.txt again with the virtual environment activated and look for errors.

备注

无论图像是否包含猫或狗,模型都始终会将图像内容分类为猫或狗,默认分类为狗。The model always classifies the content of the image as a cat or a dog, regardless of whether the image contains either, defaulting to dog. 例如,老虎和豹子的图像通常分类为猫,而大象、胡萝卜或飞机的图像则分类为狗。Images of tigers and panthers, for example, typically classify as cat, but images of elephants, carrots, or airplanes classify as dog.

清理资源Clean up resources

由于整篇教程在计算机本地运行,因此没有任何 Azure 资源或服务需要清理。Because the entirety of this tutorial runs locally on your machine, there are no Azure resources or services to clean up.

后续步骤Next steps

在本教程中,你已了解如何使用 Azure Functions 生成和自定义 HTTP API 终结点,以使用 TensorFlow 模型分类图像。In this tutorial, you learned how to build and customize an HTTP API endpoint with Azure Functions to classify images using a TensorFlow model. 此外,你还了解了如何从 Web 应用调用 API。You also learned how to call the API from a web app. 可以使用本教程中所述的方法生成具有不同复杂性的 API,所有这些 API 都可在 Azure Functions 提供的无服务器计算模型上运行。You can use the techniques in this tutorial to build out APIs of any complexity, all while running on the serverless compute model provided by Azure Functions.

另请参阅:See also: