(二十六:2021.01.07)Pytorch1.7.1 API 全解读之《TORCH包》

对pytorch1.7.1的API进行一次完全的解读

  • 讲在前面
  • API
    • TORCH
      • 1.Tensor(对张量本身进行的一些操作)
        • 1.1 `is_tensor`
        • 1.2 `is_storage`
        • 1.3 `is_complex`
        • 1.4 `is_floating_point`
        • 1.5 `is_nonzero`
        • 1.6 `set_default_dtype`
        • 1.7 `get_default_dtype`
        • 1.7 `set_default_tensor_type`
        • 1.7 `numel`
        • 1.8 `set_printoptions`
        • 1.8 `set_flush_denormal`
      • 2.Creation Ops(创建张量的操作)
        • 2.1 `tensor`
        • 2.2 `spares_coo_tensor()`

讲在前面

针对pytorch 1.7.1进行一次全方位的解读,所以此博客会持续更新相当的一段时间。随后的博客会跟进torch的版本更新信息,其中能添加的实例代码我都会添加。

API

TORCH

这个包含了多维张量的数据结构和一些对于张量的数学操作。另外,提供了对张量和其他数据类型进行有效序列化的方法,还有些其他的方法。

1.Tensor(对张量本身进行的一些操作)

pytorch对于tensor的存储是一分为二的,一个创建好的张量,其头信息区叫作Tensor,负责存储tensor的形状、步长、数据类型等,其内部数据保存为数组,存储在存储区Srorage中。
所以,Tensor占用的内存较小,真正占用内存的地方是Storage

1.1 is_tensor

  • 函数源码解释:
def is_tensor(obj):
    r"""如果对象为PyTorch的张量,则返回True.

    Note that this function is simply doing ``isinstance(obj, Tensor)``.
    Using that ``isinstance`` check is better for typechecking with mypy,
    and more explicit - so it's recommended to use that instead of
    ``is_tensor``.

    参数:
        输入参数为要测试的对象
    """
    return isinstance(obj, torch.Tensor)
  • 代码测试:
import torch
import numpy as np

a = np.ones([1, 2])
t = torch.from_numpy(a)

print(torch.is_tensor(a))
print(torch.is_tensor(t))
print(t)
-----------
False
True
tensor([[1., 1.]], dtype=torch.float64)

1.2 is_storage

  • 函数源码解释:
def is_storage(obj):
    r"""如果对象是PyTorch storage的话.则返回True

    参数:
        测试对象
    """
    return type(obj) in _storage_classes
  • 代码测试:
import torch

a = torch.rand(3, 5)
print(a)
print(a.storage())
print(type(a.storage()))
print(a.storage()[0])

x = a.storage()
print(torch.is_storage(x))
----------
tensor([[0.8754, 0.7499, 0.3954, 0.3763, 0.8578],
        [0.7598, 0.9750, 0.6963, 0.1602, 0.3442],
        [0.9445, 0.5585, 0.2020, 0.9230, 0.4736]])
 0.8753897547721863
 0.7498539090156555
 0.3954319953918457
 0.3762640357017517
 0.857833981513977
 0.7598322033882141
 0.9749904870986938
 0.6962557435035706
 0.16019368171691895
 0.34423667192459106
 0.9444983005523682
 0.5584731101989746
 0.20202845335006714
 0.9230412840843201
 0.473596453666687
[torch.FloatStorage of size 15]
<class 'torch.FloatStorage'>
0.8753897547721863
True

1.3 is_complex

  • 函数源码解释:
def is_complex(input: Tensor) -> _bool: ...
r"""
判断输入张量是否为复数类型(torch.complex64或者torch.complex128),是则返回True。
"""
  • 代码测试:
import torch

a = torch.tensor([1, 2], dtype=torch.float32) #创建复数的实部
b = torch.tensor([3, 4], dtype=torch.float32) #创建复数的虚部
z = torch.complex(a, b) #只有1.7以后才有这个方法
print(z)
print(z.dytpe)
print(torch.is_complex(z))
----------
tensor([1.+3.j, 2.+4.j])
torch.complex64
True

1.4 is_floating_point

  • 函数源码解释:
def is_floating_point(input: Tensor) -> _bool: ...
r"""
判断输入张量的数据类型是不是浮点型(float64\float32\float16)
"""
  • 代码测试:
import torch
a = torch.tensor([1, 2], dtype=torch.float16)
print(torch.is_floating_point(a))
----------
True

1.5 is_nonzero

只用来判断单元素张量,判断多元素张量会报错。

  • 函数源码解释:
