Penulisan skrip entri lanjutan

BERLAKU UNTUK:SDK Python azureml v1

Artikel ini menjelaskan cara menulis skrip entri untuk kasus penggunaan khusus.

Prasyarat

Artikel ini mengasumsikan Anda sudah memiliki model pembelajaran mesin terlatih yang ingin Anda terapkan dengan Azure Machine Learning. Untuk mempelajari selengkapnya tentang penyebaran model, lihat Menyebarkan model pembelajaran mesin ke Azure.

Membuat skema Swagger secara otomatis

Untuk menghasilkan skema untuk layanan web Anda secara otomatis, berikan sampel input dan/atau output di konstruktor untuk salah satu objek jenis yang ditentukan. Jenis dan sampel digunakan untuk membuat skema secara otomatis. Azure Pembelajaran Mesin kemudian membuat spesifikasi OpenAPI (sebelumnya, spesifikasi Swagger) untuk layanan web selama penyebaran.

Peringatan

Anda tidak boleh menggunakan data sensitif atau privat untuk contoh input atau output. Halaman Swagger untuk inferensi yang di-hosting AML memaparkan data sampel.

Tipe ini saat ini didukung:

  • pandas
  • numpy
  • pyspark
  • Objek Python standar

Untuk menggunakan pembuatan skema, sertakan paket sumber terbuka inference-schema versi 1.1.0 atau lebih tinggi dalam file dependensi Anda. Untuk informasi selengkapnya tentang paket ini, lihat InferenceSchema di GitHub. Untuk menghasilkan Swagger yang sesuai untuk konsumsi layanan web otomatis, fungsi penilaian skrip run() harus memiliki bentuk API:

  • Parameter pertama jenis StandardPythonParameterType, bernama Input dan berlapis
  • Parameter kedua opsional dari jenis StandardPythonParameterType, bernama GlobalParameters
  • Mengembalikan kamus jenis StandardPythonParameterType, bernama Hasil dan berlapis

Tentukan format sampel input dan output dalam variabel input_sample dan output_sample, yang mewakili format permintaan dan respons untuk layanan web. Gunakan sampel ini dalam dekorator fungsi input dan output pada fungsi run(). Contoh scikit-learn berikut menggunakan pembuatan skema.

Titik akhir Power BI yang kompatibel

Contoh berikut menunjukkan cara menentukan bentuk API sesuai dengan instruksi sebelumnya. Metode ini didukung untuk mengonsumsi layanan web yang digunakan dari Power BI.

import json
import pickle
import numpy as np
import pandas as pd
import azureml.train.automl
from sklearn.externals import joblib
from sklearn.linear_model import Ridge

from inference_schema.schema_decorators import input_schema, output_schema
from inference_schema.parameter_types.standard_py_parameter_type import StandardPythonParameterType
from inference_schema.parameter_types.numpy_parameter_type import NumpyParameterType
from inference_schema.parameter_types.pandas_parameter_type import PandasParameterType


def init():
    global model
    # Replace filename if needed.
    model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_regression_model.pkl')
    # Deserialize the model file back into a sklearn model.
    model = joblib.load(model_path)


# providing 3 sample inputs for schema generation
numpy_sample_input = NumpyParameterType(np.array([[1,2,3,4,5,6,7,8,9,10],[10,9,8,7,6,5,4,3,2,1]],dtype='float64'))
pandas_sample_input = PandasParameterType(pd.DataFrame({'name': ['Sarah', 'John'], 'age': [25, 26]}))
standard_sample_input = StandardPythonParameterType(0.0)

# This is a nested input sample, any item wrapped by `ParameterType` will be described by schema
sample_input = StandardPythonParameterType({'input1': numpy_sample_input, 
                                        'input2': pandas_sample_input, 
                                        'input3': standard_sample_input})

sample_global_parameters = StandardPythonParameterType(1.0) # this is optional
sample_output = StandardPythonParameterType([1.0, 1.0])
outputs = StandardPythonParameterType({'Results':sample_output}) # 'Results' is case sensitive

@input_schema('Inputs', sample_input) 
# 'Inputs' is case sensitive

@input_schema('GlobalParameters', sample_global_parameters) 
# this is optional, 'GlobalParameters' is case sensitive

@output_schema(outputs)

def run(Inputs, GlobalParameters): 
    # the parameters here have to match those in decorator, both 'Inputs' and 
    # 'GlobalParameters' here are case sensitive
    try:
        data = Inputs['input1']
        # data will be convert to target format
        assert isinstance(data, np.ndarray)
        result = model.predict(data)
        return result.tolist()
    except Exception as e:
        error = str(e)
        return error

Tip

Nilai yang ditampilkan dari skrip mungkin merupakan objek Python apa pun yang dapat diserialkan ke JSON. Misalnya, jika model Anda menampilkan dataframe Panda yang berisi beberapa kolom, Anda dapat menggunakan dekorator output yang mirip dengan kode berikut:

