Files
crpto_predictor/test_dlinear.py
T
crypto_predictorandClaude Sonnet 4.5 9bbdc8d42b Initial commit: BTC 1h prediction model (53.10% accuracy)
🎯 项目成果:
- 准确率: 53.10% (2026年测试集)
- 任务类型: 二分类 (预测涨/跌)
- 特征: OHLCV + RSI + MACD (9个特征)
- 训练数据: 2020-2025年BTC小时数据 (52,351序列)
- 测试数据: 2026年1-29日 (484序列)

📊 性能指标:
- 精确率: 51.79%
- 召回率: 49.36%
- F1分数: 0.5054
- 预测分布: 非常平衡 (偏差仅-11个)

🔬 实验历史:
- 尝试了5种方案 (回归/分类, 不同数据划分)
- 分类任务优于回归任务 (53.10% vs 49.5%)
- 全量训练避免了过拟合问题

📦 主要模型文件:
- models/checkpoints/dlinear_classification_2026/
  - best_model.pt (最佳模型)
  - preprocessor.pkl (预处理器)
  - test_2026_results.json (测试结果)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-29 21:27:15 +08:00

170 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""加密货币价格预测系统 - DLinear模型端到端测试"""
import sys
import os
# 添加项目根目录到路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from data.fetcher import BinanceDataFetcher
from data.preprocessor import CryptoPreprocessor, split_data
from data.dataset import create_dataloaders
from models.dlinear.model import DLinear, DLinearConfig
from training.trainer import Trainer
from training.config import TrainingConfig
def main():
print("="*80)
print("加密货币价格预测系统 - DLINEAR模型测试")
print("="*80)
# 步骤1: 获取数据
print("\n[1/7] 从Binance获取BTC 1小时数据...")
fetcher = BinanceDataFetcher()
df = fetcher.fetch_ohlcv('BTC', '1h', use_cache=True)
print(f"✓ 已获取 {len(df)} 行数据,时间范围:{df['timestamp'].min()} 至 {df['timestamp'].max()}")
# 步骤2: 数据预处理
print("\n[2/7] 数据预处理(添加技术指标、创建序列)...")
preprocessor = CryptoPreprocessor(lookback=168, forecast_horizon=24)
X, y, processed_df = preprocessor.preprocess_pipeline(df, task='classification', fit=True)
print(f"✓ 已创建序列:X形状 = {X.shape}, y形状 = {y.shape}")
print(f"✓ 特征数量:{X.shape[-1]}")
print(f"✓ 标签分布:下跌(0) = {(y==0).sum()}, 上涨(1) = {(y==1).sum()}")
# 步骤3: 划分数据集
print("\n[3/7] 划分训练/验证/测试集 (70/15/15)...")
train_data, val_data, test_data = split_data(X, y, train_split=0.7, val_split=0.15)
# 步骤4: 创建数据加载器
print("\n[4/7] 创建PyTorch数据加载器...")
train_loader, val_loader, test_loader = create_dataloaders(
train_data, val_data, test_data,
task='classification',
batch_size=64
)
print(f"✓ 训练批次:{len(train_loader)}")
print(f"✓ 验证批次:{len(val_loader)}")
print(f"✓ 测试批次:{len(test_loader)}")
# 步骤5: 创建模型
print("\n[5/7] 创建DLinear模型...")
model_config = DLinearConfig(
input_dim=X.shape[-1],
lookback=168,
task='classification',
hidden_dim=512,
dropout=0.1,
moving_avg_kernel=25
)
model = DLinear(model_config)
print(f"✓ 模型已创建,可训练参数:{model.count_parameters():,} 个")
# 步骤6: 训练模型
print("\n[6/7] 开始训练模型...")
train_config = TrainingConfig(
batch_size=64,
max_epochs=20, # 测试用较少轮数
learning_rate=0.001,
early_stopping_patience=5,
lr_scheduler='plateau',
save_best=True,
checkpoint_dir='./models/checkpoints/dlinear_test'
)
trainer = Trainer(model, train_config, task='classification')
history = trainer.fit(train_loader, val_loader)
# 步骤7: 评估模型
print("\n[7/7] 在测试集上评估模型...")
metrics = trainer.evaluate(test_loader)
# 打印结果摘要
print("\n" + "="*80)
print("最终测试结果")
print("="*80)
print(f"\n分类指标:")
print(f" 准确率: {metrics.get('accuracy', 0):.4f}")
print(f" F1分数: {metrics.get('f1', 0):.4f}")
print(f" 精确率: {metrics.get('precision', 0):.4f}")
print(f" 召回率: {metrics.get('recall', 0):.4f}")
if 'true_positives' in metrics:
print(f"\n混淆矩阵:")
print(f" 真阳性: {metrics['true_positives']}")
print(f" 真阴性: {metrics['true_negatives']}")
print(f" 假阳性: {metrics['false_positives']}")
print(f" 假阴性: {metrics['false_negatives']}")
print(f"\n回测结果:")
print(f" 总收益率: {metrics.get('backtest_total_return', 0)*100:.2f}%")
print(f" 最终资金: ${metrics.get('backtest_final_capital', 0):,.2f}")
print(f" 夏普比率: {metrics.get('backtest_sharpe_ratio', 0):.4f}")
print(f" 最大回撤: {metrics.get('backtest_max_drawdown', 0)*100:.2f}%")
print(f" 胜率: {metrics.get('backtest_win_rate', 0)*100:.2f}%")
print(f" 交易次数: {metrics.get('backtest_num_trades', 0)}")
# 测试ONNX导出
print("\n" + "="*80)
print("测试ONNX导出")
print("="*80)
try:
import onnx
import onnxruntime as ort
import torch
import numpy as np
onnx_path = './models/checkpoints/dlinear_test/model.onnx'
os.makedirs(os.path.dirname(onnx_path), exist_ok=True)
print("\n[1/3] 导出模型到ONNX格式...")
model.to_onnx(onnx_path)
print(f"✓ ONNX模型已保存至:{onnx_path}")
print("\n[2/3] 验证ONNX模型...")
onnx_model = onnx.load(onnx_path)
onnx.checker.check_model(onnx_model)
print("✓ ONNX模型有效")
print("\n[3/3] 测试ONNX推理与PyTorch对比...")
# 创建测试输入
test_input = torch.randn(1, 168, X.shape[-1])
# PyTorch推理(在CPU上)
model.cpu()
model.eval()
with torch.no_grad():
pytorch_output = model(test_input).numpy()
# ONNX推理
ort_session = ort.InferenceSession(onnx_path)
onnx_output = ort_session.run(
None,
{'input': test_input.numpy()}
)[0]
# 比较输出
diff = np.abs(pytorch_output - onnx_output).max()
print(f"✓ PyTorch与ONNX的最大差异:{diff:.8f}")
if diff < 1e-5:
print("✓ ONNX导出成功!输出在容差范围内匹配。")
else:
print("⚠ 警告:ONNX输出与PyTorch有差异(但可能仍可接受)")
except Exception as e:
print(f"✗ ONNX导出失败:{e}")
print("\n" + "="*80)
print("测试成功完成!")
print("="*80)
print("\n下一步:")
print(" 1. 查看训练历史:./models/checkpoints/dlinear_test/")
print(" 2. 实现N-BEATS模型(阶段3)")
print(" 3. 在所有币种上训练(BTC、ETH、SOL)")
print(" 4. 创建FastAPI预测服务")
if __name__ == "__main__":
main()