Skip to content

Commit

Permalink
The new network, set to incorporate different paths of the same quest…
Browse files Browse the repository at this point in the history
…ion in one go and output a softmax over the candidates.

INCOMPLETE - Still working on manipulating the matrices to fit the model inputs and outputs.
  • Loading branch information
geraltofrivia committed Dec 19, 2017
1 parent 07e3c4a commit 46802d1
Showing 1 changed file with 74 additions and 23 deletions.
97 changes: 74 additions & 23 deletions network.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers.recurrent import LSTM
from keras.layers.merge import concatenate
from keras import optimizers, metrics


# Some Macros
DATA_DIR = './data/training/multi_path_mini'
EPOCHS = 50
EPOCHS = 60

'''
F1 measure
F1 measure functions
'''


def recall(y_true, y_pred):
"""Recall metric.
Only computes a batch-wise average of recall.
Expand All @@ -29,6 +32,7 @@ def recall(y_true, y_pred):
recall = true_positives / (possible_positives + K.epsilon())
return recall


def fbeta_score(y_true, y_pred, beta=1):
"""Computes the F score.
The F score is the weighted harmonic mean of precision and recall.
Expand Down Expand Up @@ -57,6 +61,7 @@ def fbeta_score(y_true, y_pred, beta=1):
fbeta_score = (1 + bb) * (p * r) / (bb * p + r + K.epsilon())
return fbeta_score


def precision(y_true, y_pred):
"""Precision metric.
Only computes a batch-wise average of precision.
Expand All @@ -68,11 +73,14 @@ def precision(y_true, y_pred):
precision = true_positives / (predicted_positives + K.epsilon())
return true_positives


def true_positives(y_true, y_pred):
return K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
return K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))


def predicted_positives(y_true, y_pred):
return K.sum(K.round(K.clip(y_pred, 0, 1)))
return K.sum(K.round(K.clip(y_pred, 0, 1)))


def fmeasure(y_true, y_pred):
"""Computes the f-measure, the harmonic mean of precision and recall.
Expand All @@ -81,7 +89,6 @@ def fmeasure(y_true, y_pred):
return fbeta_score(y_true, y_pred, beta=1)



def smart_save_model(model):
"""
Function to properly save the model to disk.
Expand Down Expand Up @@ -125,6 +132,12 @@ def smart_save_model(model):
x_q = np.load(open(DATA_DIR + '/Q.npz'))
y = np.load(open(DATA_DIR + '/Y.npz'))

# Shuffle these matrices together @TODO this!
indices = np.random.permutation(x_p.shape[0])
x_p = x_p[indices]
x_q = x_q[indices]
y = y[indices]

# Divide the data into diff blocks
x_path_train = np.asarray(x_p[:int(len(x_p) * .80)]).astype('float32')
y_train = np.asarray(y[:int(len(y) * .80)]).astype('float32')
Expand All @@ -133,36 +146,74 @@ def smart_save_model(model):
q_path_train = np.asarray(x_q[:int(len(x_q) * .80)]).astype('float32')
q_path_test = np.asarray(x_q[int(len(x_q) * .80):]).astype('float32')

path_input_shape = x_path_train.shape[1:]
question_input_shape = q_path_train.shape[1:]
path_input_shape = x_path_train.shape[2:]


"""
Model Time!
"""
# Encode the pos and neg path using the same path encoder and also the question
x_ques = Input(shape=path_input_shape)
ques_encoder = LSTM(64)(x_ques)
x_path = Input(shape=question_input_shape)
path_encoder = LSTM(64)(x_path)
# Define input to the models
x_ques = Input(shape=question_input_shape)
x_paths = [ Input(shape=path_input_shape) for x in range(x_path_train.shape[1])]

# Concatenate question with the two paths
merge = concatenate([ques_encoder, path_encoder])
# Encode the question
ques_encoded = LSTM(64)(x_ques)

# Encode 21 paths
path_encoder = LSTM(64)
path_encoded = [path_encoder(x) for x in x_paths]

# For every path, concatenate question with the path
merges = [concatenate([ques_encoded, x]) for x in path_encoded]

# First Dense layers over these 128,_ tensors
dense_1 = Dense(64, activation='relu')
dense_1_outputs = [dense_1(x) for x in merges]

# Dropout time
dropout = Dropout(0.5)
dropout_outputs = [dropout(x) for x in dense_1_outputs]

# Merge these sons of bitches into one tensor of 64 x 21
merged_tensor = concatenate(dropout_outputs)

# Final Dense (Output layer)soft
output = Dense(x_path_train.shape[1], activation='softmax')(merged_tensor)

output = Dense(1, activation='sigmoid')(merge)

"""
Run Time!
"""
# Prepare input tensors
inputs = [x_ques] + x_paths

# Model time!
model = Model(inputs=[x_ques,x_path], outputs=output)
model = Model(inputs=inputs, outputs=output)

print(model.summary())

model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])

model.fit([x_path_train, q_path_train], y_train, batch_size=1, epochs=EPOCHS)

smart_save_model(model)

model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=[fmeasure, 'accuracy'])

# Prepare training data
# x_path_train = np.swapaxes(x_path_train, 0, 1)

# Breaking the 21 different paths
# x_path_train = [ x_path_train[i] for i in range(x_path_train.shape[0])]
# x_path_train.append(q_path_train)

# training_input = [q_path_train] + [x for x in x_path_train]

# model.fit(training_input, y_train, batch_size=1, epochs=EPOCHS)
#
# # smart_save_model(model)
#
# # Prepare test data
# x_path_test = np.swapaxes(x_path_test, 0, 1)
# testing_input = [q_path_test] + [x for x in x_path_test] # x_p_test = 21, 89, 23, 300
#
# model.evaluate(testing_input, y_test)
#
#

0 comments on commit 46802d1

Please sign in to comment.