Pytorch
一、导学
我们为什么要选择学习PyTorch?
- 活跃度:逐渐形成了完整的开发生态,资源多
- 动态图:动态图架构,且运行速度较快
- 代码简洁:易于理解,设计优雅,易于调试

二、PyTorch框架与环境搭建
1.初识Pytorch基本框架
Facebook人工智能研究员(FAIR)于2017年在GitHub上开源

PyTorch VS TensorFlow
PyTorch:
- 简洁性(编程同Python几乎一致)
- 动态计算
- visdom
- 部署不方便
TensorFlow 1.0:
- 接口复杂
- 静态图(TF2.0 Eager Execution已经引入动态图)
- Tensorboard
- 部署方便(TF serving)
静态图与动态图
- 动态图:编好程序即可执行
- 静态图:先搭建计算图,后运行;允许编译器进行优化 问题:代码编程复杂 / 调试不直观
2.环境配置
安装步骤

安装步骤‘1 --- Ubuntu 16.04
注意事项:
- 为什么选择+Ubuntu16.04
- 安装双系统,不要使用虚拟机
- 如果有条件,尽量使用高配置台式机或者高性能的笔记本(我的:GTX1080Ti+ 16G内存)
- 参考安装教程:https://www.php.cn/linux-373791.html
- 安装显卡驱动
- https://www.imooc.com/article/303674
- nvidia-smi
安装步骤2---CUDA/cuDNN
注意事项
- CUDA9.0 OR CUDA10.0 OR CUDA10.1
- cuDNN
- https://www.imooc.com/article/303675

安装步骤3 --- Python3 OR Anaconda
注意事项:
- 课程中推荐使用Python3 + pip3安装所需依赖包
- Anaconda安装源:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/
安装步骤4---PyTorch
注意事项
https://pytorch.org/get-started/locally/
GPU版本: pip3 install torch==1.5.0+cu101 torchvision==0.6.0+cu101-f https://download.pytorch.org/whl/torch_stable.html
CPU版本:
pip install torch==1.5.0+cpu torchvision==0.6.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
三、PyTorch基础
1. 机器学习中的分类与回归问题


机器学习问题的构成元素?

2.Tensor
PyTorch的基本概念

Tensor:张量,标量,向量矩阵都属于张量。
Variable(autograd):变量,机器学习中使用变量表达参数。
nn.Module:封装了解决计算机视觉任务的网络结构。
Tensor的基本概念


X=样本 W b 在未知的情况下表示为变量。

Tensor的类型

Tensor的创建

