pytorch学习笔记(一)

前言

此为小弟pytorch的学习笔记,希望自己可以坚持下去。(2020/2/17)

pytorch官方文档

pytorch中文教程

tensor

tensor是pytorch的最基本数据类型,相当于numpy中的ndarray,并且属性和numpy相似,tensor可在GPU上进行运算。

tensor常见的基本属性:

1.创建tensor

通常此类方法都有以下属性,特别注意,区别numpy,一般这里的入口参数size都是数字序列,而不是元组或者列表:

image-20200217184344218
#创建无初始化tensor
x1 = torch.empty(5, 3)
#创建全0值tensor
x2 = torch.zeros(5, 3, dtype=torch.long)
#创建随机值tensor
x3 = torch.rand(5, 3)
#创建全1
x4 =torch.ones(5,3)

#根据已有tensor创建新的tensor,可继承之前的所有属性,包括dtype,device等
x = x1.new_ones(5, 3, dtype=torch.double)#必须输入size
x = torch.randn_like(x1, dtype=torch.float)

#根据其余数据类型创建tensor
#列表
x=torch.tensor([1,2,3])
#ndarray
np_data=np.arange(4).reshape((2,2))
x=torch.tensor(np_data,dtype=torch.float)

补充:关于随机数,这里提供一个总结后的帖子:随机数生成

2. 基本属性

requires_grad:是否需要梯度,如果为true则会允许自动求导

#设置为有梯度属性
x= torch.rand(5, 3,requires_grad=True)
#改变梯度属性
x.requires_grad_(False)

3. 基本方法

size():获取大小

item():获取只有一个值的tensor的值

view():改变shape,此改变创建了新的副本

x= torch.rand(5, 3,requires_grad=True)
#Size()为元组
x.size()
x=torch.arange(6,dtype=torch.float).reshape((2,3))

#view() 	
y1=x.view(-1,1)
y2=x.view(3,2)
print(
    '\n',y1,
    '\n',y2
)

3.1 gather

沿给定轴dim,将输入索引张量index指定位置的值进行聚合.

torch.gather(input, dim, index, out=None) → Tensor

其中index是一个矩阵张量,其size与输出的大小一致,用于做(行或者列的)索引值。dim表示index的索引数值用于索引哪个轴,比如:当dim=1,那么index中的数值1就表示(×,1)这个数值,其余坐标与index的坐标一致。

比如:

tensor([[0, 1, 2],
       			 [3, 4, 5],
       			 [6, 7, 8]])
index1 =torch.tensor([[1,2,2],[0,1,1]])
tensor([[1, 2, 2],
        		[0, 1, 1]])
out1=torch.gather(input=input,index=index1,dim=0)
out1        
tensor([[3, 7, 8],
       			 [0, 4, 5]])

这里我们选择dim=0,也就是index中的数值代表的是dim=0(行号0),比如index中(0,0)位置的1,索引的就是input中的(1,0),将index的位置取代为其数值。注意:你选择哪个维度,索引的其余维度的必须与input相同,因为必须保证,index有能力访问所有input的数值。比如input->(3,3),选择dim=0,那么index中dim=1的维数必须为3。选择dim=1,dim=0就必须为3。

index2 =torch.tensor([[1,2,2],[0,1,1]]).reshape(3,2)
index2

out2=torch.gather(input=input,index=index2,dim=1)
out2
tensor([[1, 2],
        [5, 3],
        [7, 7]])

4. 运算

tensor的所有常规运算都是基于元素的。

x=torch.arange(4,dtype=torch.float).reshape((2,2))
#点乘
out1=x*x
#如果要用到叉乘
out2=torch.mm(x,x)

print(
    '\n',out1,
    '\n',out2
)
>>>>>>>
 tensor([[0., 1.],
        [4., 9.]]) 
 tensor([[ 2.,  3.],
        [ 6., 11.]])

5. GPU运算

#创建tensor
x=torch.ones(3,4,dtype=torch.float)
# 当GPU可用时,我们可以运行以下代码
# 我们将使用`torch.device`来将tensor移入和移出GPU
if torch.cuda.is_available():
    device = torch.device("cuda")          # a CUDA device object
    y = torch.ones_like(x, device=device)  # 直接在GPU上创建tensor
    # x = x.to(device)                       # 或者使用`.to("cuda")`方法
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))       # `.to`也能在移动时改变dtype

自动求导Autograd

对于一个tensor,若其requires_grad=True 那么它将会追踪对于该张量的所有操作。当完成计算后可以通过调用 .backward(),来自动计算所有的梯度。这个张量的所有梯度将会自动累加到.grad属性.

x = torch.ones(3,3, requires_grad=True)
y=x*x+2
#
out1=y.sum()
#out1通常是一个标量,若是一个非变量,不可直接进行backward()
out1.backward()
#根据链式求导法则,x_i.grad=1*2x=2
print(
    '\n',x,
    '\n',y,
    '\n',x.grad
)
>>>>>>>>>
 tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], requires_grad=True) 
 tensor([[3., 3., 3.],
        [3., 3., 3.],
        [3., 3., 3.]], grad_fn=<AddBackward0>) 
 tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]])
 
#若输出结果是一个非标量
x = torch.rand(2,2, requires_grad=True)
y = torch.rand(2,1,requires_grad=True)
out1=2*torch.mm(x,y)
#不可直接使用out1.backward()
out1.backward(torch.ones_like(y))
print(
    '\n',x,
    '\n',y,
    '\n',out1,
    '\n',y.grad
)

对于向量的求导,实际atuograd已经计算了雅可比矩阵,但是pytorch的内部机制,或者说本身pytorch就是为神经网络设计的,反向传播的起点为损失函数,必然为一个标量,所以,自动求导的out是需要为标量。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dH54kvIx-1593401469011)(D:\CV\pytorch\md_img\2.1.1)]

out1.backward(torch.ones_like(y))这里实际上输入了一个[1,1].T 的向量,代表某个标量l对out1的导数,等同于以下程序:

x2 = torch.ones(2,2,requires_grad=True)
y2 = torch.ones(2,1,requires_grad=True)
z=2*torch.mm(x2,y2)
out2=z.sum()
print(out2)
#不可直接使用out1.backward()
out2.backward()
print(
    '\n',y2.grad
)

关于更多,更深入的atuograd理解,可品读这个帖子,深入浅出:PyTorch 自动一阶求导在标量、向量、矩阵、张量运算中的定义

清空grad

当我们需要清除某个tensor的梯度时,我们需要:

tensor.grad = None

阻止autograd跟踪

除了修改tensor的requires_grad为False以外,我们还可以进行这样的操作,阻止autograd跟踪:

with torch.no_grad():
    print((y2*y2).requires_grad):	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值