Chapter 1

Introduction to Machine Learning

Learning Objectives

  • Understand what Machine Learning is and why it matters
  • Distinguish between Supervised, Unsupervised, and Reinforcement Learning
  • Identify real-world ML applications across industries
  • Understand the end-to-end ML workflow

What is Machine Learning?

Machine Learning (ML) is a branch of Artificial Intelligence that enables computers to learn patterns from data and make decisions without being explicitly programmed for every scenario. Instead of writing rules by hand, you feed the algorithm data and let it discover the rules itself.

Arthur Samuel (1959) defined ML as the "field of study that gives computers the ability to learn without being explicitly programmed." Tom Mitchell provided a more formal definition:

A computer program is said to learn from experience E with respect to task T and performance measure P, if its performance at T, as measured by P, improves with experience E.

Types of Machine Learning

1. Supervised Learning

The algorithm learns from labeled data — each training example comes with the correct answer (label). The model learns a mapping from inputs to outputs.

  • Classification: Predicting a category — spam vs. not spam, cat vs. dog
  • Regression: Predicting a continuous value — house prices, temperature

2. Unsupervised Learning

The algorithm works with unlabeled data and tries to find hidden patterns or groupings without knowing the correct answers.

  • Clustering: Grouping similar customers together
  • Dimensionality Reduction: Compressing data while keeping important features (PCA)
  • Association: Finding items that frequently co-occur (market basket analysis)

3. Reinforcement Learning

An agent learns by interacting with an environment, receiving rewards for good actions and penalties for bad ones. Used in game AI, robotics, and self-driving cars.

TypeDataGoalExample
SupervisedLabeledPredict outputEmail spam detection
UnsupervisedUnlabeledFind structureCustomer segmentation
ReinforcementRewards/PenaltiesMaximize rewardAlphaGo, robotics

Real-World Applications

Machine Learning powers many products and services you use daily:

  • Healthcare: Disease diagnosis from X-rays, drug discovery, patient risk prediction
  • Finance: Fraud detection, algorithmic trading, credit scoring
  • E-commerce: Product recommendations (Amazon, Netflix), dynamic pricing
  • Transportation: Self-driving cars (Tesla), route optimization (Google Maps)
  • Language: Machine translation (Google Translate), voice assistants (Siri, Alexa)
  • Social Media: Content recommendation, face recognition, sentiment analysis

The ML Workflow

Every ML project follows a standard pipeline:

  1. Define the Problem: What question are you trying to answer?
  2. Collect Data: Gather relevant, high-quality data
  3. Explore & Preprocess: Clean data, handle missing values, visualize patterns
  4. Feature Engineering: Select and transform the most informative features
  5. Train the Model: Choose an algorithm and fit it to the training data
  6. Evaluate: Test the model on unseen data using appropriate metrics
  7. Tune & Optimize: Adjust hyperparameters for better performance
  8. Deploy: Put the model into production and monitor its performance

Setting Up Your Environment

bash
# Install essential ML libraries
pip install numpy pandas matplotlib scikit-learn
pip install tensorflow keras
pip install seaborn jupyter

# Verify installation
python -c "import sklearn; print(sklearn.__version__)"

Exercises

Exercise 1.1: Classify each problem as Supervised, Unsupervised, or Reinforcement Learning

a) Predicting house prices from square footage → Supervised (Regression)

b) Grouping news articles by topic without labels → Unsupervised (Clustering)

c) Teaching a robot to walk → Reinforcement Learning

d) Detecting fraudulent credit card transactions → Supervised (Classification)

e) Reducing image features from 1000 to 50 → Unsupervised (Dimensionality Reduction)

Exercise 1.2: List 3 ML applications in your daily life and identify the type

