Skip to content
Codeloom
Machine Learning

What Is Machine Learning? A Developer's Introduction

A clear introduction to machine learning for developers — supervised vs unsupervised, features and labels, train/test split, when ML beats rules, and a tiny scikit-learn example.

·9 min read · By Codeloom
Beginner 12 min read

What you'll learn

  • What machine learning is, and what it isn't
  • The difference between supervised and unsupervised learning
  • Features, labels, and the train/test split
  • When ML genuinely beats hand-written rules, and when it doesn't
  • A small scikit-learn classification snippet you can read end to end

Prerequisites

Machine learning is the part of AI that gets the most weather. It also has the most jargon. This post is a developer’s introduction — what ML actually is, the handful of concepts that explain most of it, and a small scikit-learn snippet that ties them together.

No advanced maths required. If you’ve written a Python function, you can follow along.

What machine learning actually is

Traditional software:

You write the rules. The computer applies them to data and produces answers.

Machine learning:

You give the computer data and answers. It produces the rules.

A spam filter is the canonical example. If you tried to write spam detection by hand, you’d start with rules (“contains ‘free iPhone’”, “from a suspicious domain”) and quickly find your list growing forever. Instead, you can give a learning algorithm thousands of emails labelled “spam” or “not spam,” and let it figure out the rule itself. The result is a model — a function that takes a new email and predicts a label.

The model isn’t magic. Under the hood it’s a mathematical function with tunable numbers (parameters). Training adjusts those numbers so the model’s predictions match the answers on your training data. Prediction runs the function on new inputs.

Features and labels

Two pieces of vocabulary you can’t avoid:

  • Features — the input columns. The things you know about each example. For an email: word counts, sender, time of day.
  • Label — the output column. The thing you want to predict. For an email: spam or not.

In code (and in pandas), the convention is X for the features (capital, because it’s typically a 2D matrix) and y for the labels (lowercase, a 1D vector).

# Conceptual shape
X = [
    [0.3, 5, 1],   # email 1: feature1, feature2, feature3
    [0.9, 2, 0],   # email 2
    [0.1, 8, 1],   # email 3
]
y = [1, 0, 0]      # 1 = spam, 0 = not spam

Choosing and engineering features is often more important than choosing the algorithm. “Garbage in, garbage out” is universally true in ML.

Supervised vs unsupervised

The two big categories.

Supervised learning

You have labels. The model learns to predict the label from the features.

Two sub-categories:

  • Classification. Predict a category. Spam or not. Cat, dog, or hamster. Fraud or legitimate.
  • Regression. Predict a number. House price. Tomorrow’s temperature. Time to next failure.

Most ML in production is supervised classification or regression.

Unsupervised learning

No labels — just data. The model finds structure in it.

  • Clustering. Group similar items. Customers into segments, articles into topics.
  • Dimensionality reduction. Compress many features into a few while keeping the structure. Useful for visualisation and for feeding into other models.

There’s also reinforcement learning (agents learning by reward), and self-supervised learning (the technique behind LLMs — labels come from the data itself). But supervised is where most projects live.

The train/test split

The cardinal sin in ML is judging a model by how well it does on the data it was trained on. Of course it does well there — it memorised. The real question is how it does on data it has never seen.

The standard discipline:

  1. Hold out a chunk of your data — 20% is a common default.
  2. Train the model on the remaining 80%.
  3. Evaluate on the held-out 20%. The score there estimates real-world performance.
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

random_state=42 (or any number) makes the split reproducible. Use it.

More sophisticated versions — cross-validation, time-aware splits for time series — exist. Start with the simple holdout; graduate when the situation demands.

Overfitting, briefly

A model overfits when it memorises training data instead of learning generalisable patterns. Telltale sign: very high training accuracy, much lower test accuracy.

It happens when:

  • The model has too many parameters relative to the data.
  • The training set is too small.
  • There are spurious patterns the model latches onto.

Antidotes: more data, simpler models, regularisation, dropout (for neural nets). And always look at the test score, never just the training score.

When ML beats rules

A practical rule of thumb. Reach for ML when:

  • The rules are too complex to write by hand and you have labelled examples. (Spam, fraud, image classification.)
  • The patterns shift over time and you can re-train on fresh data. (Recommendations, demand forecasting.)
  • The decision is fuzzy and a probability is more useful than a hard answer. (Risk scoring.)
  • You have lots of data and the cost of being wrong sometimes is acceptable.

When rules beat ML

Reach for hand-written rules when:

  • The logic is clear, stable, and auditable. (Tax calculations, validation.)
  • The cost of an error is high and unverifiable.
  • You don’t have labelled data and can’t get any cheaply.
  • The volume is too low for a model to learn anything useful.

A common mistake on new teams is using ML for a problem two if statements would solve better. ML is not a synonym for “modern.” A boring rule that works and that anyone can read often wins.

A small worked example with scikit-learn

The dataset: the classic Iris flowers, built into scikit-learn. Features are petal and sepal measurements; the label is the species.

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report

# 1. Load data
iris = load_iris()
X, y = iris.data, iris.target
print(X.shape, y.shape)
# output: (150, 4) (150,)

# 2. Train/test split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 3. Pick a model and train it
model = LogisticRegression(max_iter=200)
model.fit(X_train, y_train)

# 4. Predict on the test set
predictions = model.predict(X_test)

# 5. Evaluate
print("Accuracy:", accuracy_score(y_test, predictions))
# output: Accuracy: 1.0   (Iris is famously easy)

print(classification_report(y_test, predictions,
                            target_names=iris.target_names))
# output:
#               precision    recall  f1-score   support
#       setosa       1.00      1.00      1.00        10
#   versicolor       1.00      1.00      1.00        10
#    virginica       1.00      1.00      1.00        10

The five-step rhythm — load, split, train, predict, evaluate — is the same for almost every supervised problem you’ll write. Swap the dataset, swap the model, the structure stays.

Some things worth noting:

  • model.fit(X_train, y_train) is the training step. For a small dataset like Iris it takes a fraction of a second.
  • model.predict(X_test) runs inference on unseen examples.
  • We never showed the test data to the model during training. The accuracy score is honest.
  • stratify=y keeps the class proportions balanced across the split — important when classes are imbalanced.

Try it yourself. Install scikit-learn (pip install scikit-learn) and run the snippet above. Then replace LogisticRegression with RandomForestClassifier or KNeighborsClassifier — both live under sklearn.ensemble and sklearn.neighbors respectively. The API is the same: fit, predict, score. The point of the exercise is to feel how scikit-learn’s uniform interface lets you swap models in one line.

A regression flavour

The same shape, slightly different model.

from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error

data = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.2, random_state=42
)

model = RandomForestRegressor(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
preds = model.predict(X_test)
print("MAE:", mean_absolute_error(y_test, preds))
# output: MAE: 0.33   (in units of $100,000)

Classification uses accuracy/precision/recall. Regression uses error metrics like MAE (mean absolute error) and RMSE. Picking the right metric is part of the modelling job — accuracy is misleading on imbalanced data, for instance.

Where the work actually goes

A pleasant surprise and an unpleasant one.

The pleasant: scikit-learn’s API is wonderfully uniform. Once you can do one classifier, you can do all of them.

The unpleasant: in real projects, the modelling code is 10% of the work. The other 90% is:

  • Getting the data — joining tables, fixing encodings, dealing with timezones.
  • Cleaning — nulls, outliers, duplicate rows, leakage.
  • Feature engineering — turning raw fields into things the model can learn from.
  • Evaluating honestly — the right split, the right metric, the right baseline.
  • Putting it into production — APIs, monitoring, retraining schedules.

Pandas and DataFrame basics are the workhorse tools for the first four. FastAPI is a common choice for the fifth.

ML vs deep learning vs LLMs

Quick map of the terms.

  • Machine learning is the umbrella. Any model that learns from data.
  • Deep learning is ML using deep neural networks. Strong on perception — images, audio, text — and dominant on benchmarks for those modalities.
  • Large language models are a specific deep-learning architecture (transformers) trained on huge text corpora. See What Is an LLM?.

For tabular business problems — the bulk of industry ML — classical models like gradient-boosted trees (XGBoost, LightGBM) still beat deep learning more often than not. Don’t reach for neural networks just because they’re in the news.

Reflection. Pick a decision in your own work — what to charge a customer, which support ticket is urgent, what to recommend next. Ask: do you have historical examples with the outcome you wanted to predict? If yes, that’s a supervised ML candidate. If no — or if the answer would be just as good from three if statements — it isn’t. Most teams overestimate how much of their work is the former.

Recap

You now know:

  • ML produces the rules from data, instead of you writing rules
  • Features are inputs; labels are outputs you want to predict
  • Supervised learning has labels (classification, regression); unsupervised doesn’t (clustering)
  • The train/test split keeps evaluation honest; overfitting is the failure to generalise
  • ML beats rules when the logic is complex and labelled data exists; rules beat ML when the logic is simple, stable, or unverifiable
  • scikit-learn’s uniform API — fit, predict, score — covers most classical ML

Next steps

The natural follow-ups are getting comfortable with the data side (Pandas DataFrames) and the language model side (What Is an LLM?, What Is RAG?). Pick whichever direction matches your current project.

Related: What Is Pandas?, What Is Python?, Prompt Engineering Basics.

Questions or feedback? Email codeloomdevv@gmail.com.