Customer Churn Classification
Customer Churn Classification
Build a complete supervised-learning flow on the canvas: split the data, train a classifier, score the held-out test set, and read the metrics — then export a runnable scikit-learn script. Every model is logged to MLflow automatically.
ML nodes appear under Machine Learning in the palette by default — see the ML Quick Start for setup details.
You'll use: File Input → Train / Test Split → Train Classifier → Predict → Evaluate → File Output.
Sample data
Save this as customers.csv and upload it on the Datasets page
(📥 download customers.csv):
customer_id,tenure,monthly_charges,support_calls,churn
1,2,79.9,4,1
2,34,55.1,0,0
3,5,99.0,3,1
4,48,42.3,1,0
5,9,88.5,5,1
6,60,38.0,0,0
7,3,72.4,2,1
8,41,49.9,1,0
9,4,85.0,3,1
10,55,40.5,0,0
11,7,91.2,4,1
12,38,47.8,1,0
13,6,77.5,2,1
14,50,44.0,0,0
15,2,95.0,5,1
16,45,39.9,0,0
Why 16 rows
Training needs at least 10 rows once the test split is set aside — a smaller
sample fails with need at least 10 rows to train. 16 rows leaves a
comfortable margin above that floor with test_size: 0.25.
The target column is churn (1 = the customer left). The remaining columns are
features.
Build the flow
- File Input — File type CSV, select the
customers.csvdataset. - Train / Test Split —
test_size: 0.25,stratify_column: "churn",seed: 42. This node has two outputs:trainandtest. - Train Classifier — wire the
trainoutput here. Pick Random Forest, settarget_column: "churn", leave features empty (uses all columns except the target), set the requiredseed: 42. The node emits a purplemodelwire.- Optional: open Advanced options for the full hyperparameter set, in-pipeline preprocessing, and the MLflow experiment name. Use Classifier Model plus Cross-Validate if you want fold scores without training a final model first.
- Predict — wire the
testsplit as the data input and themodelwire from the train node. It adds apredictioncolumn. - Evaluate —
task_type: classification,target_column: "churn",prediction_column: "prediction". It returns a tidymetric/valuetable. - File Output — write the metrics table as
metrics.csv.
Use the live preview at each step, then Run the flow. Open the Models page to see the run logged in MLflow with its metrics and lineage.
What Evaluate produces
With test_size: 0.25 on 16 rows, the held-out test set is 4 rows. This
toy dataset separates cleanly on tenure/charges/support calls alone, so the
model gets all four right:
| customer_id | churn | prediction |
|---|---|---|
| 8 | 0 | 0 |
| 3 | 1 | 1 |
| 14 | 0 | 0 |
| 13 | 1 | 1 |
| metric | value |
|---|---|
| accuracy | 1 |
| precision | 1 |
| recall | 1 |
| f1 | 1 |
Exported Python
Click Export → Python. The split and training steps generate a faithful
scikit-learn script (this is the real codegen pattern — preprocessing is bundled
into the Pipeline so it's reapplied identically at predict time):
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import RandomForestClassifier
from sklearn.impute import SimpleImputer
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
df_customers = pd.read_csv('customers.csv')
df_1, df_2 = train_test_split(df_customers, test_size=0.25, random_state=42, stratify=df_customers['churn'])
df_1 = df_1.reset_index(drop=True)
df_2 = df_2.reset_index(drop=True)
_features = [c for c in df_1.columns if c != 'churn']
_X = df_1[_features]
_numeric = [c for c in _features if pd.api.types.is_numeric_dtype(_X[c])]
_categorical = [c for c in _features if c not in _numeric]
_transformers = []
if _numeric:
_transformers.append(('num', Pipeline([('impute', SimpleImputer(strategy='median')), ('scale', StandardScaler())]), _numeric))
if _categorical:
_transformers.append(('cat', Pipeline([('impute', SimpleImputer(strategy='most_frequent')), ('encode', OneHotEncoder(handle_unknown='ignore'))]), _categorical))
_preprocessor = ColumnTransformer(_transformers, remainder='drop')
_y = df_1['churn']
df_3 = Pipeline([('preprocessor', _preprocessor), ('model', RandomForestClassifier(random_state=42))])
df_3.fit(_X, _y)
Variables follow Ciaren's generated naming (the input frame is named after your
dataset, node outputs get df_1, df_2, …, and _-prefixed locals hold
intermediates) rather than hand-picked names — export the flow yourself to see
it verbatim. The Predict and Evaluate nodes continue the script — scoring
df_2 (the test split) and computing the metric table — so the whole flow runs
anywhere scikit-learn is installed, with no Ciaren dependency.
Variations
- Different model? Swap Random Forest for Logistic Regression, XGBoost, LightGBM, SVM, or KNN in the Train Classifier node — the rest of the flow is unchanged.
- Regression instead? Use Train Regressor with a numeric target and an
Evaluate node set to
task_type: regression(RMSE, MAE, R²). - Which features matter? Add a Feature Importance node off the
modelwire (tree-based and linear models). - Retrain on a schedule? Attach a schedule to retrain periodically as new data arrives.
Next steps
- Feature Engineering — scale, encode, and reduce features
- ML Nodes Reference
- ML Quick Start