brain icon indicating copy to clipboard operation
brain copied to clipboard

New training option

Open antoniodeluca opened this issue 10 years ago • 20 comments

Added a new training option that enable users to specify if the weights of the neural network have to be (re)initialized or not. This is very useful when an user wants to call more time the neural network training method or for any other reason for which one doesn't want that weights change.

antoniodeluca avatar May 14 '15 17:05 antoniodeluca

@antoniodeluca , if this does what I think it does, you're my hero!

Say I've been training a net for 2 days, and it's 84 iterations in by this point (turns out understanding human attraction is rather complex, even for a computer). I'd love to be able to train that same net even more at some point in the future, to take advantage of the two days worth of work that has already gone into training it.

If your PR does that, I'd be super happy! I'd been debating how complex this would be to implement myself; I'm glad I bothered checking out the PRs here to find you've already figured it out, and see that the tests for this are longer than the source code!

ClimbsRocks avatar Oct 04 '15 19:10 ClimbsRocks

@ClimbsRocks , yes it does exactly what you need. Hope it will help you.

antoniodeluca avatar Oct 08 '15 21:10 antoniodeluca

It already is! I created GridSearch for this library, and then at the end, I wanted to train the best classifier for significantly longer. Allowing the classifier to warm start at the point it had previously trained to has been awesome!

It's part of a larger project, but I hope to spin gridSearch out into it's own repo pretty soon to make harthur's awesome brainjs even more accessible to developers. I love her philosophy of abstracting away complexity, which pretty directly contrasts with scikit-learn's approach. I'm actually trying to build out my project to take that philosophy of avoiding unnecessary complexity to an even higher level.

Thanks again for this critical component of it!

ClimbsRocks avatar Oct 08 '15 23:10 ClimbsRocks

Thanks a lot, I'll need this too and I prefer this as using streams or anything. gotta be useful in my IA development. You made my day.

Archivist062 avatar Oct 11 '15 18:10 Archivist062

For me this pull-request does not work. Here a simple example:

net.train([{input: [1, 1], output: [0]}]); //trains 1,1 => 0
net.runInput([1, 1]); //results 0.0702838678761908 => correct

net.train([{input: [1, 0], output: [1]}]); //trains 1,0 => 1
net.runInput([1, 1]); //results 0.850795812504698 => incorrect
net.runInput([1, 0]); //results 0.929557447931592 => correct

I've simply commented out this this.initialize() call, so it never gets initialized.

To me its seems a lot of iterations to learn the new 1,0 => 1 overwrite simply the learned 1,1=>0 as the result of the learning, not through resetting the weights.

marcj avatar Dec 31 '15 02:12 marcj

@marcj, your code is not working because you are not passing the "initialization" parameter. brainjs normally reinitializes the weights each time you call the train function (because the initialization parameter value defaults to "true"). If you want to preserve the weights for the next training sessions you should pass a "false" initialization parameter. This is not needed on the first training session because it is supposed that the first time you train the neural network the weights have to be initialized. You could see an example of the code looking into the commit test case. For brevity here are two little example snippets:

First training session

net.train(data, { errorThresh: 0.2, iterations: 100000 });

Second training session

net.train(data, { errorThresh: 0.2, iterations: 1, initialization: false })

antoniodeluca avatar Dec 31 '15 08:12 antoniodeluca

Well, as I said

I've simply commented out this this.initialize() call, so it never gets initialized.

What I mean with that is that I deleted the line this.initialize(sizes); manually, so the network.js does not reset anything when I call train(). so, there's no need to pass the "initialization" parameter. :) I tested with this your approach of being able to continue the learning process by skipping the reset/initialize method.

marcj avatar Dec 31 '15 14:12 marcj

Is there a reason why you only use one iteration for the second training? I guess with such low iterations the network has no chance to learn enough to get the errors low. Also with one iteration there's no need to pass any errorThreshold because the network has no chance to react with one iteration to a high error rate.

marcj avatar Dec 31 '15 14:12 marcj

@marcj, I do not think that the initialize function should be removed. It is very good to have an initialization function that properly represents a point in which the system prepares the data structures and does eventual needed tasks.

antoniodeluca avatar Jan 02 '16 08:01 antoniodeluca

@marcj, the second training is done with one iterarion just as an example. Sorry if the example was very minimalist. The intention was just to show the use of the initialization parameter. In your real scenario you have to do as many iterations as you need.

antoniodeluca avatar Jan 02 '16 08:01 antoniodeluca

Hi, I'm trying to use your patch with loading a neural network from a file first, however it fails with the error

rain/lib/neuralnetwork.js:180 this.errors[layer][node] = error; ^ TypeError: Cannot read property '3' of undefined

The way I am doing is to load the file with fromJSON and then running train() with the 'initialization' parameter set to false, but it doesn't seem to work.

Apparently some default values are set in the init method that is disabled.

What can I do?

Thanks

mindphlux1 avatar Jan 02 '16 14:01 mindphlux1

@antoniodeluca, well I called this.initialize() on my own in my userland code of course, so the network is initialized after is has been created.

Can you confirm this behavior of this code?

net.train([{input: [1, 1], output: [0]}]); //trains 1,1 => 0
net.runInput([1, 1]); //results 0.0702838678761908 => correct

net.train([{input: [1, 0], output: [1]}], {initialization: false}); //trains 1,0 => 1
net.runInput([1, 1]); //results 0.850795812504698 => incorrect
net.runInput([1, 0]); //results 0.929557447931592 => correct

marcj avatar Jan 02 '16 15:01 marcj

Would you consider closing this here, and reopening at: https://github.com/harthur-org/brain.js/pulls?

If so, we could add you as a collaborator.

robertleeplummerjr avatar Dec 21 '16 02:12 robertleeplummerjr

Yes, sure. I do it today or tomorrow.

antoniodeluca avatar Dec 21 '16 09:12 antoniodeluca

Sometime back I added a keepNetworkIntact argument, I believe it does exactly what you want: https://github.com/harthur-org/brain.js/blob/3843729dd0ae5cb8e6be21b6040c254a9fcf4e0b/src/neural-network.js#L41

robertleeplummerjr avatar Dec 21 '16 13:12 robertleeplummerjr

Usage example:

const net = brain.NeuralNetwork();
net.train([]);
//sometime later
net.train([], { keepNetworkIntact: true });

robertleeplummerjr avatar Dec 21 '16 13:12 robertleeplummerjr

Sometime back I added a keepNetworkIntact argument

I installed 'npm install brain.js' and these not have argument keepNetworkIntact. What?

Dok11 avatar Dec 22 '16 11:12 Dok11

We need to bump the version. In the meantime, can you install via: npm i https://github.com/harthur-org/brain.js.git?

robertleeplummerjr avatar Dec 22 '16 13:12 robertleeplummerjr

@robertleeplummerjr thank you, that's work, and arg 'keepNetworkIntact' too ok!

Dok11 avatar Dec 22 '16 15:12 Dok11

robertleeplummerjr avatar Dec 22 '16 16:12 robertleeplummerjr