Прогноз временного ряда Keras сначала дает хорошие результаты, а затем ухудшается. Есть идеи, почему? - PullRequest
0 голосов
/ 13 января 2020

Я делаю прогноз временных рядов с LSTM NN и Keras. В качестве входных данных есть две переменные (осадки и температура), и одна цель, которая должна быть предсказана, - уровень грунтовых вод.

предсказания сначала кажутся хорошими, но затем, примерно через три четверти, результаты просто становятся очень плохо: enter image description here

Сначала я подумал, что какая-то другая переменная, кажется, влияет на выходные данные с этого момента, но у меня возникает та же проблема, когда я передаю данные только до 2014 года в сеть. Что-то заставляет сеть давать плохие прогнозы после трех четвертей работы. То же самое происходит с данными из других точек наблюдения, так что это не только этот временной ряд. Это должно быть какая-то проблема с самой сетью или предварительной обработкой данных. У кого-нибудь есть идея, что может вызвать эту проблему?

  • Я использую скользящее окно из 360 точек данных (один год), но это также происходит, когда я уменьшаю окно до 30, например.
  • Тогда я использую партию размером 30 и тренируюсь в течение 20 эпох.
  • Я также использую планировщик скорости обучения cycli c.
  • Архитектура представляет собой LSTM с 3 скрытыми слоями по 12 узлов в каждом.

Буду признателен за любую помощь в этом. Спасибо :-)

Это код моей сети:

# Split in Input and Output Data 
x_1 = data[['MeanT']].values
x_2 = data[['Precip']].values
y = data[['Z_424A_6857']].values

# Scale Data
x = np.hstack([x_1, x_2])
scaler = MinMaxScaler(feature_range=(0, 1))
x = scaler.fit_transform(x)

scaler_out = MinMaxScaler(feature_range=(0, 1))
y = scaler_out.fit_transform(y)

# Reshape Data
x_1, x_2, y = H.create2feature_data(x_1, x_2, y, window)
train_size = int(len(x_1) * .8)
test_size = int(len(x_1)) #  * .5

x_1 = np.expand_dims(x_1, 2) # 3D tensor with shape (batch_size, timesteps, input_dim) // (nr. of samples, nr. of timesteps, nr. of features)
x_2 = np.expand_dims(x_2, 2)
y = np.expand_dims(y, 1)

# Split Training Data
x_1_train = x_1[:train_size]
x_2_train = x_2[:train_size]
y_train = y[:train_size]

# Split Test Data
x_1_test = x_1[train_size:test_size]
x_2_test = x_2[train_size:test_size]
y_test = y[train_size:test_size]

# Define Model Input Sets
inputA = Input(shape=(window, 1))
inputB = Input(shape=(window, 1))

# Build Model Branch 1
branch_1 = layers.GRU(16, activation=act, dropout=0, return_sequences=False, stateful=False, batch_input_shape=(batch, 30, 1))(inputA)
branch_1 = layers.Dense(8, activation=act)(branch_1)
#branch_1 = layers.Dropout(0.2)(branch_1)
branch_1 = Model(inputs=inputA, outputs=branch_1) 

# Build Model Branch 2
branch_2 = layers.GRU(16, activation=act, dropout=0, return_sequences=False, stateful=False, batch_input_shape=(batch, 30, 1))(inputB)
branch_2 = layers.Dense(8, activation=act)(branch_2)
#branch_2 = layers.Dropout(0.2)(branch_2)
branch_2 = Model(inputs=inputB, outputs=branch_2) 

# Combine Model Branches
combined = layers.concatenate([branch_1.output, branch_2.output])

# apply a FC layer and then a regression prediction on the combined outputs
comb = layers.Dense(6, activation=act)(combined)
comb = layers.Dense(1, activation="linear")(comb)

# Accept the inputs of the two branches and then output a single value
model = Model(inputs=[branch_1.input, branch_2.input], outputs=comb)
model.compile(loss='mse', optimizer='adam', metrics=['mse', H.r2_score])

model.summary()

# Training
model.fit([x_1_train, x_2_train], y_train, epochs=epoch, batch_size=batch, validation_split=0.2, callbacks=[tensorboard])
model.reset_states()

# Evaluation
print('Train evaluation')
print(model.evaluate([x_1_train, x_2_train], y_train))

print('Test evaluation')
print(model.evaluate([x_1_test, x_2_test], y_test))

# Predictions
predictions_train = model.predict([x_1_train, x_2_train])
predictions_test = model.predict([x_1_test, x_2_test])

predictions_train = np.reshape(predictions_train, (-1,1))
predictions_test = np.reshape(predictions_test, (-1,1))

# Reverse Scaling
predictions_train = scaler_out.inverse_transform(predictions_train)
predictions_test = scaler_out.inverse_transform(predictions_test)

, и это функция для подготовки моих входных данных:

def create2feature_data(x_1, x_2, y, window_size = 1):
    inp_1, inp_2, out = [], [], []    
    for i in range(window_size, len(x_1)):  
        inp_1.append(x_1[i-window_size:i, 0])
        inp_2.append(x_2[i-window_size:i, 0])
        out.append(y[i, 0])        
    return(np.array(inp_1), np.array(inp_2), np.array(out))
...