NumPy for Machine Learning
NumPy (Numerical Python) is one of the most important numerical libraries in the Python ML ecosystem. pandas and scikit-learn work closely with NumPy arrays, while frameworks such as TensorFlow and PyTorch use their own tensor objects with similar array-based ideas. Learning NumPy gives you a strong foundation for understanding how numerical data is represented and processed in ML.
NumPy in Simple Words
Think of NumPy as a fast way to store and calculate with many numbers together. In Machine Learning, one row often represents one example and one column represents one feature.
| Student | Study Hours | Attendance % | Previous Marks |
|---|---|---|---|
| A | 2 | 70 | 55 |
| B | 4 | 85 | 72 |
| C | 5 | 90 | 80 |
Rows
Each row is one student (one sample).
Columns
Each numeric column is a feature.
NumPy Array
NumPy can store the numeric part as one 2D array.
Python List vs NumPy Array
| Question | Python List | NumPy Array |
|---|---|---|
| Main use | General Python data | Numerical calculations |
| Element types | Can mix types | Usually one data type |
| Math on all values | Usually needs a loop/comprehension | Vectorised operations |
Fast vectorised ops
Often much faster than Python loops
N-dimensional arrays
Scalars, vectors, matrices, tensors
Linear algebra
dot, matmul, inv, eig
Statistical functions
mean, std, percentile, corrcoef
# Installation (run once in terminal)
pip install numpy
# Import convention — always use 'np' alias
import numpy as np
print(np.__version__) # prints the NumPy version installed on your systemExample: 2.x (your version may differ)1. Creating Arrays
The ndarray is NumPy's core data structure — think of it as a turbo-charged Python list
# From Python list
a = np.array([10, 20, 30, 40, 50])
print(a)
print(type(a))
print(a.dtype) # data type of elements
print(a.shape) # tuple: (5,) means 1D array of 5 elements
print(a.ndim) # number of dimensions[10 20 30 40 50]
<class 'numpy.ndarray'>
int64
(5,)
1See a 2D Array Before Coding It
Here the array has 3 rows and 3 columns, so its shape is (3, 3).
3 rows × 3 columns
It has two axes
9 values in total
# 2D array (matrix) — common in ML for feature matrices
X = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print(X.shape) # (3, 3) → 3 rows, 3 columns (3 samples × 3 features)
print(X.ndim) # 2 dimensions(3, 3)
2# Built-in array creators — essential in ML
np.zeros((3, 4)) # 3×4 matrix of zeros (initialise weights)
np.ones((2, 5)) # 2×5 matrix of ones
np.eye(4) # 4×4 identity matrix
np.arange(0, 10, 2) # [0, 2, 4, 6, 8] — like range()
np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1.0] — evenly spaced
np.random.randn(3, 3) # 3×3 standard normal random values
np.random.randint(1,100, size=(4,)) # 4 random integers 1–99
print(np.arange(0, 10, 2))
print(np.linspace(0, 1, 5))[0 2 4 6 8]
[0. 0.25 0.5 0.75 1. ]2. Indexing & Slicing
Access specific rows, columns, or subsets — critical for train/test splits and feature extraction
a = np.array([10, 20, 30, 40, 50])
# Basic indexing (0-based)
print(a[0]) # 10 — first element
print(a[-1]) # 50 — last element
print(a[1:4]) # [20 30 40] — slice (start:stop, stop excluded)
print(a[::2]) # [10 30 50] — every 2nd element10
50
[20 30 40]
[10 30 50]How 2D Indexing Looks
For X[row, column], choose the row first and then the column.
| Col 0 | Col 1 | Col 2 | |
|---|---|---|---|
| Row 0 | 1 | 2 | 3 |
| Row 1 | 4 | 5 | 6 |
| Row 2 | 7 | 8 | 9 |
X[:, 1] means: all rows, but only column 1 → [2, 5, 8].
# 2D indexing — very common in ML
X = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(X[0]) # First row: [1 2 3]
print(X[:, 1]) # Second column: [2 5 8]
print(X[0:2, 1:3]) # Rows 0-1, Cols 1-2 — submatrix
print(X[-1, -1]) # Last row, last col: 9[1 2 3]
[2 5 8]
[[2 3]
[5 6]]
9# Boolean (conditional) indexing — filter rows meeting a condition
scores = np.array([45, 72, 88, 55, 91, 63])
# Who scored above 70?
mask = scores > 70
print(mask) # [False True True False True False]
print(scores[mask]) # [72 88 91]
# One-liner
print(scores[scores > 70])[False True True False True False]
[72 88 91]
[72 88 91]3. Vectorised Math Operations
Apply numerical operations across arrays without writing a Python loop for each element
Vectorisation: One Instruction, Many Numbers
You write one NumPy operation; NumPy applies it across the array without you writing a Python loop for each value.
a = np.array([1, 2, 3, 4])
# Element-wise arithmetic (no loop needed!)
print(a + 10) # [11 12 13 14]
print(a * 3) # [ 3 6 9 12]
print(a ** 2) # [ 1 4 9 16]
print(np.sqrt(a)) # [1. 1.414 1.732 2.]
# Two arrays
b = np.array([10, 20, 30, 40])
print(a + b) # [11 22 33 44]
print(a * b) # [10 40 90 160][11 12 13 14]
[ 3 6 9 12]
[ 1 4 9 16]
[1. 1.41421356 1.73205081 2. ]
[11 22 33 44]
[ 10 40 90 160]Broadcasting — See the Idea First
NumPy can apply a shorter compatible row of values across several rows automatically.
| 1 | 2 | 3 | − | 2.5 | 3.5 | 4.5 | = | -1.5 | -1.5 | -1.5 |
| 4 | 5 | 6 | − | 2.5 | 3.5 | 4.5 | = | 1.5 | 1.5 | 1.5 |
The row [2.5, 3.5, 4.5] is not literally copied first; NumPy follows broadcasting rules so the operation behaves as if it were aligned with each compatible row.
# Broadcasting — NumPy aligns compatible shapes for arithmetic
# This subtraction pattern is one idea used in feature scaling.
X = np.array([[1, 2, 3],
[4, 5, 6]]) # shape (2, 3)
mean = np.array([2.5, 3.5, 4.5]) # shape (3,) → broadcast across rows
print(X - mean) # subtract mean of each column from every row[[-1.5 -1.5 -1.5]
[ 1.5 1.5 1.5]]4. Statistical Functions
These are the building blocks of data analysis and feature engineering
data = np.array([23, 45, 12, 67, 34, 89, 56, 11, 78, 42])
print(f"Mean: {np.mean(data):.2f}")
print(f"Median: {np.median(data):.2f}")
print(f"Std dev: {np.std(data):.2f}")
print(f"Variance: {np.var(data):.2f}")
print(f"Min: {np.min(data)}, Max: {np.max(data)}")
print(f"25th pct: {np.percentile(data, 25)}")
print(f"75th pct: {np.percentile(data, 75)}")
print(f"Sum: {np.sum(data)}")Mean: 45.70
Median: 43.50
Std dev: 25.46
Variance: 648.41
Min: 11, Max: 89
25th pct: 25.75
75th pct: 64.25
Sum: 457Understanding axis with Student Marks
| Student | Maths | English | Science | Row mean axis=1 |
|---|---|---|---|---|
| 1 | 80 | 75 | 90 | 81.67 |
| 2 | 65 | 88 | 72 | 75.00 |
| 3 | 92 | 60 | 85 | 79.00 |
| Column mean axis=0 | 79.00 | 74.33 | 82.33 |
# Axis-wise stats — critical for working with feature matrices
X = np.array([[80, 75, 90], # Student 1: Maths, English, Science
[65, 88, 72], # Student 2
[92, 60, 85]]) # Student 3
print("Column means (avg per subject):", np.mean(X, axis=0))
print("Row means (avg per student):", np.mean(X, axis=1))
print("Overall max:", np.max(X))Column means (avg per subject): [79. 74.33 82.33]
Row means (avg per student): [81.67 75. 79. ]
Overall max: 925. Reshaping & Stacking
Reshape arrays to fit model input requirements — one of the most-used operations in ML pipelines
Reshape Changes the Arrangement, Not the Number of Values
Shape (12,)
[1 2 3 4 5 6 7 8 9 10 11 12]
Shape (3, 4)
12 values before, 12 values after. A reshape is valid only when the total number of elements is compatible with the requested shape.
a = np.arange(1, 13) # [1 2 3 4 5 6 7 8 9 10 11 12]
print(a.shape) # (12,)
# Reshape to 2D matrix
B = a.reshape(3, 4) # 3 rows × 4 columns
print(B)
print(B.shape) # (3, 4)
# Reshape to 3D tensor (for deep learning)
C = a.reshape(2, 2, 3)
print(C.shape) # (2, 2, 3)
# -1 lets NumPy infer the dimension automatically
D = a.reshape(-1, 3) # infer rows → 4 rows × 3 columns
print(D.shape) # (4, 3)(12,)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
(3, 4)
(2, 2, 3)
(4, 3)# Stacking arrays — used to combine features
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.hstack([a, b])) # [1 2 3 4 5 6] — side by side
print(np.vstack([a, b])) # [[1 2 3] — stacked rows
# [4 5 6]]
# Adding a new column to a feature matrix
X = np.array([[1, 2], [3, 4], [5, 6]]) # 3×2
bias = np.ones((3, 1)) # 3×1 bias column
print(np.hstack([X, bias]))[1 2 3 4 5 6]
[[1 2 3]
[4 5 6]]
[[1. 2. 1.]
[3. 4. 1.]
[5. 6. 1.]]6. Linear Algebra (Essential for ML)
Dot products and matrix operations appear in many important ML algorithms
Dot Product — A Tiny Numerical Example
Suppose a model has two features [2, 3] and two weights [0.5, 1.0].
(2 × 0.5) + (3 × 1.0)1 + 34So the dot product is 4. ML models repeatedly perform calculations like this when combining feature values with learned weights.
# Dot product — at the heart of linear regression and neural networks
# y = X·w (prediction = features dot weights)
X = np.array([[1, 2], [3, 4], [5, 6]]) # 3 samples × 2 features
w = np.array([0.5, 1.5]) # 2 weights
predictions = np.dot(X, w) # or X @ w (Python 3.5+)
print("Predictions:", predictions)
# Matrix multiplication
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print("A @ B =")
print(A @ B)Predictions: [ 3.5 7.5 11.5]
A @ B =
[[19 22]
[43 50]]# Useful linear algebra operations
A = np.array([[2, 1], [5, 3]])
print("Transpose:\n", A.T)
print("Determinant:", np.linalg.det(A))
print("Inverse:\n", np.linalg.inv(A))
# Eigenvalues & eigenvectors (used in PCA)
vals, vecs = np.linalg.eig(A)
print("Eigenvalues:", vals)Transpose:
[[2 5]
[1 3]]
Determinant: 1.0
Inverse:
[[ 3. -1.]
[-5. 2.]]
Eigenvalues: [0.20871215 4.79128785]7. Complete ML Example: Linear Regression with NumPy
Build a small linear regression model from scratch using NumPy to understand the matrix idea behind least squares
import numpy as np
# Dataset: Study hours → Exam score
hours = np.array([1, 2, 3, 4, 5, 6, 7, 8])
scores = np.array([52, 58, 64, 70, 75, 82, 88, 95])
# Linear Regression: score = w * hours + b
# Normal-equation form for learning: w = (XᵀX)⁻¹ Xᵀy
# (Production libraries generally use more numerically stable solvers.)
X = np.column_stack([np.ones(len(hours)), hours]) # add bias column
y = scores
# Solve for weights [b, w]
weights = np.linalg.inv(X.T @ X) @ X.T @ y
b, w = weights
print(f"Intercept (b): {b:.2f}")
print(f"Slope (w): {w:.2f}")
print(f"Equation: score = {w:.2f} × hours + {b:.2f}")
# Predict for 9 hours of study
new_hours = 9
prediction = w * new_hours + b
print(f"\nPrediction for {new_hours} hours: {prediction:.1f}")Intercept (b): 45.68
Slope (w): 6.07
Equation: score = 6.07 × hours + 45.68
Prediction for 9 hours: 100.3Why did the model predict about 100.3 marks?
The model learned approximately score = 6.07 × hours + 45.68. For 9 hours: (6.07 × 9) + 45.68 ≈ 100.3. The model simply extends the straight-line pattern beyond the training range of 1–8 hours; it does not automatically know that an exam may have a maximum of 100 marks. This is called extrapolation. It is a reminder to combine model output with real-world constraints and domain knowledge.
Common NumPy Questions
What is the difference between shape, ndim, and size?
shape tells you the length of each dimension, ndim tells you how many dimensions there are, and size tells you the total number of values.
Why is broadcasting useful in Machine Learning?
It lets NumPy combine compatible arrays without writing explicit loops. A common example is subtracting one mean value per feature from every row during feature scaling.
Does reshape() always copy the data?
Not necessarily. NumPy returns a view when possible, but a copy can be required in some memory layouts. For beginners, the key idea is that reshaping changes how the same values are organised as long as the element count is compatible.
Should I learn all NumPy linear algebra before Machine Learning?
No. Start with arrays, indexing, vectorised operations, statistics, reshaping, and dot products. Learn deeper linear algebra gradually as algorithms such as PCA and Linear Regression require it.
Where to Go Next
🎯 NumPy Cheat Sheet — Essential ML Operations
| Operation | Code | Used in |
|---|---|---|
| Create array | np.array([1,2,3]) | Everything |
| Shape of array | X.shape | Debugging |
| Reshape | X.reshape(n, -1) | Model inputs |
| Column mean | X.mean(axis=0) | Feature scaling |
| Boolean filter | X[X > 0] | Data cleaning |
| Dot product | X @ w or np.dot(X,w) | Linear/Neural nets |
| Transpose | X.T | Matrix math |
| Stack arrays | np.hstack([a,b]) | Combining features |
| Random seed | np.random.seed(42) | Reproducibility |
| Concatenate | np.concatenate([a,b]) | Joining datasets |