DAY 35 模型可视化与推理

知识点回顾:

  1. 三种不同的模型可视化方法:推荐torchinfo打印summary+权重分布可视化
  2. 进度条功能:手动和自动写法,让打印结果更加美观
  3. 推理的写法:评估模式

作业:调整模型定义时的超参数,对比下效果。

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
from torchinfo import summary
import matplotlib.pyplot as plt
import numpy as np
from tqdm import tqdm

# 设置随机种子确保结果可复现
torch.manual_seed(42)
np.random.seed(42)

# 定义数据预处理
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))  # MNIST数据集的均值和标准差
])

# 加载MNIST数据集
train_dataset = datasets.MNIST('data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST('data', train=False, transform=transform)

# 定义超参数配置
configs = [
    {
        'name': ' baseline',
        'hidden_size': 128,
        'learning_rate': 0.01,
        'batch_size': 64,
        'activation': 'relu'
    },
    {
        'name': '增加隐藏层大小',
        'hidden_size': 256,
        'learning_rate': 0.01,
        'batch_size': 64,
        'activation': 'relu'
    },
    {
        'name': '降低学习率',
        'hidden_size': 128,
        'learning_rate': 0.001,
        'batch_size': 64,
        'activation': 'relu'
    },
    {
        'name': '增加批量大小',
        'hidden_size': 128,
        'learning_rate': 0.01,
        'batch_size': 128,
        'activation': 'relu'
    },
    {
        'name': '使用LeakyReLU',
        'hidden_size': 128,
        'learning_rate': 0.01,
        'batch_size': 64,
        'activation': 'leaky_relu'
    }
]

# 定义模型
class MLP(nn.Module):
    def __init__(self, hidden_size=128, activation='relu'):
        super(MLP, self).__init__()
        self.fc1 = nn.Linear(28 * 28, hidden_size)
        self.fc2 = nn.Linear(hidden_size, hidden_size)
        self.fc3 = nn.Linear(hidden_size, 10)
        
        # 根据配置选择激活函数
        if activation == 'relu':
            self.activation = nn.ReLU()
        elif activation == 'leaky_relu':
            self.activation = nn.LeakyReLU()
        else:
            raise ValueError(f"不支持的激活函数: {activation}")
    
    def forward(self, x):
        x = x.view(-1, 28 * 28)
        x = self.activation(self.fc1(x))
        x = self.activation(self.fc2(x))
        x = self.fc3(x)
        return x

# 训练和评估函数
def train_and_evaluate(config):
    # 创建数据加载器
    train_loader = DataLoader(train_dataset, batch_size=config['batch_size'], shuffle=True)
    test_loader = DataLoader(test_dataset, batch_size=config['batch_size'])
    
    # 初始化模型
    model = MLP(hidden_size=config['hidden_size'], activation=config['activation'])
    
    # 打印模型摘要
    print(f"\n=== {config['name']} 模型摘要 ===")
    summary(model, input_size=(1, 28, 28))
    
    # 定义损失函数和优化器
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=config['learning_rate'])
    
    # 训练模型
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.to(device)
    
    train_losses = []
    test_accuracies = []
    
    print(f"\n=== 训练 {config['name']} 模型 ===")
    for epoch in range(5):  # 训练5个epoch
        model.train()
        running_loss = 0.0
        
        # 使用tqdm显示进度条
        progress_bar = tqdm(enumerate(train_loader), total=len(train_loader))
        for batch_idx, (data, target) in progress_bar:
            data, target = data.to(device), target.to(device)
            
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
            
            running_loss += loss.item()
            progress_bar.set_description(f'Epoch {epoch+1}, Batch {batch_idx+1}/{len(train_loader)}, Loss: {loss.item():.4f}')
        
        # 记录训练损失
        epoch_loss = running_loss / len(train_loader)
        train_losses.append(epoch_loss)
        
        # 评估模型
        model.eval()  # 设置为评估模式
        test_correct = 0
        test_total = 0
        
        with torch.no_grad():  # 关闭梯度计算以加速推理
            for data, target in test_loader:
                data, target = data.to(device), target.to(device)
                output = model(data)
                _, predicted = torch.max(output.data, 1)
                test_total += target.size(0)
                test_correct += (predicted == target).sum().item()
        
        test_accuracy = 100.0 * test_correct / test_total
        test_accuracies.append(test_accuracy)
        
        print(f'Epoch {epoch+1}, 训练损失: {epoch_loss:.4f}, 测试准确率: {test_accuracy:.2f}%')
    
    # 可视化权重分布
    visualize_weight_distribution(model, config['name'])
    
    return train_losses, test_accuracies

