一些 pytorch 学习笔记

张量 Tensor

初始化

  1. 构造一个 5x3 矩阵,不初始化 (empty)
x = torch.empty(5,3)
print(x)
# 教程的输出
tensor(1.00000e-04 *
       [[-0.0000,  0.0000,  1.5135],
        [ 0.0000,  0.0000,  0.0000],
        [ 0.0000,  0.0000,  0.0000],
        [ 0.0000,  0.0000,  0.0000],
        [ 0.0000,  0.0000,  0.0000]])
# 自己测试的输出
tensor([[9.6429e-39, 9.2755e-39, 9.1837e-39],
        [9.3674e-39, 1.0745e-38, 1.0653e-38],
        [9.5510e-39, 1.0561e-38, 1.0194e-38],
        [1.1112e-38, 1.0561e-38, 9.9184e-39],
        [1.0653e-38, 4.1327e-39, 1.0194e-38]])
  1. 构造一个随机初始化的矩阵 (rand)
x = torch.rand(5,3)
print(x)
# 输出
tensor([[ 0.6291,  0.2581,  0.6414],
        [ 0.9739,  0.8243,  0.2276],
        [ 0.4184,  0.1815,  0.5131],
        [ 0.5533,  0.5440,  0.0718],
        [ 0.2908,  0.1850,  0.5297]])
  1. 构造一个全为 0 的矩阵,且指定数据类型为 long (zeros)

    ps. 如果想令填充数字为 1,则使用 torch.ones

x = torch.zeros(5,3,dtype=torch.long)
print(x)
# 输出
tensor([[ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0]])
  1. 构建一个张量,直接使用数据(tensor)
x = torch.tensor([5.5, 3])
print(x)
# 输出
tensor([ 5.5000,  3.0000])
  1. 用正态分布的随机数创建张量

    例如以下代码创建一个形状为(3, 4)的张量

    其中每个元素都从均值为 0,标准差为 1 的标准正态分布中随机取样

torch.randn(3, 4)   // 3,4是形状
# 输出
tensor([[ 0.4114,  0.3654, -0.3493,  0.2873],
        [-0.1792,  1.5127,  1.5238,  1.1396],
        [-0.2556, -0.2120, -0.1249, -0.4377]])
# 如果想产生可导的随机数
a = torch.randn(size=(),requires_grad=True)
  1. 基于已存在的 tensor 创建 tensor
# 返回一个与size大小相同的用1填充的张量。可选择改变数据类型
x = x.new_ones(5, 3, dtype=torch.double)
# 仅保留size
x = torch.randn_like(x, dtype=torch.float)
  1. 创建行向量(arange)
x = torch.arange(3)
# 输出
tensor([0, 1, 2])
  1. 获取维度信息(size)
x.size()
# 输出
torch.Size([5, 3])
  1. 访问元素形状和元素总数(shape & numel)
x.shape   # torch.Size([12])
x.numel()   # 12
  1. 访问张量长度(len)
len(x)
  1. 改变张量形状(reshape)
X = x.reshape(3, 4)  # 变成3行4列

