Как построить фрейм данных для временных рядов с четкими временными метками? - PullRequest
1 голос
/ 24 мая 2019

Для моего эксперимента у меня есть отформатированный файл csv , который выглядит как матрица [NxM], где N = 40 общее количество циклов (отметок времени) и M = 1440 пикселей. Для каждого цикла у меня есть 1440 пикселей, соответствующих 1440 пикселям. как следующее:

timestamps[row_index] | feature1  | feature2 | ... | feature1439 | feature1440 |
-----------------------------------------------------------------
       1              |  1.00     |   0.32   |   0.30   |   0.30  |   0.30   | 
       2              |  0.35     |   0.33   |   0.30   |   0.30  |   0.30   | 
       3              |  1.00     |   0.33   |   0.30   |   0.30  |   0.30   | 
      ...             |   ....    |   ....   |   ....   |   ....  |   ....   | 
                      | -1.00     |   0.26   |   0.30   |   0.30  |   0.30   | 
                      |   0.67    |   0.03   |   0.30   |   0.30  |   0.30   | 
       30             |   0.75    |   0.42   |   0.30   |   0.30  |   0.30   |
________________________________________________________________________________ 
      31              |  -0.36    |   0.42   |   0.30   |   0.30  |   0.30   | 
      ...             |   ....    |   ....   |   ....   |   ....  |   ....   | 
      40              |   1.00    |   0.34   |   0.30   |   0.30  |  -1.00   |

img

Я бы хотел разделить набор данных на наборы поездов и набор тестов таким образом, чтобы:

Поезд содержит [1-30] меток времени. Информация

Набор тестов содержит [31-40] информацию о временных метках

Проблема в том, что я не смог добиться правильного непрерывного графика после тренировки NN, скорее всего, из-за неправильной техники разделения данных, которую я использовал с помощью train_test_split, но никогда не пробовал TimeSeriesSplit следующим образом:

trainX, testX, trainY, testY = train_test_split(trainX,trainY, test_size=0.2 , shuffle=False) 

учитывая, что я использовал shuffle=False и ожидаю, что 0.2 из конца данных будет считаться тестовыми данными, и я могу получить их правильно, но все равно не могу получить доступ к числу циклов, которое считаются тестовыми данными, поэтому, когда я строю график, он начинается с 0! вместо продолжения последнего цикла данных поезда!

Мне было интересно, лучше ли передать данные в pd.DataFrame и попробовать нарезать данные по pd.Timestamp на основе этой записи ! Это полезно или не нужно?

Обновление - полный код: моя маркировка столбцов соответствует шаблону ниже, просто предсказав, что 960 из 1440 столбцов:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from keras.layers import Dense , Activation , BatchNormalization
from keras.layers import Dropout
from keras.layers import LSTM,SimpleRNN
from keras.models import Sequential
from keras.optimizers import Adam, RMSprop

data_train = pd.read_csv("D:\train.csv", header=None)
#select interested columns to predict 980 out of 1440
j=0
index=[]
for i in range(1439):
    if j==2:
        j=0
        continue
    else:
        index.append(i)
        j+=1

Y_train= data_train[index]
data_train = data_train.values
print("data_train size: {}".format(Y_train.shape))

Создание истории

def create_dataset(dataset,data_train,look_back=1):
    dataX,dataY = [],[]
    print("Len:",len(dataset)-look_back-1)

    for i in range(len(dataset)-look_back-1):
        a = dataset[i:(i+look_back), :]
        dataX.append(a)
        dataY.append(data_train[i + look_back,  :])
    return np.array(dataX), np.array(dataY)

look_back = 10
trainX,trainY = create_dataset(data_train,Y_train, look_back=look_back)
#testX,testY = create_dataset(data_test,Y_test, look_back=look_back)
trainX, testX, trainY, testY = train_test_split(trainX,trainY, test_size=0.2)
print("train size: {}".format(trainX.shape))
print("train Label size: {}".format(trainY.shape))
print("test size: {}".format(testX.shape))
print("test Label size: {}".format(testY.shape))