Example answers:

  • YouTube recommendations → Supervised Learning (predicting what you'll click)
  • Google Photos grouping faces → Unsupervised Learning (clustering)
  • Siri learning your preferences → Reinforcement Learning
Exercise 1.3: Describe the 8 steps of the ML workflow for a movie recommendation system

1. Define: Recommend movies users will enjoy.

2. Collect: User ratings, watch history, movie metadata.

3. Explore: Analyze rating distributions, popular genres, viewing patterns.

4. Feature Engineering: User preferences, genre encoding, watch time features.

5. Train: Collaborative filtering or content-based model.

6. Evaluate: Measure with RMSE, precision@k on held-out data.

7. Tune: Optimize number of factors, learning rate.

8. Deploy: Serve recommendations in real-time via API.

Chapter Summary

  • ML enables computers to learn from data rather than explicit programming
  • Three main types: Supervised, Unsupervised, and Reinforcement Learning
  • ML is used across healthcare, finance, e-commerce, transportation, and more
  • Every ML project follows a systematic workflow from problem definition to deployment
Chapter 2

Python Essentials for Machine Learning

Learning Objectives

  • Master NumPy arrays and operations for numerical computing
  • Use Pandas DataFrames for data manipulation and analysis
  • Create informative visualizations with Matplotlib
  • Understand vectorized operations for efficient computation

NumPy: Numerical Computing Foundation

NumPy is the backbone of scientific computing in Python. It provides high-performance multidimensional arrays and tools for working with them.

Python
import numpy as np

# Creating arrays
a = np.array([1, 2, 3, 4, 5])
matrix = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9]])

# Useful array generators
zeros = np.zeros((3, 4))         # 3x4 matrix of zeros
ones = np.ones((2, 3))           # 2x3 matrix of ones
rng = np.arange(0, 10, 2)       # [0, 2, 4, 6, 8]
lin = np.linspace(0, 1, 5)      # [0, 0.25, 0.5, 0.75, 1.0]
rand = np.random.randn(3, 3)    # 3x3 random normal values

# Array properties
print(matrix.shape)    # (3, 3)
print(matrix.dtype)    # int64
print(matrix.ndim)     # 2

Vectorized Operations

Python
# Element-wise operations (much faster than loops)
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

print(a + b)      # [5, 7, 9]
print(a * b)      # [4, 10, 18]
print(a ** 2)     # [1, 4, 9]
print(np.dot(a, b))  # 32  (dot product)

# Statistical operations
data = np.array([14, 23, 18, 29, 35, 22])
print(np.mean(data))    # 23.5
print(np.std(data))     # 6.99
print(np.median(data))  # 22.5

# Matrix operations
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(A @ B)               # Matrix multiplication
print(np.linalg.inv(A))    # Matrix inverse
print(np.linalg.det(A))    # Determinant: -2.0

Pandas: Data Analysis Powerhouse

Python
import pandas as pd

# Creating a DataFrame
df = pd.DataFrame({
    'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
    'Age': [25, 30, 35, 28],
    'Salary': [50000, 60000, 75000, 55000],
    'Department': ['ML', 'Web', 'ML', 'Data']
})

# Exploring data
print(df.head())          # First 5 rows
print(df.info())          # Column types, non-null counts
print(df.describe())      # Statistical summary

# Selecting & filtering
ml_team = df[df['Department'] == 'ML']
high_salary = df[df['Salary'] > 55000]

# Groupby operations
avg_salary = df.groupby('Department')['Salary'].mean()

# Handling missing data
df.dropna()               # Remove rows with NaN
df.fillna(0)              # Replace NaN with 0
df.fillna(df.mean())      # Replace NaN with column mean

# Reading from CSV
df = pd.read_csv('data.csv')
df.to_csv('output.csv', index=False)

Matplotlib: Data Visualization

Python
import matplotlib.pyplot as plt
import numpy as np

# Line plot
x = np.linspace(0, 10, 100)
plt.figure(figsize=(10, 6))
plt.plot(x, np.sin(x), label='sin(x)', linewidth=2)
plt.plot(x, np.cos(x), label='cos(x)', linewidth=2)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Trigonometric Functions')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

# Scatter plot
np.random.seed(42)
x = np.random.randn(100)
y = 2 * x + np.random.randn(100) * 0.5
plt.scatter(x, y, alpha=0.7, c='#4f46e5')
plt.xlabel('Feature')
plt.ylabel('Target')
plt.title('Linear Relationship with Noise')
plt.show()

# Histogram
data = np.random.normal(100, 15, 1000)
plt.hist(data, bins=30, edgecolor='white', color='#7c3aed')
plt.title('Normal Distribution')
plt.show()

Exercises

Exercise 2.1: Create a NumPy array of 20 random integers between 1-100. Find the mean, max, min, and standard deviation.
import numpy as np
arr = np.random.randint(1, 101, size=20)
print(f"Array: {arr}")
print(f"Mean: {np.mean(arr):.2f}")
print(f"Max: {np.max(arr)}")
print(f"Min: {np.min(arr)}")
print(f"Std: {np.std(arr):.2f}")
Exercise 2.2: Create a Pandas DataFrame of 5 students with Name, Maths, Science, English scores. Add a Total and Percentage column.
import pandas as pd
df = pd.DataFrame({
    'Name': ['Amit', 'Priya', 'Ravi', 'Sneha', 'Karan'],
    'Maths': [85, 92, 78, 95, 88],
    'Science': [90, 88, 82, 91, 76],
    'English': [78, 95, 85, 89, 92]
})
df['Total'] = df[['Maths','Science','English']].sum(axis=1)
df['Percentage'] = (df['Total'] / 300 * 100).round(2)
print(df)
Exercise 2.3: Plot a bar chart showing the average score per subject from Exercise 2.2
subjects = ['Maths', 'Science', 'English']
averages = [df[s].mean() for s in subjects]
plt.bar(subjects, averages, color=['#4f46e5','#10b981','#f59e0b'])
plt.ylabel('Average Score')
plt.title('Average Score by Subject')
plt.ylim(70, 100)
plt.show()

Chapter Summary

  • NumPy provides fast, vectorized array operations essential for ML math
  • Pandas simplifies data loading, cleaning, filtering, and groupby analysis
  • Matplotlib enables line, scatter, bar, and histogram visualizations
  • Vectorized operations are 10-100x faster than Python loops
Chapter 3

Data Preprocessing & Feature Engineering

Learning Objectives

  • Handle missing data with various imputation strategies
  • Encode categorical variables using Label and One-Hot encoding
  • Scale numerical features with StandardScaler and MinMaxScaler
  • Perform feature selection and train-test splitting

Why Preprocessing Matters

Raw data is messy — it contains missing values, inconsistent formats, outliers, and mixed data types. Garbage in = garbage out. Preprocessing transforms raw data into a clean, ML-ready format. Studies show that data scientists spend 60-80% of their time on data preprocessing.

Handling Missing Data

Python
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'Age': [25, np.nan, 35, 28, np.nan],
    'Salary': [50000, 60000, np.nan, 55000, 70000],
    'City': ['Delhi', 'Mumbai', 'Delhi', None, 'Bangalore']
})

# Check missing values
print(df.isnull().sum())

# Strategy 1: Drop rows with any NaN
df_dropped = df.dropna()

# Strategy 2: Fill with mean/median (numerical)
df['Age'].fillna(df['Age'].mean(), inplace=True)
df['Salary'].fillna(df['Salary'].median(), inplace=True)

# Strategy 3: Fill with mode (categorical)
df['City'].fillna(df['City'].mode()[0], inplace=True)

# Strategy 4: Scikit-learn SimpleImputer
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='mean')
df[['Age','Salary']] = imputer.fit_transform(df[['Age','Salary']])

Encoding Categorical Variables

Python
from sklearn.preprocessing import LabelEncoder, OneHotEncoder

# Label Encoding (for ordinal data: low < medium < high)
le = LabelEncoder()
df['City_encoded'] = le.fit_transform(df['City'])
# Delhi=1, Mumbai=2, Bangalore=0

