动手学习深度学习笔记——PyTorch版(一)

torch基本操作

import torch

# 创建
x = torch.arange(12, dtype=torch.float32)	# 创建值为0-11的向量
y = torch.tensor([[1,2,3],[4,5,6]]) 		# 通过数组创建张量
torch.zeros((2,3,4))    					# 形状为 2*3*4 的全0张量
torch.ones((2,3,4))   						# 形状为 2*3*4 的全1张量
# 操作
x.shape  									# 查看张量形状
type(x)										# 查看x的数据类型
x.numel() 									# 查看张量元素个数
x = x.reshape(3, 4)      					# 改变张量形状 1*12 改为 3*4
torch.cat((x,y), dim=0)						# 按第0维连结张量
x.type(torch.float)							# 转换数据类型

# 计算:加减乘除,幂运算,指数运算 —— 均可按元素计算,可通过广播机制计算
# 广播机制:用于计算的张量形状如果对应某一个维度, 缺失的维度会自动复制填充
x+y, x-y,x*y,x/y,x**y, torch.exp(x)
# 生成逻辑张量 —— 必须对应一个或所有维度
x == torch.tensor([[0, 4, 5]])
x == torch.tensor([[1], [3]])
x == 2
x == torch.arange(12, dtype=torch.float32)
# 元素求和 —— 可按照多维, 结果形状相当于去除进行求和的维度
x.sum(axis=0)
x.sum(axis=[0, 1])
x.cumsum(axis=0)		# 累加求和
# 求均值
x.mean(axis=0)

# 内存
id(x)					# 类似c的指针
x = x+1 				# x的id会改变
x += 1					# x的id不变 —— 减少内存开销
x[:] = 1				# x的id不变
# 创建形状相同张量
z = torch.zeros_like(x)	# 创建一个大小与x相同的张量 

# torch转换为numpy数组
z = x.numpy()

# numpy数组转torch
torch.tensor(z)

# 大小为1的张量转python标量
a = torch.tensor([10])
a.item()

数据预处理

数据生成

import os

os.makedirs(os.path.join('.', 'data'), exist_ok=True)   # 创建文件夹 exist_ok=True表示文件存在时继续
data_file = os.path.join('.', 'data', 'test.csv')       # 创建文件
with open(data_file, 'w') as f:
    f.write('a,b,c\n')      # 列名
    f.write('NA,PC,362\n')  # 以下为各行数据
    f.write('4,NA,3110\n')
    f.write('5,NA,35\n')
    f.write('NA,NA,31\n')
    f.close()

数据预处理

import os
import pandas as pd

data_file = os.path.join('.', 'data', 'test.csv')
data = pd.read_csv(data_file)
print(data)

# 处理缺失数据 —— 常用删除和差值,以下通过平均值插值
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]	# 通过index location 分离首行和数据
inputs = inputs.fillna(inputs.mean())					# 通过平均值填充(非数值型不会填充)
# 将非数值单独分列(通过0-1表示),dummy_na=True 表示非数值列的NAN数据也单独分成一列
inputs = pd.get_dummies(inputs, dummy_na=True)	

# inputs.values 将 pandas 格式转为 numpy 数组格式,之后将其转为张量
X, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
X, y

线性代数

  • 矩阵相乘代表一种空间扭曲

image-20220205221913138

image-20220205222100692

# 线性代数的实现
A = torch.arange(20).reshape(4,5)
B = torch.arange(15).reshape(5,3)
x = torch.arange(5)
A.T						# 矩阵的转置
A.clone()				# 得到A的副本,如果使用B=A,id(A)==id(B)
# 向量点积,
x.dot(x)								
torch.dot(x, x)
torch.sum(x*x)
# 矩阵与向量点积
torch.mv(A,x)
# 矩阵与矩阵点积
torch.mm(A,B)
# L1范数 —— 向量元素绝对值求和
torch.abs(u).sum()
# L2范数 —— 向量元素平方和的平方根
u = torch.tensor([3.0, 4.0])
torch.norm(u)
# 矩阵的 弗罗贝尼乌斯范数 —— 元素平方和的平方根
torch.norm(A.type(torch.float))

微积分

  • 求导
    • 标量求导
    • 向量求导——梯度
    • 矩阵求导

image-20220205232612240

image-20220205232452462

标量对向量求导

image-20220205232647379

向量对向量求导

image-20220205232717307

image-20220205233647934

例一

image-20220205234657669

例二

image-20220205234711242

向量链式求导法则

image-20220205234638867

正向累积,反向累计(反向传递)

计算图

显式构造

  • 有变量 a、b,公式 c = a + b;=> a=1,b=2 时,c=3

隐式构造

  • 系统先记住 a=1,b=2;=> 有公式 c = a + b,则 c=3

正向累积:计算原函数结果和中间值

  • 时间复杂度O(n):操作子个数
  • 空间复杂度O(1)

反向传递:计算梯度

  • 时间复杂度O(n):操作子个数
  • 空间复杂度O(n):需要先进行正向累积储存所有中间结果(耗资源)

