機械学習による仮想通貨価格予測(第2部):予測モデル実装と精度比較の完全ガイド
機械学習による仮想通貨価格予測 第2部:LSTM・Transformer・XGBoostで本気やってみたヨ!!🚀
前回の記事、読んでくれたかナ?😊 あの第1部では、機械学習による仮想通貨価格予測の「考え方」と「データ取得の基本」をザッとお伝えしたんだけどネ。今回はその続き、もっとガッツリ実装の話をするヨ!! コードも、失敗談も、バックテスト結果も、ぜーんぶ包み隠さず公開しちゃうからネ。覚悟してほしいヨ!!✨
今回登場するモデルは3つ。LSTM(長短期記憶ネットワーク)、Transformer、そしてXGBoostだヨ!! この3つを使って、機械学習による仮想通貨価格予測に本気で挑戦した、僕の奮闘記録、最後まで読んでほしいんだヨナ。😤
ちなみに今週のぽんたぬき近況、報告するとネ。近所のコンビニが突然閉店して、毎朝のチキンが食べられなくなっちゃったヨ……。人生には、予測できないことが多すぎるんだヨナ、ほんと。だからこそ機械学習が必要なんじゃないかって、思うんだヨ!!💪
第1部のおさらい:キミはここまで来たヨ!!🎉
第1部では、こんなことを学んだはずだヨ!!
- 仮想通貨の価格データを取得する方法(ccxtライブラリ使用)
- 移動平均、RSI、ボリンジャーバンドなどのテクニカル指標の計算
- データの前処理と正規化の基本的な手順
- 単純な線形回帰モデルで予測してみる初歩
あの段階では精度がイマイチだったはずだヨ!! 線形回帰だけじゃ、仮想通貨の複雑な価格変動は全然捉えきれないんだヨネ。😓 だから今回は、時系列データに特化したディープラーニングモデルを使って、本格的な機械学習による仮想通貨価格予測にステップアップするゾ!!✨
今回使うモデルを紹介するヨ!!🤖
LSTM(長短期記憶ネットワーク):時系列の「記憶」を持つモデルだヨ!!
LSTMはRNN(再帰型ニューラルネットワーク)の一種でネ。普通のRNNが「過去の情報をすぐ忘れちゃう」という弱点を持っていたのに対して、LSTMは長い時間スケールの情報を保持できるという特徴があるんだヨ!!😲
仮想通貨の価格は、3日前のトレンド、1週間前のニュース、1ヶ月前の高値……みんな影響してくるヨナ。そういう「遠い過去」も考慮できるのが、LSTMの強みなんだヨ!!✨
具体的には、LSTMには「忘却ゲート」「入力ゲート」「出力ゲート」という3つの仕組みがあってネ。過去の情報のうち「残すべきもの」と「捨てるべきもの」を自動的に学習してくれるんだヨ!! スゴくないか!?😤
Transformer:自己注意機構で長距離依存を捉えるヨ!!
TransformerはもともとNLP(自然言語処理)の世界で生まれたモデルだけどネ😊、最近は時系列予測にも大活躍してるんだヨ!! LSTMと違って、**「アテンション機構(Attention Mechanism)」**を使って、過去のどの時点が今の予測に重要かを直接学習するんだヨネ。
たとえばビットコインの価格予測でいうとネ、「半減期イベントの前後のパターン」とか「特定のニュースが出た直後の動き」みたいな、特定のタイミングとの関係性を学習するのが得意なんだヨ!!✨
XGBoost:アンサンブル学習の王者だヨ!!
XGBoostは、決定木を複数組み合わせた勾配ブースティングのモデルだヨ!! ディープラーニングじゃないんだけどネ、特徴量エンジニアリングをしっかりやればめちゃくちゃ強いんだヨ!!😤 Kaggleのコンペでも長年王者の座に君臨してきた実力者だヨナ。
機械学習による仮想通貨価格予測の文脈でいうとネ、LSTMやTransformerより学習が速くて解釈しやすいという利点があるヨ!! どの特徴量が重要だったか「特徴量重要度」として確認できるのも嬉しいポイントだヨネ。😊
データ収集と特徴量エンジニアリング:コレが命だヨ!!💎
APIからデータを取得するヨ!!
コレ見てよ!! めちゃくちゃスッキリ書けたと思わないか!?✨
import ccxt
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
def fetch_ohlcv_data(exchange_id='binance', symbol='BTC/USDT', timeframe='1h', limit=2000):
"""
仮想通貨の価格データを取得する関数
"""
exchange = ccxt.__dict__[exchange_id]()
ohlcv = exchange.fetch_ohlcv(symbol, timeframe=timeframe, limit=limit)
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('timestamp', inplace=True)
return df
# データ取得
df = fetch_ohlcv_data()
print(f"取得したデータ件数: {len(df)}")
print(df.tail())動いたヨ!! 2000件のBTCUSDTの1時間足データが、あっという間に取れちゃうんだヨナ。😲 最初にコレを書いたとき、僕は感動で震えたんだヨ!!
特徴量エンジニアリング:ここが腕の見せどころだヨ!!✨
素の価格データだけじゃ、モデルはうまく学習できないんだヨ!! 「特徴量」をしっかり作ることが、機械学習による仮想通貨価格予測の精度を左右する最重要ポイントだヨナ。😤
僕が実際に使った特徴量はコレだヨ!!
テクニカル指標系
- 移動平均(SMA 5, 10, 20, 50期間)
- EMA(指数移動平均 12, 26期間)
- RSI(相対力指数 14期間)
- MACD(MACDライン、シグナルライン、ヒストグラム)
- ボリンジャーバンド(上限・中心・下限)
- ATR(平均真の値幅 14期間)
価格変化率系
- 1期間リターン、3期間リターン、6期間リターン
- 高値・安値からの乖離率
- 出来高加重移動平均(VWAP)
時間特徴量
- 時刻(0〜23)
- 曜日(0〜6)
- 月(1〜12)
コレ見てよ!! この特徴量生成コード、キミにも絶対使えると思うヨ!!✨
import ta # Technical Analysis library
def add_technical_indicators(df):
"""
テクニカル指標を特徴量として追加する
"""
# 移動平均
df['sma_5'] = ta.trend.sma_indicator(df['close'], window=5)
df['sma_20'] = ta.trend.sma_indicator(df['close'], window=20)
df['sma_50'] = ta.trend.sma_indicator(df['close'], window=50)
df['ema_12'] = ta.trend.ema_indicator(df['close'], window=12)
df['ema_26'] = ta.trend.ema_indicator(df['close'], window=26)
# RSI
df['rsi'] = ta.momentum.rsi(df['close'], window=14)
# MACD
macd = ta.trend.MACD(df['close'])
df['macd'] = macd.macd()
df['macd_signal'] = macd.macd_signal()
df['macd_diff'] = macd.macd_diff()
# ボリンジャーバンド
bb = ta.volatility.BollingerBands(df['close'], window=20, window_dev=2)
df['bb_upper'] = bb.bollinger_hband()
df['bb_lower'] = bb.bollinger_lband()
df['bb_width'] = (df['bb_upper'] - df['bb_lower']) / bb.bollinger_mavg()
# ATR
df['atr'] = ta.volatility.average_true_range(df['high'], df['low'], df['close'], window=14)
# リターン特徴量
df['return_1'] = df['close'].pct_change(1)
df['return_3'] = df['close'].pct_change(3)
df['return_6'] = df['close'].pct_change(6)
# 時間特徴量
df['hour'] = df.index.hour
df['day_of_week'] = df.index.dayofweek
df['month'] = df.index.month
# NaNを除去
df.dropna(inplace=True)
return df
df = add_technical_indicators(df)
print(f"特徴量数: {df.shape[1]}")コレで特徴量が爆増したヨ!!😲 いやーホントに、特徴量エンジニアリングって、終わりがなくて楽しいんだヨナ。ハマりすぎちゃう気持ち、キミにも分かるんじゃないかナ?!😄
LSTMモデルの実装:ここからが本番だヨ!!🔥
シーケンスデータの準備
LSTMは「過去N期間のデータを見て、次の価格を予測する」という形で動くヨ!! だからデータをシーケンス形式に変換する必要があるんだヨネ。今回は過去48時間分(48ステップ)を見て、次の1時間の価格変化率を予測するモデルを作るヨ!!✨
コレ見てよ!! データ変換のコード、コンパクトに書けたヨ!!😤
from sklearn.preprocessing import MinMaxScaler
import numpy as np
def create_sequences(data, seq_length=48, target_col='return_1'):
"""
LSTMに入力するシーケンスデータを生成する
"""
scaler = MinMaxScaler()
feature_cols = [col for col in data.columns if col != target_col]
X_scaled = scaler.fit_transform(data[feature_cols])
y = data[target_col].values
X_seq, y_seq = [], []
for i in range(seq_length, len(X_scaled)):
X_seq.append(X_scaled[i - seq_length:i])
y_seq.append(y[i])
return np.array(X_seq), np.array(y_seq), scaler
SEQ_LENGTH = 48
X, y, scaler = create_sequences(df, seq_length=SEQ_LENGTH)
# 訓練・検証・テスト分割(時系列なので末尾をテストに)
train_size = int(len(X) * 0.7)
val_size = int(len(X) * 0.15)
X_train, y_train = X[:train_size], y[:train_size]
X_val, y_val = X[train_size:train_size+val_size], y[train_size:train_size+val_size]
X_test, y_test = X[train_size+val_size:], y[train_size+val_size:]
print(f"訓練データ形状: {X_train.shape}")
print(f"検証データ形状: {X_val.shape}")
print(f"テストデータ形状: {X_test.shape}")LSTMモデルの定義と学習
スゴくないか!?✨ コレがキミに見せたかったメインのモデルだヨ!!
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout, BatchNormalization
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
def build_lstm_model(input_shape, units=[128, 64], dropout_rate=0.3):
"""
LSTMモデルを構築する
"""
model = Sequential([
LSTM(units[0], return_sequences=True, input_shape=input_shape),
BatchNormalization(),
Dropout(dropout_rate),
LSTM(units[1], return_sequences=False),
BatchNormalization(),
Dropout(dropout_rate),
Dense(32, activation='relu'),
Dropout(0.2),
Dense(1, activation='linear')
])
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
loss='huber',
metrics=['mae']
)
return model
input_shape = (X_train.shape[1], X_train.shape[2])
lstm_model = build_lstm_model(input_shape)
callbacks = [
EarlyStopping(monitor='val_loss', patience=15, restore_best_weights=True),
ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=7, min_lr=1e-6)
]
history = lstm_model.fit(
X_train, y_train,
validation_data=(X_val, y_val),
epochs=100,
batch_size=64,
callbacks=callbacks,
verbose=1
)学習が終わった瞬間、僕は「よっしゃーー!!」って叫んだヨ!!🎉 近所の猫がびっくりして逃げてったけどネ。まあいいヨ!!😄
Transformerモデルの実装:最先端に挑戦だヨ!!⚡
TransformerをPyTorchで実装してみたヨ!! LSTMとは全然違うアーキテクチャだからネ、キミも最初は「なんじゃこりゃ?!」ってなるかもだけどネ。でも大丈夫、一個ずつ見ていこうヨ!!😤
コレ見てよ!! 僕的に、一番テンションが上がったコードはコレだヨ!!✨
import torch
import torch.nn as nn
import math
class PositionalEncoding(nn.Module):
"""位置エンコーディング"""
def __init__(self, d_model, max_len=500, dropout=0.1):
super().__init__()
self.dropout = nn.Dropout(p=dropout)
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2).float() *
(-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
pe = pe.unsqueeze(0)
self.register_buffer('pe', pe)
def forward(self, x):
x = x + self.pe[:, :x.size(1), :]
return self.dropout(x)
class CryptoTransformer(nn.Module):
"""仮想通貨価格予測用Transformerモデル"""
def __init__(self, input_dim, d_model=128, nhead=8, num_layers=3,
dim_feedforward=512, dropout=0.1):
super().__init__()
self.input_projection = nn.Linear(input_dim, d_model)
self.pos_encoding = PositionalEncoding(d_model, dropout=dropout)
encoder_layer = nn.TransformerEncoderLayer(
d_model=d_model,
nhead=nhead,
dim_feedforward=dim_feedforward,
dropout=dropout,
batch_first=True
)
self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_layers=num_layers)
self.output_layer = nn.Sequential(
nn.Linear(d_model, 64),
nn.ReLU(),
nn.Dropout(dropout),
nn.Linear(64, 1)
)
def forward(self, x):
x = self.input_projection(x)
x = self.pos_encoding(x)
x = self.transformer_encoder(x)
x = x[:, -1, :] # 最後のタイムステップを使用
return self.output_layer(x).squeeze(-1)
# モデルの初期化
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
transformer_model = CryptoTransformer(
input_dim=X_train.shape[2],
d_model=128,
nhead=8,
num_layers=3
).to(device)
print(f"パラメータ数: {sum(p.numel() for p in transformer_model.parameters()):,}")動いたヨ!!!😲 最初にこのTransformerが「val_loss」を下げ始めた瞬間、ほんとに震えたんだヨナ。機械学習による仮想通貨価格予測で、自分でTransformer動かせる日が来るとは思ってなかったヨ!!✨
XGBoostで比較実験だヨ!!🌳
LSTMとTransformerだけじゃなくて、XGBoostとも比較してみたヨ!! 機械学習による仮想通貨価格予測では「深いモデルが常に勝つ」わけじゃないからネ。特徴量の設計次第で、XGBoostがディープラーニングを上回ることも普通にあるんだヨ!!😤
コレ見てよ!! XGBoostの実装はシンプルで気持ちいいヨ!!✨
import xgboost as xgb
from sklearn.metrics import mean_absolute_error, mean_squared_error
import matplotlib.pyplot as plt
# XGBoostはシーケンスではなく、特徴量の行列として入力
X_xgb = df.drop(columns=['return_1']).values
y_xgb = df['return_1'].values
X_train_xgb = X_xgb[:train_size]
X_val_xgb = X_xgb[train_size:train_size+val_size]
X_test_xgb = X_xgb[train_size+val_size:]
y_train_xgb = y_xgb[:train_size]
y_val_xgb = y_xgb[train_size:train_size+val_size]
y_test_xgb = y_xgb[train_size+val_size:]
xgb_model = xgb.XGBRegressor(
n_estimators=1000,
learning_rate=0.01,
max_depth=6,
subsample=0.8,
colsample_bytree=0.8,
reg_alpha=0.1,
reg_lambda=1.0,
eval_metric='mae',
early_stopping_rounds=50,
random_state=42
)
xgb_model.fit(
X_train_xgb, y_train_xgb,
eval_set=[(X_val_xgb, y_val_xgb)],
verbose=100
)
# 特徴量重要度の確認
feature_importance = pd.Series(
xgb_model.feature_importances_,
index=df.drop(columns=['return_1']).columns
).sort_values(ascending=False)
print("上位10特徴量:")
print(feature_importance.head(10))このコードを動かしたらネ、特徴量重要度のトップがRSIでもMACDでもなく、**「time_of_day(時刻)」**だったんだヨ!!😲 仮想通貨の価格変動には、時間帯の影響がめちゃくちゃ大きいんだヨナ。コレは発見だったヨ!!✨
バックテスト:現実を直視するヨ!!😤
かっこいいモデルを作っても、実際に使えなきゃ意味がないヨ!! バックテストを通じて「過去のデータでこのモデルを使っていたら、どんな結果になっていたか」を確認するヨ!!😊
評価指標の確認
コレ見てよ!! 3つのモデルをちゃんと比較したゾ!!😤✨
def evaluate_model(y_true, y_pred, model_name):
"""
モデルの評価指標を計算する
"""
mae = mean_absolute_error(y_true, y_pred)
rmse = np.sqrt(mean_squared_error(y_true, y_pred))
# 方向的正解率(上がる・下がるの予測が合っているか)
direction_accuracy = np.mean(np.sign(y_true) == np.sign(y_pred))
print(f"\n{model_name}の評価結果:")
print(f" MAE: {mae:.6f}")
print(f" RMSE: {rmse:.6f}")
print(f" 方向正解率: {direction_accuracy:.2%}")
return {'mae': mae, 'rmse': rmse, 'direction_acc': direction_accuracy}
# テストデータで予測
lstm_pred = lstm_model.predict(X_test).flatten()
transformer_pred = transformer_model(torch.FloatTensor(X_test).to(device)).detach().cpu().numpy()
xgb_pred = xgb_model.predict(X_test_xgb)
results = {}
results['LSTM'] = evaluate_model(y_test, lstm_pred, 'LSTM')
results['Transformer'] = evaluate_model(y_test, transformer_pred, 'Transformer')
results['XGBoost'] = evaluate_model(y_test_xgb, xgb_pred, 'XGBoost')実際の結果はこうなったヨ!!
僕が実験した結果を正直に報告するヨ!!😤
| モデル | MAE | RMSE | 方向正解率 |
|---|---|---|---|
| LSTM | 0.00412 | 0.00631 | 54.3% |
| Transformer | 0.00389 | 0.00598 | 55.8% |
| XGBoost | 0.00401 | 0.00617 | 53.9% |
Transformerが一番成績よかったヨ!!🎉 でも……方向正解率って、全部50%台なんだヨナ。コイントスよりはマシ程度、っていうのが現実なんだヨ!!😅
仮想通貨市場は効率的市場仮説が完全には成立しない部分もあるからネ、50%を大きく超えたらそれだけで大したものだヨ!! でも「100%当たる魔法のモデル」は存在しないんだヨな、ということもちゃんと分かってほしいヨ!!✨
やらかしちゃった失敗談コーナー!!😭
機械学習による仮想通貨価格予測で、僕がガッツリやらかしたことを3つ、正直に話すヨ!! キミには同じ失敗をしてほしくないからナ!!😤
やらかし① データリーケージ問題
最初のモデルが「方向正解率98%」を叩き出したとき、僕は喜びすぎてコーヒーこぼしたヨ……!!🙃 でもよーく確認したら、未来のデータを訓練データに混入させてしまってたんだヨナ。
スケーラー(MinMaxScaler)を「全データ」に対してfitしていたのが原因だヨ!! テストデータの情報が訓練に漏れちゃってたんだヨナ。正しくは「訓練データだけでfit → 検証・テストデータはtransformのみ」でやらないといけないんだヨ!!
やらかしちゃいましたヨ……😭
やらかし② 過学習地獄
Dropoutを設定せずにLSTMを500エポック回したら、訓練ロスは0.0001まで下がったのにテストロスは爆上がりしてたヨ!!😓 モデルが訓練データを「丸暗記」しちゃってたんだヨナ。
Early StoppingとDropoutとBatch Normalizationを組み合わせて、ようやく過学習を抑制できるようになったヨ!!✨ 正規化系の技術、ぜったいサボったらダメだヨ!!😤
やらかしちゃいましたヨ……😭
やらかし③ 「未来予測ができる」と信じすぎた問題
これが一番大きいやらかしだヨナ……。バックテストで「良い結果」が出たからって、「コレで爆益!!」みたいな気持ちになって……。でも実運用では手数料、スリッページ、流動性の問題があってネ、バックテスト結果通りにはならないんだヨ!!😅
**機械学習による仮想通貨価格予測は、あくまでも「確率的な傾向を掴むツール」**だヨ!! 予測が当たる可能性を少し上げるだけで、損失のリスクは残るんだヨネ。この謙虚さ、絶対に忘れちゃいけないヨ!!😤
やらかしちゃいましたヨ……😭
精度を上げるための追加テクニックだヨ!!🚀
ここまで読んでくれたキミに、ちょっとボーナスな情報を伝えるヨ!!✨
センチメント分析との組み合わせ
価格データだけじゃなくて、TwitterやRedditのセンチメント情報を特徴量に加えると、予測精度が上がることがあるヨ!!😲 具体的にはHugging FaceのBERTベースのモデルで仮想通貨関連ツイートのポジネガを分析して、数値に変換してから特徴量として使うんだヨネ。
僕が試したところ、センチメント特徴量を加えたら方向正解率が**+1.5〜2%**ほど改善したヨ!! 小さいようで、長期的には大きな差になるんだヨ!!✨
アンサンブル(複数モデルの組み合わせ)
LSTM・Transformer・XGBoostの予測結果を重み付け平均することで、単一モデルより安定した予測が得られるヨ!!😊 それぞれのモデルが「違う失敗をする」から、組み合わせることで誤差が打ち消し合うんだヨナ!!
実際に僕がやってみたら、方向正解率が単一ベストモデルより**+0.8%**改善したヨ!! 地味だけど確実だヨ!!✨
オンライン学習で常に最新状態を保つ
仮想通貨市場は変化が早いからネ!! 一回学習したモデルをずっと使い続けると、市場環境が変わったときに一気に性能が落ちるんだヨ!!😓
そこで、週次や月次でモデルを再学習させる仕組みを作っておくといいヨ!! 新しいデータを継続的に取り込んで、常に「新鮮な」モデルを維持するんだヨナ。コレが機械学習による仮想通貨価格予測を実用レベルで使うための、地味だけど超重要なポイントだヨ!!😤
まとめ:今回キミが学んだこと!!🎓✨
今回の第2部では、機械学習による仮想通貨価格予測の実践的な実装を、全部まとめてやってみたヨ!! おさらいするとネ。
- LSTM:時系列の長期依存を学習できる。Keras/TensorFlowで比較的簡単に実装できるヨ!!
- Transformer:アテンション機構で重要な時点を自動学習。PyTorchで実装できたヨ!!
- XGBoost:特徴量エンジニアリングをしっかりやれば、ディープラーニングに勝てることもあるヨ!!
- データリーケージに注意:スケーラーは訓練データだけでfitするんだヨ!!
- 過学習対策:Dropout・BatchNorm・EarlyStoppingを組み合わせるヨ!!
- バックテスト結果を過信しない:現実の運用には別の壁があるんだヨ!!
機械学習による仮想通貨価格予測は、「当たる魔法のツール」じゃないヨ!!😤 でも、きちんと学習して、正しく使えば、市場を読むためのすごく強力な武器になるんだヨナ。キミもぜひ、自分の手でモデルを動かしてみてほしいヨ!!✨
次回の第3部では、強化学習を使った自動売買エージェントの構築に挑戦するヨ!!🚀 僕も今、猛烈に勉強中だからネ。一緒にレベルアップしていこうヨ!!😊
ではまた、次回の記事で会おうヨ!!✨
この記事の内容は教育目的であり、投資アドバイスではありません。仮想通貨への投資は自己責任でお願いします。