unify model names

This commit is contained in:
Dobromir Popov
2025-09-09 01:10:35 +03:00
parent 0e886527c8
commit 317c703ea0
5 changed files with 229 additions and 104 deletions

View File

@@ -6,8 +6,6 @@ Much larger and more sophisticated architecture for better learning
import os
import logging
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
import math
@@ -15,10 +13,30 @@ import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import torch.nn.functional as F
from typing import Dict, Any, Optional, Tuple
# Try to import optional dependencies
try:
import numpy as np
HAS_NUMPY = True
except ImportError:
np = None
HAS_NUMPY = False
try:
import matplotlib.pyplot as plt
HAS_MATPLOTLIB = True
except ImportError:
plt = None
HAS_MATPLOTLIB = False
try:
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
HAS_SKLEARN = True
except ImportError:
HAS_SKLEARN = False
# Import checkpoint management
from NN.training.model_manager import save_checkpoint, load_best_checkpoint
from NN.training.model_manager import create_model_manager
@@ -423,11 +441,11 @@ class EnhancedCNNModel(nn.Module):
'features': self._memory_barrier(processed_features)
}
def predict(self, feature_matrix: np.ndarray) -> Dict[str, Any]:
def predict(self, feature_matrix) -> Dict[str, Any]:
"""
Make predictions on feature matrix
Args:
feature_matrix: numpy array of shape [sequence_length, features]
feature_matrix: tensor or numpy array of shape [sequence_length, features]
Returns:
Dictionary with prediction results
"""
@@ -435,10 +453,12 @@ class EnhancedCNNModel(nn.Module):
with torch.no_grad():
# Convert to tensor and add batch dimension
if isinstance(feature_matrix, np.ndarray):
if HAS_NUMPY and isinstance(feature_matrix, np.ndarray):
x = torch.FloatTensor(feature_matrix).unsqueeze(0) # Add batch dim
else:
elif isinstance(feature_matrix, torch.Tensor):
x = feature_matrix.unsqueeze(0)
else:
x = torch.FloatTensor(feature_matrix).unsqueeze(0)
# Move to device
device = next(self.parameters()).device
@@ -448,13 +468,19 @@ class EnhancedCNNModel(nn.Module):
outputs = self.forward(x)
# Extract results with proper shape handling
if HAS_NUMPY:
probs = outputs['probabilities'].cpu().numpy()[0]
confidence_tensor = outputs['confidence'].cpu().numpy()
regime = outputs['regime'].cpu().numpy()[0]
volatility = outputs['volatility'].cpu().numpy()
else:
probs = outputs['probabilities'].cpu().tolist()[0]
confidence_tensor = outputs['confidence'].cpu().tolist()
regime = outputs['regime'].cpu().tolist()[0]
volatility = outputs['volatility'].cpu().tolist()
# Handle confidence shape properly
if isinstance(confidence_tensor, np.ndarray):
if HAS_NUMPY and isinstance(confidence_tensor, np.ndarray):
if confidence_tensor.ndim == 0:
confidence = float(confidence_tensor.item())
elif confidence_tensor.size == 1:
@@ -465,7 +491,7 @@ class EnhancedCNNModel(nn.Module):
confidence = float(confidence_tensor)
# Handle volatility shape properly
if isinstance(volatility, np.ndarray):
if HAS_NUMPY and isinstance(volatility, np.ndarray):
if volatility.ndim == 0:
volatility = float(volatility.item())
elif volatility.size == 1:
@@ -476,18 +502,27 @@ class EnhancedCNNModel(nn.Module):
volatility = float(volatility)
# Determine action (0=BUY, 1=SELL for 2-action system)
if HAS_NUMPY:
action = int(np.argmax(probs))
else:
action = int(torch.argmax(torch.tensor(probs)).item())
action_confidence = float(probs[action])
# Convert logits to list
if HAS_NUMPY:
raw_logits = outputs['logits'].cpu().numpy()[0].tolist()
else:
raw_logits = outputs['logits'].cpu().tolist()[0]
return {
'action': action,
'action_name': 'BUY' if action == 0 else 'SELL',
'confidence': float(confidence),
'action_confidence': action_confidence,
'probabilities': probs.tolist(),
'regime_probabilities': regime.tolist(),
'probabilities': probs if isinstance(probs, list) else probs.tolist(),
'regime_probabilities': regime if isinstance(regime, list) else regime.tolist(),
'volatility_prediction': float(volatility),
'raw_logits': outputs['logits'].cpu().numpy()[0].tolist()
'raw_logits': raw_logits
}
def get_memory_usage(self) -> Dict[str, Any]:

