모델 어댑터의 입력과 출력 API
api()는 추론에 필요한 입력과 출력의 이름 및 자료형을 선언합니다. 간편 정의에서는 입력 사전과 출력 사전을 쌍으로 반환합니다. Foundry는 선언한 이름으로 predict()에 입력을 전달하고 반환값을 출력에 연결합니다.
표와 추가 매개변수
다음 어댑터는 input_dataframe의 input_feature를 실제 모델에 전달하고 예측에 input_parameter를 곱합니다. model 인자는 해당 특성의 표를 받아 행별 수치 예측을 반환하는 학습된 모델이어야 합니다. 입력 표의 다른 열은 유지합니다.
import palantir_models as pm
class ExampleModelAdapter(pm.ModelAdapter):
@pm.auto_serialize
def __init__(self, model):
self.model = model
@classmethod
def api(cls):
inputs = {
"input_dataframe": pm.Pandas(columns=[("input_feature", float)]),
"input_parameter": pm.Parameter(float, default=1.0),
}
outputs = {
"output_dataframe": pm.Pandas(
columns=[("input_feature", float), ("prediction", float)]
)
}
return inputs, outputs
def predict(self, input_dataframe, input_parameter):
features = input_dataframe[["input_feature"]]
input_dataframe["prediction"] = self.model.predict(features) * input_parameter
return input_dataframe
추가 매개변수가 필요하지 않으면 input_parameter 선언과 메서드 인자 및 배율을 제거한 단일 표 입력 API로 정의합니다. 이름 있는 입력과 출력은 여러 개 선언할 수 있습니다. 여러 출력을 쓰는 경우에는 run_inference를 사용합니다.
입력과 출력의 종류
| 선언 | 의미와 조건 |
|---|---|
| pm.Pandas(columns) | Pandas DataFrame 입력 또는 출력입니다. 열 이름 및 자료형을 선언합니다. |
| pm.Spark(columns=[]) | Spark DataFrame 입력 또는 출력입니다. 기본 열 목록은 빈 목록입니다. |
| pm.Parameter(type=Any, default=None) | 단일 값 매개변수입니다. 자료형과 생략 시 기본값을 지정합니다. |
| pm.FileSystem() | Foundry 데이터셋 파일시스템입니다. transform 또는 transform_write에 데이터셋 입력을 전달할 때 사용할 수 있습니다. 입력은 데이터셋 파일시스템, 출력은 파일을 쓰는 open 메서드를 제공합니다. 파일시스템 출력은 transform_write로 소비합니다. |
| pm.MediaReference() | 미디어 참조 입력입니다. 참조 객체를 JSON 문자열 또는 사전으로 전달합니다. 독립 모델 출력 타입으로는 지원하지 않습니다. |
| pm.Object(object_type) | 생성한 Python OSDK의 객체 타입입니다. 해당 객체 인스턴스 또는 기본 키를 입력합니다. 출력 타입으로는 지원하지 않습니다. |
| pm.ObjectSet(object_type) | 생성한 OSDK 객체 타입의 집합입니다. 해당 ObjectSet 인스턴스 또는 객체 집합 RID를 입력합니다. 출력 타입으로는 지원하지 않습니다. |
Pandas와 Spark 열은 이름 문자열의 목록 또는 (열 이름, Python 자료형) 튜플 목록으로 선언합니다. 이름만 지정한 열의 자료형은 Any입니다.
표 열의 자료형
str, int, float, bool, list, dict, datetime.date, datetime.time, datetime.datetime, typing.Any 및 MediaReference를 지원합니다. List[str]나 Dict[str, float] 같은 구체 컬렉션 자료형도 사용할 수 있습니다.
배치 추론에서 열의 선언 자료형은 대체로 엄격하게 강제하지 않습니다. 추가 열도 삭제하지 않고 predict에 전달합니다. 직접 온라인 배포는 선언한 자료형으로 입력을 변환하며 필수 열이 없거나 변환할 수 없으면 오류가 발생합니다. Modeling Objective 온라인 배포는 같은 자동 자료형 변환을 지원하지 않습니다. MediaReference 열은 모델 어댑터에서 참조 문자열을 실제 미디어 참조 객체로 변환합니다.
출력 스키마에는 필수 열만 선언할 수 있습니다. 입력에 input_feature와 extra_column을 전달하고 prediction을 추가한 표를 반환하면 extra_column도 결과에 유지할 수 있습니다. 모델에는 학습에 쓴 특성만 선택해서 전달해야 합니다. 모델이 열 순서에 의존하면 예측 전에 순서를 맞춥니다. REST의 JSON 객체 순서가 학습 특성의 순서와 같다고 가정하지 않습니다.
단일 매개변수의 자료형
str, int, float, bool, list, dict, typing.Any와 pm.NDArray를 지원합니다. Parameter 자료형은 항상 검증하며 model.transform에 선언과 맞지 않는 값을 전달하면 실행 오류가 발생합니다. 인자를 생략하면 구성한 default를 사용합니다.
NumPy NDArray
pm.Parameter(type=pm.NDArray(shape, dtype))로 N차원 배열을 선언합니다. shape와 dtype을 모두 지정해야 합니다. shape는 list[int]이며 특정 차원의 길이를 검사하지 않으려면 그 위치에 -1을 사용합니다.
지원 dtype은 np.str_, np.bool_, np.int8, np.int16, np.int32, np.int64, np.float16, np.float32 및 np.float64입니다.
아래 어댑터는 model.process(ndarray)가 같은 선언의 NumPy 배열을 반환하는 모델을 받습니다. 배열 형태는 [1, 1, 2], dtype은 np.int8이며 기본 입력은 [[[1, -5]]]입니다.
import numpy as np
import palantir_models as pm
class NumpyModelAdapter(pm.ModelAdapter):
@pm.auto_serialize
def __init__(self, model):
self.model = model
@classmethod
def api(cls):
inputs = {
"ndarray_in": pm.Parameter(
type=pm.NDArray([1, 1, 2], np.int8),
default=np.array([[[1, -5]]], dtype=np.int8),
)
}
outputs = {
"ndarray_out": pm.Parameter(type=pm.NDArray([1, 1, 2], np.int8))
}
return inputs, outputs
def predict(self, ndarray_in):
return self.model.process(ndarray_in)
변환에서 ndarray 객체를 predict에 직접 전달할 수 있습니다. transform은 배열을 표현한 중첩 목록도 받아 선언된 배열로 변환합니다. 아래 model은 앞의 어댑터를 로드한 인스턴스입니다.
import numpy as np
ndarray = np.array([[[-95, -63]]], dtype=np.int8)
array_from_predict = model.predict(ndarray_in=ndarray)
array_from_transform = model.transform(ndarray_in=ndarray.tolist()).ndarray_out
두 결과는 np.ndarray입니다. 모델 함수에서는 입력을 항상 JSON 호환 중첩 목록으로 전달하고 출력도 중첩 목록으로 받습니다. 위 API의 입력 이름은 ndarray_in이며 다음 JSON은 3차원 정수 입력입니다. TypeScript 함수에서 해당 값은 Integer[][][]으로 표현합니다.
{"ndarray_in": [[[-95, -63]]]}
객체와 객체 집합
온톨로지에서 생성한 OSDK의 객체 클래스를 선언에 사용합니다. 예시 ExampleRestaurant 타입에는 pm.Object(ExampleRestaurant)와 pm.ObjectSet(ExampleRestaurant)를 지정합니다. predict는 해당 객체와 객체 집합을 전달받습니다. 온톨로지 연결에 SDK 생성 위치, Query 선택기 및 추론 중 객체 조회 예제가 있습니다.
Modeling Objectives의 배치 배포
목표에서 직접 구성하는 배치 배포와 자동 모델 평가는 표 데이터셋 입력 하나를 받는 모델에 연결됩니다. 여러 입력이 필요한 모델은 Python 변환에서 배치 추론을 구성합니다.
자동 평가는 표 입력 하나와 표 출력 하나를 요구합니다. 평가 데이터의 실제값 열을 출력에 유지하여 예측과 비교할 수 있어야 합니다. 실제값 열을 API의 필수 입력 또는 출력에 명시하지는 않습니다. 온라인 추론에는 실제값이 없으므로 필수 열로 선언하면 그 요청이 실패합니다.
다음 예제는 median_income, housing_median_age와 total_rooms로 학습한 모델을 받습니다. house_price 실제값이 입력에 있으면 원래 표에 남기지만 모델 특성에는 넣지 않습니다. 예측 열 이름은 선언과 실행 모두 predicted_house_price입니다.
import palantir_models as pm
from palantir_models.serializers import DillSerializer
class LinearRegressionModelAdapter(pm.ModelAdapter):
@pm.auto_serialize(model=DillSerializer())
def __init__(self, model):
self.model = model
@classmethod
def api(cls):
input_columns = [
("median_income", float),
("housing_median_age", float),
("total_rooms", float),
]
output_columns = input_columns + [("predicted_house_price", float)]
return (
{"df_in": pm.Pandas(input_columns)},
{"df_out": pm.Pandas(output_columns)},
)
def predict(self, df_in):
feature_columns = ["median_income", "housing_median_age", "total_rooms"]
df_in["predicted_house_price"] = self.model.predict(df_in[feature_columns])
return df_in
Functions로 게시할 때
모델 API의 입력은 Parameter, 표 형식, Object 또는 ObjectSet이어야 합니다. API에는 Any를 사용할 수 없습니다. 표 입력과 출력에 필수 열을 명시해야 하므로 열이 없는 pm.Pandas()나 pm.Spark()는 사용할 수 없습니다. list와 dict는 list[str]나 dict[str, str]처럼 원소 자료형을 명시합니다.
게시한 뒤 API를 바꾸면 함수를 사용하는 앱과 코드도 새 함수 API에 맞춰 갱신합니다.