Pytorch第一课:package-torch(1)之张量初识

微博:https://weibo.com/wangxiaocaoai/profile?rightmod=1&wvr=6&mod=personinfo
微信公众号:搜索"AI躁动街"


本节要点:

1 张量

2 创建张量的方式

3 张量的索引,切片,连接,换位等操作

4 随机抽样的操作

5 序列化(保存与加载)

6 并行化

1 张量Tensor

1.1 判断是否为张量

torch.is_tensor(obj) 如果obj 是一个pytorch张量,则返回True

import torch

# 创建一个普通数值
a = 1
print(torch.is_tensor(a))

# 创建一个float类型的tensor
b = torch.FloatTensor(a)
print(torch.is_tensor(b))

False
True

1.2 判断是否为一维数组

torch.Storage是单个数据类型的连续的一维数组,每个torch.Tensor都具有相同数据类型的相应存储。他是torch.tensor底层数据结构,他除了像Tensor一样定义数值,还可以直接把文件映射到内存中进行操作

torch.is_storage(obj),如何obj 是一个pytorch storage对象,则返回True

# 创建torch.storage,共有以下8中类型
torch.FloatStorage([1,2,3,4,5])
torch.ByteStorage([1,2,3,4,5])
torch.ShortStorage([1,2,3,4,5])
torch.IntStorage([1,2,3,4,5])
torch.LongStorage([1,2,3,4,5])
torch.FloatStorage([1,2,3,4,5])
torch.DoubleStorage([1,2,3,4,5])
torch.ShortStorage([1,2,3,4,5])

# 判断是否为torch.storage
# 随机创建长度为5的一维数组
a = torch.FloatStorage(5)
print(a)
# 判断
print(torch.is_storage(a))
 0.0
 -0.0
 821.166015625
 4.657746965897047e-10
 5.000000953674316
[torch.FloatStorage of size 5]
True

1.3 设置默认的tensor类型

torch.set_default_tensor_type(torch.FloatTensor)
torch.get_default_dtype()
torch.float32

1.4 获取张量中元素的个数

# 随机创建1*2*3维的tensor
a = torch.randn(1,2,3)
print(a)

# 输出元素个数
print(torch.numel(a))
tensor([[[-1.9520, -1.2041, -0.8372],
         [-0.8017, -0.5982,  0.5224]]])
6

1.5 设置打印选项

完全参考numpy

参数:

precision – 浮点数输出的精度位数 (默认为8 )

threshold – 阈值,触发汇总显示而不是完全显示(repr)的数组元素的总数 (默认为1000)

edgeitems – 汇总显示中,每维(轴)两端显示的项数(默认值为3)

linewidth – 用于插入行间隔的每行字符数(默认为80)。Thresholded matricies will ignore this parameter.

profile – pretty打印的完全默认值。 可以覆盖上述所有选项 (默认为short, full)

torch.set_printoptions(precision=None, threshold=None, edgeitems=None, linewidth=None, profile=None)

2 创建操作 Creation Ops

2.1 创建对角位置为1的2维张量

torch.eye(n, m=None, out=None)

参数:

n (int ) – 行数

m (int, optional) – 列数.如果为None,则默认为n

out (Tensor, optinal) - Output tensor

a = torch.eye(4, 4)
print(a)
tensor([[ 1.,  0.,  0.,  0.],
        [ 0.,  1.,  0.,  0.],
        [ 0.,  0.,  1.,  0.],
        [ 0.,  0.,  0.,  1.]])

2.2 将numpy.ndarray 转换为pytorch的 Tensor

返回的张量tensor和numpy的ndarray共享同一内存空间。修改一个会导致另外一个也被修改。返回的张量不能改变大小。

import numpy as np

# 互换
a = np.array([1,2,3,4])
print('a:',a)
t = torch.from_numpy(a)
print('t:', t)

# 共享内存,修改一个,另一个改变
t[0] = -10
print('a:',a)

# tensor转numpy
 t_a = t.numpy()
a: [1 2 3 4]
t: tensor([ 1,  2,  3,  4])
a: [-10   2   3   4]

2.3 linspace创建1维张量:等差数列

包含在区间start 和 end 上均匀间隔的steps个点。 输出1维张量的长度为steps。

参数:

start (float) – 序列的起始点

end (float) – 序列的最终值

steps (int) – 在start 和 end间生成的样本数

out (Tensor, optional) – 结果张量

a = torch.linspace(start=1, end=20, steps=10)
print(a)
tensor([  1.0000,   3.1111,   5.2222,   7.3333,   9.4444,  11.5556,
         13.6667,  15.7778,  17.8889,  20.0000])

2.4 logspace创建1维张量:等比数列

返回一个1维张量,包含在区间 10start 和 10end上以对数刻度均匀间隔的steps个点。 输出1维张量的长度为steps。

参数:

start (float) – 序列的起始点

end (float) – 序列的最终值

steps (int) – 在start 和 end间生成的样本数

out (Tensor, optional) – 结果张量

a = torch.logspace(start=-10, end=10, steps=5)
print(a)
tensor([ 1.0000e-10,  1.0000e-05,  1.0000e+00,  1.0000e+05,  1.0000e+10])

2.5 创建全为1的张量

torch.ones(*sizes, out=None) → Tensor

参数:

sizes (int…) – 整数序列,定义了输出形状

out (Tensor, optional) – 结果张量

a = torch.ones(3, 4)
print(a)
tensor([[ 1.,  1.,  1.,  1.],
        [ 1.,  1.,  1.,  1.],
        [ 1.,  1.,  1.,  1.]])

2.6 创建0-1随机张量

回一个张量,包含了从区间[0,1)的均匀分布中抽取的一组随机数,形状由可变参数sizes 定义。

参数:

sizes (int…) – 整数序列,定义了输出形状

out (Tensor, optinal) - 结果张量 例子:

a = torch.rand(3, 4)
print(a)
tensor([[ 0.4617,  0.3783,  0.5476,  0.6975],
        [ 0.9122,  0.4346,  0.7784,  0.4307],
        [ 0.6557,  0.1655,  0.3513,  0.8785]])

2.7 创建标准正态分布随机张量

返回一个张量,包含了从标准正态分布(均值为0,方差为 1,即高斯白噪声)中抽取一组随机数,形状由可变参数sizes定义。

参数:

sizes (int…) – 整数序列,定义了输出形状

out (Tensor, optinal) - 结果张量

a = torch.randn(3, 4)
print(a)
tensor([[ 0.4216,  0.0764,  0.5121, -0.6687],
        [-0.2173,  1.3139, -1.9322, -0.9506],
        [-0.1711, -0.4935, -0.0649, -0.0772]])

2.8 创建随机整数排列

给定参数n,返回一个从0 到n -1 的随机整数排列。

参数:

n (int) – 上边界(不包含)

a = torch.randperm(10)
print(a)
tensor([ 6,  0,  7,  3,  2,  1,  8,  5,  4,  9])

2.9 创建有序序列(前闭后开)

torch.arange(start, end, step=1, out=None) → Tensor

返回一个1维张量,长度为 floor((end−start)/step)。包含从start到end,以step为步长的一组序列值(默认步长为1)。

参数:

start (float) – 序列的起始点

end (float) – 序列的终止点

step (float) – 相邻点的间隔大小

out (Tensor, optional) – 结果张量

a = torch.arange(10, 20, 2)
print(a)
tensor([ 10.,  12.,  14.,  16.,  18.])

2.10 创建有序序列(前闭后闭)

警告:建议使用函数 torch.arange()

a = torch.range(10, 20, 2)
print(a)
tensor([ 10.,  12.,  14.,  16.,  18.,  20.])

2.11 创建全为0的张量

返回一个全为标量 0 的张量,形状由可变参数sizes 定义。

参数:

sizes (int…) – 整数序列,定义了输出形状

out (Tensor, optional) – 结果张量

a = torch.zeros(3, 4)
print(a)
tensor([[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]])

3 索引,切片,连接,换位Indexing, Slicing, Joining, Mutating Ops

3.1 张量连接操作

torch.cat(inputs, dimension=0) → Tensor

参数:

inputs (sequence of Tensors) – 可以是任意相同Tensor 类型的python 序列

dimension (int, optional) – 沿着此维连接张量序列。

a = torch.randn(2, 4)
b = torch.randn(2, 4)
a_b_0 = torch.cat((a, b), 0)
a_b_1 = torch.cat((a, b), 1)

print(a)
print(b)
print(a_b_0)
print(a_b_1)

tensor([[ 0.6137,  0.1970, -0.2391, -0.9429],
        [ 1.8466,  1.6018,  1.4970,  0.2305]])
tensor([[ 0.7776,  0.1084, -0.8127, -1.3126],
        [ 1.1053,  0.3898,  0.1087, -0.4667]])
tensor([[ 0.6137,  0.1970, -0.2391, -0.9429],
        [ 1.8466,  1.6018,  1.4970,  0.2305],
        [ 0.7776,  0.1084, -0.8127, -1.3126],
        [ 1.1053,  0.3898,  0.1087, -0.4667]])
tensor([[ 0.6137,  0.1970, -0.2391, -0.9429,  0.7776,  0.1084, -0.8127,
         -1.3126],
        [ 1.8466,  1.6018,  1.4970,  0.2305,  1.1053,  0.3898,  0.1087,
         -0.4667]])

3.2 张量分块操作

torch.chunk(tensor, chunks, dim=0)

在给定维度(轴)上将输入张量进行分块儿。

参数:

tensor (Tensor) – 待分块的输入张量

chunks (int) – 分块的个数

dim (int) – 沿着此维度进行分块

a = torch.randn(4, 6)
a_chunk = torch.chunk(a, 2, 0)
print('a_chunk:', a_chunk)
print('type:', type(a_chunk))  # 返回的是一个tuple
a_chunk: (tensor([[-0.9597, -0.6585, -1.1580,  0.2790, -0.5184,  1.8365],
        [ 0.5250,  1.1513, -0.8885,  0.1913,  1.2182, -0.0828]]), tensor([[ 2.3396, -0.6564,  0.2860, -1.0066, -0.1558,  0.4544],
        [-1.4732,  0.6251, -1.3311,  2.0909, -0.5014,  1.0714]]))
type: 
a_chunk = torch.chunk(a, 2, 1) # 在维度=1上进行分块
print('a_chunk:', a_chunk)
a_chunk: (tensor([[-0.9597, -0.6585, -1.1580],
        [ 0.5250,  1.1513, -0.8885],
        [ 2.3396, -0.6564,  0.2860],
        [-1.4732,  0.6251, -1.3311]]), tensor([[ 0.2790, -0.5184,  1.8365],
        [ 0.1913,  1.2182, -0.0828],
        [-1.0066, -0.1558,  0.4544],
        [ 2.0909, -0.5014,  1.0714]]))

3.3 张量聚合操作

torch.gather(input, dim, index, out=None) → Tensor

其实是根据dim和index去取出input中的元素

参数:

input (Tensor) – 源张量

dim (int) – 索引的轴

index (LongTensor) – 聚合元素的下标

out (Tensor, optional) – 目标张量

a = torch.Tensor([[1, 2, 3],[4, 5, 6]])
print(a)
tensor([[ 1.,  2.,  3.],
        [ 4.,  5.,  6.]])
# 其实就是在维度1上取出下标为[[0, 1], [2, 0]]的a中的元素
a_gather = torch.gather(a, 1, torch.LongTensor([[0, 1], [2, 0]]))
print(a_gather)
tensor([[ 1.,  3.,  2.],
        [ 5.,  6.,  4.]])
# 换成0维度感受一下
a_gather = torch.gather(a, 0, torch.LongTensor([[1, 0, 1], [0, 1, 1]]))
print(a_gather)
tensor([[ 4.,  2.,  6.],
        [ 1.,  5.,  6.]])

3.4 根据索引切割张量

沿着指定维度对输入进行切片,取index中指定的相应项(index为一个LongTensor),然后返回到一个新的张量, 返回的张量与原始张量_Tensor_有相同的维度(在指定轴上)。

注意: 返回的张量不与原始张量共享内存空间。

torch.index_select(input, dim, index, out=None) → Tensor

参数:

input (Tensor) – 输入张量

dim (int) – 索引的轴

index (LongTensor) – 包含索引下标的一维张量

out (Tensor, optional) – 目标张量

a = torch.rand(4, 6)
print(a)
tensor([[ 0.6482,  0.9216,  0.7734,  0.5927,  0.9646,  0.5529],
        [ 0.9330,  0.5138,  0.4323,  0.5836,  0.2940,  0.8188],
        [ 0.8988,  0.1239,  0.6988,  0.0342,  0.3798,  0.8176],
        [ 0.4482,  0.5771,  0.9904,  0.6088,  0.9014,  0.6419]])
