Python之Pytorch--从入门到精通笔记

Python之Pytorch--从入门到精通笔记,第1张

Python之Pytorch--从入门到精通笔记 What is Pytorch?

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 类型:

数据类型CPU TensorGPU Tensor32-bit floating pointtorch.FloatTensortorch.cuda.FloatTensor64-bit floating pointtorch.DoubleTensortorch.cuda.DoubleTensor16-bit floating pointN/Atorch.cuda.HalfTensor8-bit integer (unsigned)torch.ByteTensortorch.cuda.ByteTensor8-bit integer (signed)torch.CharTensortorch.cuda.CharTensor16-bit integer (signed)torch.ShortTensortorch.cuda.ShortTensor32-bit integer (signed)torch.IntTensortorch.cuda.IntTensor64-bit integer (signed)torch.LongTensortorch.cuda.LongTensor

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 本身不改变。

类似的

函数描述torch.sqrt(t)返回一个新张量,元素为输入的元素开方后的结果torch.round(t)返回一个新张量,元素为输入的元素四舍五入到最接近的整数torch.sign(t)返回一个新张量,元素为输入的元素的符号,正为1,负为-1torch.transpose(t)返回一个新张量,为原来张量的转置torch.abs(t)返回一个新张量,元素为输入元素的绝对值torch.ceil(t)返回一个新张量,元素为大于输入元素最小的整数torch.cos(t)返回一个新张量,元素为输入元素的 cos值torch.sin(t)返回一个新张量,元素为输入元素的sin值
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=14​zi​

下面对 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

先到这儿吧,明天加油!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5711050.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存