Понимание входных данных для пользовательских процедур прогнозирования платформы Google AI

Я следую документации это по пользовательским процедурам прогнозирования и пытаюсь понять, как выглядят входные данные для пользовательской процедуры прогнозирования. Код для отправки ввода выглядит следующим образом:

instances = [
        [6.7, 3.1, 4.7, 1.5],
        [4.6, 3.1, 1.5, 0.2],
    ]
service = discovery.build('ml', 'v1')
name = 'projects/{}/models/{}'.format(project, model)

if version is not None:
    name += '/versions/{}'.format(version)

response = service.projects().predict(
    name=name,
    body={'instances': instances}
).execute()

а Predictor.py на данный момент очень просто. Я просто пытаюсь понять, как выглядит ввод...

class Predictor(object):
    """An example Predictor for an AI Platform custom prediction routine."""

    def __init__(self, model):
        self._model = model

    def predict(self, instances, **kwargs):

        inputs = np.asarray(instances)
        if kwargs.get('max'):
            return np.argmax(inputs, axis=1)

        return np.sum(inputs)


    @classmethod
    def from_path(cls, model_dir):
        return cls(None)

Но когда я пытаюсь получить ответ, я получаю следующую ошибку:

{
  "error": "Prediction failed: unknown error."
}

Кроме того, крайне сложно отлаживать код, потому что нет возможности войти в код или распечатать журналы... Я понятия не имею, что происходит... Как выглядит ввод? как мне получить к ним доступ? Это всего лишь простой тест, но в конце концов я хочу отправить изображения, тогда отладить будет еще сложнее. Как я их получу? Как я буду обрабатывать их в препроцессоре? Предположим, что пропроцессинг, который я сделал во время обучения, выглядит так:

data = cv2.imread(str(img_path))
data = cv2.resize(data, (224, 224))
data = cv2.cvtColor(data, cv2.COLOR_BGR2RGB)
x = data.astype(np.float32) / 255.
return np.expand_dims(x, axis=0)

Как выглядит объект instances, чтобы я мог соответствующим образом построить препроцессор? заранее спасибо.

Вы можете использовать --enable-console-logging при создании модели, чтобы включить вывод журнала в ведение журнала StackDriver.

rhaertel80 24.06.2019 16:49
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения текстовых сообщений может быть настолько сложным или простым, насколько вы его сделаете. Как и в любом ML-проекте, вы можете выбрать...
7 лайфхаков для начинающих Python-программистов
7 лайфхаков для начинающих Python-программистов
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
Установка Apache Cassandra на Mac OS
Установка Apache Cassandra на Mac OS
Это краткое руководство по установке Apache Cassandra.
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ...
Создание персонального файлового хранилища
Создание персонального файлового хранилища
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это...
Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
4
1
1 364
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я создаю новый образец для пользовательского прогноза, который может быть полезен для отладки: Сначала я пишу файл локально через ноутбук (Colab)

%%writefile model_prediction.py

import numpy as np
import os
import pickle
import pandas as pd
import importlib

