Skip to content

Generalize injection in layer outputs for non-linear architectures #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
nniranjhana opened this issue May 21, 2021 · 0 comments
Open
Labels
enhancement New feature or request

Comments

@nniranjhana
Copy link
Collaborator

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:

Screenshot from 2021-05-21 13-28-18

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:

Screenshot from 2021-05-21 13-37-28

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant