import numpy as np
from keras.models import Sequential
from keras.layers import LSTM, Dense, Dropout

def visualize_training_results(results):
    """
    Plots the loss and accuracy for the training and testing data
    """
    history = results.history
    plt.figure(figsize=(12,4))
    plt.plot(history['val_loss'])
    plt.plot(history['loss'])
    plt.legend(['val_loss', 'loss'])
    plt.title('Loss')
    plt.xlabel('Epochs')
    plt.ylabel('Loss')
    plt.show()
    
    plt.figure(figsize=(12,4))
    plt.plot(history['val_accuracy'])
    plt.plot(history['accuracy'])
    plt.legend(['val_accuracy', 'accuracy'])
    plt.title('Accuracy')
    plt.xlabel('Epochs')
    plt.ylabel('Accuracy')
    plt.show()
    
    
def split_sequence(seq, n_steps_in, n_steps_out):
    """
    Splits the univariate time sequence
    """
    X, y = [], []
    
    for i in range(len(seq)):
        end = i + n_steps_in
        out_end = end + n_steps_out
        
        if out_end > len(seq):
            break
        
        seq_x, seq_y = seq[i:end], seq[end:out_end]
        
        X.append(seq_x)
        y.append(seq_y)
    
    return np.array(X), np.array(y)


def layer_maker(n_layers, n_nodes, activation, drop=None, d_rate=.5):
    """
    Create a specified number of hidden layers for an RNN
    Optional: Adds regularization option, dropout layer to prevent potential overfitting if necessary
    """
    model = Sequential()
    # Creating the specified number of hidden layers with the specified number of nodes
    for x in range(1,n_layers+1):
        model.add(LSTM(n_nodes, activation=activation, return_sequences=True))

        # Adds a Dropout layer after every Nth hidden layer (the 'drop' variable)
        try:
            if x % drop == 0:
                model.add(Dropout(d_rate))
        except:
            pass

[((1429, 1441), 'keras.models.Sequential', 'Sequential', ([], {}), '()\n', (1439, 1441), False, 'from keras.models import Sequential\n'), ((1144, 1155), 'numpy.array', 'np.array', (['X'], {}), '(X)\n', (1152, 1155), True, 'import numpy as np\n'), ((1157, 1168), 'numpy.array', 'np.array', (['y'], {}), '(y)\n', (1165, 1168), True, 'import numpy as np\n'), ((1582, 1641), 'keras.layers.LSTM', 'LSTM', (['n_nodes'], {'activation': 'activation', 'return_sequences': '(True)'}), '(n_nodes, activation=activation, return_sequences=True)\n', (1586, 1641), False, 'from keras.layers import LSTM, Dense, Dropout\n'), ((1795, 1810), 'keras.layers.Dropout', 'Dropout', (['d_rate'], {}), '(d_rate)\n', (1802, 1810), False, 'from keras.layers import LSTM, Dense, Dropout\n')]