如何在 Azure 机器学习服务的初始化过程中传入模型名称?

How to pass in the model name during init in Azure Machine Learning Service?

我正在通过 Azure 机器学习服务在 Azure 容器实例上部署 50 个 NLP 模型。所有 50 个模型都非常相似并且具有相同的 input/output 格式,只是模型实现略有变化。

我想编写一个通用的 score.py 入口文件并传入模型名称作为参数。接口方法签名不允许在score.py的init()方法中有参数,所以我将模型加载移到了运行方法中。我假设 init() 方法获得 运行 一次,而 运行(data) 将在每次调用时执行,所以这可能不理想(模型大小为 1 gig)

那么我怎样才能将一些值传递给容器的 init() 方法来告诉它加载什么模型?

这是我当前的工作代码:

def init():

def loadModel(model_name):
    model_path = Model.get_model_path(model_name)  
    return fasttext.load_model(model_path)

def run(raw_data):
    # extract model_name from raw_data omitted...
    model = loadModel(model_name)

    ...

但这就是我想做的(这会破坏界面)

def init(model_name):
    model = loadModel(model_name)

def loadModel(model_name):
    model_path = Model.get_model_path(model_name)  
    return fasttext.load_model(model_path)

def run(raw_data):
    ...

如果您希望使用相同的已部署容器并在请求之间切换模型;它不是 Azure 机器学习服务的首选设计选择,我们需要在 build/deploy.

期间指定要加载的模型名称

理想情况下,每个部署的网络服务端点应该只允许推断一个模型;使用在容器之前定义的模型名称,图像开始 building/deploying。

入口脚本必须具有 init()run(raw_data) 以及那些 完全 签名。

目前,我们无法更改 init() 方法的签名以采用 init(model_name) 中的参数。

您唯一可以传递到此 Web 服务的动态用户输入是通过 run(raw_data) 方法。正如您所尝试的那样,考虑到通过 运行 传递它的模型的大小是不可行的。

init() 是 运行 第一次,也是仅 一次 在您的网络服务部署之后。即使 init() 接受了 model_name 参数,也没有直接调用此方法并传递所需模型名称的直接方法。


但是,一种可能的解决方案是:

您可以像下面这样创建参数文件并将该文件存储在 azure blob 存储中。

示例运行时间参数生成脚本:

import pickle

params = {'model_name': 'YOUR_MODEL_NAME_TO_USE'}

with open('runtime_params.pkl', 'wb') as file:
    pickle.dump(params, file)

您需要使用 Azure Storage Python SDK to write code that can read from your blob storage account. This also mentioned in the official docs here

然后您可以从得分脚本中的 init() 函数访问它。

示例 score.py 脚本:

from azure.storage.blob import BlockBlobService
import pickle

def init():

  global model

  block_blob_service = BlockBlobService(connection_string='your_connection_string')

  blob_item = block_blob_service.get_blob_to_bytes('your-container-name','runtime_params.pkl')

  params = pickle.load(blob_item.content)

  model = loadModel(params['model_name'])

您可以将连接字符串存储在 Azure KeyVault 中以实现安全访问。 Azure ML Workspaces 带有内置的 KeyVault 集成。更多信息 here.

使用这种方法,您可以将 运行时间参数配置抽象到另一个云位置而不是容器本身。因此您不需要重新构建映像或再次部署网络服务。只需重新启动容器即可。


如果您只是想简单地重复使用 score.py(不更改代码)多个容器中的多个模型部署,那么这是另一个可能的解决方案。

您可以在文本文件中定义要在网络服务中使用的模型名称,并在 score.py 中阅读。在设置图像配置时,您需要将此文本文件作为依赖项传递。

但是,每个容器部署都需要多个参数文件。

dependencies 中的 'runtime_params.pkl' 传递给您的图像配置(更详细的示例 here):

image_config = ContainerImage.image_configuration(execution_script="score.py", 
                                                  runtime="python", 
                                                  conda_file="myenv.yml",
                                                  dependencies=["runtime_params.pkl"],
                                                  docker_file="Dockerfile")

在您的 score.py init() 函数中阅读此内容:

def init():

  global model

  with open('runtime_params.pkl', 'rb') as file:
    params = pickle.load(file)

  model = loadModel(params['model_name'])

由于您使用这种方法创建了新的映像配置,因此您需要构建映像并重新部署服务。