In the previous article, we used pandas to load a dataset, inspect its rows and columns, find missing values, filter records, and calculate useful statistics.
That gave us a convenient way to look at data as humans.
A table such as this makes immediate sense to us:
| Hours Studied | Attendance | Previous Grade | Passed |
|---|---|---|---|
| 5.5 | 92 | 78 | 1 |
| 2.0 | 68 | 55 | 0 |
| 7.0 | 95 | 91 | 1 |
| 3.5 | 81 | 73 | 1 |
| 4.5 | 88 | 79 | 1 |
We understand what the columns mean. We know that 92 represents attendance, that 5.5 represents hours studied, and that 1 in the final column means the student passed.
But a machine-learning model does not look at this table and understand “students,” “attendance,” or “grades” the way we do.
Most machine-learning models ultimately work with numbers arranged in specific structures.
One student's features might become:
[5.5, 92, 78]
Several students might become:
[
[5.5, 92, 78],
[2.0, 68, 55],
[7.0, 95, 91],
[3.5, 81, 73],
[4.5, 88, 79]
]
That second structure may look like a simple table without headings, but it introduces several ideas that appear everywhere in artificial intelligence:
arrays, vectors, matrices, dimensions, and shapes.
This is where NumPy becomes useful.
NumPy is a Python library built for working efficiently with numerical arrays. It sits underneath a huge amount of scientific computing, data science, and machine-learning work in Python.
The goal of this article is not to memorize dozens of NumPy functions.
The important goal is to understand how data becomes numbers, how those numbers are organized, and what terms such as vector, matrix, dimension, and shape actually mean when you see them in AI code.
Once those ideas make sense, a lot of machine-learning code becomes much less mysterious.
Everything Starts With Numbers
Consider a student named Anna.
We might describe her like this:
Hours studied: 5.5
Attendance: 92%
Previous grade: 78
For a machine-learning model, we can represent those three features numerically:
[5.5, 92, 78]
The meaning has not disappeared.
We know which position corresponds to which feature:
[hours studied, attendance, previous grade]
so:
[5.5, 92, 78]
means:
hours studied = 5.5
attendance = 92
previous grade = 78
This is a simple but extremely important idea.
Real-world information has been converted into an organized numerical representation.
That is what happens throughout machine learning.
A house can become numbers describing its size, age, number of rooms, and location.
A customer can become numbers describing purchases, account age, activity, and spending.
A photograph can become numbers representing pixels.
A sentence can eventually become arrays of numbers representing tokens and meaning.
The real world is complicated.
Models need mathematical representations they can calculate with.
NumPy gives us one of the main tools for working with those representations in Python.
Installing and Importing NumPy
If NumPy is not already installed, you can install it with:
pip install numpy
Then import it in Python:
import numpy as np
You will see this line constantly in data science and machine learning:
import numpy as np
np is simply the conventional short name used for NumPy.
Instead of writing:
numpy.array(...)
we write:
np.array(...)
Python Lists vs NumPy Arrays
You already know Python lists.
For example:
scores = [72, 84, 91, 68, 80]
A list is a general-purpose Python container. It can store numbers, strings, objects, or combinations of different things.
NumPy introduces another structure called an array:
import numpy as np
scores = np.array([72, 84, 91, 68, 80])
print(scores)
Output:
[72 84 91 68 80]
At first, the NumPy array does not look dramatically different from the Python list.
The important difference appears when we start performing numerical operations.
Imagine that every student receives five bonus points.
With a normal Python list, this does not work:
scores = [72, 84, 91, 68, 80]
scores + 5
Python cannot simply add the number 5 to every item in the list.
You could write a loop:
new_scores = []
for score in scores:
new_scores.append(score + 5)
With NumPy:
scores = np.array([72, 84, 91, 68, 80])
new_scores = scores + 5
print(new_scores)
Output:
[77 89 96 73 85]
NumPy applies the operation across the array.
The same applies to multiplication:
values = np.array([1, 2, 3, 4])
print(values * 10)
Output:
[10 20 30 40]
Or division:
attendance = np.array([92, 68, 95, 81, 88])
attendance_decimal = attendance / 100
print(attendance_decimal)
Output:
[0.92 0.68 0.95 0.81 0.88]
This style of working with whole arrays is one reason NumPy is so useful.
Instead of thinking:
Take item one, calculate something, take item two, calculate something, take item three...
you can often describe the operation directly:
attendance / 100
NumPy handles the element-by-element calculation for you.
This is commonly called vectorized computation.
You do not need to master that term yet. The important idea is simpler:
NumPy lets us perform numerical operations on collections of numbers without manually looping through every value.
An Important Difference: + Does Not Mean the Same Thing
Here is another example worth understanding.
With Python lists:
a = [1, 2, 3]
b = [10, 20, 30]
print(a + b)
Output:
[1, 2, 3, 10, 20, 30]
Python joins the two lists.
Now try NumPy:
a = np.array([1, 2, 3])
b = np.array([10, 20, 30])
print(a + b)
Output:
[11 22 33]
NumPy adds corresponding values:
1 + 10 = 11
2 + 20 = 22
3 + 30 = 33
That difference becomes extremely important when mathematical calculations start appearing in machine learning.
NumPy arrays are not simply Python lists with a different appearance.
They are structures designed specifically for numerical computation.
Scalars, Vectors, and Matrices
Three words appear constantly when learning AI:
scalar
vector
matrix
The names sound mathematical, but the basic ideas are straightforward.
Scalar: One Number
A scalar is simply one value.
For example:
5.5
or:
92
or:
0.73
A student's study time could be represented by one scalar:
5.5
Nothing complicated yet.
Vector: A Sequence of Numbers
Now suppose we want to describe one student using three features:
Hours studied
Attendance
Previous grade
We can store those values together:
student = np.array([5.5, 92, 78])
print(student)
Output:
[ 5.5 92. 78. ]
This one-dimensional array can represent a vector.
Conceptually:
student
↓
[5.5, 92, 78]
↑ ↑ ↑
hours | previous grade
|
attendance
A vector allows several related numerical values to describe one thing.
In machine learning, this is extremely common.
A house could be:
[120, 3, 8]
where the values represent:
[size, bedrooms, age]
A customer could be:
[42, 13, 580.50]
representing:
[age, purchases, total spending]
A machine could be:
[82.4, 0.32, 1450]
representing:
[temperature, vibration, RPM]
The numbers themselves do not tell us what they mean.
Their meaning comes from the feature definition and their position in the vector.
That is why keeping features consistent is so important.
If position zero means hours_studied during training, position zero must not suddenly mean attendance when making a prediction.
Matrix: Many Vectors Together
One student can be represented by one vector:
[5.5, 92, 78]
But machine-learning datasets usually contain many examples.
Suppose we have five students:
students = np.array([
[5.5, 92, 78],
[2.0, 68, 55],
[7.0, 95, 91],
[3.5, 81, 73],
[4.5, 88, 79]
])
print(students)
Output:
[[ 5.5 92. 78. ]
[ 2. 68. 55. ]
[ 7. 95. 91. ]
[ 3.5 81. 73. ]
[ 4.5 88. 79. ]]
Now we have a two-dimensional array.
We can think of it as a matrix.
Each row represents one student:
Student 1 → [5.5, 92, 78]
Student 2 → [2.0, 68, 55]
Student 3 → [7.0, 95, 91]
Student 4 → [3.5, 81, 73]
Student 5 → [4.5, 88, 79]
Each column represents one feature:
hours attendance previous grade
↓ ↓ ↓
Student 1 5.5 92 78
Student 2 2.0 68 55
Student 3 7.0 95 91
Student 4 3.5 81 73
Student 5 4.5 88 79
This is one of the most important structures in classical machine learning.
You will often see something called X:
X = np.array([
[5.5, 92, 78],
[2.0, 68, 55],
[7.0, 95, 91],
[3.5, 81, 73],
[4.5, 88, 79]
])
In many machine-learning examples:
X = input features
y = target or labels
So we might also have:
y = np.array([1, 0, 1, 1, 1])
where:
1 = passed
0 = failed
The complete structure is therefore:
X y
[5.5, 92, 78] ------------> 1
[2.0, 68, 55] ------------> 0
[7.0, 95, 91] ------------> 1
[3.5, 81, 73] ------------> 1
[4.5, 88, 79] ------------> 1
The model receives the features in X and learns their relationship with the known answers in y.
We are not training that model yet.
For now, we are learning what the data going into that model actually looks like.
Understanding Shape
Once you start working with NumPy, you will constantly see the word shape.
Shape tells us how an array is organized.
Consider:
students = np.array([
[5.5, 92, 78],
[2.0, 68, 55],
[7.0, 95, 91],
[3.5, 81, 73],
[4.5, 88, 79]
])
print(students.shape)
Output:
(5, 3)
What does (5, 3) mean?
It means:
5 rows
3 columns
In our dataset:
5 examples
3 features per example
This is exactly the same basic idea you saw with:
df.shape
in pandas.
The difference is that we are now looking directly at a numerical array.
Think of:
shape = (rows, columns)
for a simple two-dimensional dataset.
So:
(1000, 20)
could mean:
1000 examples
20 features per example
A model receiving that dataset is receiving 20 numerical values for each of 1,000 examples.
Dimensions: What Does ndim Mean?
NumPy arrays can have different numbers of dimensions.
You can check this with:
array.ndim
Consider:
scores = np.array([72, 84, 91, 68, 80])
print(scores.ndim)
Output:
1
This is a one-dimensional array.
Its shape is:
print(scores.shape)
(5,)
That means there is one axis containing five values.
The comma in:
(5,)
is simply Python's notation for a tuple containing one item.
Now consider our student dataset:
print(students.ndim)
Output:
2
And:
print(students.shape)
Output:
(5, 3)
It has two dimensions:
rows × columns
A useful beginner picture is:
one value → scalar
[1, 2, 3] → 1D array / vector
[[1, 2, 3],
[4, 5, 6]] → 2D array / matrix
Arrays can also have three, four, or many more dimensions.
That becomes especially important for images and deep learning.
shape, ndim, and size Are Different
These three properties are easy to confuse.
Consider:
data = np.array([
[10, 20, 30],
[40, 50, 60]
])
Check them:
print(data.shape)
print(data.ndim)
print(data.size)
Output:
(2, 3)
2
6
They answer different questions.
shape
(2, 3)
How is the data arranged?
Two rows and three columns.
ndim
2
How many dimensions or axes does the array have?
Two.
size
6
How many individual values are stored in total?
Six.
So:
shape → organization
ndim → number of dimensions
size → total number of elements
This distinction becomes useful very quickly when debugging machine-learning code.
Selecting Values From an Array
Just like Python lists, NumPy arrays use indexes starting at zero.
Consider:
scores = np.array([72, 84, 91, 68, 80])
The first value is:
print(scores[0])
Output:
72
The third:
print(scores[2])
Output:
91
Two-dimensional arrays introduce rows and columns.
Using our student dataset:
students = np.array([
[5.5, 92, 78],
[2.0, 68, 55],
[7.0, 95, 91],
[3.5, 81, 73],
[4.5, 88, 79]
])
The first student is:
print(students[0])
Output:
[ 5.5 92. 78. ]
The second student:
print(students[1])
Output:
[ 2. 68. 55.]
To select one specific value, provide both the row and column:
print(students[0, 1])
Output:
92.0
Why?
students[0, 1]
↑ ↑
row column
Row 0 is the first student.
Column 1 is attendance.
Therefore:
students[0, 1]
means:
Give me the attendance value for the first student.
Selecting an Entire Column
This syntax appears strange the first time you see it:
students[:, 0]
But it becomes easy once you read it correctly.
The colon means:
Take everything along this dimension.
So:
students[:, 0]
means:
all rows
column 0
Column zero contains study hours:
study_hours = students[:, 0]
print(study_hours)
Output:
[5.5 2. 7. 3.5 4.5]
Attendance is column one:
attendance = students[:, 1]
print(attendance)
Output:
[92. 68. 95. 81. 88.]
Previous grade is column two:
previous_grades = students[:, 2]
This gives us a useful mental model:
students[row, column]
Examples:
students[0, :] # every feature from the first student
students[:, 0] # study hours from every student
students[:, 1] # attendance from every student
students[:, 2] # previous grades from every student
You do not need advanced NumPy indexing yet.
If these four examples make sense, you already have enough indexing knowledge for many beginner AI examples.
One Dimension Is Not the Same as Two Dimensions
This causes many beginner errors.
Look at this:
student = np.array([5.5, 92, 78])
print(student.shape)
Output:
(3,)
This is a one-dimensional array containing three values.
Now:
student_2d = np.array([
[5.5, 92, 78]
])
print(student_2d.shape)
Output:
(1, 3)
These arrays contain the same three numbers, but their shapes are different.
(3,) → one-dimensional array with 3 values
(1, 3) → two-dimensional array with
1 row
3 columns
That distinction matters because many machine-learning functions expect data in the form:
(number of examples, number of features)
So one student with three features may need to look like:
(1, 3)
rather than:
(3,)
You can change the shape with reshape():
student = np.array([5.5, 92, 78])
student_2d = student.reshape(1, 3)
print(student_2d)
print(student_2d.shape)
Output:
[[ 5.5 92. 78. ]]
(1, 3)
Nothing about the actual values changed.
Only their organization changed.
This is exactly what reshape means.
Data Types: What Kind of Numbers Are Stored?
NumPy arrays also have a data type, usually called a dtype.
Create an integer array:
numbers = np.array([1, 2, 3, 4])
print(numbers.dtype)
NumPy reports an integer type.
Now:
numbers = np.array([1.5, 2.5, 3.5])
print(numbers.dtype)
It reports a floating-point type.
You normally do not need to choose the exact dtype when starting out, but understanding that it exists is useful.
NumPy generally stores an array using one common data type.
For example:
student = np.array([5.5, 92, 78])
print(student)
You may notice:
[ 5.5 92. 78. ]
The values 92 and 78 are displayed as floating-point numbers.
Why?
Because the array also contains 5.5.
NumPy chooses a compatible numerical type that can represent all the values.
This is usually exactly what we want for numerical computation.
But it can also reveal mistakes.
For example:
values = np.array([10, 20, "30"])
print(values)
print(values.dtype)
Because one value is text, NumPy may represent the array as strings rather than as normal numerical values.
That can cause problems later if you expect to perform mathematics.
It is one reason data types matter when preparing datasets.
Performing Calculations on Arrays
Now that we understand how arrays are organized, we can use them for calculations.
Consider:
scores = np.array([72, 84, 91, 68, 80])
Add five:
print(scores + 5)
[77 89 96 73 85]
Multiply everything by two:
print(scores * 2)
[144 168 182 136 160]
Divide everything by 100:
print(scores / 100)
[0.72 0.84 0.91 0.68 0.8 ]
We can also compare values:
print(scores >= 80)
Output:
[False True True False True]
NumPy performed the comparison for every value.
We can use that result to select only the matching values:
high_scores = scores[scores >= 80]
print(high_scores)
Output:
[84 91 80]
Read this expression:
scores[scores >= 80]
as:
Give me the values from
scoreswhere the conditionscore >= 80is true.
This same basic idea is closely related to the filtering you used with pandas.
Different library, same general data-thinking skill.
What Is Broadcasting?
You have already used broadcasting without realizing it.
When we wrote:
scores + 5
we combined:
an array containing several values
with:
one value
NumPy understood that the 5 should be applied across the array.
Conceptually:
[72, 84, 91, 68, 80]
+
5
behaves like:
[72 + 5,
84 + 5,
91 + 5,
68 + 5,
80 + 5]
NumPy calls this kind of compatible expansion broadcasting.
Broadcasting can become much more sophisticated when multidimensional arrays are involved, but we do not need those rules yet.
For now, remember this:
NumPy can often apply smaller numerical values or arrays across larger arrays when their shapes are compatible.
When shapes are not compatible, NumPy will tell you.
And that leads us to one of the most common NumPy problems.
Shape Mismatches
Consider:
a = np.array([1, 2, 3])
b = np.array([10, 20])
print(a + b)
NumPy cannot pair these values cleanly.
We have:
a → 3 values
b → 2 values
What should happen?
Should NumPy calculate:
1 + 10
2 + 20
3 + ???
There is no obvious answer.
So the operation fails because the shapes are incompatible.
This is why examining:
array.shape
is one of the first things you should do when numerical AI code produces a confusing error.
You will eventually encounter many errors whose real meaning is simply:
The numbers are arranged differently from what this operation expects.
Understanding shape now will save you a lot of confusion later.
From pandas to NumPy
Now we can connect this directly to the previous article.
Suppose our data starts in a CSV file:
hours_studied,attendance,previous_grade,passed
5.5,92,78,1
2.0,68,55,0
7.0,95,91,1
3.5,81,73,1
4.5,88,79,1
Load it with pandas:
import pandas as pd
df = pd.read_csv("students.csv")
Then select the input features:
X = df[
["hours_studied", "attendance", "previous_grade"]
]
And the target:
y = df["passed"]
At this point, X is still a pandas DataFrame.
Print it:
print(X)
You get something conceptually like:
hours_studied attendance previous_grade
0 5.5 92 78
1 2.0 68 55
2 7.0 95 91
3 3.5 81 73
4 4.5 88 79
pandas is excellent here because the column names carry meaning.
But we can convert those values into a NumPy array:
X_array = X.to_numpy()
print(X_array)
Output:
[[ 5.5 92. 78. ]
[ 2. 68. 55. ]
[ 7. 95. 91. ]
[ 3.5 81. 73. ]
[ 4.5 88. 79. ]]
Now:
print(X_array.shape)
gives:
(5, 3)
Five examples.
Three features.
We can do the same with the labels:
y_array = y.to_numpy()
print(y_array)
print(y_array.shape)
Output:
[1 0 1 1 1]
(5,)
This is the connection between pandas and NumPy:
CSV file
↓
pandas DataFrame
↓
inspect and prepare data
↓
numerical arrays
↓
machine-learning calculations
You should not take this diagram too literally.
Many machine-learning libraries can accept pandas DataFrames directly, so you do not always need to manually call .to_numpy() before training a model.
The important lesson is conceptual.
The headings, labels, and table formatting are useful to us as programmers.
The calculations performed by machine-learning algorithms ultimately operate on numerical values with specific dimensions and shapes.
That is the world NumPy helps us understand.
Images Are Arrays of Numbers
So far, our data already started as numbers.
But what about something that looks completely different, such as a photograph?
A computer image is also numerical data.
Let's start with the simplest case: a tiny grayscale image.
Imagine this 3 × 3 image:
dark gray bright
gray bright gray
bright gray dark
We could represent it as:
image = np.array([
[0, 128, 255],
[128, 255, 128],
[255, 128, 0]
])
For a common 8-bit grayscale representation:
0 → black
255 → white
Values between them represent different brightness levels.
So:
128
is roughly halfway between black and white.
Our matrix:
[
[0, 128, 255],
[128, 255, 128],
[255, 128, 0]
]
is not just a random collection of numbers.
It describes an image.
Check its shape:
print(image.shape)
Output:
(3, 3)
Three rows of pixels.
Three columns of pixels.
The model does not need a tiny picture drawn on the screen.
It can work with the numerical values that represent that picture.
That is the important connection:
what we see:
an image
what the computer can work with:
an array of pixel values
What About Color Images?
A color image needs more information.
One common representation uses three values for each pixel:
Red
Green
Blue
or RGB.
A pixel might therefore look like:
[255, 0, 0]
which represents strong red with no green or blue.
Another pixel could be:
[0, 255, 0]
for green.
And:
[0, 0, 255]
for blue.
Instead of each pixel containing one number, each pixel now contains three.
That means a color image can have a shape such as:
(1080, 1920, 3)
Conceptually:
height × width × color channels
or:
1080 rows of pixels
1920 columns of pixels
3 color values per pixel
We will return to images properly when we reach computer vision later in this series.
For now, the important point is not image processing.
The important point is:
Something that looks visual to us can still be represented as a multidimensional numerical array.
Text Must Become Numbers Too
Images becoming pixels may feel intuitive.
Text is less obvious.
Suppose we have:
AI learns from data
A mathematical model cannot directly perform ordinary numerical calculations on those letters.
Modern language systems therefore transform text into numerical representations.
A simplified intermediate step might look like:
AI → 104
learns → 582
from → 27
data → 913
producing:
[104, 582, 27, 913]
Real language models usually break text into units called tokens, and those tokens can be associated with numerical IDs.
There is an important warning here.
If:
data → 913
from → 27
that does not mean the word data has more meaning than from because 913 is larger than 27.
Those numbers can simply identify tokens.
Modern language models then use richer numerical representations, including vectors called embeddings, to represent useful patterns and relationships.
We will explore tokenization and embeddings properly later in this series.
For now, remember the larger idea:
table → numerical features
image → pixel values
text → tokens and numerical representations
Different kinds of information eventually become structures made from numbers.
That is one of the foundations of modern AI.
A Complete NumPy Exercise
Let's put the important pieces together.
Start by importing NumPy:
import numpy as np
Create our student feature matrix:
students = np.array([
[5.5, 92, 78],
[2.0, 68, 55],
[7.0, 95, 91],
[3.5, 81, 73],
[4.5, 88, 79]
])
And the labels:
passed = np.array([1, 0, 1, 1, 1])
First inspect the arrays:
print(students)
print(passed)
Now examine the structure:
print("Students shape:", students.shape)
print("Students dimensions:", students.ndim)
print("Students size:", students.size)
print("Labels shape:", passed.shape)
You should get:
Students shape: (5, 3)
Students dimensions: 2
Students size: 15
Labels shape: (5,)
Why is the size 15?
Because:
5 students × 3 features = 15 values
Now retrieve the first student:
first_student = students[0]
print(first_student)
Output:
[ 5.5 92. 78. ]
Retrieve only the study hours:
study_hours = students[:, 0]
print(study_hours)
Output:
[5.5 2. 7. 3.5 4.5]
Retrieve attendance:
attendance = students[:, 1]
print(attendance)
Output:
[92. 68. 95. 81. 88.]
Convert attendance percentages to decimal values:
attendance_decimal = attendance / 100
print(attendance_decimal)
Output:
[0.92 0.68 0.95 0.81 0.88]
Select students with at least 90 percent attendance:
high_attendance = students[
students[:, 1] >= 90
]
print(high_attendance)
The matching rows are:
[[ 5.5 92. 78. ]
[ 7. 95. 91. ]]
Notice what happened.
We began with a complete matrix.
We selected one column.
We performed a numerical operation on that entire column.
We created a condition.
Then we used that condition to select matching rows.
That is already a small but realistic numerical-data workflow.
And we did it without manually looping through every student.
Common NumPy Mistakes
NumPy is not especially difficult, but a few ideas confuse almost everyone at the beginning.
Mistake 1: Treating a NumPy Array Like a Python List
Remember:
[1, 2, 3] + [4, 5, 6]
joins lists.
But:
np.array([1, 2, 3]) + np.array([4, 5, 6])
performs numerical addition.
Know which type of object you are working with.
Mistake 2: Ignoring Shape
These are not the same:
(3,)
and:
(1, 3)
One is one-dimensional.
The other is a two-dimensional matrix with one row and three columns.
When machine-learning code complains about dimensions, print the shape:
print(X.shape)
That simple line often tells you exactly where the problem is.
Mistake 3: Confusing size With shape
For:
data = np.array([
[1, 2, 3],
[4, 5, 6]
])
we have:
shape = (2, 3)
size = 6
Shape tells you the structure.
Size tells you the total number of values.
Mistake 4: Mixing Incompatible Shapes
This works:
np.array([1, 2, 3]) + 10
This also works:
np.array([1, 2, 3]) + np.array([10, 20, 30])
But this does not naturally match:
np.array([1, 2, 3]) + np.array([10, 20])
Whenever an array operation fails, compare the shapes of the arrays involved.
Mistake 5: Forgetting About Data Types
This looks innocent:
data = np.array([10, 20, "30"])
But "30" is text.
That can influence the dtype of the entire array and prevent the numerical behavior you expected.
Machine-learning datasets often fail for surprisingly simple reasons such as numbers accidentally being stored as strings.
Mistake 6: Thinking Numerical IDs Automatically Carry Meaning
If a token is represented by:
913
and another by:
27
you cannot conclude that the first token is somehow “larger,” “stronger,” or “more important.”
Numerical representation does not always mean numerical magnitude carries meaning.
Understanding what each number represents is just as important as having the number itself.
Mini Challenge: Build a Tiny Image
Create a 3 × 3 grayscale image using a NumPy array.
Use values between:
0 and 255
where:
0 = black
255 = white
Start with:
import numpy as np
image = np.array([
[..., ..., ...],
[..., ..., ...],
[..., ..., ...]
])
Choose your own pixel values.
Then answer these questions using Python:
- What is the shape of the image?
- How many dimensions does it have?
- How many pixel values are stored?
- What is the darkest pixel value?
- What is the brightest pixel value?
- What happens if you calculate
255 - image?
Try it before reading the solution.
One Possible Solution
For example:
image = np.array([
[0, 128, 255],
[64, 192, 64],
[255, 128, 0]
])
Check the shape:
print(image.shape)
(3, 3)
Check the number of dimensions:
print(image.ndim)
2
Check the number of values:
print(image.size)
9
Find the darkest value:
print(image.min())
0
Find the brightest:
print(image.max())
255
Now invert the values:
inverted = 255 - image
print(inverted)
Result:
[[255 127 0]
[191 63 191]
[ 0 127 255]]
Notice what happened.
A black pixel:
0
became:
255
A white pixel:
255
became:
0
And the intermediate shades changed accordingly.
We performed an operation on an entire image using one expression:
255 - image
That tiny example demonstrates exactly why numerical arrays are so powerful.
Once data has been represented numerically, mathematical operations can transform many values at once.
The Bigger Picture
At this point, NumPy should not feel like just another Python library.
It represents a larger idea.
When we build AI systems, we repeatedly convert information into structured numbers.
One student:
[5.5, 92, 78]
is a vector of features.
Many students:
[
[5.5, 92, 78],
[2.0, 68, 55],
[7.0, 95, 91]
]
form a matrix.
A grayscale image can become:
[
[0, 128, 255],
[128, 255, 128],
[255, 128, 0]
]
A color image can have a shape such as:
(height, width, 3)
Text can be transformed into tokens and later into richer numerical vectors.
Different types of data look completely different to us.
But once converted into numerical representations, models can perform mathematical operations on them.
This is one of the bridges between the real world and machine learning.
Key Takeaways
The important ideas from this article are:
- NumPy is a Python library for numerical array computing.
- A scalar is one numerical value.
- A vector can represent several related values, such as the features of one example.
- A matrix can represent many examples, with rows usually representing examples and columns representing features.
- A NumPy array's shape tells you how its values are organized.
ndimtells you how many dimensions an array has.sizetells you how many total values it contains.- NumPy can perform operations across entire arrays without requiring explicit Python loops.
- Array indexing lets you select individual values, rows, columns, and subsets.
- Shape mismatches are one of the most common sources of confusion in numerical code.
- pandas is excellent for loading and inspecting tabular data, while NumPy helps expose its numerical structure.
- Images can be represented as arrays of pixel values.
- Text must also eventually be converted into numerical representations before modern machine-learning models can process it.
- Understanding arrays and shapes now will make later machine-learning code much easier to understand.
What Comes Next
We now have the pieces needed to describe data numerically.
We know what it means when a dataset has a shape such as:
(1000, 20)
We know how one example can become a vector, how many examples can become a matrix, and how completely different kinds of information such as images and text can eventually be represented using numbers.
But having numbers is only the beginning.
The next question is:
What mathematics do machine-learning systems actually perform with those numbers?
This is where many people assume AI suddenly requires advanced mathematics.
It does not.
Before learning actual machine-learning algorithms, we need a small collection of mathematical ideas that appear again and again: averages, variation, probability, relationships between variables, functions, vectors, matrices, and prediction error.
That is what we will cover next in The Math You Actually Need for AI.
The goal will not be to turn this series into a mathematics textbook.
It will be to understand enough mathematics that when a machine-learning model starts calculating, measuring errors, and learning patterns, you understand what those calculations are trying to accomplish.