20251011_Pytorch从入门到精通

20251011_Pytorch从入门到精通

https://www.bilibili.com/video/BV1xK7fzNEtV/

讲的很不错! 就是这课太老了 复习下机器学习基础还能看 用作入门也很好 其他的略过即可

1 2

py 复制代码
import torch
from torch import autograd

x = torch.tensor(1.)
a = torch.tensor(1., requires_grad=True)
b = torch.tensor(2., requires_grad=True)
c = torch.tensor(3., requires_grad=True)

y = a**2*x + b*x +c

a.grad, b.grad, c.grad # None
grads = autograd.grad(y, [a,b,c])
grads[0], grads[1], grads[2] # 有值了

常用层:

py 复制代码
nn.Linear
nn.Conv2d
nn.LSTM

nn.ReLU
nn.Sigmoid

nn.Softmax
nn.CrossEntropyLoss
nn.MSE

3

conda安装

cuda安装(显卡驱动安装) 环境变量配置

pytorch安装

VSCode安装

4~13

梯度下降

https://spin.atomicobject.com

  • linear regression
  • logistic regression
  • classification

用激活函数 增强模型的非线性表达能力

讲的真不错!

14~15

py 复制代码
# 数据类型
a = torch.randn(2, 3)
print("打印张量类型:", a.type())

# type(a)
isinstance(a, torch.FloatTensor)

a = a.cuda()
isinstance(a, torch.cuda.FloatTensor)


b = torch.tensor(1.3)
len(b.shape) # 标量 shape为 0,size=[]

torch.FloatTensor(1) # 这个不是标量 而是一个长度为1的向量 

torch.from_numpy(data)

a.shape[0]
a.size(0)
list(a.shape)[0]

a.numel() # 元素数 多维维度数相乘
a.dim() # 

16~17

py 复制代码
# 创建tensor
a = np.ones([2,3])
torch.from_numpy(a)

torch.tensor([1,2,3]) # from list

torch.set_default_tensor_type(torch.DoubleTensor) # 默认是 torch.FloatTensor

a = torch.rand(3,3) # [0.1]之间 随机均匀初始化
torch.rand_like(a)

torch.randint(1, 10 , [3, 3]) # [1,10)之间 均匀分布

torch.randn(3,3) # 正太分布

torch.full([2,3], 1)

torch.arange(0, 10, 2) # [0,10) 等差

torch.linspace(0, 10 , steps=4) # [0,10] 等分
torch.logspace(0, -1 ,steps=10)
 
torch.ones(2,2)
torch.ones_like(a)
torch.zeros(3,3)
torch.eye(3,4) # 对角线全1

torch.randperm(10) # 0~9 随机打乱

18~19

py 复制代码
# 索引和切片
a[:,:,::2,::2]

a.index_select(2, torch.arange(8)) # 第一个参数指定 要采样的维度 第二个参数指定该维度要采样的索引

x = torch.randn(3,4)
mask = x.ge(0.5) # 大于等于0.5的位置 设为1 其余为0
torch.masked_select(x, mask) # 会把选中的值 放到一个1为向量中 如torch.Size([3])

20~33

张量操作

py 复制代码
# 维度变换
# view
a = torch.rand(4, 1, 28 ,28)
a.view(4, 28*28)
# reshape
a.reshape(4, 28*28)

# squeeze 删减维度
a.squeeze() # 挤压所有
a.squeeze(0)
# unsqueeze 增加维度
a.unsqueeze(0)
# transpose 交换维度
a.transpose(1, 3)
# t 转置
a.T
a.t()
# permute 多维度交换
a.permute(0,2,3,1)
# expand 扩展维度
a = torch.rand(1, 32, 1 ,1)
a.expand(4,32,14,-1) # -1表示不变
# repeat 扩展维度
# contiguous


# torch.all
# torch.eq

BroadCast机制

py 复制代码
[4, 3, 32, 32]
+[32, 32]
+[3, 1, 1]
+[1, 1, 1, 1]
py 复制代码
# 拼接和拆分
# Cat
a = torch.rand(4, 32, 8)
b = torch.rand(5, 32, 8)
torch.cat([a,b], dim=0) # [9 32 8]

# Stack:会创建一个新的维度
a = torch.rand(4,1, 16, 8)
b = torch.rand(4,1, 16, 8)
torch.stack([a,b], dim=2) # [4 1 2 16 8]
torch.stack([a,b], dim=0) # [2 4 1 16 8]

# Split:根据单元长度拆分
c = torch.rand(3, 4,1, 16, 8)
aa, _ = c.split([2, 1], dim=0) # [2 4 1 16 8]
aa, _, _ = c.split(1, dim=0) # [1 4 1 16 8]

