Skip to content

Bug: Exported/saved models are completely inaccurate for inference #1963

Description

@g-rov

Bug Description

Models exported with export_model() and exported models that are saved and loaded are completely inaccurate for inference. This affects StructuredDataRegressor and most probably other models that rely on pipelines.
In my understanding, this is because the export_model() function does not take into account any pre- and post-processors that might be included in the pipeline. Hence, the predictions are off.

Bug Reproduction

Code for reproducing the bug:

import tensorflow as tf
import keras
import numpy as np
import autokeras as ak
    
# Example usage
if __name__ == "__main__":
    max_trials = 10
    epochs = 20
    batch_size = 50

    X = np.random.rand(200,10)
    X[:,:5] = X[:,:5] * [1, 5, 100, 2, 0.1] + [0, 2, 1000, -200, -1]
    # Creating categorical variables to force encoder
    X[:,6] = np.round(X[:,6])
    X[:,7:] = np.round(X[:,7:],1)
    X_train = X[:100]
    X_test = X[100:150]
    X_val = X[150:]

    y = np.random.rand(200,1) * 20 + 50
    y_train = y[:100]
    y_val = y[100:150]
    y_test = y[150:]

    model = ak.StructuredDataRegressor(
        column_names=["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
        column_types={"0": "numerical", "1": "numerical", "2": "numerical", "3": "numerical", "4": "numerical", "5": "categorical", "6": "categorical", "7": "categorical", "8": "categorical", "9": "categorical"},
        output_dim=1,
        loss="mse",
        metrics=[keras.metrics.RootMeanSquaredError()],
        project_name="structured_data_regressor",
        max_trials=max_trials,
        directory='structured_data_regressor',
        objective="val_loss",
        overwrite=False,
        seed=42,
    )
    model.fit(
        X_train,
        y_train,
        validation_data=(X_val, y_val),
        epochs=epochs,
        batch_size=batch_size,
        verbose=2
    )
    best_model = model.export_model()
    best_model.save('best_model.keras')

    # Evaluate AutoModel
    val_loss, val_rmse = model.evaluate(X_test, y_test, batch_size=batch_size, verbose=2)
    print(f"\nValidation Weighted MSE: {val_loss:.6f}")
    print(f"Validation RMSE: {val_rmse:.6f}")

    # Evaluate best model
    model_backup = model
    del model
    model = best_model
    val_loss, val_rmse = model.evaluate(X_test, y_test, batch_size=batch_size, verbose=2)
    print(f"\nValidation Weighted MSE: {val_loss:.6f}")
    print(f"Validation RMSE: {val_rmse:.6f}")

    # Evaluate best reloaded model
    del model
    model = keras.models.load_model('best_model.keras')
    val_loss, val_rmse = model.evaluate(X_test, y_test, batch_size=batch_size, verbose=0)
    print(f"\nValidation Weighted MSE: {val_loss:.6f}")
    print(f"Validation RMSE: {val_rmse:.6f}")

Expected Behavior

The MSE / RMSE reported by the StructuredDataRegressor, the exported model and the reloaded model should match. However, they differ significantly. In the example code above, the difference is consistently ~20%. Depending on the data (number of categorical variables, distribution, etc.) the difference can go up by orders of magnitude.

Setup Details

Include the details about the versions of:

  • OS type and version: Ubuntu 24.04.3 LTS
  • Python: 3.13.9
  • autokeras: 3.0.0
  • keras-tuner: 1.4.8
  • scikit-learn: 1.7.2
  • numpy: 2.3.5
  • pandas: 2.3.3
  • tensorflow: 2.20.0

Additional context

The export_model() function should produce a model that has equal or, at least, equivalent performance with the AutoModel.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions