Upload a trained model

Upload a trained model

Turn a fitted scikit-learn, Keras or PyTorch model into a registered Kaimei model with one call.

client.models.upload(estimator, name=…) reads the live estimator in your process, extracts its layers and learned weights into a kaimei.structure.v1 spec, registers the model and uploads the spec. Small tensors travel inline as JSON; anything above externalize_above values (default 65,536) streams as a zlib-compressed float32 blob referenced from the spec, so models with millions of parameters upload at about four bytes per weight. The original .h5, .pt or pickle is never sent.

Arguments

estimatorobjectrequired

A fitted scikit-learn estimator or pipeline, a Keras model, a torch.nn.Module, or a wrapper that stores one on a conventional attribute (model_, estimator_, best_estimator_, module).

namestrrequired

Display name. The slug is derived from it unless you pass slug.

feature_names / featureslistoptional

Input names, or a full feature schema. Optional when the estimator knows its names (feature_names_in_, a DataFrame).

task, outputs, frameworkoptional

Inferred from the estimator when omitted. Pass outputs={"labels": [...]} to name the classes.

X, yarray-likeoptional

Reference rows (capped at 5,000) and optional labels, uploaded after the model is created.

inferencedictoptional
{"type": "remote", "url": ...} for models Kaimei cannot execute itself.
weightsstroptionaldefault "full"
"full" or "summary", which uploads shapes and statistics only: the architecture is drawable, the weights never leave your environment, and explanations need a remote URL.
externalize_aboveint | Noneoptionaldefault 65536

Values per tensor above which it uploads as binary. None keeps everything inline.

progresscallableoptional
progress(stage, done, total), called while tensors upload (stage is "tensors" then "structure").
input_shapetupleoptional

Image models in PyTorch: (channels, height, width). Keras models report their own.

preprocessdictoptional
{"mean": [...], "std": [...]} baked into the graph for torchvision-style models that expect Normalize on [0, 1] pixels.
value_rangelistoptional
[0, 255] when callers send and the model reads 0 to 255 pixels (a Keras Rescaling(1/255) model, for example).
slug, version, description, tags, metadata, project_idoptional
EstimatorWhat is uploadedExecutable
sklearn linear modelsExact coef_ / intercept_Yes
sklearn MLPClassifier / MLPRegressorExact layersYes
sklearn treeFull node listYes
sklearn forest / extra treesTrees if ≤ 30 estimators and ≤ 4,000 nodes; otherwise feature importancesOnly when trees are inlined
sklearn Pipeline + StandardScaler / MinMaxScalerScaler folded or inserted, then the estimatorAs the final step
Keras / TensorFlowDense, Conv2D (any stride, padding, dilation, groups), Depthwise/SeparableConv2D, BatchNormalization, pooling, Add, Multiply, Concatenate, ZeroPadding2D, Rescaling, Normalization, Flatten, Dropout, LayerNorm; functional graphs and nested modelsYes, unless a layer is unrecognised
torch.nn CNNsTraced with torch.fx: Conv2d, BatchNorm2d, pooling, residual +, torch.cat, squeeze-excitation *, Flatten and the common activations (ResNet, MobileNet, EfficientNet, DenseNet, VGG, SqueezeNet)Yes, with input_shape
torch.nn dense netsLinear, activations, Dropout, LayerNorm, Embedding, BatchNorm1d, in forward-hook orderYes, unless a layer is unrecognised
XGBoost / LightGBM / CatBoostfeature_importances_ summaryNo: pass inference or attributions
ONNX, Hugging Face, LLMsFramework label onlyNo

Unknown Keras or PyTorch layers that keep their input's shape are passed through and the spec is marked approximate: it visualises but cannot be queried without a remote URL. Shape-changing operations that cannot be replayed (a channel shuffle, an upsampling decoder) raise StructureError(code="unsupported_layers") naming them. kaimei.extract_structure(estimator, …) returns the spec and tensors without uploading; client.models.upload_structure(model, estimator_or_spec) attaches weights to a model you already registered.

from kaimei import Kaimei

client = Kaimei()

# a scikit-learn model with its validation rows as the reference population
model = client.models.upload(
    clf,
    name="Churn net",
    feature_names=list(X_valid.columns),
    X=X_valid, y=y_valid,
    outputs={"labels": ["stay", "churn"]},
    tags=["lifecycle"],
)
print(model.slug, model.framework)   # churn-net sklearn

# a model Kaimei cannot run: draw it, score it through your endpoint
client.models.upload(
    xgb_model,
    name="Churn forest",
    inference={"type": "remote", "url": "https://scoring.example.com/predict"},
)

# a PyTorch CNN: give the input size, bake in the normalization
client.models.upload(
    resnet,
    name="Defect classifier",
    task="multiclass_classification",
    outputs={"labels": ["ok", "scratch", "dent"]},
    input_shape=(3, 224, 224),
    preprocess={"mean": [0.485, 0.456, 0.406], "std": [0.229, 0.224, 0.225]},
    X=sample_images,                      # (n, 3, 224, 224) or (n, 224, 224, 3)
    progress=lambda stage, done, total: print(stage, done, "/", total),
)

# weights that must stay private: shapes and statistics only
client.models.upload(net, name="Pricing net", weights="summary",
                     inference={"type": "remote", "url": "https://..."})