Datawhale AI夏令营(AI+生命科学)深度学习-Task1学习笔记

赛题解析

        1、赛题背景

        本次比赛聚焦于通过机器学习技术,利用化学修饰后的siRNA序列来预测RNA干扰(RNAi)机制下对靶基因(target gene)的沉默效率,这一指标与药物实际疗效直接相关。RNAi是生物体内天然存在的一种基因表达调控机制,通过抑制靶基因的表达来实现降低目标蛋白量的目的,这一机制一般可通过siRNA实现。

        目前开源的数据库中,以RNA主干序列(裸序列)为主,缺少相应的化学修饰数据。而本赛题特别关注了化学修饰对siRNA序列功能的影响,化学修饰对siRNA的毒性、体内稳定性、靶向效果、药效等具有重大影响,在实际药物设计中至关重要。

        本赛题的研究成果将可以直接用于优化siRNA药物在医学研究和临床应用中的效率和安全性。此外通过建立对应预测模型,可以加速新型siRNA药物的虚拟筛选,促进个性化医疗的实现。

        2、数据集介绍

(1)train_data.csv

        train_data.csv的每行为一条训练记录,包含数据记录的id、siRNA裸序列、相应的siRNA修饰序列、目标mRNA序列、siRNA浓度、细胞系、转染方法等实验室条件以及对应的实验室测量的mRNA Remaining值等总计19个字段。其中mRNA Remaining值为我们模型的训练目标,其余18个字段的全部或部分可以作为模型的输入特征。

(2)vocab.csv

        3、评价指标

        4、提交格式

Baseline代码及解析

        1、导入库

#%pip install pandas
#%pip install rich
#%pip install torch
#如果是在魔搭平台上运行不需要以上三个环境的配置,在本地运行则需要添加以上三个依赖库
import os  # 文件操作
import torch  # 深度学习框架
import random  # 随机数生成
import numpy as np  # 数值计算
import pandas as pd  # 数据处理

import torch.nn as nn  # 神经网络模块
import torch.optim as optim  # 优化器模块

from tqdm import tqdm  # 进度条显示
from rich import print  # 美化打印输出
from collections import Counter  # 计数器工具

from torch.utils.data import Dataset, DataLoader  # 数据集和数据加载器
from sklearn.model_selection import train_test_split  # 数据集划分
from sklearn.metrics import precision_score, recall_score, mean_absolute_error  # 模型评估指标

# 这些库包括了文件操作、深度学习、数据处理、模型评估等必要的工具。

def set_random_seed(seed):
    # 设置NumPy的随机种子
    np.random.seed(seed)
    # 设置Python内置的随机数生成器的种子
    random.seed(seed)
    # 设置PyTorch的随机种子
    torch.manual_seed(seed)
    # 设置CUDA的随机种子
    torch.cuda.manual_seed(seed)
    # 设置所有CUDA设备的随机种子
    torch.cuda.manual_seed_all(seed)
    # 确保每次卷积算法选择都是确定的,避免了由于不同的算法选择而导致的结果不一致性
    torch.backends.cudnn.deterministic = True
    # 关闭CuDNN自动优化功能,确保结果可复现
    # 因为启用此功能时,CuDNN 可能会根据硬件条件选择最快的算法,但这可能会导致结果的微小差异
    torch.backends.cudnn.benchmark = False

        2、 基因组分词器类

        该类用于将基因组序列分割成固定长度的n-gram

class GenomicTokenizer:

(1)__init__ 方法

def __init__(self, ngram=5, stride=2):
    self.ngram = ngram
    self.stride = stride
  • ngram:表示分词的长度,默认为5,即 n-gram 中的 n。
  • stride:表示步幅,默认为2,决定了每次移动多少个字符来生成下一个 n-gram。

(2)tokenize 方法 

