저는 절삭력 값인 x, y를 독립변수로 두고 이들의 rms 값을 rms라는 타겟 레이블로 두고 rms 값을 예측하는 시계열 모델을 만들고자 했습니다. 아래는 저의 코드입니다.
X = df.iloc[:, :-1]
y = df.iloc[:, -1:]
ms = MinMaxScaler()
ss = StandardScaler()
X_ss = ss.fit_transform(X)
y_ms = ms.fit_transform(y)
train_len = int(len(X)*0.8)
X_train = X_ss[:train_len,:]
X_test = X_ss[train_len:,:]
y_train = y_ms[:train_len, : ]
y_test = y_ms[train_len:, : ]
X_train_tensors = torch.Tensor(X_train)
X_test_tensors = torch.Tensor(X_test)
y_train_tensors = torch.Tensor(y_train)
y_test_tensors = torch.Tensor(y_test)
X_train_tensors_f = torch.reshape(X_train_tensors, (X_train_tensors.shape[0], 1, X_train_tensors.shape[1]))
X_test_tensors_f = torch.reshape(X_test_tensors, (X_test_tensors.shape[0], 1, X_test_tensors.shape[1]))
LSTM 네트워크
class LSTM(nn.Module):
def init(self, num_classes,input_size, hidden_size, num_layers, seq_length):
super(LSTM, self).init()
self.num_classes = num_classes #number of classes
self.num_layers = num_layers #number of layers
self.input_size = input_size #input size -> 입력 크기로 훈련 데이터셋의 칼럼 개수를 의미
self.hidden_size = hidden_size #hidden state 은닉층의 뉴런 개수
self.seq_length = seq_length #sequence length
self.lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size,
num_layers=num_layers, batch_first=True) #lstm 계층
self.fc_1 = nn.Linear(hidden_size, 128) #fully connected 1 완전연결층
self.fc = nn.Linear(128, num_classes) #fully connected last layer 출력층
self.relu = nn.ReLU()
def forward(self,x):
h_0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size) #은닉 상태를 0으로 초기화
c_0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size) #셀 상태를 0으로 초기화
output, (hn, cn) = self.lstm(x, (h_0, c_0)) #lstm 계층에 은닉 상태와 셀 상태 적용
hn = hn.view(-1, self.hidden_size) #reshape 완전연결층 적용을 위해 데이터의 형태 조정(1차원으로 조정)
out = self.relu(hn)
out = self.fc_1(out) #fully connected 1
out = self.relu(out) #relu
out = self.fc(out) #fully connected last layer
return out
변수 값 설정
num_epochs = 100 #에폭
learning_rate = 0.001 #학습률
input_size = 2 #입력 데이터 셋의 칼럼 개수
hidden_size = 2 #은닉층의 뉴런/유닛 개수
num_layers = 1 lstm 계층의 개수
num_classes = 1 # 클래스 개수
model = LSTM(num_classes, input_size, hidden_size, num_layers, X_train_tensors_f.shape[1]) # 앞에서 정의한 값들을 이용하여 LSTM 모델 학습
criterion = torch.nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr = learning_rate)
for epoch in range(num_epochs):
outputs = model.forward(X_train_tensors_f) # 전방향 학습
optimizer.zero_grad()
loss = criterion(outputs, y_train_tensors) # 손실 함수를 이용한 오차 계산(모델 학습 결과(outputs)와 레이블(y_train_tensors)의 차이 계산)
loss.backward() # 기울기 계산
optimizer.step() # 오차 업데이트
if epoch % 10 == 0:
print("Epoch: %d, loss: %1.5f" % (epoch, loss.item()))
df_x_ss = ss.transform(df.iloc[:, :-1])
df_y_ms = ms.transform(df.iloc[:, -1:])
df_x_ss = torch.Tensor(df_x_ss)
df_y_ms = torch.Tensor(df_y_ms)
df_x_ss = torch.reshape(df_x_ss, (df_x_ss.shape[0], 1, df_x_ss.shape[1]))
train_predict = model(df_x_ss)
predicted = train_predict.data.numpy()
label_y = df_y_ms.data.numpy()
predicted= ms.inverse_transform(predicted)
label_y = ms.inverse_transform(label_y)
plt.figure(figsize=(10,6))
plt.axvline(x=train_len, c='r', linestyle='--')
plt.plot(label_y, label='Actual Data')
plt.plot(predicted, label='Predicted Data')
plt.title('Time-Series Prediction')
plt.legend()
plt.show()
이렇게 되는 경우 테스트할때 x, y값을 입력변수로 넣어줘야 rms 값을 예측할 수 있는거 아닌가요? 그런데 미래에는 x, y값을 알 수가 없잖아요 ? 게다가 사실 x, y 값을 알면 그냥 수학적 계산 하면 rms가 나오는 거기도 하구요. 미래의 rms 값을 예측하는 방법은 없는건가요? lstm 활용이 잘 이해가 안되네요.