深度学习(二):数据操作

1 创建Tensor(张量)

  深度学习中,数据的操作很频繁。在《动手学深度学习》中,将使用torch.Tensor作为存储和变换数据的主要工具。
  Tensor与Numpy相比,主要优势在于:与Numpy功能类似,并提供GPU计算和自动求梯度等更丰富的功能。
  关于:什么是Tensor的介绍?

1.1 初始化

  1)torch.empty:创建给定大小的Tensor

import torch
x = torch.empty(4)#创建1*4的一维Tensor
y = torch.empty(4, 5)#创建4*5的二维Tensor
y = torch.empty([4, 5])
y = torch.empty(size=(4, 5))
y = torch.empty([4, 5], dtype=torch.int)#指定初始值类型
z = torch.empty(4, 5, 6)#创建4*5*6的三维Tensor

  x的结果如下:

tensor([0.0000e+00, 0.0000e+00, 1.2115e+11, 4.5911e-41])

  2)其他创建方式如下表(只列出二维Tensor的创建):

函数 用法示例 功能
rand(size, dtype) torch.rand(4, 5) 初始值为均匀分布的随机数
randn(size, dtype) torch.randn(4, 5) 初始值为标准正态分布的随机数
normal(mean, std, size) torch.normal(mean=10, std=2, size(4, 5)) 指定平均值、标准差和大小
zeros(size, dtype) torch.zeros(4, 5) 初始值为0
eye(size, dtype) torch.eye(4, 5) 对角线为1
tensor(list) torch.tensor([1, 2]) 根据值创建
arange(s, e, step) torch.arange(1, 10, 3) 类似于numpy.arange()
linspace(s, e, step) torch.linspace(1, 10, 3) 将区间[1, 10]均匀分成3部分
randperm(m) torch.randperm(10) 随机排列

1.2 属性获取

  1)size()或者shape:获取Tensor大小

x = torch.zeros(4, 5)
m, n = x.size()#m, n = x.shape
x_size = x.size()

  需要注意的是x.size()返回的是一个tuple,支持所有tuple的操作

2 基本操作

2.1 算术操作

  以下面代码中的x, y为例:

x = torch.rand(4, 5)
y = torch.randn(4, 5)

  加法操作:
  1)x + y
  2)torch.add(x, y)
  3)y.add_(x)
  其他操作如x*b、x/b、x%b、x.均与numpy类似

  常用的线性函数如下:

函数 使用示例 功能
trace(diagonal) x.trace()或者torch.trace(x) 主对角线元素之和
diag(diagonal) x.diag()或者torch.diag(x) 主对角线元素
triu(diagonal) x.triu(diagonal=1)或者torch.triu(diagonal=1) 矩阵的上三角,可指定偏移量
tril(diagonal) x.tril()或者torch.tril(x) 矩阵的下三角
mm() x.mm(y)或者torch.mm(x, y) 矩阵乘法
bmm() torch.bmm(x, y), x, y必须为3维 batchd的矩阵乘法
t() x.t()或者torch.t(x) 矩阵转置
dot() x.dot(y)或者torch.dot(x, y) 内积
inverse() x.inverse()或者torch.inverse(x) 矩阵求逆
svd() x.svd()或者torch.svd(x) 奇异值分解

2.2索引操作

  Tensor的索引操作与numpy中一致,需要注意的是索引出来的结果与原数据共享内存,即修改一个,另一个也会跟着改变。示例如下:

x = torch.rand(4, 5)
print(x[i, :])#输出给定行
print(x[:, j])#输出给定列
print(x[i, 0:-1:2])#输出给定行-->第0个元素到第-1个元素之间-->按照2为间隔取值的元素

  一些高级选择函数如下:

函数 使用示例 功能
index_select(input, dim, index) torch.index_select(x, 0, torch.tensor([0, 2])) 在给定维度:0上选取给定索引:[0, 2]的元素
masked_select(input, mask) torch.masked_select(x, x>0) 返回一维Tensor:选取>0的元素
non_zero(input) torch.non_zero(x) 返回非零元素的下标

2.3 改变形状

  用view()改变Tensor的形状:

x = torch.rand(4, 5)
y = x.clone().view(20)#变为一维,用clone()可以避免x被改变
y = x.clone().view(-1, 10)#变为指定大小,-1表示的维度可以根据其他维度推算
y = x.clone().view(10, -1)

  另一个常用的函数是item(),可以将一个标量Tensor转换为一个Python Number:

x = torch.Tensor([10])
print(x, x.item())

  运行结果如下:

tensor([10.]) 10.0

2.4 广播机制

  当两个形状不同的Tensor按元素运算时,会触发广播机制:先复制元素使这两个Tensor形状相同后在按元素运算,例如:

import torch

def test():
    x = torch.arange(1, 3).view(1, 2)
    y = torch.arange(1, 4).view(3, 1)
    z = torch.add(x, y)
    print(x)
    print(y)
    print(z)

if __name__ == '__main__':
    test()

  输出如下:

tensor([[1, 2]])
tensor([[1],
        [2],
        [3]])
tensor([[2, 3],
        [3, 4],
        [4, 5]])

2.5 运算的内存开销

  索引、view()不会开辟新内存,但是类似于y = x + y这样的运算却会,例子如下:
  1)开辟新内存:

import torch

def test():
    x = torch.arange(1, 3)
    y = torch.arange(2, 4)
    id_before = id(y)
    y = y + x
    print(id(y) == id_before)#False

if __name__ == '__main__':
    test()

  2)不开辟新内存:

import torch

def test():
    x = torch.arange(1, 3)
    y = torch.arange(2, 4)
    id_before = id(y)
    y[:] = y + x#或者:torch.add(x, y, out=y)
    print(id(y) == id_before)#True

if __name__ == '__main__':
    test()

2.6 Tensor与Numpy转换

  Tensor与Numpy数组的转换需要用到numpy()和from_numpy(),需要注意的是:这两个函数所产生的Tensor和Numpy中的数组共享相同的内存,故改变其中一个另一个也会改变

  转换示例如下:

import torch
import numpy as np

def test():
    x = torch.arange(1, 3)
    a = np.arange(2, 4)
    y = x.numpy()
    b = torch.from_numpy(a)
    print(x, y)
    print(a, b)

if __name__ == '__main__':
    test()

  输出如下:

tensor([1, 2]) [1 2]
[2 3] tensor([2, 3], dtype=torch.int32)

2.7 Tensor ON GPU

  用方法to可以将Tensor在GPU和CPU之间相互移动,例子如下:

import torch

def test():
    torch.cuda._initialized = True#初始化
    x = torch.arange(2, 4, device='cuda')#直接创建
    print("直接创建:", x)
    y = torch.arange(2, 4)
    y = y.to('cuda', dtype=torch.double)#可以更改数据类型,使用y = y.cuda()亦可
    print("间接转换:", y)
    z = x + y
    print("转换回CPU:", z.to('cpu', dtype=torch.int))

if __name__ == '__main__':
    test()

  输出如下:

直接创建: tensor([2, 3], device='cuda:0')
间接转换: tensor([2., 3.], device='cuda:0', dtype=torch.float64)
转换回CPU: tensor([4, 6], dtype=torch.int32)
原创文章 35 获赞 44 访问量 8633

猜你喜欢

转载自blog.csdn.net/weixin_44575152/article/details/103872799
今日推荐