Обучение модели на основе GRU для прогноза цены
GRU (Gated Recurrent Unit) — упрощённая версия LSTM, предложенная в 2014 году. Вместо трёх gate'ов (input, forget, output) у LSTM, GRU имеет два: reset gate и update gate. Это делает GRU быстрее в обучении и inference при сопоставимом качестве на большинстве задач.
GRU vs LSTM: когда что выбирать
GRU предпочтительнее когда:
- Данных мало (< 1 года истории)
- Нужен быстрый inference (trading latency critical)
- Ресурсы ограничены (edge deployment)
- Быстрое прототипирование
LSTM предпочтительнее когда:
- Много данных (3+ лет)
- Критически важна долгосрочная память (200+ свечей контекста)
- Задача требует тонкого управления памятью
Архитектура GRU для крипто прогнозирования
import torch
import torch.nn as nn
class CryptoGRU(nn.Module):
def __init__(self, input_size, hidden_size=128, num_layers=2,
dropout=0.2, output_horizon=1):
super().__init__()
self.gru = nn.GRU(
input_size=input_size,
hidden_size=hidden_size,
num_layers=num_layers,
dropout=dropout if num_layers > 1 else 0,
batch_first=True
)
# Bidirectional GRU для более богатого представления
self.bi_gru = nn.GRU(
input_size=input_size,
hidden_size=hidden_size // 2,
num_layers=1,
bidirectional=True,
batch_first=True
)
# Temporal attention
self.attention = nn.Sequential(
nn.Linear(hidden_size, 32),
nn.Tanh(),
nn.Linear(32, 1),
nn.Softmax(dim=1)
)
self.output_layer = nn.Sequential(
nn.Linear(hidden_size, 64),
nn.SiLU(),
nn.Dropout(0.1),
nn.Linear(64, output_horizon)
)
def forward(self, x):
# Основной GRU
gru_out, _ = self.gru(x)
# Attention weights по timestep'ам
attn_weights = self.attention(gru_out) # (batch, seq, 1)
attended = (gru_out * attn_weights).sum(dim=1) # взвешенная сумма
return self.output_layer(attended)
def predict_with_uncertainty(self, x, n_samples=100):
"""Monte Carlo Dropout для оценки неопределённости"""
self.train() # включаем dropout в inference
predictions = []
with torch.no_grad():
for _ in range(n_samples):
pred = self.forward(x)
predictions.append(pred)
preds = torch.stack(predictions)
mean = preds.mean(0)
uncertainty = preds.std(0)
return mean, uncertainty
Temporally Aware GRU
Для крипторынка важны temporally-aware features — модель должна «знать» что сейчас ночь UTC или выходной день:
class TemporallyAwareGRU(nn.Module):
def __init__(self, input_size, temporal_size=8, hidden_size=128, **kwargs):
super().__init__()
# Embeddings для временных признаков
self.hour_emb = nn.Embedding(24, 4)
self.weekday_emb = nn.Embedding(7, 4)
total_input = input_size + temporal_size
self.gru = nn.GRU(total_input, hidden_size, batch_first=True)
self.fc = nn.Linear(hidden_size, 1)
def forward(self, x, hours, weekdays):
# Temporal embeddings для каждого timestep
h_emb = self.hour_emb(hours) # (batch, seq, 4)
w_emb = self.weekday_emb(weekdays) # (batch, seq, 4)
# Конкатенируем с features
x_augmented = torch.cat([x, h_emb, w_emb], dim=-1)
gru_out, _ = self.gru(x_augmented)
return self.fc(gru_out[:, -1, :])
Multi-step forecasting с GRU
class MultiStepGRU(nn.Module):
"""Direct multi-step forecasting: предсказываем все горизонты одновременно"""
def __init__(self, input_size, hidden_size=128, forecast_horizons=[1, 4, 12, 24]):
super().__init__()
self.horizons = forecast_horizons
self.gru = nn.GRU(input_size, hidden_size, 2, batch_first=True)
# Отдельная head для каждого горизонта
self.heads = nn.ModuleList([
nn.Linear(hidden_size, 1) for _ in forecast_horizons
])
def forward(self, x):
gru_out, _ = self.gru(x)
last = gru_out[:, -1, :]
return {h: head(last) for h, head in zip(self.horizons, self.heads)}
Ensembling GRU моделей
Ансамбль из нескольких GRU, обученных с разными seed и гиперпараметрами, стабильнее единственной модели:
def ensemble_predict(models, X, weights=None):
if weights is None:
weights = [1/len(models)] * len(models)
predictions = []
for model, w in zip(models, weights):
model.eval()
with torch.no_grad():
pred = model(torch.FloatTensor(X))
predictions.append(pred.numpy() * w)
return np.array(predictions).sum(axis=0)
Вычислительные требования
GRU с hidden_size=128, 2 слоями, batch_size=256, seq_len=60:
- Обучение на CPU: ~2 часа на 2 года 1h данных
- Обучение на GPU (T4): ~15 минут
- Inference: < 5ms на CPU для одного батча
Разрабатываем и обучаем GRU ансамбль с temporal awareness, Monte Carlo Dropout для неопределённости, multi-step forecasting и production-ready API.







