0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】PyTorchでUSDJPYの価格予測をしてみた

Posted at

PyTorchを初めて使い、USDJPYの価格予測をしてみました.
色々、試行錯誤しましたが、損失があまり変わらないです.
移動平均線みたいな予測になってますね.
過学習かどうかの判断が難しいな...

%matplotlib inline

import matplotlib.pyplot as plt
import pandas as pd
pd.set_option('display.max_columns', None)
df = pd.read_csv('candle_d_dmi_close_5.csv')
df.head()
time volume open high low close spread tr plus_dm minus_dm smoothed_tr smoothed_plus_dm smoothed_minus_dm plus_di minus_di dx adx
0 2016-09-01 0.0 103.409 103.996 103.058 103.230 0.017 0.938 0.508 0.000 0.938 0.169 0.000 18.053 0.000 100.000 100.000
1 2016-09-02 0.0 103.238 104.319 102.799 103.761 0.265 1.520 0.323 0.000 1.132 0.221 0.000 19.484 0.000 100.000 100.000
2 2016-09-05 0.0 104.047 104.107 103.144 103.405 0.044 0.963 0.000 0.000 1.076 0.147 0.000 13.669 0.000 100.000 100.000
3 2016-09-06 0.0 103.398 103.805 101.929 102.011 0.014 1.876 0.000 1.215 1.342 0.098 0.405 7.302 30.169 61.026 87.009
4 2016-09-07 0.0 101.996 102.128 101.205 101.737 0.010 0.923 0.000 0.724 1.203 0.065 0.511 5.434 42.518 77.336 83.784
# import
%matplotlib inline

import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.preprocessing import MinMaxScaler, StandardScaler
import matplotlib.pyplot as plt
from torch.utils.data import Dataset, DataLoader
from sklearn.model_selection import train_test_split
# Dataset
class TimeSeriesDataset(Dataset):
    def __init__(self, X, y):
        self.X = torch.tensor(X, dtype=torch.float32)
        self.y = torch.tensor(y, dtype=torch.float32)
        
    def __len__(self):
        return len(self.X)
    
    def __getitem__(self, idx):
        return self.X[idx], self.y[idx]