# 在维度1上切割
a_select = torch.index_select(a, 1, torch.LongTensor([0, 3]))
print(a_select)
tensor([[ 0.6482,  0.5927],
        [ 0.9330,  0.5836],
        [ 0.8988,  0.0342],
        [ 0.4482,  0.6088]])
# 在维度0上切割
a_select = torch.index_select(a, 0, torch.LongTensor([0,2]))
print(a_select)
tensor([[ 0.6482,  0.9216,  0.7734,  0.5927,  0.9646,  0.5529],
        [ 0.8988,  0.1239,  0.6988,  0.0342,  0.3798,  0.8176]])

3.5 根据掩码选择张量

根据掩码张量mask中的二元值,取输入张量中的指定项( mask为一个 ByteTensor),将取值返回到一个新的1D张量,

张量 mask须跟input张量有相同数量的元素数目,但形状或维度不需要相同。 注意: 返回的张量不与原始张量共享内存空间。

torch.masked_select(input, mask, out=None) → Tensor

参数:

input (Tensor) – 输入张量

mask (ByteTensor) – 掩码张量,包含了二元索引值

out (Tensor, optional) – 目标张量

a = torch.rand(2, 4)
print(a)
tensor([[ 0.6390,  0.5035,  0.6042,  0.8629],
        [ 0.3294,  0.6633,  0.3334,  0.5081]])
mask = torch.ByteTensor([[0, 0, 1, 0], [1, 1, 0, 1]])
a_mask_select = torch.masked_select(a, mask)
print(a_mask_select)  # 注意,返回的是一个一维的张量, 该张量里的元素是a中mask里1对应位置的元素
tensor([ 0.6042,  0.3294,  0.6633,  0.5081])

3.6 选择非0张量

返回一个包含输入input中非零元素索引的张量。输出张量中的每行包含输入中非零元素的索引。

如果输入input有n维,则输出的索引张量output的形状为 z x n, 这里 z 是输入张量input中所有非零元素的个数。

torch.nonzero(input, out=None) → LongTensor

参数:

input (Tensor) – 源张量

out (LongTensor, optional) – 包含索引值的结果张量

a = torch.Tensor([[1, 2, 3, 0, 5], [6, 7, 0, 7, 9]])
print(a)
tensor([[ 1.,  2.,  3.,  0.,  5.],
        [ 6.,  7.,  0.,  7.,  9.]])
a_nonzero = torch.nonzero(a)
print(a_nonzero)  # 注意,输出的是非零元素的索引哦
tensor([[ 0,  0],
        [ 0,  1],
        [ 0,  2],
        [ 0,  4],
        [ 1,  0],
        [ 1,  1],
        [ 1,  3],
        [ 1,  4]])

3.7 等分张量

将输入张量分割成相等形状的chunks(如果可分)。 如果沿指定维的张量形状大小不能被split_size 整分, 则最后一个分块会小于其它分块。

torch.split(tensor, split_size, dim=0)

参数:

tensor (Tensor) – 待分割张量

split_size (int) – 单个分块的形状大小

dim (int) – 沿着此维进行分割

a = torch.randn(4, 7)
print(a)
tensor([[ 1.9670,  1.0551,  0.1469, -0.2239, -1.7594, -1.2708, -0.4926],
        [-0.8019, -0.4658,  0.4625,  1.3451,  0.3857, -0.8660, -1.1791],
        [ 1.4074, -0.8085, -1.2970, -0.7953,  0.2780,  0.9627, -1.0428],
        [ 1.2674, -1.3966, -0.7654,  1.2177,  0.9083, -0.1382, -0.3038]])
a_split = torch.split(a, 2, dim=1)
print(a_split)   # 注意当不能整分的时候,最后一个分块是小于其他分块的
(tensor([[ 1.9670,  1.0551],
        [-0.8019, -0.4658],
        [ 1.4074, -0.8085],
        [ 1.2674, -1.3966]]), tensor([[ 0.1469, -0.2239],
        [ 0.4625,  1.3451],
        [-1.2970, -0.7953],
        [-0.7654,  1.2177]]), tensor([[-1.7594, -1.2708],
        [ 0.3857, -0.8660],
        [ 0.2780,  0.9627],
        [ 0.9083, -0.1382]]), tensor([[-0.4926],
        [-1.1791],
        [-1.0428],
        [-0.3038]]))

