기본 콘텐츠로 건너뛰기

[ML] 결정트리(Decision Tree) 모델

Sequential Data에 LSTM 적용

내용

Sequential Data에 LSTM 적용

시퀀스 데이터(Sequential Data)

시퀀스 데이터는 데이터가 나열되어 있는 순서에 중요한 의미가 부여됩니다. 몇 가지 일반적인 유형의 순차 데이터를 예제와 함께 살펴보겠습니다.

Language data 또는 a sentence
예를 들어 “My name is Ahmad”의 문장을 “Name is my Ahmad”와 같이 단어의 순서를 바꾼다면 성립하지 않습니다. 즉, 단어들의 순서가 문장의 의미를 전달하는 데 중요한 요소이기 때문에 순차 데이터입니다.
Time Series Data
예를 들어, 회사 A의 연간 주식 시장 가격과 같은 종류의 데이터는 연도별로 확인하고 순서와 추세를 찾아야 합니다. 연도의 순서는 변경할 수 없습니다.
Biological Data
예를 들어, DNA 서열은 순서대로 유지되어야 합니다.

관찰하면 시퀀스 데이터는 우리 주변 어디에나 있습니다. 예를 들어 오디오를 음파, 텍스트 데이터 등의 시퀀스로 볼 수 있습니다. 이것들은 순서를 유지해야 하는 시퀀스 데이터의 몇 가지 일반적인 예입니다.

전통적 신경망의 한계

다음의 단순한 신경망을 생각해 봅니다.

plt.figure(dpi=100)
font1={'family':'nanumgothic', 'size':12, 'weight':'bold'}
plt.scatter([1, 2], [1, 1], s=200)
plt.annotate("", (1,1), (2,1),arrowprops=dict(color="blue", arrowstyle="-"))
plt.text(1, 0.99, 'Input Layer', fontdict=font1)
plt.text(1.8, 0.99, 'Output Layer', fontdict=font1)
plt.xticks([])
plt.yticks([])
plt.show()

위 그림은 X가 입력이고 ŷ이 수학적 계산을 통해 생성된 출력인 간단한 신경망의 작동을 보여줍니다. 이것은 간단한 일대일 신경망입니다. 유사하게 다음 그림과 같이 다대다 신경망 또는 조밀하게 연결된 신경망을 가질 수 있습니다.

plt.figure(dpi=100)
x1, x2, x3=np.repeat(0.5, 16),[1,1,1], 1.5
y1, y2, y3=np.linspace(1, 20, 16), [5, 10, 15], 10
plt.scatter(x1, y1, s=70, color='white', edgecolor='blue')
plt.scatter(x2, y2, s=70, color='white', edgecolor='gray')
plt.scatter(x3, y3, s=70, color='white', edgecolor='red')
for i1, i2 in zip(x1, y1):
    for j1, j2 in zip(x2, y2):
        plt.annotate('', (i1,i2),(j1, j2), arrowprops=dict(color="blue", arrowstyle="-"))
        plt.annotate('', (j1,j2),(x3, y3), arrowprops=dict(color="gray", arrowstyle="-"))
plt.xticks([])
plt.yticks([])
plt.show()

이러한 네트워크는 기존 기계 학습 알고리즘보다 성능이 우수하지만 몇 가지 단점이 있습니다. 그 중 하나는 물론 순차 데이터입니다. 기존 신경망의 다른 단점은 다음과 같습니다.

