By Sagi Shaier · 7 October 2026 · 4 min read
Sine and cosine for machine learning
Sine and cosine are the coordinates of a point on a circle of radius 1, and they repeat every full turn. This post explains the unit circle, the identity sin² + cos² = 1, and how sine and cosine features let a model see that hour 23 and hour 0 are one hour apart, with PyTorch code.
Sine and cosine are two functions of an angle that give the y and x coordinates of a point on a circle of radius 1. In machine learning they show up when a feature goes in a cycle, such as the hour of the day or the day of the year, because they repeat every full turn and put the end of the cycle right next to its start.
For ML, the useful part of trigonometry is knowing what $\sin$ and $\cos$ are, what range their values fall in, and why they repeat.
Sine and cosine on the unit circle
The unit circle is a circle of radius 1 centered at the origin. Pick an angle $\theta$ (the Greek letter theta), measured counterclockwise from the positive x-axis, and walk that angle around the circle. You land on one point.
That point's x-coordinate is $\cos(\theta)$ and its y-coordinate is $\sin(\theta)$. This is the definition. The circle has radius 1, so both values stay between -1 and 1.
Angles in ML code are measured in radians, where a full turn is $2\pi$ (about 6.283) instead of 360 degrees. A quarter turn is $\pi/2$ and a half turn is $\pi$. At $\theta = \pi/3$, which is 60 degrees, the point sits at $\cos(\theta) = 0.5$ and $\sin(\theta) \approx 0.87$.

The identity sin² + cos² = 1
One identity follows straight from the definition:
$$\sin^2(\theta) + \cos^2(\theta) = 1$$
Every point on a circle of radius 1 satisfies $x^2 + y^2 = 1$, and the point at angle $\theta$ has coordinates $x = \cos(\theta)$ and $y = \sin(\theta)$. Substituting them in gives the identity, for any angle.

Why sine and cosine repeat
Sine and cosine are periodic: they repeat every $2\pi$ radians, because walking one full turn around the circle brings you back to the same point.
$$\sin(\theta) = \sin(\theta + 2\pi)$$
The same holds for $\cos$. The curves above repeat their shape every $2\pi$ for this reason.
Encoding things that cycle
Many features wrap around: the hour of the day, the day of the week, the day of the year, a compass direction. Fed to a model as a raw number, hour 23 and hour 0 are 23 apart, even though they are one hour apart on the clock.
The fix is to turn the hour into an angle and give the model the point on the circle instead of the number. One full day is one full turn:
$$\theta = \frac{2\pi \cdot \text{hour}}{24}$$
The model then gets two features, $\sin(\theta)$ and $\cos(\theta)$. Hours 23 and 0 land on neighbouring points of the circle, so the wrap-around is part of the input.

Both features are needed. $\sin(\theta)$ alone gives the same value for hour 3 and hour 9, since both sit at the same height on the circle, and $\cos(\theta)$ tells them apart.
Sine and cosine in PyTorch
torch.sin and torch.cos take angles in radians:
1import math
2import torch
3
4theta = torch.tensor([0.0, math.pi / 3, math.pi / 2, math.pi])
5print(torch.cos(theta))
6print(torch.sin(theta))
7print(torch.sin(theta) ** 2 + torch.cos(theta) ** 2)1tensor([ 1.0000e+00, 5.0000e-01, -4.3711e-08, -1.0000e+00])
2tensor([ 0.0000e+00, 8.6603e-01, 1.0000e+00, -8.7423e-08])
3tensor([1., 1., 1., 1.])Values like -4.3711e-08 are 0 up to floating point rounding, since $\pi$ cannot be stored exactly. The last line checks the identity at all four angles.
Now hours 23, 0 and 12 as sine and cosine features, with the distance between them:
1import math
2import torch
3
4hours = torch.tensor([23.0, 0.0, 12.0])
5theta = 2 * math.pi * hours / 24
6features = torch.stack([torch.sin(theta), torch.cos(theta)], dim=1)
7
8print(features)
9print("raw gap 23 vs 0: ", abs(hours[0] - hours[1]))
10print("sin/cos gap 23 vs 0: ", torch.dist(features[0], features[1]))
11print("sin/cos gap 0 vs 12:", torch.dist(features[1], features[2]))1tensor([[-2.5882e-01, 9.6593e-01],
2 [ 0.0000e+00, 1.0000e+00],
3 [-8.7423e-08, -1.0000e+00]])
4raw gap 23 vs 0: tensor(23.)
5sin/cos gap 23 vs 0: tensor(0.2611)
6sin/cos gap 0 vs 12: tensor(2.)As raw numbers, 23 and 0 are as far apart as two hours can be. As points on the circle they are 0.26 apart, the same as any two neighbouring hours, and hour 12 sits on the opposite side at the largest possible distance, 2. If the features come out wrong, check the period first: 24 for hours, 7 for weekdays, 365 for days of the year.
When to use sine and cosine features
Use them for any feature whose last value is next to its first: time of day, weekday, month, day of year, wind direction, an angle. Skip them for values that do not wrap around, such as a year, an age or a price, since putting those on a circle would make the largest value look close to the smallest.
Common mistakes:
- Using degrees.
torch.sinexpects radians.torch.sin(torch.tensor(90.0))is about 0.89, not 1. - Keeping only the sine. Two different hours can share a sine value, so the model needs both.
- The wrong period. Dividing by 23 instead of 24 for hours 0 to 23 puts hour 23 on top of hour 0.
Related math
$\theta$ has a second meaning in optimization, where it usually stands for the model's parameters rather than an angle. That use, with argmin and the other symbols around it, is in how to read the math notation in ML papers. Exponents and logarithms are the other functions in this part of the math toolkit, in exponents and logarithms for machine learning.
QuiddityML teaches sine, cosine and the unit circle as their own concept in the Math track, and the exercises include picking the PyTorch line that computes the sine of a tensor of angles and tracing sine and cosine values through a short piece of code.