Len: 29
train size: (23, 10, 1440)
train Label size: (23, 960)
test size: (6, 10, 1440)
test Label size: (6, 960)

Аналогично реализация RNN, LSTM, GRU

# create and fit the SimpleRNN model
model_RNN = Sequential()
model_RNN.add(SimpleRNN(units=1440, input_shape=(trainX.shape[1], trainX.shape[2])))
model_RNN.add(Dense(960))
model_RNN.add(BatchNormalization())
model_RNN.add(Activation('tanh'))
model_RNN.compile(loss='mean_squared_error', optimizer='adam')
callbacks = [
    EarlyStopping(patience=10, verbose=1),
    ReduceLROnPlateau(factor=0.1, patience=3, min_lr=0.00001, verbose=1)]
hist_RNN=model_RNN.fit(trainX, trainY, epochs =50, batch_size =20,validation_data=(testX,testY),verbose=1, callbacks=callbacks)

В итоге я бы ожидал следующий выходной сюжет:

Y_RNN_Test_pred=model_RNN.predict(testX)
test_RNN= pd.DataFrame.from_records(Y_RNN_Test_pred)
test_RNN.to_csv('New/ttest_RNN_history.csv', sep=',', header=None, index=None)
test_MSE=mean_squared_error(testY, Y_RNN_Test_pred)

plt.plot(trainY[:,0],'b-',label='Train data')
plt.plot(testY[:,0],'c-',label='Test data')
plt.plot(Y_RNN_Test_pred[:,0],'r-',label='prediction')

img

1 Ответ

1 голос
/ 24 мая 2019

Есть небольшая проблема с индексом.

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

df = pd.read_csv('Train.csv', header=None)

# I'm not sure what the label-column is, so i use df[0]
# and exclude this colums in the data via df.loc[:,df.columns!=0]
trainX,testX,trainY,testY = train_test_split(df.loc[:,df.columns!=0],df[0], test_size=0.2, shuffle=False)

plt.plot(trainY)
plt.plot(testY)

enter image description here

кажется в порядке.: -)

, поэтому теперь мы хотим предсказать:

from sklearn.svm import SVR
reg = SVR(C=1, gamma='auto')
reg.fit(trainX, trainY) 
predY = reg.predict(testX)

plt.plot(trainY)
plt.plot(testY)
plt.plot(predY)

enter image description here

Индекс неверный :-( Давайте исправим этоНапример, используйте индекс testY:

plt.plot(trainY)
plt.plot(testY)
plt.plot(testY.index,predY)

enter image description here

РЕДАКТИРОВАТЬ

Более общийрешение состоит в том, чтобы взять диапазон длины вашего набора данных поезда и установить его в качестве индекса, то же самое с testY и predY, просто с другим начальным значением (длина trainY)

trainY.index = range(len(trainY))
testY.index = range(len(trainY), len(trainY)+len(testY))
#Maybe convert to DataFrame first
predY = pd.DataFrame(predY)
predY.index = range(len(trainY), len(trainY)+len(predY))

plt.plot(trainY)
plt.plot(testY)
plt.plot(predY)

Редактировать на основе вашего нового кода

trainY.index = range(len(trainY))
testY.index = range(len(trainY), len(trainY)+len(testY))
test_RNN.index = range(len(trainY), len(trainY)+len(test_RNN))

plt.plot(trainY,'b-',label='Train data')
plt.plot(testY,'c-',label='Test data')
plt.plot(test_RNN,'r-',label='prediction')

Редактировать 2

Хорошо, давайте пошагово пройдемся по вашему коду:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from keras.layers import Dense , Activation , BatchNormalization
from keras.layers import Dropout
from keras.layers import LSTM,SimpleRNN
from keras.models import Sequential
from keras.optimizers import Adam, RMSprop

data_train = pd.read_csv("Train.csv", header=None)
#select interested columns to predict 980 out of 1440

На самом деле вы выбираете только 960 столбцов для прогнозирования, см. Ниже.

#j=0
#index=[]
#for i in range(1439):
#    if j==2:
#        j=0
#        continue
#    else:
#        index.append(i)
#        j+=1

idx2 = [i for i in list(range(1440)) if i%3!=2]

Если я правильно понял ваш цикл, вы просто хотите принимать каждые три из двух значений. Так что понимание списка немногобыстрее idx2 = [i for i in list(range(1440)) if i%3!=2]. Возможно, вы также хотите включить все столбцы? Поэтому используйте 1440 вместо 1439.

Y_train= data_train[index]
data_train = data_train.values
print("data_train size: {}".format(Y_train.shape))

В вашем коде форма Y_train равна (40,960).Итак, вы хотите предсказать 690 переменных, верно?Если это так, «чистый» способ будет удалить эти столбцы из data_train (и сделать X_train):

index2 = [i for i in list(range(1440)) if i%3==2]
X_train = data_train[index2]

Теперь давайте проверим формы:

print("X_train size: {}".format(X_train.shape))
print("Y_train size: {}".format(Y_train.shape))

>X_train size: (40, 480)
>Y_train size: (40, 960)

Кажется правильным ...; -)

