本周目标:
- 完成毕业论文
- 学习Bert理论+code
20240228
一. Jupyter Lab调试
1.打开jupyter Lab
- 打开Anaconda prompt
- 输入:Jupyter Lab D:\XXX\XXX(想要打开的目录)
2.jupyter Lab 快捷键
3.jupyter Lab 切换环境(Kernel)
- Anaconda prompt——>activate pytorch_gpu(环境名)——>pip install --user --ignore-installed jupyter
- 重新打开Jupyter Lab,发现环境导入成功
二. Fbprophet
1. 相关知识
1.1 epoch和batch?
- epoch:1个epoch,整个数据集在NN中前向传播和反向传播一次。
- batch:1个batch,NN接收一批训练样本进行前向传播、损失计算、反向传播和参数更新。一个数据集可以分割成多个batch。
1.2 动态调整学习率(scheduler)
from torch.optim.lr_scheduler import LambdaLR
import torch
from torch.optim import SGD
from torch.optim.lr_scheduler import LambdaLR
# 定义优化器
optimizer = SGD(model.parameters(), lr=0.1)
# 定义 Lambda 函数来动态调整学习率
lambda_func = lambda epoch: 0.95 ** epoch # 例如,每个 epoch 学习率减少 5%
# 使用 LambdaLR 来设置学习率调度器
scheduler = LambdaLR(optimizer, lr_lambda=lambda_func)
# 在训练循环中根据需要调用 scheduler.step() 来更新学习率
for epoch in range(num_epochs):
# 训练模型的代码
# 更新学习率
scheduler.step()
2. fbprophet算法细节
2.1 时序拆解
y ( t ) = g ( t ) + s ( t ) + h ( t ) y(t)=g(t)+s(t)+h(t) y(t)=g(t)+s(t)+h(t)
- 趋势项 g ( t ) g(t) g(t)
- 季节性项 s ( t ) s(t) s(t),月或周,通过标准傅里叶级数来近似。
- 节假日项 h ( t ) h(t) h(t)
三. pytorch
1. (小土堆版)
3.1 数据相关
- Dataset:提供一种方式去获取数据及其label;告诉外面总共有多少数据
- Dataloader:为后面的网络提供不同的数据形式
3.2 tensorboard报错
- 在anaconda prompt 中激活环境,再输入tensorboard --logdir=(…\logs)。(…)表示logs所在绝对位置;
- 报错:
- 解决:电脑用户名不能包含中文,更改用户名再重启即可
3.3 知识点
- __init__和 __call__的区别:
- _init_ :创建对象时,用来初始化对象的状态,不能返回任何值,只做初始化;
- _call_ :可以像函数一样被调用,返回值;
- 卷积后输出参数维度:
- 输入: ( N , C i n , H i n , W i n ) (N,C_{in},H_{in},W_{in}) (N,Cin,Hin,Win); 输出: ( N , C o u t , H o u t , W o u t ) (N,C_{out},H_{out},W_{out}) (N,Cout,Hout,Wout);
- H o u t = H i n − 2 ∗ p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] ∗ ( k e r n a l s i z e [ 0 ] − 1 ) − 1 s t r i d e [ 0 ] + 1 H_{out}=\frac{H_{in}-2*padding[0]-dilation[0]*(kernal_size[0]-1)-1}{stride[0]}+1 Hout=stride[0]Hin−2∗padding[0]−dilation[0]∗(kernalsize[0]−1)−1+1
- W o u t = W i n − 2 ∗ p a d d i n g [ 1 ] − d i l a t i o n [ 1 ] ∗ ( k e r n a l s i z e [ 1 ] − 1 ) − 1 s t r i d e [ 1 ] + 1 W_{out}=\frac{W_{in}-2*padding[1]-dilation[1]*(kernal_size[1]-1)-1}{stride[1]}+1 Wout=stride[1]Win−2∗padding[1]−dilation[1]∗(kernalsize[1]−1)−1+1
* dilation:空洞卷积
- torch.nn.functional.conv2d与torch.nn.Conv2d的区别
- torch.nn.functional.conv2d:
- 一个无状态函数,每次调用都需要输入张量和卷积核作为参数传递给它;
- 只需要进行简单的卷积操作而无需学习参数时使用。
- torch.nn.Conv2d:
- 一个有状态的类,需要创建该类的实例,并将数据传递给这个实例的forward;
- 在实例化时,它会创建可学习的卷积核参数,并在调用时自动使用这些参数进行卷积操作;
- 具有可学习的权重和偏置,适用于在神经网络中学习卷积核参数。
- 激活函数
sigmoid:
f ( x ) = 1 1 + e − x f(x)=\frac{1}{1+e^{-x}} f(x)=1+e−x1
- 适用于二分类。当 x → + ∞ x\to+\infty x→+∞时, f ( x ) → 1 f(x)\to1 f(x)→1;当 x → − ∞ x\to-\infty x→−∞时, f ( x ) → 0 f(x)\to0 f(x)→0;
- 特点:由sigmoid导数可知,当输入值过大或者过小时,前一层参数梯度接近于0,参数无法得到有效更新,梯度饱和,产生梯度消失问题;不是关于中心对称,收敛速度慢。
tanh:
- f ( x ) = e x − e − x e x + e − x f(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}} f(x)=ex+e−xex−e−x
- 值域 ( − 1 , 1 ) (-1,1) (−1,1)
- 特点:由tanh导数可知,当输入值过大或者过小时,前一层参数梯度接近于0,参数无法得到有效更新,产生梯度消失问题。
ReLU
- f ( x ) = m a x x , 0 f(x)=max{x,0} f(x)=maxx,0
- 取正操作
- 使部分输出参数为0,造成网络稀疏性,减少了参数之间依存关系,缓解过拟合的发生;梯度较大时,神经元变得无效。
- 梯度消失和梯度爆炸
梯度消失:
- 反向传播过程中,神经网络的梯度逐渐变小,最终趋近于零。
- 原因:使用的激活函数的梯度在一些区域接近于零,比如sigmoid和tanh,在极值点附近梯度接近于0,当网络层数较多时,梯度相乘,导致整体梯度趋近于零。
梯度爆炸
- 反向传播过程中,梯度逐渐变大,参数更新过大,导致网络数值不稳定,使得训练无法收敛或异常结果;
- 原因:梯度在传播过程中被放大,原因包括参数初始化不合适、激活函数选择不恰当、学习率过大等。
解决方法:使用恰当激活函数;良好的初始化策略;梯度裁剪(限制梯度大小);批归一化(输入进行归一化处理,加速收敛)。
- torch.nn.Sequential
self.model = nn.Sequential(nn.Linear(784, 128), # 输入层到隐藏层的全连接层,输入维度为 784,输出维度为 128
nn.ReLU(), # ReLU 激活函数
nn.Linear(128, 10), # 隐藏层到输出层的全连接层,输入维度为 128,输出维度为 10(分类任务中通常是类别数)
nn.Softmax(dim=1) ) # Softmax 激活函数,用于多分类问题中的输出层)`
- 构建NN的容器,允许用户按照顺利将多个层组合在一起,构成NN。
- 分类问题中的交叉熵损失
loss_cross = nn.CrossEntropyLoss()
result_loss = loss_cross(input, target)
- l o s s ( x , c l a s s t a r g e t ) = − l o g ( e x p ( x [ c l a s s t a r g e t ] ) ∑ j e x p ( x [ j ] ) ) = − x [ c l a s s t a r g e t ] + l o g ( ∑ j e x p ( x [ j ] ) ) loss(x,class_{target})=-log(\frac{exp(x[class_{target}])}{\sum_{j} exp(x[j])})=-x[class_{target}]+log(\sum_{j} exp(x[j])) loss(x,classtarget)=−log(∑jexp(x[j])exp(x[classtarget]))=−x[classtarget]+log(j∑exp(x[j]))
- 优化器
包括随机梯度下降(SGD)、Adam、RMSprop等。
optim = torch.optim.SGD(model.parameters(),lr=0.01) # 随机梯度下降优化器
...
optim.zero_grad()
# 梯度要清零,避免梯度累加。
result_loss.backward()
# 调用损失函数的反向传播,利用优化器根据求出的梯度对参数进行调整,
# 训练模型使整体loss降低。
optim.step() # 根据梯度,对网络的参数进行调优
- 学习率优化
影响模型训练速度和性能(更快收敛,避免陷入局部最优解)。
scheduler = torch.optim.lr_scheduler.StepLR(optim, step_size=5, gamma=0.1)
# 每过 step_size 更新一次优化器,更新是学习率为原来的学习率的的 0.1 倍
...
optim.step() # 根据梯度,对网络的参数进行调优
scheduler.step() # 更新学习率
- Dropout层
防止模型过拟合,随机丢弃一部分(0.2到0.5的概率)节点的输出(使其为0),防止节点之间相互依存,使模型更鲁棒。 - 利用GPU训练模型
import torch
from torch import nn, optim
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision.transforms import ToTensor
# 检查 GPU 可用性
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 加载数据集并转移到 GPU 上
train_dataset = MNIST(root='./data', train=True, transform=ToTensor(), download=True)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
# 定义模型并转移到 GPU 上
model = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 128),
nn.ReLU(),
nn.Linear(128, 10)
)
model.to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
criterion = criterion .to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练循环
for epoch in range(5): # 假设训练 5 个 epoch
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device) # 将输入数据和标签移到 GPU 上
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
print(f'Epoch [{epoch+1}/5], Loss: {loss.item()}')