Skip to main content

πŸ”¨ Chapter VI - Curb Your Enthusiasm

Remember that big warn in Chapter II about extensions' determinism?

elephant.jpeg

"different copies of an elephant in the room, futuristic scene, simple colors and shapes, retro futurism old poster"

The problem...​

The brain.js library is not deterministic by default. You can easily verify it by yourself - training the network with the same input will each time produce a slightly different network state.
Or you can try to call predict with the exact same input on the same model - each time the result will be slightly different.

LSTM models, like most neural networks, rely on random weight initialization and stochastic gradient descent (watch the Prerequisites videos...) during the training process. These random elements make it difficult to achieve a deterministic training process.

...and how to fix it.​

But we won't give up that easily!

Let's drill down a little further. The source of non-determinism in the brain.js library comes from using Math.random: img.png

- e.g. in the shuffleArray function which is used by the train function.

This can be fixed - we need to set a seed for the random number generator. Let's first add seedrandom library:

npm install --save seedrandom

The easiest way to seed the Math.random is to call:

import seedrandom from 'seedrandom';

Math.random = seedrandom(contractTxId);

BUT - as the seedrandom library warns:

caution

calling Math.seedrandom('constant') without new will make Math.random() predictable globally, which is intended to be useful for derandomizing code for testing, but should not be done in a production library. If you need a local seeded PRNG, use myrng = new Math.seedrandom('seed') instead.

So this solution is good for making some local tests or using it in a fully isolated environment (e.g. the way how the D.R.E. nodes are evaluating the contracts - each evaluation happens in a forked node process with a separate V8 instance).

The ultimate solution would be to fork the brain.js library and add an option of passing a custom PRNG in the neural network constructor.