image-20220206000235748

自动求导实现

标量求导

image-20220305122756725

import torch

x = torch.arange(4.0, requires_grad=True)  # requires_grad 用于存储梯度
# x = torch.arange(4.0)
# x.requires_grad_(True) 	# 同等效果
x.grad == None  			# 初始默认为None
y = 2 * torch.dot(x, x)  	# 隐式构造计算图并执行 —— grad_fn
y.backward()				# 隐式调用反向传播函数自动计算y关于x每个分量的梯度
x.grad  					# 结果,默认累计梯度
x.grad.zero_()  			# 清零之前的值
y = x.sum() 			 	# 新函数
y.backward()
x.grad
  • y.backward()

    • 若结果非标量

      • 通过 sum,例:y.sum().backward()
      • 显式调用 例:y.backward(torch.tensor([1, 1])),1为梯度系数
      x = torch.tensor([1.,2],requires_grad=True)
      y = 2 * x
      y.backward(torch.tensor([1.0, 1]))
      print(x.grad)  # tensor([2., 2.])
      
    • y = x 1 + x 2 = > d y d x = d x 1 d x + d x 2 d x = > [ d x 1 d x , d x 2 d x ] y=x1+x2 => \frac{dy}{dx}=\frac{dx1}{dx}+\frac{dx2}{dx} => [\frac{dx1}{dx}, \frac{dx2}{dx}] y=x1+x2=>dxdy=dxdx1+dxdx2=>[dxdx1,dxdx2]

    • 默认执行后清空中间值,所以如果需要多次使用,需要加上retain_graph=True保存

      • y.backward(retain_graph=True)

向量对向量求导的自动求导示例——雅可比矩阵

y = [ y 1 , y 2 , y 3 ] = [ x 1 2 + 2 x 2 , x 2 2 + 4 x 1 , x 3 2 + 2 x 1 + x 2 ] x = [ x 1 , x 2 , x 3 ] = [ 1 , 2 , 3 ] J a c o b i a n = [ ∂ y 1 ∂ x 1 , ∂ y 2 ∂ x 1 , ∂ y 3 ∂ x 1 ∂ y 1 ∂ x 2 , ∂ y 2 ∂ x 2 , ∂ y 3 ∂ x 2 ∂ y 1 ∂ x 3 , ∂ y 2 ∂ x 3 , ∂ y 3 ∂ x 3 ] = [ 2 x 1 4 2 2 2 x 2 1 0 0 2 x 3 ] = [ 2 4 2 2 4 1 0 0 6 ] y=[y_1,y_2,y_3]=[x_1^2+2x_2, x_2^2+4x_1, x_3^2+2x_1+x_2] \\\\ x=[x_1,x_2,x_3]=[1,2,3] \\\\ Jacobian = \begin{bmatrix} \frac{\partial y_1}{\partial x_1},\frac{\partial y_2}{\partial x_1},\frac{\partial y_3}{\partial x_1} \\ \frac{\partial y_1}{\partial x_2},\frac{\partial y_2}{\partial x_2},\frac{\partial y_3}{\partial x_2} \\ \frac{\partial y_1}{\partial x_3},\frac{\partial y_2}{\partial x_3},\frac{\partial y_3}{\partial x_3} \end{bmatrix} = \begin{bmatrix} 2x_1&4&2\\ 2&2x_2&1\\ 0&0&2x_3 \end{bmatrix} = \begin{bmatrix} 2&4&2\\ 2&4&1\\ 0&0&6 \end{bmatrix} y=[y1,y2,y3]=[x12+2x2,x22+4x1,x32+2x1+x2]x=[x1,x2,x3]=[1,2,3]Jacobian=x1y1,x1y2,x1y3x2y1,x2y2,x2y3x3y1,x3y2,x3y3=2x12042x20212x3=220440216

import torch

x = torch.tensor([[1.0, 2, 3]], requires_grad=True)
Jacobian = torch.zeros(3, 3)
y = torch.zeros(1, 3)
y[0, 0] = x[0, 0] ** 2 + 2 * x[0, 1]
y[0, 1] = x[0, 1] ** 2 + 4 * x[0, 0]
y[0, 2] = x[0, 2] ** 2 + 2 * x[0, 0] + x[0, 1]

y.backward(torch.tensor([[1, 0, 0]]), retain_graph=True)  # 第一列
Jacobian[:, 0] = x.grad
x.grad.zero_()

y.backward(torch.tensor([[0, 1, 0]]), retain_graph=True)  # 第二列
Jacobian[:, 1] = x.grad
x.grad.zero_()

y.backward(torch.tensor([[0, 0, 1]]), retain_graph=True)  # 第三列
Jacobian[:, 2] = x.grad
x.grad.zero_()

print(Jacobian)
# tensor([[2., 4., 2.],
#         [2., 4., 1.],
#         [0., 0., 6.]])
  • 高阶求导需要分步计算,且每次计算前梯度需要清零

课程:动手学深度学习课程 (d2l.ai)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

solmp

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

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

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

打赏作者

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

抵扣说明:

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

余额充值