torch_chunk与torch_split区别:
torch_chunk传入的参数是要分多少块,torch_split传入的参数是每块多少大。

3.8 压缩张量

将输入张量形状中的1 去除并返回。 如果输入是形如(A×1×B×1×C×1×D),那么输出形状就为: (A×B×C×D)
当给定dim时,那么挤压操作只在给定维度上。例如,输入形状为: (A×1×B), squeeze(input, 0) 将会保持张量不变,只有用 squeeze(input, 1),形状会变成 (A×B)。

注意: 返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。

torch.squeeze(input, dim=None, out=None)

参数:

input (Tensor) – 输入张量

dim (int, optional) – 如果给定,则input只会在给定维度挤压

out (Tensor, optional) – 输出张量

创建一个4维的张量,其中有两个维度的大小为1
a = torch.rand(2,1,3,1)
print(a)
tensor([[[[ 0.3762],
          [ 0.8454],
          [ 0.6275]]],


        [[[ 0.5402],
          [ 0.9575],
          [ 0.6968]]]])
# 把所有大小为1的维度给去掉了
a_squeeze = torch.squeeze(a)
print(a_squeeze)
print('size:', a_squeeze.size())  # 压缩之后维度变成了2*3
tensor([[ 0.3762,  0.8454,  0.6275],
        [ 0.5402,  0.9575,  0.6968]])
size: torch.Size([2, 3])
# 也可以指定维度压缩
a_squeeze = torch.squeeze(a, 1)
print(a_squeeze)
print('size:', a_squeeze.size()) # 于是只去掉了第1维度上的1
tensor([[[ 0.3762],
         [ 0.8454],
         [ 0.6275]],

        [[ 0.5402],
         [ 0.9575],
         [ 0.6968]]])
size: torch.Size([2, 3, 1])

3. 9 新维度连接张量

沿着一个新维度对输入张量序列进行连接。 序列中所有的张量都应该为相同形状。
注意和torch.cat的区别,torch.stack是在新的维度上进行拼接,也就是说拼接后维度数会+1

torch.stack(sequence, dim=0)

参数:

sqequence (Sequence) – 待连接的张量序列

dim (int) – 插入的维度。必须介于 0 与 待连接的张量序列数之间。

a = torch.randn(2, 2)
b = torch.ones(2, 2)
c = torch.zeros(2, 2)

stack = torch.stack((a, b, c), 0)
print(stack)
tensor([[[ 1.1905,  0.0067],
         [ 0.1899, -0.0446]],

        [[ 1.0000,  1.0000],
         [ 1.0000,  1.0000]],

        [[ 0.0000,  0.0000],
         [ 0.0000,  0.0000]]])
# 指定其他维度
stack = torch.stack((a, b, c), 1)
print(stack)
tensor([[[ 1.1905,  0.0067],
         [ 1.0000,  1.0000],
         [ 0.0000,  0.0000]],

        [[ 0.1899, -0.0446],
         [ 1.0000,  1.0000],
         [ 0.0000,  0.0000]]])
# 指定其他维度
stack = torch.stack((a, b, c), 2)
print(stack)
tensor([[[ 1.1905,  1.0000,  0.0000],
         [ 0.0067,  1.0000,  0.0000]],

        [[ 0.1899,  1.0000,  0.0000],
         [-0.0446,  1.0000,  0.0000]]])

3.10 转置2维张量

输入一个矩阵(2维张量),并转置0, 1维。 可以被视为函数transpose(input, 0, 1)的简写函数。

torch.t(input, out=None) → Tensor

参数:

input (Tensor) – 输入张量

out (Tensor, optional) – 结果张量

a = torch.randn(2, 3)
print(a)
tensor([[-0.0530,  0.3038,  0.9280],
        [ 0.0992,  0.6662, -0.4005]])
a_t = torch.t(a)
print(a_t)
tensor([[-0.0530,  0.0992],
        [ 0.3038,  0.6662],
        [ 0.9280, -0.4005]])

3.11 通用的转置

返回输入矩阵input的转置。交换维度dim0和dim1。 输出张量与输入张量共享内存,所以改变其中一个会导致另外一个也被修改。