Tensor创建编程实例
import torch
# 初始化张量
a = torch.Tensor([[1, 2], [3, 4]]) # 创建一个二维张量
print(a) # 打印张量
print(a.type()) # 打印张量的数据类型
# 两行三列的张量
a = torch.Tensor(2, 3)
print(a)
print(a.type())
# 创建全1张量
a = torch.ones(2, 2)
print(a)
print(a.type())
# 创建单位矩阵
a = torch.eye(2, 2)
print(a)
print(a.type())
# 创建全0张量
a = torch.zeros(2, 2)
print(a)
print(a.type())
# 定义两行三列全为0的矩阵
b = torch.Tensor(2, 3)
b = torch.zeros_like(b)
print(b)
print(b.type())
b = torch.ones_like(b)
print(b)
print(b.type())
"""随机生成"""
a = torch.rand(2, 2)
print(a)
print(a.type())
"""正太分布"""
a = torch.normal(mean=0.0, std=torch.rand(5))
print(a)
print(a.type())
# tensor([-0.0384, 1.5809, -0.3815, -1.1301, 0.0369])
# torch.FloatTensor
a = torch.normal(mean=torch.rand(5), std=torch.rand(5))
print(a)
print(a.type())
# tensor([ 0.3320, 1.4965, 0.7779, 1.2353, -0.5314])
# torch.FloatTensor
"""均匀分布"""
a = torch.Tensor(2, 2).uniform_(-1, 1)
print(a)
print(a.type())
# tensor([[ 0.4821, -0.3142],
# [-0.6499, -0.3663]])
"""序列"""
a= torch.arange(0, 10,2)
print(a)
print(a.type())
# tensor([0, 2, 4, 6, 8])
# torch.LongTensor
"""等间隔序列"""
a=torch.linspace(2,10,4) # 拿到等间隔的n个数字
print(a)
print(a.type())
# tensor([ 2.0000, 4.6667, 7.3333, 10.0000])
# torch.FloatTensor
"""打乱顺序"""
a = torch.randperm(10)
print(a)
print(a.type())
# tensor([0, 7, 3, 2, 5, 9, 4, 6, 8, 1])
# torch.LongTensor
"""numpy"""
import numpy as np
a = np.array([[1, 2], [2, 3]])
print(a)
# [[1 2]
# [2 3]]
Tensor的属性
- 每一个Tensor有torch.dtype、torch.device、torch.layout三种属性。 dtype 数据类型
- torch.device标识了torch.Tensor对象在创建之后所存储在的设备名称。 device 存储设备
- torch.layout表示torch.Tensor内存布局的对象。
torch.tensor([1, 2, 3], dtype=torch.float32, device-torch.device(' cpu')) 1.数值 2.类型 3.存放设备
Tensor的属性 稀疏的张量
torch.sparse_coo_tensor
coo类型表示了非零元素的坐标形式 非零元素的个数越多越稀疏
indices = torch. tensor([[0, 1,1], [2, 0, 2]]) 指定非零元素的坐标 values = torch. tensor([3, 4, 5], dtype=torch. float32) x = torch. sparse_coo_tensor(i, v, [2, 4])通过稀疏可以使模型变得更简单 参数中0越多,代表模型可以简化
减少在内存中的开销。
稀疏张量编程实战
import torch
# 定义device 将Tensor放入CPU中
dev = torch.device("cpu")
# 创建张量放入device中
a = torch.tensor([2, 2], dtype=torch.float32 ,device=dev)
print(a)
# 定义一个稀疏的张量
# 不指定tensor的类型时候都是稠密的张量
i = torch.tensor([[0, 1,2], [0, 1,2]]) # 定义坐标 将对角线定义为非零元素
v = torch.tensor([1, 2,3]) # 具体的值
a = torch.sparse_coo_tensor(i,v,(4,4))
print(a)
a = torch.sparse_coo_tensor(i,v,(4,4),device= dev,dtype=torch.float32).to_dense()
print(a)
Tensor的算术运算

Tensor的算术运算 加法运算
c = a + b
C = torch.add(a,b)
a.add(b)
a.add_(b) # 区别为计算结果的同时对a的值进行修改
Tensor的算术运算 减法运算
c = a - b
C = torch.sub(a,b)
a.sub(b)
a.sub_(b)
Tensor的算术运算 乘法运算
- 哈达玛积(element wise,对应元素相乘)
c = a * b
C = torch.mul(a,b)
a.mul(b)
a.mul_(b)
Tensor的算术运算 除法运算
c = a / b
C = torch.div(a , b)
a.div(b)
a.div_(b)
Tensor的算术运算 矩阵运算
- 二维矩阵乘法运算操作包括torch.mm()、torch.matmul()、@
a = torch.ones(2, 1)
b = torch.ones(1, 2)
print(torch.mm(a, b))
print(torch.matmul(a, b))
print(a @ b)
print(a.matmul(b))
print(a.mm(b))
- 对于高维的Tensor(dim>2),定义其矩阵乘法仅在最后的两个维度上,要求前面的维度必须保持一致,就像矩阵的索引一样并且运算操只有torch.matmul()。
a = torch.ones(1, 2, 3, 4)
b = torch.ones(1, 2, 4, 3)
print(a.matmul(b))
print(torch.matmul(a, b))
Tensor的算术运算 幂运算
print(torch.pow(a, 2))
print(a.pow(2))
print(a**2)
print(a.pow(2))
print(torch.exp(a))
b = a.exp()
Tensor的算术运算一 开方运算
print(a.sqrt())
print(a.sqrt_())
print(a)
Tensor的算术运算 对数运算
print(torch.log2(a))
print(torch.logl0(a))
print(torch.log(a))
print(torch.log (a))
Tensor的算术运算编程实战
import torch
# add 加法
a = torch.randn(2, 2)
b = torch.randn(2, 2)
print(a)
print(b)
print(a + b)
print(a.add(b))
print(torch.add(a, b))
print(a.add_(b))
print(a)
# sub 减法
print("sub 减法")
print(a - b)
print(a.sub(b))
print(torch.sub(a, b))
print(a.sub_(b))
print(a)
# mul 乘法 哈达马基
print("mul 乘法")
print(a * b)
print(a.mul(b))
print(torch.mul(a, b))
print(a.mul_(b))
print(a)
# div 除法
print("div 除法")
print(a / b)
print(a.div(b))
print(torch.div(a, b))
print(a.div_(b))
print(a)
# matmul 矩阵乘法
print("matmul 矩阵乘法")
a = torch.ones(2, 1)
b = torch.zeros(1, 2)
print(a)
print(b)
print( a @ b)
print(a.matmul(b))
print(torch.matmul(a, b))
print(torch.mm(a,b))
print(a.mm(b))
# 高维度 tensor
a = torch.ones(1,2, 3, 4)
b = torch.ones(1,2, 4, 3)
print(a.matmul(b))
print(a.matmul(b).shape)
# pow 幂
print("pow 幂")
a = torch.Tensor([1,2])
print(a)
print(torch.pow(a,3))
print(a.pow(3))
print(a ** 3)
print(a.pow_(3))
print(a)
# exp 指数
print("exp 指数")
a = torch.Tensor([1,2])
print(a.type())
print(torch.exp(a))
print(torch.exp_(a))
print(a.exp_())
print(a.exp())
# log 底数
print("log 底数")
a = torch.Tensor([10,2])
print(torch.log(a))
print(torch.log_(a))
print(a.log())
print(a.log_())
# sqrt 平方根
print("sqrt 平方根")
a = torch.Tensor([10,2])
print(torch.sqrt(a))
print(torch.sqrt_(a))
print(a.sqrt())
print(a.sqrt_())
print(a)
in-place操作
- “就地”操作,即不允许使用临时变量。
- 也称为原位操作。
- x = x + y
- add_ 、sub_ 、mul_ 等等
Pytorch中的广播机制
- 广播机制:张量参数可以自动扩展为相同大小
- 广播机制需要满足两个条件:
- 每个张量至少有一个维度
- 满足右对齐
- torch.rand(2,1,1)+torch.rand(3)
import torch
a = torch.rand(2, 3)
b = torch.rand(3)
# a, 2*3
# b, 1*3
# c, 2*3
c = a + b
print(a)
print(b)
print(c)
print(c.shape)
Tensor的取整/取余运算
- floor()向下取整数
- ceil()向上取整数
- round()四舍五入>=0.5向上取整,<0.5向下取整
- trunc()裁剪,只取整数部分
- frac()只取小数部分
- %取余
import torch
a = torch.rand(2,2)
a = a * 10
print(a)
# 向下取整数
print(torch.floor(a))
# 向上取整数
print(torch.ceil(a))
# 四舍五入
print(torch.round(a))
# 裁剪,只取整数部分
print(torch.trunc(a))
# 获取小数部分
print(torch.frac(a))
# 取余
print(a % 2)
Tensor的比较运算
- torch.eq(input, other, out=None) # 按成员进行等式操作,相同返回True
- torch.equal(tensor1,tensor2)# 如果tensor1和tensor2有相同的sizeflelements, strue
- torch.ge(input, other, out=None) #input>= other
- torch.gt(input, other, out=None) #input>other
- torch.le(input, other, out=None) #input=<other
- torch.lt(input, other, out=None) #input<other
- torch.ne(input, other, out=None) # input != other 不等于
Tensor的取前k大/前k小/第k小的数值及其索引
- torch. sort(input, dimNone, descending=False, out=None) #对目标input进行排序
- torch. topk(input, k, dim=None, largest=True, sorted=True,out=None) #沿着指定维度返回最大k个数值及其索引值
- torch. kthvalue(input, k, dim=None, out=None) # 沿着指定维度返回第k个最小值及其索引值
Tensor判定是否为finite/inf/nan
- torch. isfinite(tensor) (有界)/torch. isinf(tensor)(无界) /torch. isnan(tensor)(有NULL)
- 返回一个标记元素是否为finite/inf/nan的mask 张量(True/False)。
import torch
a = torch.rand(2, 3)
b = torch.rand(2, 3)
print(a)
print(b)
# 比较运算 返回Tensor
print(torch.eq(a, b))
# 比较运算 返回布尔值
print(torch.equal(a, b))
# 大于等于
print(torch.ge(a, b))
# 大于
print(torch.gt(a, b))
# 小于等于
print(torch.le(a, b))
# 小于
print(torch.lt(a, b))
# 不等于
print(torch.ne(a, b))
#### Tensor的取前k大/前k小/第k小的数值及其索引
a = torch.tensor([[1, 4, 4, 3, 5],
[2, 3, 1, 3, 5]])
print(a.shape)
# 排序 dim=1 指定轴 descending=False 降序
print(torch.sort(a, dim=1,
descending=False))
# 排序后顺序
# values=tensor([[1, 3, 4, 4, 5],
# [1, 2, 3, 3, 5]]),
# 对应的索引值
# indices=tensor([[0, 3, 1, 2, 4],
# [2, 0, 1, 3, 4]]))
##topk 沿着指定维度返回最大k个数值及其索引值
a = torch.tensor([[2, 4, 3, 1, 5],
[2, 3, 5, 1, 4]])
print(a.shape)
# 返回前2个最大的值,在第1维度操作 降序
print(torch.topk(a, k=2, dim=1, largest=False))
# 沿着指定维度返回第k个最小值及其索引值
print(torch.kthvalue(a, k=2, dim=0))
# 沿着指定维度返回第k个最小值及其索引值
print(torch.kthvalue(a, k=2, dim=1))
a = torch.rand(2, 3)
print(a)
print(a/0)
# 有界
print(torch.isfinite(a))
print(torch.isfinite(a/0))
# 无界
print(torch.isinf(a/0))
# Null
print(torch.isnan(a))
import numpy as np
a = torch.tensor([1, 2, np.nan])
print(torch.isnan(a))
a = torch.rand(2, 3)
print(a)
print(torch.topk(a, k=2, dim=1, largest=False))
print(torch.topk(a, k=2, dim=1, largest=True))
Tensor的三角函数
torch. abs(input, out=None)
torch. acos(input, out=None)
torch. asin(input, out=None)
torch. atan(input, out=None)
torch. atan2(input, inpu2,out=None)
torch. cos(input, out=None)
torch. cosh(input, out=None)
torch. sin(input, out=None)
torch. sinh(input, out=None)
torch. tan(input, out=None)
torch. tanh(input, out=None)
import torch
a = torch.zeros(2, 3)
b = torch.cos(a)
print(a)
print(b)
tensor([[0., 0., 0.],
[0., 0., 0.]])
tensor([[1., 1., 1.],
[1., 1., 1.]])
Tensor中其他的数学函数
torch.abs()
torch.erf()
torch.erfinv()
torch.sigmoid()
torch.neg()
torch.reciprocal()
torch.rsqrt()
torch.sign()
torch.lerp()
torch.addcdiv()
torch.addcmul()
torch.cumprod()
torch.cumsum()
Tensor中统计学相关的函数
torch.mean()#返回平均值
torch.sum()#返回总和
torch.prod()#计算所有元素的积
torch.max()#返回最大值
torch.min()#返回最小值
torch.argmax()#返回最大值排序的索引值
torch.argmin()#返回最小值排序的索引值
torch.std()#返回标准差
torch.var()#返回方差
torch.median()#返回中间值
torch.mode()#返回众数值
torch.histc()#计算input的直方图
torch.bincount()#返回每个值得频数。
import torch
# 创建一个 2x2 的随机张量,元素值在 [0, 1) 之间
a = torch.rand(2, 2)
# 打印原始张量
print(a)
# 计算沿第0维(列方向)的均值,结果为每列的平均值
print(torch.mean(a, dim=0))
# 计算沿第0维(列方向)的和,结果为每列元素之和
print(torch.sum(a, dim=0))
# 计算沿第0维(列方向)的乘积,结果为每列元素相乘
print(torch.prod(a, dim=0))
# 找出沿第0维(列方向)最大值的索引(行号),返回每列最大值所在的行索引
print(torch.argmax(a, dim=0))
# 找出沿第0维(列方向)最小值的索引(行号),返回每列最小值所在的行索引
print(torch.argmin(a, dim=0))
# 计算整个张量 a 的标准差(默认无偏估计,Bessel's correction)
print(torch.std(a))
# 计算整个张量 a 的方差(默认无偏估计)
print(torch.var(a))
# 计算整个张量 a 的中位数(将所有元素排序后取中间值)
print(torch.median(a))
# 计算整个张量 a 的众数(出现频率最高的值及其频数),注意:torch.mode 返回值和索引
print(torch.mode(a))
# 重新生成一个 2x2 的随机张量,并放大到 [0, 10) 范围
a = torch.rand(2, 2) * 10
print(a)
# 使用 torch.histc 计算张量 a 的直方图:
# - 6 个分桶(bins)
# - 值域范围从 0 到 0(注意:这里范围是 [0,0],即无效范围)
# ⚠️ 注意:min=0, max=0 是错误的设置,会导致所有值被忽略或报错,应为 min < max
# 正确用法例如:torch.histc(a, bins=6, min=0, max=10)
print(torch.histc(a, 6, 0, 0))
# 生成一个 2x10 的整数张量,元素值在 [0, 10) 范围内(即 0~9)
a = torch.randint(0, 10, [2, 10])
print(a)
# 对张量 a 进行计数(bincount):
# ⚠️ 注意:torch.bincount 只能用于一维非负整数张量
# 这里 a 是二维的,直接使用会报错
# 正确做法是先展平:torch.bincount(a.flatten()) 或 a.view(-1)
print(torch.bincount(a))
# 统计某一个类别样本的个数
Tensor的torch.distributions
distributions包含可参数化的概率分布和采样函数
得分函数
强化学习中策略梯度方法的基础
pathwise derivative估计器
变分自动编码器中的重新参数化技巧
ExponentialFamily、 Bernoulli、 Categorical、 Beta、 Binomial Cauchy、 Chi2、 Dirichlet、 Exponential、 FisherSnedecor Gamma、 Geometric、 Gumbel、 HalfCauchy、 HalfNormal Independent、 Laplace、 LogNormal, LowRankMultivariateNormal、 Multinomial、 MultivariateNormal、NegativeBinomial、Normal、 OneHotCategorical、 Pareto、Poisson、 RelaxedBernoulli、 RelaxedOneHotCategorical, StudentT、 TransformedDistribution、 Uniform、 Weibull
KL Divergence 度量两种分布之间的相似性
Transforms 两种分布之间的转换
Constraint 分布约束
Tensor中的随机抽样
定义随机种子
torch.manual seed(seed)
定义随机数满足的分布
torch.normal()
import torch
# 设置随机种子为1,确保结果可复现
torch.manual_seed(1)
# 生成一个形状为 (1, 2) 的张量,作为每个输出元素的均值(mean)
# 值在 [0, 1) 之间随机生成
mean = torch.rand(1, 2)
# 生成一个形状为 (1, 2) 的张量,作为每个输出元素的标准差(standard deviation)
# 值在 [0, 1) 之间随机生成
std = torch.rand(1, 2)
# 使用 torch.normal(mean, std) 从正态分布中采样:
# - mean: 指定每个位置的均值
# - std: 指定对应位置的标准差(必须非负)
# 输出张量的形状与 mean 和 std 相同:(1, 2)
# 注意:torch.normal() 支持广播机制,但此处 shape 一致,无需广播
print(torch.normal(mean, std))
通过随机种子可以约束随机抽样,保证抽样结果一致。
Tensor中的范数运算
- 范数
- 在泛函分析中,它定义在赋范线性空间中,并满足一定的条件,即①非负性;
即①非负性;②齐次性;③三角不等式。
常被用来度量某个向量空间(或矩阵)中的每个向量的长度或大小。
0范数/1范数/2范数/p范数/核范数
torch.dist(input,other,p=2)计算p范数
torch.norm()计算2范数
import torch
# 生成两个形状为 (2, 1) 的随机张量 a 和 b,元素值在 [0, 1) 之间
a = torch.rand(2, 1)
b = torch.rand(2, 1)
# 打印 a 和 b 的值
print("a:\n", a)
print("b:\n", b)
# 计算 a 与 b 之间的 p-范数距离(广义距离)
# p=1: 曼哈顿距离(L1 距离),即 |a_i - b_i| 的绝对值之和
print("L1 距离 (p=1):", torch.dist(a, b, p=1))
# p=2: 欧几里得距离(L2 距离),即 sqrt(Σ(a_i - b_i)^2)
print("L2 距离 (p=2):", torch.dist(a, b, p=2))
# p=3: L3 距离,即 (Σ|a_i - b_i|^3)^(1/3)
print("L3 距离 (p=3):", torch.dist(a, b, p=3))
# 计算张量 a 的 p-范数(从原点到 a 的向量长度)
# 默认 p=2,即 L2 范数:sqrt(Σ(a_i)^2)
print("a 的 L2 范数 (p=2):", torch.norm(a))
# 计算 a 的 L3 范数:(Σ|a_i|^3)^(1/3)
print("a 的 L3 范数 (p=3):", torch.norm(a, p=3))
# 计算 Frobenius 范数(仅对矩阵定义,等价于所有元素的 L2 范数)
# 对于向量或标量张量,'fro' 在 torch.norm 中等价于 L2 范数
print("a 的 Frobenius 范数:", torch.norm(a, p='fro'))
作用:1.定义Loss 2. 参数约束
Tensor中的矩阵分解
常见的矩阵分解
- LU分解:将矩阵A分解成L(下三角)矩阵和U(上三角)矩阵的乘积
- QR分解:将原矩阵分解成一个正交矩阵Q和一个上三角矩阵R的乘积
- EVD分解:特征值分解
- SVD分解:奇异值分解
特征值分解
- 将矩阵分解为由其特征值和特征向量表示的矩阵之积的方法
- 特征值 VS 特征向量

