深度学习笔记-1.基本的数据操作


在深度学习中,我们通常会频繁地对数据进行操作。作为动手学深度学习的基础,掌握对内存中数据的处理,以及一些函数的掌握很有必要,本章是开篇对深度学习的Pytorch版本的学习与记录,原书是李沐 MXNet版本《动手学深度学习》,!


1-tensor创建

Tensor和NumPy的多维数组非常类似
"tensor"这个单词一般可译作“张量”,张量可以看作是一个多维数组。标量可以看作是0维张量,向量可以看作1维张量,矩阵可以看作是二维张量.

import torch

x=torch.empty(5,3)#创建一个5x3的未初始化的Tensor
print(x)
#tensor([[2.8035e+10, 5.6332e-43, 2.8035e+10],
#        [5.6332e-43, 2.8035e+10, 5.6332e-43],
#        [2.8035e+10, 5.6332e-43, 2.8035e+10],
#        [5.6332e-43, 2.8035e+10, 5.6332e-43],
#        [2.8035e+10, 5.6332e-43, 2.8035e+10]])

x=torch.rand(5)#返回区间[0, 1) np.random.rand(5)
#tensor([0.2398, 0.4620, 0.0815, 0.1845, 0.7786])

torch.zeros((2,2),dtype=torch.long)#创建一个2x2的long型全0的Tensor: np.zeros((2,2),dtype=np.int8)
#tensor([[0, 0],
#        [0, 0]])
torch.tensor([5.5000, 3.0000])#直接按照数据创建
#tensor([5.5000, 3.0000]

x=x.new_ones(5, 3, dtype=torch.float64)  # 返回的tensor默认具有相同的torch.dtype和torch.device

#返回一个均值为0.方差为1的正态分布的随机数,指定类型为float
torch.randn_like(x, dtype=torch.float) # 指定新的数据类型
# 查看纬度张量大小
x.shape / x.size()

2-功能函数

这些方法在创建的时候可以指定数据类型dtype和存放device(cpu/gpu)

#可以联想Numpy的一些函数,很类似,可以去官方API查阅
ones(size)# 全1,
zeros(size) #全 0,
eye(size) #对角1矩阵,
arrange(s,e,steps) #从s到e,步长为step 类似循环循
linspace(s,e,steps)#从s到e,均匀切分成steps份
rand/randn(*size) #均匀/标准分布
normal(mean,std)/uniform(from,to) ##正态分布/均匀分布
randperm(m) #随机排列 m为int 随机返回[0,m) 

3-算术操作
#加法 x+x1 add(x,x1) add(x,x1,out=torch.empty(size))
y  = torch.tensor([5, 3])
y1 = torch.tensor([4, -1])
print(y+y1)#tensor([9, 2])
print(torch.add(y,y1))#函数tensor([9, 2])
#可以指定输出
result = torch.empty(2)
torch.add(y1, y, out=result)
print(result)

PyTorch操作inplace版本都有后缀_, 例如x.copy_(y), x.t_() 修改原值

y.add_(y1)# y的值从tensor([5, 3])变为tensor([9, 2])
#而y.add(y1) 不修改y的值

4-数据操作

索引可以联想Numpy的用法,索引出来的结果与原数据共享内存,也即修改一个,另一个会跟着修改

#切片的操作 共享内存一起修改
y = x[0, :]
y += 1
print(y)
print(x[0, :]) # 源tensor也被改了 x的0行也修改了
#==>tensor([1.6035, 1.8110, 0.9549])
#   tensor([1.6035, 1.8110, 0.9549])
4_1. index_select

index_select(input,dim.index) 在指定维度dim上选取,比如选取某些行、某些列
切片操作的话的会修改原共享内存,源数据

x=torch.tensor([[ 2.3967,  2.0892,  1.4369],
       			[ 1.6995,  2.0453,  0.6539],
		        [-0.1553,  3.7016, -0.3599]])
		        
##在x 的基础上,0表示按行 选择index 0,2行的数据
torch.index_select(x,0,index=torch.tensor([0,2]))
#tensor([[ 2.3967,  2.0892,  1.4369],
#        [-0.1553,  3.7016, -0.3599]])

#在x 的基础上,1表示按列 选择index 0列,2列的数
torch.index_select(x,1,index=torch.tensor([0,2]))
#tensor([[ 2.3967,  1.4369],
#        [ 1.6995,  0.6539],
#        [-0.1553, -0.3599]])
4_2. masked_select