torch.transpose(input, dim0, dim1, out=None) → Tensor

参数:

input (Tensor) – 输入张量

dim0 (int) – 转置的第一维

dim1 (int) – 转置的第二维

a = torch.randn(2, 3, 2)
print(a)
tensor([[[ 0.8596,  0.6972],
         [ 0.8587, -0.4417],
         [-2.0626, -1.9395]],

        [[-0.5063, -0.9338],
         [-0.0316, -1.2842],
         [ 0.7219, -1.5864]]])
# 指定要交换的两个维度
a_trans = torch.transpose(a, 1, 2)
print(a_trans)
tensor([[[ 0.8596,  0.8587, -2.0626],
         [ 0.6972, -0.4417, -1.9395]],

        [[-0.5063, -0.0316,  0.7219],
         [-0.9338, -1.2842, -1.5864]]])

3.12 移除指定维度

移除指定维后,返回一个元组,包含了沿着指定维切片后的各个切片

torch.unbind(tensor, dim=0)

参数:

tensor (Tensor) – 输入张量

dim (int) – 删除的维度

a = torch.randn(2, 3, 2)
print(a)
tensor([[[-0.6012, -0.4857],
         [-0.5015, -0.6248],
         [-0.7119, -0.9076]],

        [[ 1.4232,  0.0932],
         [-0.6209,  1.1310],
         [-0.7734,  0.0066]]])
a_unbind = torch.unbind(a, 0)
print(a_unbind)  # 移除维度0, 拆分成了两个3*2的矩阵
(tensor([[-0.6012, -0.4857],
        [-0.5015, -0.6248],
        [-0.7119, -0.9076]]), tensor([[ 1.4232,  0.0932],
        [-0.6209,  1.1310],
        [-0.7734,  0.0066]]))

3.13 扩张指定维度

返回一个新的张量,对输入的制定位置插入维度 1

注意: 返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。

如果dim为负,则将会被转化dim+input.dim()+1

torch.unsqueeze(input, dim, out=None)

参数:

tensor (Tensor) – 输入张量

dim (int) – 插入维度的索引

out (Tensor, optional) – 结果张量

# 先创建一个只有一个维度的tensor
a = torch.rand(4)
print('a:', a)
print('size:', a.size())
a: tensor([ 0.2107,  0.0282,  0.5163,  0.3185])
size: torch.Size([4])
# 在维度1上新增一个维度
a_1 = torch.unsqueeze(a, 1)
print('a_1', a_1)
print('size:', a_1.size())  # 维度变成了2维:4*1
a_1 tensor([[ 0.2107],
        [ 0.0282],
        [ 0.5163],
        [ 0.3185]])
size: torch.Size([4, 1])

4 随机抽样

4.1 人为设定种子

设定生成随机数的种子,并返回一个 torch._C.Generator 对象.

参数: seed (int or long) – 种子.

x = torch.manual_seed(10)
print(x)

4.2 获得种子值

x = torch.initial_seed()
print(x)
10

4.3 获得与设置随机生成器状态

# 获得当前状态
print(torch.get_rng_state())
tensor([  10,    0,    0,  ...,    0,    0,    0], dtype=torch.uint8)
# 设置状态
torch.set_rng_state(torch.get_rng_state())

4.4 获得默认的随机生成器

print(torch.default_generator)

4.5 从不同分布中获取随机数

4.5.1 伯努利分布

从伯努利分布中抽取二元随机数(0 或者 1)。

输入张量须包含用于抽取上述二元随机值的概率。 因此,输入中的所有值都必须在[0,1]区间,即 0<=inputi<=1
输出张量的第i个元素值, 将会以输入张量的第i个概率值等于1。

返回值将会是与输入相同大小的张量,每个值为0或者1 参数:

input (Tensor) – 输入为伯努利分布的概率值

out (Tensor, optional) – 输出张量(可选)

# 创建一个0-1分布的矩阵,表示概率
a = torch.Tensor(3, 3).uniform_(0,1)
print(a)
tensor([[ 0.4581,  0.4829,  0.3125],
        [ 0.6150,  0.2139,  0.4118],
        [ 0.6938,  0.9693,  0.6178]])
# 转换成0/1伯努利分布,即在伯努利分布中抽取随机数,1表示抽取出的数
b = torch.bernoulli(a)
print(b)
tensor([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 1.,  1.,  1.]])