Я внес некоторые изменения в следующую часть: - Вам не нужно вычитать 1 из диапазона (for i in range(len(dataset)-look_back):.В отличие от некоторых других языков программирования, Python не включает последнее значение, поэтому, например, если вы сделаете list(range(0,3)), список будет [0,1,2]. Вероятно, это ваши пропущенные 10 значений (последние) ... - Я также взял values из Y_train

def create_dataset(dataset,data_train,look_back=1):
    dataX,dataY = [],[]

    for i in range(len(dataset)-look_back):
        a = dataset[i:(i+look_back), :]
        dataX.append(a)
        dataY.append(data_train[i+look_back, :])
    return np.array(dataX), np.array(dataY)

look_back = 10
trainX,trainY = create_dataset(X_train.values, Y_train.values, look_back=look_back)
trainX, testX, trainY, testY = train_test_split(trainX,trainY, test_size=0.2)
print("train size: {}".format(trainX.shape))
print("train Label size: {}".format(trainY.shape))
print("test size: {}".format(testX.shape))
print("test Label size: {}".format(testY.shape))

>train size: (24, 10, 480)
>train Label size: (24, 960)
>test size: (6, 10, 480)
>test Label size: (6, 960)

Мне пришлось добавить дваимпортирует в тренинг from keras.callbacks import EarlyStopping, ReduceLROnPlateau, поэтому:

from keras.callbacks import EarlyStopping, ReduceLROnPlateau
# create and fit the SimpleRNN model
model_RNN = Sequential()
model_RNN.add(SimpleRNN(units=1440, input_shape=(trainX.shape[1], trainX.shape[2])))
model_RNN.add(Dense(960))
model_RNN.add(BatchNormalization())
model_RNN.add(Activation('tanh'))
model_RNN.compile(loss='mean_squared_error', optimizer='adam')
callbacks = [
    EarlyStopping(patience=10, verbose=1),
    ReduceLROnPlateau(factor=0.1, patience=3, min_lr=0.00001, verbose=1)]
hist_RNN=model_RNN.fit(trainX, trainY, epochs =50, batch_size =20,validation_data=(testX,testY),verbose=1, callbacks=callbacks)

Сделайте прогнозы (без изменений):

Y_RNN_Test_pred=model_RNN.predict(testX)
test_RNN= pd.DataFrame.from_records(Y_RNN_Test_pred)
#test_RNN.to_csv('New/ttest_RNN_history.csv', sep=',', header=None, index=None)
test_MSE=mean_squared_error(testY, Y_RNN_Test_pred)

и нанесите данные с изменениями на оси x, как описано выше:

x_start =  range(look_back, look_back+len(trainY))
x_train_start = range(look_back + len(trainY), look_back + len(trainY)+len(testY))
x_pred_start = range(look_back + len(trainY), look_back +len(trainY)+len(Y_RNN_Test_pred))
plt.plot(x_start, trainY[:,0],'b-',label='Train data')
plt.plot(x_train_start, testY[:,0],'c-',label='Test data')
plt.plot(x_pred_start, Y_RNN_Test_pred[:,0],'r-',label='prediction')

enter image description here

...