masked_select(input, mask) mask的类似于过滤的操作 df[df.age>0] mask 有四种类型:
torch.ge(input, other, out=None) → Tensor ------input >= other
torch.gt (input, other, out=None) → Tensor ------input > other
torch.le (input, other, out=None) → Tensor ------input <= other
torch.lt (input, other, out=None) → Tensor ------input < other
other 可以是一个数也可以是一个与input 同类型的张量,输出一个bool形的张量。

x.ge(1)#筛选大于1的数据 生成bool true or False
torch.masked_select(x,x.ge(1))#筛选大于1的数据
#==>tensor([1.6035, 1.8110, 1.0482, 2.8663, 1.0739, 2.2628])
4_3. torch.nonzero

帅选非零元素的下标torch.nonzero(x),然后可以通过下标获取元素

4_4. torch.gather

gather(input, dim, index) 根据index,在dim维度上选取数据,输出的size与index一样
dim=0 length矩阵中的数的值代表的是行数,所处位置代表的是列数。
dim=1 length矩阵中的数的值代表的是列数,所处位置代表的是行数。

x=torch.tensor([[ 2.3967,  2.0892,  1.4369],
        [ 1.6995,  2.0453,  0.6539],
        [-0.1553,  3.7016, -0.3599]])
#dim=0 [[00,01],[10,01]]   index矩阵表示行数  列数表示位置所处的列数
torch.gather(x,0, torch.tensor([[0, 0], [1, 0]]))
#tensor([[2.3967, 2.0892],
#       [1.6995, 2.0892]])

#dim=1 index矩阵的数字表示列数 [[00,00],[11,10]] 01->表示0行1列 行数表示位置所处的行数
torch.gather(x,1, torch.tensor([[0, 0], [1, 0]]))
#tensor([[2.3967, 2.3967],
#        [2.0453, 1.6995]])
4_5. view

用于改变view的形状
注意view()返回的新Tensor与源Tensor虽然可能有不同的size,但是是共享data的,也即更改其中的一个,另外一个也会改变

x.shape# (5,3)
z=x.view(-1,5)#(3,5)
x.view(-1)#(1,15)
z+=1#修改操作  源x 也改变了

用view()会修改源数据,一般会先clone创造一个副本然后再使用view

x_cp = x.clone().view(15)#先用clone创造一个副本然后再使用view  copy
#修改x 不影响x_cp的值
x-=1

item 将一个标量 tensor 转化为number

x = torch.randn(1)
print(x)
print(x.item())

5-线性函数

在这里插入图片描述
支持很多操作如转置、索引、切片、数学运算、线性代数、随机数等等,更多可参考官方文档

6-Tensor与Numpy相互转换
6_1. broadcasting

当对两个形状不同的Tensor按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个Tensor形状相同后再按元素运算

x = torch.arange(1, 3).view(1, 2)
print(x)
y = torch.arange(1, 4).view(3, 1)
print(y)
------------------------------------
==> tensor([[1, 2]])
	tensor([[1],
        [2],
        [3]])

6_2. 内存机制

在这里插入图片描述
还可以使用运算符全名函数中的out参数或者自加运算符+=(也即add_())达到上述效果,例如torch.add(x, y, out=y)和y += x(y.add_(x))

x = torch.tensor([1, 2])
y = torch.tensor([3, 4])
id_before = id(y)
torch.add(x, y, out=y) # y += x, y.add_(x)
print(id(y) == id_before) # True   
print(y)#tensor([4, 6]) 因为共享内存 值改变 

注:虽然view返回的Tensor与源Tensor是共享data的,但是依然是一个新的Tensor(因为Tensor除了包含data外还有一些其他属性),二者id(内存地址)并不一致。

6_3. 自动梯度求导

numpy()from_numpy()TensorNumPy中的数组相互转换。但是需要注意的一点是: 这两个函数所产生的的TensorNumPy中的数组共享相同的内存(所以他们之间的转换很快),改变其中一个时另一个也会改变!!!

1-Tensor 转Numpy

import numpy as np

a=torch.ones(5)#tensor([1., 1., 1., 1., 1.])
b=a.numpy()#转numpy  array([1., 1., 1., 1., 1.], dtype=float32)
#执行操作a+=1 or b+=1 都会修改对应的数据
a+=1
print(a,b)#(tensor([2., 2., 2., 2., 2.]), array([2., 2., 2., 2., 2.], dtype=float32))

2-Numpy 数组转 Tensor

a = np.ones(5)#
b = torch.from_numpy(a)
print(a,b)#[1. 1. 1. 1. 1.] tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
#执行操作a+=1 or b+=1 都会修改对应的数据

通过以下方式的不会共享内存。torch.tensor()

c = torch.tensor(a)
a += 1
print(a, c)
#==>[2. 2. 2. 2. 2.] tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elvis_hui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值