import numpy as np
np.random.seed(1337)
import datetime
from IPython.display import SVG
from keras.datasets import mnist
from keras import activations
from keras.layers import Dense, Input, concatenate, Conv1D, Conv2D, Dropout, MaxPooling1D, MaxPooling2D
from keras.layers import Dense, Flatten
from keras.models import Sequential, load_model
from keras.utils import plot_model
from keras.utils.vis_utils import model_to_dot
from matplotlib import gridspec
from matplotlib.ticker import NullFormatter, NullLocator, MultipleLocator
from scipy import stats
from sklearn.metrics import auc, roc_curve
from sklearn.model_selection import train_test_split
from vis.utils import utils
from vis.visualization import visualize_activation
from vis.visualization import visualize_saliency
import datetime
import keras
import matplotlib.pylab as plt
import pandas as pd
import seaborn as sns
import talos as ta
sns.set_palette('husl')
sns.set(style='ticks')

%matplotlib inline
plt.rcParams["figure.figsize"] = [17, 17]

"""
Explanation: Keras models visualizations
End of explanation
"""


num_classes = 2
model = Sequential()
model.add(Conv1D(32, (5), strides = (1), input_shape = (18, 1), activation = 'tanh'))
model.add(MaxPooling1D(pool_size = (2), strides = (2)))
model.add(Conv1D(32, (3), strides = (1), input_shape = (18, 1), activation = 'tanh'))
model.add(Flatten())
model.add(Dense(300,                                            activation = 'tanh'))
model.add(Dropout(rate = 0.5))
model.add(Dense(300,                                            activation = 'tanh'))
model.add(Dropout(rate = 0.5))
model.add(Dense(num_classes,                                    activation = 'softmax', name = "preds"))
model.compile(loss="categorical_crossentropy", optimizer="nadam", metrics=['accuracy'])

"""
Explanation: For the purposes of this notebook, a simple model is constructed.
End of explanation
"""


checkpoint = keras.callbacks.ModelCheckpoint(
    filepath       = 'best_model.{epoch:02d}-{val_loss:.2f}.h5',
    monitor        = 'val_loss',
    save_best_only = True
)

"""
Explanation: Model checkpoints can be saved during training. They are usually saved in the HDF5 format.
A callback to make regular saves of a model to separate files could be something like the following:
End of explanation
"""


checkpoint = keras.callbacks.ModelCheckpoint(
    filepath       = 'model_latest.h5',
    monitor        = 'val_loss',
    save_best_only = True
)

"""
Explanation: To save only the latest model in training, something like the following callback could be used:
End of explanation
"""


from keras.models import load_model
model = load_model('model_latest.h5')

"""
Explanation: A saved HDF5 file can be loaded as a model in a way like the following:
End of explanation
"""


model.summary()

"""
Explanation: A model can be summarized in a way like the following:
End of explanation
"""


SVG(model_to_dot(model).create(prog='dot', format='svg'))

"""
Explanation: An SVG of the model can be displayed in Jupyter in a way like the following:
End of explanation
"""


model.layers

"""
Explanation: The layers of a model can be accessed:
End of explanation
"""


model.layers[8].get_config()

"""
Explanation: The configuration of an individual layer can be inspected:
End of explanation
"""


index = 0
plt.imshow(model.layers[index].get_weights()[0].squeeze(), cmap='gray')
plt.title(model.layers[index].get_config()['name']);

index = 4
plt.imshow(model.layers[index].get_weights()[0].squeeze(), cmap='gray')
plt.title(model.layers[index].get_config()['name']);

"""
Explanation: The weights of individual layers can be accessed and visualized:
End of explanation
"""


