How to computing 1/(1+exp(x)) ? cordic maybe ? Solution Found!
Bean
Posts: 8,129
I'm working on a project where I need to compute 1/(1+exp(x))*65536 for a given x in 16.16 fixed point format.
Is it possible to use cordic to compute this ? If not what other methods might work.
We need as much precision as possible.
This is for the SX chip, so I can't use the propeller log tables either.
Any ideas guys...?
[edit] Solution found. See post on page 2
Bean
Is it possible to use cordic to compute this ? If not what other methods might work.
We need as much precision as possible.
This is for the SX chip, so I can't use the propeller log tables either.
Any ideas guys...?
[edit] Solution found. See post on page 2
Bean
Comments
http://www.leonheller.com/ADI/Chapter_4.pdf
It was easier to upload it than it was to find it on ADI's web site.
What's X's domain (min to max)?
-Phil
Phil,
The "x" value is could be anything in the positive range (the negative range is just a mirror image around 0.5). So that's zero to 32767.999984.
Bean
I'm thinking that precision is more important. Accuracy is not as long as it is 100% repeatable. We can deal with accuracy on the PC side.
Bean
In it's basic form it is doing a curve fit.
We have two (or more) input variables that are used. So I guess that would be a 2D curve fit.
Bean
-Phil
This sounds like a classic engineering design problem. Fun.
First, we need better specs.
Why are you using the SX? Interface, cost (meaningless on a oneoff), space, weight, etc.
Significant places of your input. Wanting maximum precision or significant places is nice, but meaningless if your input/hardware has a limit.
What is your turnover requirement (is that the right word guys?). If you need a million a second, forget the SX and start looking for a (more expensive) specialized chip. If you only need a response every second or so, calculation by series is great and you have the time to carry it out to any level of precision you can conceive.
Next, if I read your description right, you will have input value of 1 - 32,000 and Y decimal places after that. Y may be specifying an accuracy that even the commercial lookup tables can't manage. (PARALLAX, how many entries in the Propeller log tables and how many places?)
Unless you have a reason for using ONLY the SX and adding no additional hardware, I would say your best bet is a series calculation. Look it up on the web. I found several sites discussing different algorithms for calculating logs. Some must be smaller/more efficient that others.
Also, be warned. Most hardware has an inherent limit on significant digits. Years ago I worked on a satellite problem that required 20 decimals of accuracy. We found out the hard way that it is NOT possible to double precision a value you have already double precisioned in FORTRAN. It required some special programming outside of the internal math functions.
Perhaps this may help: the Newton's handwriting recognizer neural networks were trained and then quantized. Their paper suggests that non-bias weights can be quantized down to a byte:
"Combining Neural Networks and Context-Driven Search for On-Line, Printed Handwriting Recognition"
http://aaaipress.org/ojs/index.php/aimagazine/article/download/1355/1255
The target device size is a 14 pin dip in a sealed metal can. The Propeller is way too large. Cost is not really a factor (within reason).
Speed is not a big concern either, about 500 exp calcs per second.
I'm working on something that seem to work, but needs more precision. I'll keep you all updated.
Sorry, I cannot give more detail, but this is a work project.
Bean
Was not serious. :-)
Here is a graph of the function, along with graphs of similar functions arctan and tanh scaled to the 0 to 1 range.
A series representation of 1/(1+exp(x)) converges slowly for larger values of the argument. Here is the Maclaurin expansion around x=0. At large x (meaning anything much greater than 1), it involves tiny differences between very large numbers. I haven't pursued it, but I question if it converges at all for x>1.
I'd like to try using ATAN(x) instead of 1/(1+exp(x)), but the cordic ATAN routine needs two parameters as it computes ATAN2(y, x)
Is there a way to use the ATAN2 cordic routine with a single parameter ?
Bean
(Please note that the sign of x in the equation for use in nerual nets is supposed to be negative.)
It produces a piecewise linear approximation, where the number of pieces increases as the power of the number of iterations. So I put it to the test, using the following Spin program:
This code assumes a 16.16 fixed-point scale. I then exported the data from the program to Excel (file attached), normalized the values to floating-point, and created a graph that plots the approximate value and the "real" value:
The agreement looks pretty good for small absolute values of x, but quickly reaches its limiting values outside the interval [-4, 4]. I think the method could be improved somewhat over what was presented in the paper, but I'm not sure how just yet.
-Phil
It seems to have better behavior than the previous algo in the tail regions. Here's my Spin code:
And here's a chart produce from the above Excel file that compares the approximation to the real thing:
-Phil
We have pretty much decided to use atan(x) and see how that works out.
Bean
Any continuous sigmoid-shaped function should work. There's certainly nothing magic about either the exponential or the atan form. You just want something that's relatively smooth and fast to compute. BTW, I'm pretty sure I can make the above approximation smoother yet. One moment, please ...
-Phil
The second paper Phil found points out that first derivative of the classic sigmoid is convenient, in the sense that if you have the fixed point binary value for f(x), then the 1st derivative is simply the original function times its own twos complement:
f'(x) = f(x) * (1 - f(x))
For atan(x), the first derivative is 1/sqrt(1 + x2), which could be harder, except if you are doing it with CORDIC, sqrt(1+x2) drops out of the algorithm as the length of the vector (which turns out to be important after all!), and you are left with finding the inverse and scaling, which is manageable but more work than would be the sigmoid.
That paper also pointed out that the first derivative of the hyperbolic tangent has a simple relation to the function, that is f'(x) = (1 - f2(x)), the twos complement of the square of the function itself at x. CORDIC can calculate tanh, but I think it does so by first finding sinh and cosh, followed by the quotient.
Bean