# Model
class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size):
        super(LSTMModel, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
        
    def forward(self, x):
        # LSTMの初期状態を初期化
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        
        # LSTM出力
        out, _ = self.lstm(x, (h0, c0))
        
        # 最後のタイムステップの出力を使用
        out = self.fc(out[:, -1, :])
        return out
# Sequence
def create_sequences(X, y, seq_length):
    X_seq, y_seq = [], []
    for i in range(len(X) - seq_length):
        X_seq.append(X[i:i+seq_length])
        y_seq.append(y[i+seq_length])  # t+1の予測
    return np.array(X_seq), np.array(y_seq)
# Main
feature_columns = ['close', 'plus_di', 'minus_di']
target_column = 'close'

sequence_lens = range(200, 201, 10)
split_ratio = 0.8
batch_size = 1000

hidden_sizes = range(200, 201, 10)
num_layers = 3
output_size = 1
num_epochs = 100

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# データ読み込み
# df = pd.read_csv('your_data.csv')

X = df[feature_columns].values
y = df[target_column].values.reshape(-1, 1)

# データの前処理(スケーリング)
X_scaler = StandardScaler()
y_scaler = StandardScaler()

X_scaled = X_scaler.fit_transform(X)
y_scaled = y_scaler.fit_transform(y)

for sequence_len in sequence_lens:
    # シーケンスデータの作成
    X_seq, y_seq = create_sequences(X_scaled, y_scaled, sequence_len)
    
    # トレーニングデータとテストデータに分割
    split_idx = int(len(X_seq) * split_ratio)
    
    X_train, X_test = X_seq[:split_idx], X_seq[split_idx:]
    y_train, y_test = y_seq[:split_idx], y_seq[split_idx:]
    
    # データローダーの作成
    train_dataset = TimeSeriesDataset(X_train, y_train)
    test_dataset = TimeSeriesDataset(X_test, y_test)
    
    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=False)
    test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
    
    for hidden_size in hidden_sizes:
        print(f"Sequence length: {sequence_len}, Hidden size: {hidden_size}")
        
        # モデルの定義
        model = LSTMModel(X_train.shape[2], hidden_size, num_layers, output_size).to(device)
        
        # 損失関数
        criterion = nn.MSELoss()
        optimizer = optim.Adam(model.parameters(), lr=0.001)
        
        # 訓練・テスト
        train_losses, test_losses = [], []
        
        for epoch in range(num_epochs):
            # 訓練
            model.train()
        
            train_loss = 0
            
            for X_batch, y_batch in train_loader:
                X_batch, y_batch = X_batch.to(device), y_batch.to(device)
                
                # フォワードパス
                outputs = model(X_batch)
        
                # 損失
                loss = criterion(outputs, y_batch)
                
                # バックワードパスと最適化
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
                
                train_loss += loss.item()
            
            # テスト
            model.eval()
            
            test_loss = 0
            
            with torch.no_grad():
                for X_batch, y_batch in test_loader:
                    X_batch, y_batch = X_batch.to(device), y_batch.to(device)
                    
                    outputs = model(X_batch)
        
                    # 損失
                    loss = criterion(outputs, y_batch)
                    
                    test_loss += loss.item()
            
            # 損失
            train_losses.append(train_loss / len(train_loader))
            test_losses.append(test_loss / len(test_loader))
        
            if (epoch+1) % 10 == 0:
                print(
                    f'Epoch [{epoch+1:03}/{num_epochs:03}], '
                    f'Train Loss: {train_losses[-1]:.4f}, '
                    f'Test Loss: {test_losses[-1]:.4f}'
                )
    
        # 予測・評価
        model.eval()
        
        predictions, actuals = [], []
        
        # 予測
        with torch.no_grad():
            for X_batch, y_batch in test_loader:
                X_batch = X_batch.to(device)
        
                outputs = model(X_batch)
                
                predictions.extend(outputs.cpu().numpy())
                actuals.extend(y_batch.cpu().numpy())
        
        # スケールを元に戻す
        predictions = y_scaler.inverse_transform(np.array(predictions))
        actuals = y_scaler.inverse_transform(np.array(actuals))
        
        # 評価
        mse = np.mean((predictions - actuals) ** 2)
        rmse = np.sqrt(mse)
        mae = np.mean(np.abs(predictions - actuals))
        
        print(f'Mean Squared Error     : {mse:.4f}')
        print(f'Root Mean Squared Error: {rmse:.4f}')
        print(f'Mean Absolute Error    : {mae:.4f}')
    
        # 可視化
        plt.figure(figsize=(20, 12))
        
        # 訓練・テストの損失
        plt.subplot(2, 1, 1)
        plt.plot(train_losses, label='Training Loss')
        plt.plot(test_losses, label='Testing Loss')
        plt.title('Model Loss')
        plt.xlabel('Epochs')
        plt.ylabel('Loss')
        plt.legend()
        
        # 実績・予測
        plt.subplot(2, 1, 2)
        plt.plot(actuals, label='Actual Price')
        plt.plot(predictions, label='Predicted Price')
        plt.title('Price Prediction')
        plt.xlabel('Time Steps')
        plt.ylabel('Price')
        plt.legend()
        
        plt.tight_layout()
        plt.show()
Sequence length: 200, Hidden size: 200
Epoch [010/100], Train Loss: 0.0606, Test Loss: 0.1134
Epoch [020/100], Train Loss: 0.0379, Test Loss: 0.1359
Epoch [030/100], Train Loss: 0.0118, Test Loss: 0.0716
Epoch [040/100], Train Loss: 0.0069, Test Loss: 0.0334
Epoch [050/100], Train Loss: 0.0047, Test Loss: 0.0221
Epoch [060/100], Train Loss: 0.0036, Test Loss: 0.0162
Epoch [070/100], Train Loss: 0.0035, Test Loss: 0.0160
Epoch [080/100], Train Loss: 0.0034, Test Loss: 0.0162
Epoch [090/100], Train Loss: 0.0033, Test Loss: 0.0156
Epoch [100/100], Train Loss: 0.0033, Test Loss: 0.0152
Mean Squared Error     : 2.8465
Root Mean Squared Error: 1.6871
Mean Absolute Error    : 1.2243

output_8_1.png

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?