Angles and waves
Radians, sine and cosine on the unit circle, the angle between embeddings, cycles and positions as waves.
Create a free account Try part of it here
Why it matters
Angles and waves turn up in more of AI than you'd expect. Cosine similarity is, literally, the cosine of the angle between two vectors. Transformers mark each word's position with sine and cosine waves of different speeds. Daily and weekly patterns in sales, traffic and server load are waves riding on a trend. This lesson builds angles, radians, sine and cosine from a single circle, then puts them to work: measuring the angle between embeddings, modeling a weekly cycle, and seeing how positions become waves.
What you'll be able to do
- Measure angles in degrees and radians, and convert between them
- Read sine and cosine as the up and across of a point on the unit circle
- Find the angle between two vectors from their cosine similarity
- Describe a repeating pattern with a wave, and explain why transformers encode positions with waves
What it covers
- Degrees and radians
- Sine and cosine on the unit circle
- A point on the circle
- The angle between two vectors
- Waves: amplitude, period and frequency
- A weekly cycle
- Positions as waves
- Angles and waves in AI
Show the answer
90
A full turn is 360°, and 12 to 3 is a quarter of the way round: 360 ÷ 4 = 90°. Angles measure how far something has turned.
Degrees and radians
A full turn is 360 degrees, a number chosen long ago because it divides evenly in many ways. Mathematics and code usually use radians instead: the angle measured by the length of arc it sweeps out on a circle of radius
- A full circle's edge is 2π long, so a full turn is 2π radians, about 6.283, and a half turn is π, about 3.142.
To convert, multiply degrees by π / 180, or radians by 180 / π. Python's math functions all expect radians, which is the most common source of wrong answers with angles in code:
import math print(math.radians(180), math.pi) print(math.degrees(math.pi / 2)) print(math.sin(90), math.sin(math.radians(90))) # 90 radians versus 90 degrees
The last line shows the trap: math.sin(90) treats 90 as radians, more than fourteen full turns, and gives a meaningless answer.
Why do mathematicians prefer radians? Because they make the formulas simple. An arc of angle θ radians on a circle of radius r is exactly r × θ long, with no conversion factor. And the calculus works out cleanly: the rate of change of sin θ is cos θ only when θ is measured in radians. Degrees stay useful for talking to people, since "a 90° turn" is easier to picture than "a turn of 1.571". So a good habit is to think in degrees and compute in radians, converting at the edges of your code.
import math print(round(math.radians(90), 4))
Show the answer
1.5708
90° is a quarter turn, and a full turn is 2π radians, so a quarter is π/2 ≈ 1.5708.
Sine and cosine on the unit circle
Draw a circle of radius 1 around the origin, the unit circle. Start at the point (1, 0) and turn counterclockwise by an angle θ. The point you land on has coordinates (cos θ, sin θ): the cosine is how far across, and the sine is how far up.
At 0° you're at (1, 0), so cos 0 = 1 and sin 0 = 0. A quarter turn takes you to (0, 1). A half turn to (−1, 0). And since every point is 1 away from the center, Pythagoras gives cos²θ + sin²θ = 1 for every angle.
import math for degrees in [0, 30, 90, 180]: t = math.radians(degrees) print(degrees, round(math.cos(t), 3), round(math.sin(t), 3))
import math print(round(math.cos(math.pi), 1), round(math.sin(math.pi), 1))
Show the answer
-1.0 0.0
π radians is a half turn, which lands on (−1, 0): all the way across to the left, and level. (Python prints sin π as a tiny number near zero, which rounds to 0.0.)
As the angle goes round, cosine traces how far across you are and sine how far up. The curve drawn is the sine wave.
A point on the circle
Set x and y to the coordinates of the point at 30° on the unit circle, each rounded to 3 places, and total to x² + y², rounded to 3 places, which should come out as 1.
import math x = 0 y = 0 total = 0 print(x, y, total)
The angle between two vectors
The dot product lesson defined cosine similarity as a·b divided by both lengths. That number is exactly the cosine of the angle between the two vectors, so you can turn it back into an angle with the inverse cosine, math.acos:
import math a = [3, 1] b = [1, 2] dot = sum(x * y for x, y in zip(a, b)) cos_sim = dot / (math.hypot(*a) * math.hypot(*b)) print(round(cos_sim, 3), round(math.degrees(math.acos(cos_sim)), 1))
A cosine similarity of 1 is an angle of 0°; 0 is 90°; −1 is 180°. Reading similarities as angles can make them easier to feel: two embeddings at a cosine of 0.5 sit 60° apart, which in a space of 1,536 dimensions is a strong sign of related meaning.
import math print(round(math.degrees(math.acos(1 / math.sqrt(2))), 1))
Show the answer
45.0
The vector [1, 1] points halfway between across and up, 45° from [1, 0]. The inverse cosine of 0.707 turns the similarity back into that angle.
Waves: amplitude, period and frequency
As the angle keeps turning, sine repeats forever: up, down, up again, every 2π. That makes it the natural shape for anything that cycles. Three numbers describe a wave:
- the amplitude: how far it swings above and below the middle;
- the period: how long one full cycle takes;
- the frequency: how many cycles fit in one unit of time, 1 ÷ period.
A pattern that repeats every 7 days is sin(2π × day / 7): after 7 days the angle has gone exactly once round. Add a middle value and an amplitude, and you have a model of weekly sales:
import math for day in range(8): print(day, round(100 + 20 * math.sin(2 * math.pi * day / 7), 1))
Day 7 matches day 0, because the wave has completed exactly one period.
Notice what each number in the formula does. The 100 sets the middle line the wave swings around. The 20 is the amplitude: sales rise to 120 at the peak and fall to 80 at the trough. The 7 under the day is the period. Change it to 30 and the cycle becomes monthly; change it to 365 and it becomes yearly. Real data rarely follows a single clean wave, but a forecasting model that knows "there's a weekly rhythm here" can separate that rhythm from the trend underneath it, and that is often the difference between a forecast that's useful and one that chases noise.
A weekly cycle
Model daily sales as 100 + 20 × sin(2π × day / 7) for days 0 to 13. Set sales to the list of values, each rounded to 1 place, and peak to the day, from 0 to 6, with the highest sales in the first week.
import math sales = [] peak = 0 print(sales, peak)
Positions as waves
A transformer reads all its words at once, so it needs a way to know where each word sits. The original transformer gave every position a list of sines and cosines at many different frequencies. Fast waves change a lot from one position to the next, so they tell neighbors apart. Slow waves barely change between neighbors, but differ across long distances, so they tell far-apart positions apart.
It works like a clock: the second hand distinguishes moments a second apart, and the hour hand moments hours apart. Read all the hands together and every time of day gets a unique pattern. Many recent models use rotary encodings instead, which rotate each word's vectors by an angle that grows with its position: angles again.
import math for pos in range(4): fast = round(math.sin(pos * 1.0), 2) slow = round(math.sin(pos * 0.01), 2) print(pos, fast, slow)
Show the answer
Fast waves tell nearby positions apart; slow ones tell far ones apart
One fast wave repeats too soon, so far-apart positions could look the same; one slow wave changes too little between neighbors. Together, like a clock's hands, they give every position a distinct pattern.
Angles and waves in AI
Beyond similarity and positions, waves are the language of seasonality in forecasting, where a weekly or yearly cycle rides on top of a trend. Audio is a sum of waves, which is how speech models see sound. Fourier features feed a network sines and cosines of its inputs so it can learn fine detail. And whenever a library function takes an angle, check whether it wants degrees or radians before you trust the answer.
import math print(round(math.sin(math.pi / 2), 4))
Show the answer
1.0
π/2 radians is a quarter turn, straight up on the unit circle, where the sine, the height, is 1.
Practice what you just read
- 5 code examples you can edit and run
- a practice exercise that checks your code
- a 6-question quiz
- 5 review cards for spaced repetition
Try a quiz question
On the unit circle, what are the coordinates of the point at angle θ?