PyTorch深度学习框架 的基础知识
目录
1.pyTorch检查是否安装成功
2.PyTorch的张量tensor 基础创建方式(三种)
2.2用列表创建tensor
2.2使用元组创建 tensor
2.3使用ndarray创建创建 tensor
2.4 快速创建tensor的常用方法
3.pyTorch中的张量tensor的常用属性
4. tensor中的基础数据类型
5.张量tensor的基础运算
6.改变tensor的形状
7.tensor聚合操作
8.tensor索引
9.矩阵乘法
10.tensor张量的自动微分(重点)
11.复合函数求导
1.pyTorch检查是否安装成功
import torch
torch.cuda_version #查看cuda版本
'12.1'
torch.cuda.is_available() #检测cuda是否能使用
True
#打印cuda设备,即显卡名字
torch.cuda.get_device_name() #检测可以使用的gpu
'NVIDIA GeForce GTX 1060'
torch.cuda.get_device_name(0)
'NVIDIA GeForce GTX 1060'
2.PyTorch的张量tensor 基础创建方式(三种)
PyTorch与TensorFlow中的张量一样,都叫做tensor,
tensor和numpy里的ndarray是一个意思,不同点:tensor可以在GPU上加速计算创建的tensor返回值都是一个一维数组
import torch
import numpy as np
2.2用列表创建tensor
torch.tensor([6,2])
tensor([6, 2])
torch.tensor([6,2], dtype = torch.int32) #指定数据类型
tensor([6, 2], dtype=torch.int32)
2.2使用元组创建 tensor
torch.tensor((6,2))
tensor([6, 2])
2.3使用ndarray创建创建 tensor
torch.tensor(np.array([6,2]))
tensor([6, 2], dtype=torch.int32)
np.array([6, 2])
array([6, 2])
2.4 快速创建tensor的常用方法
快速创建tensor的常用方法, 和numpy中的routines的方法一样
例如:ones, zeros, full, eye, random.randn, random.normal, arange....
#创建一个0到1之间的随机数组成的tensor
torch.rand((2, 3))
tensor([[0.6626, 0.1513, 0.6840], [0.1509, 0.0196, 0.4638]])
torch.rand(2, 3)
tensor([[0.6335, 0.3162, 0.9308], [0.5522, 0.2508, 0.6437]])
#创建一个两行三列的标准正态分布,均值为0
torch.randn(2,3)
tensor([[ 0.0580, 1.5962, -0.6440],
[ 0.9074, 2.2482, -0.3065]])
torch.randn((2,3))
tensor([[ 0.3305, 0.7139, -0.0988],
[-0.1087, 0.1576, -0.9505]])
torch.ones(2,3)
tensor([[1., 1., 1.],
[1., 1., 1.]])
torch.zeros(2,3)
tensor([[0., 0., 0.],
[0., 0., 0.]])
3.pyTorch中的张量tensor的常用属性
#tensor最常用的属性shape
x = torch.zeros(2, 3, 4) #创建 两行 三列 四个 的数据
display(x)
x.shape #查看tensor的shape
tensor([[[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]], [[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]])Out[18]:
torch.Size([2, 3, 4])
#也可以使用.size()方法查看tensor的shape
x.size() #等同于x.shape
torch.Size([2, 3, 4])
#.size()中可以传入shape的索引,来获取某个维度的数值
x.size(0)
2
4. tensor中的基础数据类型
- 32位浮点数:torch.float32
- 64位浮点数:torch.float64
- 32位整数:torch.int32
- 16位整数:torch.int16
- 64位整数:torch.int64
- 32位整数:torch.int32 表示能够存储2^31次方,前两位是储存 数据的正负 符号的
#TensorFlow没有直接用tensor()方法创建tensor
#TensorFlow是被谷歌收购的, 2019年之前:TensorFlow框架的人较多; 2019年:pyTorch框架使用者超过前者;2019年之后:二者使用人数交替
#TensorFlow提供了常量constant、变量Variable的创建方式,两者有区分,
#pyTorch与Python更接近一点,创建的都是变量
#tensor可以与ndarray进行转化
n = np.random.randn(2, 3) #创建两行三列的ndarray数据 (随机正态分布数据)
n
array([[ 1.32327941, -0.64770757, 0.77327725], [ 1.64796259, -0.56311173, -0.26610105]])
a = torch.from_numpy(n) #将ndarray转化为tensor数据
a
tensor([[ 1.3233, -0.6477, 0.7733], [ 1.6480, -0.5631, -0.2661]], dtype=torch.float64)
#将tensor转化为ndarray a.numpy()
array([[ 1.32327941, -0.64770757, 0.77327725], [ 1.64796259, -0.56311173, -0.26610105]])
5.张量tensor的基础运算
#tensor的基础运算规则与ndarray很像
#和单个数字运算
#和单个数字运算
t = torch.ones(2,3)
t
tensor([[1., 1., 1.], [1., 1., 1.]])
t + 3 #torch矩阵数据中每个数据都+3
tensor([[4., 4., 4.], [4., 4., 4.]])
torch.add(t, 3) #上一行代码与这一行代码一致
tensor([[4., 4., 4.], [4., 4., 4.]])
t1 = torch.ones(2,3)
t1
display(t, t1)
tensor([[1., 1., 1.], [1., 1., 1.]])tensor([[1., 1., 1.], [1., 1., 1.]])
# 前提条件:形状shape必须相同。 对应位置的元素相加, element-wise操作 残差网络的+ 就是element-wise相加
t1 + t
tensor([[2., 2., 2.], [2., 2., 2.]])
#有输出返回值的不会改变原始值
t1.add(t) #上一行代码与这一行代码一致
tensor([[2., 2., 2.], [2., 2., 2.]])
t1
tensor([[1., 1., 1.], [1., 1., 1.]])
## 如果想改变原始值. pytorch中带下划线_的操作会改变原始值.
t1.add_(t)
tensor([[2., 2., 2.], [2., 2., 2.]])
t1 #t1被改变了原始值
tensor([[2., 2., 2.], [2., 2., 2.]])
t
tensor([[1., 1., 1.], [1., 1., 1.]])
#tensor张量矩阵求逆矩阵
torch.inverse()
6.改变tensor的形状
t
tensor([[1., 1., 1.], [1., 1., 1.]])
t.reshape(3, 2)
tensor([[1., 1.], [1., 1.], [1., 1.]])
t.view(3, 2)
tensor([[1., 1.], [1., 1.], [1., 1.]])
7.tensor聚合操作
t
tensor([[1., 1., 1.], [1., 1., 1.]])
t.mean()
tensor(1.)
t.sum()
tensor(6.)
# 指定维度进行聚合, 不写维度, 默认会把所有维度聚合掉.
# dim(dimension)相当于axis
x = t.sum(dim = 1)
x
tensor([3., 3.])
# 一个数字叫做scalars(标量), 带中括号的数据较做向量
# item是专门用来取出tensor中的标量的值
x1 = t.sum()
x1.item()
6.0
8.tensor索引
a = torch.randn(3, 4)
a
tensor([[ 1.7353, -1.0547, -1.7341, 1.3166], [ 0.7245, 0.5138, -0.2932, -0.4307], [ 0.5311, 0.8725, -0.9907, 1.3229]])
a[0]
tensor([ 1.7353, -1.0547, -1.7341, 1.3166])
# tensor的切片和索引操作和ndarray是完全一样.
a[0, :3]
tensor([ 1.7353, -1.0547, -1.7341])
#索引例子:索引获取图像色彩数据
a1 = torch.rand(32, 224, 224, 3)
a1.shape
torch.Size([32, 224, 224, 3])
a1
tensor([[[[0.8823, 0.3511, 0.6211], [0.0789, 0.2923, 0.8930], [0.0243, 0.2673, 0.8913], ..., [0.0356, 0.0213, 0.5672], [0.1055, 0.2254, 0.1522], [0.4944, 0.3775, 0.3731]], [[0.7983, 0.8197, 0.2490], [0.4326, 0.1828, 0.0983], [0.5347, 0.8690, 0.1389], ..., [0.1191, 0.3159, 0.0347], [0.3169, 0.5657, 0.0882], [0.8005, 0.5183, 0.2349]]]])
# 取出图片数据
a1[0, :, :, 0].shape
torch.Size([224, 224])
9.矩阵乘法
# 矩阵乘法
s1 = torch.randn(2, 3)
s2 = torch.randn(3, 5)
torch.matmul(s1, s2)
tensor([[ 2.7162, 1.9755, 0.2429, -0.9626, 0.3315], [ 1.2003, 0.8906, 0.0307, -0.6301, 0.1311]])
# @也是矩阵点乘的快捷写法
s1 @ s2
tensor([[ 2.7162, 1.9755, 0.2429, -0.9626, 0.3315], [ 1.2003, 0.8906, 0.0307, -0.6301, 0.1311]])
b1 = torch.rand(5)
b2 = torch.rand(5)
print(b1, b2)
#pytorch中的dot是向量的乘法(内积),必须是一维向量,
b1.dot(b2)
tensor([0.6465, 0.1404, 0.3810, 0.0404, 0.6999]) tensor([0.7392, 0.1680, 0.3585, 0.5969, 0.0146])Out[56]:
tensor(0.6724)
(b1 * b2).sum()
tensor(0.6724)
10.tensor张量的自动微分(重点)
无关知识点随记:jupyter notebook中查看调用封装函数的参数 快捷键 shift+tab
# tensor张量的自动微分 就是 自动求导.
# 在要求导的变量定义中加上requires_grad=True表示要追踪这个变量的导数
x = torch.ones(2,3, requires_grad = True) #默认requires_grad=False,不能自动求导
x
tensor([[1., 1., 1.], [1., 1., 1.]], requires_grad=True)
y = x + 2
#requires_grad查看变量是否能够求导
x.requires_grad
True
y
tensor([[3., 3., 3.], [3., 3., 3.]], grad_fn=<AddBackward0>)
y.requires_grad #查看变量y是否能够求导
True
# 导数必须由标量输出创建. 即要求的最后结果, 必须是一个标量. 不能是向量.
# 导数的定义中要求是对某一点(x, y)求导.
z = y.mean() #必须使用聚合运算使数据变成一个数(标量)
z
tensor(3., grad_fn=<MeanBackward0>)
# 只有执行完backward之后, 所有requires_grad=True的变量的导数都会被自动求出.
z.backward()
x.grad #求出x关于y函数的导数
tensor([[0.1667, 0.1667, 0.1667], [0.1667, 0.1667, 0.1667]])
11.复合函数求导
#假设复合函数 f = 3*y*y
y
tensor([[3., 3., 3.], [3., 3., 3.]], grad_fn=<AddBackward0>)
f = 3*y*y
f
tensor([[27., 27., 27.], [27., 27., 27.]], grad_fn=<MulBackward0>)
f.requires_grad #查看变量f是否能求导
True
out = f.mean() #只能在某一点求导,将f的tensor矩阵进行 聚合运算的 mean (求平均值) 变成一个标量(一个数叫标量)
out
tensor(27., grad_fn=<MeanBackward0>)
#grad_fn=<MeanBackward0> 记录求导的全部过程
out.backward() #反向传播
y.requires_grad #查看变量y是否能求导
True
# 求非叶子节点的tensor的导数, 必须使用retain_grad, 不然会报警告.
y.retain_grad
<function Tensor.retain_grad> #版本显示问题?有待纠正!!!
# 如果不需要求导, 可以把代码包在torch.no_grad()中, 表示临时不求导
x.requires_grad
True
(x**2).requires_grad #返回值是True表示能求导
True
# 通过with torch.no_grad() 暂时不对x求导
with torch.no_grad():
print((x**2).requires_grad)#返回值是False表示不能求导
False
x.requires_grad
True #上述 通过with torch.no_grad() 暂时不对x求导 不改变X原始求导的 原属性
#detach() 剥离, 从tensor原数据中剥离出来,返回一个新的tensor (新的tensor默认为requires_grad=False)
x.detach()
tensor([[1., 1., 1.], [1., 1., 1.]])
y = x.detach()
y.requires_grad
False ##不能求导
y = x.detach() ** 2 + 2
y.requires_grad
False ##变量y不能求导
# 除了在定义变量的时候指定requires_grad,也可以通过requires_grad_()方法修改变量的requires_grad属性
d = torch.randn(2, 2)
d = d * 3 +2
print(d.requires_grad)
False
# 加了下划线, 会直接修改原始数据.
d.requires_grad_(True)
tensor([[ 3.0569, 4.0794], [-0.5465, 1.1926]], requires_grad=True)
# 加了下划线, 会直接修改原始数据.
d.requires_grad_(True)
print(d.requires_grad)
True
短期记忆变成长期记忆
艾宾浩斯记忆曲线
第一遍理解为主
总结, 提问. 重复复习.
看得多, 练得少.一般都是用pyTorch中已经封装好的API去写一些算法和模型