day 33简单的神经网络

发布于:2025-05-23 ⋅ 阅读:(16) ⋅ 点赞:(0)

知识点回顾:

  1. PyTorch和cuda的安装
  2. 查看显卡信息的命令行命令(cmd中使用)
  3. cuda的检查
  4. 简单神经网络的流程
    1. 数据预处理(归一化、转换成张量)
    2. 模型的定义
      1. 继承nn.Module类
      2. 定义每一个层
      3. 定义前向传播流程
    3. 定义损失函数和优化器
    4. 定义训练流程
    5. 可视化loss过程
    6. # test_pytorch.py
      import torch
      
      # 检查导入是否成功
      print(f"PyTorch版本: {torch.__version__}")
      print(f"CUDA可用: {torch.cuda.is_available()}")
      
      # 设置随机种子
      torch.manual_seed(42)
      
      # 创建一个张量测试
      x = torch.randn(5, 5)
      print(f"随机张量:\n{x}")
      import torch.nn as nn
      import torch.optim as optim
      from torch.utils.data import DataLoader, TensorDataset
      import numpy as np
      import matplotlib.pyplot as plt
      
      # 设置随机种子确保结果可复现
      torch.manual_seed(42)
      np.random.seed(42)
      
      # -------------------------
      # 1. 环境检查
      # -------------------------
      def check_environment():
          """检查CUDA可用性并打印环境信息"""
          if torch.cuda.is_available():
              print(f"CUDA可用 - 设备: {torch.cuda.get_device_name(0)}")
              print(f"CUDA版本: {torch.version.cuda}")
          else:
              print("CUDA不可用,将使用CPU进行计算")
          print(f"PyTorch版本: {torch.__version__}")
      
      # -------------------------
      # 2. 数据预处理
      # -------------------------
      class DataPreprocessor:
          """数据预处理类,支持回归和分类任务"""
          
          def __init__(self, task_type="regression"):
              """
              task_type: 'regression' 或 'classification'
              """
              self.task_type = task_type
              self.x_mean, self.x_std = None, None
              self.y_mean, self.y_std = None, None
          
          def preprocess(self, x, y):
              """预处理数据并转换为张量"""
              # 特征归一化
              self.x_mean, self.x_std = x.mean(), x.std()
              x_normalized = (x - self.x_mean) / self.x_std
              
              # 根据任务类型处理标签
              if self.task_type == "regression":
                  self.y_mean, self.y_std = y.mean(), y.std()
                  y_normalized = (y - self.y_mean) / self.y_std
                  y_tensor = torch.tensor(y_normalized, dtype=torch.float32).view(-1, 1)
              else:  # 分类任务
                  y_tensor = torch.tensor(y, dtype=torch.long)
              
              x_tensor = torch.tensor(x_normalized, dtype=torch.float32).view(-1, 1)
              return x_tensor, y_tensor
          
          def denormalize_prediction(self, pred):
              """将预测结果反归一化(仅用于回归任务)"""
              if self.task_type == "regression":
                  return pred * self.y_std + self.y_mean
              return pred
      
      # -------------------------
      # 3. 模型定义
      # -------------------------
      class SimpleNet(nn.Module):
          """简单的两层神经网络"""
          
          def __init__(self, input_size=1, hidden_size=10, output_size=1):
              super(SimpleNet, self).__init__()
              self.fc1 = nn.Linear(input_size, hidden_size)
              self.relu = nn.ReLU()
              self.fc2 = nn.Linear(hidden_size, output_size)
          
          def forward(self, x):
              x = self.fc1(x)
              x = self.relu(x)
              x = self.fc2(x)
              return x
      
      # -------------------------
      # 4. 训练模块
      # -------------------------
      class Trainer:
          """模型训练器"""
          
          def __init__(self, model, task_type="regression", lr=0.01):
              self.model = model
              self.task_type = task_type
              
              # 根据任务类型选择损失函数
              self.criterion = nn.MSELoss() if task_type == "regression" else nn.CrossEntropyLoss()
              self.optimizer = optim.Adam(model.parameters(), lr=lr)
              self.train_losses = []
          
          def train(self, dataloader, num_epochs=100, print_every=10):
              """训练模型并记录损失"""
              for epoch in range(num_epochs):
                  epoch_loss = 0.0
                  for inputs, targets in dataloader:
                      # 前向传播
                      outputs = self.model(inputs)
                      loss = self.criterion(outputs, targets)
                      
                      # 反向传播和优化
                      self.optimizer.zero_grad()
                      loss.backward()
                      self.optimizer.step()
                      
                      epoch_loss += loss.item()
                  
                  # 记录每个epoch的平均损失
                  avg_loss = epoch_loss / len(dataloader)
                  self.train_losses.append(avg_loss)
                  
                  if (epoch + 1) % print_every == 0:
                      print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {avg_loss:.4f}')
              
              return self.train_losses
          
          def plot_loss(self):
              """可视化训练损失"""
              plt.figure(figsize=(10, 6))
              plt.plot(range(1, len(self.train_losses) + 1), self.train_losses, label='Training Loss')
              plt.xlabel('Epoch')
              plt.ylabel('Loss')
              plt.title('Training Loss over Epochs')
              plt.legend()
              plt.grid(True)
              plt.show()
      
      # -------------------------
      # 5. 主函数
      # -------------------------
      def main():
          # 检查环境
          check_environment()
          
          # 生成示例数据
          task_type = "regression"  # 或 "classification"
          
          if task_type == "regression":
              # 回归任务数据
              x = np.linspace(0, 10, 100)
              y = 2 * x + 1 + np.random.randn(100) * 0.5  # y = 2x + 1 + 噪声
          else:
              # 分类任务数据
              x = np.linspace(0, 10, 100)
              y = (x > 5).astype(int)  # 二分类问题
          
          # 数据预处理
          preprocessor = DataPreprocessor(task_type)
          x_tensor, y_tensor = preprocessor.preprocess(x, y)
          
          # 创建数据加载器
          dataset = TensorDataset(x_tensor, y_tensor)
          dataloader = DataLoader(dataset, batch_size=16, shuffle=True)
          
          # 初始化模型
          if task_type == "regression":
              model = SimpleNet(input_size=1, output_size=1)
          else:
              model = SimpleNet(input_size=1, output_size=2)  # 二分类问题有2个类别
          
          # 训练模型
          trainer = Trainer(model, task_type=task_type, lr=0.01)
          losses = trainer.train(dataloader, num_epochs=100)
          
          # 可视化损失
          trainer.plot_loss()
          
          # 评估模型
          model.eval()
          with torch.no_grad():
              test_x = np.array([5.0])  # 测试输入
              test_x_normalized = (test_x - preprocessor.x_mean) / preprocessor.x_std
              test_tensor = torch.tensor(test_x_normalized, dtype=torch.float32).view(-1, 1)
              
              prediction = model(test_tensor)
              
              if task_type == "regression":
                  # 反归一化回归预测结果
                  prediction = preprocessor.denormalize_prediction(prediction.item())
                  print(f"回归预测结果: {prediction:.4f}")
                  print(f"真实值: {2*test_x[0] + 1:.4f}")  # 基于y=2x+1
              else:
                  # 获取分类预测结果
                  _, predicted = torch.max(prediction, 1)
                  print(f"分类预测类别: {predicted.item()}")
                  print(f"真实类别: {1 if test_x[0] > 5 else 0}")
      
      if __name__ == "__main__":
          main()    


网站公告

今日签到

点亮在社区的每一天
去签到