output_sample = pd.DataFrame(data=[{"a1": 5, "a2": 6}])
@output_schema(PandasParameterType(output_sample))
...
result = model.predict(data)
return result

Data biner (yaitu, citra)

Jika model Anda menerima data biner, seperti gambar, Anda harus memodifikasi file score.py yang digunakan untuk penyebaran Anda untuk menerima permintaan HTTP mentah. Untuk menerima data mentah, gunakan kelas AMLRequest di skrip entri Anda dan tambahkan dekorator @rawhttp ke fungsi run().

Berikut adalah contoh score.py yang menerima data biner:

from azureml.contrib.services.aml_request import AMLRequest, rawhttp
from azureml.contrib.services.aml_response import AMLResponse
from PIL import Image
import json


def init():
    print("This is init()")
    

@rawhttp
def run(request):
    print("This is run()")
    
    if request.method == 'GET':
        # For this example, just return the URL for GETs.
        respBody = str.encode(request.full_path)
        return AMLResponse(respBody, 200)
    elif request.method == 'POST':
        file_bytes = request.files["image"]
        image = Image.open(file_bytes).convert('RGB')
        # For a real-world solution, you would load the data from reqBody
        # and send it to the model. Then return the response.

        # For demonstration purposes, this example just returns the size of the image as the response.
        return AMLResponse(json.dumps(image.size), 200)
    else:
        return AMLResponse("bad request", 500)

Penting

Kelas AMLRequest berada di namespace layanan azureml.contrib. Entitas di ruang nama ini sering berubah saat kami bekerja untuk meningkatkan layanan. Apa pun di ruang nama ini harus dianggap sebagai pratinjau yang tidak sepenuhnya didukung oleh Microsoft.

Jika Anda perlu menguji ini di lingkungan pengembangan lokal Anda, Anda dapat memasang komponen dengan menggunakan perintah berikut:

pip install azureml-contrib-services

Catatan

500 tidak disarankan sebagai kode status kustom, seperti di sisi azureml-fe, kode status akan ditulis ulang menjadi 502.

  • Kode status diteruskan melalui azureml-fe, lalu dikirim ke klien.
  • Azureml-fe hanya menulis ulang 500 yang dikembalikan dari sisi model menjadi 502, klien menerima 502.
  • Tetapi jika azureml-fe itu sendiri mengembalikan 500, sisi klien masih menerima 500.

Kelas ini AMLRequest hanya memungkinkan Anda mengakses data mentah yang diposting dalam file score.py , tidak ada komponen sisi klien. Dari klien, Anda mem-posting data seperti biasa. Misalnya, kode Python berikut membaca file gambar dan mem-posting data:

import requests

uri = service.scoring_uri
image_path = 'test.jpg'
files = {'image': open(image_path, 'rb').read()}
response = requests.post(uri, files=files)

print(response.json)

Berbagi sumber daya lintas asal (CORS)

Berbagi sumber daya lintas asal adalah cara untuk memungkinkan sumber daya pada halaman web diminta dari domain lain. CORS bekerja melalui header HTTP yang dikirim dengan permintaan klien dan dikembalikan dengan respons layanan. Untuk informasi selengkapnya tentang CORS dan header yang valid, lihat Berbagi sumber daya lintas asal di Wikipedia.

Untuk mengonfigurasi penyebaran model untuk mendukung CORS, gunakan kelas AMLResponse di skrip entri Anda. Kelas ini memungkinkan Anda untuk mengatur header pada objek respons.

Contoh berikut mengatur header Access-Control-Allow-Origin untuk respons dari skrip entri:

from azureml.contrib.services.aml_request import AMLRequest, rawhttp
from azureml.contrib.services.aml_response import AMLResponse


def init():
    print("This is init()")

@rawhttp
def run(request):
    print("This is run()")
    print("Request: [{0}]".format(request))
    if request.method == 'GET':
        # For this example, just return the URL for GET.
        # For a real-world solution, you would load the data from URL params or headers
        # and send it to the model. Then return the response.
        respBody = str.encode(request.full_path)
        resp = AMLResponse(respBody, 200)
        resp.headers["Allow"] = "OPTIONS, GET, POST"
        resp.headers["Access-Control-Allow-Methods"] = "OPTIONS, GET, POST"
        resp.headers['Access-Control-Allow-Origin'] = "http://www.example.com"
        resp.headers['Access-Control-Allow-Headers'] = "*"
        return resp
    elif request.method == 'POST':
        reqBody = request.get_data(False)
        # For a real-world solution, you would load the data from reqBody
        # and send it to the model. Then return the response.
        resp = AMLResponse(reqBody, 200)
        resp.headers["Allow"] = "OPTIONS, GET, POST"
        resp.headers["Access-Control-Allow-Methods"] = "OPTIONS, GET, POST"
        resp.headers['Access-Control-Allow-Origin'] = "http://www.example.com"
        resp.headers['Access-Control-Allow-Headers'] = "*"
        return resp
    elif request.method == 'OPTIONS':
        resp = AMLResponse("", 200)
        resp.headers["Allow"] = "OPTIONS, GET, POST"
        resp.headers["Access-Control-Allow-Methods"] = "OPTIONS, GET, POST"
        resp.headers['Access-Control-Allow-Origin'] = "http://www.example.com"
        resp.headers['Access-Control-Allow-Headers'] = "*"
        return resp
    else:
        return AMLResponse("bad request", 400)

Penting

Kelas AMLResponse berada di namespace layanan azureml.contrib. Entitas di ruang nama ini sering berubah saat kami bekerja untuk meningkatkan layanan. Apa pun di ruang nama ini harus dianggap sebagai pratinjau yang tidak sepenuhnya didukung oleh Microsoft.

Jika Anda perlu menguji ini di lingkungan pengembangan lokal Anda, Anda dapat memasang komponen dengan menggunakan perintah berikut:

pip install azureml-contrib-services

Peringatan

Azure Pembelajaran Mesin hanya merutekan permintaan POST dan GET ke kontainer yang menjalankan layanan penilaian. Ini dapat menyebabkan kesalahan karena browser menggunakan permintaan OPTIONS untuk permintaan CORS pra-pengaktifan.

Memuat model terdaftar

Ada dua cara untuk menemukan model dalam skrip entri Anda:

  • AZUREML_MODEL_DIR: Variabel lingkungan yang berisi jalur ke lokasi model
  • Model.get_model_path: API yang mengembalikan jalur ke file model menggunakan nama model terdaftar

AZUREML_MODEL_DIR

AZUREML_MODEL_DIR adalah variabel lingkungan yang dibuat selama penyebaran layanan. Anda dapat menggunakan variabel lingkungan ini untuk menemukan lokasi model yang disebarkan.

Tabel berikut ini menjelaskan nilai AZUREML_MODEL_DIR bergantung pada jumlah model yang disebarkan:

Penyebaran Nilai variabel lingkungan
Model tunggal Jalur ke folder yang berisi model.
Beberapa model Jalur ke folder yang berisi semua model. Model terletak berdasarkan nama dan versi dalam folder ini ($MODEL_NAME/$VERSION)

Selama pendaftaran dan penyebaran model, Model ditempatkan di jalur AZUREML_MODEL_DIR, dan nama file aslinya dipertahankan.

Untuk mendapatkan jalur ke file model di skrip entri Anda, gabungkan variabel lingkungan dengan jalur file yang Anda cari.

Contoh model tunggal

# Example when the model is a file
model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_regression_model.pkl')

# Example when the model is a folder containing a file
file_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'my_model_folder', 'sklearn_regression_model.pkl')

Contoh beberapa model

Dalam skenario ini, dua model terdaftar di ruang kerja:

  • my_first_model: Berisi satu file (my_first_model.pkl) dan hanya ada satu versi, 1
  • my_second_model: Berisi satu file (my_second_model.pkl) dan ada dua versi, 1 dan 2

Ketika layanan disebarkan, kedua model disediakan dalam operasi penyebaran:

first_model = Model(ws, name="my_first_model", version=1)
second_model = Model(ws, name="my_second_model", version=2)
service = Model.deploy(ws, "myservice", [first_model, second_model], inference_config, deployment_config)

Dalam gambar Docker yang meng-hosting layanan, variabel lingkungan AZUREML_MODEL_DIR berisi direktori tempat model berada. Dalam direktori ini, masing-masing model terletak di jalur direktori MODEL_NAME/VERSION. Di mana MODEL_NAME adalah nama model terdaftar, dan VERSION adalah versi model. File yang membentuk model terdaftar disimpan dalam direktori ini.

Dalam contoh ini, jalan akan $AZUREML_MODEL_DIR/my_first_model/1/my_first_model.pkl dan $AZUREML_MODEL_DIR/my_second_model/2/my_second_model.pkl.

# Example when the model is a file, and the deployment contains multiple models
first_model_name = 'my_first_model'
first_model_version = '1'
first_model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), first_model_name, first_model_version, 'my_first_model.pkl')
second_model_name = 'my_second_model'
second_model_version = '2'
second_model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), second_model_name, second_model_version, 'my_second_model.pkl')

get_model_path

Saat mendaftarkan model, Anda memberikan nama model yang digunakan untuk mengelola model di registri. Anda menggunakan nama ini dengan metode Model.get_model_path() untuk mengambil jalur berkas model atau berkas pada sistem berkas lokal. Jika Anda mendaftarkan folder atau koleksi file, API ini mengembalikan jalur direktori yang berisi file-file tersebut.

Ketika Anda mendaftarkan model, Anda memberinya nama. Nama ini sesuai dengan tempat model ditempatkan, baik secara lokal atau selama penyebaran layanan.

Contoh spesifik kerangka kerja

Lihat artikel berikut untuk contoh skrip entri lainnya untuk kasus penggunaan pembelajaran mesin tertentu: