I have wrapped my keras-tf-model into a Sklearn Pipeline, which also does some pre- and postprocessing. I want to serialize this model and capture its dependencies via MLflow.
I have tried mlflow.keras.save_model(), which seems not appropriate. (it's not a "pure" keras model and as no save() attribute)
I also tried mlflow.sklearn.save_model() and mlflow.pyfunc.save_model(), which both lead my to the same error:
NotImplementedError: numpy() is only available when eager execution is enabled.
(This error seems to stem from a clash between python and tensorflow, maybe?)
I wonder, should it already/ generally be possible to serialize these kind of "hybrid" models with mlflow?
Please finde a minimal example below
# In[1]:
from mlflow.sklearn import save_model
import mlflow.sklearn
from sklearn.datasets import load_iris
from sklearn import tree
from tensorflow.keras.models import Sequential
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
# ### Save Keras Model
# In[2]:
iris_data = load_iris()
x = iris_data.data
y_ = iris_data.target.reshape(-1, 1)
# One Hot encode the class labels
encoder = OneHotEncoder(sparse=False)
y = encoder.fit_transform(y_)
# Split the data for training and testing
train_x, test_x, train_y, test_y = train_test_split(x, y, test_size=0.20)
# Build the model
model = Sequential()
model.add(Dense(10, input_shape=(4,), activation='relu', name='fc1'))
model.add(Dense(10, activation='relu', name='fc2'))
model.add(Dense(3, activation='softmax', name='output'))
optimizer = Adam(lr=0.001)
model.compile(optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
# Train the model
model.fit(train_x, train_y, verbose=2, batch_size=5, epochs=20)
# In[3]:
import mlflow.keras
mlflow.keras.save_model(model, "modelstorage/model40")
# ### Save Minimal SKlearn-Pipeline (with Keras)
# In[4]:
from category_encoders.target_encoder import TargetEncoder
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from keras.wrappers.scikit_learn import KerasClassifier
# In[5]:
def define_model():
"""
Create fully connected network with given parameters.
"""
keras_model = Sequential()
keras_model.add(Dense(10, input_shape=(4,), activation='relu', name='fc1'))
keras_model.add(Dense(10, activation='relu', name='fc2'))
keras_model.add(Dense(3, activation='softmax', name='output'))
optimizer = Adam(lr=0.001)
keras_model.compile(optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
return model
# In[6]:
# target_encoder = TargetEncoder()
scaler = StandardScaler()
keras_model = KerasClassifier(define_model, batch_size=5, epochs=20)
# In[7]:
pipeline = Pipeline([
# ('encoding', target_encoder),
('scaling', scaler),
('modeling', keras_model)
])
# In[8]:
pipeline.fit(train_x, train_y)
# In[9]:
mlflow.keras.save_model(pipeline, "modelstorage/model42") #not working
# In[10]:
import mlflow.sklearn
mlflow.sklearn.save_model(pipeline, "modelstorage/model43")
Output from modelstorage/model43/conda.yaml:
======================
channels:
- defaults
dependencies:
- python=3.6.7
- scikit-learn=0.21.2
- pip:
- mlflow
- cloudpickle==1.2.1
name: mlflow-env
======================
Doesn't seem to capture Tensorflow.