书上内容太多太杂,看完容易忘记,特此记录方便日后查看,所有基础语法以代码形式呈现,代码和注释均来源与书本和案例的整理。
# -*- coding: utf-8 -*-
# All codes and comments from <>
# 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.]])
新建Tensor的几种方法
函数
功能
Tensor(*sizes)
基础构造函数
tensor(data,)
类似np.array的构造函数
ones(*sizes)
全1Tensor
zeros(*sizes)
全0Tensor
eye(*sizes)
对角线为1,其他为0
arange(s,e,step)
从s到e,步长为step
linspace(s,e,steps)
从s到e,均匀切分成steps份
rand/randn(*sizes)
均匀/标准正态分布
normal(mean,std)/uniform(from,to)
正态分布/均匀分布
randperm(m)
随机排列
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
参考资料