DEV Community

Cover image for Customer Purchase Prediction with Logistic Regression - A Beginner's End-to-End ML Project
Waleed Shamhan
Waleed Shamhan

Posted on

Customer Purchase Prediction with Logistic Regression - A Beginner's End-to-End ML Project

 When I finished my first machine learning lectures, I wanted a project that used everything I had learned: data loading, preprocessing, train-test split, scaling, training, and evaluation. So I built a small but complete project: predicting whether a customer will purchase a product, based on their age, salary, experience, and gender.

The dataset is tiny (8 customers), which makes it perfect for learning — you can follow every number by hand.

The data

Age Salary Experience Gender Approved
22 500 1 Male No
25 600 2 Female No
28 700 3 Male No
31 800 4 Female Yes
34 900 5 Male Yes
37 1000 6 Female Yes
40 1100 8 Male Yes
43 1200 9 Female Yes

Approved is the target: Yes means the customer bought, No means they didn't. The rest are the features.

Step 1: Load the data and encode the categories

Models work with numbers, so the Gender and Approved columns need encoding: Male = 0, Female = 1, No = 0, Yes = 1.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

data = {
    'Age': [22, 25, 28, 31, 34, 37, 40, 43],
    'Salary': [500, 600, 700, 800, 900, 1000, 1100, 1200],
    'Experience': [1, 2, 3, 4, 5, 6, 8, 9],
    'Gender': ['Male', 'Female', 'Male', 'Female', 'Male', 'Female', 'Male', 'Female'],
    'Approved': ['No', 'No', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes']
}
df = pd.DataFrame(data)
df['Gender'] = df['Gender'].map({'Male': 0, 'Female': 1})
df['Approved'] = df['Approved'].map({'No': 0, 'Yes': 1})
Enter fullscreen mode Exit fullscreen mode

Step 2: Split features and target, then train/test

X = df[['Age', 'Salary', 'Experience', 'Gender']]
y = df['Approved']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
# Train shape: (6, 4) — Test shape: (2, 4)
Enter fullscreen mode Exit fullscreen mode

test_size=0.2 means 20% of the data goes to testing. random_state=42 makes the split reproducible.

Step 3: Scale the features

Age ranges up to 43, Salary up to 1200. Without scaling, the bigger numbers dominate the model. StandardScaler fixes that — and the key rule is: fit only on the training data, then transform both sets.

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)  # never fit_transform on test data!
Enter fullscreen mode Exit fullscreen mode

Step 4: Train and evaluate

Since the target is yes/no, this is a classification problem, and logistic regression is the natural first model:

model = LogisticRegression()
model.fit(X_train, y_train)

y_pred = model.predict(X_test)
print("Actual:   ", list(y_test))   # [0, 1]
print("Predicted:", list(y_pred))   # [0, 1]
print("Accuracy: ", accuracy_score(y_test, y_pred))  # 1.0
Enter fullscreen mode Exit fullscreen mode

The model predicted both test customers correctly: accuracy 1.0.

Step 5: Predict a new customer

Now the fun part — a brand-new customer: age 36, salary 950, 6 years of experience, female. The new data must go through the same scaler (transform, not fit):

new_customer = [[36, 950, 6, 1]]
new_customer_scaled = scaler.transform(new_customer)
prediction = model.predict(new_customer_scaled)
print("Approved" if prediction[0] == 1 else "Not Approved")  # Approved
Enter fullscreen mode Exit fullscreen mode

Result: Approved (Yes) — the model predicts this customer will purchase.

What I learned

  • Preprocessing is half the project. Encoding categories and scaling features matter as much as the model itself.
  • Never fit on test data. Fitting the scaler on test data leaks information and gives fake results.
  • Small data teaches the pipeline. With 8 rows I could trace every step; the same pipeline scales to thousands of rows.
  • Accuracy on 2 test samples is not proof. A 1.0 here is encouraging, not conclusive — real evaluation needs more data and more metrics (precision, recall, confusion matrix).
  • If you are learning ML, build this project yourself and change one thing at a time: try a different random_state, add a feature, or compare logistic regression with a decision tree. That is where the real learning happens.

Top comments (0)