Fundamentals of Machine Learning
Using Google Colab and Python Libraries to Run ML Models
Find all the jupiter notebooks and datasets here: https://github.com/yash-nigam/AI-ML-Foundations
Table of Contents
- What is Artificial Intelligence?
- What is Machine Learning?
- How Python Helps Implement Machine Learning
- Exploratory Data Analysis: Investigating the Dataset
- Working with the Loan Prediction Dataset
- Encoding
- Train/Test Split
-
Machine Learning Models
- 8.1 Confusion Matrix
- Gradio: Turning a Model into an Application
- What "Learning" Actually Means
- The Real ML Skill — Questions to Be Able to Answer
1. What is Artificial Intelligence?
Artificial Intelligence (AI) is the broad idea of building systems that can perform tasks that normally require some form of human intelligence, such as:
- Recognizing an image
- Generating text / writing an email
- Generating an image
- Recommending a movie
- Detecting fraud
- Predicting the price/value of something
A useful mental model for the hierarchy:
2. What is Machine Learning?
Machine learning is teaching a computer to find patterns in examples, instead of telling it exact rules to follow.
Example: The old way to predict if a customer will cancel their telecom subscription — you could try writing rules by hand:
IF contract = month-to-month
AND monthly charges = high
AND tenure = low
THEN churn = yes
The machine learning way: show the ML algorithm many past customers along with what actually happened to them:
| Customer | Contract type | Monthly charges | Tenure | Did they churn? |
|---|---|---|---|---|
| A | Month-to-month | High | Low | Yes |
| B | Two year | Low | High | No |
| C | Month-to-month | Low | High | No |
| D | Month-to-month | High | Low | Yes |
The algorithm studies this data and figures out the pattern on its own — no one told it "low tenure + high charges = risky."
Using it to predict for a new customer
Once trained, you can hand it a brand-new customer it has never seen:
New customer's info
↓
Trained model
↓
Predicted: churn or not
2.1 Types of Machine Learning
| Supervised Learning | Unsupervised Learning | Reinforcement Learning | |
|---|---|---|---|
| Core idea | Learn from examples with known answers | Find hidden patterns with no answers given | Learn by trial and error, guided by rewards |
| Data needed | Inputs + labels | Inputs only, no labels | No fixed dataset — agent generates its own data |
| Task types | Classification, Regression | Clustering, dimensionality reduction, anomaly detection | Choosing actions to maximize long-term reward |
| Common algorithms | Logistic Regression, Decision Trees, Random Forest | K-Means, DBSCAN, PCA | Q-Learning, DQN, Policy Gradient |
| How it's evaluated | Accuracy, precision, recall, MAE, RMSE | No ground truth — silhouette score, human judgment | Total reward earned |
| Real-world examples | Churn prediction, spam filtering, price estimation | Customer segmentation, topic discovery | Game-playing agents, robotics, ad bidding |
2.2 Supervised Learning
Supervised learning is the case where you already know the right answers for your training data.
The model makes a guess, checks it against the known answer, sees how wrong it was, and adjusts. Repeat this thousands of times and it gets good at guessing.
Input (X) → Known answer (Y)
X is everything you know about a customer. Y is what actually happened to them.
X = [tenure=2, contract=month-to-month, charges=95.5] → Y = churned
X = [tenure=48, contract=two-year, charges=45.2] → Y = stayed
The model's job is to learn the relationship between X and Y well enough that when a new X shows up with no Y attached, it can produce a sensible guess.
The key requirement: you need historical data where the outcome is already recorded. No answer key, no supervised learning.
The only question that splits supervised learning in two
Is the thing I'm predicting a category, or a number?
That's it. That single question decides whether you're doing classification or regression — and it changes your algorithms, your metrics, and how you evaluate success.
| Classification | Regression | |
|---|---|---|
| Question it answers | Which category? | How much? |
| Type of answer | A fixed label (bucket) | A number on a scale |
| Examples | Spam or Not spam Churn or No churn Cat / Dog / Horse |
House price: ₹87,45,000 Temperature: 31.4°C Fuel efficiency: 23.7 MPG |
| What the output means | A label, not a quantity — 1 isn't "more" than 0
|
A real quantity — 6,000 truly is twice 3,000 |
| Model output | A probability → converted to a label e.g. 0.91 → "Churn"
|
A direct number e.g. 6,500
|
| Threshold involved? | Yes — usually 0.5, adjustable | No |
| Being "wrong" | Binary — right label or wrong label | A matter of degree — off by a little or a lot |
| Common metrics | Accuracy, Precision, Recall | MAE, RMSE, R² |
| Common algorithms | Logistic Regression, SVC, Decision Tree Classifier | Linear Regression, KNN Regressor, SVR, Random Forest Regressor |
| In your project | Telco churn (Yes/No) | Customer Lifetime Value (a number) |
Quick test for your own problems — when you get a new dataset, look at the target column and ask:
Does averaging two values in this column produce something meaningful?
Average of ₹5,000 and ₹7,000 = ₹6,000 ✓ meaningful → regression
Average of "spam" and "not spam" ✗ meaningless → classification
2.3 Unsupervised Learning
In unsupervised learning, we do not have a known target. Instead, the algorithm tries to discover structure in the data.
Customer data
↓
Find groups
↓
Group 1: high-value customers
Group 2: price-sensitive customers
Group 3: new customers
Common examples:
- K-Means clustering
- Hierarchical clustering
- PCA
2.4 Reinforcement Learning
Reinforcement learning is different. An agent interacts with an environment and receives rewards or penalties.
Agent
↓ action
Environment
↓
Reward / penalty
↓
Agent learns
Examples:
- Game-playing agents
- Robotics
- Certain recommendation/control systems
This was not part of the five-day practical work.
3. How Python Helps Implement Machine Learning
Machine learning is mostly mathematics — matrix operations, optimization, statistics. In principle you could write all of it yourself, but in practice nobody does. Python has become the default language for ML because a small set of mature libraries already implement those pieces, tested and optimized, so you can focus on the problem rather than the arithmetic.
What makes Python work well here is that these libraries fit together as a pipeline, not as isolated tools. Each one covers one stage of the journey, and they hand data to each other in a common format — a Pandas DataFrame or a NumPy array — so nothing needs translating in between.
A typical project moves through the stack like this:
Load and clean the data → Pandas (with NumPy underneath)
Explore and visualize it → Matplotlib + Seaborn
Prepare features and split → Scikit-learn
Train and predict → Scikit-learn
Evaluate the results → Scikit-learn (+ Seaborn to plot them)
Notice that roughly the first half of that pipeline has nothing to do with modeling at all. In real projects, loading, cleaning, and understanding the data usually takes far more time than calling .fit(). The libraries reflect that reality: Pandas and Seaborn get used constantly, while the actual model training is often two lines.
The other thing Python gives you is a consistent interface. Once you learn scikit-learn's fit → predict pattern, it works the same way for logistic regression, random forests, and support vector machines alike. Swapping one algorithm for another is a one-line change, which makes it cheap to try several and compare.
3.1 The Libraries and What Each One Handles
| Library | Import | Role in the Pipeline | Key Functions/Methods | Notes |
|---|---|---|---|---|
| NumPy | import numpy as np |
The numerical foundation — fast array math that every other library is built on |
np.nan, np.log1p(), np.expm1()
|
np.nan = missing value. log1p(x) = log(1+x), useful for skewed targets. expm1(x) reverses it — used to convert log predictions back to the original CLV scale. You rarely use NumPy directly; it works underneath Pandas and scikit-learn |
| Pandas | import pandas as pd |
Load and clean the data — a spreadsheet Python can manipulate |
read_csv(), column selection/removal, dtype conversion, missing-value detection/fill, X/Y selection, encoding, saving predictions |
Where most of your time actually goes. Example: df = pd.read_csv("Telco_Customer_Churn.csv")
|
| Matplotlib | import matplotlib.pyplot as plt |
The plotting engine — controls figures, titles, axes, display |
plt.figure(), plt.title(), plt.show()
|
Rarely used alone; it's the layer Seaborn sits on top of |
| Seaborn | import seaborn as sns |
Explore and understand the data through statistical plots |
countplot, boxplot, histplot, pairplot, scatterplot, heatmap
|
One line gives you a plot that would take many in raw Matplotlib. A graph is a tool for asking questions about the data, not decoration |
| Scikit-learn | from sklearn... import ... |
Everything modeling-related: splitting, preprocessing, scaling, encoding, training, prediction, evaluation |
train_test_split(), StandardScaler(), model.fit(X_train, Y_train), model.predict(X_test), metrics functions |
The fit → predict pattern is identical across nearly every model, so trying a different algorithm is a one-line change |
The short version: Pandas gets the data into shape, Seaborn helps you understand it, and scikit-learn learns from it — with NumPy doing the arithmetic underneath and Matplotlib drawing the pictures.
4. Exploratory Data Analysis: Investigating the Dataset
| Command | What It Does & How to Use It |
|---|---|
df.head() |
Shows the first few rows of the dataset. Run this right after loading data to confirm it loaded correctly and get a quick look at the columns and values. |
df.shape |
Returns the number of rows and columns, e.g. (398, 9). Use it to quickly gauge dataset size, which affects model choice and computation time. |
df.info() |
Lists each column's data type and non-null count. Use it to spot missing values and type problems — e.g. a numeric column showing as object usually means it contains hidden text like "?". |
df.describe() / df.describe(include="all")
|
Shows summary statistics (count, mean, min, max, etc.) for numeric columns, or all columns with include="all". Use it to check the scale of each variable and spot possible outliers. |
df.sample(n) |
Shows n random rows instead of just the first few. Use it after head() to catch inconsistencies or unusual values that only appear later in the data. |
df.isnull().sum() |
Counts missing (NaN) values per column. Use it to identify which columns need cleaning — note it only catches true NaNs, not disguised placeholders like "?", which need to be checked separately. |
5. Working with the Loan Prediction Dataset
5.1 Making the Dataset Ready for ML Models
Raw data collected from forms, surveys, or real-world systems is almost never ready to feed straight into a machine learning model.
ML models cannot by themselves guess around these problems, and these gaps could reduce the accuracy of your results.
5.2 What Should Be Cleaned Up
-
NaN(missing values) — ML models cannot handle these by themselves; they'll throw errors or silently produce garbage results. - Unique-identifier columns — Unique IDs create noise and aren't helpful for learning genuine patterns in the data.
- Text/categorical values — Numbers are expected by most ML models, not strings like "Yes"/"No".
- Imbalanced or skewed data — If 70% of your data is one outcome, a lazy model can get 70% accuracy by always predicting that outcome, without actually learning anything useful.
- Outliers and skewed numeric columns — A few extreme values can pull the mean far from what's "typical," making mean-based decisions misleading.
5.3 Cleanup Steps
5.3.1 Remove Unique/Identifier Columns
Columns like IDs (e.g. Loan_ID) don't carry predictive signal and should be dropped.
df = df.drop("Loan_ID", axis=1)
Removes the Loan_ID column. It's a unique identifier for each row (like a primary key) — it has no predictive value and would only confuse or overfit a model if left in.
5.3.2 Handle Missing Values
Either drop rows/columns with too many nulls, or fill them in:
- Use median for numeric columns that are skewed (robust to outliers, e.g. income, loan amount).
- Use mean for numeric columns that are roughly symmetric/normally distributed.
- Use mode (most frequent value) for categorical columns, since averaging text categories isn't meaningful.
Using Median
median_loanamount = df["LoanAmount"].median()
Calculates the median of LoanAmount. Median is preferred over mean here because loan/income data is typically skewed by a few very high values, and median is more robust to outliers.
median_loanamount_term = df["Loan_Amount_Term"].median()
Same logic — computes the median loan term to use for filling its missing values later.
median_credit_history = df["Credit_History"].median()
Computes the median of Credit_History (a 0/1 flag). Even though it's binary, median is used instead of mean to avoid producing a non-integer/ambiguous fill value.
Use the calculated values to fill:
df["LoanAmount"] = df["LoanAmount"].replace(np.nan, median_loanamount)
df["Loan_Amount_Term"] = df["Loan_Amount_Term"].replace(np.nan, median_loanamount_term)
df["Credit_History"] = df["Credit_History"].replace(np.nan, median_credit_history)
Fills missing values with the calculated medians. This avoids dropping rows (losing data) while keeping the columns usable for modeling, since most ML algorithms can't handle NaN.
Using Mode
Calculates the mode (most frequent value) for gender, married, dependents, and self_employed. Mode is used instead of median/mean because these are categorical columns — you can't average "Male" and "Female".
mode_gender = df["Gender"].mode()[0]
mode_married = df["Married"].mode()[0]
mode_dependents = df["Dependents"].mode()[0]
mode_self_employed = df["Self_Employed"].mode()[0]
Replace the missing entries with the most common category, which is a reasonable, low-bias guess for a categorical field:
df["Gender"] = df["Gender"].replace(np.nan, mode_gender)
df["Married"] = df["Married"].replace(np.nan, mode_married)
df["Dependents"] = df["Dependents"].replace(np.nan, mode_dependents)
df["Self_Employed"] = df["Self_Employed"].replace(np.nan, mode_self_employed)
5.3.3 Standardize & Encode Categorical Values
- Standardize categorical values — fix inconsistent labels (e.g. "male", "Male", "MALE" should all become one consistent value).
- Encode categorical variables — convert text categories into numbers using techniques like Label Encoding or One-Hot Encoding, since most ML models only accept numeric input.
LabelEncoder() # + loop over cat_cols
Converts all text/categorical columns (Loan_Status, Married, Gender, etc.) into numeric codes (e.g., "Yes"/"No" → 1/0). This step is required because scikit-learn models only accept numeric input, not strings.
5.3.4 Outliers, Duplicates, Imbalance, Scaling, Split
-
Check and handle outliers — identify extreme values (via boxplots,
.describe(), or z-scores) and decide whether to cap, remove, or transform them. - Check for and remove duplicate rows — duplicate records can bias the model toward those repeated patterns.
- Address class imbalance — if one outcome dominates the target column, apply techniques like upsampling, downsampling, or SMOTE so the model doesn't just learn to predict the majority class.
- Feature scaling (when needed) — normalize or standardize numeric ranges for models sensitive to scale (like SVM, KNN, or Logistic Regression with regularization).
- Split before further transformation — separate train/test sets early so cleaning decisions (like fill values from training data) don't leak information from the test set.
5.3.5 Replace Non-Standard Placeholder Values
df["horsepower"] = df["horsepower"].replace("?", np.nan)
This converts the placeholder "?" into a real missing value.
df["horsepower"] = pd.to_numeric(df["horsepower"])
This then converts the column into a proper numeric type so it can be used in calculations and models.
6. Encoding
6.1 Why Does ML Need Encoding?
Many ML algorithms work with numbers. But real-world data contains categories like:
Male
Female
Yes
No
Month-to-month
One year
Two year
Fiber optic
DSL
No
The model needs these values represented numerically. This is called encoding.
6.2 Label Encoding
from sklearn.preprocessing import LabelEncoder
For a binary column:
No → 0
Yes → 1
This can be reasonable for a binary variable. For example:
Churn:
No → 0
Yes → 1
That makes intuitive sense.
7. Train/Test Split
Repeatedly used:
train_test_split(X, Y, test_size=0.3)
This is one of the most important ML concepts.
Suppose we have 1,000 examples. We might use:
700 → training
300 → testing
The training set is used to learn the model. The test set is held back to evaluate how the trained model performs on unseen data.
Think of it like an exam:
Training data = practice questions
Test data = unseen exam questions
7.1 Why Not Train and Test on the Same Data?
Because the model could simply memorize the training examples. Suppose:
Training score = 99%
Test score = 65%
That is a warning sign. The model learned the training data extremely well but does not generalize well. This is called:
Overfitting
7.2 Underfitting
The opposite can happen. If the model is too simple:
Training score = 60%
Test score = 58%
It may not have learned enough from the data. This is:
Underfitting
A useful mental picture:
Underfitting
Model too simple
↓
misses important patterns
Good fit
Learns useful patterns
↓
works on unseen data
Overfitting
Model learns noise/details
↓
great training performance
poor unseen performance
7.3 Why random_state Matters
In one Telco notebook:
train_test_split(X, Y, test_size=0.3)
In the improved notebook:
train_test_split(X, Y, test_size=0.3, random_state=42)
A random state makes the split reproducible. Without it, the random split can change between runs — meaning your score may change between runs too. With random_state=42, you can reproduce the same split every time. The number 42 is not magical; any fixed integer can serve this purpose.
8. Machine Learning Models
| Model / Concept | What It Does & How to Use It |
|---|---|
| Logistic Regression | Despite the name, used for classification — estimates the probability of belonging to a class, then applies a threshold to assign a label. A simple, fast, interpretable baseline model — good starting point before trying complex models. |
| SVC (Support Vector Machine) | Finds a decision boundary that best separates classes, aiming for maximum margin between them. Sensitive to feature scale, so scale your data (e.g. with StandardScaler) before using it. |
| Decision Tree | Predicts by asking a sequence of yes/no questions, ending at a leaf with the prediction. Easy to visualize but prone to overfitting — control this with max_depth, min_samples_split, min_samples_leaf. |
| Random Forest | Combines many decision trees and averages their predictions for a more robust result. An ensemble method — generally more reliable than a single decision tree. |
| Bagging | Trains multiple models on different random samples of the data, then combines their predictions. Reduces variance and makes predictions more stable; Random Forest is a specialized version of this. |
| AdaBoost | Builds models sequentially, where each new model focuses on the mistakes of the previous one. A boosting method — improves weak learners step by step rather than averaging independent ones. |
| KNN (K-Nearest Neighbors) | Predicts by finding the most similar existing examples ("neighbors") and using their values. Relies on distance, so it needs feature scaling to avoid large-scale features dominating the result. |
| StandardScaler | Scales features to comparable ranges before training distance-sensitive models. Always fit_transform on training data, then only transform (not fit) on test data, to avoid data leakage. |
| Linear Regression | Models the relationship between features and a numeric target as a straight-line equation (Y = b0 + b1X1 + ...). Used for predicting continuous values, e.g. Customer Lifetime Value. |
R² Score (.score()) |
Measures how well the model explains variation in the target — 1 is perfect, 0 means no better than predicting the average. Report it as "R² of 0.90," not "90% accuracy" — they're not the same thing. |
| Accuracy Score | The proportion of correct predictions out of all predictions made, used for classification. Easy to understand, but misleading when classes are imbalanced (e.g. 95% "no churn" data). |
8.1 Confusion Matrix
A confusion matrix organizes classification predictions.
Actual
No Yes
Predicted No TN FN
Predicted Yes FP TP
Meaning:
- True Positive — model predicted positive and it was positive.
- True Negative — model predicted negative and it was negative.
- False Positive — model predicted positive but it was negative.
- False Negative — model predicted negative but it was positive.
This is much more informative than accuracy alone when the cost of errors differs.
9. Gradio: Turning a Model into an Application
import gradio as gr
Building a UI around your model is an important step because it changes the project from:
Notebook experiment
to:
User input
↓
Preprocessing
↓
Model
↓
Prediction
↓
Human-readable result
For example:
Gender: Female
Tenure: 12 months
Contract: Month-to-month
Monthly charges: $70
...
↓
Predict Churn
↓
High Churn Risk
Probability: ...
This demonstrates an important ML engineering concept:
A model is useful only when it can be integrated into a workflow where people or systems can use its predictions.
10. What "Learning" Actually Means
When you run:
model.fit(X_train, y_train)
the model is not magically understanding the world. It is optimizing internal parameters so that its predictions match the training examples according to the algorithm's objective.
For example, linear regression learns coefficients. A tree learns split rules. A neural network learns weights.
So:
Training means finding model parameters that make the model perform well according to a defined objective.
10.1 What Happens During Prediction?
Once training is complete:
prediction = model.predict(X_test)
the model does not learn again from the test examples. It applies what it learned during training.
Conceptually:
Training:
X_train + y_train
↓
model.fit()
↓
learned model
Prediction:
X_test
↓
learned model
↓
prediction
11. The Real ML Skill — Questions to Be Able to Answer
- What problem are you solving?
- What is the target?
- What features are available?
- What does the data look like?
- What problems did you find?
- How did you clean them?
- How did you encode the data?
- Why did you choose the algorithm?
- How did you evaluate it?
- Does it generalize?
- What would you improve?
- Why was a specific algorithm chosen?


Top comments (0)