Home > Back-end >  Turning Python Keras Machine Learning model into repeatable function that can take as input multiple
Turning Python Keras Machine Learning model into repeatable function that can take as input multiple

Time:07-22

I am currently building various machine learning models, each of the models takes in X and Y data that represent different stock prices e.g. there's an X and y data frame for each stock e.g. Apple, Microsoft.

I am trying to produce these models so that they are repeatable, modular, functions that I can quickly call for each of my X and y data sets.

I have tried these models as standalone lines of code, or as functions that don't take in parameters and they work as intended, however whenever I try to pass my X and y data sets as parameters they don't work!

Currently I have:

def LSTM_regressor(X_train, X_test, y_train, y_test):
    convert_X_y_to_numpy_and_reshape(X_train, X_test, y_train, y_test)
    model = Sequential()
    model.add(Dense(1, input_dim=(X_train.shape[1]), kernel_initializer='normal', activation='sigmoid'))
    model.compile(loss='mse', optimizer='adam', metrics=['mse'])
    model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=20)
    print(model.summary())

final_model = KerasRegressor(build_fn=LSTM_regressor(X_train_reg_aapl, X_test_reg_aapl, y_train_reg_aapl, y_test_reg_aapl),batch_size=20, epochs=50, verbose=1)
kfold = KFold(n_splits=10) # random_state=seed)
results = cross_val_score(final_model, X_train_reg_aapl, y_train_reg_aapl, cv=kfold, n_jobs=1)
print("Results: %.2f (%.2f) MSE" % (results.mean(),results.std()))

I am trying to pass the below into the function:

X_train_reg_aapl, X_test_reg_aapl, y_train_reg_aapl, y_test_reg_aapl

but I get the error message:

AttributeError: 'KerasRegressor' object has no attribute '__call__'

I have tried making a nested function and calling that, but it still doesn't work.

Also, the below is a function that I have created that I wanted to use to transform the parameters entered into the machine learning model into a data format suitable for the model type.

 convert_X_y_to_numpy_and_reshape(X_train, X_test, y_train, y_test)

It's full code is this:

def convert_X_y_to_numpy_and_reshape(X_train,X_test,y_train,y_test):
    X_train = X_train.to_numpy()
    X_test = X_test.to_numpy()
    y_train = y_train.to_numpy()
    y_test = y_test.to_numpy()
    y_train = y_train.reshape(-1)
    y_test = y_test.reshape(-1)
    X_train = X_train.reshape((X_train.shape[0], X_train.shape[1], 1))
    X_test = X_test.reshape((X_test.shape[0], X_test.shape[1], 1))

Any help on this would really be appreciated!

CodePudding user response:

Try providing default values for your LSTM_regressor function.

def LSTM_regressor(X_train=X_tr, X_test=X_te, y_train=y_tr, y_test=y_te):

From the docs:

sk_params takes both model parameters and fitting parameters. Legal model parameters are the arguments of build_fn. Note that like all other estimators in scikit-learn, 'build_fn' should provide default values for its arguments, so that you could create the estimator without passing any values to sk_params.

As a remark, you don't need ask full datasets as arguments. You can have a stock_name as an argument and use that as a key to dictionary of your stock dataframes.

dataset_dict = {"AAPL":(X_train, X_test, y_train, y_test), "GOOGL": (...)}

def LSTM_regressor(stock_name="AAPL"):  # default value
   X_train, X_test, y_train, y_test = dataset_dict[stock_name]
   .... 
   

CodePudding user response:

I was able to solve my problem by creating a new function that calls the LSTM model building function. Within the new function I included all the data processing functions needed and when calling the LSTM model building function I used "model=" rather than "build_fn" which allowed me to pass custom parameters to my LSTM model without triggering the below error.

AttributeError: 'KerasRegressor' object has no attribute '__call__'

My final LSTM build model:

def LSTM_regressor(X_train, X_test, y_train, y_test,hidden_layer_sizes, dropout, ):
    model = Sequential()
    model.add(LSTM(64, input_shape = X_train.shape[1:], activation='relu')) 
    model.add(Dense(24,activation='relu'))
    return model

Function used to pass parameters and processed data to my LSTM build model:

def Run_LSTM_Regressor(stock_name,X_train, X_test, y_train, y_test):
    index_train, index_test =  shift_X_reg(1,X_train,X_test)
    y_index_train, y_index_test  = shift_y_reg(1,y_train,y_test)
    X_train, X_test = shift_X_reg(1,X_train,X_test)
    y_train, y_test = shift_y_reg(1,y_train,y_test)
    X_train, X_test = normalise_X(X_train,X_test)
    X_train, X_test, y_train, y_test = convert_X_y_to_numpy_and_reshape_LSTM(X_train,X_test, y_train, y_test)
    run_lstm_regressor_model = KerasRegressor(model=LSTM_regressor(X_train, X_test, y_train, y_test,hidden_layer_sizes=(100,),dropout=0.5),loss="mse",metrics=['mean_squared_error'],epochs=100, verbose=1)
    run_lstm_regressor_model.fit(X_train,y_train)
  • Related