compute-predictions-to-excel-with-automl

piotrek / compute-predictions-to-excel-with-automl

Read a file "/home/piotr/Documents/charges/insurance_historical.xlsx"

Thinking

Determining file selection

I need to figure out the file selection process first. The user has provided an explicit path, and I’ll focus on the code to load and inspect the file. It's important to determine if the file is an Excel document and then convert it into a DataFrame (df). This step is crucial before moving forward with any further analysis or operations on the data.

</>Load insurance data
import pandas as pd

df = pd.read_excel("/home/piotr/Documents/charges/insurance_historical.xlsx")

print(f"Shape: {df.shape}")
columns = df.columns.tolist()
print(f"Columns ({len(columns)}):", columns if len(columns) <= 100 else columns[:100] + ["..."])
df.head()
Shape: (1238, 7)
Columns (7): ['age', 'sex', 'bmi', 'children', 'smoker', 'region', 'charges']
age sex bmi children smoker region charges
0 19 female 27.900 0 yes southwest 16884.92400
1 18 male 33.770 1 no southeast 1725.55230
2 28 male 33.000 3 no southeast 4449.46200
3 33 male 22.705 0 no northwest 21984.47061
4 32 male 28.880 0 no northwest 3866.85520

The workbook has been read into df with 1,238 records and 7 fields. It contains demographic and policy attributes (age, sex, bmi, children, smoker, region) alongside the insurance cost outcome, charges.

Train an AutoML model to predict charges

charges is a continuous target, so this is a regression task. The available predictors contain no identifier-like fields to exclude.

</>Fit AutoML regression
from supervised.automl import AutoML

X = df.drop(columns="charges")
y = df["charges"]

automl = AutoML(
    mode="Explain",
    ml_task="regression",
    results_path="insurance_charges_automl",
    random_state=42,
)

automl.fit(X, y)

report = automl.report_structured()
print(report)

automl.report()
AutoML directory: insurance_charges_automl
The task is regression with evaluation metric rmse
AutoML will use algorithms: ['Baseline', 'Linear', 'Decision Tree', 'Random Forest', 'Xgboost', 'Neural Network']
AutoML is generating and selecting models automatically. Review outputs before important use.
AutoML will ensemble available models
AutoML steps: ['simple_algorithms', 'default_algorithms', 'ensemble']
* Step simple_algorithms will try to check up to 3 models
1_Baseline rmse 11837.203081 trained in 0.44 seconds
/home/piotr/.config/mljar-studio/jlab_server/lib/python3.12/site-packages/sklearn/tree/_classes.py:1351: FutureWarning: Value `"friedman_mse"` for `criterion` is deprecated and will be removed in 1.11. It maps to `"squared_error"` as both were always equivalent. Use `criterion="squared_error"` to remove this warning.
2_DecisionTree rmse 4649.463036 trained in 3.85 seconds
3_Linear rmse 6077.089454 trained in 3.79 seconds
* Step default_algorithms will try to check up to 3 models
4_Default_Xgboost rmse 4917.773106 trained in 45.5 seconds
5_Default_NeuralNetwork rmse 4950.48459 trained in 2.6 seconds
6_Default_RandomForest rmse 4545.946127 trained in 5.45 seconds
* Step ensemble will try to check up to 1 model
Ensemble rmse 4512.614975 trained in 0.19 seconds
AutoML fit time: 68.13 seconds
AutoML best model: Ensemble
# MLJAR AutoML Report

> Models in this report were generated and selected automatically by MLJAR AutoML. Review model behavior, data suitability, and decision impact before important use.

## Leaderboard

| name                    | model_type     | metric_type   |   metric_value |   train_time |
|:------------------------|:---------------|:--------------|---------------:|-------------:|
| 1_Baseline              | Baseline       | rmse          |       11837.2  |         0.74 |
| 2_DecisionTree          | Decision Tree  | rmse          |        4649.46 |         4.29 |
| 3_Linear                | Linear         | rmse          |        6077.09 |         4.39 |
| 4_Default_Xgboost       | Xgboost        | rmse          |        4917.77 |        45.97 |
| 5_Default_NeuralNetwork | Neural Network | rmse          |        4950.48 |         2.96 |
| 6_Default_RandomForest  | Random Forest  | rmse          |        4545.95 |         6.11 |
| Ensemble                | Ensemble       | rmse          |        4512.61 |         0.19 |

