【李宏毅深度学习——回归模型的PyTorch架构】Homework 1:COVID-19 Cases Prediction (Regression)

目录

[1、显示NVIDIA GPU的状态信息](#1、显示NVIDIA GPU的状态信息)

2、数据集的两种不同的下载方式

3、导入相关库

4、三个工具函数

5、定义自己的数据集类

6、定义神经网络模型

7、定义选择特征的函数

8、训练过程

[9、超参数字典 config](#9、超参数字典 config)

10、准备和加载数据

11、创建并训练模型

[12、加载并启动 TensorBoard](#12、加载并启动 TensorBoard)

13、使用训练好的模型进行预测

14、下载文件到本地


1、显示NVIDIA GPU的状态信息

python 复制代码
# check gpu type
!nvidia-smi

!nvidia-smi 是在Jupyter Notebook或Google Colab等环境中运行的Shell命令,用于显示NVIDIA GPU的状态信息。在colab中,若要运行Shell命令,则可在前面加:!

**2、**数据集的两种不同的下载方式

python 复制代码
# google drive link
!gdown --id '1BjXalPZxq9mybPKNjF3h5L3NcF7XKTS-' --output covid_train.csv
!gdown --id '1B55t74Jg2E5FCsKCsUEkPKIuqaY7UIi1' --output covid_test.csv

# dropbox link
# !wget -O covid_train.csv https://www.dropbox.com/s/lmy1riadzoy0ahw/covid.train.csv?dl=0
# !wget -O covid_test.csv https://www.dropbox.com/s/zalbw42lu4nmhr2/covid.test.csv?dl=0

这段代码使用了数据集的两种不同的下载方式(gdown和wget)

  1. 使用gdown下载(激活状态)

    • gdown是一个命令行工具,专门用于从Google Drive下载文件

    • --id '1BjXalPZxq9mybPKNjF3h5L3NcF7XKTS-' 指定了Google Drive上文件的ID

    • --output covid_train.csv 指定了下载后的文件名为covid_train.csv

    • 同样的方法下载测试集,保存为covid_test.csv

  2. 使用wget下载(已注释)

    • 这部分代码被注释掉了,但提供了另一种从Dropbox下载同样文件的方法

    • wget -O 命令用于从指定URL下载文件并保存为指定名称

    • dl=0 参数改为 dl=1 会直接下载Dropbox文件而不是预览页面

Dropbox 介绍:

Dropbox 是一个云存储服务,允许用户存储、同步和共享文件。它提供跨设备访问,用户可以将文件上传到云端,并在多个设备间同步。Dropbox 支持文件共享,用户可以生成共享链接与他人共享文件,并控制文件访问权限。它还支持版本控制,允许用户查看和恢复文件的历史版本。

Dropbox 提供免费和付费版本。免费版提供 2 GB 存储空间,适合个人使用;付费版提供更多存储空间和团队协作功能,如 Dropbox Plus(2 TB 存储)和 Dropbox Business(企业级功能)。通过安装客户端,用户可以在不同设备上访问文件,确保文件始终保持同步。

此外,Dropbox 允许用户与团队共同工作,支持多人同时编辑文件,并与其他应用(如 Google Docs、Microsoft Office)集成。它适用于文件备份、团队协作以及跨设备的文件访问和共享。

总结来说,Dropbox 是一个简单且功能强大的工具,方便个人和团队存储、管理和共享文件。

3、导入相关库

python 复制代码
# Numerical Operations
import math
import numpy as np

# Reading/Writing Data
import pandas as pd
import os
import csv

# For Progress Bar为循环提供进度条,在训练深度学习模型时非常有用
from tqdm import tqdm

# Pytorch
import torch 
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader, random_split

# For plotting learning curve
from torch.utils.tensorboard import SummaryWriter

数值计算库

  • import math - 提供基本数学函数

  • import numpy as np - 提供高效的数值计算功能,尤其是处理数组和矩阵

数据处理库

  • import pandas as pd - 用于数据分析和操作结构化数据

  • import os - 提供与操作系统交互的功能,如文件路径操作

  • import csv - 用于读写CSV文件

进度显示

  • from tqdm import tqdm - 为循环提供进度条,在训练深度学习模型时非常有用

PyTorch相关

  • import torch - PyTorch的核心库

  • import torch.nn as nn - 包含神经网络层的定义和各种损失函数

  • from torch.utils.data import Dataset, DataLoader, random_split - 数据加载和处理工具

    • Dataset - 用于自定义数据集

    • DataLoader - 用于批量加载数据

    • random_split - 用于将数据集随机分割成训练集和验证集

可视化工具

  • from torch.utils.tensorboard import SummaryWriter - 用于记录训练过程中的指标并可视化

这是一个典型的深度学习项目的导入部分,表明您可能在准备构建一个PyTorch模型来处理之前下载的COVID相关数据集。这些导入涵盖了数据处理、模型构建、训练过程跟踪和可视化等完整的深度学习工作流程所需的工具。

4、三个工具函数

python 复制代码
def same_seed(seed): 
    '''Fixes random number generator seeds for reproducibility.'''
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False
    np.random.seed(seed)
    torch.manual_seed(seed)
    if torch.cuda.is_available():
        torch.cuda.manual_seed_all(seed)

def train_valid_split(data_set, valid_ratio, seed):
    '''Split provided training data into training set and validation set'''
    valid_set_size = int(valid_ratio * len(data_set)) 
    train_set_size = len(data_set) - valid_set_size
    train_set, valid_set = random_split(data_set, [train_set_size, valid_set_size], generator=torch.Generator().manual_seed(seed))
    return np.array(train_set), np.array(valid_set)

def predict(test_loader, model, device):
    model.eval() # Set your model to evaluation mode.
    preds = []
    for x in tqdm(test_loader):
        x = x.to(device)                        
        with torch.no_grad():                   
            pred = model(x)                     
            preds.append(pred.detach().cpu())   
    preds = torch.cat(preds, dim=0).numpy()  
    return preds

第一个函数

用于确保实验的可重复性,通过固定各种随机数生成器的种子:

具体来说,它做了以下几件事:

  1. torch.backends.cudnn.deterministic = True

    • 设置CUDNN(NVIDIA的深度学习库)为确定性模式,这意味着每次运行时都会得到相同的结果。通常,CUDNN会尝试优化计算速度,这可能导致不稳定的随机性,设置为True可以保证可复现性。
  2. torch.backends.cudnn.benchmark = False

    • 禁用CUDNN的自动调优功能。当网络的输入大小不变时,禁用这个选项可以保证每次运行时的计算方式保持一致,进一步增加可复现性。
  3. np.random.seed(seed)

    • 设置NumPy的随机数种子。很多深度学习代码会用到NumPy来生成随机数,设置种子可以确保生成的随机数序列一致。
  4. torch.manual_seed(seed)

    • 设置PyTorch的CPU随机数生成种子,确保CPU上的所有随机操作(如初始化权重等)具有可复现性。
  5. torch.cuda.manual_seed_all(seed)

    • 如果GPU可用,这行代码设置所有GPU设备上的随机数生成种子,确保GPU上的所有随机操作也有一致的输出。

总结: 这段代码确保了在每次运行时,所有涉及随机性的操作(如权重初始化、数据加载等)都能生成相同的结果,从而实现了实验的可复现性。

第二个函数

用于将数据集分割为训练集和验证集。

第三个函数

用于使用训练好的模型对测试数据进行预测。

5、定义自己的数据集类

python 复制代码
class COVID19Dataset(Dataset):
    '''
    x: Features.
    y: Targets, if none, do prediction.
    '''
    def __init__(self, x, y=None):
        if y is None:
            self.y = y
        else:
            self.y = torch.FloatTensor(y)
        self.x = torch.FloatTensor(x)

    def __getitem__(self, idx):
        if self.y is None:
            return self.x[idx]
        else:
            return self.x[idx], self.y[idx]

    def __len__(self):
        return len(self.x)

这段代码定义了一个自定义的 PyTorch 数据集类 COVID19Dataset,继承自 torch.utils.data.Dataset。这个类的目的是将输入的特征(x)和目标(y)封装成一个可以用于 PyTorch 数据加载器的对象,方便在训练和预测时进行批量处理。

6、定义神经网络模型

python 复制代码
class My_Model(nn.Module):
    def __init__(self, input_dim):
        super(My_Model, self).__init__()
        # TODO: modify model's structure, be aware of dimensions. 
        self.layers = nn.Sequential(
            nn.Linear(input_dim, 16),
            nn.ReLU(),
            nn.Linear(16, 8),
            nn.ReLU(),
            nn.Linear(8, 1)
        )

    def forward(self, x):
        x = self.layers(x)
        x = x.squeeze(1) # (B, 1) -> (B)
        return x

这段代码定义了一个简单的神经网络模型 My_Model,继承自 torch.nn.Module。该模型用于执行回归任务(因为最后一层输出的是一个标量),并通过 nn.Sequential 来定义一个包含多层的网络结构。

7、定义选择特征的函数

python 复制代码
def select_feat(train_data, valid_data, test_data, select_all=True):
    '''Selects useful features to perform regression'''
    y_train, y_valid = train_data[:,-1], valid_data[:,-1]
    raw_x_train, raw_x_valid, raw_x_test = train_data[:,:-1], valid_data[:,:-1], test_data

    if select_all:
        feat_idx = list(range(raw_x_train.shape[1]))
    else:
        feat_idx = [0,1,2,3,4] # TODO: Select suitable feature columns.
        
    return raw_x_train[:,feat_idx], raw_x_valid[:,feat_idx], raw_x_test[:,feat_idx], y_train, y_valid

这段代码定义了一个用于选择特征的函数 select_feat,它从训练数据、验证数据和测试数据中选择合适的特征进行回归分析。根据参数 select_all,该函数可以选择所有特征或指定的部分特征。

8、训练过程

python 复制代码
def trainer(train_loader, valid_loader, model, config, device):

    criterion = nn.MSELoss(reduction='mean') # Define your loss function, do not modify this.

    # Define your optimization algorithm. 
    # TODO: Please check https://pytorch.org/docs/stable/optim.html to get more available algorithms.
    # TODO: L2 regularization (optimizer(weight decay...) or implement by your self).
    optimizer = torch.optim.SGD(model.parameters(), lr=config['learning_rate'], momentum=0.7) 
    writer = SummaryWriter() # Writer of tensoboard.

    if not os.path.isdir('./models'):
        os.mkdir('./models') # Create directory of saving models.

    n_epochs, best_loss, step, early_stop_count = config['n_epochs'], math.inf, 0, 0

    for epoch in range(n_epochs):
        model.train() # Set your model to train mode.
        loss_record = []

        # tqdm is a package to visualize your training progress.
        train_pbar = tqdm(train_loader, position=0, leave=True)

        for x, y in train_pbar:
            optimizer.zero_grad()               # Set gradient to zero.
            x, y = x.to(device), y.to(device)   # Move your data to device. 
            pred = model(x)             
            loss = criterion(pred, y)
            loss.backward()                     # Compute gradient(backpropagation).
            optimizer.step()                    # Update parameters.
            step += 1
            loss_record.append(loss.detach().item())
            
            # Display current epoch number and loss on tqdm progress bar.
            train_pbar.set_description(f'Epoch [{epoch+1}/{n_epochs}]')
            train_pbar.set_postfix({'loss': loss.detach().item()})

        mean_train_loss = sum(loss_record)/len(loss_record)
        writer.add_scalar('Loss/train', mean_train_loss, step)

        model.eval() # Set your model to evaluation mode.
        loss_record = []
        for x, y in valid_loader:
            x, y = x.to(device), y.to(device)
            with torch.no_grad():
                pred = model(x)
                loss = criterion(pred, y)

            loss_record.append(loss.item())
            
        mean_valid_loss = sum(loss_record)/len(loss_record)
        print(f'Epoch [{epoch+1}/{n_epochs}]: Train loss: {mean_train_loss:.4f}, Valid loss: {mean_valid_loss:.4f}')
        # writer.add_scalar('Loss/valid', mean_valid_loss, step)

        if mean_valid_loss < best_loss:
            best_loss = mean_valid_loss
            torch.save(model.state_dict(), config['save_path']) # Save your best model
            print('Saving model with loss {:.3f}...'.format(best_loss))
            early_stop_count = 0
        else: 
            early_stop_count += 1

        if early_stop_count >= config['early_stop']:
            print('\nModel is not improving, so we halt the training session.')
            return

这段代码实现了一个训练过程,包括模型训练、验证、损失记录、模型保存、早停等功能。它利用 PyTorch 进行训练,并使用 TensorBoard 来记录训练过程的损失值。

逐部分解释:

  1. 定义损失函数和优化器:
python 复制代码
criterion = nn.MSELoss(reduction='mean') # Define your loss function
optimizer = torch.optim.SGD(model.parameters(), lr=config['learning_rate'], momentum=0.7)
  • criterion :使用均方误差(MSE)作为损失函数。reduction='mean' 表示取损失的平均值。

  • optimizer:使用随机梯度下降(SGD)作为优化器,并设置学习率和动量。优化器会更新模型的参数。

  1. TensorBoard 写入器:
python 复制代码
writer = SummaryWriter() # Writer of TensorBoard
  • 创建一个 SummaryWriter 对象,用于记录损失值到 TensorBoard 以便可视化训练过程。
  1. 创建模型保存目录:
python 复制代码
if not os.path.isdir('./models'):
    os.mkdir('./models') # Create directory of saving models
  • 如果 models 目录不存在,则创建一个,用于保存训练过程中表现最好的模型。
  1. 初始化训练参数:
python 复制代码
n_epochs, best_loss, step, early_stop_count = config['n_epochs'], math.inf, 0, 0
  • n_epochs:训练的总轮数。

  • best_loss:记录最好的验证损失,初始设置为正无穷。

  • step:记录训练步数,通常用于 TensorBoard。

  • early_stop_count:用于早停策略的计数器,初始值为 0。

  1. 训练和验证过程:
python 复制代码
for epoch in range(n_epochs):
    model.train() # Set your model to train mode
    loss_record = []

    train_pbar = tqdm(train_loader, position=0, leave=True) # tqdm progress bar

    for x, y in train_pbar:
        optimizer.zero_grad() # Reset gradients to zero
        x, y = x.to(device), y.to(device) # Move data to device (CPU/GPU)
        pred = model(x) # Forward pass
        loss = criterion(pred, y) # Compute loss
        loss.backward() # Backpropagation
        optimizer.step() # Update parameters
        step += 1
        loss_record.append(loss.detach().item())
        
        train_pbar.set_description(f'Epoch [{epoch+1}/{n_epochs}]') # Update progress bar
        train_pbar.set_postfix({'loss': loss.detach().item()})

    mean_train_loss = sum(loss_record) / len(loss_record) # Calculate average training loss
    writer.add_scalar('Loss/train', mean_train_loss, step)

    model.eval() # Set model to evaluation mode
    loss_record = []
    for x, y in valid_loader:
        x, y = x.to(device), y.to(device)
        with torch.no_grad(): # No gradient calculation during validation
            pred = model(x)
            loss = criterion(pred, y)

        loss_record.append(loss.item())

    mean_valid_loss = sum(loss_record) / len(loss_record) # Calculate average validation loss
    print(f'Epoch [{epoch+1}/{n_epochs}]: Train loss: {mean_train_loss:.4f}, Valid loss: {mean_valid_loss:.4f}')
  • 训练模式 :调用 model.train() 使模型进入训练模式,启用如 Dropout、BatchNorm 等层的训练状态。

  • 训练进度条 :使用 tqdm 来显示训练进度条,实时显示每个批次的损失。

  • 前向传播和反向传播:在每个批次中,首先将数据移到设备上(CPU 或 GPU),然后进行前向传播,计算损失,进行反向传播并更新模型参数。

  • 验证过程 :使用 model.eval() 将模型设置为评估模式,禁用 Dropout 等操作。在验证时,使用 torch.no_grad() 禁用梯度计算,以节省内存和计算资源。

  1. 模型保存和早停策略:
python 复制代码
if mean_valid_loss < best_loss:
    best_loss = mean_valid_loss
    torch.save(model.state_dict(), config['save_path']) # Save your best model
    print('Saving model with loss {:.3f}...'.format(best_loss))
    early_stop_count = 0
else: 
    early_stop_count += 1

if early_stop_count >= config['early_stop']:
    print('\nModel is not improving, so we halt the training session.')
    return
  • 保存最好的模型:如果当前验证损失比之前的最好损失更小,保存当前模型的参数,并重置早停计数器。

  • 早停机制 :如果验证损失连续多次没有改善(由 early_stop_count 控制),则停止训练,避免过拟合。

9、超参数字典 config

python 复制代码
device = 'cuda' if torch.cuda.is_available() else 'cpu'
config = {
    'seed': 5201314,      # Your seed number, you can pick your lucky number. :)
    'select_all': True,   # Whether to use all features.
    'valid_ratio': 0.2,   # validation_size = train_size * valid_ratio
    'n_epochs': 5000,     # Number of epochs.            
    'batch_size': 256, 
    'learning_rate': 1e-5,              
    'early_stop': 600,    # If model has not improved for this many consecutive epochs, stop training.     
    'save_path': './models/model.ckpt'  # Your model will be saved here.
}

这段代码设置了一个字典 config,其中包含了一些重要的配置参数,这些参数将在模型训练过程中使用。这些配置定义了训练的基本设置、超参数、早停策略以及文件保存路径等内容。

10、准备和加载数据

python 复制代码
same_seed(config['seed'])
train_data, test_data = pd.read_csv('./covid_train.csv').values, pd.read_csv('./covid_test.csv').values
train_data, valid_data = train_valid_split(train_data, config['valid_ratio'], config['seed'])

# Print out the data size.
print(f"""train_data size: {train_data.shape} 
valid_data size: {valid_data.shape} 
test_data size: {test_data.shape}""")

# Select features
x_train, x_valid, x_test, y_train, y_valid = select_feat(train_data, valid_data, test_data, config['select_all'])

# Print out the number of features.
print(f'number of features: {x_train.shape[1]}')

train_dataset, valid_dataset, test_dataset = COVID19Dataset(x_train, y_train), \
                                            COVID19Dataset(x_valid, y_valid), \
                                            COVID19Dataset(x_test)

# Pytorch data loader loads pytorch dataset into batches.
train_loader = DataLoader(train_dataset, batch_size=config['batch_size'], shuffle=True, pin_memory=True)
valid_loader = DataLoader(valid_dataset, batch_size=config['batch_size'], shuffle=True, pin_memory=True)
test_loader = DataLoader(test_dataset, batch_size=config['batch_size'], shuffle=False, pin_memory=True)

这段代码主要用于准备和加载训练数据、验证数据和测试数据,为后续的训练和推理过程做准备。

11、创建并训练模型

python 复制代码
model = My_Model(input_dim=x_train.shape[1]).to(device) # put your model and data on the same computation device.
trainer(train_loader, valid_loader, model, config, device)

这段代码的作用是创建并训练一个深度学习模型,确保模型和数据都被加载到同一个计算设备(GPU 或 CPU),并且开始训练。

12、加载并启动 TensorBoard

python 复制代码
%reload_ext tensorboard
%tensorboard --logdir=./runs/

这两行代码是在 Jupyter Notebook 中用于加载并启动 TensorBoard 的。

13、使用训练好的模型进行预测

python 复制代码
def save_pred(preds, file):
    ''' Save predictions to specified file '''
    with open(file, 'w') as fp:
        writer = csv.writer(fp)
        writer.writerow(['id', 'tested_positive'])
        for i, p in enumerate(preds):
            writer.writerow([i, p])

model = My_Model(input_dim=x_train.shape[1]).to(device)
model.load_state_dict(torch.load(config['save_path']))
preds = predict(test_loader, model, device) 
save_pred(preds, 'pred.csv')

这段代码的目的是使用训练好的模型进行预测,并将预测结果保存到指定的文件中。它分为三个主要步骤:加载模型、进行预测、保存预测结果。

14、下载文件到本地

python 复制代码
from google.colab import files
files.download('pred.csv')

这段代码是用于在 Google Colab 环境中下载文件。具体来说,它通过 files.download() 方法将本地文件(pred.csv)下载到你的本地计算机。

相关推荐
琢磨先生David2 小时前
Java 在人工智能领域的突围:从企业级架构到边缘计算的技术革新
java·人工智能·架构
kuaile09062 小时前
DeepSeek 与开源:肥沃土壤孕育 AI 硕果
人工智能·ai·gitee·开源·deepseek
飞火流星020274 小时前
BERT、T5、ViT 和 GPT-3 架构概述及代表性应用
人工智能·gpt-3·bert·t5·vit·人工智能模型架构
程序小K4 小时前
自然语言处理Hugging Face Transformers
人工智能·自然语言处理
恒拓高科WorkPlus4 小时前
BeeWorks:打造安全可控的企业内网即时通讯平台
大数据·人工智能·安全
爱数模的小驴4 小时前
2025 年“认证杯”数学中国数学建模网络挑战赛 C题 化工厂生产流程的预测和控制
深度学习·算法·计算机视觉
newxtc5 小时前
【指纹浏览器系列-chromium编译】
人工智能·安全
轻闲一号机5 小时前
【机器学习】机器学习笔记
人工智能·笔记·机器学习
光锥智能5 小时前
傅利叶发布首款开源人形机器人N1:开发者可实现完整复刻
人工智能
恒拓高科WorkPlus5 小时前
一款安全好用的企业即时通讯平台,支持统一门户
大数据·人工智能·安全