def tokenize(self, t):
    t = t.upper()
    if self.ngram == 1:
        toks = list(t)
    else:
        toks = [t[i:i+self.ngram] for i in range(0, len(t), self.stride) if len(t[i:i+self.ngram]) == self.ngram]
    
    if len(toks[-1]) < self.ngram:
        toks = toks[:-1]
    
    return toks
  • tokenize 方法接收一个字符串 t 作为输入,将其转换为大写(.upper() 方法)以保证大小写一致性。
  • 如果 self.ngram 等于 1,直接将输入序列 t 拆分为单个字符,存储在列表 toks 中。否则,按照步幅 self.stride 对输入序列 t 进行 n-gram 分词:
    • 使用列表推导式 [t[i:i+self.ngram] for i in range(0, len(t), self.stride) if len(t[i:i+self.ngram]) == self.ngram],从序列中提取长度为 self.ngram 的子串。
    • 这里的条件 if len(t[i:i+self.ngram]) == self.ngram 确保生成的子串长度为 self.ngram,避免了因为序列末尾不足 self.ngram 而导致的不完整分词。
  • 最后,检查最后一个分词的长度是否小于 self.ngram,如果是,则移除最后一个分词,以确保输出的所有分词长度一致。
  • 返回分词结果 toks

         3、基因组词汇类

        该类用于创建一个词汇表,用于将基因组片段映射成索引 

class GenomicVocab:

(1)__init__ 方法

def __init__(self, itos):
    self.itos = itos
    self.stoi = {v: k for k, v in enumerate(self.itos)}
  • itos 是一个列表,包含词汇表中的所有 token。
  • self.stoi 是一个字典,将词汇表中的 token 映射到它们的索引位置,即从词汇到索引的映射。

(2)create 类方法 

@classmethod
def create(cls, tokens, max_vocab, min_freq):
    freq = Counter(tokens)
    itos = ['<pad>'] + [o for o, c in freq.most_common(max_vocab - 1) if c >= min_freq]
    return cls(itos)
  • 参数说明:
    • tokens:输入的 token 列表,通常是经过分词后的结果。
    • max_vocab:词汇表的最大大小,即词汇表中最多包含多少个 token。
    • min_freq:最小频率,只保留出现频率大于等于 min_freq 的 token。
  • freq = Counter(tokens):使用 Counter 类统计 tokens 列表中每个 token 的出现次数。
  • itos = ['<pad>'] + [o for o, c in freq.most_common(max_vocab - 1) if c >= min_freq]
    • 构建词汇表 itos,将出现频率大于等于 min_freq 的 token 加入词汇表中。
    • <pad> 是一个特殊 token,通常用于填充序列长度,确保所有序列等长。
  • return cls(itos):返回一个 GenomicVocab 类的实例,使用 itos 初始化词汇表对象。

         4、siRNA数据集

         该类用于加载siRNA数据,并将序列数据转换为模型可以处理的格式

class SiRNADataset(Dataset):

(1)__init__ 方法

def __init__(self, df, columns, vocab, tokenizer, max_len, is_test=False):
    self.df = df  # 传入的数据框,包含基因序列和目标值
    self.columns = columns  # 包含序列的列名,用于从数据框中选择特定的列
    self.vocab = vocab  # 词汇表对象,用于将序列 token 化并编码为索引
    self.tokenizer = tokenizer  # 分词器对象,用于将序列分词
    self.max_len = max_len  # 最大序列长度,所有序列将被填充或截断到这个长度
    self.is_test = is_test  # 布尔值,指示是否是测试集,决定是否返回目标值

(2)__len__ 方法 

def __len__(self):
    return len(self.df)
  • __len__ 方法返回数据集的长度,即数据框 df 的行数 

(3)__getitem__ 方法

def __getitem__(self, idx):
    row = self.df.iloc[idx]  # 获取第idx行数据
    
    seqs = [self.tokenize_and_encode(row[col]) for col in self.columns]
    if self.is_test:
        return seqs
    else:
        target = torch.tensor(row['mRNA_remaining_pct'], dtype=torch.float)
        return seqs, target
  • seqs = [self.tokenize_and_encode(row[col]) for col in self.columns]:对于每一个列名 colcolumns 中,调用 tokenize_and_encode 方法处理序列,并将结果存储在 seqs 列表中。
  • 如果 self.is_testTrue:在测试集模式下,仅返回编码后的序列 seqs;否则(非测试集模式):
    • 获取目标值 target,将其转换为 torch.tensor 类型,并指定数据类型为 torch.float
    • 返回编码后的序列 seqs 和目标值 target

 (4)tokenize_and_encode 方法

