Logistic regression vs random forest vs gradient boosting: bar chart with scores of 0.870, 0.830 and 0.840

Logistic Regression vs Random Forest vs Gradient Boosting: When the Simple Model Wins

Logistic regression, random forest, or gradient boosting?

These models have different strengths; none is the automatic winner for every dataset. Logistic regression provides a useful linear baseline, while tree ensembles can represent nonlinear relationships and interactions. Compare them using a metric and validation procedure suited to your problem.

The results below illustrate one dataset and configuration. They do not establish a general ranking or explain why a model won by themselves. Use validation data for model selection and preserve a final test set for the selected workflow.

Check preprocessing requirements, compare the errors that matter, and investigate training–validation gaps before increasing complexity.

Build the habit of honest evaluation. Read the free Starter Kit excerpt on test sets. The complete practical handbook is €19.

It was not. Here are the real results, from code that was actually executed, and what they teach about choosing a model.

The dataset

A customer churn table with four features: tenure, monthly charges, support calls and contract type. Roughly one customer in five has churned. Every model below is trained on the same training set and scored on the same sealed test set.

Step 1: a single decision tree

A tree restricted to two levels of questions already scores 0.810 on the test set. Remove the depth limit and it grows to depth 14, reaches a perfect 1.000 on the training data, and scores exactly the same 0.810 on the test set. Every extra question was memorising the training data, not learning anything new: textbook overfitting.

# OUTPUT
# depth=2     train acc=0.832  test acc=0.810
# unlimited   train acc=1.000  test acc=0.810
# unlimited tree depth reached: 14

Step 2: a random forest

Two hundred trees, each trained on a random sample of rows and features, voting together. Accuracy moves by only two points, but AUC, which measures how well the model ranks churners above loyal customers, jumps from 0.731 to 0.863. Accuracy alone would have hidden most of that improvement.

from sklearn.ensemble import RandomForestClassifier

forest = RandomForestClassifier(n_estimators=200, random_state=0)
forest.fit(X_train, y_train)

# OUTPUT
# single tree (unlimited) test acc : 0.810   AUC : 0.731
# forest (200 trees)      test acc : 0.830   AUC : 0.863
Illustration of the 90-day machine learning roadmap PDF

Stay on track. Get the Roadmap.

Download the 90-Day Roadmap PDF + get weekly tips and resources to help you succeed

Step 3: gradient boosting, against both rivals

from sklearn.ensemble import GradientBoostingClassifier

gb = GradientBoostingClassifier(
    n_estimators=200, learning_rate=0.05, max_depth=3, random_state=0
)
gb.fit(X_train, y_train)
gb.score(X_test, y_test)

# OUTPUT
# logistic regression   test acc=0.870
# random forest         test acc=0.830
# gradient boosting     test acc=0.840

Plain logistic regression beat both tree ensembles. This is not a bug, and it is not unusual. Churn in this dataset is driven by a mostly linear combination of tenure, support calls and contract type, exactly the kind of relationship a linear model handles well. The extra flexibility of trees bought nothing.

Boosting also showed diminishing returns quickly. Its first tree alone reached 78.0% accuracy; by around eighty trees it had essentially arrived at its final score, and the remaining hundred and twenty trees added almost nothing.

The plot twist: a better feature beat a better algorithm

Adding one engineered column, support calls divided by tenure, to the unchanged boosting model moved accuracy from 0.840 to 0.855. That is a larger gain than the gap between several of the algorithms above.

df["calls_per_month_tenure"] = df["support_calls"] / (df["tenure"] + 1)
# refit the SAME boosting model, changing nothing except this one column

# OUTPUT
# without engineered feature : test acc=0.840  AUC=0.886
# with engineered feature    : test acc=0.855  AUC=0.888

How to choose

ModelReach for it when
Logistic regressionThe relationship is roughly linear, or you need a fast, interpretable baseline
Random forestYou want strong performance with minimal tuning and some resistance to overfitting
Gradient boostingYou have time to tune carefully and want to squeeze out the last few points

The rule that matters more than the table: there is no “best” algorithm independent of the data. Always train a simple baseline first, compare honestly on a sealed test set, and check more than one metric. If you are new to the distinction between the model families themselves, start with supervised vs unsupervised learning.

Key takeaways

  • On this churn data: logistic regression 0.870, gradient boosting 0.840, random forest 0.830.
  • An unlimited decision tree hit 1.000 on training data and gained nothing on the test set.
  • AUC revealed an improvement (0.731 to 0.863) that accuracy mostly hid.
  • One good engineered feature moved the needle more than switching algorithms.

Learn this properly, with code that actually ran

These results come from Part 4 of the Machine Learning Starter Kit (Chapters 14 to 17), a 172-page handbook where every listing was executed and every output is the real one. Just starting out? Get the free 90-Day Machine Learning Roadmap first.

Subscribe to our awesome newsletter to get the best content on your journey to learn Machine Learning, including some exclusive free goodies!

HOW IS MACHINE LEARNING