고정된 입력 길이를 가집니다.
입력 길이가 고정되어 신경망이 동일한 길이의 입력을 받아야 한다는 것을 의미합니다.
한 국가의 연간 GDP와 같은 일반적인 순차적 데이터 세트의 경우 동일한 수의 특성(feature)을 갖기 때문에 이 문제는 큰 문제가 아닙니다. 그러나 이 문제는 각 문장의 길이가 다른 언어와 같은 데이터를 다룰 때 발생합니다.
예를 들어 ["Hello", "How", "are", "you]는 길이가 4이고 ["My", "Name", "is", "Ahmad", "and", "I", "am", "sleeping"]은 9개의 단어로 구성된 벡터입니다. 이것은 매우 제한적인 심각한 문제입니다. 이러한 문제는 전통적 신경망 모델에서 잘 수행되지 않습니다.
데이터의 순서를 기억할 수 없습니다. 즉, 순서는 중요하지 않습니다.
데이터의 순서를 기억할 수 없거나 순서가 중요하지 않다는 것입니다.
예를 들어 이 문제를 이해합시다. "I am Ahmad, not Hassan"이라는 문장과 "I am Hassan, not Ahmad"라는 문장이 있다고 가정해 보겠습니다. 두 문장 모두 동일한 단어를 가지고 있기 때문에 전통적인 신경망은 이러한 문장을 동일하게 처리하지만 각 문장의 의미는 완전히 반대로 변경될 수 있습니다.
시퀀스 전체에서 매개변수를 공유할 수 없습니다.
이 문제를 이해하기 위해 "what is your name? My name is Ahmad" 이제 네트워크가 공통 단어를 동일하게 처리하기를 원할 것입니다. 이 경우 "name"이라는 공유 매개변수를 가져야 하며 신경망은 단일 시퀀스에서 "name"이 몇 번 나타나는지 알 수 있어야 합니다. 불행히도 기존 신경망은 이러한 유형의 패턴을 인식하지 못하므로 특정 기계 학습 솔루션에 적합하지 않습니다. 보시다시피, 이러한 제한은 단순한 신경망을 순차 작업에 적합하지 않게 만듭니다. 이는 언어 관련 작업이나 가변 입력이 있는 작업을 처리할 때 특히 제한적입니다.

이러한 제한은 단순한 신경망을 순차 작업에 적합하지 않게 만듭니다. 이는 언어 관련 작업이나 가변 입력이 있는 작업을 처리할 때 특히 제한적입니다.

이제 순차 작업에 필수적인 몇 가지 중요한 요구 사항을 살펴보겠습니다.

  1. 모델은 가변 길이 시퀀스를 처리할 수 있어야 합니다.
  2. 장기 종속성을 추적할 수 있음
  3. 순서에 대한 정보 유지
  4. 시퀀스 전체에서 매개변수를 공유합니다.

RNN

RNN(Recurrent Neural Networks)은 원래 기존의 신경망이 할 수 없는 요구 사항을 충족하도록 설계되었습니다. 다음은 전통적 신경망 모델과 RNN의 구조를 나타낸 것입니다.

위 그림에서와 같이 단순 신경망은 단방향입니다. 즉, 단일 방향을 갖는 반면, RNN은 타임스탬프(순서) t 동안 정보를 유지하기 위해 내부에 루프가 있습니다. 이것이 RNN이 "반복" 신경망으로 알려진 이유입니다. 이 반복에 의해 시퀀스에 대한 정보를 보존됩니다. 이제 내부에서 무슨 일이 일어나고 있는지 더 깊이 파헤쳐 보겠습니다. 단순화된 설명은 시퀀스를 처리하기 위해 모든 타임스탬프에 적용되는 반복 관계가 있다는 것입니다.

ht=fw(ht-1, xt)
- ht: 현재 셀 상태 - fw: 가중치들에 의해 매개변수화된 함수 - ht-1: 이전 또는 마지막 상태 - xt: 시간 단계 t에서의 입력 벡터

여기서 주목해야 할 중요한 점은 모든 타임스탬프에서 동일한 함수와 매개변수 세트를 사용하고 있다는 것입니다.

이제 이전 타임스탬프(또는 시퀀스 순서)를 무시하지 않으므로 현재 타임스탬프를 업데이트하는 데 도움이 되는 이전 타임스탬프인 ht-1을 통해 이를 확인할 수 있습니다. 입력 벡터 Xt가 주어지면 RNN은 표준 신경망 작업인 은닉 상태(hidden state)를 업데이트하는 기능을 적용합니다.

ht=tanh(WThh ht-1 + WTxhxt)

입력 벡터 Xt와 이전 상태 ht-1을 모두 함수에 입력합니다. 여기에 2개의 개별 가중치 행렬이 있고 이 2개의 가중치 행렬에 곱한 후 입력 Xt와 이전 상태 ht-1의 합에 비선형성(tanh)을 적용합니다. 마지막으로 타임스탬프 t에서 출력 벡터 ŷt를 갖게 됩니다.
$$\begin{equation}\hat{y}_t=W^T_{hy}h_t \end{equation}$$

위 함수는 이 내부 상태의 수정된 변형된 버전으로, 단순히 다른 가중치 행렬을 곱하여 생성됩니다. 이것은 단순히 RNN이 숨겨진 상태를 업데이트하고 출력을 계산하는 방법입니다. 위 그림의 RNN을 펼쳐보이면 위 식이 좀더 명백해 집니다.

  • Whh: 이전 상태를 업데이트하기 위한 가중치 행렬
  • Wxh: 입력값에 적용되는 가중치 행렬
  • Why: 출력 ŷ를 계산하기 위해 적용되는 가중치 행렬

위 그림에서 나타낸 것과 같이 모든 타임 스탬프에서 동일한 가중치 행렬을 사용할 것입니다. 각 시간단계에서 예측되는 $\hat{y}_0, \hat{y}_1, \cdots, \hat{y}_t$와 실측치와의 차이로 부터 비용(loss) l1, l2, …, lt를 계산할 수 있습니다. loss를 계산함으로 순방향 전파를 완료하고 RNN 섹션을 완료합니다.

  • RNN은 입력 및 이전 상태를 통해 은닉 상태를 업데이트합니다.
  • Wxh인 간단한 신경망 연산을 통해 출력 행렬을 계산합니다.
  • 출력을 반환하고 은닉 상태를 업데이트합니다.

위에서 언급한 각 시간단계의 모든 손실의 합계를 취하여 총 손실 L을 계산할 수 있습니다. 이를 통해 역전파를 진행할 수 있습니다. 다음은 RNN에서 역전파가 작동하는 방식을 시각적으로 나타낸 것입니다.

RNN의 역전파는 다음과 같은 주요 단계가 있는 단순 신경망의 역전파와 유사하게 작동합니다.

  • 각 매개변수의 손실의 미분을 계산
  • 손실(loss)를 최소화하는 방향으로 기존의 각 가중치에 대응하는 미분값을 고려하여 가중치 업데이트

그라디언트를 계산하는 과정에 Whh의 많은 요소와 반복되는 계산이 필요하므로 exploding gradient, vanishing gradient등의 문제가 발생될 수 있습니다.

Exploding Gradient

반복되는 그라디언트 계산과 관련된 결과가 매우 커져 최적화에 문제를 발생시키는 경우를 의미합니다. 이 문제는 본질적으로 그라디언트를 더 작은 값으로 축소하는 그라디언트 클리핑으로 알려진 프로세스를 통해 해결할 수 있습니다.

Vanishing Gradients

반복되는 기울기 계산과 관련된 많은 값이 너무 작거나 1보다 작을 때 발생합니다. 이 문제에서 기울기는 이러한 계산이 반복적으로 발생함에 따라 점점 작아집니다. 긴 시퀀스에서의 미분 계산 반복 횟수가 증가합니다. 이러한 경우 vanishing gradient가 발생할 수 있으며 학습이 진행되지 않습니다. 이러한 문제를 **장기적인 의존성 문제(problem of long term depencdency)**라 합니다.

이 문제는 3가지 방법으로 해결할 수 있습니다.

  • 활성함수(tanh 대신 ReLU 적용)
  • 가중치의 초기화
  • 네트워트 아키텍쳐의 변경

위 방법중 네트워크 아키텍처를 변경하는 방법으로 RNN의 아키텍처를 수정한 LSTM 또는 GRU(Gated Recurrent Units)와 같은 모델을 사용할 수 있습니다.

Long Short Term Memory (LSTMs)

LSTM은 Recurrent Neural Networks와 유사하게 작동하지만 RNN보다 더 잘 실행되는 특별한 유형의 Neural Networks이며, 장기적 종속성과 소실 그라디언트에 대한 RNN의 중요한 단점 중 일부를 추가로 해결합니다.

다음 그림은 단일 RNN 셀의 작업 흐름입니다.

위 그림의 RNN의 단일 블록 내에서 다음의 계산이 이루어 집니다.

  • tanh 활성화가 있는 단일 계산 레이어
  • ht는 위의 방정식과 같이 이전 셀 상태 ht-1과 현재 입력 Xt의 함수입니다.

LSTM에는 서로 다른 상호 작용 레이어가 있습니다. 이러한 레이어는 상호 작용하여 셀을 통한 정보 흐름을 선택적으로 제어합니다. LSTM의 핵심 빌딩 블록은 Gate로 알려진 구조입니다. 이 gate를 통해 정보가 추가되거나 제거됩니다. Gates는 예를 들어 아래 그림과 같이 시그모이드 레이어와 포인트별 곱셈을 통해 정보를 선택적으로 전달할 수 있습니다.

게이트는 시그모이드(sigmoid, σ)와 같은 신경망 레이어와 아래 그림에서 표시된 점별 곱셈과 덧셈으로 구성됩니다. Sigmoid는 게이트를 통과할 때 캡쳐되는 정보의 양을 [0, 1] 사이의 값으로 전환합니다. 예를 들어 0은 정보가 유지되지 않음을 의미하고 1은 모든 정보가 유지됨을 의미합니다. LSTM의 작동에 대해 더 자세히 알아보겠습니다.

적용

Python과 PyTorch를 사용하여 삼성전자의 주가를 예측하는 간단한 LSTM 모델을 살펴보겠습니다.

모델 적용에 적합하도록 데이터를 준비합니다. 이 과정에서는 데이터를 feature와 label로 분리하고 각각을 표준화 또는 정규화하는 데이터 전처리를 위한 것입니다. 또한 pytorch의 신경망 모형에서 사용하는 데이터 타입은 float32형입니다.

먼저 FinanceDataReader 패키지의 DataReader() 함수를 사용하여 주가 자료를 호출합니다.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn import metrics
from sklearn.model_selection import train_test_split
import torch
import torch.nn as nn
import torch.nn.functional as F
import FinanceDataReader as fdr
df=fdr.DataReader('005930', '2010, 1, 1','2022, 4, 6')
df.head(2)
Open High Low lose Volume Change
Date
2010-01-04 16060 16180 16000 16180 239271 0.012516
2010-01-05 16520 16580 16300 16440 559219 0.016069

위 자료중에서 Close의 일일 변화율을 분석하기 위해 그 열의 시퀀스 자료를 생성합니다. 이 분석에서는 직전 20일간의 종가 데이터로서 당일의 종가를 예측합니다.

pandas객체.pct_change(periods=1, fill_method="pad") 메소드를 적용합니다. 이 메소드의 인수 중 fill_method는 na등의 결측치를 조절하는 매개변수로서 'ffill'과 'bfill'의 인수를 가진다. 각각은 결측치를 그 위치의 직전값과 직후값으로 대체합니다.

cl=df["Close"].pct_change(periods=1, fill_method="ffill").dropna()
cl.head()
Date
2010-01-05 0.016069
2010-01-06 0.023114
2010-01-07 -0.033294
2010-01-08 0.009840
2010-01-11 -0.029233
Name: Close, dtype: float64

feature(특징)으로서 지연된 데이터 사용

시간 단계를 특징으로 사용하는 것부터 시작하겠습니다. 다시 말해, 이전 n개의 관측값 Xt, Xt+1, … , Xt+n-1에서 다음 값 Xt+n을 예측하려고 합니다.

다음은 Close를 label로 지연된 자료들을 feature로 합니다. 이 지연된 자료를 만들기 위해 pandsObject.shift() 메서드를 사용합니다.

ex=pd.DataFrame(cl)
ex['lag1']=cl.shift(1)
ex.head(3)
Close lag1
Date
2010-01-05 0.016069 NaN
2010-01-06 0.023114 0.016069
2010-01-07 -0.033294 0.023114

위 결과의 Na 행을 삭제하기 위해 pabdas의 dropna() 메소드를 적용합니다. 다양한 시간차이를 가지는 데이터를 생성하기 위해 다음과 같이 함수를 작성하여 사용합니다.

def generateTimesLag(data, nLag):
    df=data
    dfN=pd.DataFrame(df.copy())
    for n in range(1, nLag+1):
        dfN[f'lag{n}']=df.shift(n)
    dfN=dfN[nLag:]
    return(dfN)
    
data=generateTimesLag(cl, 20)
data.tail(2)
Close lag1 lag19 lag20
Date
2022-03-30 -0.004274 0.007174 -0.005548 0.002782
2022-03-31 -0.004292 -0.004274 0.016736 -0.005548

위 자료에서 feature(x, 지연된 Close)와 label(y, 현재의 Close)를 분리합니다. 또한 최종 구축한 모델에 적용할 특성(feature)인 tar 객체를 생성합니다.

dat=data.values.astype(np.float32)
x=dat[:,1:]
y=dat[:, :1] #하나의 열을 slice시 [시작:끝]과 같이 시작과 끝의 인덱스를 명시하면 DataFrame형이 됩니다.  
#반면에 [하나의 정수]와 같이 slice시 결과는 Series 형이 됩니다. 
tar=dat[-1,:-1].reshape(1, -1)
x.shape, y.shape, tar.shape
((3004, 20), (3004, 1), (1, 20))

x, y의 표준화를 위해 kleran.preprocessing.StandardScaler() 클래스를 적용합니다.

xss=StandardScaler().fit(x)
yss=StandardScaler().fit(y)
xn=xss.transform(x)
tarn=xss.transform(tar)
yn=yss.transform(y)
xn.shape, yn.shape, tarn.shape
((3004, 20), (3004, 1), (1, 20))

학습셋(train set)과 검정셋(test set)을 구분합니다. 이는 sklearn.model_selection.train_test_split() 함수를 사용합니다. 또한 이 과정까지의 데이터는 numpy 배열형입니다. 이를 pytorch tensor 형으로 전환합니다. 이것은 map()함수를 적용하여 위 과정에서 생성한 모든 데이터 셋을 일괄적으로 변환할 수 있습니다.

#train, test 분리 
xTr, xTe, yTr, yTe=train_test_split(xn, yn, test_size=0.15, shuffle=False)
xTr.shape, xTe.shape
((2553, 20), (451, 20))
#torch 형으로 전환 
xTrTensor, xTeTensor, yTrTensor, yTeTensor, tarTensor=map(torch.Tensor, [xTr, xTe, yTr, yTe, tarn])
xTrShape, xTeShape=xTrTensor.shape, xTeTensor.shape
xTrShape, tarTensor.shape
(torch.Size([2553, 20]), torch.Size([1, 20]))

LSTM은 sequence 데이터용으로 특별히 제작되었기 때문에 단순한 2차원 데이터를 입력으로 받을 수 없습니다. 하나의 행은 하나의 별도 타임 단계를 통과합니다. 그러므로 데이터 차원은 (행의수, 1, 열의수) 로 전환합니다. 이 차원에서 두번째 인수인 1이 sequence length가 됩니다.

xTrTensorFinal=torch.reshape(xTrTensor, (xTrShape[0], 1, xTrShape[1]))
xTeTensorFinal=torch.reshape(xTeTensor, (xTeShape[0], 1, xTeShape[1]))
xTrTensorFinal.shape, xTeTensorFinal.shape
(torch.Size([2553, 1, 20]), torch.Size([451, 1, 20]))

다음은 lstm의 모델(층)을 구성합니다. 이 모델은 다음의 LSTM1 클래스입니다. 이 클래스는 nn.Module 슈퍼클래스에서 상속합니다. 여기에서 모든 중요한 변수와 레이어를 정의했습니다. 다음으로 (hidden_size를 통해) 동일한 하이퍼파라미터가 서로 겹쳐진 2개의 LSTM 레이어를 사용할 것입니다. 2개의 완전 연결 레이어, ReLU 레이어 및 일부 변수를 정의했습니다. 다음으로 LSTM의 정방향 패스를 정의합니다.

class LSTM1(nn.Module):
    def __init__(self, num_classes, input_size, hidden_size, num_layers, seq_length):
        super(LSTM1, self).__init__()
        self.num_classes = num_classes #최종 출력 수
        self.num_layers = num_layers #lstm 층의 개수
        self.input_size = input_size #입력벡터의 feature 수
        self.hidden_size = hidden_size #은닉층의 feature 수(하이퍼파라메타)
        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) #밀집층(dense layer)
        self.relu = nn.ReLU()#비선형함수(활성함수)
        self.fc = nn.Linear(128, num_classes) #최종 밀집층
        
    
    def forward(self,x):
        h_0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size) #최초 은닉상태(초기화)
        c_0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size) #최초 셀상태(초기화)
        #위의 초기화를 정의하지 않으면 0으로 자동 할당 됩니다.
        # LSTM → activation → Dense layer → activation → Final Dense layer(output)의 통한 순전파
        output, (hn, cn) = self.lstm(x, (h_0, c_0)) #입력벡터featuretn,(h_0, c_0)
        #hn은 최종 은닉상태로서 (batch, sequence, feature)의 모양
        #다음 Dense Layer에 전달하기 위해 위의 3차원을 2차원으로 전환해야 합니다.
        hn = hn.view(-1, self.hidden_size) 
        out = self.relu(hn)
        out = self.fc_1(out) #first Dense
        out = self.relu(out) #relu
        out = self.fc(out) #Final Output
        return out