# 可视化权重分布
def visualize_weight_distribution(model, config_name):
    weights = []
    for name, param in model.named_parameters():
        if 'weight' in name:
            weights.append(param.cpu().detach().numpy().flatten())
    
    plt.figure(figsize=(10, 6))
    plt.hist(weights, bins=50, label=[name for name, param in model.named_parameters() if 'weight' in name])
    plt.title(f'{config_name} 模型权重分布')
    plt.xlabel('权重值')
    plt.ylabel('频率')
    plt.legend()
    plt.tight_layout()
    plt.savefig(f'{config_name}_weights.png')
    plt.close()

# 运行所有配置并比较结果
results = {}
for config in configs:
    train_losses, test_accuracies = train_and_evaluate(config)
    results[config['name']] = {
        'train_losses': train_losses,
        'test_accuracies': test_accuracies,
        'final_accuracy': test_accuracies[-1]
    }

# 比较不同配置的最终准确率
plt.figure(figsize=(12, 6))
plt.bar([config['name'] for config in configs], 
        [results[config['name']]['final_accuracy'] for config in configs])
plt.title('不同超参数配置的最终测试准确率')
plt.xlabel('配置')
plt.ylabel('准确率 (%)')
plt.ylim(95, 100)  # 设置合适的y轴范围以便更好地比较
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.savefig('hyperparameter_comparison.png')
plt.show()

# 打印最终结果
print("\n=== 最终结果比较 ===")
for config in configs:
    print(f"{config['name']}: 最终准确率 = {results[config['name']]['final_accuracy']:.2f}%")    

=== 最终结果比较 ===
 baseline: 最终准确率 = 96.05%
增加隐藏层大小: 最终准确率 = 95.38%
降低学习率: 最终准确率 = 97.64%
增加批量大小: 最终准确率 = 96.49%
使用LeakyReLU: 最终准确率 = 96.32%

### 时序知识推理的流程 时序知识推理是一种基于时间序列的知识图谱技术,用于处理具有时间维度的信息。其核心目标是从历史数据中提取规律,并对未来趋势做出预测或解释当前现象的原因。以下是关于时序知识推理的主要流程及其可视化表示的相关说明。 #### 1. 数据收集预处理 在构建时序知识图谱的过程中,第一步是对原始数据进行清洗和标准化。这些数据通常来自多个异构源,包括但不限于日志文件、传感器读数以及社交媒体动态等。为了确保后续分析的有效性,需执行如下操作: - **去噪**:移除异常值或噪声点以提高准确性[^2]。 - **对齐时间戳**:统一不同来源的时间单位以便比较和计算差异[^3]。 #### 2. 实体识别时序建模 此阶段重点在于检测文本中的关键要素——即所谓的“实体”,并将它们映射到已知类别下(如地点、日期)。同时建立各实体间随时间变化的关系网络: - 使用自然语言处理工具标注句子成分; - 应用机器学习算法训练模型来捕捉长期依赖性和周期特性[^4]。 #### 3. 关系抽取及时效性评估 一旦确定了各个节点的位置,则进一步挖掘连接两者的边属性—也就是具体发生的事件或者相互作用形式: - 自动化方式通过依存句法树解析器实现自动化关系提取; - 手工定义规则补充遗漏情况, 特别是在缺乏充足样本支持的小众领域内. 此外还需考虑每条记录有效期限长短不一的问题 – 即所谓时效性的度量标准 [^1]. #### 4. 推理引擎设计优化 最后一步就是搭建实际运行环境下的推理机制框架 : - 结合先验知识库辅助决策制定过程 ; - 运用概率论方法量化不确定性水平 , 如贝叶斯网路结构学习 . 对于整个系统的性能表现而言 , 不仅要关注单次查询响应速度还要兼顾整体吞吐能力平衡两者之间取舍关系至关重要 . --- ### 可视化建议 针对上述提到的不同环节可以分别采取相应的图形展示手段帮助理解复杂逻辑链条 : - 对于基础架构层面可以用分层拓扑图直观呈现组件间的隶属关系 ; - 当涉及到大量时间节点交互时推荐采用甘特图样式排列各项活动顺序便于追踪进度安排 ; - 如果想突出某些特殊时间段内的密集程度则散点分布图会更加合适一些 。 ```python import matplotlib.pyplot as plt from datetime import timedelta def plot_timeline(events): fig, ax = plt.subplots() start_dates = [] end_dates = [] labels = [] for event in events: label = f"{event['name']} ({str(event['start'])[:10]} - {str(event['end'])[:10]})" start_dates.append(event["start"]) end_dates.append(event["end"] + timedelta(days=1)) # Add one day to make the bar visible. labels.append(label) ax.barh(labels, [(e-s).days for s,e in zip(start_dates,end_dates)], left=start_dates) ax.set_xlabel('Timeline') ax.xaxis_date() # Ensure that x-axis is treated as dates plot_timeline([ {"name": "Event A", "start": date(2023,9,1), "end":date(2023,9,7)}, {"name": "Event B", "start": date(2023,8,15),"end":date(2023,8,25)} ]) plt.show() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值