๐ PyTorch๋ก ์๊ณ์ด ์์ธก์ ์ธ๊ณ์ ๋น ์ ธ๋ค๋ค
๋ฏธ๋๋ฅผ ์์ธกํ๋ ๊ฒ์ ์ธ์ ๋ ํฅ๋ฏธ๋ก์ด ์ผ์ด๋ค. ์ฃผ์ ๊ฐ๊ฒฉ์ ๋ฑ๋ฝ, ๋ด์ผ์ ๋ ์จ, ํน์ ๋ค์ ๋ถ๊ธฐ ๋งค์ถ๊น์ง. ์ด๋ฐ ์์ธก์ ์ค์ฌ์ ๋ฐ๋ก ์๊ณ์ด ๋ฐ์ดํฐ๊ฐ ์๋ค. ์ค๋์ PyTorch๋ฅผ ์ด์ฉํด ๊ณผ๊ฑฐ์ ๋ฐ์ดํฐ๋ก ๋ฏธ๋๋ฅผ ์ฟ๋ณด๋ ๋ค์ํ ๋ฅ๋ฌ๋ ๋ชจ๋ธ๋ค์ ํํํ๋ฉฐ, ์๊ณ์ด ์์ธก์ ๊ธฐ์ด๋ถํฐ ์ฐจ๊ทผ์ฐจ๊ทผ ์ ๋ณตํด๋๊ฐ ๊ณผ์ ์ ๊ธฐ๋กํ๋ค.
๐ก โ๊ณผ๊ฑฐ๋ ๋ฏธ๋์ ๊ฑฐ์ธ์ด๋ค.โ
์๊ณ์ด ๋ฐ์ดํฐ๋ ์๊ฐ์ ๋ฐ๋ผ ๊ธฐ๋ก๋ ๋ฐ์ดํฐ๋ก, ๊ทธ ์์๋ ํธ๋ ๋, ๊ณ์ ์ฑ, ์๊ธฐ ์๊ด ๋ฑ ๋ฏธ๋๋ฅผ ์์ธกํ ์ ์๋ ์ค์ํ ๋จ์๋ค์ด ์จ์ด์๋ค. ์ด ๋จ์๋ค์ ์ด๋ป๊ฒ ์ฐพ์๋ด๊ณ ํ์ฉํ๋์ง๊ฐ ์์ธก ๋ชจ๋ธ์ ์ฑํจ๋ฅผ ์ข์ฐํ๋ค.
๐ ์๊ณ์ด ๋ฐ์ดํฐ, ๋ฌด์์ ๋ด๊ณ ์์๊น?
์๊ณ์ด ๋ฐ์ดํฐ๋ ํฌ๊ฒ 4๊ฐ์ง ๊ณตํต ํน์ง์ ๊ฐ์ง๋ค. ์ด๋ค์ ์ดํดํ๋ ๊ฒ์ด ๋ถ์์ ์ฒซ๊ฑธ์์ด๋ค.
- ํธ๋ ๋ (Trend): ๋ฐ์ดํฐ๊ฐ ์ฅ๊ธฐ์ ์ผ๋ก ์์นํ๊ฑฐ๋ ํ๊ฐํ๋ ๋ฐฉํฅ์ฑ.
- ๊ณ์ ์ฑ (Seasonality): ํน์ ์ฃผ๊ธฐ๋ก ๋ฐ๋ณต๋๋ ํจํด (e.g., ์๋ณ, ๊ณ์ ๋ณ).
- ์๊ธฐ ์๊ด (Autocorrelation): ์ด์ ์์ ์ ๋ฐ์ดํฐ๊ฐ ํ์ฌ ๋๋ ๋ฏธ๋ ๋ฐ์ดํฐ์ ์ํฅ์ ๋ฏธ์น๋ ํ์.
- ์ก์ (Noise): ์์ธก ๋ถ๊ฐ๋ฅํ ์์์ ๋ณ๋.
์ด๋ฐ ํน์ง๋ค์ ์ฝ๋๋ก ์ง์ ๋ง๋ค์ด๋ณด๋ฉฐ ์๊ณ์ด ๋ฐ์ดํฐ์ ์นํด์ง๋ ์๊ฐ์ ๊ฐ์ก๋ค.
# ์๊ณ์ด ๋ฐ์ดํฐ ์์ฑ์ ์ํ ํจ์ ์ ์
import numpy as np
import matplotlib.pyplot as plt
def trend(time, slope=0):
return slope * time
def seasonal_pattern(season_time):
return np.where(season_time < 0.4,
np.cos(season_time * 2 * np.pi),
1 / np.exp(3 * season_time))
def seasonality(time, period, amplitude=1, phase=0):
season_time = ((time + phase) % period) / period
return amplitude * seasonal_pattern(season_time)
def noise(time, noise_level=1, seed=None):
rnd = np.random.RandomState(seed)
return rnd.randn(len(time)) * noise_level
# 4๋
์น ์๊ณ์ด ๋ฐ์ดํฐ ์์ฑ
time = np.arange(4 * 365 + 1, dtype="float32")
baseline = 10
amplitude = 15
noise_level = 6
series = baseline + trend(time, 0.05) + seasonality(time, period=365, amplitude=amplitude)
series += noise(time, noise_level, seed=42)
๐ ๏ธ ๋ฅ๋ฌ๋ ๋ชจ๋ธ๋ณ ์์ธก ๋์ ๊ธฐ
1. ์๋์ฐ ๋ฐ์ดํฐ์ : ์์ธก์ ์ํ ์ฌ๋ฃ ์์ง
๋ฅ๋ฌ๋ ๋ชจ๋ธ์ ์๊ณ์ด ๋ฐ์ดํฐ๋ฅผ ๋ฃ๊ธฐ ์ํด์ โ์๋์ฐโ ๋จ์๋ก ์๋ผ์ฃผ๋ ์์
์ด ํ์ํ๋ค. ํน์ ๊ธฐ๊ฐ(window)์ ๋ฐ์ดํฐ๋ฅผ ์
๋ ฅ(X)์ผ๋ก, ๋ฐ๋ก ๋ค์ ์์ ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ต(y)์ผ๋ก ๋ง๋๋ ๊ฒ์ด๋ค. PyTorch์ Dataset
๊ณผ DataLoader
๋ฅผ ํ์ฉํด ์ด ๊ณผ์ ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ค.
from torch.utils.data import Dataset, DataLoader
class WindowedDataset(Dataset):
def __init__(self, data, window_size, shift):
self.data = data
self.window_size = window_size
self.shift = shift
self.windows = [data[i:i+window_size+1] for i in range(0, len(data)-window_size, shift)]
def __len__(self):
return len(self.windows)
def __getitem__(self, idx):
window = self.windows[idx]
return window[:-1], window[-1:]
2. DNN (Deep Neural Network) ๋ชจ๋ธ
๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ Linear
๋ ์ด์ด๋ฅผ ์์ ๋ง๋ DNN ๋ชจ๋ธ๋ก ์ฒซ ์์ธก์ ์๋ํ๋ค. ๊ฒฐ๊ณผ๋ MSE 42.65, MAE 5.20. ์๊ฐ๋ณด๋ค ์ฑ๋ฅ์ด ์ข์ง ์์ ์์ฌ์ ๋ค. ๐ค
3. 1D CNN (Convolutional Neural Network) ๋ชจ๋ธ
Conv1d
๋ ์ด์ด๋ฅผ ์ฌ์ฉํด ์๊ณ์ด์ ์ง์ญ์ ํจํด์ ํฌ์ฐฉํ๋ CNN ๋ชจ๋ธ์ ๋ง๋ค์๋ค. ์ด๋ฏธ์ง ์ฒ๋ฆฌ์๋ง ์ฐ์ด๋ ์ค ์์๋ CNN์ ์๊ณ์ด์ ์ ์ฉํ๋ ์ ๊ธฐํ๋ค. ํ์ง๋ง ์ฑ๋ฅ์ MSE 44.18, MAE 5.32๋ก DNN๊ณผ ๋น์ทํ๋ค.
4. RNN (Recurrent Neural Network) ๋ชจ๋ธ
์์ฐจ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ๊ฐ์ ์ ๊ฐ์ง RNN์ ํฐ ๊ธฐ๋๋ฅผ ๊ฑธ์๋ค. ์ด์ ์คํ
์ ์ถ๋ ฅ์ ๋ค์ ์คํ
์ ์
๋ ฅ์ผ๋ก ์ฌ์ฉํ๋ โ๋๋จน์ ๊ตฌ์กฐโ ๋๋ถ์ ์๊ณ์ด์ โํ๋ฆโ์ ํ์ตํ ์ ์์๋ค. yfinance
๋ก ์ค์ AAPL ์ฃผ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ์์ธก์ ์งํํ๋ ํจ์ฌ ํฅ๋ฏธ๋ก์ ๋ค. ๐
# RNN ๋ชจ๋ธ ์ ์
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, seq_size):
super(RNN, self).__init__()
self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)
self.fc1 = nn.Linear(seq_size * hidden_size, 64)
self.output = nn.Linear(64, 1)
self.relu = nn.ReLU()
def forward(self, x, h0=None):
# ... (forward pass logic)
return torch.flatten(x)
5. LSTM (Long Short-Term Memory) ๋ชจ๋ธ
RNN์ ์ฅ๊ธฐ ์์กด์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ LSTM์ ์ญ์ ๊ฐ๋ ฅํ๋ค. โ์ ์ํ(Cell State)โ์ 3๊ฐ์ ๊ฒ์ดํธ(๋ง๊ฐ, ์ ๋ ฅ, ์ถ๋ ฅ)๋ฅผ ํตํด ์ ๋ณด์ ํ๋ฆ์ ์ ๊ตํ๊ฒ ์ ์ดํ๋ ๊ตฌ์กฐ๊ฐ ์ธ์ ๊น์๋ค. RNN๋ณด๋ค ๋ณต์กํ์ง๋ง, ๊ทธ๋งํผ ์ฅ๊ธฐ์ ์ธ ํจํด์ ์ ํ์ตํด๋ด๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.
LSTM์ ํต์ฌ์ ์ ๋ณด๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ธฐ์ตํ๊ณ ์๋ ๋ฅ๋ ฅ์ ์๋ค. ๋๋ถ์ ๋ฉ๋ฆฌ ๋จ์ด์ง ๊ณผ๊ฑฐ์ ๋ฐ์ดํฐ๊ฐ ํ์ฌ ์์ธก์ ๋ฏธ์น๋ ์ํฅ์ ํฌ์ฐฉํ ์ ์๋ค.
# LSTM ๋ชจ๋ธ ์ ์
class LSTM(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, seq_size):
super(LSTM, self).__init__()
self.lstm = nn.LSTM(input_size=input_size,
hidden_size=hidden_size,
num_layers=num_layers,
batch_first=True)
self.fc1 = nn.Linear(in_features=seq_size * hidden_size, out_features=64)
self.fc2 = nn.Linear(in_features=64, out_features=1)
self.relu = nn.ReLU()
def forward(self, x, h0, c0):
x, (hn, cn) = self.lstm(x, (h0, c0))
x = torch.reshape(x, (x.shape[0], -1))
x = self.relu(self.fc1(x))
x = self.fc2(x)
return x
โจ ์ค๋์ ํ๊ณ
์ค๋์ ์๊ณ์ด ๋ฐ์ดํฐ์ ํน์ง๋ถํฐ ์์ํด DNN, CNN, RNN, ๊ทธ๋ฆฌ๊ณ LSTM์ ์ด๋ฅด๊ธฐ๊น์ง ๋ค์ํ ๋ฅ๋ฌ๋ ๋ชจ๋ธ๋ก ์์ธก์ ์ํํด๋ดค๋ค. ๊ฐ ๋ชจ๋ธ์ ๊ตฌ์กฐ์ ์ฅ๋จ์ ์ ์ฝ๋๋ก ์ง์ ๊ตฌํํ๋ฉฐ ๋น๊ตํด๋ณด๋ ์ด๋ก ์ผ๋ก๋ง ๋ฐฐ์ฐ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ช ํํ๊ฒ ์ดํดํ ์ ์์๋ค. ํนํ RNN๊ณผ LSTM์ด ์ ์๊ณ์ด ๋ฐ์ดํฐ์ ์ ํฉํ์ง, ๊ทธ ๊ตฌ์กฐ์ ์ฐจ์ด๊ฐ ์ฑ๋ฅ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น๋์ง ์ฒด๊ฐํ ์ ์๋ ์ข์ ๊ฒฝํ์ด์๋ค.
๋ค์์๋ Transformer ๊ธฐ๋ฐ์ ๋ชจ๋ธ(e.g., Informer
, Autoformer
)์ ์ฌ์ฉํด ์๊ณ์ด ์์ธก์ ๋์ ํด๋ณด๊ณ ์ถ๋ค. LSTM์ ๋ฐ์ด๋๋ ์ฑ๋ฅ์ ๋ณด์ฌ์ค๋ค๊ณ ํ๋, ์ผ๋ง๋ ๋ ์ ํํ ์์ธก์ด ๊ฐ๋ฅํ ์ง ๊ธฐ๋๋๋ค. ๐