이것으로 Forward Pass와 LSTM1 클래스가 완성됩니다. 런타임에 모델을 훈련하는 동안 역전파 논리를 적용합니다. 사용할 몇 가지 중요한 변수를 정의 합니다. 이들은 Epoch 수, 숨겨진 크기 등과 같은 하이퍼파라미터입니다. 모델 인쇄를 통해 모델 통계를 볼 수 있습니다.

input_size = 20 #number of features
hidden_size = 8 #number of features in hidden state
num_layers = 1 #number of stacked lstm layers
num_classes = 1 #number of output classes 
lstm1=LSTM1(num_classes, input_size, hidden_size, num_layers, xTrTensorFinal.shape[1])
lstm1
LSTM1(
  (lstm): LSTM(20, 8, batch_first=True)
  (fc_1): Linear(in_features=8, out_features=128, bias=True)
  (relu): ReLU()
  (fc): Linear(in_features=128, out_features=1, bias=True)
)
learning_rate = 0.001 #0.0001 lr
criterion = torch.nn.MSELoss()    # mean-squared error for regression
optimizer = torch.optim.Adam(lstm1.parameters(), lr=learning_rate) 
num_epochs = 10000 #1000 epochs
for epoch in range(num_epochs+1):
    outputs = lstm1(xTeTensorFinal) #forward pass
    optimizer.zero_grad() #caluclate the gradient, manually setting to 0
    # obtain the loss function
    loss = criterion(outputs, yTeTensor)
    loss.backward() #calculates the loss of the loss function
    optimizer.step() #improve from loss, i.e backprop
    if epoch % 1000 == 0:
        print("Epoch: %d, loss: %1.5f" % (epoch, loss.item()))