4.5.2 多项式分布

返回一个张量,每行包含从input相应行中定义的多项分布中抽取的num_samples个样本。

[注意]:输入input每行的值不需要总和为1 (这里我们用来做权重),但是必须非负且总和不能为0。

当抽取样本时,依次从左到右排列(第一个样本对应第一列)。

如果输入input是一个向量,输出out也是一个相同长度num_samples的向量。如果输入input是有 m行的矩阵,输出out是形如m×n的矩阵。

如果参数replacement 为 True, 则样本抽取可以重复。否则,一个样本在每行不能被重复抽取。

参数num_samples必须小于input长度(即,input的列数,如果是input是一个矩阵)。

参数:

input (Tensor) – 包含概率值的张量

num_samples (int) – 抽取的样本数

replacement (bool, optional) – 布尔值,决定是否能重复抽取

out (Tensor, optional) – 结果张量

weights = torch.Tensor([0, 10, 3, 0])

# 无放回,num_samples 必须小于等于weights的长度
b = torch.multinomial(weights, 3)
print(b)
tensor([ 2,  1,  0])
# 有放回,num_samples 任意
c = torch.multinomial(weights, 4, replacement=True)
print(c)
tensor([ 1,  1,  1,  2])

4.5.3 正态分布

返回一个张量,包含从给定参数means,std的离散正态分布中抽取随机数。 均值means是一个张量,包含每个输出元素相关的正态分布的均值。 std是一个张量,包含每个输出元素相关的正态分布的标准差。 均值和标准差的形状不须匹配,但每个张量的元素个数须相同。

参数:

means (Tensor) – 均值

std (Tensor) – 标准差

out (Tensor) – 可选的输出张量

torch.normal(mean=0.5, std=torch.arange(1, 6))

tensor([-1.2336,  2.2541, -0.6556, -1.9196,  0.8095])

5 序列化

5.1 保存对象到硬盘文件

保存一个对象到一个硬盘文件上 参考: Recommended approach for saving a model

torch.save(obj, f, pickle_module=, pickle_protocol=2)

参数:

obj – 保存对象

f - 类文件对象 (返回文件描述符)或一个保存文件名的字符串

pickle_module – 用于pickling元数据和对象的模块

pickle_protocol – 指定pickle protocal 可以覆盖默认参数

# 假设有如下模型和优化器需要被保存到硬盘文件
model = Net()
optimizer = optim.Adam(model.parameters(), lr=args.lr)

# 先建立一个词典
state = {'net': model.state_dict(), 'optimizer':optimizer.state_dict(), 'epoch': epoch}

# 保存
torch.save(state, dir)

5.2 从磁盘中读取torch.save保存的对象

从磁盘文件中读取一个通过torch.save()保存的对象。 torch.load() 可通过参数map_location 动态地进行内存重映射,使其能从不动设备中读取文件。一般调用时,需两个参数: storage 和 location tag. 返回不同地址中的storage,或着返回None (此时地址可以通过默认方法进行解析). 如果这个参数是字典的话,意味着其是从文件的地址标记到当前系统的地址标记的映射。 默认情况下, location tags中 "cpu"对应host tensors,‘cuda:device_id’ (e.g. ‘cuda:2’) 对应cuda tensors。 用户可以通过register_package进行扩展,使用自己定义的标记和反序列化方法。

torch.load(f, map_location=None, pickle_module=)

参数:

f – 类文件对象 (返回文件描述符)或一个保存文件名的字符串

map_location – 一个函数或字典规定如何remap存储位置

pickle_module – 用于unpickling元数据和对象的模块 (必须匹配序列化文件时的pickle_module )

# 直接读取对象
torch.load('tensor.pt')

# 将所有tensor读取到GPU上
torch.load('tensor.pt', map_location=lambda storage, loc:storage)

# 将tensor从GPU1映射到GPU0上
torch.load('tensor.pt', map_location={'cuda:1':'cuda:0'})

若想读取回5.1操作中保存的参数

checkpoint = torch.load(dir)
model.load_state_dict(checkpoint['net'])
optimizer.load_state_dict(checkpoint['optimizer'])
state_epoch = checkpoint['epoch'] + 1

6 并行化

6.1 并行化CPU操作

torch.set_num_threads(2)

你可能感兴趣的:(Pytorch)