def tokenize_and_encode(self, seq):
    if ' ' in seq:  # 修改过的序列
        tokens = seq.split()  # 按空格分词
    else:  # 常规序列
        tokens = self.tokenizer.tokenize(seq)  # 使用分词器分词
    
    encoded = [self.vocab.stoi.get(token, 0) for token in tokens]  # 将token转换为索引
    padded = encoded + [0] * (self.max_len - len(encoded))  # 将序列填充到最大长度
    return torch.tensor(padded[:self.max_len], dtype=torch.long)  # 返回张量格式的序列
  • tokenize_and_encode 方法接收一个字符串 seq,根据字符串中是否包含空格判断序列是否已经分词过。
  • 如果包含空格,则使用 split() 方法分割序列为 token;否则,调用 tokenizertokenize 方法进行分词。
  • 将分词后的 token 转换为索引,未知 token 使用索引 0,即 <pad>
  • 将编码后的序列填充(如果需要)到最大长度 max_len
  • 返回一个 torch.tensor 类型的序列,数据类型为 torch.long(表示整数类型)

         5、siRNA Model

        这是一个基于GRU的神经网络模型,用于处理siRNA序列

class SiRNAModel(nn.Module):

(1)__init__ 方法

def __init__(self, vocab_size, embed_dim=200, hidden_dim=256, n_layers=3, dropout=0.5):
    super(SiRNAModel, self).__init__()
    
    self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
    self.gru = nn.GRU(embed_dim, hidden_dim, n_layers, bidirectional=True, batch_first=True, dropout=dropout)
    self.fc = nn.Linear(hidden_dim * 4, 1)
    self.dropout = nn.Dropout(dropout)
  • vocab_size:词汇表的大小,即词汇表中 token 的数量。
  • embed_dim:嵌入层的维度,即每个 token 被嵌入为多少维的向量。
  • hidden_dim:GRU 层的隐藏单元数量。
  • n_layers:GRU 层的层数。
  • dropout:Dropout 层的丢弃概率。
  • self.embedding:嵌入层,将输入的 token 序列转换为稠密的嵌入向量。
  • self.gru:GRU 循环神经网络层,处理嵌入向量序列。
  • self.fc:全连接层,将 GRU 输出的特征映射到最终的输出维度(这里是一个标量,因为只预测一个值)。
  • self.dropout:Dropout 层,用于在训练过程中随机丢弃部分神经元,防止过拟合。

(2)forward 方法 

def forward(self, x):
    embedded = [self.embedding(seq) for seq in x]
    outputs = []
    
    for embed in embedded:
        x, _ = self.gru(embed)
        x = self.dropout(x[:, -1, :])
        outputs.append(x)
    
    x = torch.cat(outputs, dim=1)
    x = self.fc(x)
    return x.squeeze()
  • forward 方法定义了数据在模型中的前向传播过程。
  • x 是一个列表,每个元素代表一个输入序列(通常是经过编码的索引序列)。
  • self.embedding(seq) 将每个输入序列 seq 转换为嵌入向量。
  • self.gru(embed) 将嵌入向量传入 GRU 层,返回 GRU 输出和最终状态。
  • self.dropout(x[:, -1, :]) 对 GRU 输出的最后一个时间步的隐藏状态进行 Dropout 处理。
  • output.appends(x)表示将处理后的输出添加到 outputs 列表中。
  • 使用 torch.cat(outputs, dim=1) 将所有序列的输出在维度 1 上进行拼接。
  • 将拼接后的结果传入全连接层 self.fc,得到最终的输出。
  • return x.squeeze() 返回模型的预测结果,使用 squeeze() 方法去除输出张量中的多余维度(例如,如果输出是 (batch_size, 1),则返回 (batch_size,))。

         6、评估指标计算函数

        该函数用于计算模型的各项评估指标,包括精确度、召回率、F1值和评分。

