Sigmoid with Large Number in JavaScript - javascript

From what I understand you use a sigmoid function to reduce a number to the range of 0-1.
Using the function found in this library
function sigmoid(z) {
return 1 / (1 + Math.exp(-z));
}
This works for a numbers 1-36. Any number higher than this will just return 1.
sigmoid(36) -> 0.9999999999999998
sigmoid(37) -> 1
sigmoid(38) -> 1
sigmoid(9000) -> 1
How do you increase the range so this function can handle a number larger than 36.

A sigmoid function is any function which has certain properties which give it the characteristic s-shape. Your question has many answers. For example, any function whose definition looks like
const k = 2;
function sigmoid(z) {
return 1 / (1 + Math.exp(-z/k));
}
will fit the bill. The larger the k, the larger the useful domain.

A Sigmoid Function doesn't have bounds, that means it accept from infinitely small to infinitely large values.
Javascript, on the other hand, will round numbers (IEEE).
Anyway, what you can do is reescale your input before passing it to the formula.
Another option is tinker with the formula values, most notably the z value.

Related

Efficient way to compute the median of an array of canvas in JavaScript

I have an array of N HTMLCanvasElements that come from N frames of a video, and I want to compute the "median canvas" in the sense that every component (r, g, b, opacity) of every pixel is the median of the corresponding component in all the canvases.
The video frames are 1280x720, so that the pixels data for every canvas (obtained with canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height).data) is a Uint8ClampedArray of length 3.686.400.
The naive way to compute the median is to:
prepare a result Uint8ClampedArray of length 3.686.400
prepare a temporary Uint8ClampedArray of length N
loop from 0 to 3.686.399
a) loop over the N canvases to fill the array
b) compute the median of the array
c) store the median to the result array
But it's very slow, even for 4 canvases.
Is there an efficient way (or existing code) to do that? My question is very similar to Find median of list of images, but I need to to this in JavaScript, not Python.
Note: for b), I use d3.median() which doesn't work on typed arrays, as far as I understand, so that it implies converting to numbers, then converting back to Uint8Clamped.
Note 2: I don't know much of GLSL shaders, but maybe using the GPU would be a way to get faster results. It would require to pass data from the CPU to the GPU though, which takes time if done repeatedly.
Note 3: the naive solution is there: https://observablehq.com/#severo/compute-the-approximate-median-image-of-a-video
You wrote
I use d3.median() which doesn't work on typed arrays…
Although that is not exactly true it leads into the right direction. Internally d3.median() uses the d3.quantile() method which starts off like this:
export default function quantile(values, p, valueof) {
values = Float64Array.from(numbers(values, valueof));
As you can see, this in fact does make use of typed arrays, it is just not your Uint8ClampedArray but a Float64Array instead. Because floating-point arithmetic is much more computation-intensive than its integer counterpart (including the conversion itself) this has a dramatic effect on the performance of your code. Doing this some 3 million times in a tight loop kills the efficiency of your solution.
Since you are retrieving all your pixel values from a Uint8ClampedArray you can be sure that you are always dealing with integers, though. That said, it is fairly easy to build a custom function median(values) derived from d3.median() and d3.quantile():
function median(values) {
// No conversion to floating point values needed.
if (!(n = values.length)) return;
if (n < 2) return d3.min(values);
var n,
i = (n - 1) * 0.5,
i0 = Math.floor(i),
value0 = d3.max(d3.quickselect(values, i0).subarray(0, i0 + 1)),
value1 = d3.min(values.subarray(i0 + 1));
return value0 + (value1 - value0) * (i - i0);
}
On top of getting rid of the problematic conversion on the first line this implementation additionally applies some more micro-optimizations because in your case you are always looking for the 2-quantile (i.e. the median). That might not seem much at first, but doing this multiple million times in a loop it does make a difference.
With minimal changes to your own code you can call it like this:
// medianImageData.data[i] = d3.median(arr); Instead of this use line below.
medianImageData.data[i] = median(arr);
Have a look at my working fork of your Observable notebook.

How to lazily evaluate a sequence by altering every alternate values in the sequence?

I have implemented a lazy infinite sequence function along with 3 functions called take,reduce,map. the take function is similar to Haskell's implementation where it takes a finite sequence from the infinite sequence given a finite value and the usual reduce and map functions in Javascript that works with the finite sequence type.
Now I'm trying to evaluate values in the sequence with various conditions applied to the sequence values.
I'm stuck at implementing functions that takes in a number term and calculate the sequence total product and sum with every alternating sequence value sign is changed to a negative sign. Here's the function I implemented for that objective:
function alternatingProduct(term) {
return reduce((x, y) => x * y, take(term, map(x => -x, generateSequence((v) => (v + 1))(1))), 1);
}
How the function supposed to work is it takes in the sequence lazily and changes every alternate value sign from positive to negative. So when sequence of 1 to 3 is generated for example, the 2 in the sequence should be negative, giving a total product of the whole finite sequence an answer of -6.
Initially I thought my code is working when I called
alternatingProduct(4)
//where it returns 24.
alternatingProduct(3)
//where it returns -6.
When i tried to implement a similar function to sum instead, that's when I realised my function is wrong.
function alternatingSum(term) {
return reduce((x, y) => x + y, take(term, map(x => -x, generateSequence((v) => (v + 1))(1))), 0);
}
alternatingSum(3)
//should return 2 because of 1+(-2)+3 but it returned 5 instead
alternatingSum(4)
//should return -2 because of 1+(-2)+3+(-4) but it returned -9 instead
Now I realised my function map changes every value in the sequence. I have no ideas how to change my code to only change alternating values of a lazy sequence. I am new to lazy sequence and evaluation and just experimenting with it so any help is appreciated
You can just use
map(x => x%2 ? x : -x, …)
so that odd values are kept and even values are negated.

Generating a random number between a range with a weight/bias?

I am trying to generate a random number between 1 and a maximum. This I don't have a problem doing so and do so with the following:
var max = 200;
var randomNumber = Math.floor(Math.random() * max) + 1;
However in an ideal situation I would like to generate a number between 1 and my maximum however the lower numbers have a higher probability of occurring. I want the variable to be biased towards 1. However my maths skills aren't strong enough to work this out, it would be great if someone could point me in the right direction.
Thank you,
Josh
a simple way will be to just square the result of Math.random(). Since the result of the function is between 0 and 1 , the square will also be in the range [0, 1], but values , for example , 0.5 from it will be mapped to lower ones - 0.25 . You can experiment with powers above 1 until you find an acceptable function.
I got a code in java which does what you want.
You should choose your own probabilities for the int[] prob arrays.
I think it wont be that hard to translate this to js or build smth. equal.
int[] probs;
void initRandom(int n, int[] probabilities)
{
int i,j,begin=0,end=0,sum=0;
int[] probs;
// sum of all propabilitys must be 100%
for(i=0;i<probabilities.length;i++) sum+=probabilities[i];
probs=new int[sum];
// fills numbers from 0 till n-1 in regard to their probabilities
// to the probability array.
for(i=0;i<n;i++)
{
begin=end;
end+=probabilities[i];
for(j=begin;j<end;j++) probs[j]=i;
}
}
int genRandom()
{
return probs[smallRand(probs.length-1)];
}
This is a very general question. First consider this link here
http://en.wikipedia.org/wiki/List_of_probability_distributions#Supported_on_a_bounded_interval
It shows some probability functions which are bounded, which I believe is what you are looking for (since min=1 and max=max).
You can also chose a semi-infine interval, and just ignore all value above your maximum. I think, this could also be acceptable, depending on your application.
Next, chose one of those probabilty functions, that suits you best. For the sake of simplicity, I chose the triangular distribution
The distribution functions are (PDF and CDF)
f(x) = 2/(2*max-1-max^2)*(x-max)
F(x) = 2/(2*max-1-max^2)*(0.5*x^2-max*x-0.5+max)
so I can generate from a uniform distribution on 0-1 a biased distribution by inverting the CDF like
var urand = Math.random();
var a = 2/(2*max-1-max^2);
var randomNumber = max-Math.sqrt(max*max-2*(max-urand/a-0.5));
Cheers
R
The following function i made up gives you a near-one-biased random number
function rand(max) {
var r = Math.random();
r = 1/(101-100 * r);
return Math.floor(r * max) - 1;
}
It only uses simple arithmetics, thus, it should be quite fast.

Save integers as floats [duplicate]

This question already has answers here:
Save integer as float
(2 answers)
Closed 8 years ago.
function prec(numb){
var numb_string = numb.toString().split('.')
return numb_string[(numb_string.length - 1)].length
}
function randy(minimum, maximum) {
var most_accurate = Math.max ( prec(minimum), prec(maximum) );
return ( ( Math.random() * ( maximum - minimum ) + minimum ).toFixed( most_accurate ) );
}
// returns random numbers between these points. 1 decimal place of precision:
console.log( randy(2.4,4.4) );
// returns random numbers between these points. 3 decimal places of precision:
console.log( randy(2.443,4.445) );
// returns random numbers between these points. Want 3 decimal places of precision. However, get 0:
console.log( randy(2.000,4.000) );
// Why do I get 0 decimal places? Because floats are rounded into integers automatically:
console.log( 4.0 ); // want 4.0 to be logged. Instead I get '4'
You don't need to read how the functions work. Just the console logs.
Basically, I need to return a random number between two points to a degree of precision. The precision is automatically derived from the most precise float passed to the randy function.
This works fine when the number range is 3.5 3.7 or 34.4322 800.3233 but not 2.0, 3.0 or 4.0000, 5.0000
Then the number is appears to be automatically saved as an integer:
console.log( 2.0 ) //=> 2
I want to extend the Number prototype so that 2.0 is saved as 2.0 so that this function can find the precision:
function prec(numb){
var numb_string = numb.toString().split('.')
return numb_string[(numb_string.length - 1)].length
}
It currently thinks that 3.000000000 has a precision of 0 decimal places because if 3E8 is passed in as the numb parameter, it's read as 3. I want it read as 3.000000000
While I can do this randy(2.toFixed(3),3.toFixed(3)) it gets unreadable and it would be undeniably nicer to do this for smaller precisions: randy(2.000,3.000).
Is this possible?
Fiddle
There is only one number type in JS.
Aside from shortfalls of the type itself (causing headaches in other languages as well), it's a good thing.
If you want to display precision, then use num.toFixed(n); to store the number as a string, rounded to the precision you requested.
You can parse the string later in your code, operate on it, and then call .toFixed(n); on the result, to perpetuate the precision...
But unless you have specific needs, or are lumping several pieces of code together, are you not going to be concerned with rounding inaccuracies, versus just operating on full-precision values, and then rounding/formatting the end results?
Of course there are plenty of other solutions...
...keep track of the mandated precision with an int, representing the value... ...or keep an int representing the floating value as an int, based on preferred precision... 1.235 becomes [1, 235].
...anything is doable.
Subclassing, though, is really not going to be the answer.
you can define a class that helps you solve the problem especially with the toSting function
function NewNumber()
{
this.value = (typeof(arguments[0]) == "number") ? arguments[0] : 0;
this.decimal = (typeof(arguments[1]) == "number") ? arguments[1] : 0;
this.Val = function()
{
return parseFloat(this.value.toFixed(this.decimal));
}
this.toString = function()
{
return (this.value.toFixed(this.decimal)).toString();
}
}
Create a number like this
var Num = NewNumber(4.123545,3);
// first argument is the value
// and second one is decimal
To get the value of your variable, you should use the function Val like this
console.log(Num.Val()); // this one prints 4.123 on your console
Then the toString function
Num.toString() // it returns "4.123"
(new NewNumber(4,4)).toString(); // it returns "4.0000"
in your functions use the toString of the NewNumber class to solve your problem

Neural Network Continuous tanh-Sigmoid Activation Function and Random Weights

I really need help implementing a continuous tanh-sigmoid activation function in a very basic neural network. If you could give a basic example that would be great, but if you could change it in my source code I would be extremely grateful! Also, what range should the random weights be initiated with (i.e. what range)?
The weight range depends on what input data range you have. In some implementations the weights can also be negative.
For possible Sigmoid functions, check here (tanh is not the only possibility):
http://en.wikipedia.org/wiki/Sigmoid_function
Tip: You can typically compute the NN with matrix multiplications.
http://www.dtreg.com/mlfn.htm
http://en.wikipedia.org/wiki/Neural_network
P.S.: probably not a good idea to do this in JavaScript.
you can either implement it via exp(x) , See: http://www.javascripter.net/faq/mathfunc.htm
sinh(x) exp(x) - exp(-x) exp(2x) - 1
tanh(x) = ------- = ------------------ = -------------
cosh(x) exp(x) + exp(-x) exp(2x) + 1
that gives you:
function tanh(x) {
e = Math.exp(2*x);
return (e - 1) / (e + 1) ;
};
another solution is to store a table with the tanh function values in an array, and define a JavaScript function which interpolates the tanh values for x based on the tanh values stored in the array
typically people don't want [-inf...+inf] as the range of the input values, and don't want [-1...+1] as the range of output values -- therefore you might need a different sigmoid function!
you need to take the expected range of input values, and the expected range of output values, and use those to shift the actual sigmoid function, the weight-ranges and the value of the threshhold.
a threshhold of 0.7 or larger is typically used. You need to experiment with that.
this.output = 2 / (1 + Math.exp(-2 * input)) - 1;

Categories

Resources