Presently, the injector architecture for layer outputs works with linear models as during run-time, the execution stops at the chosen layer n, injects faults into that layer and continues with the next n+1 layer. Suppose that the n layer outputs feed back into n-1 layer (a non-linear connection), the current design would not handle that.
We have a workaround for such a non-linear architecture such as the SqueezeNet model which looks like so:

where the fire modules consist of "squeeze" and "expand" layers, with the expand layers splitting into two parallel convolutional layers of different left (1x1) and right (3x3) filters:

Keras stores all layers in order so the left and right layers are also stored with serial consecutive indices. This means for certain n layers in the fire modules, the outputs feed into two parallel layers n1 + 1 and n2 + 1 and so we manually figured out the exception layers and handled the four cases like so:
while(True):
randnum = random.randint(0, len(model.layers) - 2)
mid_layer = model.layers[randnum]
get_output = K.function([model.layers[0].input], [mid_layer.output])
mid_layer_outputs = get_output([x_test])
elem_shape = mid_layer_outputs[0].shape
mid_layer_outputs[0] = mid_layer_outputs[0].flatten()
num = mid_layer_outputs[0].shape[0]
if(num >= sz):
break
ind = random.sample(range(num), sz)
for item in ind:
val = mid_layer_outputs[0][item]
pos = random.randint(0, 31)
val_ = bitflip(val, pos)
mid_layer_outputs[0][item] = val_
mid_layer_outputs[0] = mid_layer_outputs[0].reshape(elem_shape)
if (randnum in [6, 13, 21, 28, 36, 43, 50, 57]):
get_output2 = K.function([model.layers[0].input], [model.layers[randnum + 1].output])
ff_mlo = get_output2([x_test])
get_pred1 = K.function([model.layers[randnum + 2].input], [model.layers[randnum + 2].output])
pred1 = get_pred1([mid_layer_outputs]);pred10 = get_pred1([ff_mlo])
get_pred2 = K.function([model.layers[randnum + 4].input], [model.layers[-1].output])
pred = get_pred2([pred1, pred10]);
elif (randnum in [7, 14, 22, 29, 37, 44, 51, 58]):
get_output2 = K.function([model.layers[0].input], [model.layers[randnum - 1].output])
ff_mlo = get_output2([x_test])
get_pred1 = K.function([model.layers[randnum + 2].input], [model.layers[randnum + 2].output])
pred1 = get_pred1([mid_layer_outputs]);pred10 = get_pred1([ff_mlo])
get_pred2 = K.function([model.layers[randnum + 3].input], [model.layers[-1].output])
pred = get_pred2([pred1, pred10]);
elif (randnum in [8, 15, 23, 30, 38, 45, 52, 59]):
get_output2 = K.function([model.layers[0].input], [model.layers[randnum + 1].output])
ff_mlo = get_output2([x_test])
get_pred2 = K.function([model.layers[randnum + 2].input], [model.layers[-1].output])
pred = get_pred2([mid_layer_outputs, ff_mlo]);
elif (randnum in [9, 16, 24, 31, 39, 46, 53, 60]):
get_output2 = K.function([model.layers[0].input], [model.layers[randnum - 1].output])
ff_mlo = get_output2([x_test])
get_pred2 = K.function([model.layers[randnum + 1].input], [model.layers[-1].output])
pred = get_pred2([mid_layer_outputs, ff_mlo]);
else:
get_pred = K.function([model.layers[randnum + 1].input], [model.layers[-1].output])
pred = get_pred([mid_layer_outputs])
return pred
Obviously, this is cumbersome to figure out and be done for each non-linear architecture. Hence we need a way to generalize - this could be using the inbound nodes of the Keras layers so we know which layers to connect to during dynamic injection at any layer.
Presently, the injector architecture for layer outputs works with linear models as during run-time, the execution stops at the chosen layer
n, injects faults into that layer and continues with the nextn+1layer. Suppose that thenlayer outputs feed back inton-1layer (a non-linear connection), the current design would not handle that.We have a workaround for such a non-linear architecture such as the SqueezeNet model which looks like so:
where the fire modules consist of "squeeze" and "expand" layers, with the expand layers splitting into two parallel convolutional layers of different left (1x1) and right (3x3) filters:
Keras stores all layers in order so the left and right layers are also stored with serial consecutive indices. This means for certain
nlayers in the fire modules, the outputs feed into two parallel layersn1 + 1andn2 + 1and so we manually figured out the exception layers and handled the four cases like so:Obviously, this is cumbersome to figure out and be done for each non-linear architecture. Hence we need a way to generalize - this could be using the inbound nodes of the Keras layers so we know which layers to connect to during dynamic injection at any layer.