Epoch: 0, loss: 0.77916
Epoch: 1000, loss: 0.02379
Epoch: 2000, loss: 0.00945
Epoch: 3000, loss: 0.00583
Epoch: 4000, loss: 0.00035
Epoch: 5000, loss: 0.00006
Epoch: 6000, loss: 0.00000
Epoch: 7000, loss: 0.00000
Epoch: 8000, loss: 0.00000
Epoch: 9000, loss: 0.00003
Epoch: 10000, loss: 0.00000

위 추정치는 표준화된 값들로 원래 스케일로 환원해주어야 합니다. 이것은 StandardScaler().inverse_trransform() 메소드를 사용합니다. 학습셋과 검정셋의 환원된 값들을 그래프로 그려보면 다음과 같습니다.

#train
yTr1= yss.inverse_transform(yTr)
yTrPre=yss.inverse_transform(lstm1(xTrTensorFinal).detach().numpy())
plt.figure(figsize=(13, 7))
plt.plot(range(len(yTr1)), yTr1, label="observe")
plt.plot(range(len(yTrPre)), yTrPre, alpha=0.3, label="prediction")
plt.xlabel('Time')
plt.ylabel("cost")
plt.legend(loc='best')
plt.show()
#test
yTe1= yss.inverse_transform(yTe)
yTePre=yss.inverse_transform(lstm1(xTeTensorFinal).detach().numpy())
plt.figure(figsize=(13, 7))
plt.plot(range(len(yTe1)), yTe1, label="observe")
plt.plot(range(len(yTePre)), yTePre,  '--',alpha=0.5,label="prediction")
plt.xlabel('Time')
plt.ylabel("cost")
plt.legend(loc='best')
plt.show()

