Spaces:
Running
Running
zhan1206
Feat: Add graphical visualization tools (attention heatmap, loss curve, architecture)
d587e7a | """ | |
| 图形版模型可视化工具 - 使用 matplotlib 绘制注意力热力图、损失曲线、模型架构图 | |
| """ | |
| import sys | |
| import torch | |
| import numpy as np | |
| from pathlib import Path | |
| sys.path.insert(0, '.') | |
| try: | |
| import matplotlib.pyplot as plt | |
| import matplotlib | |
| MATPLOTLIB_AVAILABLE = True | |
| except ImportError: | |
| MATPLOTLIB_AVAILABLE = False | |
| print("[WARN] matplotlib 未安装,将使用文本模式可视化") | |
| print(" 安装命令: pip install matplotlib") | |
| def visualize_attention_graphical(attention_weights, head_idx=0, max_len=32, output_path=None): | |
| """ | |
| 图形化注意力可视化(需要 matplotlib) | |
| Args: | |
| attention_weights: 注意力权重,形状为 (batch, num_heads, seq_len, seq_len) | |
| head_idx: 要可视化的注意力头索引 | |
| max_len: 最大可视化长度 | |
| output_path: 输出路径(如果提供,则保存为文件) | |
| """ | |
| if not MATPLOTLIB_AVAILABLE: | |
| print("[WARN] matplotlib 未安装,跳过图形化注意力可视化") | |
| return | |
| print("[VISUALIZE] 图形化注意力可视化...") | |
| # 获取指定头的注意力权重 | |
| attn = attention_weights[0, head_idx, :max_len, :max_len].cpu().numpy() # (seq_len, seq_len) | |
| # 创建热力图 | |
| plt.figure(figsize=(8, 6)) | |
| plt.imshow(attn, cmap='Blues', aspect='auto') | |
| plt.colorbar(label='Attention Weight') | |
| plt.title(f'Attention Head {head_idx}') | |
| plt.xlabel('Key Position') | |
| plt.ylabel('Query Position') | |
| plt.tight_layout() | |
| # 保存或显示 | |
| if output_path: | |
| plt.savefig(output_path, dpi=100) | |
| print(f" 注意力热力图已保存到: {output_path}") | |
| else: | |
| plt.show() | |
| plt.close() | |
| print(" 图形化注意力可视化完成") | |
| print() | |
| def visualize_loss_curve_graphical(losses, window=10, output_path=None): | |
| """ | |
| 图形化损失曲线可视化(需要 matplotlib) | |
| Args: | |
| losses: 损失值列表 | |
| window: 平滑窗口大小 | |
| output_path: 输出路径(如果提供,则保存为文件) | |
| """ | |
| if not MATPLOTLIB_AVAILABLE: | |
| print("[WARN] matplotlib 未安装,跳过图形化损失曲线可视化") | |
| return | |
| print("[VISUALIZE] 图形化损失曲线可视化...") | |
| if len(losses) < 2: | |
| print(" 损失点太少,无法可视化") | |
| return | |
| # 平滑损失(移动平均) | |
| smoothed = [] | |
| for i in range(len(losses)): | |
| start = max(0, i - window // 2) | |
| end = min(len(losses), i + window // 2 + 1) | |
| smoothed.append(sum(losses[start:end]) / (end - start)) | |
| # 创建损失曲线图 | |
| plt.figure(figsize=(10, 6)) | |
| plt.plot(range(1, len(losses) + 1), losses, 'b-', alpha=0.3, label='Original') | |
| plt.plot(range(1, len(smoothed) + 1), smoothed, 'r-', label=f'Smoothed (window={window})') | |
| plt.xlabel('Step') | |
| plt.ylabel('Loss') | |
| plt.title('Training Loss Curve') | |
| plt.legend() | |
| plt.grid(True, alpha=0.3) | |
| plt.tight_layout() | |
| # 保存或显示 | |
| if output_path: | |
| plt.savefig(output_path, dpi=100) | |
| print(f" 损失曲线图已保存到: {output_path}") | |
| else: | |
| plt.show() | |
| plt.close() | |
| print(" 图形化损失曲线可视化完成") | |
| print() | |
| def visualize_model_architecture_graphical(model, output_path=None): | |
| """ | |
| 图形化模型架构可视化(需要 matplotlib) | |
| Args: | |
| model: PyTorch 模型 | |
| output_path: 输出路径(如果提供,则保存为文件) | |
| """ | |
| if not MATPLOTLIB_AVAILABLE: | |
| print("[WARN] matplotlib 未安装,跳过图形化模型架构可视化") | |
| return | |
| print("[VISUALIZE] 图形化模型架构可视化...") | |
| # 获取所有模块 | |
| modules = [] | |
| params = [] | |
| for name, module in model.named_modules(): | |
| if name == "": | |
| continue | |
| modules.append(name) | |
| params.append(sum(p.numel() for p in module.parameters())) | |
| # 创建条形图 | |
| plt.figure(figsize=(12, 6)) | |
| plt.barh(range(len(modules)), params, color='skyblue') | |
| plt.yticks(range(len(modules)), modules, fontsize=8) | |
| plt.xlabel('Parameters') | |
| plt.title('Model Architecture (Parameters per Module)') | |
| plt.tight_layout() | |
| # 保存或显示 | |
| if output_path: | |
| plt.savefig(output_path, dpi=100) | |
| print(f" 模型架构图已保存到: {output_path}") | |
| else: | |
| plt.show() | |
| plt.close() | |
| print(" 图形化模型架构可视化完成") | |
| print() | |
| def save_visualization_report_graphical(model, attention_weights, losses, output_dir): | |
| """ | |
| 保存图形化可视化报告到文件 | |
| Args: | |
| model: PyTorch 模型 | |
| attention_weights: 注意力权重 | |
| losses: 损失值列表 | |
| output_dir: 输出目录 | |
| """ | |
| if not MATPLOTLIB_AVAILABLE: | |
| print("[WARN] matplotlib 未安装,无法生成图形化报告") | |
| return | |
| print("[VISUALIZE] 保存图形化可视化报告...") | |
| # 创建输出目录 | |
| output_dir = Path(output_dir) | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| # 1. 注意力热力图 | |
| if attention_weights is not None: | |
| attention_path = output_dir / "attention_heatmap.png" | |
| visualize_attention_graphical( | |
| attention_weights, | |
| head_idx=0, | |
| max_len=min(32, attention_weights.shape[2]), | |
| output_path=str(attention_path) | |
| ) | |
| # 2. 损失曲线图 | |
| if losses is not None and len(losses) > 1: | |
| loss_path = output_dir / "loss_curve.png" | |
| visualize_loss_curve_graphical( | |
| losses, | |
| window=10, | |
| output_path=str(loss_path) | |
| ) | |
| # 3. 模型架构图 | |
| architecture_path = output_dir / "model_architecture.png" | |
| visualize_model_architecture_graphical( | |
| model, | |
| output_path=str(architecture_path) | |
| ) | |
| print(f" 图形化报告已保存到: {output_dir}") | |
| print() | |
| if __name__ == "__main__": | |
| print("=" * 60) | |
| print("Fusion-LLM 图形化模型可视化工具测试") | |
| print("=" * 60) | |
| print() | |
| if not MATPLOTLIB_AVAILABLE: | |
| print("[WARN] matplotlib 未安装,无法运行图形化测试") | |
| print(" 安装命令: pip install matplotlib") | |
| sys.exit(1) | |
| # 1. 测试注意力热力图 | |
| print("[1] 测试图形化注意力热力图...") | |
| attention_weights = torch.rand(1, 2, 8, 8) # (batch, num_heads, seq_len, seq_len) | |
| attention_weights = torch.softmax(attention_weights, dim=-1) | |
| visualize_attention_graphical( | |
| attention_weights, | |
| head_idx=0, | |
| max_len=8, | |
| output_path="output/attention_heatmap_test.png" | |
| ) | |
| print() | |
| # 2. 测试损失曲线图 | |
| print("[2] 测试图形化损失曲线图...") | |
| losses = [5.0, 4.5, 4.0, 3.5, 3.0, 2.8, 2.5, 2.3, 2.1, 2.0] | |
| visualize_loss_curve_graphical( | |
| losses, | |
| window=3, | |
| output_path="output/loss_curve_test.png" | |
| ) | |
| print() | |
| # 3. 测试模型架构图 | |
| print("[3] 测试图形化模型架构图...") | |
| from models.fusion_mini import FusionMini, FusionMiniConfig | |
| config = FusionMiniConfig( | |
| vocab_size=100, | |
| hidden_size=32, | |
| num_hidden_layers=1, | |
| ) | |
| model = FusionMini(config) | |
| visualize_model_architecture_graphical( | |
| model, | |
| output_path="output/model_architecture_test.png" | |
| ) | |
| print() | |
| # 4. 保存完整报告 | |
| print("[4] 保存图形化可视化报告...") | |
| save_visualization_report_graphical( | |
| model=model, | |
| attention_weights=attention_weights, | |
| losses=losses, | |
| output_dir="output/visualization_report_graphical" | |
| ) | |
| print() | |
| print("[PASS] 图形化模型可视化工具测试通过") | |
| sys.exit(0) | |