The nice thing about the trigonometric circle is that it is, quite so indeed, a circle. But it’s also a disadvantage when you consider the implementations of functions manipulating angles, especially .
This is particularly a problem when you’re not so much interested by a specific angle (which is at all time always well-defined) than by a series of angles varying in time. If you’re certain that your angle is always within or within , you do not expect problems. What if, on the contrary the angle wraps around?
So here how the problem arose for me (at least in a simplified version). I have a time series composed of angles , and, given (a possibly large portion of) the history, I must predict . Normally, that shouldn’t be too complicated. Except that I do not generate the series, and all angles I have are .
If I was the one generating the angles, I could have simply stored them using differences, that is, starting at an initial , I would emit only the differences, the , and then I am free to store internally angles of if I please.
However, since the angles I have are stored , it is not always possible to figure out how to repair the series so that angles are not stored . If the differences around a zero-crossing are small, then you go from close to zero to close to and you can correct and remove the offset of . But if the variation is large enough to hide a zero-crossing (or a -crossing) you have ambiguity.
The solution I found was to use quadrature phase encoding, where angles are not stored directly as, say, , but as a pair
This encoding seemingly doubles the quantity of information you have to learn (if you’re doing machine learning) but in fact, it’s only a re-representation of the input that removes the wrap-arounds (without special cases) and gives a representation that is varying smoothly with any angle , regardless of whether or not you’re crossing zero (or ).
Let us have a look at what this representation does on angle time-series. For the need of the demonstration, I used a random walk where . In all graphs the colors are: black, the non-wrapped series, red, the series , dashed purple, the cosine component, and dashed blue the sine component. So, let us look at a first graph:
There’s a zero crossing somewhere around 45-50, and the series jumps up close to , which leaves the predictor to understand what happened there. No need to say, in a compression setting, that jumps means a lots of bits to compensate for the use prediction error, as the prediction would probably be around -0.1 or something and the observed value close to .
The second example makes the point entirely I think. The (true) series remains close to zero and there are plenty of crossing. From the point of view of a learning algorithm, the sequence would seem rather hard to understand—because we, in general, do not suppose the learning algorithm knows something about the data it learns from.
If we look at what represents geometrically, we see that it just generates the points on the unit circle. If we cross zero or , just describes another point on the unit circle and the variation is smooth (i.e., a small change in gives a small change in .
If we had a pair angles, say and , it would now describe a sphere, and the encoding would become , which is the spherical-cartesian coordinates transform. If we had more angles (in a higher-dimensional case), we could find similar equations to accommodate the encoding of angles. In general, we will have one more encoded component than the number of angles (indeed), so the cost goes down as the number of dimensions goes up.
I do not know yet if this representation will help my learning algorithm or not, but I suspect that removing the (apparently random) discontinuities will certainly not hurt. One could also address the more general problem of representing orientations relative to a given vector. What makes things complicated is that we are not very good, in general, at picturing high-dimensional objects—it seems every time I start thinking about these they end up curiously 3D volume- and plane-like.