def calculate_metrics(y_true, y_pred, threshold=30):

(1)平均绝对误差(MAE)计算

    mae = np.mean(np.abs(y_true - y_pred))
  • 使用 NumPy 计算预测值 y_pred 和真实值 y_true 的平均绝对误差。

 (2)二进制分类转换

    y_true_binary = (y_true < threshold).astype(int)
    y_pred_binary = (y_pred < threshold).astype(int)
  • 将真实值 y_true 和预测值 y_pred 转换为二进制分类,根据阈值 threshold,低于阈值为1,高于或等于阈值为0。

 (3)范围内样本的平均绝对误差计算

    mask = (y_pred >= 0) & (y_pred <= threshold)
    range_mae = mean_absolute_error(y_true[mask], y_pred[mask]) if mask.sum() > 0 else 100
  • 创建一个掩码 mask,用于筛选预测值在 0 和 threshold 之间的样本。
  • 计算在这个范围内的预测值和真实值的平均绝对误差 range_mae。如果没有符合条件的样本,将 range_mae 设为 100。

 (4)精确度、召回率和F1得分计算

    precision = precision_score(y_true_binary, y_pred_binary, average='binary')
    recall = recall_score(y_true_binary, y_pred_binary, average='binary')
    f1 = 2 * precision * recall / (precision + recall)
  • 使用 precision_scorerecall_score 函数计算二进制分类的精确度、召回率和 F1 得分。

 (5)综合评分计算

    score = (1 - mae / 100) * 0.5 + (1 - range_mae / 100) * f1 * 0.5
  • 计算综合评分 score,结合平均绝对误差的改进(越小越好)和范围内样本的平均绝对误差(越小越好),以及 F1 分数(越大越好)。

 (6)返回结果

    return score

        7、模型评估函数

         该函数用于在测试集上评估模型性能

def evaluate_model(model, test_loader, device='cuda'):

(1)设置模型为评估模式和初始化空列表

    model.eval()  # 设置模型为评估模式,这会关闭具有批量标准化和dropout等功能的训练模式
    predictions = []  # 初始化预测结果列表
    targets = []  # 初始化目标值列表

 (2)禁用梯度计算并遍历数据

    with torch.no_grad(): # 禁用梯度计算,以减少内存消耗和加快计算速度
        for inputs, target in test_loader: # 遍历 test_loader 中的每个批次
            inputs = [x.to(device) for x in inputs]  # 将输入数据移动到指定设备上
            outputs = model(inputs)  # 获取模型的输出
            predictions.extend(outputs.cpu().numpy())  # 将预测结果从GPU移到CPU并转换为 NumPy 数组,然后添加到predictions列表
            targets.extend(target.numpy())  # 将目标值转换为numpy数组,并添加到targets列表

(3)计算评估指标并打印测试得分

    y_pred = np.array(predictions)  # 将预测结果转换为NumPy数组
    y_test = np.array(targets)  # 将目标值转换为NumPy数组
    
    score = calculate_metrics(y_test, y_pred)  # 调用calculate_metrics函数计算评估指标
    print(f"Test Score: {score:.4f}")  # 打印测试得分,保留四位小数

         8、模型训练函数

        该函数用于训练模型,并在每一个epoch后评估模型的性能,保存最佳模型。

def train_model(model, train_loader, val_loader, criterion, optimizer, num_epochs=50, device='cuda', output_dir: str=""):

