BindsNET/bindsnet

Network converted from ANN doesn't retain weights after training?

0xnurl opened this issue · 3 comments

First of all thank you so much for this very impressive project!

My current process:

  1. Build a deep ANN using a regular PyTorch module.
  2. Convert the ANN to SNN using bindsnet.conversion.ann_to_snn().
  3. Train the SNN using Network.run()

For training, I am following the training and test methods in examples/eth_mnist.py.
For conversion from ANN to SNN, I am following this conversion example script.

The SNN seems to learn something, and reaches ~50% accuracy on MNIST.

However, the SNN doesn't seem to retain the weights learned while running Network.run(). When I test or retrain the SNN, it resets to the same performance it had before running run().

I am attaching a minimal reproduction script. The critical part is that after running _train_snn() for the second time, the performace resets and progresses in the same way as it did during the first training.

More details:

  • I am running the SNN training on the exact same data in both times.
  • If the ANN is trained before conversion to SNN, the weights of the ANN are retained (but the network still doesn't improve after training as an SNN)

Thank you in advance for any help!

bindnset_issue.py.txt

Thank you for using BindsNET.
I'm a little confused, are you training the SNN twice?

The conversion process should be:

  1. Build an ANN using a regular PyTorch module and train it using your favorite gradient descent method.
  2. Building an SNN with the same topology as the ANN from the previous step.
  3. Converting the ANN weights to the equivalent range for SNN from the previous step.
  4. Testing SNN on the testing data.

Note

  1. when the training/conversion process finish, use network. train(mode=False) to freeze the weights.
  2. ANN conversion to SNN should be used only once, running the code twice can lead to unexpected results. If the conversion wasn't successful the first time, some parameters need to be changed, and the process need to be started again.

ps. The script that you are using to convert the network is not updated and is not part of the supported code in BindsNET. The code you are using probably contain some code that needs to be update. With that said, I will be happy to help you use it, and hopefully, you can help by contributing your time to fix some of the small kinks that exist in the BindsNET code.

Thanks Hananel for the very quick reply!

We're not training the SNN twice. We're just using the ANN->SNN conversion as a way to build a deep SNN architecture. We couldn't find an example of a multilayer architecture in your example, so we've been using this method. Does this make sense?

So our process is:

  1. Build multilayer ANN in PyTorch.
  2. Convert to SNN using bindsnet.conversion.ann_to_snn()
  3. Train SNN as in your examples (eth_mnist.py)

So basically this should work right? The problem is that after step 3, the SNN doesn't seem to retain the weights.

Re: unsupported code, yes I'm aware of that and even opened a pull request to update the external script.
However, the conversion module is part of the BindsNET package, so should be supported, right?

Any help would be much appreciated.
Thanks again!

If I'm not mistaken (I didnt use this part of the code for a long time) the method bindsnet.conversion.ann_to_snn() assume that the given ANN is already fully trained. The result of this method is an equivalent SNN that should perform similarly to the ANN.
The only training here should be performed on the ANN, not the SNN. Therefore, step three is not relevant.

About the PR, if the code work on the main BindsNET, I will be glad if you submit it to this repository, with only one request, you will help in the future to update the code if necessary to new upcoming changes in PyTorch/BindsNET.