# Chunk
aa, _, _ = c.chunk(3, dim=0) # [1 4 1 16 8]
py 复制代码
# 数学运算
# add/minus/multiply/divide:对应位置元素操作
a + b
torch.add(a , b)
torch.sub(a , b)
torch.mul(a , b)
torch.div(a , b)

# matmul 矩阵相乘
a @ b
torch.matmul(a, b)

a = torch.rand(4,3,28,64)
b = torch.rand(4,3,64,32)
torch.matmul(a,b) # [4,3,28,32] 高维的只取最后两维进行运算(适用BroadCast机制)

# pow
a = torch.full([2,2], 3)
a.pow(2) # 2次方
aa = a ** 2

# sqrt/rsqrt
aa.sqrt() # 平方根
aa = a ** 0.5
aa.rsqrt() # 平方根倒数

# exp、log
a = torch.exp(torch.ones(2,2)) # e的1次方矩阵 
torch.log(a) # 默认以e为底的对数计算

# round
a.floor() # 向下取整
a.ceil() # 向上取整
a.trunc() # 整数部分
a.frac() # 小数部分
a.round() # 四舍五入取整

# 其他
grad = torch.rand(2,3) * 15
grad.max()
grad.median()
grad.clamp(10) # 裁剪掉小于10的数据 相应位置赋值为10
grad.clamp(0, 10) # 常用在梯度剪裁 防止梯度弥散和梯度爆炸
py 复制代码
# 统计方法
# norm:计算范数(注意不是normalize的意思)
a = torch.full([8], 1)
b = a.view(2,4)
c = a.view(2,2,2)

a.norm(1) # L1范数 所有元素绝对值和  8
a.norm(2) # L2范数 所有元素绝对值的平方和再开方(模计算) 2.828
b.norm(1, dim=1) # 4 矩阵
b.norm(2, dim=1) # 2 矩阵
c.norm(1, dim=0) # 2 矩阵 
c.norm(2, dim=0) # 1.414 矩阵 

# mean sum
# prod:累乘
# max min 
# argmin argmax:默认会打平 可指定dim 返回的是索引 支持keepdim参数

# kthvalue topk
a.topk(3, dim=1)
a.topk(3, dim=1, largest=False) # 最小的k个
# kthvalue # 排序第k个元素


torch.eq(a,b) # 逐位置判断
torch.equal(a,b) # 判断张量是否一样

# where
# gather
torch.where(condition, x, y)
torch.gather(input, dim, index, out=None) # 查表
prob = torch.randn(4,10)
idx = prob.topk(3, dim=1)
idx = idx[1]
label = torch.arange(10) + 100
torch.gather(label.expand(4,10), dim=1, index=idx.long())

34~40

梯度:函数对所有自变量的偏微分向量

  • 向量方向 表示 函数在当前点 变化的方向
  • 向量的模 表示 函数在当前点 变化的速率

ResNet中的残差链接 可以起到 平滑超平面的作用,使得寻找极值点更容易;

影响寻找极小值的因素:参数初始值、学习率、动量(momentum,如何逃离局部极小值,就像沿着梯度下降方向运动的一个惯性)

激活函数和它的梯度:

sigmoid

  • (-inf, +inf) 压缩到=> (0, 1) 连续光滑 导数∂(1 - ∂)
  • 缺点:梯度弥散,值0或1附近很大范围 不会更新或更新很慢

ReLU:

  • Rectified Linear Unit
  • 小于0不响应 大于0时线性响应,梯度为1(不变)

Loss及其梯度

  • MSE:Mean Squared Error
  • Cross Entropy Loss:一般和Softmax激活函数一起使用
py 复制代码
x = torch.ones(1)
w = torch.full([1], 2)
w.requires_grad_()
mse = F.mse_loss(torch.ones(1), x*w)
# 方式1
torch.autograd.grad(mse, [w])
# 方式2
mse.backward()
mse.grad # 多维向量的话 可以进一步使用norm查看模的大小

41~52

感知机 MLP多层 的梯度推到(厉害了!)

求导链式法则:∂y/∂x = ∂y/∂u * ∂u/∂x

py 复制代码
# 优化问题shi'jian
def himmelblau(x):# 一个用于测试梯度下降的经典函数
    return (x[0] ** 2 + x[1] - 11) ** 2 + (x[0] + x[1] ** 2 - 7) ** 2

x = np.arange(-6, 6 , 0.1)    
y = np.arange(-6, 6 , 0.1)    
X, Y = np.meshgrid(x,y)
Z = himmelblau([X, Y])

