# compile our model
print("[INFO] compiling model...")
opt = Adam(lr=INIT_LR, decay=DEC)
model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["accuracy"])

# train the head of the network
print("[INFO] training head...")
H = model.fit_generator(trainAug.flow(trainX, trainY, batch_size=BS),
                        steps_per_epoch=len(trainX) // BS,
                        validation_data=(testX, testY),
                        validation_steps=len(testX) // BS,
                        epochs=EPOCHS)

# make predictions on the testing set
print("[INFO] evaluating network...")
predIdxs = model.predict(testX, batch_size=BS)

# for each image in the testing set we need to find the index of the label with corresponding largest predicted probability
predIdxs = np.argmax(predIdxs, axis=1)

# show a nicely formatted classification report
print(
    classification_report(testY.argmax(axis=1),
                          predIdxs,
                          target_names=lb.classes_))

# compute the confusion matrix and and use it to derive the raw accuracy, sensitivity, and specificity
cm = confusion_matrix(testY.argmax(axis=1), predIdxs)
total = sum(sum(cm))
acc = (cm[0, 0] + cm[1, 1]) / total
sensitivity = cm[0, 0] / (cm[0, 0] + cm[0, 1])
    # by looking at resnet.layers in the console
    partial_model = Model(inputs=resnet.input,
                          outputs=resnet.layers[175].output)

    # maybe useful when building your model
    # to look at the layers you're trying to copy
    print(partial_model.summary())

    # create an instance of our own model
    my_partial_resnet = TFResNet()

    # make a fake image
    X = np.random.random((1, 224, 224, 3))

    # get keras output
    keras_output = partial_model.predict(X)

    ### get my model output ###

    # init only the variables in our net
    init = tf.variables_initializer(my_partial_resnet.get_params())

    # note: starting a new session messes up the Keras model
    session = keras.backend.get_session()
    my_partial_resnet.set_session(session)
    session.run(init)

    # first, just make sure we can get any output
    first_output = my_partial_resnet.predict(X)
    print("first_output.shape:", first_output.shape)
def compute_ig_within_GRU(seq2seq,
                          decoder_states_container,
                          decoder_inputs_container,
                          real_h,
                          target_gate="z",
                          target_class=[0],
                          reference=False,
                          k=32):
    """
	Compute ig within GRU for several gates.
	Arguments:
		decoder_states_container, decoder_inputs_container: For only one time step, the inputs of decoder GRU cell.
		target_gate: A list of {"h", "r", "z"}.
		target_class: A list of int.
	"""
    assert target_gate == "z" or target_gate == "r" or target_gate == "h", "No this gate."
    print("\nCompute on %s gate." % target_gate)
    weight = seq2seq.decoder_model.get_layer("decoder_gru").get_weights()
    emb_layer_model = Model(
        inputs=seq2seq.decoder_model.get_layer('decoder_emb').get_input_at(-1),
        outputs=seq2seq.decoder_model.get_layer('decoder_emb').output)
    inputs = np.squeeze(emb_layer_model.predict(decoder_inputs_container,
                                                verbose=0),
                        axis=1)
    states = np.copy(decoder_states_container)
    h_tm1, h, z, r, hh, x_h, split_recurrent_h = gruig.get_GRU_components(
        inputs, states, weight)
    weight_array = np.concatenate(
        [weight[0], weight[1],
         np.expand_dims(weight[2], axis=0)], axis=0)
    units = seq2seq.units
    if target_gate == "h":
        gate_model = gruig.build_GRU_with_h_gate_model(seq2seq)
        gate_model.get_layer("wx_h").set_weights(
            [weight[0][:, units * 2:], weight[2][units * 2:]])
        gate_model.get_layer("uh_h").set_weights([weight[1][:, units * 2:]])
        y = gate_model.predict([h_tm1, inputs, z, r], steps=1)
        feed_dict = {
            gate_model.input[1]: inputs,
            gate_model.input[2]: z,
            gate_model.input[3]: r,
        }
        real = real_h
    elif target_gate == "z":
        gate_model = gruig.build_GRU_with_z_gate_model(seq2seq, weight_array)
        y = gate_model.predict([h_tm1, inputs, r, hh], steps=1)
        feed_dict = {
            gate_model.input[1]: inputs,
            gate_model.input[2]: r,
            gate_model.input[3]: hh
        }
        real = y
    elif target_gate == "r":
        gate_model = gruig.build_GRU_with_r_gate_model(seq2seq, weight_array)
        y = gate_model.predict([h_tm1, inputs, z, x_h, split_recurrent_h],
                               steps=1)
        feed_dict = {
            gate_model.input[1]: inputs,
            gate_model.input[2]: z,
            gate_model.input[3]: x_h,
            gate_model.input[4]: split_recurrent_h
        }
        real = y
    assert np.mean(
        np.abs(y -
               real)) < 1e-6, "Wrong computation for error = %.8f" % np.mean(
                   np.abs(y - real))
    print("delta =", np.mean(np.abs(y - real)))
    #assert np.mean(np.abs(y - h)) < 1e-6, "Wrong computation for error = %.8f" % np.mean(np.abs(y - h))

    interpolate, num_steps, step_size = linearly_interpolate(
        decoder_states_container)  # (50, N, 10), int, (N, 10)
    result = np.zeros(decoder_states_container.shape)  # (N, 256),
    total_result = np.zeros(decoder_states_container.shape)
    sess = K.get_session()

    for class_ in target_class:
        print("Class index =", class_)
        gradient = gradients(gate_model.output[:, class_], gate_model.input[0])
        result = np.zeros(decoder_states_container.shape)
        for i in range(num_steps):
            feed_dict[gate_model.input[0]] = interpolate[i]
            x = sess.run(gradient[0], feed_dict=feed_dict)
            result += x
        result = np.multiply(result, step_size)
        """if target_gate == "h":
			score = np.abs(np.mean(result, axis=0))
			print("selected =", list(np.argsort(score)[::-1][:k]))
			print("other =", list(np.argsort(score)[::-1][k:]))
			print(np.sort(score)[::-1][:4])	"""
        total_result += result
    total_result /= float(len(target_class))
    score = np.abs(np.mean(total_result, axis=0))
    print("(total) selected =", list(np.argsort(score)[::-1][:k]))
    #print("other =", list(np.argsort(score)[::-1][k:]))
    print(np.sort(score)[::-1][:4])
    return score