def is_nonzero(input: Tensor) -> _bool: ...
r"""
判断输入张量的数据类型是不是单元素非零张量(非[0]\[0.]\[False]),是的话返回True。
"""
  • 代码测试:
import torch

print(torch.is_nonzero(torch.tensor([0.])))
print(torch.is_nonzero(torch.tensor([1.])))
print(torch.is_nonzero(torch.tensor([False])))
print(torch.is_nonzero(torch.tensor([True])))

print(torch.is_nonzero(torch.tensor([1,2,3])))
----------
False
True
False
True
Traceback (most recent call last):
  File "/home/qiao/PythonProjects/torchapi/TORCH/Tensor/is_nonzero.py", line 8, in <module>
    print(torch.is_nonzero(torch.tensor([1,2,3])))
RuntimeError: Boolean value of Tensor with more than one value is ambiguous

1.6 set_default_dtype

torch.tensor()创建出的张量的数据类型进行初始化自定义,修改之前的torch.tensor()的默认数据类型。

  • 函数源码解释:
def set_default_dtype(d):
    r"""将数据类型设置为d.
    1.用`torch.tensor`推理之后的数据类型.
    2. 因为默认的数据类型是torch.float32,所以复数张量的默认数据类型torch.complex64。
    3. 如果自定义默认数据类型为torch.float64,那么复数数据类型变成对应的torch.complex128。
    """
    _C._set_default_dtype(d)
  • 代码测试:
import torch

print(torch.tensor([1.2, 3]).dtype)
print(torch.tensor([1.2, 3j]).dtype)

torch.set_default_dtype(torch.float64)
print(torch.tensor([1.2, 3]).dtype)
print(torch.tensor([1.2, 3j]).dtype)
---------
torch.float32
torch.complex64
torch.float64
torch.complex128

1.7 get_default_dtype

获取当前的默认张量数据类型。

  • 函数源码解释:
def get_default_dtype() -> _dtype: ...
r"""
获取当前的默认张量数据类型。
"""
  • 代码测试:
import torch

print(torch.get_default_dtype())

torch.set_default_dtype(torch.float64)
print(torch.get_default_dtype())

torch.set_default_tensor_type(torch.FloatTensor)
print(torch.get_default_dtype())
----------
torch.float32
torch.float64
torch.float32

1.7 set_default_tensor_type

这个方法与前面的set_default_dtype有点相似,但还是有不同,下面的实例中我们会测试一下。

  • 函数源码解释:
def set_default_tensor_type(t):
    r"""同样是设置默认的张量数据类型,但是这个输入的t与之前不同,
    这里只可以输入torch.FloatTensor这种格式。
    """
    if isinstance(t, _string_classes):
        t = _import_dotted_name(t)
    _C._set_default_tensor_type(t)
  • 代码测试:
import torch

print(torch.tensor([1.2, 3]).dtype)    # initial default for floating point is torch.float32

torch.set_default_tensor_type(torch.DoubleTensor)
print(torch.tensor([1.2, 3]).dtype)    # a new floating point tensor

torch.set_default_tensor_type(torch.float32)
print(torch.tensor([1.2, 3]).dtype)
--------
torch.float32
torch.float64
Traceback (most recent call last):
  File "/home/qiao/PythonProjects/torchapi/TORCH/Tensor/set_default_tensor_type.py", line 8, in <module>
    torch.set_default_tensor_type(torch.float32)
  File "/home/qiao/anaconda3/lib/python3.7/site-packages/torch/__init__.py", line 295, in set_default_tensor_type
    _C._set_default_tensor_type(t)
TypeError: invalid type object
  • 对比测试:
import torch

print(torch.tensor([1.2, 3]).dtype)    # initial default for floating point is torch.float32

torch.set_default_tensor_type(torch.DoubleTensor)
print(torch.tensor([1.2, 3]).dtype)    # a new floating point tensor

torch.set_default_dtype(torch.float32)
print(torch.tensor([1.2, 3]).dtype)

torch.set_default_dtype(torch.DoubleTensor)
print(torch.tensor([1.2, 3]).dtype)
--------
torch.float32
torch.float64
torch.float32
Traceback (most recent call last):
  File "/home/qiao/PythonProjects/torchapi/TORCH/Tensor/set_default_tensor_type.py", line 11, in <module>
    torch.set_default_dtype(torch.DoubleTensor)
  File "/home/qiao/anaconda3/lib/python3.7/site-packages/torch/__init__.py", line 326, in set_default_dtype
    _C._set_default_dtype(d)
TypeError: invalid dtype object

1.7 numel

计算张量的所有元素的总个数。

  • 函数源码解释:
def numel(self: Tensor) -> _int: ...
r"""
返回张量所有元素的总个数
"""
  • 代码测试:
import torch

a = torch.randn(1, 2, 3, 4, 5)
print(torch.numel(a))

a = torch.zeros(4,4)
print(torch.numel(a))
---------
120
16

1.8 set_printoptions

这个方法主要是为了设置print展示出来的张量的显示格式等,和numpy对应的该方法一模一样。

  • 函数源码解释:
def set_printoptions(
        precision=None,
        threshold=None,
        edgeitems=None,
        linewidth=None,
        profile=None,
        sci_mode=None
):
    r"""
    Args:
        precision: 显示出来每个元素的精度数,默认为4;
        threshold: 总元素数大于某个值时进行折叠,默认为1000;
        edgeitems: 某个维度上的行数只显示前n行和后n行,中间的折叠,默认n为3;
        linewidth: 每行的宽度超过这个值会换行,默认为80;
        profile: 有 `default`, `short`, `full`三个模式,full显示小数点后四位,short显示小数点后两位);
        sci_mode: 是否开启科学计数法。
    """
    if profile is not None:
        if profile == "default":
            PRINT_OPTS.precision = 4
            PRINT_OPTS.threshold = 1000
            PRINT_OPTS.edgeitems = 3
            PRINT_OPTS.linewidth = 80
        elif profile == "short":
            PRINT_OPTS.precision = 2
            PRINT_OPTS.threshold = 1000
            PRINT_OPTS.edgeitems = 2
            PRINT_OPTS.linewidth = 80
        elif profile == "full":
            PRINT_OPTS.precision = 4
            PRINT_OPTS.threshold = inf
            PRINT_OPTS.edgeitems = 3
            PRINT_OPTS.linewidth = 80

    if precision is not None:
        PRINT_OPTS.precision = precision
    if threshold is not None:
        PRINT_OPTS.threshold = threshold
    if edgeitems is not None:
        PRINT_OPTS.edgeitems = edgeitems
    if linewidth is not None:
        PRINT_OPTS.linewidth = linewidth
    PRINT_OPTS.sci_mode = sci_mode
  • 代码测试:
    这篇博客很认真的探讨了这几个参数,由于篇幅原因,不做赘述了。

1.8 set_flush_denormal

为了防止一些特别小的数引起的问题。开启时,当数组过小时,会将这个值归为0。

  • 代码测试:
import torch

torch.set_flush_denormal(True)

print(torch.tensor([1e-323], dtype=torch.float64))

torch.set_flush_denormal(False)

print(torch.tensor([1e-323], dtype=torch.float64))
--------
tensor([0.], dtype=torch.float64)
tensor([9.8813e-324], dtype=torch.float64)

2.Creation Ops(创建张量的操作)

2.1 tensor

这个看似很简单的方法其实有很多的细节要注意:

  • 1.torch.tensor()在使用的时候总是会对源数据进行一次复制,如果是对Tensor源数据调用这个方法想要避免复制,要使用torch.Tensor.requires_grad_()或者torch.Tensor.detach();如果Numpy源数据使用这个方法且避免复制,要使用torch.as_tensor()
  • 2.如果源数据是一个tensor时,torch.tensor()x.clone().detach()
    torch.tensor(x, requires_grad=True)x.clone().detach().requires_grad_(True)。建议使用后面这种包含clone()detach()的方式。

2.2 spares_coo_tensor()

创建稀疏张量,所谓的稀疏矩阵是内部有很多0元素的矩阵,稀疏张量也由此而来。按照上面的tensor的存储方法,稀疏张量也一分为二来存储,而元素数据占用最大内存,那么对于一个0很多的张量来说,大部分的内存全被0占用,显然这样非常耗费资源,所以这里用COO这样的格式存储稀疏张量。COO格式可以概括为一个三元组,也就是三行数据,第一行为每个张量中每个元素的行索引、第二行为每个元素的列索引、第三行为每个元素的元素值。这篇博客很好的做了解释。

  • 代码测试:
import torch

indices = torch.tensor([[4, 2, 1], [2, 0, 2]])
values = torch.tensor([3, 4, 5], dtype=torch.float32)
x = torch.sparse_coo_tensor(indices=indices, values=values, size=[5, 5])
print(x)
---------
tensor(indices=tensor([[4, 2, 1],
                       [2, 0, 2]]),
       values=tensor([3., 4., 5.]),
       size=(5, 5), nnz=3, layout=torch.sparse_coo)

你可能感兴趣的:(深度学习基础,深度学习框架,pytorch)