fig = plt.figure("himmelblau")
ax = fig.gca(projection="3d")
ax.plot_surface(X,Y,Z)
ax.view_init(60, -30)
ax.set_xlabel("x")
ax.set_ylabel("y")
plt.show()


x = torch.tensor([0., 0.], requires_grad=True) # 优化的参数初始点
optimizer = torch.optim.Adam([x], lr=1e-3)
for step in range(20000):
    pred = himmelblau(x)

    optimizer.zero_grad()
    pred.backward()
    optimizer.step()

    if step % 200 == 0:
        print(step, x.tolist(), pred.item())

regression vs classification

MSE vs Cross Entropy

交叉熵损失:

  • 熵是surprise的衡量度,熵越大越稳定,熵越小,惊喜度越高;
  • 交叉熵则是衡量两个分布之间的不稳定程度(KL散度的衡量)

F.cross_entropy(logits, torch.tensor([3]))的输入是logits,内置了Softmax,这里的3是label;

讲的很好!

py 复制代码
device = torch.device("cuda:0")
tensor_data.to(device)
# 代替
tensor_data.cpu()
tensor_data.cuda()

53~59

py 复制代码
# acc计算示例
logits = torch.rand(4, 10)
pred = F.softmax(logits, dim=1)
pred_label = pred.argmax(dim=1)

logits.argmax(dim=1)

label = torch.tensor([9,3,2,4])
correct = torch.eq(pred_label, label)

correct.sum().float().item() / 4 # item() 转numpy

训练过程可视化:

  • tensorboardX
  • visdom
py 复制代码
# pip install tensorboardX
from tensorboardX import SummaryWriter

writer = SummaryWriter()
writer.add_scalar(...)
writer.add_scalars(...)

writer.add_image(...)
writer.add_text(...)
writer.add_histogram(...)

writer.close()

过拟合 vs 欠拟合

  • underfitting:模型表达能力不够
  • overfitting:模型表达能力强,拟合了噪声,导致泛化能力变差
    • 更多的数据
    • 更可是的模型规模
    • 正则化 Regularization/weight decay
    • dropout:torch.nn.Dropout(0.5) 删除50%的神经元(model的train和eval模式切换)
    • 数据增强
    • early stopping
py 复制代码
# L2-Regularization
optimizer = optim.SGD(net.parameters(), lr=learning_rate, weight_decay=0.01)

数据集的划分及作用;

py 复制代码
torch.utils.data.random_split(...)

K-fold cross-validation:

  • 合理利用train-val,k折交叉验证;
  • randomly sample 1/k as val set;

动量和学习率衰减

  • momentum
  • learning rate decay
py 复制代码
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=args.momentum weight_decay=args.weight_decay)

schedulre = ReduceLRRnPlateau(optimizer, "min")

...
schedulre.step()

Stochastic Gradient Descent:基于Batch的随机梯度下降;

60~71

卷积神经网络

  • input_channels

  • kernel_channels

  • kernel_size

  • stride

  • padding

    Input:(N, C, H, W)
    Output:(N,C,H,W)

    Hout = (H + 2 x padding[0] - dilation[0] x (kernel_size[0] - 1) - 1) / stride[0] + 1
    Wout = (W + 2 x padding[1] - dilation[1] x (kernel_size[1] - 1) - 1) / stride[1] + 1

    layer = nn.Conv2d(1, 3, kernel_size=3, stride=1, padding=0)
    layer.weight
    layer.bias

pooling池化层:最大池化 平均池化

  • nn.MaxPool2d

upsample上采样

  • F.interpolate

ReLU:conv2d batchNorm Pooling ReLU

batchNorm:特征缩放,Normalization的一种,基于Batch计算的统计值(均值和方差),完成Batch数据输入的标准差标准化,使用可优化的参数学习实际的Norm用的标准差和方差;

py 复制代码
x = torch.rand(1, 16 , 7,7)

layer = nn.BatchNorm2d(16)
out = layer(x)
# 统计的均值方差
# layer.running_mean
# layer.running_var
# 可优化的参数
layer.weight
layer.bias 

1x1的卷积的作用:维度转换;

经典卷积网模型:ResNet残差网!