(1)初始化变量

    model.to(device) # 将定义的模型移动到指定的设备上
    best_score = -float('inf')  # 初始化最佳得分为负无穷,确保第一个模型的得分能够超过这个值
    best_model = None  # 初始化最佳模型为None

 (2)训练循环

    for epoch in range(num_epochs): # 外层循环控制训练的轮数,共 num_epochs 轮
        model.train()  # 设置模型为训练模式
        train_loss = 0  # 初始化训练损失
        for inputs, targets in tqdm(train_loader, desc=f'Epoch {epoch+1}/{num_epochs}'): # 使用 tqdm 迭代器来显示训练进度条,train_loader 包含了训练数据的批次
            inputs = [x.to(device) for x in inputs]  # 将输入移动到设备
            targets = targets.to(device)  # 将目标值移动到设备
            
            optimizer.zero_grad()  # 使用优化器 optimizer 清空梯度
            outputs = model(inputs)  # 前向传播
            loss = criterion(outputs, targets)  # 计算损失
            loss.backward()  # 反向传播
            optimizer.step()  # 更新参数
            
            train_loss += loss.item()  # 累加训练损失
        
        model.eval()  # 设置模型为评估模式
        val_loss = 0  # 初始化验证损失
        val_preds = []
        val_targets = []

        with torch.no_grad():
            for inputs, targets in val_loader: # val_loader 包含了验证数据的批次
                inputs = [x.to(device) for x in inputs]  # 将输入移动到设备
                targets = targets.to(device)  # 将目标值移动到设备
                outputs = model(inputs)  # 前向传播
                loss = criterion(outputs, targets)  # 计算损失
                val_loss += loss.item()  # 累加验证损失
                val_preds.extend(outputs.cpu().numpy())  # 将模型在验证集上的预测结果 outputs 转移到 CPU 并转换为 NumPy 数组,添加到 val_preds 列表中,收集预测值
                val_targets.extend(targets.cpu().numpy())  # 将验证集的目标值 targets 转移到 CPU 并转换为 NumPy 数组,添加到 val_targets 列表中,收集目标值
        
        train_loss /= len(train_loader)  # 计算平均训练损失
        val_loss /= len(val_loader)  # 计算平均验证损失
        
        val_preds = np.array(val_preds)
        val_targets = np.array(val_targets)
        score = calculate_metrics(val_targets, val_preds)  # 计算验证集上的得分
        
        # 打印当前轮次的训练损失、验证损失、学习率以及验证集的评分 score
        print(f'Epoch {epoch+1}/{num_epochs}')
        print(f'Train Loss: {train_loss:.4f}, Val Loss: {val_loss:.4f}')
        print(f'Learning Rate: {optimizer.param_groups[0]["lr"]:.6f}')
        print(f'Validation Score: {score:.4f}')

        if score > best_score:
            best_score = score  # 更新最佳得分
            best_model = model.state_dict().copy()  # 更新最佳模型
            torch.save(model.state_dict(), os.path.join(output_dir, "best.pt".format(epoch)))  # 保存最佳模型
            print(f'New best model found with score: {best_score:.4f}') # 打印出找到新的最佳模型并显示其得分

 (3)返回最佳模型

    return best_model

        9、训练主程序 

(1)设置参数和环境

# 设置参数
bs = 64    # 批次大小
epochs = 50    # 训练的迭代次数
lr = 0.001    # 学习率
seed = 42    # 随机种子
output_dir = "output/models"    # 模型保存路径

# 选择设备
device = 'cuda' if torch.cuda.is_available() else 'cpu'

# 设置随机种子以确保结果可重复
set_random_seed(seed)

# 创建输出目录
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

(2)加载和预处理数据

# 加载数据
train_data = pd.read_csv('train_data.csv')
# 指定需要处理的列
columns = ['siRNA_antisense_seq', 'modified_siRNA_antisense_seq_list']
# 删除包含空值的行,确保数据的完整性
train_data.dropna(subset=columns + ['mRNA_remaining_pct'], inplace=True)
# 将数据分为训练集和验证集
train_data, val_data = train_test_split(train_data, test_size=0.1, random_state=42)

 (3)创建分词器和词汇表

# 创建分词器
tokenizer = GenomicTokenizer(ngram=3, stride=3)

# 创建词汇表
all_tokens = []
for col in columns:
    for seq in train_data[col]:
        if ' ' in seq:  # 修改过的序列
            all_tokens.extend(seq.split())
        else:
            all_tokens.extend(tokenizer.tokenize(seq))
