Pytorch学习笔记(一)---- 基础语法

书上内容太多太杂,看完容易忘记,特此记录方便日后查看,所有基础语法以代码形式呈现,代码和注释均来源与书本和案例的整理。

# -*- coding: utf-8 -*-
# All codes and comments from <<深度学习框架Pytorch入门与实践>>
# Code url : https://github.com/zhouzhoujack/pytorch-book
# lesson_1 : Basic code syntax of PT(Pytorch)

import torch as t
import numpy as np

# 1.The version of torch
print(t.__version__)                # version is 1.0.1

# 2.The defination of tensor
x = t.Tensor(5, 3)                 # 构建 5x3 矩阵,只是分配了空间,未初始化
x = t.Tensor([[1,2],[3,4]])

# 3.Initialize tensor by [0,1] uniform distribution
x = t.rand(5, 3)
print(x, x.size()[0])              # torch.Size 是tuple对象的子类,因此它支持tuple的所有操作,如x.size()[0]

# 4.Addition
x = t.rand(5, 3)
y = t.rand(5, 3)
print("first method: ", x + y)
print("second method: ", t.add(x,y))

result = t.Tensor(5, 3)             # 加法的第三种写法:指定加法结果的输出目标为result,预先分配空间
t.add(x, y, out=result)             # 结果存到result
print("thid method: ", result)      # 函数名后面带下划线_ 的函数会修改Tensor本身。x.add_(y)会改变x,但x.add(y)返回一个新的Tensor,x不变

# 5.Tensor <-> Numpy
a = t.ones(5)
b = a.numpy()
print(b)                              # array([1., 1., 1., 1., 1.], dtype=float32)
a = np.ones(5)
b = t.from_numpy(a)
print(b)                              # tensor([1., 1., 1., 1., 1.], dtype=torch.float64)

# 6.Get specific index from a tensor
a = t.rand(5)
scalar = a[0]
print(scalar,scalar.size())     # 0-dim tensor
print(scalar.item())            # 使用scalar.item()能从中取出python对象的数值

# 7.Autograd
# 在Tensor上的所有操作,autograd都能为它们自动提供微分
# 使得Tensor使用autograd功能,只需要设置tensor.requries_grad=True.
# Variable正式合并入Tensor, Variable本来实现的自动微分功能,Tensor就能支持
# Variable主要包含三个属性:
# data:保存Variable所包含的Tensor
# grad:保存data对应的梯度,grad也是个Variable,而不是Tensor,它和data的形状一样。
# grad_fn:指向一个Function对象,这个Function用来反向传播计算输入的梯度
x = t.ones(2, 2, requires_grad=True)      # 为tensor设置 requires_grad 标识,代表着需要求导数
y = x.sum()
y.backward()                              # 反向传播,计算梯度
print(x.grad)                             # tensor([[ 1.,  1.],[ 1.,  1.]])
x.grad.data.zero_()                       # grad在反向传播过程中是累加的,每一次运行反向传播,梯度都会累加之前的梯度,所以反向传播之前需把梯度清零。
print(x.grad)                             # tensor([[ 0.,  0.],[ 0.,  0.]])

Backward()详解

对上面的y.backward() 运行原理还不是很熟悉,特此记录一下:

backward()函数用于反向求导数,使用链式法则求导,当自变量为不同变量形式时,求导方式和结果有变化。

1.scalar标量

import torch as t
from torch.autograd import Variable

a = Variable(t.FloatTensor([2, 3]), requires_grad=True)    # 这里为一维标量
b = a + 3
c = b * b * 3
out = c.mean()
out.backward()      
print(a.grad)       # tensor([15., 18.])

2.张量

# y1 = x1^2  y2 = x2^3
# dy1/dx1 | x1=2 = 2*x1 = 2*2 =4
# dy2/dx2 | x2=3 = 3*x2*x2 = 27
m = Variable(t.FloatTensor([[2, 3]]), requires_grad=True)   # 注意这里有两层括号,非标量
n = Variable(t.zeros(1, 2))
n[0, 0] = m[0, 0] ** 2
n[0, 1] = m[0, 1] ** 3

n.backward(t.Tensor([[1, 1]]),retain_graph=True)            # 这里[[1, 1]]作为梯度的系数看待
print(m.grad)                                               # tensor[[4,27]]

3.链式求导(还有疑问)

z = (w+x)Tb 其中:dz/dx = dz/dw= z, dz/db = w+x = y , dz/dy = b

# y = x*w
# z = y + b
# k.backward(p)接受的参数p必须要和k的大小一样,x.grad = p*dk/dx
w = Variable(t.randn(3), requires_grad=True)
x = Variable(t.randn(3), requires_grad=True)
b = Variable(t.randn(3), requires_grad=True)
y = w + x
z = y.dot(b)
y.backward(b,retain_graph=True)
print(x.grad,w.grad,b)   # x.gard=w.gard=b

参考资料

Backward()详解:http://www.mamicode.com/info-detail-2167311.html

猜你喜欢

转载自www.cnblogs.com/huxiaozhouzhou/p/10611393.html