py 复制代码
# 基本单元
class ResBlk(nn.Module):
    def __init__(self, ch_in, ch_out):
        self.conv1 = nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=1, padding=1)
        self.bn1 = nn.BatchNorm2d(ch_out)
        self.conv2 = nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1)
        self.bn2 = nn.BatchNorm2d(ch_out)

        self.extra = nn.Sequential()

        if ch_out != ch_in:
            # c不同 使用1x1卷积 进行对齐
            self.extra = nn.Sequential(
                nn.Conv2d(ch_in, ch_out, kernel_size=1, stride=1),
                nn.BatchNorm2d(ch_out)
            )
    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out = self.extra(x) + out
        return out

72~74

nn.Module模块:所有网络结构的父类

  • 大量基础网络结构
  • nn.Sequential() 网络结构组织容器
  • .parameters迭代器 返回模型所有参数
  • .to(device)
  • save and load
py 复制代码
device = torch.device('cuda')
net = Net()
net.to(device)

net.load_state_dict(torch.load('ckpt.mdl'))

torch.save(net.state_dict(), 'ckpt.mdl')

数据增强:data argumentation

  • 数据多样性
    • 旋转 剪裁 调色 加噪声
    • Flip翻转 Rotate RandomMove&Crop GAN
py 复制代码
# torchvision
transform = transforms.Compose([
    transforms.RandomHorizentalFlip(), # 随机 可能做也可能不做
    transforms.RandomVerticalFlip(),
    transforms.RandomRotation(15),
    transforms.RandomRotation([90, 180, 270]),
    transforms.Resize([32, 32]) # 参照中心点缩放
    transforms。RandomCrop([28, 28])
    transforms.ToTensor(), # 附带0~1
    # transforms.Normalize((0.1307,),(0.3081,)) # 标准化
])

# 叠加高斯噪声

75~94

Data

  • torchvision.datasets
  • torchvision.transforms
  • torch.utils.data.DataLoader

Model

  • torch.nn
  • torch.optim
py 复制代码
mode.eval()
with torch.no_grad():
     pass

ResNet:

py 复制代码
self.extra = nn.Sequential()
if ch_out != ch_in:
    self.extra = nn.Sequential(
        nn.Conv2d(ch_in, ch_out, kernel_size = 1, stride=2),
        nn.BatchNorm2d(ch_out)
    )

# ...
out = self.extra(x) + out
py 复制代码
# [b, 512, h, w] => [b, 512, 1, 1]
x = F.adaptive_avg_pool2d(x, [1, 1])
x = x.view(x.size(0), -1)
x = self.outlayer(x)

Embedding;

RNN:时间维度共享权值;(略)

梯度爆炸(Gradient Exploading)的解决:对梯度进行剪裁(clipping)

py 复制代码
loss = criterion(output, y)
model.zero_grad()
loss.backward()
for p in model.parameters():
    print(p.grad.norm()) # 查看参数梯度的模
    torch.nn.utils.clip_grad_norm_(p, 10)
optimizer.step()

梯度弥散(Gradient Vanishing):累乘算子导致的;

LSTM(略);

  • nn.Embedding(vocab_size, embedding_dim)
  • nn.RNN
  • nn.LSTM
  • nn.LSTMCell

Google CoLab

95~106

自定义数据集

  • 继承torch.utils.data.Dataset
    • __len__/__getitem__
py 复制代码
class Flattern(nn.Module):
    def __init__(self):
        super(Flattern, self).__init__()

    def forward(self, x):
        shape = torch.prod(torch.tensor(x.shape[1:])).item()
        return x.view(-1, shape)

def plot_image(img, label, name):
    fig = plt.figure()
    for i in range(6):
        plt.subplot(2,3, i+1)
        plt.tight_layout()
        plt.imshow(img[i][0] * 0.3081 + 0.1307, cmap="gray", interpolation="none")
        plt.title("{} : {}".format(name, label[i].item()))
        plt.xticks([])
        plt.yticks([])
    plt.show()


# random.shuffle([1,2,3])

# PIL.Image
# lambda x: Image.open(x).convert('RGB')

glob.glob是Python标准库中的文件路径匹配函数,通过通配符实现灵活的文件搜索。

‌匹配当前目录文件‌

  • glob.glob('*.txt'):返回当前目录下所有.txt文件路径列表。 ‌

‌递归搜索子目录‌

  • glob.glob('**/*.py', recursive=True):搜索所有.py文件,支持多层子目录。 ‌

‌通配符示例‌

  • *: 匹配任意文件名(如*.png匹配所有图片文件) ‌
  • ?: 匹配单个字符(如file?.txt匹配file1.txtfile2.txt) ‌
  • []: 匹配指定范围(如[0-9].log匹配数字结尾的日志文件)

便捷载入图片数据集:torchvision.datasets.ImageFolder(root, transform)

打印模型参数量:sum(map(lambda p:p.numel(), model.parameters()))