vocab = GenomicVocab.create(all_tokens, max_vocab=10000, min_freq=1)
  • 根据训练集中指定列 columns 的序列数据,通过分词器 tokenizer 将序列转换为 tokens,然后创建词汇表 vocab
  • GenomicVocab.create 方法基于 tokens 统计每个 token 的频率,并根据指定的最大词汇量 max_vocab 和最小频率 min_freq 创建词汇表

 (4)创建数据集和数据加载器

# 找到最大序列长度
max_len = max(max(len(seq.split()) if ' ' in seq else len(tokenizer.tokenize(seq)) 
                    for seq in train_data[col]) for col in columns)

# 创建数据集
train_dataset = SiRNADataset(train_data, columns, vocab, tokenizer, max_len)
val_dataset = SiRNADataset(val_data, columns, vocab, tokenizer, max_len)

# 创建数据加载器
train_loader = DataLoader(train_dataset, batch_size=bs, shuffle=True) # 使用 PyTorch 的 DataLoader 类创建训练集和验证集的数据加载器,指定批次大小 bs,并对训练集进行随机打乱(shuffle)
val_loader = DataLoader(val_dataset, batch_size=bs)

(5)初始化模型、损失函数和优化器,并开始训练

# 初始化模型
model = SiRNAModel(len(vocab.itos))
criterion = nn.MSELoss() # 使用均方误差损失函数 nn.MSELoss() 作为损失函数

# 初始化优化器
optimizer = optim.Adam(model.parameters(), lr=lr) # 使用 Adam 优化器 optim.Adam,传入模型的参数和学习率 lr

# 训练模型
best_model = train_model(model, train_loader, val_loader, criterion, optimizer, epochs, device, output_dir=output_dir)

         10、测试程序

(1)设置输出目录和加载测试数据

output_dir = "result"
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

test_data = pd.read_csv('sample_submission.csv')
columns = ['siRNA_antisense_seq', 'modified_siRNA_antisense_seq_list']
test_data.dropna(subset=columns, inplace=True)
  • output_dir 设置输出目录为 "result",如果目录不存在则创建。
  • 使用 Pandas 加载测试数据集,文件名为 'sample_submission.csv'。
  • 删除测试数据中包含空值的行,确保数据的完整性

 (2)创建分词器和词汇表

tokenizer = GenomicTokenizer(ngram=3, stride=3)

all_tokens = []
for col in columns:
    for seq in test_data[col]:
        if ' ' in seq:  # 修改过的序列
            all_tokens.extend(seq.split())
        else:
            all_tokens.extend(tokenizer.tokenize(seq))
            
vocab = GenomicVocab.create(all_tokens, max_vocab=10000, min_freq=1)

(3)确定最大序列长度和创建测试数据集

max_len = max(max(len(seq.split()) if ' ' in seq else len(tokenizer.tokenize(seq)) 
                for seq in test_data[col]) for col in columns)

test_dataset = SiRNADataset(test_data, columns, vocab, tokenizer, max_len, is_test=True)
  • 计算测试数据集中所有序列的最大长度 max_len,用于保证输入模型的序列长度一致。
  • 使用自定义的 SiRNADataset 类创建测试数据集 test_dataset,设置 is_test=True 表示在测试模式下。

(4)创建数据加载器和初始化模型

test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

model = SiRNAModel(len(vocab.itos))
model.load_state_dict(best_model)  # 加载之前训练得到的最佳模型权重
model.to(device=device)
model.eval()  # 切换到评估模式,确保模型不使用 Dropout 等特定于训练模式的功能

 (5)进行预测并保存结果

preds = []
with torch.no_grad():
    for inputs in tqdm(test_loader):
        inputs = [x.to(device) for x in inputs]
        outputs = model(inputs)
        preds.extend(outputs.cpu().numpy())

test_data["mRNA_remaining_pct"] = preds
df = pd.DataFrame(test_data)

output_csv = os.path.join(output_dir, "submission.csv")
print(f"submission.csv 保存在 {output_csv}")
df.to_csv(output_csv, index=False)

