मैंने डेटा स्टॉक पूर्वानुमान के लिए पर्यवेक्षित शिक्षण के साथ एक LSTM (RNN) तंत्रिका नेटवर्क बनाया। समस्या यह है कि यह अपने प्रशिक्षण डेटा पर गलत भविष्यवाणी क्यों करता है? (नोट: नीचे दिए गए प्रतिलिपि योग्य उदाहरण )
मैंने अगले 5 दिनों के स्टॉक मूल्य की भविष्यवाणी करने के लिए सरल मॉडल बनाया:
model = Sequential()
model.add(LSTM(32, activation='sigmoid', input_shape=(x_train.shape[1], x_train.shape[2])))
model.add(Dense(y_train.shape[1]))
model.compile(optimizer='adam', loss='mse')
es = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)
model.fit(x_train, y_train, batch_size=64, epochs=25, validation_data=(x_test, y_test), callbacks=[es])
सही परिणाम y_test
(5 मान) हैं, इसलिए मॉडल ट्रेनें, पिछले 90 दिनों की ओर देख रही हैं और फिर सबसे अच्छे ( val_loss=0.0030
) परिणाम से वजन बहाल करती हैं patience=3
:
Train on 396 samples, validate on 1 samples
Epoch 1/25
396/396 [==============================] - 1s 2ms/step - loss: 0.1322 - val_loss: 0.0299
Epoch 2/25
396/396 [==============================] - 0s 402us/step - loss: 0.0478 - val_loss: 0.0129
Epoch 3/25
396/396 [==============================] - 0s 397us/step - loss: 0.0385 - val_loss: 0.0178
Epoch 4/25
396/396 [==============================] - 0s 399us/step - loss: 0.0398 - val_loss: 0.0078
Epoch 5/25
396/396 [==============================] - 0s 391us/step - loss: 0.0343 - val_loss: 0.0030
Epoch 6/25
396/396 [==============================] - 0s 391us/step - loss: 0.0318 - val_loss: 0.0047
Epoch 7/25
396/396 [==============================] - 0s 389us/step - loss: 0.0308 - val_loss: 0.0043
Epoch 8/25
396/396 [==============================] - 0s 393us/step - loss: 0.0292 - val_loss: 0.0056
भविष्यवाणी परिणाम बहुत बढ़िया है, है ना?
ऐसा इसलिए है क्योंकि एल्गोरिथ्म ने # 5 युग से सर्वश्रेष्ठ वजन बहाल किया। ओके, अब इस मॉडल को .h5
फाइल करने, बैक -10 दिनों को स्थानांतरित करने और पिछले 5 दिनों की भविष्यवाणी करने के लिए सहेजें (पहले उदाहरण में हमने मॉडल बनाया और 17-23 अप्रैल को सप्ताहांत के दिन सहित, अब 2-8 अप्रैल को परीक्षण करते हैं)। परिणाम:
यह बिल्कुल गलत दिशा दिखाता है। जैसा कि हम देखते हैं कि मॉडल को प्रशिक्षित किया गया था और 17-23 अप्रैल को सत्यापन के लिए # 5 युग सर्वश्रेष्ठ लिया गया था, लेकिन 2-8 पर नहीं। अगर मैं और अधिक ट्रेन करने की कोशिश करता हूं, तो मैं जो भी चुनूं, उसके साथ खेलता हूं, जो कुछ भी करता हूं, उसमें हमेशा बहुत समय अंतराल होता है, जिसमें गलत भविष्यवाणी होती है।
मॉडल अपने स्वयं के प्रशिक्षित डेटा पर गलत परिणाम क्यों दिखाता है? मैंने डेटा को प्रशिक्षित किया, यह याद रखना चाहिए कि सेट के इस टुकड़े पर डेटा की भविष्यवाणी कैसे करें, लेकिन गलत भविष्यवाणी करता है। मैंने भी क्या प्रयास किया:
- अधिक या कम सुविधाओं को जोड़ते हुए, 50k + पंक्तियों, 20 साल के स्टॉक की कीमतों के साथ बड़े डेटा सेट का उपयोग करें
- विभिन्न प्रकार के मॉडल बनाएं, जैसे अधिक छिपी हुई परतें जोड़ना, अलग बैच_साइज, विभिन्न परतों की सक्रियता, ड्रॉपआउट, बल्लेबाजी
- कस्टम अर्लीस्टॉपिंग कॉलबैक बनाएं, कई वैलिडेशन डेटा सेट से औसत वेल_लॉस प्राप्त करें और सर्वश्रेष्ठ चुनें
शायद मुझे कुछ याद है? मैं क्या सुधार कर सकता हूं?
यहाँ बहुत ही सरल और प्रतिलिपि प्रस्तुत करने योग्य उदाहरण है। yfinance
डाउनलोड एस एंड पी 500 स्टॉक डेटा।
"""python 3.7.7
tensorflow 2.1.0
keras 2.3.1"""
import numpy as np
import pandas as pd
from keras.callbacks import EarlyStopping, Callback
from keras.models import Model, Sequential, load_model
from keras.layers import Dense, Dropout, LSTM, BatchNormalization
from sklearn.preprocessing import MinMaxScaler
import plotly.graph_objects as go
import yfinance as yf
np.random.seed(4)
num_prediction = 5
look_back = 90
new_s_h5 = True # change it to False when you created model and want test on other past dates
df = yf.download(tickers="^GSPC", start='2018-05-06', end='2020-04-24', interval="1d")
data = df.filter(['Close', 'High', 'Low', 'Volume'])
# drop last N days to validate saved model on past
df.drop(df.tail(0).index, inplace=True)
print(df)
class EarlyStoppingCust(Callback):
def __init__(self, patience=0, verbose=0, validation_sets=None, restore_best_weights=False):
super(EarlyStoppingCust, self).__init__()
self.patience = patience
self.verbose = verbose
self.wait = 0
self.stopped_epoch = 0
self.restore_best_weights = restore_best_weights
self.best_weights = None
self.validation_sets = validation_sets
def on_train_begin(self, logs=None):
self.wait = 0
self.stopped_epoch = 0
self.best_avg_loss = (np.Inf, 0)
def on_epoch_end(self, epoch, logs=None):
loss_ = 0
for i, validation_set in enumerate(self.validation_sets):
predicted = self.model.predict(validation_set[0])
loss = self.model.evaluate(validation_set[0], validation_set[1], verbose = 0)
loss_ += loss
if self.verbose > 0:
print('val' + str(i + 1) + '_loss: %.5f' % loss)
avg_loss = loss_ / len(self.validation_sets)
print('avg_loss: %.5f' % avg_loss)
if self.best_avg_loss[0] > avg_loss:
self.best_avg_loss = (avg_loss, epoch + 1)
self.wait = 0
if self.restore_best_weights:
print('new best epoch = %d' % (epoch + 1))
self.best_weights = self.model.get_weights()
else:
self.wait += 1
if self.wait >= self.patience or self.params['epochs'] == epoch + 1:
self.stopped_epoch = epoch
self.model.stop_training = True
if self.restore_best_weights:
if self.verbose > 0:
print('Restoring model weights from the end of the best epoch')
self.model.set_weights(self.best_weights)
def on_train_end(self, logs=None):
print('best_avg_loss: %.5f (#%d)' % (self.best_avg_loss[0], self.best_avg_loss[1]))
def multivariate_data(dataset, target, start_index, end_index, history_size, target_size, step, single_step=False):
data = []
labels = []
start_index = start_index + history_size
if end_index is None:
end_index = len(dataset) - target_size
for i in range(start_index, end_index):
indices = range(i-history_size, i, step)
data.append(dataset[indices])
if single_step:
labels.append(target[i+target_size])
else:
labels.append(target[i:i+target_size])
return np.array(data), np.array(labels)
def transform_predicted(pr):
pr = pr.reshape(pr.shape[1], -1)
z = np.zeros((pr.shape[0], x_train.shape[2] - 1), dtype=pr.dtype)
pr = np.append(pr, z, axis=1)
pr = scaler.inverse_transform(pr)
pr = pr[:, 0]
return pr
step = 1
# creating datasets with look back
scaler = MinMaxScaler()
df_normalized = scaler.fit_transform(df.values)
dataset = df_normalized[:-num_prediction]
x_train, y_train = multivariate_data(dataset, dataset[:, 0], 0,len(dataset) - num_prediction + 1, look_back, num_prediction, step)
indices = range(len(dataset)-look_back, len(dataset), step)
x_test = np.array(dataset[indices])
x_test = np.expand_dims(x_test, axis=0)
y_test = np.expand_dims(df_normalized[-num_prediction:, 0], axis=0)
# creating past datasets to validate with EarlyStoppingCust
number_validates = 50
step_past = 5
validation_sets = [(x_test, y_test)]
for i in range(1, number_validates * step_past + 1, step_past):
indices = range(len(dataset)-look_back-i, len(dataset)-i, step)
x_t = np.array(dataset[indices])
x_t = np.expand_dims(x_t, axis=0)
y_t = np.expand_dims(df_normalized[-num_prediction-i:len(df_normalized)-i, 0], axis=0)
validation_sets.append((x_t, y_t))
if new_s_h5:
model = Sequential()
model.add(LSTM(32, return_sequences=False, activation = 'sigmoid', input_shape=(x_train.shape[1], x_train.shape[2])))
# model.add(Dropout(0.2))
# model.add(BatchNormalization())
# model.add(LSTM(units = 16))
model.add(Dense(y_train.shape[1]))
model.compile(optimizer = 'adam', loss = 'mse')
# EarlyStoppingCust is custom callback to validate each validation_sets and get average
# it takes epoch with best "best_avg" value
# es = EarlyStoppingCust(patience = 3, restore_best_weights = True, validation_sets = validation_sets, verbose = 1)
# or there is keras extension with built-in EarlyStopping, but it validates only 1 set that you pass through fit()
es = EarlyStopping(monitor = 'val_loss', patience = 3, restore_best_weights = True)
model.fit(x_train, y_train, batch_size = 64, epochs = 25, shuffle = True, validation_data = (x_test, y_test), callbacks = [es])
model.save('s.h5')
else:
model = load_model('s.h5')
predicted = model.predict(x_test)
predicted = transform_predicted(predicted)
print('predicted', predicted)
print('real', df.iloc[-num_prediction:, 0].values)
print('val_loss: %.5f' % (model.evaluate(x_test, y_test, verbose=0)))
fig = go.Figure()
fig.add_trace(go.Scatter(
x = df.index[-60:],
y = df.iloc[-60:,0],
mode='lines+markers',
name='real',
line=dict(color='#ff9800', width=1)
))
fig.add_trace(go.Scatter(
x = df.index[-num_prediction:],
y = predicted,
mode='lines+markers',
name='predict',
line=dict(color='#2196f3', width=1)
))
fig.update_layout(template='plotly_dark', hovermode='x', spikedistance=-1, hoverlabel=dict(font_size=16))
fig.update_xaxes(showspikes=True)
fig.update_yaxes(showspikes=True)
fig.show()
df.drop(df.tail(10).index, inplace=True)
, उसने वही खराब परिणाम दिखाया जैसा कि मेरे पास था।