최종 target 변수에 대한 추정을 시행합니다. 이 변수들을 위에서 구축한 lstm1 모델에 전달하기 위해서는 (sequence, 1, feature)와 같이 3차원으로 모양을 변환하고 원시 스케일로 환원해주어야 합니다.

#target=torch.tensor(ss.transform(data.iloc[-2:-1,:-1]), dtype=torch.float32)
target=torch.reshape(tarTensor, (tarTensor.shape[0], 1, tarTensor.shape[1]))
pre=yss.inverse_transform(lstm1(target).detach().numpy())
pre
array([[0.0040075]], dtype=float32)

위 결과는 전날과의 변화량입니다. 그러므로 원시데이터의 마지막 close에 대한 변화량이므로 다음과 같이 계산합니다.

preVal=df.values[-1, 3]*(1+float(pre))
preVal
68774.51347187161

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. $$\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B $$ 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. \begin{align}\tag{식 2} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align} 식 2의 행렬식은 식 3과 같이 정리됩니다. \begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \textsf{det}(I)\end{aligned}\end{align} 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같

[matplotlib] 히스토그램(Histogram)

히스토그램(Histogram) 히스토그램은 확률분포의 그래픽적인 표현이며 막대그래프의 종류입니다. 이 그래프가 확률분포와 관계가 있으므로 통계적 요소를 나타내기 위해 많이 사용됩니다. plt.hist(X, bins=10)함수를 사용합니다. x=np.random.randn(1000) plt.hist(x, 10) plt.show() 위 그래프의 y축은 각 구간에 해당하는 갯수이다. 빈도수 대신 확률밀도를 나타내기 위해서는 위 함수의 매개변수 normed=True로 조정하여 나타낼 수 있다. 또한 매개변수 bins의 인수를 숫자로 전달할 수 있지만 리스트 객체로 지정할 수 있다. 막대그래프의 경우와 마찬가지로 각 막대의 폭은 매개변수 width에 의해 조정된다. y=np.linspace(min(x)-1, max(x)+1, 10) y array([-4.48810153, -3.54351935, -2.59893717, -1.65435499, -0.70977282, 0.23480936, 1.17939154, 2.12397372, 3.0685559 , 4.01313807]) plt.hist(x, y, normed=True) plt.show()

