Tensor 基本数据操作
1. 基本操作
Tensor是Pytorch的基本数据结构,Tensor具有dimension属性,也称为阶数(与矩阵的阶无关)。
每个维度(轴)有对应的长度,很多和张量相关的函数都有dim参数,指定对张量的某一维度(轴)进行操作。
0阶 - 标量 - scalor
1阶 - 向量 - vector
2阶 - 矩阵 - matrix
3阶 - 张量 - tensor
torch tensor 和numpy ndarray 操作映射表格
[todo]
import torch
import numpy as np
1.1 创建
def test_create_tensor():
"""
Function: create tensor, dtype, from_numpy()
"""
n = 4
row, col = 2, 2
# 1. 用List创建Tensor
a = torch.tensor([0, 1, 2, 3])
b = torch.tensor([[0, 1], [2, 3]])
c = torch.tensor(range(n)).reshape(row, col)
"""print
Tensor from List, a: tensor([0, 1, 2, 3]) torch.LongTensor torch.int64
Tensor from List, b:
tensor([[0, 1],
[2, 3]])
Tensor from List, c:
tensor([[0, 1],
[2, 3]])
"""
# 2. 随机Tensor, torch.randn(x, y, z)
d = torch.randn(n) # n个随机数,正态分布,
e = torch.rand(n) # n个随机数,[0,1)间均匀分布
f = torch.randperm(n) # 随机打乱整数[0, n)
"""print
随机数 正态分布, d: tensor([ 0.9517, 0.0963, -0.5927, -0.0353])
随机数 [0, 1)均匀分布, e: tensor([0.6249, 0.8082, 0.2404, 0.7206])
随机打乱 [0, n), f: tensor([0, 1, 2, 3])
"""
# 3. 全0, 全1 Tensor
g = torch.zeros(row, col)
h = torch.ones(row, col)
# 4. 对角矩阵, 只能是二维的,shape只能是int,
i = torch.eye(3) # 对角方阵
j = torch.eye(3, 4) # 对角矩阵
"""print
全0 Tensor, g:
tensor([[0., 0.],
[0., 0.]])
全1 Tensor, h:
tensor([[1., 1.],
[1., 1.]])
对角方阵, i:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
对角矩阵, j:
tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])
"""
# 5. 一维序列
k = torch.arange(start=0, end=n, step=1) # [0, n), 步长为step
l = torch.linspace(start=0, end=n, steps=2) # [0, n], 一共steps个, steps名称歧议!!
"""print
Arange Tensor:, k: tensor([0, 1, 2, 3])
Linspace Tensor:, l: tensor([0., 4.])
"""
# 6. torch.tensor <=> np.array, 若Tensor为GPU类型数据,需要转换为CPU类型[.cpu()]才能转换成ndarray
m = np.array([0, 1, 2, 3])
m1 = torch.from_numpy(m)
m2 = m1.numpy()
"""print
type(m), <class 'numpy.ndarray'>
type(m1), <class 'torch.Tensor'>
type(m2), <class 'numpy.ndarray'>
"""
# 7. 数据类型未显式指定,默认torch.int64/torch.float32
# 指定类型
# 指定数据类型, dtype=torch.float/torch.bool, tensor(), zeros(), ones()等都接受dtype参数
# 复制已有类型, type_as(), torch.IntTensor()
# 查看类型(两种不同表达方式)
# tensor.dtype, torch.float/torch.bool
# tensor.type(), string='torch.FloatTensor'/'torch.cuda.FloatTensor' 可以看出CPU/GPUtensor
n = torch.tensor([0, 1], dtype=torch.float)
o = torch.tensor([0, 1], dtype=torch.bool)
n1 = n.type_as(torch.IntTensor()) # torch.IntTensor([1])
n2 = n1.type_as(n)
"""print
n.type(): torch.FloatTensor, n.dtype: torch.float32, n.data: tensor([0., 1.])
n1.type(): torch.IntTensor, n1.dtype: torch.int32, n1.data: tensor([0, 1], dtype=torch.int32)
n2.type(): torch.FloatTensor, n2.dtype: torch.float32, n2.data: tensor([0., 1.])
o.type(): torch.BoolTensor, o.dtype: torch.bool, 0.data: tensor([False, True])
p.type: torch.IntTensor, p.dtype: torch.int32, p.data: tensor([1, 2], dtype=torch.int32)
"""
torch tensor 和numpy ndarray 结构基本一致,ndarray构建方式如下:
def test_create_ndarray():
"""
Function: np 构建 ndarray Vs torch 构建 tensor
"""
n, low = 4, 4
row, col = 2, 2
# 1. 用List创建ndarray
a = np.array([0, 1, 2, 3])
b = np.array([[0, 1], [2, 3]])
c = np.array(range(n)).reshape(row, col)
"""print
ndarray from List, a: [0 1 2 3] int64
ndarray from List, b:
[[0 1]
[2 3]]
ndarray from List, c:
[[0 1]
[2 3]]
"""
# 2. 随机ndarray, np.random.randn(x, y, z)
d = np.random.randn(n) # n个随机数,正态分布,
e = np.random.rand(n) # n个随机数,[0,1)间均匀分布
e1 = np.random.random((n)) # n个随机数,[0,1)间均匀分布, np.random.random((x, y, z)), 参数传递用tuple封装
e2 = np.random.randint(low, high=None, size=None) # n个随机整数,[0, low)/[low, high) 间的均匀分布
f = np.arange(n)
np.random.shuffle(f) # 随机打乱整数[0, n)
"""print
随机数 正态分布, d: [-0.05405188 1.32983551 -0.8320061 0.85252288]
随机数 [0, 1)均匀分布, e: [0.62507954 0.62382814 0.47105695 0.79694156]
随机打乱 [0, n), f: [3 0 2 1]
"""
# 3. 全0, 全1 Tensor
g = np.zeros((row, col))
h = np.ones((row, col))
# 4. 对角矩阵
i = np.eye(3) # 对角方阵
j = np.eye(3, 4) # 对角矩阵
"""print
全0 ndarray, g:
[[0. 0.]
[0. 0.]]
全1 ndarray, h:
[[1. 1.]
[1. 1.]]
对角方阵, i:
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
对角矩阵, j:
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]]
"""
# 5. 一维序列
k = np.arange(start=0, stop=n, step=1) # [0, n), 步长为step
l = np.linspace(start=0, stop=n, num=2) # [0, n], 一共steps个, num参数名明了
"""print
Arange Tensor:, k: [0 1 2 3]
Linspace Tensor:, l: [0. 4.]
"""
# 6. torch.tensor <=> np.array, 若Tensor为GPU类型数据,需要转换为CPU类型[.cpu()]才能转换成ndarray
m = np.array([0, 1, 2, 3])
m1 = torch.from_numpy(m)
m2 = m1.numpy()
"""print
type(m), <class 'numpy.ndarray'>
type(m1), <class 'torch.Tensor'>
type(m2), <class 'numpy.ndarray'>
"""
# 7. 数据类型未显式指定,默认np.int64/np.float64
# 指定类型np.float/np.bool
# 指定数据类型, dtype=xxx, array(), zeros(), ones()等都接受dtype参数
# 复制已有类型, astype(xxx),
# 查看类型(两种不同表达方式)
# ndarray.dtype, return xxxx
n = np.array([0, 1], dtype=np.float)
o = np.array([0, 1], dtype=np.bool)
n1 = n.astype(np.int32) # 没有np.astype, n2 = n1.astype(n)
print("n.dtype: {}, n data: {} ".format(n.dtype, n))
print("n1.dtype: {}, n1 data: {} ".format(n1.dtype, n1))
print("o.dtype: {}, 0 data: {}".format(o.dtype, o))
"""print
n.dtype: float64, n data: [0. 1.]
n1.dtype: int32, n1 data: [0 1]
o.dtype: bool, 0 data: [False True]
"""
1.2 索引, 切片, cat, stack, reshape, transpos, squeeze, flatten
def test_shape_operate():
"""
Function: 索引、切片、拼接、堆叠、reshape(), transpos(), squeeze()
"""
a = torch.randn(4, 5)
# 1. 索引,取出某轴/某分量
# 1.1 index_select(), index 1-D IntTensor/LongTensor
b1 = torch.index_select(a, dim=0, index=torch.tensor([0, 2])) # [4, 5] -> [2, 5]
b2 = torch.index_select(a, dim=1, index=torch.tensor([0, 2])) # [4, 5] -> [4, 2]
# 1.2 np风格下标索引
b3 = a[[0, 2], :] # [4, 5] -> [2, 5]
b4 = a[:, [0, 2]] # [4, 5] -> [4, 2]
# 1.3 masked_select(a, mask), a.shape 和 mask.shape 符合广播规范即可, boolen index
masked_a = a > 0 # [4, 5]
masked_a2 = a.sum(dim=1, keepdim=True) > 0 # [4, 1]
b5 = torch.masked_select(a, mask=masked_a) # [4, 5] -> [k] 1-D Tensor
b6 = torch.masked_select(a, mask=masked_a2) # [4, 5] -> [k * 5], 配合reshape 可以实现用bool mask index行
"""print
[origin] a.shape: torch.Size([4, 5]), a.data:
tensor([[-0.1340, -1.0141, -0.4921, 0.5482, -0.8680],
[ 1.1184, 0.3712, -0.2858, 2.2291, -1.0631],
[ 0.8453, 2.1079, -0.8402, 0.2716, 1.2784],
[-0.9252, 0.0023, 0.5246, -1.1401, -1.0689]])
[index_select] b1.shape: torch.Size([2, 5]), b1.data:
tensor([[-0.1340, -1.0141, -0.4921, 0.5482, -0.8680],
[ 0.8453, 2.1079, -0.8402, 0.2716, 1.2784]])
[index_select] b2.shape: torch.Size([4, 2]), b2.data:
tensor([[-0.1340, -0.4921],
[ 1.1184, -0.2858],
[ 0.8453, -0.8402],
[-0.9252, 0.5246]])
[index_select] b3.shape: torch.Size([2, 5]), b3.data:
tensor([[-0.1340, -1.0141, -0.4921, 0.5482, -0.8680],
[ 0.8453, 2.1079, -0.8402, 0.2716, 1.2784]])
[index_select] b4.shape: torch.Size([4, 2]), b4.data:
tensor([[-0.1340, -0.4921],
[ 1.1184, -0.2858],
[ 0.8453, -0.8402],
[-0.9252, 0.5246]])
[masked_select] masked_a.shape: torch.Size([4, 5]), masked_a.data:
tensor([[False, False, False, True, False],
[ True, True, False, True, False],
[ True, True, False, True, True],
[False, True, True, False, False]])
[masked_select] masked_a2.shape: torch.Size([4, 1]), masked_a2.data:
tensor([[False],
[ True],
[ True],
[False]])
[masked_select] b5.shape: torch.Size([10]), b5.data:
tensor([0.5482, 1.1184, 0.3712, 2.2291, 0.8453, 2.1079, 0.2716, 1.2784, 0.0023,
0.5246])
[masked_select] b6.shape: torch.Size([10]), b6.data:
tensor([ 1.1184, 0.3712, -0.2858, 2.2291, -1.0631, 0.8453, 2.1079, -0.8402,
0.2716, 1.2784])
"""
# 2. 切块, tuple(trunk0, truank1, ....), 向上取整,最后一块比较小
a = torch.randn(5, 4)
c1 = torch.chunk(a, chunks=2) # ((3, 4), (2, 4))
c2 = torch.chunk(a, chunks=2, dim=1) # ((5, 2), (5, 2))
c3 = torch.split(a, split_size_or_sections=2, dim=0) # ((2, 4), (2, 4), (1, 4))
c4 = torch.split(a, split_size_or_sections=[1, 4], dim=0) # ((1, 4), (4, 4))
"""print
[origin] a.shape: torch.Size([5, 4])
[chunk] len(c1): 2, c1[0].shape: torch.Size([3, 4]), c1[1].shape: torch.Size([2, 4])
[chunk] len(c2): 2, c2[0].shape: torch.Size([5, 2]), c2[1].shape: torch.Size([5, 2])
[split] len(c3): 3, c3[0].shape: torch.Size([2, 4]), c3[1].shape: torch.Size([2, 4]), cd[2],shape: torch.Size([1, 4])
[split] len(c4): 2, c4[0].shape: torch.Size([1, 4]), c4[1].shape: torch.Size([4, 4])
"""
# 3. 拼接cat() - 不扩张维度,
a = torch.randn(2, 3)
d1 = torch.cat([a, a], dim=0) # [4, 3]
d2 = torch.cat([a, a], dim=1) # [2, 6]
# 堆叠stack() - 扩张维度
d3 = torch.stack([a, a], dim=0) # [2, 2, 3]
d4 = torch.stack([a, a], dim=2) # [2, 3, 2] 很难看出原来张量的样子了[2, 3, 1]
"""print
[origin] a.shape: torch.Size([2, 3]), a.data:
tensor([[ 0.9315, -0.8230, -0.4260],
[ 0.6940, -0.6632, -0.0699]])
[cat] d1.shape: torch.Size([4, 3]), d1.data:
tensor([[ 0.9315, -0.8230, -0.4260],
[ 0.6940, -0.6632, -0.0699],
[ 0.9315, -0.8230, -0.4260],
[ 0.6940, -0.6632, -0.0699]])
[cat] d2.shape: torch.Size([2, 6]), d2.data:
tensor([[ 0.9315, -0.8230, -0.4260, 0.9315, -0.8230, -0.4260],
[ 0.6940, -0.6632, -0.0699, 0.6940, -0.6632, -0.0699]])
[stack] d3.shape: torch.Size([2, 2, 3]), d3.data:
tensor([[[ 0.9315, -0.8230, -0.4260],
[ 0.6940, -0.6632, -0.0699]],
[[ 0.9315, -0.8230, -0.4260],
[ 0.6940, -0.6632, -0.0699]]])
[stack] d4.shape: torch.Size([2, 3, 2]), d4.data:
tensor([[[ 0.9315, 0.9315],
[-0.8230, -0.8230],
[-0.4260, -0.4260]],
[[ 0.6940, 0.6940],
[-0.6632, -0.6632],
[-0.0699, -0.0699]]])
"""
# 4. .reshape()
a = torch.randn(2, 1, 3)
e = torch.reshape(a, shape=(2, 3)) # a.rehape(2, 3)
"""print
[origin] a.shape: torch.Size([2, 1, 3]), a.data:
tensor([[[ 1.7180, -0.3074, 0.4583]],
[[-1.6315, 1.0407, 0.1717]]])
[reshape] e.shape: torch.Size([2, 3]), e.data:
tensor([[ 1.7180, -0.3074, 0.4583],
[-1.6315, 1.0407, 0.1717]])
"""
# 5. .transpose()转置, 仅仅影响了张量的形状和步长
f1 = torch.transpose(a, dim0=0, dim1=1) # [2, 1, 3] -> [1, 2, 3]
f2 = torch.transpose(a, dim0=1, dim1=2) # [2, 1, 3] -> [2, 3, 1]
"""print
[origin] a.shape: torch.Size([2, 1, 3]), a.data:
tensor([[[ 1.7180, -0.3074, 0.4583]],
[[-1.6315, 1.0407, 0.1717]]])
[transpose] f1.shape: torch.Size([1, 2, 3]), f1.data:
tensor([[[ 1.7180, -0.3074, 0.4583],
[-1.6315, 1.0407, 0.1717]]])
[transpose] f2.shape: torch.Size([2, 3, 1]), f2.data:
tensor([[[ 1.7180],
[-0.3074],
[ 0.4583]],
[[-1.6315],
[ 1.0407],
[ 0.1717]]])
"""
# 6. .squeeze(), .unsqueeze()
g1 = torch.squeeze(a, dim=1) # dim=None, 压缩所有长度为1的维度
g2 = torch.unsqueeze(g1, dim=1) # 扩张指定的维度长度为1
"""print
[origin] a.shape: torch.Size([2, 1, 3]), a.data:
tensor([[[ 1.7180, -0.3074, 0.4583]],
[[-1.6315, 1.0407, 0.1717]]])
[squeeze] g1.shape: torch.Size([2, 3]), g1.data:
tensor([[ 1.7180, -0.3074, 0.4583],
[-1.6315, 1.0407, 0.1717]])
[unsqueeze] g2.shape: torch.Size([2, 1, 3]), g2.data:
tensor([[[ 1.7180, -0.3074, 0.4583]],
[[-1.6315, 1.0407, 0.1717]]])
"""
# 7. flatten(input, start_dim=0, end_dim=-1)
h0 = torch.arange(8).reshape(2, 2, 2)
h1 = torch.flatten(h0, start_dim=1) # [2, 4]
h2 = torch.flatten(h0) # [8]
"""print
[origin] h0.shape: torch.Size([2, 2, 2]), h0.data:
tensor([[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]])
[flatten] h1.shape: torch.Size([2, 4]), h1.data:
tensor([[0, 1, 2, 3],
[4, 5, 6, 7]])
[flatten] h2.shape: torch.Size([8]), h2.data:
tensor([0, 1, 2, 3, 4, 5, 6, 7])
"""
# np demo
h0 = np.arange(8).reshape(2, 2, 2)
h1 = np.matrix.flatten(h0, order='K') # [2, 4]
h2 = np.matrix.flatten(h0) # [8]
# Parameters: (没搞懂)
# order{‘C’, ‘F’, ‘A’, ‘K’}, optional
# ‘C’ means to flatten in row-major (C-style) order.
# ‘F’ means to flatten in column-major (Fortran-style) order.
# ‘A’ means to flatten in column-major order if m is Fortran contiguous in memory, row-major order otherwise.
# ‘K’ means to flatten m in the order the elements occur in memory. The default is ‘C’.
"""print
[origin] array h0.shape: (2, 2, 2), h0.data:
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
[flatten] array h1.shape: (8,), h1.data:
[0 1 2 3 4 5 6 7]
[flatten] array h2.shape: (8,), h2.data:
[0 1 2 3 4 5 6 7]
"""
1.3 storage, device
def test_storage():
"""
Function:
1. 同一块内存 可以被多个张量'索引',从不同的地方引用, points 和 second_point 是不同的索引。
'索引'具有三个属性:
大小(size): 每个维度上有多少个元素
偏移(storage offset):每个元素与第一个元素之间的偏移
步长(stride):沿着存储的每个维度获取下一个元素需要跳过的元素数量
2. 更改子张量 会影响原张量
3. 连续张量 沿最右边的维开始存放在内存的张量,用tensor.is_contiguous判断
"""
points = torch.tensor([[1.0, 4.0], [2.0, 5.0], [3.0, 6.0]]) # [3, 2]
second_point = points[1]
print("[points] size(): {}, torage_offset(): {}, stride(): {}, is_contiguous: {}".format(
points.size(), points.storage_offset(), points.stride(), points.is_contiguous()))
print("[second points] size(): {}, torage_offset(): {}, stride(): {}, is_contiguous: {}".format(
second_point.size(), second_point.storage_offset(), second_point.stride(), second_point.is_contiguous()))
"""print
[points] size(): torch.Size([3, 2]), torage_offset(): 0, stride(): (2, 1), is_contiguous: True
[second points] size(): torch.Size([2]), torage_offset(): 2, stride(): (1,), is_contiguous: True
"""
def test_device():
"""
Function:
1. tensor 创建后设备转换
返回GPU张量副本: tensor.cuda() / tensor.cuda(0),
返回CPU张量副本: tensor.cpu()
device属性指定: tensor.to(device="cuda"), 'cuda'/'cpu'/'gpu:0'/'cpu:0'
3. 不同设备中的张量不能直接参与同一个运算
"""
print("orch.cuda.is_available(): {}".format(torch.cuda.is_available())) # False
print("torch.cuda.device_count(): {}".format(torch.cuda.device_count())) # 0
# print(torch.cuda.current_device())
# 自适应设置device
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
data = torch.tensor([[1, 2], [3, 4]], device=device)
1.4 广播机制
def test_broadcast():
"""
Function:
torch 很多操作都支持广播机制:无需显示复制数据,可以将参与运算的张量自动扩展为相同的形状
广播三条法则如下:
"""
# 1. tensor + scalar
a1 = torch.arange(3)
r1 = a1 + 3
"""prin
[broadcast] tensor + scalar: tensor([0, 1, 2]) + 3 = tensor([3, 4, 5])
"""
# 2. 两个tensor dims数量一致,且其中存在长度为1的轴
a1 = torch.arange(12).reshape((3, 4)) # [3, 4]
a2 = torch.ones(1, 4) # [1, 4]
r1 = a1 + a2
"""print
[broadcast] a1.shape: torch.Size([3, 4]), a1.data:
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
[broadcast] a2.shape: torch.Size([1, 4]), a2.data:
tensor([[1., 1., 1., 1.]])
[broadcast] r1.shape: torch.Size([3, 4]), r1.data:
tensor([[ 1., 2., 3., 4.],
[ 5., 6., 7., 8.],
[ 9., 10., 11., 12.]])
"""
# 3. 两个tensor dims数量不一致,尾部对齐后,某个tensor较短
a1 = torch.arange(6).reshape(3, 2) # [3, 2]
a2 = torch.arange(4, 6) # [2]
r1 = a1 + a2
"""print
[broadcast] a1.shape: torch.Size([3, 2]), a1.data:
tensor([[0, 1],
[2, 3],
[4, 5]])
[broadcast] a2.shape: torch.Size([2]), a2.data:
tensor([4, 5])
[broadcast] r1.shape: torch.Size([3, 2]), r1.data:
tensor([[ 4, 6],
[ 6, 8],
[ 8, 10]])
"""
2. Tensor 数据分析统计量
数据统计功能: 求和、均值,方差
2.1 加减, 乘除, 幂pow()
def test_cal():
"""
Function:
数据 a shape = [x, y, z]
tensor 对应dim = 0, 1, 2
ndarray对应axis = 0, 1, 2
"""
# 1. Tensor求和
a = torch.ones(2, 3) # a.shape = (2, 3), dim=0, 是长度为2的轴
sum0 = torch.sum(a, dim=0) # [3], 列和, 沿着地零个轴求和
sum1 = torch.sum(a, dim=1) # [2], 行和
sum2 = torch.sum(a) # [1], 全部和
"""print
[Tensor origin] a.shape: torch.Size([2, 3]), a.data:
tensor([[1., 1., 1.],
[1., 1., 1.]])
[Tensor col sum] sum0.shape: torch.Size([3]), sum0.data:
tensor([2., 2., 2.])
[Tensor row sum] sum1.shape: torch.Size([2]), sum1.data:
tensor([3., 3.])
[Tensor total sum] sum2.shape: torch.Size([]), sum2.data:
6.0
"""
# np demo - Ndarra求和
a = np.ones((2, 3)) # a.shape = (2, 3), dim=0, 是长度为2的轴
sum0 = np.sum(a, axis=0) # [3], 列和, 沿着地零个轴求和
sum1 = np.sum(a, axis=1) # [2], 行和
sum2 = np.sum(a) # [1], 全部和
"""print
[Ndarray origin] a.shape: (2, 3), a.data:
[[1. 1. 1.]
[1. 1. 1.]]
[Ndarray col sum] sum0.shape: (3,), sum0.data:
[2. 2. 2.]
[Ndarray row sum] sum1.shape: (2,), sum1.data:
[3. 3.]
[Ndarray total sum] sum2.shape: (), sum2.data:
6.0
"""
# 2. elements wise mul
a = torch.ones(2, 3) # [2, 3]
b = a * 2 # [2, 3], 广播机制
mul1 = a * b
mul2 = np.multiply(a, b)
"""print
[Tensor] a.shape: torch.Size([2, 3]), a.data:
tensor([[1., 1., 1.],
[1., 1., 1.]])
[Tensor] b.shape: torch.Size([2, 3]), b.data:
tensor([[2., 2., 2.],
[2., 2., 2.]])
[Tensor] mul1.shape: torch.Size([2, 3]), mul1.data:
tensor([[2., 2., 2.],
[2., 2., 2.]])
[Tensor] mul2.shape: torch.Size([2, 3]), mul2.data:
tensor([[2., 2., 2.],
[2., 2., 2.]])
"""
# np demo
a = np.ones((2, 3))
b = a * 2
mul1 = a * b
mul2 = np.multiply(a, b)
"""print
[Ndarray] a.shape: (2, 3), a.data:
[[1. 1. 1.]
[1. 1. 1.]]
[Ndarray] b.shape: (2, 3), b.data:
[[2. 2. 2.]
[2. 2. 2.]]
[Ndarray] mul1.shape: (2, 3), mul1.data:
[[2. 2. 2.]
[2. 2. 2.]]
[Ndarray] mul2.shape: (2, 3), mul2.data:
[[2. 2. 2.]
[2. 2. 2.]]
"""
# 3. 矩阵乘法 两个矩阵需要满足行列尺寸关系
t1 = torch.ones(2, 3)
t2 = torch.arange(6).reshape(3, 2).type_as(t1)
mul = torch.matmul(t1, t2) # [2, 3]
"""print
[Tensor] t1.shape: torch.Size([2, 3]), t1.data:
tensor([[1., 1., 1.],
[1., 1., 1.]])
[Tensor] t2.shape: torch.Size([3, 2]), t2.data:
tensor([[0., 1.],
[2., 3.],
[4., 5.]])
[Tensor] mul.shape: torch.Size([2, 2]), mul.data:
tensor([[6., 9.],
[6., 9.]])
"""
# np demo
t1 = np.ones((2, 3))
t2 = np.arange(6).reshape(3, 2).astype(np.float32)
mul = np.matmul(t1, t2) # [2, 3]
"""print
[Ndarray] t1.shape: (2, 3), t1.data:
[[1. 1. 1.]
[1. 1. 1.]]
[Ndarray] t2.shape: (3, 2), t2.data:
[[0. 1.]
[2. 3.]
[4. 5.]]
[Ndarray] mul.shape: (2, 2), mul.data:
[[6. 9.]
[6. 9.]]
"""
# 4. 幂运算 torch.pow()
a = torch.arange(6).reshape(2, 3)
e = torch.arange(6).reshape(2, 3)
p0 = torch.pow(a, 2) # a^2
p1 = torch.pow(a, e) # a^e
"""print
[Tensor] a.shape: torch.Size([2, 3]), a.data:
tensor([[0, 1, 2],
[3, 4, 5]])
[Tensor] e.shape: torch.Size([2, 3]), e.data:
tensor([[0, 1, 2],
[3, 4, 5]])
[Tensor] p0.shape: torch.Size([2, 3]), p0.data:
tensor([[ 0, 1, 4],
[ 9, 16, 25]])
[Tensor] p1.shape: torch.Size([2, 3]), p1.data:
tensor([[ 1, 1, 4],
[ 27, 256, 3125]])
"""
# np demo
a = np.arange(6).reshape(2, 3)
e = np.arange(6).reshape(2, 3)
p0 = np.power(a, 2) # a^2
p1 = np.power(a, e) # a^e
"""print
[Ndarray] a.shape: (2, 3), a.data:
[[0 1 2]
[3 4 5]]
[Ndarray] e.shape: (2, 3), e.data:
[[0 1 2]
[3 4 5]]
[Ndarray] p0.shape: (2, 3), p0.data:
[[ 0 1 4]
[ 9 16 25]]
[Ndarray] p1.shape: (2, 3), p1.data:
[[ 1 1 4]
[ 27 256 3125]]
"""
2.2 均值、方差
numpy 与torch .std()计算公式差别
numpy:
s
t
d
=
1
N
∑
i
=
1
N
(
x
i
−
x
‾
)
2
std=\sqrt{\frac{1}{N}\sum_{i=1}^N(x_i-\overline{x})^2}
std=N1i=1∑N(xi−x)2
torch:
s
t
d
=
1
N
−
1
∑
i
=
1
N
(
x
i
−
x
‾
)
2
std=\sqrt{\frac{1}{N-1}\sum_{i=1}^N(x_i-\overline{x})^2}
std=N−11i=1∑N(xi−x)2
4.1 torch tensor.mean() .std()
>a.mean() # a为Tensor型变量
>a.std()
>torch.mean(a) # a为Tensor型变量
>torch.std(a)
>>> torch.Tensor([1,2,3,4,5])
tensor([1., 2., 3., 4., 5.])
>>> a=torch.Tensor([1,2,3,4,5])
>>> a.mean()
tensor(3.)
>>> torch.mean(a)
tensor(3.)
>>> a.std()
tensor(1.5811)
>>>> torch.std(a)
tensor(1.5811) # 注意和numpy求解的区别
torch.mean(input) 输出input 各个元素的的均值,不指定任何参数就是所有元素的算术平均值,指定参数可以计算每一行或者 每一列的算术平均数
> a = torch.randn(4, 4)
>>tensor([[-0.3841, 0.6320, 0.4254, -0.7384],
[-0.9644, 1.0131, -0.6549, -1.4279],
[-0.2951, -1.3350, -0.7694, 0.5600],
[ 1.0842, -0.9580, 0.3623, 0.2343]])
# 每一行的平均值
> torch.mean(a, 1, True) #dim=true,计算每一行的平均数,输出与输入有相同的维度:两维度(4,1)
>>tensor([[-0.0163],
[-0.5085],
[-0.4599],
[ 0.1807]])
> torch.mean(a, 1) # 不设置dim,默认计算每一行的平均数,内嵌了一个torch.squeeze(),将数值为1的维度压缩(4,)
>>tensor([-0.0163, -0.5085, -0.4599, 0.1807])
4.2 numpy array.mean() .std()
>a.mean() # a为np array型变量
>a.std()
>numpy.mean(a) # a为np array型变量
>numpy.std(a)
>>> import numpy
>>> c=numpy.array([1,2,3,4,5])
>>> c.mean()
3.0
>>> numpy.mean(c)
3.0
>>> c.std()
1.4142135623730951
>>> numpy.std(c)
1.4142135623730951
>>> d=numpy.array([1,1,1,1])
>>> d.mean()
1.0
>>> d.std()
0.0
2.3 最大/最小/非零 值索引
tensor.argmax()
tensor.argmax(dim)
返回tensor最大的值对应的index。dim 不设置-全部元素的最大值,dim = 0 每列的最大值,dim = 1每行的最大值。
>>> a = torch.randn(3,4)
>>> a
tensor([[ 1.1360, -0.5890, 1.8444, 0.6960],
[ 0.3462, -1.1812, -1.5536, 0.4504],
[-0.4464, -0.5600, -0.1655, 0.3914]])
>>> a.argmax()
tensor(2) # 按行拉成一维向量,对应的小次奥
>>> a.argmax(dim = 0)
tensor([0, 2, 0, 0]) # 每一列最大值的索引
>>> a.argmax(dim = 1)
tensor([2, 3, 3]) # 每一行最大值索引
8.2 tensor.argmin()
与tensor.argmax() 用法相同,在多分类问题求准确率时会用到。
output_labels = outputs.argmax(dim = 1)
train_acc = (output_labels == labels).float().mean()
8.3 tensor.nonzero()
返回非零元素对应的下标
>>> a = torch.tensor([[1,0],[0,3]])
>>> a.nonzero()
tensor([[0, 0],
[1, 1]])
>>> a= torch.tensor([1,2,3,0,4,5,0])
>>> a.nonzero()
tensor([[0],
[1],
[2],
[4],
[5]])
Reference: