Pytorch:张量常用方法与基本运算

Pytorch: 张量常用方法与基本计算

Copyright: Jingmin Wei, Pattern Recognition and Intelligent System, School of Artificial and Intelligence, Huazhong University of Science and Technology

Pytorch教程专栏链接


本教程不商用,仅供学习和参考交流使用,如需转载,请联系本人。

数学上的张量实际上就是高维矩阵(dim>=2)的意思。

但在 pytorch 中,张量表示标量,向量,矩阵。和 numpy 中的 ndarray 是一个道理,二者经常相互转换。

pytorch 统一的计算数据类型为张量(tensor)。张量的基本计算是深度学习框架的基础。

有 numpy 基础的同学,这一章除开最后部分,前面三个 part 可以快速翻阅后跳过。

导入常用库

import torch
import numpy as np
张量数据类型
# 获取数据类型
torch.tensor([1.2, 3.4]).dtype
torch.float32
# 设置张量默认类型
torch.set_default_tensor_type(torch.DoubleTensor)
# 恢复torch默认数据类型
torch.set_default_tensor_type(torch.FloatTensor)
# 获取默认数据类型
torch.get_default_dtype()
torch.float32
# 张量转为其他类型
a = torch.tensor([1.2, 3.4])
print('a.dtype:', a.dtype)
print('a.long.dtype:', a.long().dtype)
print('a.int.dtype:', a.int().dtype)
print('a.float.dtype:', a.float().dtype)
a.dtype torch.float32
a.long.dtype torch.int64
a.int.dtype torch.int32
a.float.dtype torch.float32
张量的生成
A = torch.tensor([[1.0, 1.0], [2, 2]])
A
tensor([[1., 1.],
        [2., 2.]])
# 获取张量维度
A.shape
torch.Size([2, 2])
# 获取张量的形状大小
A.size()
torch.Size([2, 2])
# 计算张量中的元素数量
A.numel()
4

dtype指定类型,requires_grad指定是否计算梯度

B = torch.tensor([[1, 2], [4, 6]], dtype=torch.float32, requires_grad=True)
B
tensor([[1., 2.],
        [4., 6.]], requires_grad=True)

只有浮点数据才能计算梯度(dtype=torch.float32)

# 计算sum(B^2)的梯度
y = B.pow(2).sum()
y.backward()
B.grad    # 求梯度
tensor([[ 2.,  4.],
        [ 8., 12.]])
创建指定形状的张量
C = torch.Tensor([1, 2, 3, 4])
C
tensor([1., 2., 3., 4.])
D = torch.Tensor(2, 3)
D
tensor([[0.0000e+00, 0.0000e+00, 8.4078e-45],
        [0.0000e+00, 1.4013e-45, 0.0000e+00]])
# 创建一个与D相同大小和类型的全1张量
torch.ones_like(D)
tensor([[1., 1., 1.],
        [1., 1., 1.]])
# 创建一个与D相同大小和类型的全0张量
torch.zeros_like(D)
tensor([[0., 0., 0.],
        [0., 0., 0.]])
# 创建一个与D相同大小和类型的随机张量
torch.rand_like(D)
tensor([[0.4752, 0.2465, 0.2338],
        [0.1713, 0.5791, 0.3344]])
# 由列表转换,创建一个类型相似尺度不同的张量
E = [[1, 2], [3, 4]]
E = D.new_tensor(E)
print(D.dtype, 'and', E.dtype)
E
torch.float32 and torch.float32

tensor([[1., 2.],
        [3., 4.]])
张量tensor与numpy转换
F = np.ones((3, 3))
Ftensor = torch.as_tensor(F)
Ftensor
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
Ftensor = torch.from_numpy(F)
Ftensor
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
Ftensor.numpy()
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])
随机数张量生成
# 指定生成随机数种子
torch.manual_seed(123)
# 服从正态(0, 1)分布的随机数
A = torch.normal(mean = 0.0, std = torch.tensor(1.0))
A
tensor(-0.1115)
# 多个随机数
# 指定每个随机数分布的标准差分别为1, 2, 3, 4
torch.manual_seed(123)
A = torch.normal(mean = 0.0, std = torch.arange(1, 5.0))
A
tensor([ 0.2093, -1.9447, -2.2651,  1.2956])
# 指定每个随机数分布的均值分别为1, 2, 3, 4,标准差分别为1, 2, 3, 4
torch.manual_seed(123)
A = torch.normal(mean = torch.arange(1, 5.0), std = torch.arange(1, 5.0))
A
tensor([1.6653, 2.7056, 5.9185, 3.8455])
# 在区间(0, 1)上生成服从均匀分布的张量
torch.manual_seed(123)
B = torch.rand(3, 4)
B
tensor([[0.2961, 0.5166, 0.2517, 0.6886],
        [0.0740, 0.8665, 0.1366, 0.1025],
        [0.1841, 0.7264, 0.3153, 0.6871]])
# 生成与其他张量尺寸相同的随机数张量
torch.manual_seed(123)
C = torch.ones(2, 3)
D = torch.rand_like(C)
D
tensor([[0.2961, 0.5166, 0.2517],
        [0.6886, 0.0740, 0.8665]])
# 生成服从标准正态分布的随机数张量
B = torch.randn(3, 3)
print(B)
B = torch.randn_like(C)
print(B)
tensor([[ 0.9447,  0.6217, -1.3501],
        [-0.1881, -2.3891, -0.4759],
        [ 1.7603,  0.6547,  0.5490]])
tensor([[ 0.3671,  0.1219,  0.6466],
        [-1.4168,  0.8429, -0.6307]])
# 将0-10的整数随机排序
torch.manual_seed(123)
torch.randperm(10)
tensor([2, 0, 8, 1, 3, 7, 4, 9, 5, 6])
其他张量创建方法
# 指定开始,结束与步长
torch.arange(start = 0, end = 10, step = 2)
tensor([0, 2, 4, 6, 8])
# 生成步长为3
B = torch.arange(start = 2, end = 10, step = 3)  
B
tensor([2, 5, 8])
# 生成固定数量为5
B = torch.linspace(start = 2, end = 10, steps = 5)  
B
tensor([ 2.,  4.,  6.,  8., 10.])
# 全1张量
C = torch.ones(3, 3)
print(C)
# 全0张量
C = torch.zeros(3, 3)
print(C)
# 单位张量
C = torch.eye(3, 3)
print(C)
# 0.25填充的张量
C = torch.full((3, 3), fill_value = 0.25)
print(C)
# 空张量
C = torch.empty(3, 3)
print(C)
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])
tensor([[0.2500, 0.2500, 0.2500],
        [0.2500, 0.2500, 0.2500],
        [0.2500, 0.2500, 0.2500]])
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
张量操作
改变张量形状
# 设置张量形状大小
A = torch.arange(12.0).reshape(3, 4)
A
tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.]])
torch.reshape(input = A, shape = (2, -1))
tensor([[ 0.,  1.,  2.,  3.,  4.,  5.],
        [ 6.,  7.,  8.,  9., 10., 11.]])
# 直接改变某张量的形状
A.resize_(2, 6)
tensor([[ 0.,  1.,  2.,  3.,  4.,  5.],
        [ 6.,  7.,  8.,  9., 10., 11.]])
# 设置为和某张量B相同的形状大小
B = torch.arange(10.0, 19.0).reshape(3, 3)
A.resize_as_(B)
print(B)
print(A)
tensor([[10., 11., 12.],
        [13., 14., 15.],
        [16., 17., 18.]])
tensor([[0., 1., 2.],
        [3., 4., 5.],
        [6., 7., 8.]])
# 在张量的指定维度上插入新的维度得到维度提升的张量
A = torch.arange(12.0).reshape(2, 6)
B = torch.unsqueeze(A, dim = 0)
B
tensor([[[ 0.,  1.,  2.,  3.,  4.,  5.],
         [ 6.,  7.,  8.,  9., 10., 11.]]])
C = B.unsqueeze(dim = 3)
C.shape
torch.Size([1, 2, 6, 1])
# 移除所有的维度为1的维度
D = torch.squeeze(C)
D.shape
torch.Size([2, 6])
# 移除指定维度为1的维度
E = torch.squeeze(C, dim=0)
E.shape
torch.Size([2, 6, 1])
A = torch.arange(3)
B = A.expand(3, -1)
B
tensor([[0, 1, 2],
        [0, 1, 2],
        [0, 1, 2]])
# 根据C的形状拓展B
C = torch.arange(6).reshape(2, 3)
B = A.expand_as(C)
B
tensor([[0, 1, 2],
        [0, 1, 2]])
# 将张量看成一个整体重复填充
D = B.repeat(1, 2, 2)
D
tensor([[[0, 1, 2, 0, 1, 2],
         [0, 1, 2, 0, 1, 2],
         [0, 1, 2, 0, 1, 2],
         [0, 1, 2, 0, 1, 2]]])
张量索引

与 numpy 中的是类似的

A = torch.arange(12).reshape(1, 3, 4)
A
tensor([[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
         [ 8,  9, 10, 11]]])
A[0]
tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]])
# 获取第0维度下矩阵的前两行元素
A[0, 0:2, :]
tensor([[0, 1, 2, 3],
        [4, 5, 6, 7]])
# 获取第0维度下的矩阵,最后一行的-4~-1列
A[0, -1, -4:-1]
tensor([ 8,  9, 10])

按条件进行筛选:

B = -A
# A > 5为ture,返回A中对应位置的值,A < 5为false,返回B中对应位置的值
torch.where(A > 5, A, B)
tensor([[[ 0, -1, -2, -3],
         [-4, -5,  6,  7],
         [ 8,  9, 10, 11]]])
# 获取A中大于5的元素
A[A>5]
tensor([ 6,  7,  8,  9, 10, 11])
# 获取矩阵张量的下三角部分
torch.tril(A, diagonal = 0)
tensor([[[ 0,  0,  0,  0],
         [ 4,  5,  0,  0],
         [ 8,  9, 10,  0]]])
torch.tril(A, diagonal = 1)
tensor([[[ 0,  1,  0,  0],
         [ 4,  5,  6,  0],
         [ 8,  9, 10, 11]]])
# 获取矩阵张量的上三角部分
torch.triu(A, diagonal = 0)
tensor([[[ 0,  1,  2,  3],
         [ 0,  5,  6,  7],
         [ 0,  0, 10, 11]]])
# 获取对角线元素
C = A.reshape(3, 4)
print(C)
print(torch.diag(C, diagonal=0))
print(torch.diag(C, diagonal=1))
tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]])
tensor([ 0,  5, 10])
tensor([ 1,  6, 11])
# 提供对角线元素生成矩阵张量
torch.diag(torch.tensor([1, 2, 3]))
tensor([[1, 0, 0],
        [0, 2, 0],
        [0, 0, 3]])
拼接和拆分
A = torch.arange(6.0).reshape(2, 3)
B = torch.linspace(0, 10, 6).reshape(2, 3)
# 在0维度上连接张量
C = torch.cat((A, B), dim = 0)
C
tensor([[ 0.,  1.,  2.],
        [ 3.,  4.,  5.],
        [ 0.,  2.,  4.],
        [ 6.,  8., 10.]])
# 在1维度上连接张量
D = torch.cat((A, B), dim = 1)
D
tensor([[ 0.,  1.,  2.,  0.,  2.,  4.],
        [ 3.,  4.,  5.,  6.,  8., 10.]])
# 在1维度上连接3个张量
E = torch.cat((A[:, 0:2], A, B), dim = 1)
E
tensor([[ 0.,  1.,  0.,  1.,  2.,  0.,  2.,  4.],
        [ 3.,  4.,  3.,  4.,  5.,  6.,  8., 10.]])
# 沿新维度连接张量
F = torch.stack((A, B), dim=0)
print(F)
print(F.shape)
tensor([[[ 0.,  1.,  2.],
         [ 3.,  4.,  5.]],

        [[ 0.,  2.,  4.],
         [ 6.,  8., 10.]]])
torch.Size([2, 2, 3])
G = torch.stack((A, B), dim=2)
print(G)
print(G.shape)
tensor([[[ 0.,  0.],
         [ 1.,  2.],
         [ 2.,  4.]],

        [[ 3.,  6.],
         [ 4.,  8.],
         [ 5., 10.]]])
torch.Size([2, 3, 2])
# 在行上分割两块
torch.chunk(E, 2, dim=0)
(tensor([[0., 1., 0., 1., 2., 0., 2., 4.]]),
 tensor([[ 3.,  4.,  3.,  4.,  5.,  6.,  8., 10.]]))
D1, D2 = torch.chunk(D, 2, dim=1)
print(D1)
print(D2)
tensor([[0., 1., 2.],
        [3., 4., 5.]])
tensor([[ 0.,  2.,  4.],
        [ 6.,  8., 10.]])
# 如果沿给定维度dim的张量大小不能被块整除,则最后一个块将最小
E1, E2, E3 = torch.chunk(E, 3, dim=1)
print(E1)
print(E2)
print(E3)
tensor([[0., 1., 0.],
        [3., 4., 3.]])
tensor([[1., 2., 0.],
        [4., 5., 6.]])
tensor([[ 2.,  4.],
        [ 8., 10.]])
# 将张量切分成块,指定每个块的大小
D1, D2, D3 = torch.split(D, [1, 2, 3], dim=1)
print(D1)
print(D2)
print(D3)
tensor([[0.],
        [3.]])
tensor([[1., 2.],
        [4., 5.]])
tensor([[ 0.,  2.,  4.],
        [ 6.,  8., 10.]])
张量的计算
比较大小

allclose: |A-B|<=atol+rtol*|B|

# 比较两个数是否接近
A = torch.tensor([10.0])
B = torch.tensor([10.1])
print(torch.allclose(A, B, rtol=1e-05, atol=1e-08, equal_nan=False))
print(torch.allclose(A, B, rtol=0.1, atol=0.01, equal_nan=False))
False
True
# 缺失值判断相近
A = torch.tensor(float('nan'))
print(torch.allclose(A, A, equal_nan = False))
print(torch.allclose(A, A, equal_nan = True))
False
True
# 计算元素是否相等
A = torch.tensor([1, 2, 3, 4, 5, 7])
B = torch.arange(1, 7)
C = torch.unsqueeze(B, dim=0)
D = torch.tensor([1, 2, 3, 4, 5, 6])
print(torch.eq(A, B))
tensor([ True,  True,  True,  True,  True, False])
# 判断两个张量是否有完全相同形状和元素
print(torch.equal(D, B))
print(torch.equal(A, C))
True
False
# 逐元素比较小于等于
print(torch.le(D, B))
# 逐元素边角小于
print(torch.lt(A, C))
tensor([True, True, True, True, True, True])
tensor([[False, False, False, False, False, False]])
# 逐元素比较不等于
print(torch.ne(A, B))
print(torch.ne(A, C))
tensor([False, False, False, False, False,  True])
tensor([[False, False, False, False, False,  True]])
# 逐元素判断是否为缺失值
torch.isnan(torch.tensor([0, 1, float('nan'), 2]))
tensor([False, False,  True, False])
基本运算
# 逐元素相乘
A = torch.arange(6.0).reshape(2, 3)
B = torch.linspace(10, 20, steps=6).reshape(2, 3)
A * B
tensor([[  0.,  12.,  28.],
        [ 48.,  72., 100.]])
# 逐元素相除
A / B
tensor([[0.0000, 0.0833, 0.1429],
        [0.1875, 0.2222, 0.2500]])
# 逐元素相加
A + B
tensor([[10., 13., 16.],
        [19., 22., 25.]])
# 逐元素相减
A - B
tensor([[-10., -11., -12.],
        [-13., -14., -15.]])
# 逐元素整除
B // A
tensor([[inf, 12.,  7.],
        [ 5.,  4.,  4.]])
# 张量的幂
print(torch.pow(A, 3))
print(A ** 3)
tensor([[  0.,   1.,   8.],
        [ 27.,  64., 125.]])
tensor([[  0.,   1.,   8.],
        [ 27.,  64., 125.]])
# 张量的指数
torch.exp(A)
tensor([[  1.0000,   2.7183,   7.3891],
        [ 20.0855,  54.5981, 148.4132]])
# 张量的对数
torch.log(A)
tensor([[  -inf, 0.0000, 0.6931],
        [1.0986, 1.3863, 1.6094]])
# 张量的平方根
print(torch.sqrt(A))
print(A ** 0.5)
tensor([[0.0000, 1.0000, 1.4142],
        [1.7321, 2.0000, 2.2361]])
tensor([[0.0000, 1.0000, 1.4142],
        [1.7321, 2.0000, 2.2361]])
# 张量平方根的倒数
print(torch.rsqrt(A))
print(1 / (A ** 0.5))
tensor([[   inf, 1.0000, 0.7071],
        [0.5774, 0.5000, 0.4472]])
tensor([[   inf, 1.0000, 0.7071],
        [0.5774, 0.5000, 0.4472]])
# 根据最大值裁剪张量
torch.clamp_max(A, 4)
tensor([[0., 1., 2.],
        [3., 4., 4.]])
# 根据最小值裁剪
torch.clamp_min(A, 3)
tensor([[3., 3., 3.],
        [3., 4., 5.]])
# 根据范围裁剪
torch.clamp(A, 2.5, 4)
tensor([[2.5000, 2.5000, 2.5000],
        [3.0000, 4.0000, 4.0000]])
# 矩阵转置
C = torch.t(A)
C
tensor([[0., 3.],
        [1., 4.],
        [2., 5.]])
# 矩阵相乘,A的行数等于C的列数
A.matmul(C)
tensor([[ 5., 14.],
        [14., 50.]])
A = torch.arange(12.0).reshape(2, 2, 3)
B = torch.arange(12.0).reshape(2, 3, 2)
AB = torch.matmul(A, B)
AB
tensor([[[ 10.,  13.],
         [ 28.,  40.]],

        [[172., 193.],
         [244., 274.]]])
# 只计算后面两个维度的乘法
print(AB[0].eq(torch.matmul(A[0], B[0])))
print(AB[1].eq(torch.matmul(A[1], B[1])))
tensor([[True, True],
        [True, True]])
tensor([[True, True],
        [True, True]])
# 矩阵的逆
C = torch.rand(3, 3)
D = torch.inverse(C)
torch.mm(C, D)
tensor([[ 1.0000e+00,  1.7502e-08, -8.7483e-08],
        [ 1.8397e-08,  1.0000e+00, -4.0170e-08],
        [-4.5937e-08,  7.6177e-08,  1.0000e+00]])
# 矩阵的迹,即对角线元素和
torch.trace(torch.arange(9.0).reshape(3, 3))
tensor(12.)
统计相关的计算
A = torch.tensor([12, 34, 25, 11, 67, 32, 29, 30, 99, 55, 23, 44])
# 最大值及其位置
print(A.max())
print(A.argmax())
# 最小值及其位置
print(A.min())
print(A.argmin())
tensor(99)
tensor(8)
tensor(11)
tensor(3)
# 二维张量的最大值和最小值
B = A.reshape(3, 4)
print(B, '\n')
# 每行的最大值及位置
print(B.max(dim=1))
print(B.argmax(dim = 1),'\n')
# 每列的最小值及位置
print(B.min(dim=0))
print(B.argmin(dim=0))
tensor([[12, 34, 25, 11],
        [67, 32, 29, 30],
        [99, 55, 23, 44]]) 

torch.return_types.max(
values=tensor([34, 67, 99]),
indices=tensor([1, 0, 0]))
tensor([1, 0, 0]) 

torch.return_types.min(
values=tensor([12, 32, 23, 11]),
indices=tensor([0, 1, 2, 0]))
tensor([0, 1, 2, 0])
# 排序,输出从小到大的结果和相应位置在原始位置的索引
torch.sort(A)
torch.return_types.sort(
values=tensor([11, 12, 23, 25, 29, 30, 32, 34, 44, 55, 67, 99]),
indices=tensor([ 3,  0, 10,  2,  6,  7,  5,  1, 11,  9,  4,  8]))
# 降序排序
torch.sort(A, descending = True)
torch.return_types.sort(
values=tensor([99, 67, 55, 44, 34, 32, 30, 29, 25, 23, 12, 11]),
indices=tensor([ 8,  4,  9, 11,  1,  5,  7,  6,  2, 10,  0,  3]))
# 2-D张量排序,以及获取相应位置在原始位置的索引
Bsort, Bsort_id = torch.sort(B)
print(Bsort)
print(Bsort_id)
print(torch.argsort(B))
tensor([[11, 12, 25, 34],
        [29, 30, 32, 67],
        [23, 44, 55, 99]])
tensor([[3, 0, 2, 1],
        [2, 3, 1, 0],
        [2, 3, 1, 0]])
tensor([[3, 0, 2, 1],
        [2, 3, 1, 0],
        [2, 3, 1, 0]])
# 获取张量前几个大的数值
torch.topk(A, 4)
torch.return_types.topk(
values=tensor([99, 67, 55, 44]),
indices=tensor([ 8,  4,  9, 11]))
# 获取2-D张量每列前几个大的数值和相应位置在原始位置的索引
Btop2, Btop2_id = torch.topk(B, 2, dim=0)
print(Btop2)
print(Btop2_id)
tensor([[99, 55, 29, 44],
        [67, 34, 25, 30]])
tensor([[2, 2, 1, 2],
        [1, 0, 0, 1]])
# 获取张量第k小的数值和位置
torch.kthvalue(A, 3)
torch.return_types.kthvalue(
values=tensor(23),
indices=tensor(10))
# 获取2-D张量第k小的数值和位置
torch.kthvalue(B, 3, dim=1)
torch.return_types.kthvalue(
values=tensor([25, 32, 55]),
indices=tensor([2, 1, 1]))
# 获取2-D张量第k小的数值和位置
Bkth, Bkth_id = torch.kthvalue(B, 3, dim=1, keepdim=True)
Bkth
tensor([[25],
        [32],
        [55]])
B = B.clone().detach()
print(B)
# 每行的平均值
print(torch.mean(B, dim=1, keepdim=True))
# 每列的平均值
print(torch.mean(B, dim=0, keepdim=True))
tensor([[12., 34., 25., 11.],
        [67., 32., 29., 30.],
        [99., 55., 23., 44.]])
tensor([[20.5000],
        [39.5000],
        [55.2500]])
tensor([[59.3333, 40.3333, 25.6667, 28.3333]])
# 每行的和
print(torch.sum(B, dim=1, keepdim=True))
# 每列的和
print(torch.sum(B, dim=0, keepdim=True))
tensor([[ 82.],
        [158.],
        [221.]])
tensor([[178., 121.,  77.,  85.]])
# 按照行计算累加和
print(torch.cumsum(B, dim=1))
# 按照列计算累加和
print(torch.cumsum(B, dim=0))
tensor([[ 12.,  46.,  71.,  82.],
        [ 67.,  99., 128., 158.],
        [ 99., 154., 177., 221.]])
tensor([[ 12.,  34.,  25.,  11.],
        [ 79.,  66.,  54.,  41.],
        [178., 121.,  77.,  85.]])
# 每行的中位数
print(torch.median(B, dim=1, keepdim=True))
# 每列的中位数
print(torch.median(B, dim=0, keepdim=True))
torch.return_types.median(
values=tensor([[12.],
        [30.],
        [44.]]),
indices=tensor([[0],
        [3],
        [3]]))
