| # 系统架构文档 |
|
|
| 本文档详细描述了情绪与生理状态变化预测模型的系统架构、设计原则和实现细节。 |
|
|
| ## 目录 |
|
|
| 1. [系统概述](#系统概述) |
| 2. [整体架构](#整体架构) |
| 3. [模型架构](#模型架构) |
| 4. [数据处理流程](#数据处理流程) |
| 5. [训练流程](#训练流程) |
| 6. [推理流程](#推理流程) |
| 7. [模块设计](#模块设计) |
| 8. [设计模式](#设计模式) |
| 9. [性能优化](#性能优化) |
| 10. [扩展性设计](#扩展性设计) |
|
|
| ## 系统概述 |
|
|
| ### 设计目标 |
|
|
| 本系统旨在实现一个高效、可扩展、易维护的情绪与生理状态变化预测模型,主要设计目标包括: |
|
|
| 1. **高性能**: 支持GPU加速,优化推理速度 |
| 2. **模块化**: 清晰的模块划分,便于维护和扩展 |
| 3. **可配置**: 灵活的配置系统,支持超参数调优 |
| 4. **易用性**: 完整的CLI工具和Python API |
| 5. **可扩展**: 支持新的模型架构和损失函数 |
| 6. **可观测**: 完整的日志和监控系统 |
|
|
| ### 技术栈 |
|
|
| - **深度学习框架**: PyTorch 1.12+ |
| - **数据处理**: NumPy, Pandas, scikit-learn |
| - **配置管理**: PyYAML, OmegaConf |
| - **可视化**: Matplotlib, Seaborn, Plotly |
| - **命令行**: argparse, Click |
| - **日志系统**: Loguru |
| - **实验跟踪**: MLflow, Weights & Biases |
| - **性能分析**: py-spy, memory-profiler |
|
|
| ## 整体架构 |
|
|
| ### 系统架构图 |
|
|
| ``` |
| ┌─────────────────────────────────────────────────────────────────┐ |
| │ 用户接口层 │ |
| ├─────────────────────────────────────────────────────────────────┤ |
| │ CLI工具 │ Python API │ Web API │ Jupyter Notebook │ |
| ├─────────────────────────────────────────────────────────────────┤ |
| │ 业务逻辑层 │ |
| ├─────────────────────────────────────────────────────────────────┤ |
| │ 训练管理器 │ 推理引擎 │ 评估器 │ 配置管理器 │ 日志管理器 │ |
| ├─────────────────────────────────────────────────────────────────┤ |
| │ 核心模型层 │ |
| ├─────────────────────────────────────────────────────────────────┤ |
| │ PAD预测器 │ 损失函数 │ 评估指标 │ 模型工厂 │ 优化器 │ |
| ├─────────────────────────────────────────────────────────────────┤ |
| │ 数据处理层 │ |
| ├─────────────────────────────────────────────────────────────────┤ |
| │ 数据加载器 │ 预处理器 │ 数据增强器 │ 合成数据生成器 │ |
| ├─────────────────────────────────────────────────────────────────┤ |
| │ 基础设施层 │ |
| ├─────────────────────────────────────────────────────────────────┤ |
| │ 文件系统 │ GPU计算 │ 内存管理 │ 异常处理 │ 工具函数 │ |
| └─────────────────────────────────────────────────────────────────┘ |
| ``` |
|
|
| ### 模块依赖关系 |
|
|
| ``` |
| CLI模块 → 业务逻辑层 → 核心模型层 → 数据处理层 → 基础设施层 |
| ↓ |
| 配置管理器 → 所有模块 |
| ↓ |
| 日志管理器 → 所有模块 |
| ``` |
|
|
| ## 模型架构 |
|
|
| ### 网络结构 |
|
|
| PAD预测器采用多层感知机(MLP)架构: |
|
|
| ``` |
| 输入层 (7维) |
| ↓ |
| 隐藏层1 (128神经元) + ReLU + Dropout(0.3) |
| ↓ |
| 隐藏层2 (64神经元) + ReLU + Dropout(0.3) |
| ↓ |
| 隐藏层3 (32神经元) + ReLU |
| ↓ |
| 输出层 (5神经元) + Linear激活 |
| ``` |
|
|
| ### 网络组件详解 |
|
|
| #### 输入层 |
| - **维度**: 7维特征向量 |
| - **特征组成**: |
| - User PAD: 3维 (Pleasure, Arousal, Dominance) |
| - Vitality: 1维 (生理活力值) |
| - Current PAD: 3维 (当前情绪状态) |
|
|
| #### 隐藏层设计原则 |
| 1. **逐层压缩**: 从128 → 64 → 32,逐层减少神经元数量 |
| 2. **激活函数**: 使用ReLU激活函数,避免梯度消失 |
| 3. **正则化**: 在前两层使用Dropout防止过拟合 |
| 4. **权重初始化**: 使用Xavier均匀初始化,适合ReLU激活 |
|
|
| #### 输出层设计 |
| - **维度**: 3维输出向量 |
| - **输出组成**: |
| - ΔPAD: 3维 (情绪变化量:ΔPleasure, ΔArousal, ΔDominance) |
| - ΔPressure: 通过 PAD 变化动态计算(公式:1.0×(-ΔP) + 0.8×(ΔA) + 0.6×(-ΔD)) |
| - **激活函数**: 线性激活,适用于回归任务 |
|
|
| ### 模型配置系统 |
|
|
| ```python |
| # 默认架构配置 |
| DEFAULT_ARCHITECTURE = { |
| 'input_dim': 7, |
| 'output_dim': 3, |
| 'hidden_dims': [512, 256, 128], |
| 'dropout_rate': 0.3, |
| 'activation': 'relu', |
| 'weight_init': 'xavier_uniform', |
| 'bias_init': 'zeros' |
| } |
| |
| # 可配置参数 |
| CONFIGURABLE_PARAMS = { |
| 'hidden_dims': { |
| 'type': list, |
| 'default': [128, 64, 32], |
| 'constraints': [ |
| lambda x: len(x) >= 1, |
| lambda x: all(isinstance(n, int) and n > 0 for n in x), |
| lambda x: x == sorted(x, reverse=True) # 递减序列 |
| ] |
| }, |
| 'dropout_rate': { |
| 'type': float, |
| 'default': 0.3, |
| 'range': [0.0, 0.9] |
| }, |
| 'activation': { |
| 'type': str, |
| 'default': 'relu', |
| 'choices': ['relu', 'tanh', 'sigmoid', 'leaky_relu'] |
| } |
| } |
| ``` |
|
|
| ## 数据处理流程 |
|
|
| ### 数据流水线 |
|
|
| ``` |
| 原始数据 → 数据验证 → 特征提取 → 数据预处理 → 数据增强 → 批次生成 |
| ↓ |
| 模型训练/推理 |
| ``` |
|
|
| ### 数据预处理流程 |
|
|
| #### 1. 数据验证 |
| ```python |
| class DataValidator: |
| """数据验证器,确保数据质量""" |
| |
| def validate_input_shape(self, data: np.ndarray) -> bool: |
| """验证输入数据形状""" |
| return data.shape[1] == 7 |
| |
| def validate_value_ranges(self, data: np.ndarray) -> Dict[str, bool]: |
| """验证数值范围""" |
| return { |
| 'pad_features_valid': np.all(data[:, :6] >= -1) and np.all(data[:, :6] <= 1), |
| 'vitality_valid': np.all(data[:, 3] >= 0) and np.all(data[:, 3] <= 100) |
| } |
| |
| def check_missing_values(self, data: np.ndarray) -> Dict[str, Any]: |
| """检查缺失值""" |
| return { |
| 'has_missing': np.isnan(data).any(), |
| 'missing_count': np.isnan(data).sum(), |
| 'missing_ratio': np.isnan(data).mean() |
| } |
| ``` |
|
|
| #### 2. 特征工程 |
| ```python |
| class FeatureEngineer: |
| """特征工程器""" |
| |
| def extract_pad_features(self, data: np.ndarray) -> np.ndarray: |
| """提取PAD特征""" |
| user_pad = data[:, :3] |
| current_pad = data[:, 4:7] |
| return np.hstack([user_pad, current_pad]) |
| |
| def compute_pad_differences(self, data: np.ndarray) -> np.ndarray: |
| """计算PAD差异""" |
| user_pad = data[:, :3] |
| current_pad = data[:, 4:7] |
| return user_pad - current_pad |
| |
| def create_interaction_features(self, data: np.ndarray) -> np.ndarray: |
| """创建交互特征""" |
| user_pad = data[:, :3] |
| current_pad = data[:, 4:7] |
| |
| # PAD内积 |
| pad_interaction = np.sum(user_pad * current_pad, axis=1, keepdims=True) |
| |
| # PAD欧氏距离 |
| pad_distance = np.linalg.norm(user_pad - current_pad, axis=1, keepdims=True) |
| |
| return np.hstack([data, pad_interaction, pad_distance]) |
| ``` |
|
|
| #### 3. 数据标准化 |
| ```python |
| class DataNormalizer: |
| """数据标准化器""" |
| |
| def __init__(self, method: str = 'standard'): |
| self.method = method |
| self.scalers = {} |
| |
| def fit_pad_features(self, features: np.ndarray): |
| """拟合PAD特征标准化器""" |
| if self.method == 'standard': |
| self.scalers['pad'] = StandardScaler() |
| elif self.method == 'minmax': |
| self.scalers['pad'] = MinMaxScaler(feature_range=(-1, 1)) |
| |
| self.scalers['pad'].fit(features) |
| |
| def fit_vitality_feature(self, features: np.ndarray): |
| """拟合活力值标准化器""" |
| if self.method == 'standard': |
| self.scalers['vitality'] = StandardScaler() |
| elif self.method == 'minmax': |
| self.scalers['vitality'] = MinMaxScaler(feature_range=(0, 1)) |
| |
| self.scalers['vitality'].fit(features.reshape(-1, 1)) |
| ``` |
|
|
| ### 数据增强策略 |
|
|
| ```python |
| class DataAugmenter: |
| """数据增强器""" |
| |
| def __init__(self, noise_std: float = 0.01, mixup_alpha: float = 0.2): |
| self.noise_std = noise_std |
| self.mixup_alpha = mixup_alpha |
| |
| def add_gaussian_noise(self, features: np.ndarray) -> np.ndarray: |
| """添加高斯噪声""" |
| noise = np.random.normal(0, self.noise_std, features.shape) |
| return features + noise |
| |
| def mixup_augmentation(self, features: np.ndarray, labels: np.ndarray) -> tuple: |
| """Mixup数据增强""" |
| batch_size = features.shape[0] |
| lam = np.random.beta(self.mixup_alpha, self.mixup_alpha) |
| |
| # 随机打乱索引 |
| index = np.random.permutation(batch_size) |
| |
| # 混合特征和标签 |
| mixed_features = lam * features + (1 - lam) * features[index] |
| mixed_labels = lam * labels + (1 - lam) * labels[index] |
| |
| return mixed_features, mixed_labels |
| ``` |
|
|
| ## 训练流程 |
|
|
| ### 训练架构 |
|
|
| ``` |
| 配置加载 → 数据准备 → 模型初始化 → 训练循环 → 模型保存 → 结果评估 |
| ``` |
|
|
| ### 训练管理器设计 |
|
|
| ```python |
| class ModelTrainer: |
| """模型训练管理器""" |
| |
| def __init__(self, model, preprocessor=None, device='auto'): |
| self.model = model |
| self.preprocessor = preprocessor |
| self.device = self._setup_device(device) |
| self.logger = logging.getLogger(__name__) |
| |
| # 训练状态 |
| self.training_state = { |
| 'epoch': 0, |
| 'best_loss': float('inf'), |
| 'patience_counter': 0, |
| 'training_history': [] |
| } |
| |
| def setup_training(self, config: Dict[str, Any]): |
| """设置训练环境""" |
| # 优化器设置 |
| self.optimizer = self._create_optimizer(config['optimizer']) |
| |
| # 学习率调度器 |
| self.scheduler = self._create_scheduler(config['scheduler']) |
| |
| # 损失函数 |
| self.criterion = self._create_criterion(config['loss']) |
| |
| # 早停机制 |
| self.early_stopping = self._setup_early_stopping(config['early_stopping']) |
| |
| # 检查点管理 |
| self.checkpoint_manager = CheckpointManager(config['checkpointing']) |
| |
| def train_epoch(self, train_loader: DataLoader) -> Dict[str, float]: |
| """训练一个epoch""" |
| self.model.train() |
| epoch_loss = 0.0 |
| num_batches = len(train_loader) |
| |
| for batch_idx, (features, labels) in enumerate(train_loader): |
| features = features.to(self.device) |
| labels = labels.to(self.device) |
| |
| # 前向传播 |
| self.optimizer.zero_grad() |
| outputs = self.model(features) |
| loss = self.criterion(outputs, labels) |
| |
| # 反向传播 |
| loss.backward() |
| |
| # 梯度裁剪 |
| torch.nn.utils.clip_grad_norm_(self.model.parameters(), max_norm=1.0) |
| |
| # 参数更新 |
| self.optimizer.step() |
| |
| epoch_loss += loss.item() |
| |
| # 日志记录 |
| if batch_idx % 100 == 0: |
| self.logger.debug(f'Batch {batch_idx}/{num_batches}, Loss: {loss.item():.6f}') |
| |
| return {'train_loss': epoch_loss / num_batches} |
| |
| def validate_epoch(self, val_loader: DataLoader) -> Dict[str, float]: |
| """验证一个epoch""" |
| self.model.eval() |
| val_loss = 0.0 |
| num_batches = len(val_loader) |
| |
| with torch.no_grad(): |
| for features, labels in val_loader: |
| features = features.to(self.device) |
| labels = labels.to(self.device) |
| |
| outputs = self.model(features) |
| loss = self.criterion(outputs, labels) |
| |
| val_loss += loss.item() |
| |
| return {'val_loss': val_loss / num_batches} |
| ``` |
|
|
| ### 训练策略 |
|
|
| #### 1. 学习率调度 |
| ```python |
| class LearningRateScheduler: |
| """学习率调度策略""" |
| |
| @staticmethod |
| def cosine_annealing_scheduler(optimizer, T_max, eta_min=1e-6): |
| """余弦退火调度器""" |
| return torch.optim.lr_scheduler.CosineAnnealingLR( |
| optimizer, T_max=T_max, eta_min=eta_min |
| ) |
| |
| @staticmethod |
| def reduce_on_plateau_scheduler(optimizer, patience=5, factor=0.5): |
| """平台衰减调度器""" |
| return torch.optim.lr_scheduler.ReduceLROnPlateau( |
| optimizer, mode='min', patience=patience, factor=factor |
| ) |
| |
| @staticmethod |
| def warmup_cosine_scheduler(optimizer, warmup_epochs, total_epochs): |
| """预热余弦调度器""" |
| def lr_lambda(epoch): |
| if epoch < warmup_epochs: |
| return epoch / warmup_epochs |
| else: |
| progress = (epoch - warmup_epochs) / (total_epochs - warmup_epochs) |
| return 0.5 * (1 + math.cos(math.pi * progress)) |
| |
| return torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda) |
| ``` |
|
|
| #### 2. 早停机制 |
| ```python |
| class EarlyStopping: |
| """早停机制""" |
| |
| def __init__(self, patience=10, min_delta=1e-4, mode='min'): |
| self.patience = patience |
| self.min_delta = min_delta |
| self.mode = mode |
| self.counter = 0 |
| self.best_score = None |
| |
| if mode == 'min': |
| self.is_better = lambda x, y: x < y - min_delta |
| else: |
| self.is_better = lambda x, y: x > y + min_delta |
| |
| def __call__(self, score): |
| if self.best_score is None: |
| self.best_score = score |
| return False |
| |
| if self.is_better(score, self.best_score): |
| self.best_score = score |
| self.counter = 0 |
| return False |
| else: |
| self.counter += 1 |
| return self.counter >= self.patience |
| ``` |
|
|
| ## 推理流程 |
|
|
| ### 推理架构 |
|
|
| ``` |
| 模型加载 → 输入验证 → 数据预处理 → 模型推理 → 结果后处理 → 输出格式化 |
| ``` |
|
|
| ### 推理引擎设计 |
|
|
| ```python |
| class InferenceEngine: |
| """高性能推理引擎""" |
| |
| def __init__(self, model, preprocessor=None, device='auto'): |
| self.model = model |
| self.preprocessor = preprocessor |
| self.device = self._setup_device(device) |
| self.model.to(self.device) |
| self.model.eval() |
| |
| # 性能优化 |
| self._optimize_model() |
| |
| # 预热 |
| self._warmup_model() |
| |
| def _optimize_model(self): |
| """模型性能优化""" |
| # TorchScript优化 |
| try: |
| self.model = torch.jit.script(self.model) |
| self.logger.info("模型已优化为TorchScript格式") |
| except Exception as e: |
| self.logger.warning(f"TorchScript优化失败: {e}") |
| |
| # 混合精度 |
| if self.device.type == 'cuda': |
| self.scaler = torch.cuda.amp.GradScaler() |
| |
| def _warmup_model(self, num_warmup=5): |
| """模型预热""" |
| dummy_input = torch.randn(1, 7).to(self.device) |
| |
| with torch.no_grad(): |
| for _ in range(num_warmup): |
| _ = self.model(dummy_input) |
| |
| self.logger.info(f"模型预热完成,预热次数: {num_warmup}") |
| |
| def predict_single(self, input_data: Union[List, np.ndarray]) -> Dict[str, Any]: |
| """单样本推理""" |
| # 输入验证 |
| validated_input = self._validate_input(input_data) |
| |
| # 数据预处理 |
| processed_input = self._preprocess_input(validated_input) |
| |
| # 模型推理 |
| with torch.no_grad(): |
| if self.device.type == 'cuda': |
| with torch.cuda.amp.autocast(): |
| output = self.model(processed_input) |
| else: |
| output = self.model(processed_input) |
| |
| # 结果后处理 |
| result = self._postprocess_output(output) |
| |
| return result |
| |
| def predict_batch(self, input_batch: Union[List, np.ndarray]) -> List[Dict[str, Any]]: |
| """批量推理""" |
| # 输入验证和预处理 |
| validated_batch = self._validate_batch(input_batch) |
| processed_batch = self._preprocess_batch(validated_batch) |
| |
| # 分批推理 |
| batch_size = min(32, len(processed_batch)) |
| results = [] |
| |
| for i in range(0, len(processed_batch), batch_size): |
| batch_input = processed_batch[i:i+batch_size] |
| |
| with torch.no_grad(): |
| if self.device.type == 'cuda': |
| with torch.cuda.amp.autocast(): |
| batch_output = self.model(batch_input) |
| else: |
| batch_output = self.model(batch_input) |
| |
| # 后处理 |
| batch_results = self._postprocess_batch(batch_output) |
| results.extend(batch_results) |
| |
| return results |
| ``` |
|
|
| ### 性能优化策略 |
|
|
| #### 1. 内存优化 |
| ```python |
| class MemoryOptimizer: |
| """内存优化器""" |
| |
| @staticmethod |
| def optimize_memory_usage(): |
| """优化内存使用""" |
| # 清理GPU缓存 |
| if torch.cuda.is_available(): |
| torch.cuda.empty_cache() |
| |
| # 设置内存分配策略 |
| if torch.cuda.is_available(): |
| torch.cuda.set_per_process_memory_fraction(0.9) |
| |
| @staticmethod |
| def monitor_memory_usage(): |
| """监控内存使用""" |
| if torch.cuda.is_available(): |
| allocated = torch.cuda.memory_allocated() / 1024**3 # GB |
| cached = torch.cuda.memory_reserved() / 1024**3 # GB |
| return {'allocated': allocated, 'cached': cached} |
| return {'allocated': 0, 'cached': 0} |
| ``` |
|
|
| #### 2. 计算优化 |
| ```python |
| class ComputeOptimizer: |
| """计算优化器""" |
| |
| @staticmethod |
| def enable_tf32(): |
| """启用TF32加速(Ampere架构GPU)""" |
| if torch.cuda.is_available(): |
| torch.backends.cuda.matmul.allow_tf32 = True |
| torch.backends.cudnn.allow_tf32 = True |
| |
| @staticmethod |
| def optimize_dataloader(dataloader, num_workers=4, pin_memory=True): |
| """优化数据加载器""" |
| return DataLoader( |
| dataloader.dataset, |
| batch_size=dataloader.batch_size, |
| shuffle=dataloader.shuffle, |
| num_workers=num_workers, |
| pin_memory=pin_memory and torch.cuda.is_available(), |
| persistent_workers=True if num_workers > 0 else False |
| ) |
| ``` |
|
|
| ## 模块设计 |
|
|
| ### 核心模块 |
|
|
| #### 1. 模型模块 (`src.models/`) |
| ```python |
| # 模型模块结构 |
| src/models/ |
| ├── __init__.py |
| ├── pad_predictor.py # 核心预测器 |
| ├── loss_functions.py # 损失函数 |
| ├── metrics.py # 评估指标 |
| ├── model_factory.py # 模型工厂 |
| └── base_model.py # 基础模型类 |
| ``` |
|
|
| **设计原则**: |
| - 单一职责:每个类只负责一个特定功能 |
| - 开闭原则:对扩展开放,对修改封闭 |
| - 依赖倒置:依赖抽象而非具体实现 |
|
|
| #### 2. 数据模块 (`src.data/`) |
| ```python |
| # 数据模块结构 |
| src/data/ |
| ├── __init__.py |
| ├── dataset.py # 数据集类 |
| ├── data_loader.py # 数据加载器 |
| ├── preprocessor.py # 数据预处理器 |
| ├── synthetic_generator.py # 合成数据生成器 |
| └── data_validator.py # 数据验证器 |
| ``` |
|
|
| **设计模式**: |
| - 策略模式:不同的数据预处理策略 |
| - 工厂模式:数据生成器工厂 |
| - 观察者模式:数据质量监控 |
|
|
| #### 3. 工具模块 (`src.utils/`) |
| ```python |
| # 工具模块结构 |
| src/utils/ |
| ├── __init__.py |
| ├── inference_engine.py # 推理引擎 |
| ├── trainer.py # 训练器 |
| ├── logger.py # 日志工具 |
| ├── config.py # 配置管理 |
| └── exceptions.py # 自定义异常 |
| ``` |
|
|
| **功能特性**: |
| - 高性能推理引擎 |
| - 灵活的训练管理 |
| - 结构化日志系统 |
| - 统一的配置管理 |
|
|
| ## 设计模式 |
|
|
| ### 1. 工厂模式 (Factory Pattern) |
|
|
| ```python |
| class ModelFactory: |
| """模型工厂类""" |
| |
| _models = { |
| 'pad_predictor': PADPredictor, |
| 'advanced_predictor': AdvancedPADPredictor, |
| 'ensemble_predictor': EnsemblePredictor |
| } |
| |
| @classmethod |
| def create_model(cls, model_type: str, config: Dict[str, Any]): |
| """创建模型实例""" |
| if model_type not in cls._models: |
| raise ValueError(f"不支持的模型类型: {model_type}") |
| |
| model_class = cls._models[model_type] |
| return model_class(**config) |
| |
| @classmethod |
| def register_model(cls, name: str, model_class): |
| """注册新的模型类型""" |
| cls._models[name] = model_class |
| ``` |
|
|
| ### 2. 策略模式 (Strategy Pattern) |
|
|
| ```python |
| class LossStrategy(ABC): |
| """损失策略抽象基类""" |
| |
| @abstractmethod |
| def compute_loss(self, predictions, targets): |
| pass |
| |
| class WeightedMSELoss(LossStrategy): |
| """加权均方误差损失""" |
| |
| def compute_loss(self, predictions, targets): |
| # 实现加权MSE |
| pass |
| |
| class HuberLoss(LossStrategy): |
| """Huber损失""" |
| |
| def compute_loss(self, predictions, targets): |
| # 实现Huber损失 |
| pass |
| |
| class LossContext: |
| """损失上下文""" |
| |
| def __init__(self, strategy: LossStrategy): |
| self._strategy = strategy |
| |
| def set_strategy(self, strategy: LossStrategy): |
| self._strategy = strategy |
| |
| def compute_loss(self, predictions, targets): |
| return self._strategy.compute_loss(predictions, targets) |
| ``` |
|
|
| ### 3. 观察者模式 (Observer Pattern) |
|
|
| ```python |
| class TrainingObserver(ABC): |
| """训练观察者抽象基类""" |
| |
| @abstractmethod |
| def on_epoch_start(self, epoch, metrics): |
| pass |
| |
| @abstractmethod |
| def on_epoch_end(self, epoch, metrics): |
| pass |
| |
| class LoggingObserver(TrainingObserver): |
| """日志观察者""" |
| |
| def on_epoch_end(self, epoch, metrics): |
| self.logger.info(f"Epoch {epoch}: {metrics}") |
| |
| class CheckpointObserver(TrainingObserver): |
| """检查点观察者""" |
| |
| def on_epoch_end(self, epoch, metrics): |
| if self.should_save_checkpoint(metrics): |
| self.save_checkpoint(epoch, metrics) |
| |
| class TrainingSubject: |
| """训练主题""" |
| |
| def __init__(self): |
| self._observers = [] |
| |
| def attach(self, observer: TrainingObserver): |
| self._observers.append(observer) |
| |
| def detach(self, observer: TrainingObserver): |
| self._observers.remove(observer) |
| |
| def notify_epoch_end(self, epoch, metrics): |
| for observer in self._observers: |
| observer.on_epoch_end(epoch, metrics) |
| ``` |
|
|
| ### 4. 建造者模式 (Builder Pattern) |
|
|
| ```python |
| class ModelBuilder: |
| """模型建造者""" |
| |
| def __init__(self): |
| self.input_dim = 7 |
| self.output_dim = 3 |
| self.hidden_dims = [128, 64, 32] |
| self.dropout_rate = 0.3 |
| self.activation = 'relu' |
| |
| def with_dimensions(self, input_dim, output_dim): |
| self.input_dim = input_dim |
| self.output_dim = output_dim |
| return self |
| |
| def with_hidden_layers(self, hidden_dims): |
| self.hidden_dims = hidden_dims |
| return self |
| |
| def with_dropout(self, dropout_rate): |
| self.dropout_rate = dropout_rate |
| return self |
| |
| def with_activation(self, activation): |
| self.activation = activation |
| return self |
| |
| def build(self): |
| return PADPredictor( |
| input_dim=self.input_dim, |
| output_dim=self.output_dim, |
| hidden_dims=self.hidden_dims, |
| dropout_rate=self.dropout_rate |
| ) |
| |
| # 使用示例 |
| model = (ModelBuilder() |
| .with_dimensions(7, 5) |
| .with_hidden_layers([256, 128, 64]) |
| .with_dropout(0.3) |
| .build()) |
| ``` |
|
|
| ## 性能优化 |
|
|
| ### 1. 模型优化 |
|
|
| #### 量化 |
| ```python |
| class ModelQuantizer: |
| """模型量化器""" |
| |
| @staticmethod |
| def quantize_model(model, calibration_data): |
| """动态量化模型""" |
| model.eval() |
| |
| # 动态量化 |
| quantized_model = torch.quantization.quantize_dynamic( |
| model, {nn.Linear}, dtype=torch.qint8 |
| ) |
| |
| return quantized_model |
| |
| @staticmethod |
| def quantize_aware_training(model, train_loader): |
| """量化感知训练""" |
| model.eval() |
| model.qconfig = torch.quantization.get_default_qat_qconfig('fbgemm') |
| torch.quantization.prepare_qat(model, inplace=True) |
| |
| # 量化感知训练 |
| for epoch in range(num_epochs): |
| for batch in train_loader: |
| # 训练步骤 |
| pass |
| |
| # 转换为量化模型 |
| quantized_model = torch.quantization.convert(model.eval(), inplace=False) |
| return quantized_model |
| ``` |
|
|
| #### 模型剪枝 |
| ```python |
| class ModelPruner: |
| """模型剪枝器""" |
| |
| @staticmethod |
| def prune_model(model, pruning_ratio=0.2): |
| """结构化剪枝""" |
| import torch.nn.utils.prune as prune |
| |
| # 剪枝所有线性层 |
| for name, module in model.named_modules(): |
| if isinstance(module, nn.Linear): |
| prune.l1_unstructured(module, name='weight', amount=pruning_ratio) |
| |
| return model |
| |
| @staticmethod |
| def remove_pruning(model): |
| """移除剪枝重参数化""" |
| import torch.nn.utils.prune as prune |
| |
| for name, module in model.named_modules(): |
| if isinstance(module, nn.Linear): |
| prune.remove(module, 'weight') |
| |
| return model |
| ``` |
|
|
| ### 2. 推理优化 |
|
|
| #### 批量推理优化 |
| ```python |
| class BatchInferenceOptimizer: |
| """批量推理优化器""" |
| |
| def __init__(self, model, device): |
| self.model = model |
| self.device = device |
| self.optimal_batch_size = self._find_optimal_batch_size() |
| |
| def _find_optimal_batch_size(self): |
| """寻找最优批次大小""" |
| batch_sizes = [1, 2, 4, 8, 16, 32, 64, 128] |
| best_batch_size = 1 |
| best_throughput = 0 |
| |
| dummy_input = torch.randn(1, 7).to(self.device) |
| |
| for batch_size in batch_sizes: |
| try: |
| # 测试批次大小 |
| batch_input = dummy_input.repeat(batch_size, 1) |
| |
| start_time = time.time() |
| with torch.no_grad(): |
| for _ in range(10): |
| _ = self.model(batch_input) |
| end_time = time.time() |
| |
| throughput = (batch_size * 10) / (end_time - start_time) |
| |
| if throughput > best_throughput: |
| best_throughput = throughput |
| best_batch_size = batch_size |
| |
| except RuntimeError: |
| break # 内存不足 |
| |
| return best_batch_size |
| ``` |
|
|
| ## 扩展性设计 |
|
|
| ### 1. 插件系统 |
|
|
| ```python |
| class PluginManager: |
| """插件管理器""" |
| |
| def __init__(self): |
| self.plugins = {} |
| self.hooks = defaultdict(list) |
| |
| def register_plugin(self, name: str, plugin): |
| """注册插件""" |
| self.plugins[name] = plugin |
| |
| # 注册插件钩子 |
| if hasattr(plugin, 'get_hooks'): |
| for hook_name, hook_func in plugin.get_hooks().items(): |
| self.hooks[hook_name].append(hook_func) |
| |
| def execute_hooks(self, hook_name: str, *args, **kwargs): |
| """执行钩子""" |
| for hook_func in self.hooks[hook_name]: |
| hook_func(*args, **kwargs) |
| |
| class PluginBase(ABC): |
| """插件基类""" |
| |
| @abstractmethod |
| def initialize(self, config): |
| pass |
| |
| @abstractmethod |
| def cleanup(self): |
| pass |
| |
| def get_hooks(self): |
| return {} |
| ``` |
|
|
| ### 2. 配置扩展 |
|
|
| ```python |
| class ConfigManager: |
| """配置管理器""" |
| |
| def __init__(self): |
| self.config_schemas = {} |
| self.config_validators = {} |
| |
| def register_config_schema(self, name: str, schema: Dict): |
| """注册配置模式""" |
| self.config_schemas[name] = schema |
| |
| def register_validator(self, name: str, validator: callable): |
| """注册配置验证器""" |
| self.config_validators[name] = validator |
| |
| def validate_config(self, config: Dict[str, Any]) -> bool: |
| """验证配置""" |
| for name, validator in self.config_validators.items(): |
| if name in config: |
| if not validator(config[name]): |
| raise ValueError(f"配置验证失败: {name}") |
| return True |
| ``` |
|
|
| ### 3. 模型注册系统 |
|
|
| ```python |
| class ModelRegistry: |
| """模型注册系统""" |
| |
| _models = {} |
| _model_metadata = {} |
| |
| @classmethod |
| def register(cls, name: str, metadata: Dict = None): |
| """模型注册装饰器""" |
| def decorator(model_class): |
| cls._models[name] = model_class |
| cls._model_metadata[name] = metadata or {} |
| return model_class |
| return decorator |
| |
| @classmethod |
| def create_model(cls, name: str, **kwargs): |
| """创建模型""" |
| if name not in cls._models: |
| raise ValueError(f"未注册的模型: {name}") |
| |
| model_class = cls._models[name] |
| return model_class(**kwargs) |
| |
| @classmethod |
| def list_models(cls): |
| """列出所有注册的模型""" |
| return list(cls._models.keys()) |
| |
| # 使用示例 |
| @ModelRegistry.register("advanced_pad", |
| {"description": "高级PAD预测器", "version": "2.0"}) |
| class AdvancedPADPredictor(nn.Module): |
| def __init__(self, **kwargs): |
| super().__init__() |
| # 模型实现 |
| pass |
| ``` |
|
|
| --- |
|
|
| 本架构文档描述了系统的整体设计和实现细节。随着项目的发展,架构会持续优化和扩展。如有建议或问题,请通过GitHub Issues反馈。 |