运算

  1. 加法

    # +
    print(x+y)
    # torch.add()
    print(torch.add(x,y))
    # 提供一个输出tensor作为参数
    result = torch.empty(5, 3)
    torch.add(x, y, out=result)
    print(result)
    # in-place 直接在y上相加
    y.add_(x) # 任何使张量发生变化的操作都有前缀"_"
    
  2. 减乘除方指

    x-y # 减
    x*y # 乘
    x/y # 除
    x**y # 方
    torch.exp(x) # 指数
  3. 连接多个张量

    x = [[ 0.,  1.,  2.,  3.],
         [ 4.,  5.,  6.,  7.],
         [ 8.,  9., 10., 11.]]
    y = [[ 2.,  1.,  4.,  3.],
         [ 1.,  2.,  3.,  4.],
         [ 4.,  3.,  2.,  1.]]
    
    • 按行( dim=0 )
    torch.cat((x,y),dim=0)
    # 输出
    tensor([[ 0.,  1.,  2.,  3.],
            [ 4.,  5.,  6.,  7.],
            [ 8.,  9., 10., 11.],
            [ 2.,  1.,  4.,  3.],
            [ 1.,  2.,  3.,  4.],
            [ 4.,  3.,  2.,  1.]])
    • 按列( dim=1 )
    torch.cat((x,y),dim=1)
    # 输出
    tensor([[ 0.,  1.,  2.,  3.,  2.,  1.,  4.,  3.],
            [ 4.,  5.,  6.,  7.,  1.,  2.,  3.,  4.],
            [ 8.,  9., 10., 11.,  4.,  3.,  2.,  1.]])
  4. 通过逻辑运算符构建二元张量

    X == Y
    # 输出
    tensor([[False, True, False, True],
            [False, False, False, False],
            [False, False, False, False]])
  5. 对张量中所有元素求和

    会产生只有一个元素的张量

    x.sum()
    # 输出
    tensor(66.)
  6. 指定在某维度上求和

    • 不保留维度

      eg. [2, 5, 4]

      如果 axis=0,则把第 1 个去掉,也就是去掉 2,变成[5, 4]

      如果 axis=1,则把第 2 个去掉,也就是去掉 5,变成[2, 4]

      B = A.sum(axis=0)
    • 保留维度( keepdims=True )

      eg. [2, 5, 4]

      如果 axis=0,则把第 1 个变成 1,也就是变成[1, 5, 4]

      如果 axis=1,则把第 2 个变成 1,也就是变成[2, 1, 4]

      B = A.sum(axis=0, keepdims=True)
    • 在维度上累积求和( cumsum(axis=x) )

      A = torch.arange(16).reshape(4,4).cumsum(axis=0)
      # 输出 在列上累积求和
      tensor([[ 0,  1,  2,  3],
              [ 4,  6,  8, 10],
              [12, 15, 18, 21],
              [24, 28, 32, 36]])
  7. 求平均值

    A.mean()
    A.sum()/A.numel()
    # 也可指定维度求和
    A.mean(axis=0)
    A.sum(axis=0)/A.numel(axis=0)
  8. 形状不同的张量相加 - 广播机制

    例如相加的是以下两个张量:
    tensor([[0],
            [1],
            [2]]),
    tensor([[0,1]])
    那么相加的时候,第一个会复制两列,第二个会复制三行
    tensor([[0, 0],
            [1, 1],
            [2, 2]])
    tensor([[0, 1],
            [0, 1],
            [0, 1]])
    然后再相加,变成
    tensor([[0, 1],
            [1, 2],
            [2, 3]])

操作元素

索引

  1. 访问特定元素

    x[0,1]
  2. 访问一行

    x[1,:]
  3. 访问一列

    x[:,1]
  4. 访问子区域

    x[1:3,1:] # 取 1-2 行 x 1-3 列
  5. 每隔一定间隔选取元素

    x[::3,::3]  # 从0开始,每隔3行取该行元素,每隔2列取该列元素
  6. 选取最后一个元素(如果是二维数组,则选取最后一行)

    x[-1]

修改

通过指定索引,将元素写入矩阵

x[1,2] = 9

为多个元素赋相同的值,只需要索引所有元素,然后为它们赋值

x[0:2,:] = 12

执行原地操作

执行一些操作可能会为新结果分配内存

如果想让变量在操作前后内存位置保持一致:

1. X += Y
2. X[:] = X + Y

转换为 NumPy 张量

A = X.numpy()

将大小为 1 的张量转换为 python 标量

a.item()
float(a)
int(a)

线性代数

标量

由只有一个元素的张量表示

x = torch.tensor([3.0])

创建 mxn 矩阵

A = torch.arange(20).reshape(5, 4)
// 输出
tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11],
        [12, 13, 14, 15],
        [16, 17, 18, 19]])

矩阵转置

A.T

点积

  1. 通过执行按元素乘法,再进行求和

    torch.sum(x*y)
  2. torch.dot(x, y)

    只能应用于一维张量

    torch.dot(x, y)

矩阵向量积 Ax

torch.mv(A, x)

矩阵乘法

torch.mm(A, B)
// 或
A*B

范数

  1. L2范数 || a ||

    矩阵元素平方和的平方根

    torch.norm(u)
  2. L1范数

    矩阵元素绝对值之和

    torch.abs(u).sum()