PyTorch2:张量的运算
1.Creation操作
1.1 转化一个已有数组
把一个已有数组转化成Tensor
,通常有四种方法:
- torch.Tensor()
array = np.arange(5)
# 方法 1
>>> tensor1 = torch.Tensor(array)
>>> print(tensor1)
tensor([0., 1., 2., 3., 4.])
>>> print(tensor1.dtype)
torch.float32
- torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
array = np.arange(5)
# 方法 2
>>> tensor2 = torch.tensor(array)
>>> print(tensor2)
tensor([0, 1, 2, 3, 4])
>>> print(tensor2.dtype)
torch.int64
- torch.from_numpy(ndarray)
array = np.arange(5)
# 方法 3
>>> tensor3 = torch.from_numpy(array)
>>> print(tensor3)
tensor([0, 1, 2, 3, 4])
>>> print(tensor3.dtype)
torch.int64
- torch.as_tensor(data, dtype=None, device=None)
array = np.arange(5)
# 方法 4
>>> tensor4 = torch.as_tensor(array)
>>> print(tensor4)
tensor([0, 1, 2, 3, 4])
>>> print(tensor14.dtype)
torch.int64
可以看出,torch.Tensor()
没有保留数值类型,其它三个都保留了。这是因为torch.Tensor()
实际上是一个类,传入的数据需要“初始化”;其它三个都是函数,而通过torch.Tensor()
生成的张量的数据类型是由一个环境变量决定的,这个环境变量可以通过torch.set_default_tensor_type(t)
这个函数来设定。
那么新的张量与原来的数组是什么关系呢?
>>> tensor1[0] = 100
>>> print(array)
[0 1 2 3 4]
>>> tensor2[1] = 100
>>> print(array)
[0 1 2 3 4]
>>> tensor3[2] = 100
>>> print(array
[ 0 1 100 3 4]
>>> tensor4[3] = 100
>>> print(array)
[ 0 1 100 100 4]
torch.Tensor()
和 torch.tensor()
复制了原数组的数据,
torch.from_numpy()
和 torch.as_tensor()
直接与原数组共享数据。
综上所述,
需要创建新张量时,推荐使用 torch.tensor()
;
需要避免复制时,推荐使用 torch.as_tensor()
。
理由如下:
-
torch.tensor()
和torch.as_tensor()
的 API 更丰富,可控制的属性更多; -
torch.Tensor()
会改变数据类型,torch.from_numpy()
可接受的变量有限。
1.2 其他创建张量的方法
1.2.1 创建全部值为定值的函数
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) # 全为 0
torch.ones(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) # 全为 1
torch.empty(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False) # 全为一个随机小数
torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) # 全为一个定值
参数说明:
- *size:新张量的形状
- out:输出的已有张量名称
- dtype:数据类型
- layout:内存里的存储方式
- device:存储设备
- require_grad:是否追踪导数
最后一个函数 torch.empty
生成的所谓“小数”真的是是非常小的、接近 0 的数:
>>> torch.empty(1)
tensor([2.0890e+20])
还可以根据已有的张量,按照该张量的形状生成相同形状的新张量:
torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)
torch.ones_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)
torch.empty_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)
torch.full_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)
举个例子,假设 a
是一个 (2, 2)
的矩阵张量:
>>> a = torch.ones(2, 2)
>>> b = torch.zeros_like(a)
>>> print(a, b)
tensor([[1., 1.],
[1., 1.]])
tensor([[0., 0.],
[0., 0.]])
1.2.2 创建一个元素间隔为常量的函数
torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
创建一个 1 维张量,范围为 [start, end)
,步进为 step
。
>>> torch.arange(4)
tensor([0, 1, 2, 3])
torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
创建一个 1 维张量,范围为 [start, end]
,步数为 step
。
>>> torch.linspace(0, 5, 6)
tensor([0., 1., 2., 3., 4., 5.])
torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
创建一个 1 维张量,范围为 ,步数为 step
。
>>> torch.logspace(-10, 10, 5, 10)
tensor([1.0000e-10, 1.0000e-05, 1.0000e+00, 1.0000e+05, 1.0000e+10])
1.2.3 创建一个对角张量
torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
对角张量指张量的对角线上的元素为 1,其余值为 0 的张量。
>>> torch.eye(3)
tensor([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
2. indexing,slicing,joining 及 mutating 操作
2.1 indexing操作
pytorch支持python式的索引操作
>>> a = torch.tensor([[1, 2, 3], [4, 5, 6]])
>>> a[0][1]
tensor(2)
torch.index_select(input, dim, index, out=None) 根据指定索引在指定轴上索引。
>>> a = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> indices = torch.tensor([0, 2])
>>> torch.index_select(a, 0, indices) # 选取第 0 轴上第 0,2 个元素
tensor([[1, 2, 3],
[7, 8, 9]])
torch.masked_select(input, mask, out=None) 在 1 位张量上以布尔值进行索引。
>>> a = torch.tensor([0, 1, 2, 3])
>>> mask = a.lt(2) # 以“小于 2”为条件创建布尔值
>>> torch.masked_select(a, mask)
tensor([0, 1])
2.2 slicing 操作
Python 原生 slicing 操作
>>> a = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> a[0:2, :]
tensor([[1, 2, 3],
[4, 5, 6]])
torch.split(tensor, split_size_or_sections, dim=0)
按照给定维度进行切片。
如果 split_size_or_sections
是一个整数,则以该数字为单位进行切片。如果张量在该维的长度不能被整除,最后一片的尺寸会小。
如果 split_size_or_sections
是一个列表,张量会按每个元素值切片。
>>> a = torch.arange(10)
>>> torch.split(a, 2, 0)
(tensor([0, 1]),
tensor([2, 3]),
tensor([4, 5]),
tensor([6, 7]),
tensor([8, 9]))
>>> torch.split(a, [3, 7], 0)
(tensor([0, 1, 2]), tensor([3, 4, 5, 6, 7, 8, 9]))
torch.chunk(input, chunks, dim=0)
在给定维度上将张量切成 chunk
份。若张量长度不能整除,则最后一份的长度会小。
>>> torch.chunk(a, 3, 0)
(tensor([0, 1, 2, 3]), tensor([4, 5, 6, 7]), tensor([8, 9]))
2.3 joining 操作
torch.cat(tensors, dim=0, out=None)
在不增加维度的情况下聚合若干个张量。
>>> x = torch.arange(6).reshape(2, 3)
>>> torch.cat([x, x], dim=0) # 在第 0 轴聚合
tensor([[0, 1, 2],
[3, 4, 5],
[0, 1, 2],
[3, 4, 5]])
>>> torch.cat([x, x], dim=1) # 在第 1 轴聚合
tensor([[0, 1, 2, 0, 1, 2],
[3, 4, 5, 3, 4, 5]])
torch.stack(tensors, dim=0, out=None)
将两个张量叠加到一起,这会产生一个新的轴。
>>> torch.stack([x, x], dim=0)
tensor([[[0,1,2],
[3,4,5]],
[[0,1,2],
[3,4,5]]])
>>> torch.stack([x, x], dim=1)
tensor([[[0,1,2],[0,1,2]],
[[3,4,5],[3,4,5]]])
3.math操作
3.1 pointwize 操作
pointwise 指的是元素对元素。比如
A = torch.Tensor([a1, a2])
A + 2. = torch.Tensor([a1+2., a2+2.])
3.1.1 张量的四则运算
torch.add(input, other, *, alpha=1, out=None) # 相加
torch.sub(input, other, out=None) # 相减
torch.mul(input, other, out=None) # 相乘
torch.div(input, other, out=None) # 相除
torch.add()比较特殊,它遵循如下公式:
例如:torch.add(torch.tensor(1), torch.tensor(2), torch.tensor(3))
的运算实际上是1+2*3=7。
还有特殊的运算:
torch.addcdiv(input, tensor1, tensor2, *, value=1, out=None),对应的运算规则为:
torch.addcmul(input, tensor1, tensor2, *, value=1, out=None),对应的运算规则为:
3.1.2 指数、对数、幂函数的运算
两个指数函数:
-
torch.exp(input, out=None)
自然指数运算: -
torch.pow(input, exponent, out=None)
任意指数运算:
四个对数函数:
-
torch.log(input, out=None)
自然对数运算: -
torch.log1p(input, out=None)
自然对数运算: -
torch.log2(input, out=None)
以 2 为底的对数运算: -
torch.log10(input, out=None)
以 10 为底的对数运算:
3.1.3 变换函数
-
torch.abs(input, out=None)
:返回张量的绝对值。 -
torch.ceil(input, out=None)
:对张量向上取整。 -
torch.floor(input, out=None)
:对张量向下取整。 -
torch.floor_divide(input, other, out=None)
:张量相除后向下取整。 -
torch.fmod(input, other, out=None)
:对张量取余。 -
torch.neg(input, out=None)
:取张量的相反数。 -
torch.round(input, out=None)
:对张量取整。 -
torch.sigmoid(input, out=None)
:对张量进行 sigmoid 计算。 -
torch.sqrt(input, out=None)
:对张量取平方根。 -
torch.square(input, out=None)
:对张量平方。 -
torch.sort(input, dim=-1, descending=False, out=None)
:返回张量的排序结果。
3.1.4 三角函数
-
torch.sin(input, out=None)
:正弦 -
torch.cos(input, out=None)
:余弦 -
torch.tan(input, out=None)
:正切
3.2 降维函数
所谓降维,就是某个维度经过运算后返回值是一个张量。
如果下述函数中的 dim
变量没有显式赋值,则对整个张量进行计算,返回一个值;若 dim
被显性赋值,则对该 dim
内的每组数据分别进行运算。
keepdim
若为 True
,每个运算结果为一个一维张量,实际上没有降维。
-
torch.argmax(input, dim, keepdim=False)
:返回张量内最大元素的索引。 -
torch.argmin(input, dim, keepdim=False, out=None)
:返回张量内最小元素的索引。
例子:
>>> a = torch.tensor([[1, 3, 2, 4], [9, 8, 7, 6]])
>>> torch.argmax(a, dim=1)
tensor([3, 0])
-
torch.max(input, dim, keepdim=False, out=None)
:返回在指定维度内进行比较后的最大值。 -
torch.min(input, dim, keepdim=False, out=None)
:返回在指定维度内进行比较后的最小值。 -
torch.mean(input, dim, keepdim=False, out=None)
:返回张量内张量的平均数。 -
torch.median(input, dim=-1, keepdim=False, out=None)
:返回张量内张量的中位数。 -
torch.prod(input, dim, keepdim=False, dtype=None)
:返回张量内元素的乘积。 -
torch.std(input, dim, unbiased=True, keepdim=False, out=None)
:返回张量内的标准差。 -
torch.sum(input, dim, keepdim=False, dtype=None)
:返回张量内元素的和。 -
torch.var(input, dim, keepdim=False, unbiased=True, out=None)
:返回张量内元素的方差。 例子:
>>> a = torch.ones((4, 3)) # 4 x 3 的全 1 矩阵
>>> torch.sum(a) # 没有维度,对所有元素求和
tensor(12.)
>>> torch.sum(a, dim=1)
tensor([3., 3., 3., 3.])
>>> torch.sum(a, dim=1, keepdim=True)
tensor([[3.],
[3.],
[3.],
[3.]])
3.3 比较函数
返回索引的函数:
-
torch.argsort(input, dim=-1, descending=False)
返回在指定维度中第几大/小索引的张量,默认升序比较最后一维:
>>> a = torch.tensor([[1, 3, 2, 4], [9, 8, 7, 6]])
>>> torch.argsort(a)
tensor([[0, 2, 1, 3],
[3, 2, 1, 0]])
既返回值,又返回索引的函数:
-
torch.sort(input, dim=-1, descending=False, out=None)
:对张量进行排序。
>>> x = torch.randn(3, 4)
>>> sorted, indices = torch.sort(x)
>>> sorted
tensor([[-0.2162, 0.0608, 0.6719, 2.3332],
[-0.5793, 0.0061, 0.6058, 0.9497],
[-0.5071, 0.3343, 0.9553, 1.0960]])
>>> indices
tensor([[ 1, 0, 2, 3],
[ 3, 1, 0, 2],
[ 0, 3, 1, 2]])
-
torch.topk(input, k, dim=None, largest=True, sorted=True, out=None)
:返回最大/最小的k
个值和它们的索引。
>>> x = torch.arange(1., 6.)
>>> x
tensor([ 1., 2., 3., 4., 5.])
>>> torch.topk(x, 3)
torch.return_types.topk(values=tensor([5., 4., 3.]), indices=tensor([4, 3, 2]))
-
torch.cummax(input, dim, out=None)
:值与索引为当前位置以前的最大值和最大值的索引。 -
torch.cummin(input, dim, out=None)
:值与索引为当前位置以前的最小值和最小值的索引。
>>> a = torch.randn(10)
>>> a
tensor([-0.3449, -1.5447, 0.0685, -1.5104, -1.1706, 0.2259, 1.4696, -1.3284,
1.9946, -0.8209])
>>> torch.cummax(a, dim=0)
torch.return_types.cummax(
values=tensor([-0.3449, -0.3449, 0.0685, 0.0685, 0.0685, 0.2259, 1.4696, 1.4696,
1.9946, 1.9946]),
indices=tensor([0, 0, 2, 2, 2, 5, 6, 6, 8, 8]))
>>> a = torch.randn(10)
>>> a
tensor([-0.2284, -0.6628, 0.0975, 0.2680, -1.3298, -0.4220, -0.3885, 1.1762,
0.9165, 1.6684])
>>> torch.cummin(a, dim=0)
torch.return_types.cummin(
values=tensor([-0.2284, -0.6628, -0.6628, -0.6628, -1.3298, -1.3298, -1.3298, -1.3298,
-1.3298, -1.3298]),
indices=tensor([0, 1, 1, 1, 4, 4, 4, 4, 4, 4]))
比较两个张量的元素,返回包含每个元素间比较的最大/小值:
torch.max(input, other, out=None)
torch.min(input, other, out=None)
这两个函数与上面的降维函数中的同名函数的区别在于上面的两个函数的输入是一个张量,这里是两个。
>>> a = torch.tensor([[1, 3, 96, 97], [98, 99, 7, 6]])
>>> b = torch.tensor([[100, 101, -1, -2], [-3, -4, 102, 103]])
>>> torch.max(a, b)
tensor([[100, 101, 96, 97],
[ 98, 99, 102, 103]])
>>> torch.min(a, b)
tensor([[ 1, 3, -1, -2],
[-3, -4, 7, 6]])
两个张量比较是否相同,返回一个布尔值:torch.equal(input, other)
>>> torch.equal(torch.tensor([1, 2]), torch.tensor([1, 2]))
True
两个张量的元素之间互相比较,每个比较返回一个布尔值,最终返回一个与被比较元素形状相同的张量:
-
torch.eq(input, other, out=None)
:如果input
中的元素等于output
中的对应元素,返回True
。 -
torch.ge(input, other, out=None)
:如果input
中的元素大于等于output
中的对应元素,返回True
。 -
torch.gt(input, other, out=None)
:如果input
中的元素大于output
中的对应元素,返回True
。 -
torch.le(input, other, out=None)
:如果input
中的元素小于等于output
中的对应元素,返回True
。 -
torch.lt(input, other, out=None)
:如果input
中的元素小于output
中的对应元素,返回True
。
>>> a = torch.tensor([[1, 3, 96, 97], [98, 99, 7, 6]])
>>> c = torch.tensor([[1, 3, 5, 7], [98, 99, 100, 101]])
>>> torch.eq(a, c)
tensor([[ True, True, False, False],
[ True, True, False, False]])
4. 随机函数
所有随机函数都有一个 generator
变量用于指定随机种子。
-
torch.manual_seed(seed)
:设置随机种子。 -
torch.bernoulli(input, *, generator=None, out=None)
:生成服从伯努利分布(二项式分布)的张量。
>>> a = torch.empty(2, 2).uniform_(0, 1)
>>> a
tensor([[0.0117, 0.2281],
[0.8750, 0.9974]])
>>> torch.bernoulli(a)
tensor([[0., 0.],
[1., 1.]])
-
torch.multinomial(input, num_samples, replacement=False, *, generator=None, out=None)
:生成符合多项式分布的张量。input
为多项式分布的权重,当replacement
为False
时,num_samples
的长度必须小于input
。
>>> weights = torch.tensor([1., 2., 3., 4.])
>>> torch.multinomial(weights, 10, replacement=True)
tensor([1, 2, 2, 2, 3, 2, 2, 3, 0, 2])
-
torch.normal(mean, std, size, *, out=None)
:生成服从均值为mean
,方差为std
的正态分布张量。mean
和std
可以省略一个,若想同时省略请使用torch.randn
函数。
>>> torch.normal(2, 1, [2, 2])
tensor([[1.7697, 2.2627],
[2.0743, 2.1683]])
-
torch.poisson(input *, generator=None)
:生成一个形状与input
相同,服从泊松分布[1]的张量。
>>> torch.poisson(torch.tensor([2., 2.]))
tensor([1., 4.])
-
torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
:生成一个范围为 的均匀分布的张量。
>>> torch.rand((2, 2))
tensor([[0.2255, 0.5614],
[0.7037, 0.2410]])
-
torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
:生成一个均值为 0,方差为 1 的标准正态分布的张量。
>>> torch.randn((2, 2))
tensor([[ 1.2622, -1.3420],
[-0.2331, 0.6151]])
-
torch.randint(low=0, high, size, *, generator=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
:生成一个范围为 内取整数的均匀分布的张量。
>>> torch.randint(10, (2, 2))
tensor([[6, 2],
[2, 3]])
-
torch.randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False)
:返回一个经过随机打乱顺序的张量。
>>> torch.randperm(10)
tensor([8, 9, 5, 3, 2, 1, 0, 7, 4, 6])
- 初学java之StringBuffer类的常用方法
- 初学java之大数处理
- hdu---1024Max Sum Plus Plus(动态规划)
- Go语言异步服务器框架原理和实现
- nyoj------布线问题(kruscal+求最小值)
- nyoj-----127星际之门(一)
- nyoj------20吝啬的国度
- HDUOJ-------2493Timer(数学 2008北京现场赛H题)
- go sync.Mutex 设计思想与演化过程 (一)
- HDUOJ--------A simple stone game(尼姆博弈扩展)(2008北京现场赛A题)
- HDUOJ----2485 Destroying the bus stations(2008北京现场赛A题)
- Go语言实践:从新手入门到上线真实的小型服务所遇到的那些坑
- Node.js真的无所不能?那些不适用的应用领域分析
- hdu-----2491Priest John's Busiest Day(2008 北京现场赛G)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- php解压缩zip和rar压缩包文件的方法
- laradock环境docker-compose操作详解
- laravel中的fillable和guarded属性详解
- PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
- Laravel 6 将新增为指定队列任务设置中间件的功能
- Python生成器传参数及返回值原理解析
- PHP Swoole异步MySQL客户端实现方法示例
- PHP实现微信公众号验证Token的示例代码
- Laravel框架之解决前端显示图片问题
- thinkPHP5.1框架中Request类四种调用方式示例
- Python TestSuite生成测试报告过程解析
- PHP goto语句用法实例
- laravel5.5安装jwt-auth 生成token令牌的示例
- Windows环境下安装PHP Pear的方法图文教程
- php菜单/评论数据递归分级算法的实现方法