## Global Feature Importance (Averaged Across Models)

Method: `mean_rank_across_models`

Models used: `5`, Features: `6`

### Most Influential Features (Top 3 by mean rank)

| Feature   |   Mean Rank |
|:----------|------------:|
| smoker    |         1   |
| bmi       |         2.2 |
| age       |         2.8 |

### Least Influential Features (Bottom 3 by mean rank)

| Feature   |   Mean Rank |
|:----------|------------:|
| children  |           4 |
| region    |           5 |
| sex       |           6 |

AutoML Leaderboard

Models in this report were generated and selected automatically by MLJAR AutoML. Review model behavior, data suitability, and decision impact before important use.

Best model name model_type metric_type metric_value train_time
1_Baseline Baseline rmse 11837.2 0.74
2_DecisionTree Decision Tree rmse 4649.46 4.29
3_Linear Linear rmse 6077.09 4.39
4_Default_Xgboost Xgboost rmse 4917.77 45.97
5_Default_NeuralNetwork Neural Network rmse 4950.48 2.96
6_Default_RandomForest Random Forest rmse 4545.95 6.11
the best Ensemble Ensemble rmse 4512.61 0.19

AutoML Performance

AutoML Performance

AutoML Performance Boxplot

AutoML Performance Boxplot

Features Importance (Original Scale)

features importance across models

Scaled Features Importance (MinMax per Model)

scaled features importance across models

Spearman Correlation of Models

models spearman correlation

Summary of 5_Default_NeuralNetwork

<< Go back

Neural Network

  • n_jobs: -1
  • dense_1_size: 32
  • dense_2_size: 16
  • learning_rate: 0.05
  • explain_level: 2

Validation

  • validation_type: split
  • train_ratio: 0.75
  • shuffle: True

Optimized metric

rmse

Training time

2.6 seconds

Metric details:

Metric Score
MAE 2805.09
MSE 2.45073e+07
RMSE 4950.48
R2 0.824703
MAPE 0.317221

Learning curves

Learning curves

Permutation-based Importance

Permutation-based Importance

True vs Predicted

True vs Predicted

Predicted vs Residuals

Predicted vs Residuals

<< Go back

Summary of 2_DecisionTree

<< Go back

Decision Tree

  • n_jobs: -1
  • criterion: friedman_mse
  • max_depth: 4
  • explain_level: 2

Validation

  • validation_type: split
  • train_ratio: 0.75
  • shuffle: True

Optimized metric

rmse

Training time

3.8 seconds

Metric details:

Metric Score
MAE 2750.64
MSE 2.16175e+07
RMSE 4649.46
R2 0.845374
MAPE 0.348553

Learning curves

Learning curves

Permutation-based Importance

Permutation-based Importance

True vs Predicted

True vs Predicted

Predicted vs Residuals

Predicted vs Residuals

SHAP Importance

SHAP Importance

SHAP Dependence plots

Dependence (Fold 1)

SHAP Dependence from Fold 1

SHAP Decision plots

Top-10 Worst decisions (Fold 1)

SHAP worst decisions from fold 1

Top-10 Best decisions (Fold 1)

SHAP best decisions from fold 1

<< Go back

Summary of 1_Baseline

<< Go back

Baseline Regressor (Baseline)

  • n_jobs: -1
  • explain_level: 2

Validation

  • validation_type: split
  • train_ratio: 0.75
  • shuffle: True

Optimized metric

rmse

Training time

0.4 seconds

Metric details:

Metric Score
MAE 8903.64
MSE 1.40119e+08
RMSE 11837.2
R2 -0.00225088
MAPE 1.60448

Learning curves

Learning curves

True vs Predicted

True vs Predicted

Predicted vs Residuals

Predicted vs Residuals

<< Go back

Summary of Ensemble

<< Go back

Ensemble structure

Model Weight
2_DecisionTree 1
5_Default_NeuralNetwork 1
6_Default_RandomForest 3

Metric details:

Metric Score
MAE 2493.07
MSE 2.03637e+07
RMSE 4512.61
R2 0.854342
MAPE 0.334347

Learning curves

Learning curves

True vs Predicted

True vs Predicted

Predicted vs Residuals

Predicted vs Residuals

<< Go back

Summary of 6_Default_RandomForest

<< Go back

Random Forest

  • n_jobs: -1
  • criterion: squared_error
  • max_features: 0.9
  • min_samples_split: 30
  • max_depth: 4
  • eval_metric_name: rmse
  • explain_level: 2

Validation

  • validation_type: split
  • train_ratio: 0.75
  • shuffle: True

Optimized metric

rmse

Training time

5.4 seconds

Metric details:

Metric Score
MAE 2628.83
MSE 2.06656e+07
RMSE 4545.95
R2 0.852182
MAPE 0.355469

Learning curves

Learning curves

Permutation-based Importance

Permutation-based Importance

True vs Predicted

True vs Predicted

Predicted vs Residuals

Predicted vs Residuals

SHAP Importance

SHAP Importance

SHAP Dependence plots

Dependence (Fold 1)

SHAP Dependence from Fold 1

SHAP Decision plots

Top-10 Worst decisions (Fold 1)

SHAP worst decisions from fold 1

Top-10 Best decisions (Fold 1)

SHAP best decisions from fold 1

<< Go back

Summary of 3_Linear

<< Go back

Linear Regression (Linear)

  • n_jobs: -1
  • explain_level: 2

Validation

  • validation_type: split
  • train_ratio: 0.75
  • shuffle: True

Optimized metric

rmse

Training time

3.8 seconds

Metric details:

Metric Score
MAE 4099.63
MSE 3.6931e+07
RMSE 6077.09
R2 0.735839
MAPE 0.451905

Learning curves

Learning curves

Coefficients

feature Learner_1
smoker 0.797924
age 0.292291
bmi 0.179434
children 0.0538462
intercept -4.27937e-18
sex -0.019646
region -0.0423077

Permutation-based Importance

Permutation-based Importance

True vs Predicted

True vs Predicted

Predicted vs Residuals

Predicted vs Residuals

SHAP Importance

SHAP Importance

SHAP Dependence plots

Dependence (Fold 1)

SHAP Dependence from Fold 1

SHAP Decision plots

Top-10 Worst decisions (Fold 1)

SHAP worst decisions from fold 1

Top-10 Best decisions (Fold 1)

SHAP best decisions from fold 1

<< Go back

Summary of 4_Default_Xgboost

<< Go back

Extreme Gradient Boosting (Xgboost)

  • n_jobs: -1
  • objective: reg:squarederror
  • eta: 0.075
  • max_depth: 6
  • min_child_weight: 1
  • subsample: 1.0
  • colsample_bytree: 1.0
  • eval_metric: rmse
  • explain_level: 2

Validation

  • validation_type: split
  • train_ratio: 0.75
  • shuffle: True

Optimized metric

rmse

Training time

45.5 seconds

Metric details:

Metric Score
MAE 2830.25
MSE 2.41845e+07
RMSE 4917.77
R2 0.827012
MAPE 0.391656

Learning curves

Learning curves

Permutation-based Importance

Permutation-based Importance

True vs Predicted

True vs Predicted

Predicted vs Residuals

Predicted vs Residuals

<< Go back

The AutoML regression model was trained on 1,238 insurance records using all six available predictors. MLJAR selected an ensemble as the best model.

  • Best validation RMSE: 4,512.61
  • Best single model: Random Forest, RMSE 4,545.95
  • Baseline RMSE: 11,837.20

The ensemble reduces prediction error by about 62% relative to the baseline. Its typical error is approximately 4,513 USD per predicted charge, measured by RMSE. The ensemble is therefore the recommended trained model for predicting charges.

explain the model performance in simple terms

The model predicts insurance charges much better than a simple average-based guess.

  • Best model: An ensemble, which combines multiple models.
  • Prediction error (RMSE): about 4,513 USD. In simple terms, a typical prediction can be off by roughly 4,500 USD, with larger mistakes weighted more heavily.
  • Baseline error: about 11,837 USD. This baseline would largely predict a general average charge for everyone.
  • Improvement: the trained ensemble reduced error by about 62% compared with the baseline.

Among individual models, the Random Forest was strongest, with an error of about 4,546 USD. Combining models improved this slightly to 4,513 USD.

This is a useful model for estimating charges, but it should not be treated as exact: actual charges can still differ substantially from predictions, especially for unusual customer situations.

Read a file "/home/piotr/Documents/charges/insurance_new_customers.xlsx"

Thinking

Inspecting file selection

I'm thinking we need to read and inspect only the first load of data. The file selection has to be explicit, which makes sense. It sounds like I need to ensure that the code is written in one block and that the columns are shaped according to the exact header requirements. This seems important for the accuracy of whatever I'm working on, so I'll make sure everything aligns properly!

Load and inspect the new-customer file before generating charge predictions.

</>Load new customer data
new_customers = pd.read_excel("/home/piotr/Documents/charges/insurance_new_customers.xlsx")

print(f"Shape: {new_customers.shape}")
columns = new_customers.columns.tolist()
print(f"Columns ({len(columns)}):", columns if len(columns) <= 100 else columns[:100] + ["..."])
new_customers.head()
Shape: (100, 6)
Columns (6): ['age', 'sex', 'bmi', 'children', 'smoker', 'region']
age sex bmi children smoker region
0 45 female 25.175 2 no northeast
1 36 female 30.020 0 no northwest
2 64 female 26.885 0 yes northwest
3 46 male 25.745 3 no northwest
4 19 male 31.920 0 yes northwest

The file contains 100 new customer records and 6 predictor fields: age, sex, BMI, number of children, smoking status, and region. Its schema matches the historical model’s input features, with no charges column—as expected for records that need predictions.

Use the trained AutoML model to predict charges for the new customers

The new-customer data matches the model’s six training features. Create predictions and display the first rows with predicted charges.

</>Predict charges for customers
predicted_customers = new_customers.copy()
predicted_customers["predicted_charges"] = automl.predict(new_customers)

predicted_customers.head()
age sex bmi children smoker region predicted_charges
0 45 female 25.175 2 no northeast 10079.179694
1 36 female 30.020 0 no northwest 5952.460288
2 64 female 26.885 0 yes northwest 27089.380112
3 46 male 25.745 3 no northwest 9773.703266
4 19 male 31.920 0 yes northwest 34537.330327

Predicted annual charges have been generated for all 100 new customers and added as predicted_charges. The sample spans approximately 5,952 USD to 34,537 USD, reflecting the model’s expected variation by customer characteristics such as age and smoking status.

Save the dataframe to insurance_new_customers_predictions.xlsx

</>Save predictions to Excel
output_path = "/home/piotr/Documents/charges/insurance_new_customers_predictions.xlsx"
predicted_customers.to_excel(output_path, index=False)

print(f"Saved predictions to: {output_path}")
Saved predictions to: /home/piotr/Documents/charges/insurance_new_customers_predictions.xlsx

The exported workbook contains the 100 new-customer records with all six original input fields plus the predicted_charges column. It was saved at:

/home/piotr/Documents/charges/insurance_new_customers_predictions.xlsx

Read a file "/home/piotr/sandbox/datasets-for-start/insurance/insurance.csv"

Thinking

Loading dataset

I need to read a new prompt from a file. It seems the dataset isn’t currently loaded in my context, and the existing DataFrame is different from what I need. I should load the dataset using pandas and inspect it with the read_csv function. That way, I can ensure I've got everything correctly set up for the task at hand. It’s all about making sure I'm working with the right data!

</>Load insurance data
import pandas as pd

df = pd.read_csv("/home/piotr/sandbox/datasets-for-start/insurance/insurance.csv")

print(f"Shape: {df.shape}")
columns = df.columns.tolist()
print(f"Columns ({len(columns)}):", columns if len(columns) <= 100 else columns[:100] + ["..."])
df.head()
Shape: (1338, 7)
Columns (7): ['age', 'sex', 'bmi', 'children', 'smoker', 'region', 'charges']
age sex bmi children smoker region charges
0 19 female 27.900 0 yes southwest 16884.92400
1 18 male 33.770 1 no southeast 1725.55230
2 28 male 33.000 3 no southeast 4449.46200
3 33 male 22.705 0 no northwest 21984.47061
4 32 male 28.880 0 no northwest 3866.85520

The CSV contains 1,338 insurance records and 7 fields: customer demographics and insurance attributes (age, sex, bmi, children, smoker, region) plus the numeric target charges. The sample confirms mixed categorical and numeric data, with charges recorded as decimal values.

the last 100 rows from the latest file, have real charges for new customers data, compare predictions, make visualization

Thinking

Evaluating predictions and comparisons

I need to use the latest data, specifically the last 100 records, and compare them to earlier predictions that might match historical data. My first step should be to validate and build a comparison between the last 100 actual records and predicted customers. Once I've ensured there's a feature match, I can create a scatter chart to visualize the actual versus predicted values. I’ll run the necessary code without making assumptions and confirm the feature alignment for accuracy.Focusing on a single chart

I realize I don’t need an output table; instead, I’m focusing on creating just one chart. This simplification will help in visualizing the data more effectively without unnecessary clutter. By concentrating on a single chart, I can make sure the insights are clear and easy to understand for the user. So, I’ll proceed with that approach to streamline the presentation and enhance the clarity of the information I'm sharing.

This compares the last 100 records’ actual charges with the existing predictions and plots predicted versus actual charges.

</>Plot predicted vs actual charges
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import mean_absolute_error, r2_score

actual_new_customers = df.tail(100).reset_index(drop=True)
comparison = actual_new_customers[["charges"]].copy()
comparison["predicted_charges"] = automl.predict(
    actual_new_customers.drop(columns="charges")
)

mae = mean_absolute_error(comparison["charges"], comparison["predicted_charges"])
r2 = r2_score(comparison["charges"], comparison["predicted_charges"])

plt.figure(figsize=(8, 6))
sns.scatterplot(
    data=comparison,
    x="charges",
    y="predicted_charges",
    s=65,
    alpha=0.75,
)
limits = [
    min(comparison["charges"].min(), comparison["predicted_charges"].min()),
    max(comparison["charges"].max(), comparison["predicted_charges"].max()),
]
plt.plot(limits, limits, linestyle="--", color="black", label="Perfect prediction")
plt.xlim(limits)
plt.ylim(limits)
plt.title(f"Predicted vs Actual Insurance Charges\nMAE: {mae:,.0f} | R²: {r2:.3f}")
plt.xlabel("Actual charges")
plt.ylabel("Predicted charges")
plt.legend()
plt.tight_layout()
plt.show()
Notebook output

The scatter plot compares actual and predicted charges for the 100 latest customer records, with the dashed diagonal representing perfect predictions. Numeric accuracy results are needed to quantify how closely the points follow that line.

</>Show error metrics
print(f"Mean absolute error: {mae:,.2f} USD")
print(f"R²: {r2:.3f}")

comparison["absolute_error"] = (
    comparison["charges"] - comparison["predicted_charges"]
).abs()

comparison[["charges", "predicted_charges", "absolute_error"]].head(10)
Mean absolute error: 2,245.14 USD
R²: 0.907
charges predicted_charges absolute_error
0 6985.50695 8498.409915 1512.902965
1 3238.43570 4983.864203 1745.428503
2 47269.85400 46279.155209 990.698791
3 49577.66240 46113.910277 3463.752123
4 4296.27120 7580.719298 3284.448098
5 3171.61490 5106.751598 1935.136698
6 1135.94070 3347.659030 2211.718330
7 5615.36900 7104.366661 1488.997661
8 9101.79800 9924.701770 822.903770
9 6059.17300 7207.865234 1148.692234

For the last 100 records with known charges, predicted charges align closely with actual charges overall: $R^2 = 0.907$, meaning the model explains about 90.7% of charge variation in this set.

The mean absolute error is 2,245.14 USD, so a prediction differs from the real charge by about 2,245 USD on average. The visualization’s points cluster around the perfect-prediction diagonal, though individual customers can have larger errors—for example, some observed examples differ by roughly 3,300 USD.

Made with MLJAR
Explore more conversationsMore from piotrek