class CustomModelPrediction(object):
    _UNUSED_COLUMNS = ['fnlwgt', 'education', 'gender']
    _CSV_COLUMNS = [
        'age', 'workclass', 'fnlwgt', 'education', 'education_num',
        'marital_status', 'occupation', 'relationship', 'race', 'gender',
        'capital_gain', 'capital_loss', 'hours_per_week', 'native_country',
        'income_bracket'
    ]
    _CATEGORICAL_TYPES = {
        'workclass': pd.api.types.CategoricalDtype(categories=[
            'Federal-gov', 'Local-gov', 'Never-worked', 'Private',
            'Self-emp-inc',
            'Self-emp-not-inc', 'State-gov', 'Without-pay'
        ]),
        'marital_status': pd.api.types.CategoricalDtype(categories=[
            'Divorced', 'Married-AF-spouse', 'Married-civ-spouse',
            'Married-spouse-absent', 'Never-married', 'Separated', 'Widowed'
        ]),
        'occupation': pd.api.types.CategoricalDtype([
            'Adm-clerical', 'Armed-Forces', 'Craft-repair',
            'Exec-managerial',
            'Farming-fishing', 'Handlers-cleaners', 'Machine-op-inspct',
            'Other-service', 'Priv-house-serv', 'Prof-specialty',
            'Protective-serv',
            'Sales', 'Tech-support', 'Transport-moving'
        ]),
        'relationship': pd.api.types.CategoricalDtype(categories=[
            'Husband', 'Not-in-family', 'Other-relative', 'Own-child',
            'Unmarried',
            'Wife'
        ]),
        'race': pd.api.types.CategoricalDtype(categories=[
            'Amer-Indian-Eskimo', 'Asian-Pac-Islander', 'Black', 'Other',
            'White'
        ]),
        'native_country': pd.api.types.CategoricalDtype(categories=[
            'Cambodia', 'Canada', 'China', 'Columbia', 'Cuba',
            'Dominican-Republic',
            'Ecuador', 'El-Salvador', 'England', 'France', 'Germany',
            'Greece',
            'Guatemala', 'Haiti', 'Holand-Netherlands', 'Honduras', 'Hong',
            'Hungary',
            'India', 'Iran', 'Ireland', 'Italy', 'Jamaica', 'Japan', 'Laos',
            'Mexico',
            'Nicaragua', 'Outlying-US(Guam-USVI-etc)', 'Peru',
            'Philippines', 'Poland',
            'Portugal', 'Puerto-Rico', 'Scotland', 'South', 'Taiwan',
            'Thailand',
            'Trinadad&Tobago', 'United-States', 'Vietnam', 'Yugoslavia'
        ])
    }

    def __init__(self, model, processor):
        self._model = model
        self._processor = processor
        self._class_names = ['<=50K', '>50K']

    def _preprocess(self, instances):
        """Dataframe contains both numeric and categorical features, convert
        categorical features to numeric.

        Args:
          dataframe: A `Pandas.Dataframe` to process.
        """
        dataframe = pd.DataFrame(data=[instances], columns=self._CSV_COLUMNS[:-1])
        dataframe = dataframe.drop(columns=self._UNUSED_COLUMNS)
        # Convert integer valued (numeric) columns to floating point
        numeric_columns = dataframe.select_dtypes(['int64']).columns
        dataframe[numeric_columns] = dataframe[numeric_columns].astype(
            'float32')

        # Convert categorical columns to numeric
        cat_columns = dataframe.select_dtypes(['object']).columns
        # Keep categorical columns always using same values based on dict.
        dataframe[cat_columns] = dataframe[cat_columns].apply(
            lambda x: x.astype(self._CATEGORICAL_TYPES[x.name]))
        dataframe[cat_columns] = dataframe[cat_columns].apply(
            lambda x: x.cat.codes)
        return dataframe

    def predict(self, instances, **kwargs):
        preprocessed_data = self._preprocess(instances)
        preprocessed_inputs = self._processor.preprocess(preprocessed_data)
        outputs = self._model.predict_classes(preprocessed_inputs)
        if kwargs.get('probabilities'):
            return outputs.tolist()
        else:
            return [self._class_names[index] for index in
                    np.argmax(outputs, axis=1)]

    @classmethod
    def from_path(cls, model_dir):
        import tensorflow as tf
        model_path = os.path.join(model_dir, 'model.h5')
        model = tf.keras.models.load_model(model_path)

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

        return cls(model, preprocessor)

После того, как файл написан, я могу протестировать его локально перед развертыванием модели:

from model_prediction import CustomModelPrediction
model = CustomModelPrediction.from_path('.')
instance = [25, 'Private', 226802, '11th', 7, 'Never-married', 'Machine-op-inspct', 'Own-child', 'Black', 'Male', 0, 0, 40, 'United-States']
model.predict(instance)

Другой вариант — после сборки установочного пакета вы также можете протестировать установку локально, где my_custom_code-0.1.tar.gz — это файл, предназначенный для развертывания на платформе AI:

 pip install --target=/tmp/custom_lib --no-cache-dir -b /tmp/pip_builds my_custom_code-0.1.tar.gz

Также взгляните на раздел это:

Вы можете использовать --enable-console-logging, чтобы экспортировать журналы в свой проект. Возможно, вам потребуется создать новую модель.

Большое спасибо за ваш ответ. Если я воспроизведу ваш второй и третий фрагмент кода, все будет работать нормально, потому что я знаю, что я передаю. Но если я развернусь на платформе Google AI и передам входные данные, завернутые в JSON (как описано здесь cloud.google.com/ml-engine/docs/v1/…), я получу ошибку и, кроме того, я думаю, что теряю понимание того, что я на самом деле получаю. Если я перейду на платформу AI > режимы > щелкну мою модель > щелкну мою версию > протестировать и использовать и вставлю туда пример ввода JSON, я получу "error": "Internal error encountered." .

DarioB 22.05.2019 22:38

Кроме того, я включил ведение журнала с помощью --enable-console-logging (надеюсь, это очень полезно), но где мне теперь найти журналы? и как мне написать в лог? Спасибо

DarioB 22.05.2019 22:40
github.com/GoogleCloudPlatform/cloudml-samples/blob/master/…, не могли бы вы пока взглянуть на этот образец? Я предоставлю больше информации
gogasca 22.05.2019 23:32

Я не запускал блокнот, но выполняю все шаги в своем примере.

DarioB 23.05.2019 14:08

Я запустил ваш ноутбук, и он отлично работает (неудивительно). Но если я изменю Predictor.predict своим кодом (больше ничего не изменилось), произойдет сбой с той же ошибкой... Возможно, вы также можете попытаться воспроизвести ошибку. Это все еще очень сложно отлаживать.

DarioB 23.05.2019 17:56

Привет DarioB, извините за поздний ответ, я просто открываю вопрос для создания журналов с помощью --enable-console-logging (похоже, журналы недоступны), с пользовательским прогнозом вам все еще нужен ключ «экземпляры», а внутри него Объект, который вы хотите предсказать, например, словарь, этот объект будет ** значением kwargs, например {"instances": "{"max": [1.1, 1.0, 0.1]}"}, каков ваш окончательный объект json? Вы пробовали: gcloud ai-platform Predict --model=${MODEL_NAME} --version=${MODEL_VERSION} --json-instances=new-data.json ?

gogasca 23.05.2019 23:20

Привет, спасибо за ваш ответ. Я попробовал то, что вы предложили. Я все еще получаю ту же ошибку. Мой ввод JSON выглядит так {"instances": [ {"values": [1, 2, 3, 4], "key": 1}, {"values": [5, 6, 7, 8], "key": 2} ]}

DarioB 24.05.2019 10:44

@DarioB, ты когда-нибудь решал эту проблему? У меня все еще та же проблема.

hockeybro 18.06.2019 00:50

да, я решил это, в моем случае я действительно добавил реальную модель (а не код отладки), и это действительно сработало. Не уверен, почему. добавлю развернутый ответ

DarioB 18.06.2019 12:54

@DarioB, что ты имеешь в виду под настоящей моделью? В чем для вас разница между реальной моделью и отладочным кодом? Я просто сохраняю модель в Tensorflow с помощью saver.save и загружаю ее. Я даже не могу заставить его работать, передав входные данные JSON в Google Cloud Console в разделе: AI platform > model > click on my model > click on my version > test & use.

hockeybro 18.06.2019 21:50

Кстати, у меня есть модель, и я все еще получаю эту ошибку.

hockeybro 18.06.2019 23:04

Понимаю. Проблема, вероятно, заключается в том, как вы переносите свои данные в объект JSON и как вы читаете их в конце предиктора. Я ожидал получить ошибку типа «Ошибка ключа», но на самом деле ее нет. Сначала попробуйте сделать прогноз локально, и пусть он сначала работает таким образом. Я надеюсь, что это помогает.

DarioB 20.06.2019 10:23

Я разобрался. Это было связано с другим пакетом, в котором не было необходимых данных.

hockeybro 21.06.2019 00:02

Привет, как я могу использовать указание prediction-class, если класс находится в подкаталоге. например, в моем tar.gz, который я загружаю, он имеет структуру (верхний уровень) setup.py, categorisation_project. Затем в папке categorization_project есть место, где мой predictor.py сидит с MyPredictor, на который нужно ссылаться. Я пытался использовать categorisation_project.predictor.MyPredictor, но это не сработало. У меня также есть __init__.py, чтобы убедиться, что все работает правильно. Есть ли способ заставить это работать?

Callum Smyth 16.06.2020 17:21
Ответ принят как подходящий

Похоже, что использование отладочного кода (на момент написания этого поста) без модели не работает. Я использовал следующий код, чтобы все работало для моего варианта использования прогнозирования изображения:

image_filename = 'your image path'
PROJECT_ID = ''
MODEL_NAME = ''
VERSION_NAME = ''

img = base64.b64encode(open(image_filename, "rb").read()).decode()
image_bite_dict = {"key": "0", "image_bytes": {"b64": img}}

instances = [
            image_bite_dict
        ]


service = googleapiclient.discovery.build('ml', 'v1')
    name = 'projects/{}/models/{}/versions/{}'.format(PROJECT_ID, MODEL_NAME, VERSION_NAME)
response = service.projects().predict(
        name=name,
        body={'instances': instances}
    ).execute()

Я все еще не могу заставить его работать. Не могли бы вы рассказать мне, как именно вы сохранили модель для развертывания? Также можете ли вы добавить образец своего класса прогнозирования?

hockeybro 19.06.2019 00:21

Другие вопросы по теме