# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# ### 1. Prepare data for ingestion into the neural network.

# +
import pandas as pd
import warnings

warnings.filterwarnings('ignore')
# -

apple_stock_df = pd.read_csv("./apple_stock_prepared.csv")
apple_stock_df.head()

X = apple_stock_df[apple_stock_df.columns[0:-1]]
Y = apple_stock_df[apple_stock_df.columns[-1]]

from sklearn.model_selection import train_test_split

import random
random.seed(100)

X_train, X_test, Y_train, Y_test = train_test_split(X,Y,test_size=0.2, random_state = 100)

X_val, X_test, Y_val, Y_test = train_test_split(X_test,Y_test,test_size=0.5, random_state = 100)

X_train.shape

X_test.shape

X_val.shape


def num_steps(length: int, batch_size: int):
    '''
    calculates number of steps from dataset and the batch size
    
    Parameters
    ----------
    
    length: the total length of the dataset
    batch_size: size of each batch
    
    Returns
    -------
    
    number_of_steps: number of steps per epoch
    
    '''
    return length//batch_size + 1


batch_size = 10
num_steps(len(X_train), batch_size)

# ### 2.  Define the neural network layers and model.

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras.optimizers import RMSprop


def stock_predictor_model(x_train):
    '''
    Define the stock predictor model
    '''
    stock_predictor = Sequential()
    # One Dense layer with number of units same as features
    stock_predictor.add(Dense(10, input_dim=x_train.shape[1],
                    activation='relu',
                    kernel_initializer='he_normal'))
    stock_predictor.add(Dense(6, input_dim=10,
                    activation='relu',
                    kernel_initializer='he_normal'))
    stock_predictor.add(Dense(3, input_dim=6,
                activation='relu',
                kernel_initializer='he_normal'))
    # Final dense layer
    stock_predictor.add(Dense(1, activation='relu',
                    kernel_initializer='he_normal'))
    # Using mse as loss and mape as the metric
    stock_predictor.compile(loss='mean_squared_error',
                  optimizer='rmsprop',
                  metrics=['mape'])
    return stock_predictor


model = stock_predictor_model(X_train)

# ### 3.  Visualize keras model by using Pydot

model.summary()

import os
os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'

from tensorflow.keras.utils import plot_model
plot_model(model, to_file='model.png')

# ### 4. Train the model using basic parameters.

batch_size = 20
num_steps(len(X_train), batch_size)

history = model.fit(X_train, Y_train, 
                    validation_data=[X_val, Y_val],
                    batch_size=batch_size,
                    epochs=1000,
                    verbose=1)

# ### 5. Analyse the model performance using loss and accuracy curves

import matplotlib.pyplot as plt
import seaborn as sns

# plot training history
plt.plot(history.history['mean_absolute_percentage_error'], label='train')
plt.plot(history.history['val_mean_absolute_percentage_error'], label='test')
plt.legend()
plt.title("Training and Test Errors")
plt.show()

# ### 6. Hyperparameter tuning of neural network

# install talos using **pip install talos**

import talos
from talos.model.hidden_layers import hidden_layers

p = {'lr': (0.1,0.5,10),
     'first_neuron':[10, 20],
     'hidden_layers':[1, 2, 3],
     'batch_size': (10,30,5),
     'epochs': [500],
     'dropout': (0, 0.5, 5),
     'shapes':['brick','funnel'],
      'activation': ['relu']
    }


# **Funnel**
#      
# Funnel is the shape that roughly looks like an upside-dowm pyramind, so that the first layer is defined with max neurons, and the next layers are sligtly decreased compared to previous ones.

# <img src='funnel.png' />

# **Brick**
#
# All the layers have first_neuron value. Called by shape='brick'.

# <img src='brick.png' />

def stock_prediction_model(x_train, y_train, x_val, y_val, params):

    # next we can build the model exactly like we would normally do it
    model = Sequential()
    model.add(Dense(params['first_neuron'], input_dim=x_train.shape[1],
                    activation='relu',
                    kernel_initializer='he_normal'))
    
    model.add(Dropout(params['dropout']))
    
    # if we want to also test for number of layers and shapes, that's possible
    hidden_layers(model, params, 1)
   
    # then we finish again with completely standard Keras way
    model.add(Dense(1, activation='relu',
                    kernel_initializer='he_normal'))
    
    model.compile(loss='mean_squared_error',
                  optimizer=RMSprop(learning_rate=params['lr']),
                  metrics=['mape'])
    
    history = model.fit(x_train, y_train, 
                        validation_data=[x_val, y_val],
                        batch_size=params['batch_size'],
                        epochs=params['epochs'],
                        verbose=0)
    
    # finally we have to make sure that history object and model are returned
    return history, model


t = talos.Scan(x=X_train,
            y=Y_train,x_val=X_val,y_val=Y_val,
            model=stock_prediction_model,
            params=p,
            experiment_name='stock_exp',
            fraction_limit=0.1)

# accessing the results data frame
t.data.head()

# access the summary details
t.details

# use Scan object as input
analyze_object = talos.Analyze(t)

# access the dataframe with the results
analyze_object.data.head()

# get the number of rounds in the Scan
analyze_object.rounds()

# get the highest result for any metric
analyze_object.low('val_mean_absolute_percentage_error')

analyze_object.data[analyze_object.data.val_mean_absolute_percentage_error==17.504638671875]

analyze_object.data.iloc[42,:]

# a regression plot for two dimensions 
analyze_object.plot_regs('val_mean_absolute_percentage_error', 'val_loss')

# line plot
analyze_object.plot_line('val_mean_absolute_percentage_error')

# heatmap correlation
analyze_object.plot_corr('val_mean_absolute_percentage_error', ['val_mean_absolute_percentage_error', 'loss', 'val_loss','mean_absolute_percentage_error'])

# a four dimensional bar grid
analyze_object.plot_bars('batch_size', 'val_mean_absolute_percentage_error', 'first_neuron', 'lr')

# ### 7. Generating predictions by using the trained model

best_model = t.best_model(metric='val_mean_absolute_percentage_error', asc=True)

best_model.summary()

# +
import numpy as np
from sklearn.utils import check_array

def mean_absolute_percentage_error(y_true, y_pred): 
    """
    measures mape score
    """

#     y_true, y_pred = check_array(y_true, y_pred)
    return np.mean(np.abs((y_true - y_pred) / y_true)) * 100


# -

mean_absolute_percentage_error(Y_test, best_model.predict(X_test)[:,-1])



StarcoderdataJupyterScriptsDedupFiltered