-
Notifications
You must be signed in to change notification settings - Fork 0
/
SingleInDepthAnalysis.py
93 lines (78 loc) · 4.04 KB
/
SingleInDepthAnalysis.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
import keras.models
from keras.optimizers import Adam
from keras.utils import np_utils
import innvestigate
soi_I = 1342 #sample of interest Index, correspinds to sample 4WM7aZDLCmlosUBiqKOx in MITestArr.csv
print("Loading data...")
x_test = pd.read_csv("MITestArr.csv", header=None, dtype=int).to_numpy(dtype=int)
y_test_1 = pd.read_csv("MITestLbs.csv", header=None, dtype=int).to_numpy(dtype=int) #labels in range 1-9
encoder = LabelEncoder()
encoder.fit(y_test_1)
y_test_0 = encoder.transform(y_test_1) #make labels in range 0-8
y_test_OHE = np_utils.to_categorical(y_test_0) #make one hot encoded label vectors
print("Data loaded!")
print("Loading Model")
json_file = open('NNmodelBest.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
model = keras.models.model_from_json(loaded_model_json)
model.load_weights("NNweightsBest.hdf5")
print("Loaded model from disk")
model.compile(loss="categorical_crossentropy",
optimizer=Adam(lr=0.001, epsilon=0.0001),
metrics=["accuracy"])
#make a model from just the first two layers (inlcuding input layer) of the original model
trunc_model1 = keras.models.Model(inputs=model.input,
outputs=model.get_layer('dense_1').output)
tm_output = trunc_model1.predict(x_test[soi_I:soi_I+1]) #get original model's hiddin layer activations for specific input
#generate model equivalent to the last layer of the original model
model2 = keras.models.Sequential([
model.get_layer('dense_2')
])
model2.compile(loss="categorical_crossentropy",
optimizer=Adam(lr=0.001, decay=0.0, amsgrad=True),
metrics=["categorical_accuracy"])
model2.build((None,40))
#if the print statments below have the same output, then model2 is equivalent to the last layer of the original model
#and trunc_model1 is the equivalent of the input and hidden layer of the original model
print("Check: The following arrays should be identicle.")
print(model2.predict_proba(tm_output))
print(model.predict_proba(x_test[soi_I:soi_I+1]),"\n")
#generate internal node analysis and save it along with internal node inputs
analyzer = innvestigate.create_analyzer("lrp.epsilon", model2)
a = analyzer.analyze(tm_output)
fp = open("midrelevances.csv","w")
for i in range(len(a[0])):
fp.write(str(tm_output[0][i])+","+str(a[0][i])+"\n")
fp.close()
print("Internal relevances for x_test["+str(soi_I)+"] saved to file: midrelevances.csv")
#create model that is duplicate of input and first hidden layer in original model, except all but one node is removed from the hidden layer
#the remianing node is the one we wish to interpret
nti = 39 #the node to interpret in the hidden layer (indexed 0 to 39)
#create model with 9980 input nodes and just one node in the next layer
model3 = keras.models.Sequential([
keras.layers.Dense(1, activation="tanh", use_bias=False),
])
model3.compile(loss="categorical_crossentropy",
optimizer=Adam(lr=0.001, decay=0.0, amsgrad=True),
metrics=["categorical_accuracy"])
model3.build((None,9980))
#use weights from original model in the connectes between the first layer and the node we wish to interpret in the hidden layer
weights = model.get_layer('dense_1').get_weights()
weights = np.reshape(np.array(weights[0]).T[nti], (9980,1))
model3.get_layer('dense_1').set_weights(np.array([weights]))
#if the print statments below have the same output, then model3 is equivalent to the first two layers of the original model if all but one node was removed from the second layer
print("Check: The following numbers should be identicle.")
print(tm_output[0][nti])
print(model3.predict(x_test[soi_I:soi_I+1])[0][0])
#generate input layer node analysis (using only one node from the hidden layer to generate relevances) and save it along with the input to the input layer
analyzer = innvestigate.create_analyzer("lrp.epsilon", model3)
a = analyzer.analyze(x_test[soi_I:soi_I+1])
fp = open("firstrelevances.csv","w")
for i in range(len(a[0])):
fp.write(str(x_test[soi_I][i])+","+str(a[0][i])+"\n")
fp.close()
print("first layer relevances saved to file: first.csv")