0
$\begingroup$

I'm creating an ensemble of NNs with the same architecture, but each NN only outputs one value when given X_test data. The data (continuous values transformed to be [-1,1]) yields results as expected when put through other ML algos (RF and XGB), so I suspect this has something to do with my model construction. Here is the entire code, I hope it provides some clues.

import pandas as pd
import numpy as np
from scipy.stats import randint
from sklearn.tree import export_graphviz
from IPython.display import Image
import graphviz
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Dense, BatchNormalization
from keras.optimizers import Adam
from keras.callbacks import EarlyStopping
from keras.regularizers import l1
import tensorflow as tf
from keras.models import load_model
## sp500 benchmark data
sp = pd.read_csv("sp500.csv")
# sp data we need to calculate monthly sp500 returns to benchmark the OOS data
sp = sp[(sp['Date'] >= '1986-12-01') & (sp['Date'] <= '2022-01-01')]
# calculate the monthly pct change
test_sp = sp['Close'].reset_index(drop=True).pct_change().dropna()
## stock market data
data = pd.read_csv("stock_char_monthly.csv")
data['month'] = pd.to_datetime(data['month'])
data['year'] = data['month'].dt.year
# drop the bottom 20% observations by market capitalization (their snr is lowest, the stocks are illiquid, Fama: 20%:3%)
percentile_cutoff = 0.2
bottom_20 = data.groupby('month')['mktcap_lag'].transform(lambda x: x.quantile(percentile_cutoff))
data = (data[data['mktcap_lag'] > bottom_20]).reset_index(drop=True)
# target and features
target = data.ret_excess
returns = data.ret_adj
feat_data = data.filter(regex="char_")
years = data.year
train_start = 1965
test_start = 1987
train_idxs = years.loc[(years >= train_start) & (years < test_start)].index
test_idxs = years.loc[years == test_start].index
# train indices
train_beg = train_idxs[0]
train_end = train_idxs[-1]+1
# test indices
test_beg = test_idxs[0]
test_end = test_idxs[-1]+1
# split
X_train = feat_data[train_beg:train_end]
y_train = target[train_beg:train_end]
X_test = feat_data[test_beg:test_end]
y_test = target[test_beg:test_end]
# test returns
test_ret=returns[test_beg:test_end]
## NN 3 hidden layers: 
# layers: 94,32,16,8,1
# activation function: ReLU
# l1 penalty: 10e-3
# learning rate: 0.001
# batch size: 10,000
# epochs: 100
# patience: 5
# adam: default
# ensemble: 5
# batch normalization between all layers
n_members = 5
models = list()
for _ in range(n_members):
    # specify model architecture
    model = Sequential()
    model.add(Dense(94, activation='relu',kernel_regularizer=l1(0.01)))
    model.add(BatchNormalization())
    model.add(Dense(32, activation='relu',kernel_regularizer=l1(0.01)))
    model.add(BatchNormalization())
    model.add(Dense(16, activation='relu',kernel_regularizer=l1(0.01)))
    model.add(BatchNormalization())
    model.add(Dense(8, activation='relu',kernel_regularizer=l1(0.01)))
    model.add(BatchNormalization())
    model.add(Dense(1), activation='linear')
    model.compile(loss='mean_squared_error', optimizer=Adam(learning_rate=0.001), metrics=['mean_squared_error'])
    early_stopping = EarlyStopping(monitor='val_loss', patience=5)
    #model.summary()
    # fit the model
    model.fit(x=X_train,
              y=y_train,
              batch_size = 10000,
              epochs = 100,
              validation_split = 0.4,
              verbose = 1,
              callbacks = early_stopping)
    models.append(model)
yhats = [model.predict(X_test) for model in models]
yhats = np.array(yhats)
print(yhats[0])

For example, the first model only outputs 0.0098383. [[0.0098383 ] [0.0098383 ] [0.0098383 ] ... [0.0098383 ] [0.00983831] [0.0098383 ]]

$\endgroup$
2
  • $\begingroup$ How do the training metrics look? I suspect this is because the model learned that predicting a single value leads to the lowest overall error, resulting from the fact that the model is unable to learn the relation between the features and the output value. This can be because the model has too few parameters, or because the features do not have enough information for the model to learn from. $\endgroup$
    – Oxbowerce
    Commented Jan 19 at 22:04
  • $\begingroup$ kernel_regularizer, that was the issue. I removed it. Moved project to Pytorch btw $\endgroup$
    – quasimodo
    Commented Feb 4 at 5:22

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.