Pytorch 是 torch 的 python 版本,是由 Facebook 开源的神经网络框架,专门针对 GPU 加速的深度神经网络 (DNN) 编程。简单说起来就是与 tensorflow 竞争的产品,不论使用哪一个,最终都能得到差不多的效果。
How to use Pytorch了解一个框架(语言),最重要的环节便是熟悉语法、方法和接口。较为基础和重要的一些将列在下面。
首先默认你已经安装了 Pytorch 并且能够正常引入,并且已经学习并掌握了 numpy。
Numpy桥
同 tensorflow 一样,pytorch 的常用数据类型也是 Tensor,Tensor 是一种包含单一数据类型元素的多维矩阵,译作“张量”(张晟的弟弟)。
类比 numpy,一维 Tensor 叫 Vector,二维 Tensor叫 Matrix,三维及以上称为 Tensor。
而 numpy 和 Tensor 不仅仅有相似之处,还可以相互转换。
torch.from_numpy(ndarray) -> Tensor
import torch # 声明一个 array,利用 from_numpy 将其转换为 tensor np_data = np.array([7, 2, 3]) torch_data = torch.from_numpy(np_data)
此时得到的 torch_data 与 np_data 共享同一内存空间。修改其中一个另一个也会被修改,且返回的张量不能改变大小。
torch_data[0] = -1 print(np_data) # 输出结果 # [-1, 2, 3]
同时 Tensor 也可以转换为 numpy.ndarray。
torch.numpy() -> ndarray
#将 torch_data 由 Tensor `转换为` numpy.ndarray ` 赋给 tensor2array tensor2array = torch_data.numpy()
Tensor 创建
对于 Python,常用的基本数据类型有 int、float、double 等,与之对应 Pytorch 也提供了多种类型的 tensor。
Pytorch 定了七种 CPU tensor 类型和八种 GPU tensor 类型:
torch.Tensor是默认的tensor类型(torch.FloatTensor)的简称。
# 构造一个 2*2 的张量 t1 = torch.Tensor(2,2) # 等价于 # t1 = torch.FloatTensor(2,2) # 同样地 # t2 = torch.IntTensor(2, 2)
一个张量还可以从 Python 的 list 或序列构建得到。
t1 = torch.FloatTensor([[1, 2, 3], [4, 5, 6]])
其次还有许多创建特殊矩阵的方法:
torch.ones(n,m): 创建n*m 维的张量,其元素都被填充了标量值1;torch.zeros(n,m): 创建n*m 维的张量,其元素都被填充了标量值0;torch.eye(n,m): 创建n*m 维的张量,其对角线为1,其余元素均为0;torch.linspace(start, end, steps=100) : 创建值start和 end之间等间距点的一维张量;torch.rand(sizes): 返回一个张量,包含了从区间[0,1)的均匀分布中抽取的一组随机数,其形状由整数序列sizes定义;torch.randn(sizes): 返回一个张量,包含了从标准正态分布(均值为0,方差为1,即高斯白噪声)中抽取一组随机数,其形状由整数序列sizes定义。
在实际应用中,常常使用 torch.size() 获取 Tensor 的大小。
a = torch.randn(2,2) print(a) print(a.size()) # 输出结果 # 1.5346 -0.1640 # 0.7025 1.7613 # [torch.FloatTensor of size 2x2] # torch.Size([2, 2])
Tensor 索引及切片
索引
- 正序索引:Tensor 的索引值从 0 开始,范围从 0 到 size - 1。
t = torch.Tensor(range(5)) print(t) # 索引为单个值 print(t[1]) # 索引为一个范围 print(t[0:3])
- 逆序索引(tensor[ : , -1 ]): 最后一个索引为 -1。负索引(tensor[ -3 ]):表示倒数第三个元素,注意索引值的大小,始终是小值在冒号的前面,[ -3, -1 ],大值在后。若写成[ -1, -3 ]将会报错。
切片
基本切片通过将 start, stop 和 step 参数提供给内置的 slice 函数来构造一个 Python slice 对象。此 slice 对象被传递给 Tensor 来提取 Tensor 的一部分。
t = torch.Tensor(range(5)) s = slice(2,5,2) print("Slicing Tensor : {}".format(t[s])) print(t[2 : 5 : 2]) # 输出结果相同 # 2 # 4 # [torch.FloatTensor of size 2]
在二维情况下,以逗号进行分割。
tensor = torch.Tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) print(tensor[0 : 3 : 2, : ]) # 输出结果 # 1 2 3 # 7 8 9
还有其他常用函数:
torch.chunk(tensor, chunks, dim = 0)
将张量沿给定维度拆分成若干块。(将要拆分的张量,返回的块数,所沿拆分维度)
torch.cat(seq, dim = 0, out = None) -> Tensor
在给定维度上连接张量的给定序列。(Python 序列,张量连接的维度,输出参数)
torch.unsqueeze(input, dim, out = None)
返回在指定位置插入尺寸为1的新张量。(输入的张量,插入单个维度的索引,结果张量)
基本运算
相加
- x + ytorch.add(x, y)y.add_(x)
x = torch.Tensor(2, 3) y = torch.rand(2, 3) print(x + y) print(torch.add(x, y)) y.add_(x) print(y) # 输出结果相同 # 函数后带下划线表示是否改变原 tensor 值 # y.add_(x) 会在原地求和,并返回改变后的 tensor, # 而 y.add(x)将会在一个新的 tensor 中计算结果, y 本身不改变。
类似的
Reshape
view
在处理数据时,由于不同的需求,我们常常需要将数据进行扩充或者在尺寸上进行变化以进行 *** 作。
这里我们使用 view() 方法,返回具有相同数据但大小不同的新张量,从而达到了 reshape 的作用。
view(args) -> Tensor
返回具有相同数据但大小不同的张量。张量必须 contiguous() 才能被查看。
关于 contiguous(),可以参考下面这篇博客,讲的很不错!
https://blog.csdn.net/kdongyi/article/details/108180250
转置
由下面两种转置产生的结果张量,与输入张量共享存储。
torch.t(input, out = None) -> Tensor
将输入的二维张量转置其维度 0 和 1。(只适用于二维张量)
x = torch.randn(5, 10) print(x.t().size()) # 输出结果 # torch.Size([10, 5])
torch.transpose(input, dim0, dim1, out = None) -> Tensor
返回一个输入转置后的张量,使两个维度相互交换。
y = torch.randn(5, 10, 15) print(y.transpose(0, 1).size()) print(y.transpose(1, 2).size()) # 输出结果 # torch.Size([10, 5, 15]) # torch.Size([5, 15, 10])
求导及梯度
在 0.4 版本以前,pytorch 使用 Variable 进行自动求导和梯度,可以参考这篇文章:
https://zhuanlan.zhihu.com/p/104519573
现在推荐使用的方法如下:
在 Tensor 中有一个参数 requires_grad,表示是否可以求导,即求梯度,默认值为 False。需要注意的是,当叶子结点有一个为可导,则根结点可导。
在使用中,我们通过:
x.requires_grad_(True / False)
设置 tensor 可导与否。但是我们只能这样设置叶子变量,否则会报错!
我们针对一个函数求梯度:
x为 2 * 2 的值全为1的张量
y i = ( x i + 4 ) 2 y_i = (x_i + 4)^2 yi=(xi+4)2
z i = y i 2 + x i + 2 z_i = y_i^2 + x_i + 2 zi=yi2+xi+2
o u t = 1 4 ∑ i = 1 4 z i out = frac{1}{4}sum_{i=1}^4z_i out=41∑i=14zi
下面对 out 求关于 x 的导数:
∂ o u t ∂ x = ( x + 4 ) 3 + 0.25 = 125.25 frac{partial{out}}{partial{x}}=(x + 4)^3 + 0.25 = 125.25 ∂x∂out=(x+4)3+0.25=125.25
然后编程验证:
x = torch.ones(2, 2, requires_grad = True) y = (x + 4) ** 2 z = y**2 + x + 2 out = z.mean() out.backward() print(x.grad) # 输出结果 # tensor([[125.2500, 125.2500], # [125.2500, 125.2500]])
我们可以使用 with torch.no_grad() 来停止梯度的计算:
print(x.requires_grad) print((x ** 2).requires_grad) with torch.no_grad(): print((x ** 2).requires_grad) # 输出结果 # True # True # False
先到这儿吧,明天加油!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)