必备概念入门

        1、循环神经网络(RNN)

(1)卷积神经网络(CNN)

        卷积神经网络(CNN)最擅长的就是图片的处理。它受到人类视觉神经系统的启发。CNN 有2大特点:

  1. 能够有效的将大数据量的图片降维成小数据量
  2. 能够有效的保留图片特征,符合图片处理的原则

        目前 CNN 已经得到了广泛的应用,比如:人脸识别、自动驾驶、美图秀秀、安防等很多领域。

典型的 CNN 由3个部分构成:

  1. 卷积层
  2. 池化层
  3. 全连接层

如果简单来描述的话:

        卷积层负责提取图像中的局部特征;池化层用来大幅降低参数量级(降维);全连接层类似传统神经网络的部分,用来输出想要的结果。


更多关于卷积神经网络的知识可以见卷积神经网络 – CNNicon-default.png?t=N7T8https://easyai.tech/ai-definition/cnn/

(2)反向传输算法(BP算法)

        ‌BP算法,也称为反向传播算法,是一种在神经网络中广泛使用的训练算法。它基于梯度下降法,通过反向传播误差来更新神经网络的权重,从而最小化网络输出与实际输出之间的误差。BP算法的主要特点是:

  • 监督学习:BP算法是一种监督学习算法,它依赖于训练数据中的输入和目标输出。网络通过调整其权重来最小化预测输出与目标输出之间的差异。

  • 多层网络:BP算法特别适用于具有多个隐藏层的神经网络,这些隐藏层允许网络学习更复杂的映射关系。

  • 梯度下降法:通过计算损失函数关于权重的梯度,BP算法能够确定权重调整的方向,以逐步减小预测误差。

        此外,BP算法也存在一些局限性,如训练时间可能较长、可能陷入局部最小值、以及在训练过程中可能会遇到学习率选择、初始化权重等问题。尽管如此,BP算法因其强大的学习和适应能力,在机器学习和人工智能领域中仍然是一个核心算法。‌


更多关于反向传播算法的原理和推导可以见 BP算法总结icon-default.png?t=N7T8https://www.cnblogs.com/NGC3603/p/15802653.html

(3)RNN的基本原理和结构

         传统神经网络的结构比较简单:输入层 – 隐藏层 – 输出层。如下图所示:

        RNN 跟传统神经网络最大的区别在于每次都会将前一次的输出结果,带到下一次的隐藏层中,一起训练。如下图所示:

        下面我们以一个句子来作为例子进行说明RNN是如何工作的:

①假如需要判断用户的说话意图(问天气、问时间、设置闹钟…),用户说了一句“what time is it?”我们需要先对这句话进行分词

②然后按照顺序输入 RNN ,我们先将 “what”作为 RNN 的输入,得到输出「01」

③然后,我们按照顺序,将“time”输入到 RNN 网络,得到输出「02」

        这个过程中我们可以观察看到,输入 “time” 的时候,前面 “what” 的输出也产生了影响(隐藏层中有一半是黑色的)。

④以此类推,前面所有的输入都对未来的输出产生了影响

⑤当我们判断意图的时候,只需要最后一层的输出「05」


引用自循环神经网络 – Recurrent Neural Network | RNN

(4)基于RNN产生的各种变种算法

         RNN 作为一种能够处理序列数据的神经网络模型,其经典变体模型有以下几种:

  1. GRU(Gated Recurrent Unit):GRU 是一种与 LSTM 类似的 RNN 变体模型,它只引入了两个门控机制(更新门、重置门),可以在一定程度上解决梯度消失和梯度爆炸问题,同时具有更少的参数。
  2. LSTM(Long Short-Term Memory):LSTM 是一种特殊的 RNN,它通过引入三个门控机制(输入门、遗忘门、输出门)来控制信息的流动,从而解决了传统 RNN 在处理长序列数据时出现的梯度消失或梯度爆炸问题。
  3. Bi-RNN(Bidirectional Recurrent Neural Network):Bi-RNN 是一种能够同时考虑过去和未来的信息的 RNN 变体模型,它由两个RNN模块组成,一个是正向RNN,另一个是反向RNN,最终输出是正向和反向RNN输出的拼接。
  4. Deep RNN(Deep Recurrent Neural Network):Deep RNN是一种增加多个循环层来实现深度学习的RNN变体模型,它能够更好地捕捉序列数据中的长期依赖关系。
  5. Attention-Based RNN:Attention-Based RNN 是一种基于注意力机制的RNN变体模型,它通过引入注意力机制来对序列中的不同部分进行加权,从而能够更好地捕捉序列数据中的重要信息。