# One-Hot Encoding (for nominal data — no order)
df_encoded = pd.get_dummies(df, columns=['City'], drop_first=True)
# Creates: City_Delhi, City_Mumbai (Bangalore is baseline)

Feature Scaling

Many algorithms (KNN, SVM, Neural Networks, Gradient Descent) are sensitive to the scale of features. A salary feature (50000-100000) would dominate an age feature (20-60) without scaling.

Python
from sklearn.preprocessing import StandardScaler, MinMaxScaler

# StandardScaler: mean=0, std=1 (z-score normalization)
scaler = StandardScaler()
df[['Age_scaled','Salary_scaled']] = scaler.fit_transform(df[['Age','Salary']])

# MinMaxScaler: scales to [0, 1]
mm_scaler = MinMaxScaler()
df[['Age_mm','Salary_mm']] = mm_scaler.fit_transform(df[['Age','Salary']])
StandardScaler: z = (x - μ) / σ     MinMaxScaler: x' = (x - x_min) / (x_max - x_min)

Train-Test Split

Python
from sklearn.model_selection import train_test_split

X = df[['Age', 'Salary']]  # Features
y = df['Target']            # Label

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
print(f"Train: {X_train.shape}, Test: {X_test.shape}")

When to use which scaler?

StandardScaler — when data follows a normal distribution. Best for SVM, Logistic Regression, PCA.

MinMaxScaler — when you need values in a fixed range [0,1]. Best for Neural Networks, KNN.

Mini-Project: Titanic Data Cleaning Pipeline

Python
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

# Load Titanic dataset
df = pd.read_csv('https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv')

# Drop irrelevant columns
df = df.drop(['Name', 'Ticket', 'Cabin', 'PassengerId'], axis=1)

# Fill missing values
df['Age'].fillna(df['Age'].median(), inplace=True)
df['Embarked'].fillna(df['Embarked'].mode()[0], inplace=True)

# Encode categorical variables
df = pd.get_dummies(df, columns=['Sex', 'Embarked'], drop_first=True)

# Split features and target
X = df.drop('Survived', axis=1)
y = df['Survived']

# Scale features
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# Split into train and test
X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, test_size=0.2, random_state=42)

print(f"Training set: {X_train.shape}")
print(f"Test set: {X_test.shape}")
print("Data is clean and ready for modeling!")

Exercises

Exercise 3.1: Given a dataset with 15% missing values in 'Income', when would you drop vs. impute?

Drop when: the dataset is very large AND the missing rows are random (MCAR). Losing 15% of a 1M row dataset still leaves 850k rows.

Impute when: the dataset is small, or the missing data has a pattern (MAR/MNAR). Use median for skewed data, mean for normal distributions.

Exercise 3.2: Encode ['Red', 'Green', 'Blue', 'Red', 'Blue'] using both Label and One-Hot encoding
from sklearn.preprocessing import LabelEncoder
colors = ['Red', 'Green', 'Blue', 'Red', 'Blue']
le = LabelEncoder()
label_encoded = le.fit_transform(colors)
print("Label:", label_encoded)  # [2, 1, 0, 2, 0]

df = pd.DataFrame({'Color': colors})
one_hot = pd.get_dummies(df, columns=['Color'])
print("One-Hot:\n", one_hot)
Exercise 3.3: Why should you fit the scaler ONLY on training data?

If you fit the scaler on the entire dataset (including test data), you introduce data leakage. The scaler would learn the mean/std of the test set, which shouldn't be available during training. This leads to overly optimistic performance estimates. Always: scaler.fit(X_train), then scaler.transform(X_test).

Chapter Summary

  • Handle missing data using dropping, mean/median/mode imputation, or SimpleImputer
  • Use Label Encoding for ordinal categories, One-Hot Encoding for nominal categories
  • Scale features with StandardScaler or MinMaxScaler to normalize ranges
  • Always split data before scaling to prevent data leakage