如何从自定义 AI 平台模型登录

Posted

技术标签:

【中文标题】如何从自定义 AI 平台模型登录【英文标题】:How to log from a custom ai platform model 【发布时间】:2020-05-26 12:31:24 【问题描述】:

我最近将一个自定义模型部署到谷歌云的 AI 平台,我正在尝试调试我的预处理逻辑的某些部分。但是,我的打印语句未记录到堆栈驱动程序输出中。我也尝试过使用从 google.cloud 导入的日志客户端,但无济于事。这是我的自定义预测文件:

import os
import pickle

import numpy as np
from sklearn.datasets import load_iris
import tensorflow as tf

from google.cloud import logging

class MyPredictor(object):
  def __init__(self, model, preprocessor):
    self.logging_client = logging.Client()
    self._model = model
    self._preprocessor = preprocessor
    self._class_names = ["Snare", "Kicks", "ClosedHH", "ClosedHH",  "Clap", "Crash", "Perc"]

  def predict(self, instances, **kwargs):
    log_name = "Here I am"
    logger = self.logging_client.logger(log_name)
    text = 'Hello, world!'
    logger.log_text(text)
    print('Logged: '.format(text), kwargs.get("sr"))

    inputs = np.asarray(instances)

    outputs = self._model.predict(inputs)

    if kwargs.get('probabilities'):
      return outputs.tolist()
      #return "[]"
    else:
      return [self._class_names[index] for index in np.argmax(outputs.tolist(), axis=1)]

  @classmethod
  def from_path(cls, model_dir):
    model_path = os.path.join(model_dir, 'model.h5')
    model = tf.keras.models.load_model(model_path, custom_objects="adam": tf.keras.optimizers.Adam, 
 "categorical_crossentropy":tf.keras.losses.categorical_crossentropy, "lr":0.01, "name": "Adam")

    preprocessor_path = os.path.join(model_dir, 'preprocessor.pkl')
    with open(preprocessor_path, 'rb') as f:
      preprocessor = pickle.load(f)

    return cls(model, preprocessor)

我在网上找不到任何关于为什么我的日志没有显示在堆栈驱动程序中的任何信息(打印语句和日志库调用都没有)。有人遇到过这个问题吗?

谢谢, 尼基塔

注意:如果您有足够的代表来创建标签,请将 google-ai-platform 标签添加到这篇文章中。我认为这真的会对处于我位置的人有所帮助。谢谢!

【问题讨论】:

您好 Nikita,我发现了同样的问题,会尽快回复您。 【参考方案1】:

来自Documentation:

如果要启用在线预测日志记录,则必须对其进行配置 创建模型资源或创建模型版本时 资源,具体取决于您要启用的日志记录类型。那里 是三种类型的日志记录,您可以单独启用它们:

访问日志记录,记录时间戳和延迟等信息 对 Stackdriver Logging 的每个请求。

您可以在创建模型资源时启用访问日志记录。

流日志记录,用于记录您的标准错误和标准输出流 Stackdriver Logging 的预测节点,可用于 调试。这种类型的日志记录处于测试阶段,不支持 Compute Engine (N1) 机器类型。

您可以在创建模型资源时启用流日志记录。

请求-响应日志记录,记录在线预测的样本 对 BigQuery 表的请求和响应。这种类型的日志记录在 测试版。

您可以通过创建模型版本来启用请求-响应日志记录 资源,然后更新该版本。

对于您的用例,请使用以下模板将自定义信息记录到 StackDriver:

型号

gcloud beta ai-platform models create MODEL_NAME \
 --regions REGION \
 --enable-logging \
 --enable-console-logging

模型版本

gcloud beta ai-platform versions create VERSION_NAME \
    --model MODEL_NAME \
    --origin gs://BUCKET/MODEL_DIR \
    --python-version 3.7 \
    --runtime-version 1.15 \
    --package-uris gs://BUCKET/PACKAGES_DIR/custom-model-0.1.tar.gz \
    --prediction-class=custom_prediction.CustomModelPrediction \
    --service-account custom@project_id.iam.gserviceaccount.com

我试过了,效果很好:

由于@classmethod 装饰器,我对构造函数做了一些修改。 创建一个服务帐号并为其授予“Stackdriver Debugger User”角色,在模型版本创建期间使用它 将google-cloud-logging 库添加到您的setup.py 考虑启用 StackDriver 日志记录的额外费用 使用log_struct 时检查是否通过了正确的类型。 (如果使用 str,请确保在 Python 3 中使用 .decode('utf-8')bytes 转换为 str) 在 Stackdriver 客户端创建期间定义 project_id 参数 logging.Client(),否则你会得到:
ERROR:root:Prediction failed: 400 Name "projects//logs/my-custom-prediction-log" is missing the parent component. Expected the form projects/[PROJECT_ID]/logs/[ID]" 

代码如下:

%%writefile cloud_logging.py

import os
import pickle
import numpy as np

from datetime import date
from google.cloud import logging

import tensorflow.keras as keras
LOG_NAME = 'my-custom-prediction-log'

class CustomModelPrediction(object):
    def __init__(self, model, processor, client):    
        self._model = model
        self._processor = processor
        self._client = client

    def _postprocess(self, predictions):
        labels = ['negative', 'positive']
        return [
            
                "label":labels[int(np.round(prediction))],
                "score":float(np.round(prediction, 4))
             for prediction in predictions]

    def predict(self, instances, **kwargs):
        logger = self._client.logger(LOG_NAME)
        logger.log_struct('instances':instances)
        preprocessed_data = self._processor.transform(instances)
        predictions =  self._model.predict(preprocessed_data)
        labels = self._postprocess(predictions)
        return labels

    @classmethod
    def from_path(cls, model_dir):        
        client = logging.Client(project='project_id') # Change to your project
        model = keras.models.load_model(
          os.path.join(model_dir,'keras_saved_model.h5'))
        with open(os.path.join(model_dir, 'processor_state.pkl'), 'rb') as f:
            processor = pickle.load(f)    
        return cls(model, processor, client)

# Verify model locally

from cloud_logging import CustomModelPrediction
classifier = CustomModelPrediction.from_path('.')

requests = ["God I hate the north", "god I love this"]
response = classifier.predict(requests)
response

然后我检查sample library:

python snippets.py my-custom-prediction-log list
Listing entries for logger my-custom-prediction-log:
* 2020-02-19T19:51:45.809767+00:00: u'instances': [u'God I hate the north', u'god I love this']
* 2020-02-19T19:57:18.615159+00:00: u'instances': [u'God I hate the north', u'god I love this']

要可视化日志,请在 StackDriver > Logging > 选择 Global 和您的日志名称,如果您想查看模型日志,您应该能够选择 Cloud ML 模型版本。

您可以在这里使用我的文件:model 和 pre-processor

【讨论】:

modelpre-processor 链接是相同的【参考方案2】:

如果你只是想让你的打印工作而不是使用我上面的记录方法,你可以在你的打印中添加刷新标志,

print(“logged”,flush=True)

【讨论】:

以上是关于如何从自定义 AI 平台模型登录的主要内容,如果未能解决你的问题,请参考以下文章

如何从自定义模型对象数组中获取特定键的值

从自定义 Django 用户模型中删除密码

Vertex AI 自定义容器批量预测

从自定义查询返回模型而不访问数据库

从自定义视觉导出标签

从自定义预训练模型中删除层