Hello @drasmuss ,
Below is the entire code which I took from https://www.nengo.ai/nengo-dl/examples/tensorflow-models.html and modified. It includes nengo_dl simulation and nengo_loihi simulation.
import tensorflow as tf
import os
import sys
import time
import pickle
import numpy as np
import nengo
import nengo_dl
import nengo_loihi
def classification_accuracy(y_true, y_pred):
return 100 * tf.metrics.sparse_categorical_accuracy(
y_true[:, -1], y_pred[:, -1])
def simple_cnn(original_shape, input_shape, output_shape, padding='valid'):
inp = tf.keras.Input(input_shape)
y = tf.keras.layers.Reshape(original_shape)(inp)
y = tf.keras.layers.Conv2D(32, (3, 3), padding=padding, activation=tf.nn.relu, use_bias=False)(y)
# y = nengo_dl.Layer(nengo.SpikingRectifiedLinear(amplitude=1))(y)
# activation=tf.nn.relu,
y = tf.keras.layers.Conv2D(32, (3, 3), padding=padding, activation=tf.nn.relu, use_bias=False)(y)
y = tf.keras.layers.AveragePooling2D(pool_size=(2, 2))(y)
y = tf.keras.layers.Conv2D(64, (3, 3), padding=padding, activation=tf.nn.relu, use_bias=False)(y)
y = tf.keras.layers.Conv2D(64, (3, 3), padding=padding, activation=tf.nn.relu, use_bias=False)(y)
y = tf.keras.layers.GlobalAveragePooling2D()(y)
y = tf.keras.layers.Flatten()(y)
y = tf.keras.layers.Dense(256, use_bias=False, activation=tf.nn.relu, )(y)
out = tf.keras.layers.Dense(output_shape, use_bias=False)(y)
model = tf.keras.Model(inputs=inp, outputs=out)
model.summary()
model.compile(optimizer=tf.optimizers.Adam(),
loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=["accuracy"])
return model
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
original_shape = x_train.shape[1:]
minibatch_size = 200
x_train = x_train.reshape((x_train.shape[0], -1))
x_test = x_test.reshape((x_test.shape[0], -1))
input_shape = x_train.shape[1:]
output_shape = 10
model = simple_cnn(original_shape, input_shape, output_shape, padding='valid')
# model.load_weights('weight.h5')
model.fit(x_train, y_train,
# validation_split=0.2,
verbose=1,
batch_size=minibatch_size,
epochs=100)
model.save('weight.h5')
print("Test accuracy:", model.evaluate(x_test, y_test, verbose=0)[1])
n_steps = 30
x_test = np.tile(x_test[:, None, :], (1, n_steps, 1))
y_test = np.tile(y_test[:, :, None], (1, n_steps, 1))
nengo_converter = nengo_dl.Converter(model, allow_fallback=False)
out_p = nengo_converter.net.probes[0]
with nengo_dl.Simulator(nengo_converter.net, minibatch_size=minibatch_size) as sim:
sim.compile(loss={out_p: classification_accuracy})
print("accuracy with ReLU: %.2f%%" %
sim.evaluate(
x_test, {out_p: y_test}, verbose=0)["loss"])
nengo_converter = nengo_dl.Converter(model, allow_fallback=False,
swap_activations={nengo.RectifiedLinear(): nengo.SpikingRectifiedLinear()})
out_p = nengo_converter.net.probes[0]
for ensemble in nengo_converter.net.ensembles:
print(ensemble, ensemble.neuron_type)
with nengo_dl.Simulator(nengo_converter.net, minibatch_size=minibatch_size) as sim:
sim.compile(loss={out_p: classification_accuracy})
print("accuracy with Spiking ReLU: %.2f%%" %
sim.evaluate(
x_test, {out_p: y_test}, verbose=0)["loss"])
dt = 0.001
presentation_time = 0.1
n_presentations = 50
nengo_loihi.add_params(nengo_converter.net)
layer_ens = nengo_converter.layer_map[model.layers[2]][0][0]
nengo_converter.net.config[layer_ens.ensemble].on_chip = False
hw_opts = dict(snip_max_spikes_per_step=120)
with nengo_loihi.Simulator(
nengo_converter.net, dt=dt, precompute=False, hardware_options=hw_opts, remove_passthrough=False
) as sim:
# run the simulation on Loihi
sim.run(n_presentations * presentation_time)
# check classification accuracy
step = int(presentation_time / dt)
output = sim.data[out_p][step - 1::step]
correct = 100 * np.mean(
np.argmax(output, axis=-1)
== test_labels[:n_presentations, -1, 0]
)
print("loihi accuracy: %.2f%%" % correct)
Here is the output:
Test accuracy: 0.7593
......
accuracy with ReLU: 75.93%
<Ensemble "conv2d.0"> SpikingRectifiedLinear()
<Ensemble "conv2d_1.0"> SpikingRectifiedLinear()
<Ensemble "conv2d_2.0"> SpikingRectifiedLinear()
<Ensemble "conv2d_3.0"> SpikingRectifiedLinear()
<Ensemble "dense.0"> SpikingRectifiedLinear()
......
Optimizing graph: creating signals finished in 0:00:00
Optimization finished in 0:00:00
accuracy with Spiking ReLU: 10.00%
Traceback (most recent call last):
File "/loihi_error_reproduce.py", line 93, in <module>
nengo_converter.net, dt=dt, precompute=False, hardware_options=hw_opts, remove_passthrough=False
File "/usr/local/lib/python3.6/dist-packages/nengo_loihi/simulator.py", line 145, in __init__
self.model.build(network)
File "/usr/local/lib/python3.6/dist-packages/nengo_loihi/builder/builder.py", line 208, in build
built = model.builder.build(model, obj, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/nengo/builder/builder.py", line 242, in build
return cls.builders[obj_cls](model, obj, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/nengo/builder/network.py", line 94, in build_network
model.build(conn)
File "/usr/local/lib/python3.6/dist-packages/nengo_loihi/builder/builder.py", line 208, in build
built = model.builder.build(model, obj, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/nengo/builder/builder.py", line 242, in build
return cls.builders[obj_cls](model, obj, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/nengo_loihi/builder/connection.py", line 65, in build_connection
build_host_to_chip(model, conn)
File "/usr/local/lib/python3.6/dist-packages/nengo_loihi/builder/connection.py", line 133, in build_host_to_chip
"Conv2D transforms not supported for off-chip to "
nengo.exceptions.BuildError: Conv2D transforms not supported for off-chip to on-chip connections where `pre` is not a Neurons object.
After swapping activation functions from ReLU to spiking ReLU, the model’s test accuracy decreased from 0.759 to 0.1. I guess after the swapping the model needs to be retrained, or it should use spiking ReLU to replace ReLU before training.
Also, I added the following lines of code
nengo_loihi.add_params(nengo_converter.net)
layer_ens = nengo_converter.layer_map[model.layers[2]][0][0]
nengo_converter.net.config[layer_ens.ensemble].on_chip = False
but still the loihi simulator raised the error. I have removed all bias terms in the model and used valid padding. Could you advise me where in the code I should modify? Thank you very much.
Will