非常感谢,datawhale提供的课程资源:https://www.bilibili.com/video/BV1e341127Lt?p=2
以下是这个课程的笔记

一、tensor的属性:

type:float,long,
device的属性:用什么卡,比如CPU,GPU
requires_grad属性:是否支持求导
pin_memory属性:是否塞到内存里面,运算快,但是内存高
is_leaf:是否是叶子节点,不是就继续往前传,是就终止

创建tensor,用dtype指定类型。注意类型要匹配

> a = torch.tensor(1.0, dtype=torch.float) 
> b = torch.tensor(1,dtype=torch.long) 
> #这个int和1.0显然是不匹配的,最好不要这么写
> c = torch.tensor(1.0, dtype=torch.int8)
>  print(a, b,c)

使用指定类型函数随机初始化指定大小的tensor

d = torch.FloatTensor(2,3)
e = torch.IntTensor(2)
 #对于python已经定义好的数据结构可以直接转换.下面的这个是一个列表,
 #list转成整型tensor.只是数据存储的格式变了,但实际还是个List
f = torch.IntTensor([1,2,3,4]) 
print(d, '\n', e, '\n', f)

tensor和numpy array之间的相互转换

import numpy as np
g = np.array([[1,2,3],[4,5,6]])
h = torch.tensor(g)
print(h)
i = torch.from_numpy(g)
print(i)
j = h.numpy()
print(j)

常见的构造Tensor的函数

k = torch.rand(2, 3) 
l = torch.ones(2, 3)
m = torch.zeros(2, 3)
#arange就是一个步长之类的,起始点0,步骤2,终点10
#这里是1维的张量
n = torch.arange(0, 10, 2)
print(k, '\n', l, '\n', m, '\n', n)

查看tensor的维度信息(两种方式)

print(k.shape)
print(k.size())

tensor的运算

o = torch.add(k,l)
print(o)

tensor的索引方式与numpy类似

print(o[:,1])
print(o[0,:])

重要:改变tensor形状的神器:view

#就是想看3行两列,怎么排列的呢,就是o矩阵从第一行开始排列过来的
print(o.view((3,2)))
#这里的-1表示不确定行数,但是我知道列数,计算机帮你排列
print(o.view(-1,2))

tensor的广播机制(使用时要注意这个特性)
我们注意最后一行,它是p+q。按道理是没办法相加的,但是我们可以自己复制粘贴,凑好数

p = torch.arange(1, 3).view(1, 2)
print(p)
q = torch.arange(1, 4).view(3, 1)
print(q)
print(p + q)

重要:扩展&压缩tensor的维度:squeeze
unsqueeze是增加维度,加的维度是空的,1代表第二个维度,0代表第一个维度
squeeze表示的是压缩维度,只能压缩之前增加的维度

print(o)
r = o.unsqueeze(1)
print(r)
print(r.shape)

二、自动求导

1.PyTorch实现模型训练
2.输入数据,正向传播
3同时创建计算图
4计算损失函数
5损失函数反向传播
6更新模型参数

●Tensor数据结构是实现自动求导的基础

python矩阵特征值 pytorch 特征值_反向传播


PyTorch自动求导提供了计算雅克比乘积的工具

损失函数l对输出y的导数是:

python矩阵特征值 pytorch 特征值_CUDA_02

那么l对输入x的导数就是:

python矩阵特征值 pytorch 特征值_反向传播_03


2.2自动求导一动态计算图 (DCG)

张量和运算结合起来创建动态计算图

就是由这样的一个计算图,知道z是由哪里算来的

python矩阵特征值 pytorch 特征值_pytorch_04


2.2自动求导-扩展

静态图和动态图

主要区别在是否需要预先定义计算图的结构

下面的图,左边是静态的,就是说模型是固定好的,再计算。右边是不需要预先定义,边计算边定义图。

python矩阵特征值 pytorch 特征值_python矩阵特征值_05

第二部分:自动求导示例

import torch

x1 = torch.tensor(1.0, requires_grad=True)
x2 = torch.tensor(2.0, requires_grad=True)
y = x1 + 2*x2
print(y)

首先查看每个变量是否需要求导

print(x1.requires_grad)
print(x2.requires_grad)
print(y.requires_grad)

查看每个变量导数大小。此时因为还没有反向传播,因此导数都不存在

print(x1.grad.data)
print(x2.grad.data)
print(y.grad.data)

out:
AttributeError: ‘NoneType’ object has no attribute ‘data’

反向传播后看导数大小

y = x1 + 2*x2
y.backward()
print(x1.grad.data)
print(x2.grad.data)

out:
tensor(1.)
tensor(2.)

导数是会累积的,重复运行相同命令,grad会增加,会影响你的值。所以要注意不要重复运行命令,到后面可以利用一个函数进行清零,不会有累加(每次计算前需要清除当前导数值避免累积,这一功能可以通过pytorch的optimizer实现。后续会讲到)

y = x1 + 2*x2
y.backward()
print(x1.grad.data)
print(x2.grad.data)

尝试,如果不允许求导,会出现什么情况?
就会报错,因为不让求导,反向传播不能进行

# 
x1 = torch.tensor(1.0, requires_grad=False)
x2 = torch.tensor(2.0, requires_grad=False)
y = x1 + 2*x2
y.backward()

out:
untimeError: element 0 of tensors does not require grad and does not have a grad_fn

并行计算:

(1)优点:
能计算-显存占用
算得快-计算速度
效果好-大batch提升训练效果

(2)怎么并行?一CUDA
GPU厂商NVIDIA提供的GPU计算框架
GPU本身的编程基于CUDA语言实现
在PyTorch中,CUDA的含义有所不同
更多的指使用GPU进行计算(而不是CPU )

(3)并行的方法

网络结构分布到不同设备中(Network Partitioning)

python矩阵特征值 pytorch 特征值_CUDA_06

同一层的任务分布到不同数据中(Layer-wise Partitioning)

python矩阵特征值 pytorch 特征值_深度学习_07

(常用的)不同数据分布到不同的设备中(Data Parallelism)

python矩阵特征值 pytorch 特征值_python矩阵特征值_08


(4)cuDNN与CUDA

cuDNN是用于深度神经网络的加速库

cuDNN基于CUDA完成深度学习的加速