更多相关资料可以参考以下文章:

【机器学习】详解 GRU

【机器学习】详解 LSTM

动手学深度学习(四十二)——双向循环神经网络(bi-RNN)

动手学深度学习(四十一)——深度循环神经网络(Deep-RNN)

论文笔记:【Attention-Based RNN】

(5)RNN的应用场景

①语言建模和文本生成:RNN可以用来建立语言模型,预测句子中下一个单词的概率分布,从而生成连贯的文本序列。这在机器翻译、对话系统和文本生成任务中特别有用。

②情感分析:通过分析文本序列中的情感信息,RNN可以帮助判断一段文本是积极的、消极的还是中性的。这在社交媒体监控、产品评论分析等方面有应用。

③机器翻译:RNN可以作为序列到序列(Seq2Seq)模型的基础,实现将一个语言的句子翻译成另一种语言的句子。它能够处理变长序列输入和输出,非常适合翻译任务。

④时间序列预测:RNN能够捕捉时间序列数据中的长期依赖关系,因此被广泛应用于股票价格预测、天气预测、交通流量预测等领域。

⑤音乐生成:通过学习音符或音乐片段的序列规律,RNN可以生成新的音乐作品,或者作曲家的风格相似的音乐。

⑥手写识别:RNN可以处理手写笔迹数据,识别手写文字,例如手写数字识别、签名验证等。

⑦视频分析:在视频序列分析中,RNN可以用于动作识别、视频描述生成等任务,通过学习视频帧之间的时间依赖关系,提取视频内容的语义信息。

        2、PyTorch框架

        PyTorch 是一个开源的机器学习框架,由 Facebook 的人工智能研究团队开发并维护。它提供了强大的张量计算(tensor computation)功能,支持动态计算图,这使得在模型训练过程中可以实时地改变神经网络的结构、参数和计算过程。

(1)动态计算图

        PyTorch 使用动态计算图,与 TensorFlow 的静态计算图相比,这意味着计算图在运行时根据代码的实际执行情况动态生成。这使得调试更为直观,并且更易于理解和编写复杂的模型。

(2)Pythonic

        PyTorch 设计上更符合 Pythonic 风格,语法简洁清晰,易于学习和使用,对于从事 Python 开发的研究人员和工程师来说,上手难度较低。

(3)易于调试

        由于动态计算图的特性,调试 PyTorch 模型相对更为直观。可以使用 Python 的调试工具直接检查模型结构和中间变量的值。

(4)丰富的库支持

        PyTorch 生态系统非常丰富,包括了众多的工具库和扩展,例如 TorchVision(用于计算机视觉)、TorchText(用于文本处理)、TorchAudio(用于音频处理)等,这些库大大加速了开发过程。

(5)GPU加速支持

        PyTorch 可以直接在 GPU 上运行,通过使用 CUDA 加速计算,大幅提升了深度学习模型的训练和推断速度。

(6)社区支持

        作为一个开源项目,PyTorch 拥有庞大的用户社区和开发者社区,提供了丰富的文档、教程和技术支持,使得用户可以快速解决问题和分享经验。


更多有关与PyTorch框架的包结构模块等内容可以见PyTorch深度学习——框架简介icon-default.png?t=N7T8https://blog.csdn.net/weixin_72324806/article/details/137266156


hahaha都看到这里了,要是觉得有用的话就辛苦动动小手点个赞吧!

  • 14
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pluses

喜欢就给颗糖果吧╰(*°▽°*

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值