View File

@@ -15,11 +15,19 @@ Architecture:
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import logging
from typing import Dict, List, Optional, Tuple, Any
from abc import ABC, abstractmethod
# Try to import numpy, but provide fallback if not available
try:
import numpy as np
HAS_NUMPY = True
except ImportError:
np = None
HAS_NUMPY = False
logging.warning("NumPy not available - COB RL model will have limited functionality")
from .model_interfaces import ModelInterface
logger = logging.getLogger(__name__)
@@ -164,12 +172,12 @@ class MassiveRLNetwork(nn.Module):
'features': x # Hidden features for analysis
}
def predict(self, cob_features: np.ndarray) -> Dict[str, Any]:
def predict(self, cob_features) -> Dict[str, Any]:
"""
High-level prediction method for COB features
Args:
cob_features: COB features as numpy array [input_size]
cob_features: COB features as tensor or numpy array [input_size]
Returns:
Dict containing prediction results
@@ -177,10 +185,13 @@ class MassiveRLNetwork(nn.Module):
self.eval()
with torch.no_grad():
# Convert to tensor and add batch dimension
if isinstance(cob_features, np.ndarray):
if HAS_NUMPY and isinstance(cob_features, np.ndarray):
x = torch.from_numpy(cob_features).float()
else:
elif isinstance(cob_features, torch.Tensor):
x = cob_features.float()
else:
# Try to convert from list or other format
x = torch.tensor(cob_features, dtype=torch.float32)
if x.dim() == 1:
x = x.unsqueeze(0) # Add batch dimension
@@ -198,11 +209,17 @@ class MassiveRLNetwork(nn.Module):
confidence = outputs['confidence'].item()
value = outputs['value'].item()
# Convert probabilities to list (works with or without numpy)
if HAS_NUMPY:
probabilities = price_probs.cpu().numpy()[0].tolist()
else:
probabilities = price_probs.cpu().tolist()[0]
return {
'predicted_direction': predicted_direction, # 0=DOWN, 1=SIDEWAYS, 2=UP
'confidence': confidence,
'value': value,
'probabilities': price_probs.cpu().numpy()[0],
'probabilities': probabilities,
'direction_text': ['DOWN', 'SIDEWAYS', 'UP'][predicted_direction]
}
@@ -250,15 +267,18 @@ class COBRLModelInterface(ModelInterface):
logger.info(f"COB RL Model Interface initialized on {self.device}")
def predict(self, cob_features: np.ndarray) -> Dict[str, Any]:
def predict(self, cob_features) -> Dict[str, Any]:
"""Make prediction using the model"""
self.model.eval()
with torch.no_grad():
# Convert to tensor and add batch dimension
if isinstance(cob_features, np.ndarray):
if HAS_NUMPY and isinstance(cob_features, np.ndarray):
x = torch.from_numpy(cob_features).float()
else:
elif isinstance(cob_features, torch.Tensor):
x = cob_features.float()
else:
# Try to convert from list or other format
x = torch.tensor(cob_features, dtype=torch.float32)
if x.dim() == 1:
x = x.unsqueeze(0) # Add batch dimension
@@ -275,11 +295,17 @@ class COBRLModelInterface(ModelInterface):
confidence = outputs['confidence'].item()
value = outputs['value'].item()
# Convert probabilities to list (works with or without numpy)
if HAS_NUMPY:
probabilities = price_probs.cpu().numpy()[0].tolist()
else:
probabilities = price_probs.cpu().tolist()[0]
return {
'predicted_direction': predicted_direction, # 0=DOWN, 1=SIDEWAYS, 2=UP
'confidence': confidence,
'value': value,
'probabilities': price_probs.cpu().numpy()[0],
'probabilities': probabilities,
'direction_text': ['DOWN', 'SIDEWAYS', 'UP'][predicted_direction]
}

View File

@@ -532,22 +532,18 @@ class ModelManager:
if not self.legacy_checkpoints_dir.exists():
return None
# Define search patterns for different model types
# Handle both orchestrator naming and direct model naming
model_patterns = {
'dqn_agent': ['dqn_agent', 'dqn', 'agent'],
'enhanced_cnn': ['cnn_model', 'enhanced_cnn', 'cnn', 'optimized_short_term'],
'cob_rl': ['cob_rl', 'rl', 'rl_agent', 'trading_agent'],
'transformer': ['transformer', 'decision'],
'decision': ['decision', 'transformer'],
# Also support direct model names
'dqn': ['dqn_agent', 'dqn', 'agent'],
'cnn': ['cnn_model', 'cnn', 'optimized_short_term'],
'rl': ['cob_rl', 'rl', 'rl_agent']
}
# Use unified model naming throughout the project
# All model references use consistent short names: dqn, cnn, cob_rl, transformer, decision
# This eliminates complex mapping and ensures consistency across the entire codebase
patterns = [model_name]
# Get patterns for this model name or use generic patterns
patterns = model_patterns.get(model_name, [model_name])
# Add minimal backward compatibility patterns
if model_name == 'dqn':
patterns.extend(['dqn_agent', 'agent'])
elif model_name == 'cnn':
patterns.extend(['cnn_model', 'enhanced_cnn'])
elif model_name == 'cob_rl':
patterns.extend(['rl', 'rl_agent', 'trading_agent'])
# Search in legacy saved directory first
legacy_saved_dir = self.legacy_checkpoints_dir / "saved"
@@ -558,7 +554,7 @@ class ModelManager:
return file_path
# Search in model-specific directories
for model_type in model_patterns.keys():
for model_type in ['cnn', 'dqn', 'rl', 'transformer', 'decision']:
model_dir = self.legacy_checkpoints_dir / model_type
if model_dir.exists():
saved_dir = model_dir / "saved"

View File

@@ -15,19 +15,41 @@ import asyncio
import logging
import time
import threading
import numpy as np
import pandas as pd
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any, Tuple, Union
from dataclasses import dataclass, field
from collections import deque
import json
# Try to import optional dependencies
try:
import numpy as np
HAS_NUMPY = True
except ImportError:
np = None
HAS_NUMPY = False
try:
import pandas as pd
HAS_PANDAS = True
except ImportError:
pd = None
HAS_PANDAS = False
import os
import shutil
# Try to import PyTorch
try:
import torch
import torch.nn as nn
import torch.optim as optim
HAS_TORCH = True
except ImportError:
torch = None
nn = None
optim = None
HAS_TORCH = False
from .config import get_config
from .data_provider import DataProvider
@@ -227,7 +249,7 @@ class TradingOrchestrator:
self.rl_agent.load_best_checkpoint() # This loads the state into the model
# Check if we have checkpoints available
from NN.training.model_manager import load_best_checkpoint
result = load_best_checkpoint("dqn_agent")
result = load_best_checkpoint("dqn")
if result:
file_path, metadata = result
self.model_states['dqn']['initial_loss'] = getattr(metadata, 'initial_loss', None)
@@ -267,7 +289,7 @@ class TradingOrchestrator:
checkpoint_loaded = False
try:
from NN.training.model_manager import load_best_checkpoint
result = load_best_checkpoint("enhanced_cnn")
result = load_best_checkpoint("cnn")
if result:
file_path, metadata = result
self.model_states['cnn']['initial_loss'] = 0.412
@@ -347,13 +369,20 @@ class TradingOrchestrator:
self.extrema_trainer = None
# Initialize COB RL Model - UNIFIED with ModelManager
cob_rl_available = False
try:
from NN.models.cob_rl_model import COBRLModelInterface
cob_rl_available = True
except ImportError as e:
logger.warning(f"COB RL dependencies not available: {e}")
cob_rl_available = False
if cob_rl_available:
try:
# Initialize COB RL model using unified approach
self.cob_rl_agent = COBRLModelInterface(
model_checkpoint_dir="@checkpoints/cob_rl",
device='cuda' if torch.cuda.is_available() else 'cpu'
device='cuda' if (HAS_TORCH and torch.cuda.is_available()) else 'cpu'
)
# Add COB RL to model states tracking
@@ -368,17 +397,17 @@ class TradingOrchestrator:
checkpoint_loaded = False
try:
from NN.training.model_manager import load_best_checkpoint
result = load_best_checkpoint("cob_rl_agent")
result = load_best_checkpoint("cob_rl")
if result:
file_path, metadata = result
self.model_states['cob_rl']['initial_loss'] = metadata.loss
self.model_states['cob_rl']['current_loss'] = metadata.loss
self.model_states['cob_rl']['best_loss'] = metadata.loss
self.model_states['cob_rl']['initial_loss'] = getattr(metadata, 'loss', None)
self.model_states['cob_rl']['current_loss'] = getattr(metadata, 'loss', None)
self.model_states['cob_rl']['best_loss'] = getattr(metadata, 'loss', None)
self.model_states['cob_rl']['checkpoint_loaded'] = True
self.model_states['cob_rl']['checkpoint_filename'] = metadata.checkpoint_id
self.model_states['cob_rl']['checkpoint_filename'] = getattr(metadata, 'checkpoint_id', 'unknown')
checkpoint_loaded = True
loss_str = f"{metadata.loss:.4f}" if metadata.loss is not None else "N/A"
logger.info(f"COB RL checkpoint loaded: {metadata.checkpoint_id} (loss={loss_str})")
loss_str = f"{getattr(metadata, 'loss', 'N/A'):.4f}" if getattr(metadata, 'loss', None) is not None else "N/A"
logger.info(f"COB RL checkpoint loaded: {getattr(metadata, 'checkpoint_id', 'unknown')} (loss={loss_str})")
except Exception as e:
logger.warning(f"Error loading COB RL checkpoint: {e}")
@@ -391,13 +420,45 @@ class TradingOrchestrator:
logger.info("COB RL starting fresh - no checkpoint found")
logger.info("COB RL Agent initialized and integrated with unified ModelManager")
except Exception as e:
logger.error(f"Error initializing COB RL: {e}")
self.cob_rl_agent = None
cob_rl_available = False
if not cob_rl_available:
# COB RL not available due to missing dependencies
# Still try to load checkpoint metadata for display purposes
logger.info("COB RL dependencies missing - attempting checkpoint metadata load only")
self.model_states['cob_rl'] = {
'initial_loss': None,
'current_loss': None,
'best_loss': None,
'checkpoint_loaded': False,
'checkpoint_filename': 'dependencies missing'
}
# Try to load checkpoint metadata even without the model
try:
from NN.training.model_manager import load_best_checkpoint
result = load_best_checkpoint("cob_rl")
if result:
file_path, metadata = result
self.model_states['cob_rl']['checkpoint_loaded'] = True
self.model_states['cob_rl']['checkpoint_filename'] = getattr(metadata, 'checkpoint_id', 'found')
logger.info(f"COB RL checkpoint metadata loaded (model unavailable): {getattr(metadata, 'checkpoint_id', 'unknown')}")
else:
logger.info("No COB RL checkpoint found")
except Exception as e:
logger.debug(f"Could not load COB RL checkpoint metadata: {e}")
self.cob_rl_agent = None
logger.info("COB RL initialization completed")
logger.info(" - Uses @checkpoints/ directory structure")
logger.info(" - Follows same load/save/checkpoint flow as other models")
logger.info(" - Integrated with enhanced real-time training system")
except ImportError as e:
logger.warning(f"COB RL Model not available: {e}")
self.cob_rl_agent = None
logger.info(" - Gracefully handles missing dependencies")
# Initialize TRANSFORMER Model
try:

View File

@@ -37,16 +37,23 @@ import traceback
import gc
import time
import psutil
import torch
from pathlib import Path
# Try to import torch
try:
import torch
HAS_TORCH = True
except ImportError:
torch = None
HAS_TORCH = False
# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def clear_gpu_memory():
"""Clear GPU memory cache"""
if torch.cuda.is_available():
if HAS_TORCH and torch.cuda.is_available():
torch.cuda.empty_cache()
torch.cuda.synchronize()