torch.return_types.median(
values=tensor([[67., 34., 25., 30.]]),
indices=tensor([[1, 0, 0, 1]]))
# 按照行计算乘积
print(torch.prod(B, dim=1, keepdim=True))
# 按照列计算乘积
print(torch.prod(B, dim=0, keepdim=True))
tensor([[ 112200.],
        [1865280.],
        [5510340.]])
tensor([[79596., 59840., 16675., 14520.]])
# 按照行计算累乘
print(torch.cumprod(B, dim=1))
# 按照列计算累乘
print(torch.cumprod(B, dim=0))
tensor([[1.2000e+01, 4.0800e+02, 1.0200e+04, 1.1220e+05],
        [6.7000e+01, 2.1440e+03, 6.2176e+04, 1.8653e+06],
        [9.9000e+01, 5.4450e+03, 1.2524e+05, 5.5103e+06]])
tensor([[1.2000e+01, 3.4000e+01, 2.5000e+01, 1.1000e+01],
        [8.0400e+02, 1.0880e+03, 7.2500e+02, 3.3000e+02],
        [7.9596e+04, 5.9840e+04, 1.6675e+04, 1.4520e+04]])
# 标准差
A = A.clone().detach().float()
torch.std(A)
tensor(25.0108)
pytorch中的自动微分

假设 y = s u m ( x 2 + 2 x + 1 ) y = sum(x^2 + 2x + 1) y=sum(x2+2x+1) , 计算 y y y x x x 上的导数

# 默认requires_grad=False,为True则指定需要计算梯度
x = torch.tensor([[1.0, 2.0], [3.0, 4.0]], requires_grad=True)
y = torch.sum(x**2 + 2*x + 1)
print(x)
print(y)
tensor([[1., 2.],
        [3., 4.]], requires_grad=True)
tensor(54., grad_fn=<SumBackward0>)
# y在x上的梯度计算框架
# 通过backward反向传播自动计算出y在x的每个元素上的导数
y.backward()
# 通过x的grad属性获取此时x的梯度信息
# grad = 2x + 2
x.grad
tensor([[ 4.,  6.],
        [ 8., 10.]])
detach()

返回一个新的tensor,从当前计算图中分离下来。但是仍指向原变量的存放位置,不同之处只是requirse_grad为false 。得到的这个tensor永远不需要计算器梯度,不具有grad。

x = torch.tensor([1., 2., 3.], requires_grad=True)
print(x.grad)
out = x.sigmoid()
print(out)

# 添加detach(), c的requires_grad为False
y = out.detach()
print(y)

# 这时候没有对y更改,所以不会影响out的backward()
out.sum().backward()
print(x.grad)
None
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward>)
tensor([0.7311, 0.8808, 0.9526])
tensor([0.1966, 0.1050, 0.0452])
计算图

它是神经网络的具体实现形式,该例中 y = w T ⋅ X , z = y + b y=w^T\cdot X,z=y+b y=wTX,z=y+b ,梯度计算遵守链式法则。

# 生成3个tensor变量,并作为叶子节点
X = torch.randn(1)
w = torch.ones(1, requires_grad=True)
b = torch.ones(1, requires_grad=True)
# 自己生成的,因此都为叶子节点
X.is_leaf, w.is_leaf, b.is_leaf 
(True, True, True)
# 是否需要求导
X.requires_grad, w.requires_grad, b.requires_grad
(False, True, True)
# 前向计算,计算生成的变量都不是叶子节点
y = w * X
z = y + b
y.is_leaf, z.is_leaf
(False, False)
# 由于叶子节点需要求导,由此生成的变量都需要求导
y.requires_grad, z.requires_grad
(True, True)
# grad_fn记录了变量进行过什么操作
y.grad_fn, z.grad_fn
(<MulBackward0 at 0x24b9c371d00>, <AddBackward0 at 0x24b9c371400>)
# 对根节点进行反向传播,计算偏导
z.backward(retain_graph=True) # # 保证计算多个梯度的输出时互不影响
w.grad, b.grad
(tensor([-0.4650]), tensor([1.]))
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值