py 复制代码
for epoch in rage(epochs):
    train(train_db)

    if epoch%10 == 0:
        val_acc = evaluate(val_db)

        if val_acc is the best:
            save_ckpt()
        if out_of_patience():
            break
load_ckpt()
test_acc = evaluate(test_db)       


# model.load_state_dict(torch.load('best.mdl'))

迁移学习(Transfer learning):初始权重 复用参数 微调训练;

  • torchvision.models导入resnet18,可以这样初始化直接带权重;
py 复制代码
trained_model = resnet18(pretrained=True)
model = nn.Sequential(
    *list(trained_model.children())[:-1],
    Flatten(),
    nn.Linear(512,10)
)

x = torch.randn(2,3,224,224)
print(model(x).shape) # [2,512,1,1]

107~117

无监督学习;unsupervised learning

https://projector.tensorflow.org/

Auto-Encoders

  • denoising
  • dropout
  • adversarial(VAE )

KL散度:度量两个分布的差异,差异越小,KL散度值越小;

py 复制代码
# VAE
x = x.view(batchsz, 28* 28)
h_ = self.encoder(x)
# [b, 20] => [b, 10] x 2
mu, sigma = h_.chunk(2, dim=1)
h = mu + sigma * torch.randn_like(sigma)
# 用 mu和sigma的均值和方差 来便捷的计算h与符合正太分布的分布间 的kl散度
kld = 0.5 * torch.sum(
    torch.pow(mu, 2) + 
    torch.pow(sigma, 2) - 
    torch.log(1e-8 + torch.pow(sigma, 2)) - 1
) / np.prod(x.shape)

x = self.decoder(h)
x = x.view(batchsz, 1, 28, 28)

118~129

GAN(generative-adversarial-networks)

  • Generator
  • Discriminator:判别Generator 与Label间分布的相似性

微积分 必要学习;否则公式推导都看不懂;

Weight Clipping:约束网络的表达能力,有利于模型收敛;

Gradient Penalty

tensor_x.detach() # stop gradient

py 复制代码
# Gradient Penalty
def gradient_penalty(D, xr, xf):
    
    # param D:
    # param xr [b,2]
    # param xf [b, 2]
    t = torch.rand(batchsz, 1).cuda()# 均匀分布
    t = t.expand_as(xr) 
    mid = t * xr + (1 - t) * xf # 线性插值
    mid.requires_grad_()
    pred = D(mid)
    grads = autograd.grad(outputs=pred, inputs=mid, grad_output=torch.ones_like(pred), create_graph=True, retain_graph=True, only_inputs=True)[0]
    gp = torch.pow(grads.norm(2, dim=1) - 1, 2).mean() # 梯度2范数 和 1越接近越好
    return gp

gp = gradient_penalty(D, xr, xf.detach()) # 通过增加线性插值的梯度惩罚损失项
loss_D = lossr + lossf + 0.2 * gp # 解决kl散度恒定 loss为0 梯度不更新的问题

130~135

  • Ubuntu
    • lsb_release -a
  • anaconda
    • whereis python
    • witch python
    • source ~/.bashrc
  • Cuda Cudnn
    • 参考官网 下载cuda并安装 安装会自动安装GOU驱动;
    • nvidia-smi:驱动可用
    • nvcc -V:Cuda可用
    • gpustat
    • htop
    • Cudnn下载需要注册Nvidia(不一定要安装,如果环境已经有了)
  • Pytorch

136~150

相关推荐
沃斯堡&蓝鸟2 小时前
DAY28 元组和OS模块
python·元组与os模块
中年程序员一枚2 小时前
Nginx配置运行python的uvicorn项目
chrome·python·nginx
لا معنى له2 小时前
学习笔记:循环神经网络(RNN)
人工智能·笔记·学习·机器学习
桜吹雪2 小时前
DeepSeekV3.2模型内置Agent体验
javascript·人工智能
逆向新手2 小时前
js逆向-某省特种设备aes加密研究
javascript·爬虫·python·逆向·js
2501_945318492 小时前
2025年数字化转型:AI技能+CAIE认证夯实进阶根基
人工智能
今夕资源网2 小时前
[AI工具]Infinite Talk数字人对口型图像转视频AI工具 支持无限时长视频生成
人工智能·数字人·视频生成·ai工具·infinite talk·对口型图像转视频·无限时长
暗之星瞳2 小时前
PYTHON学习——决策树
python·学习·随机森林
咚咚王者2 小时前
人工智能之数学基础 概率论与统计:第二章 核心定理
人工智能·概率论