PCA与特征值分解
- PCA:将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征
- PCA算法的优化目标就是:
- 降维后同一纬度的方差最大
- 不同维度之间的相关性为0
- 协方差矩阵
奇异值分解(EVD分解)

LDA与奇异值分解


EVD分解 VS SVD分解
- 矩阵方阵且满秩(可对角化)
- 矩阵分解不等于特征降维度
- 协方差矩阵描述方差和相关性
Pytorch中的奇异值分解
- torch.svd()
Tensor的裁剪运算
- 对Tensor中的元素进行范围过滤
- 常用于梯度裁剪(gradient clipping),即在发生梯度离散或者梯度爆炸时对梯度的处理
- a.clamp(2,10)
import torch
# 生成一个形状为 (2, 2) 的随机张量,元素值在 [0, 1) 之间,然后乘以 10,得到范围 [0, 10) 的浮点数
a = torch.rand(2, 2) * 10
# 打印原始张量(值在 0 到 10 之间)
print("原始张量 a:")
print(a)
# 使用 clamp 函数对张量 a 进行“裁剪”(限幅):
# - 所有小于 2 的元素被替换为 2
# - 所有大于 5 的元素被替换为 5
# - 在 [2, 5] 范围内的元素保持不变
# clamp(min, max) 实现的是“硬阈值”操作
a = a.clamp(2, 5)
# 打印裁剪后的张量,所有值都被限制在 [2, 5] 区间内
print("\n裁剪后(clamp(2, 5))的张量 a:")
print(a)
3-21