R 미분과 적분

내용 expression 미분 2차 미분 mosaic를 사용한 미분 적분 미분과 적분 R에서의 미분과 적분 함수는 expression()함수에 의해 생성된 표현식을 대상으로 합니다. expression expression(문자, 또는 식) 이 표현식의 평가는 eval() 함수에 의해 실행됩니다. > ex1<-expression(1+0:9) > ex1 expression(1 + 0:9) > eval(ex1) [1] 1 2 3 4 5 6 7 8 9 10 > ex2<-expression(u, 2, u+0:9) > ex2 expression(u, 2, u + 0:9) > ex2[1] expression(u) > ex2[2] expression(2) > ex2[3] expression(u + 0:9) > u<-0.9 > eval(ex2[3]) [1] 0.9 1.9 2.9 3.9 4.9 5.9 6.9 7.9 8.9 9.9 미분 D(표현식, 미분 변수) 함수로 미분을 실행합니다. 이 함수의 표현식은 expression() 함수로 생성된 객체이며 미분 변수는 다음 식의 분모의 변수를 의미합니다. $$\frac{d}{d \text{변수}}\text{표현식}$$ 이 함수는 어떤 함수의 미분의 결과를 표현식으로 반환합니다. > D(expression(2*x^3), "x") 2 * (3 * x^2) > eq<-expression(log(x)) > eq expression(log(x)) > D(eq, "x") 1/x > eq2<-expression(a/(1+b*exp(-d*x))); eq2 expression(a/(1 + b * exp(-d * x))) > D(eq2, "x") a * (b * (exp(-d * x) * d))/(1 + b