# mypy: 允许未类型化定义
导入 copyreg
导入
枚举
导入 functools
导入
警告
来自
集合
导入 OrderedDict
来自
复制
导入
深拷贝
来自
数字
导入
数
来自
打字
导入
任何,
可调用,
角色,
可选,
联合
导入
火炬
导入 torch._C as _C
来自 torch._namedtensor_internals
导入 (
检查序列化命名张量,
是否省略号,
解析省略号,
单个省略号索引,
解压命名形状,
更新名称,
)
来自 torch.overrides
导入 (
获取默认不换行函数,
handle_torch_function,
有 torch 功能,
has_torch_function_unary,
has_torch_function_variadic,
)
def 处理 torch 函数并将类型错误包装为未实现(f):
分配 = functools.
包装任务
@functools.包装(f,
分配=
分配)
def 包装(*
参数, **kwargs):
尝试:
# See https://github.com/pytorch/pytorch/issues/75462
如果
有 torch 功能(
参数):
返回 handle_torch_function(
包装,
参数, *
参数, **kwargs)
返回 f(*
参数, **kwargs)
除了
类型错误:
返回 NotImplemented
返回
包装
# 应该不使用,仅为了向后兼容加载旧的序列化张量子类
def 从类型重建(
函数,
类型,
参数,
字典):
如果
类型
是
张量:
返回
函数(*
参数)
返回 =
函数(*
参数).
作为子类(
类型)
返回.
字典 =
字典
返回
返回
def 从类型重建_v2(
函数,
新类型,
参数,
状态):
返回 =
函数(*
参数)
如果
类型(
返回)
是
不
新类型:
返回 =
返回.
作为子类(
新类型)
# 张量即使没有定义 __setstate__,也定义了 __getstate__。所以只有当它不是在 Tensor 上定义的时才使用 __setstate__
# __getstate__。所以只有使用 __setstate__ 如果它不是 Tensor 上定义的那个
# 的
如果 (
getattr(返回.
类, "__setstate__",
张量.__setstate__)
是
不
张量.__setstate__
):
返回.__setstate__(
状态)
否则:
ret = PyTorch._utils._set_obj_state(
返回,
状态)
返回
返回
def _dtype_to_typestr(数据类型):
# CUDA 设备为小端序,张量以本地字节顺序存储
# 1 字节条目是端序无关的。
返回 {
PyTorch.complex64: "<c8",
PyTorch.complex128: "<c16",
PyTorch.bfloat16: "<V2",
# 相同于 ml_dtypes.bfloat16.dtype.str.
PyTorch.float16: "<f2",
PyTorch.float32: "<f4",
PyTorch.float64: "<f8",
PyTorch.uint8: "|u1",
PyTorch.int8: "|i1",
PyTorch.uint16: "<u2",
PyTorch.int16: "<i2",
PyTorch.uint32: "<u4",
PyTorch.int32: "<i4",
PyTorch.uint64: "<u8",
PyTorch.int64: "<i8",
PyTorch.bool: "|b1",
}
数据类型]
# 如果您想子类化 Tensor,并且想要跨进程共享子类化的类
# 您还必须更新 torch/multiprocessing/reductions.py
# 为该类定义一个 ForkingPickler 序列化模式。
#
# NB: 如果您向 Tensor 添加新方法,您必须更新
# torch/_C/__init__.pyi.in 以添加您的方法的类型注解;
# 否则,它将不会显示在自动完成中。
类
张量(
PyTorch._C.TensorBase):
_is_param
是参数: 布尔值
def 清除非序列化缓存数据(self):
r清除张量`__dict__`中任何可能阻止张量
从序列化中。
例如,具有自定义分派大小/步长的子类将此信息缓存在
``__dict__`` 中的非序列化 PyCapsules 中,并且必须在序列化到函数之前清除。
任何覆盖此方法的子类都必须调用 ``super()._clear_non_serializable_cached_data().``
任何覆盖此方法的子类都必须调用 ``super()._clear_non_serializable_cached_data().``
在覆盖中清除的附加数据必须能够透明地重新缓存
以避免破坏子类功能。
"""
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
_清除非序列化缓存数据, (self,), self
)
# 注意:实现自定义分派大小/步长缓存的包装子类
# 此信息通过非序列化 PyCapsules 获取。
缓存的大小、步长和键 = [
_sym_sizes_capsule,
_sym_sizes_capsule_len,
“对称步长胶囊”,
“对称步长胶囊长度”,
]
for 键
在
“缓存的大小、步长和键”:
self.字典.
流行(
键,
无)
def 深拷贝(self,
描述):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
深拷贝, (self,), self,
描述)
如果
不 self.
是否为叶子节点:
抛出
运行时错误(
“仅由用户显式创建的张量”
"(图叶子)目前支持 deepcopy 协议。"
"如果你尝试 deepcopy 一个模块,这可能是因为"
"torch.nn.utils.weight_norm 的使用,"
"请参阅 https://github.com/pytorch/pytorch/pull/103001"
)
如果 id(self)
在
描述:
返回
描述[id(self)]
替换为
PyTorch.
不梯度():
# TODO: 跳过存储副本是元数据错误,因为元数据
# 精确的别名跟踪;然而,下面的代码
因为 # 不起作用
# https://github.com/pytorch/pytorch/issues/47442
# 如果您从这里删除 'meta',请更新 test_serialization 中的测试
如果 (
self.is_sparse
或者 self.
设备.
类型
在 [
懒惰,
轻快,
翻译,
国会议员,
美亚,
元数据,
知识产权]
或者 (
不
PyTorch._C.
有存储(self)
和 self.
设备.
类型 ==
PyTorch._C._get_privateuse1_backend_name()
)
或者 (
类型(self)
是
不
张量
和 self.
数据指针() == 0)
):
新张量 = self.
克隆()
如果
类型(
新张量)
是
不
类型(self):
抛出
运行时错误(
"__deepcopy__()"的默认实现仅适用于包装子类的子类
"实现 clone()并且克隆返回同一子类实例的类型"
"您应该为您的子类正确实现 clone()或重写__deepcopy__()"
"__deepcopy__()"方法"
"如果 clone()返回不同类型的实例是预期行为,那么"
"就是这样的。"
)
否则:
新存储 = self._typed_storage().
深拷贝(
描述)
如果 self.
是否量化:
# quantizer_params 的类型可以根据 torch 属性的不同而不同
量化器参数:
联合[
元组[
PyTorch.
q 方案, float, int
]
元组[
PyTorch.
q 方案,
张量,
张量, int
]
]
如果 self.
q 方案() ==
PyTorch.
每张张量仿射:
量化器参数 = (
self.q 方案(),
self.q_scale(),
self.q_zero_point(),
)
如果...否则 self.
q 方案()
在 (
PyTorch.
单通道仿射变换,
PyTorch.
单通道仿射变换浮点 Q 参数,
):
量化器参数 = (
self.q 方案(),
self.每通道缩放的 q(),
self.
q_per_channel_zero_points
q_per_channel_零点(),
self.每通道轴的 q(),
)
否则:
抛出
运行时错误(
f不支持 Q 方案{self.
q 方案()}
在 deepcopy"中
)
# TODO: 一旦我们决定中断序列化 FC,就不再
# 需要使用 TypedStorage 包装
新张量 =
PyTorch._utils.
重建 qtensor(
PyTorch.
存储.
类型化存储(
包装存储=
新存储.
未类型化存储,
数据类型=self.
数据类型,
内部=True,
),
self.存储偏移(),
self.尺寸(),
self.步长(),
量化器参数,
self.需要梯度,
self._backward_hooks,
)
如果
类型(
新张量)
是
不
类型(self):
抛出
运行时错误(
"__deepcopy__()"的默认实现,用于量化张量
"期望 torch._utils._rebuild_qtensor()返回的 tensor 与被复制的实例类型匹配。如果您遇到这种情况,"
"请在 PyTorch 的 GitHub 上提交一个 issue。"
"请打开 PyTorch 的 GitHub 上的一个 issue。"
)
否则:
新 tensor = self.
新空([])
如果
类型(
新张量)
是
不
类型(self):
抛出
运行时错误(
"__deepcopy__()"的默认实现仅适用于非包装子类
"且这些子类实现了 new_empty()方法,并且该方法返回同一子类的另一个实例。你应该"
"为此实现自己的__deepcopy__()方法。"
"正确实现子类中的 new_empty() 方法,或者覆盖 "
"__deepcopy__(),如果 new_empty() 返回不同类型的实例是预期行为的话,"
"则返回一个不同类型的实例。"
)
新张量.
集合(
新存储, self.
存储偏移(), self.
尺寸(), self.
步长()
)
如果 self.
是连词():
新张量 =
新张量.
物理连词()
如果 self.
是否定():
新张量 =
新张量.
否定()
如果 self.
需要梯度:
新张量.
需要梯度_()
如果 self.
梯度
是
不
无:
新张量.
梯度 = self.
研究生.
深拷贝(
描述)
如果
类型(self)
是
不
张量:
如果
类型(
新张量)
是
不
类型(self):
抛出
运行时错误(
"深度拷贝的结果类型与源张量类型不匹配。"
"如果您遇到这种情况,请在 PyTorch 的 GitHub 上提交一个 issue。"
)
# 纯张量没有槽位
slots_to_save = 复制注册.
_槽位名称(self.
类)
# 类型:忽略[已定义]
for 槽
在
要保存的槽位:
如果
有属性(self,
槽):
setattr(新张量,
槽,
深拷贝(getattr(self,
槽),
描述))
# 不要尝试深拷贝非序列化缓存数据
self._清除非序列化缓存数据()
新张量.
字典 =
深拷贝(self.
字典,
描述)
描述[id(self)] =
新张量
返回
新张量
def __reduce_ex__(self, proto):
materialize_fake_tensors = (
PyTorch.
序列化.
序列化 TLS.materialize_fake_tensors
)
状态 =
PyTorch._utils.
_获取对象状态(self)
使用 FakeTensor 时,由于 FakeTensor 具有无法序列化的状态,请忽略所有状态,使用 skip_data(materialize_fake_tensors)
# 一些无法序列化的状态
如果 (
# TODO: 删除 hasattr,这是一个为了支持 torch 的某些版本而采用的 hack 方法
没有子类
有属性(
PyTorch,
"_子类")
和
类型(self)
是
PyTorch.
子类.
模拟张量.
模拟 Tensor
和
实现伪造张量
) 或者 (
类型(self)
是
张量
和
不
状态):
定制路径用于没有 Python 状态的常规张量。
返回 self._reduce_ex_internal(
协议)
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.__reduce_ex__, (self,), self,
协议)
函数, args = self._reduce_ex_internal(proto)
# 需要在这里清除大小/步长缓存,因为它将被重新缓存
# 如果提前清除。注意,状态引用的是实际的张量字典。
self._清除非序列化缓存数据()
返回 (
从类型重建_v2, (
函数,
类型(self),
参数,
状态))
[文档] def storage(self):
r"""
storage() -> torch.TypedStorage
返回底层的 :class:`TypedStorage`。
.. 警告::
class:`TypedStorage` 已弃用。它将在未来被移除,而
class:`UntypedStorage` 将成为唯一的存储类。要访问
直接使用 :class:`UntypedStorage`,请使用 :attr:`Tensor.untyped_storage()`。
"""
如果有 torch_function_unary(self):
返回 handle_torch_function(Tensor.storage, (self,), self)
torch.storage._warn_typed_storage_removal(stacklevel=2)
return self._typed_storage()
仅限内部使用,避免引发弃用警告
def _typed_storage(self):
未类型化存储 = self.
未类型化存储()
返回
PyTorch.
类型化存储(
包装存储=
未类型化存储,
数据类型=self.
数据类型,
内部=
真实
)
def _reduce_ex_internal(self, 原型):
检查序列化命名张量(self)
来自 torch.utils.hooks
导入
如果有钩子则警告
# 请参阅注释[不要序列化钩子]
警告如果存在钩子(self)
向后钩子:
字典[
任何,
任何] =
有序字典()
跳过数据 =
PyTorch.
序列化.
序列化 TLS.
跳过数据
材料化假张量 = (
PyTorch.
序列化.
序列化 TLS.
实现伪造张量
)
如果 self.
设备.
类型
在 ["xla",
"玛雅"]
或者 (
不
PyTorch._C._has_storage(self)
和 self.
设备.
类型 ==
PyTorch._C._get_privateuse1_backend_name()
):
如果
跳过数据:
抛出
运行时错误(
无法在跳过数据上下文管理器下将张量序列化到没有存储的后端
)
CPU 张量 = self.cpu()
返回 (
PyTorch.
_工具.
从 CPU 张量重建设备张量,
(cpu_tensor, self.数据类型, str(self.
设备), self.
需要梯度),
)
# 旧评论已不再适用。
# 注意:Numpy 数组被选为 XLA、MTIA、MAIA 张量的重建组件。
# 我们考虑了几种选择:
# 1. 这里不能使用 CPU 张量。
否则在 torch.load 中,CPU 存储以随机方式重建
初始化数据,移动到后端设备,然后更新存储
将序列化内容添加到其中。这对于 CPU/CUDA 来说效果很好,但不适用于这些后端。
他们的张量与存储断开连接,因此不会收到更新。
由于性能原因,Python 列表不是一个好的选择。
`tolist()`会将张量中的每个元素都转换为 Python 对象。
然后将它们一个接一个地序列化。
如果 self.
设备.
类型
在 [
翻译
]
在将 BFloat16 张量转换为 numpy 之前,请将其转换为 Float32,因为 numpy 不支持 BFloat16。
由于 numpy 不支持 BFloat16,重建张量时将接受原始 self.dtype,从而从 numpy 中重建 BFloat16 张量。
这将重建 numpy 中的 BFloat16 张量。
如果
跳过数据:
抛出
运行时错误(
在 skip_data 上下文管理器下,无法序列化没有存储的 backend 上的张量。
)
numpy 张量 = (
self.cpu().numpy()
如果 self.dtype !=
PyTorch.bfloat16
否则 self.cpu().
到(
PyTorch.float32).numpy()
)
返回 (
PyTorch.
_工具.
从 NumPy 重建设备张量,
(numpy 张量, self.
数据类型, str(self.
设备), self.
需要梯度),
)
如果 self.
设备.
类型 ==
元数据:
# 注意:此实现会破坏存储共享。当前
没有人关心元张量。
如果
跳过数据:
警告.
警告(
在跳过数据上下文管理器下,将张量序列化到元设备上是一个无操作。
)
arg_meta = (
self.数据类型,
元组(self.
尺寸()),
self.步长(),
self.需要梯度,
)
返回 (
PyTorch.
_工具.
重建元张量不存储,
参数元)
如果 self.
是否量化:
如果
跳过数据:
抛出
运行时错误(
"无法在跳过数据上下文管理器下序列化 qtensor,如需此功能请提交问题"
)
# quantizer_params 的类型可以根据 torch 属性的不同而不同
量化器参数:
联合[
元组[
PyTorch.
q 方案, float, int
]
元组[
任何,
张量,
张量, int]
]
如果 self.
q 方案() ==
PyTorch.
每张张量仿射:
量化器参数 = (
PyTorch.
每张张量仿射,
self.q_scale(),
self.q_zero_point(),
)
如果...否则 self.
q 方案()
在 (
PyTorch.
每通道仿射,
PyTorch.
每通道仿射浮点量化参数,
):
# 将尺度因子和零点转换为元组以避免递归调用
# 当/如果未来我们得到多轴量化张量,形状
# 可以从主张量形状中恢复
量化参数 = (
PyTorch.
每通道仿射变换,
self.每通道缩放的 q(),
self.
q_per_channel_zero_points
q_per_channel_零点(),
self.每通道轴的 q(),
)
否则:
抛出
运行时错误(
f"不支持序列化类型为张量的序列化"{self.
q 方案()}"
)
# TODO: 一旦我们决定在断开序列化 FC 后不再
需要使用 TypedStorage 包装
args_qtensor = (
PyTorch.
存储.
类型化存储(
包装存储=self._typed_storage().
未类型化存储,
数据类型=self.
数据类型,
内部=True,
),
self.storage_offset(),
元组(self.
尺寸()),
self.步长(),
量化器参数,
self.需要梯度,
后向钩子,
)
返回 (
PyTorch.
_工具.
重建_qtensor,
args_qtensor 参数)
如果...否则 self.is_sparse:
如果 self.
布局 ==
PyTorch.
稀疏 COO:
args_sparse 稀疏参数 = (
self.布局,
(self.索引(), self.
值(), self.
尺寸(), self.
是否合并()),
)
否则:
抛出
不支持的操作异常(
f稀疏张量 __reduce_ex__ 用于布局 `{self.
布局}
)
返回 (
PyTorch.
_工具.
重建稀疏张量, args_sparse)
如果...否则 self.
布局
在 {
PyTorch.
稀疏压缩存储格式,
PyTorch.
稀疏压缩存储格式,
PyTorch.
稀疏_bsr,
PyTorch.
稀疏矩阵,
}:
如果 self.
布局
在 {
PyTorch.
稀疏压缩存储格式,
PyTorch.
稀疏_bsr}:
压缩索引,
平凡索引 = (
self.鸡索引(),
self.列索引(),
)
否则:
压缩索引,
平凡索引 = (
self.c 列索引(),
self.行索引(),
)
稀疏压缩参数 = (
self.布局,
(
压缩索引,
平凡索引,
self.值(),
self.尺寸(),
),
)
返回 (
PyTorch.
_工具.
重建稀疏张量,
args 稀疏压缩)
如果...否则 self.
是嵌套的:
如果
跳过数据:
抛出
运行时错误(
在 skip_data 上下文管理器下无法序列化嵌套张量,如需此功能请提交问题
)
args 嵌套 = (
# NB: values() 当前以不安全的方式返回存储为缓冲区。
# 理想情况下,我们会使用私有 API 来完成这项工作。TODO: 如果可行,切换到这个 API。
# 如果我们最终添加了它,我们将解决这个问题。
self.值(),
self._嵌套张量大小(),
self._嵌套张量步长(),
self._嵌套张量存储偏移量(),
)
返回 (
PyTorch.
_工具.
_重建嵌套张量,
args 嵌套)
如果...否则 (
类型(self)
是
不
PyTorch.
张量
和
类型(self).
__torch 分派__
是
不
PyTorch.
张量.__torch_dispatch__
和 (
isinstance(self, PyTorch.
子类.functional_tensor.FunctionalTensor)
或者 (
不 isinstance(self,
PyTorch.
子类.fake_tensor.
假 Tensor)
和 self.
数据指针() == 0
)
)
):
参数包装子类 = (
类型(self),
self.数据类型,
元组(self.
尺寸()),
self.步长(),
self.存储偏移(),
self.布局,
self.设备,
self.需要梯度,
)
返回 (
PyTorch.
_工具.
重建包装子类,
参数包装子类)
如果...否则 (
类型(self)
是
不
PyTorch.
张量
和
类型(self).__torch_dispatch__
是
不
PyTorch.
张量.__torch_dispatch__
和 (
isinstance(self, PyTorch.
子类.
模拟张量.
模拟 Tensor)
和
不 (
跳过数据
和
材料化伪造张量)
)
):
参数包装子类 = (
类型(self),
self.数据类型,
元组(self.
尺寸()),
self.步长(),
self.存储偏移(),
self.布局,
self.设备,
self.需要梯度,
)
返回 (
PyTorch.
_工具.
重建包装子类,
参数包装子类)
否则:
v3 数据类型 =
PyTorch.
存储._new_dtypes()
如果 self.dtype
在
v3 数据类型:
重建函数 =
PyTorch.
_工具.
_重建_v3 张量
存储 = self.
未类型化存储()
否则:
# TODO:一旦我们决定要中断序列化 FC,就不再
需要使用 TypedStorage 包装
重建函数 =
PyTorch.
_工具.
_重建张量_v2
# 类型:忽略[赋值]
存储 =
PyTorch.
存储.
类型化存储(
包装存储=self._typed_storage().
未类型化存储,
数据类型=self.
数据类型,
内部=True,
) # 类型:忽略[赋值]
# TODO: 移除 hasattr,这是一个为了支持旧版 torch 而采用的 hack
# 不要有_subclasses
如果 (
有属性(
PyTorch,
_subclasses)
和 isinstance(self,
PyTorch.
子类.fake_tensor.
伪造张量)
和
跳过数据
):
存储.
_假设备 = self.
设备
args = (
存储,
self.存储偏移(),
元组(self.
尺寸()),
self.步长(),
self.需要梯度,
后退钩子,
) #之前是 self._backward_hooks
如果 isinstance(
存储,
PyTorch.
存储.
未类型化存储):
args = args + (self.数据类型,)
# 类型:忽略[赋值]
元数据 =
PyTorch.
_工具.
获取张量元数据(self)
如果
元数据:
args = args + (元数据,)
# 类型:忽略[赋值]
返回 (rebuild_func,
参数)
def __setstate__(self, 状态):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.__setstate__, (self,), self,
状态)
# 警告:当你使用 torch.load()加载张量时,此方法不会被调用;
# 这是由_rebuild_tensor_v2 管理的
如果
不 self.
是否为叶子节点:
抛出
运行时错误(
"__setstate__只能在叶子张量上调用")
如果
长度(
状态) == 4:
# 线张量序列化
self.集合(*
状态)
返回
如果...否则
长度(
状态) == 5:
# 变量序列化
self.数据 =
状态[0]
状态 = (
状态[3
]
状态[4
]
状态[2])
# _backward_hooks 的设置预期为空操作。
# 参考注释 [不要序列化钩子]
self.需要梯度, _, self._backward_hooks =
状态
def __repr__(self, *, 张量内容=
无):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.__repr__, (self,), self,
张量内容=
张量内容
)
# 所有字符串在 Python 3 中都是 Unicode。
返回
PyTorch._tensor_str.
字符串(self,
张量内容=
张量内容)
[文档] def
反向(
self, 渐变=
无, retain_graph=
无,
创建图=False,
输入=
无
):
r计算当前张量相对于图叶的梯度。
使用链式法则对图进行微分。如果张量不是标量(即其数据包含多个元素)且需要梯度,则函数还需要指定一个“梯度”。
如果张量非标量(即其数据包含多个元素)且需要计算梯度,则该函数还需要额外指定一个“梯度”。
如果张量非标量(即其数据包含多个元素)且需要梯度,则函数还需要指定一个“梯度”。
应该是一个类型和形状匹配的张量,表示对“self”的微分函数的梯度。
表示对“self”的微分函数的梯度。
此函数在叶子节点中累积梯度 - 你可能需要将其清零。
在调用之前,请查看 `.grad` 属性或将其设置为 `None`。
请参阅::ref:`默认梯度布局`。
关于累积梯度的内存布局详情。
.. 注意::
如果运行任何前向操作,创建“gradient”,以及/或调用“backward”。
在用户指定的 CUDA 流上下文中,请参阅
ref:`反向传播的流语义`.
.. 注意::
当提供 `inputs` 并给定输入不是叶子节点时,
当前实现将调用其 grad_fn(尽管获取这些梯度并非绝对必要)。
这是一个实现细节,用户不应依赖。
更多详情请见 https://github.com/pytorch/pytorch/pull/60521#issuecomment-867061780。
参数:
梯度(张量,可选):函数相对于 ``self`` 的梯度
的微分
此参数可以省略,如果 ``self`` 是标量
retain_graph(布尔值,可选):如果 ``False``,则用于计算
毕业生将被释放。请注意,在几乎所有情况下设置
这个选项设置为 True 是不必要的,通常可以绕过
以更高效的方式。默认值为
``创建图``。
创建图(布尔值,可选):如果 ``True``,则创建导数的图
可以构建,允许计算高阶导数
products。默认为 ``False``。
输入(Tensor 序列,可选):相对于该梯度将被
累积到 ``.grad`` 的。所有其他张量将被忽略。如果没有提供,
则梯度将累积到所有叶张量中。
用于计算 :attr:`张量`。
"""
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
反向,
(self,),
self,
渐变=
渐变,
retain_graph=retain_graph,
创建图=
创建图,
输入=
输入,
)
PyTorch.
自动微分.
反向(
self, 渐变, retain_graph,
创建图,
输入=
输入
)
[文档] def register_hook(self, hook):
注册反向钩子。
每次计算相对于梯度的梯度时,都会调用此钩子。
张量已计算。钩子应具有以下签名::
hook(grad) -> Tensor 或 None
钩子不应修改其参数,但可以可选地返回
一个新的梯度,该梯度将用于替换 :attr:`grad`。
该函数返回一个带有方法 `handle.remove()` 的句柄
该方法从模块中移除钩子
.. 注意::
有关此钩子何时执行的更多信息,请参阅 :ref:`backward-hooks-execution`
执行过程及其相对于其他钩子的执行顺序。
示例::
>>> v = torch.tensor([0., 0., 0.], requires_grad=True)
>>> h = v.register_hook(lambda grad: grad * 2) # 将梯度加倍
>>> v.backward(torch.tensor([1., 2., 3.]))
>>> v.grad
2
4
6
[torch.FloatTensor of size (3,)]
>>> h.remove() # 移除钩子
"""
if has_torch_function_unary(self):
return handle_torch_function(Tensor.register_hook, (self,), self, hook)
if not self.requires_grad:
raise RuntimeError(
无法在不需要梯度的张量上注册钩子
)
如果 self._backward_hooks 是 None:
self._backward_hooks = 有序字典()
如果 self.grad_fn 不为 None:
self.grad_fn._register_hook_dict(self)
从 torch.utils.hooks 导入 RemovableHandle
handle = RemovableHandle(self._backward_hooks)
self._backward_hooks[handle.id] = hook
return handle
[文档] def register_post_accumulate_grad_hook(self, hook):
r注册一个在梯度累积之后运行的回退钩子。
钩子将在张量所有梯度累积后调用
这意味着该张量上的 .grad 字段已被更新。该帖子
累积梯度钩子仅适用于叶张量(无子张量的张量)
在非叶子张量上注册此钩子将报错!
该钩子应具有以下签名:
hook(param: Tensor) -> None
注意,与其它自动微分钩子不同,此钩子作用于张量
这需要梯度而不是梯度本身。钩子可以就地修改
并访问其 Tensor 参数,包括其.grad 字段。
此函数返回一个带有方法`handle.remove()`的句柄
该方法从模块中移除钩子。
.. 注意::
查看::ref:`backward-hooks-execution` 了解有关此钩子何时执行的更多信息
执行方式及其相对于其他钩子的执行顺序。由于
这个钩子在反向传播期间运行,它将以 no_grad 模式运行(除非
创建图是 True)。您可以使用 torch.enable_grad()重新启用自动微分
在钩子中,如果您需要的话。
示例::
>>> v = torch.tensor([0., 0., 0.], requires_grad=True)
>>> lr = 0.01
>>> # 模拟简单的 SGD 更新
>>> h = v.register_post_accumulate_grad_hook(lambda p: p.add_(p.grad, alpha=-lr))
>>> v.backward(torch.tensor([1., 2., 3.]))
>>> v
tensor([-0.0100, -0.0200, -0.0300], requires_grad=True)
>>> h.remove() # 移除钩子
"""
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.register_post_accumulate_grad_hook, (self,), self,
钩子
)
如果
不 self.
需要梯度:
抛出
运行时错误(
"无法在不需要梯度的张量上注册钩子"
)
如果 self.grad_fn
是
不
无:
抛出
运行时错误(
"非叶子张量上无法注册后累加梯度钩子"
)
如果 self._post_accumulate_grad_hooks
是
无:
self._post_accumulate_grad_hooks: 字典[
任何,
任何] =
有序字典()
来自 torch.utils.hooks
导入
可移除句柄
handle = 可移除句柄(self._post_accumulate_grad_hooks)
self._post_accumulate_grad_hooks[处理.id] =
钩子
返回
处理
def 加强(self,
奖励):
def 剪辑(str):
返回 "
输入文本翻译为简体中文为:\n".
连接
[
行.strip() for
行
在 str.
分割("
输入文本翻译为简体中文为:\n"
)))
抛出
运行时错误(
去除(
r"reinforce() 已移除。
使用 torch.distributions 代替。
请参阅 https://maskerprc.github.io/docs/main/distributions.html
取代:
probs = policy_network(state)
action = probs.multinomial()
next_state, reward = env.step(action)
action.reinforce(reward)
action.backward()
使用:
probs = policy_network(state)
# NOTE: categorical 是以前所说的 multinomial 的等价物
m = torch.distributions.Categorical(probs)
action = m.sample()
next_state, reward = env.step(action)
loss = -m.log_prob(action) * reward
loss.backward()
"""
)
)
detach = _C._添加文档字符串(
_C.TensorBase.detach,
r""
返回一个新的 Tensor,与当前图分离。
结果永远不会需要梯度。
此方法还会影响前向模式 AD 梯度,并且结果将永远不会
具有前向模式的 AD 梯度。
.. 注意::
返回的 Tensor 与原始 Tensor 共享相同的存储空间。
对任一 Tensor 的就地修改都将被看到,并可能触发
正确性检查中的错误。
"沉浸式翻译",
)
断开连接 = _C.
_添加文档字符串(
_C.TensorBase.断开连接,
r""
从创建它的图中分离张量,使其成为叶子节点。
视图不能就地分离。
此方法还会影响前向模式 AD 梯度,结果将不会有前向模式 AD 梯度。
将不会有前向模式 AD 梯度。
""",
)
[文档] def is_shared(self):
r"""检查张量是否在共享内存中。
对于 CUDA 张量,这始终是 ``True``。
"""
如果有 torch_function_unary(self):
返回 handle_torch_function(Tensor.is_shared, (self,), self)
返回 self._typed_storage()._is_shared()
[文档] def share_memory_(self):
r"""将底层存储移动到共享内存。
如果底层存储已经位于共享内存中,则此操作不执行任何操作。
对于 CUDA 张量也是如此。共享内存中的张量不能调整大小。
查看更多详情,请参阅::meth:`torch.UntypedStorage.share_memory_`。
"""
如果 has_torch_function_unary(self) 为真:
返回 handle_torch_function(Tensor.share_memory_, (self,), self)
self._typed_storage()._share_memory_()
return self
[文档] def module_load(self, other, assign=False):
r"""定义了在 :meth:`~nn.Module.load_state_dict` 中将 ``other`` 载入 ``self`` 时如何转换。"""
当 `:func:`~torch.__future__.get_swap_module_params_on_conversion` 为 `True` 时使用。
预期 `self` 是 `nn.Module` 中的一个参数或缓冲区,而 `other` 是具有相应键的状态字典中的值。
此方法定义了在通过 `other` 与 `self` 交换之前,`other` 将如何重新映射。
通过 `other` 与 `self` 交换之前,`other` 将如何重新映射。
在 :meth:`~nn.Module.load_state_dict` 中的 :func:`~torch.utils.swap_tensors`。
.. 注意::
此方法应始终返回一个新对象,该对象不是 ``self`` 或 ``other``。
例如,默认实现返回 ``self.copy_(other).detach()``。
如果 `assign` 为 `False` 或 `assign` 为 `True` 时调用 `other.detach()`。
参数:
other (Tensor):与 `self` 对应键的 state dict 中的值
assign (bool):传递给 :meth:`nn.Module.load_state_dict` 的 assign 参数
"""
如果有 torch_function_variadic(self, other)函数:
返回 handle_torch_function(
Tensor.module_load, (self, other), self, other, assign=assign
)
如果分配:
返回 other.detach()
否则:
返回 self.copy_(other).detach()
def __倒序__(self):
r将张量沿维度 0 反转。
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
__倒序__, (self,), self)
如果 self.
维度() == 0:
返回 self
否则:
返回 self.
翻转(0)
[文档] def norm(
self,
p: Optional[Union[float, str]] = "fro",
dim=None,
keepdim=False,
dtype=None,
):
r"""参见 :func:`torch.norm`"""
if has_torch_function_unary(self):
return handle_torch_function(
Tensor.norm, (self,), self, p=p, dim=dim, keepdim=keepdim, dtype=dtype
)
return torch.norm(self, p, dim, keepdim, dtype=dtype)
def 求解(self, other):
来自 torch._linalg_utils
导入
解决
返回
求解(self, other)
def 最小二乘法(self, other):
来自 torch._linalg_utils
导入 lstsq
返回
最小二乘法(self, other)
def 特征向量(self,
特征向量=False):
来自 torch._linalg_utils
导入
特征值
返回
特征向量(self,
特征向量=
特征向量)
def 特征值(self,
特征向量=False):
来自 torch._linalg_utils
导入 _symeig
返回 _symeig(self,
特征向量=
特征向量)
[文档] def lu(self, pivot=True, get_infos=False):
查看函数:torch.lu
如果 get_infos 为 True,则不需要检查错误,反之亦然
如果 has_torch_function_unary(self)为真:
返回 handle_torch_function(
Tensor.lu, (self,), self, pivot=pivot, get_infos=get_infos
)
LU, pivots, infos = torch._lu_with_info(
self, pivot=pivot, check_errors=(not get_infos)
)
如果获取信息:
返回 LU、pivots、infos
否则:
返回 LU,转置
[文档] 定义 stft(
self,
n_fft: 整数,
hop_length: 可选[int] = None,
win_length: 可选[int] = None,
window: "可选[Tensor]" = None,
center: bool = True,
pad_mode: str = "reflect",
normalized: bool = False,
onesided: Optional[bool] = None,
return_complex: Optional[bool] = None,
align_to_window: 可选[bool] = None,
):
r"""参见 :func:`torch.stft`
.. 警告::
这个函数在版本 0.4.1 中改变了签名。使用之前的签名调用可能会导致错误或返回不正确的结果。
使用之前的签名调用可能会导致错误或返回不正确的结果。
"""
如果 has_torch_function_unary(self):
return handle_torch_function(
Tensor.stft,
(self,),
self,
n_fft
hop_length=hop_length
win_length=win_length
window=window
center=居中,
pad_mode=填充模式,
normalized=归一化,
onesided=单边,
return_complex=return_complex,
align_to_window=align_to_window,
)
return torch.stft(
self,
n_fft,
hop_length,
win_length,
窗口,
居中,
填充模式,
标准化,
单方面,
return_complex=return_complex,
align_to_window=align_to_window,
)
[文档] def istft(
self,
n_fft: int,
hop_length: Optional[int] = None,
win_length: 可选[int] = None,
window: "Optional[Tensor]" = None,
center: bool = True,
normalized: bool = False,
onesided: 可选[bool] = None,
length: 可选[int] = None,
return_complex: bool = False,
):
查看函数:`torch.istft`
如果有 torch 函数一元运算符(self):
返回 handle_torch_function(
Tensor.istft,
self,
self,
n_fft,
hop_length=hop_length,
win_length=win_length,
window=window,
center=center,
normalized=normalized,
onesided=onesided,
length=length,
return_complex=return_complex,
)
return torch.istft(
self,
n_fft,
hop_length,
win_length,
window,
center,
normalized,
单方面的,
长度,
return_complex=return_complex,
)
def 调整大小(self, *
尺寸):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
调整大小, (self,), self, *
尺寸)
警告.
警告(
"非原地调整大小已弃用")
来自 torch.autograd._functions
导入
调整大小
返回
调整大小.
应用(self,
尺寸)
def 调整为(self,
张量):
如果 has_torch_function_variadic(self,
张量):
返回 handle_torch_function(
张量.
调整为, (self,
张量), self,
张量)
警告.
警告(
"原地 resize_as 已弃用")
来自 torch.autograd._functions
导入
调整大小
返回
调整大小.
应用(self,
张量.
尺寸())
[文档] def split(self, split_size, dim=0):
查看函数::func:`torch.split`
if has_torch_function_unary(self):
return handle_torch_function(
Tensor.split, (self,), self, split_size, dim=dim
)
如果 split_size 是 Tensor 类型:
尝试:
split_size = int(split_size)
except ValueError:
pass
if isinstance(split_size, (int, torch.SymInt)):
return torch._VF.split(self, split_size, dim) # 忽略未定义的属性
else:
return torch._VF.split_with_sizes(self, split_size, dim)
[文档] def unique(self, sorted=True, return_inverse=False, return_counts=False, dim=None):
返回输入张量的唯一元素。
查看 :func:`torch.unique`
""
如果 has_torch_function_unary(self):
return handle_torch_function(
Tensor.unique
(self,)
self
sorted=sorted,
return_inverse=return_inverse,
return_counts=return_counts,
dim=dim,
)
return torch.unique(
self,
sorted=sorted,
return_inverse=return_inverse,
return_counts=return_counts,
dim=dim,
)
[文档] def unique_consecutive(self, return_inverse=False, return_counts=False, dim=None):
移除每个等效元素连续组中除了第一个元素之外的所有元素。
查看 :func:`torch.unique_consecutive`
"""
if has_torch_function_unary(self):
return handle_torch_function(
Tensor.unique_consecutive,
(self,)
self,
return_inverse=return_inverse,
return_counts=return_counts,
dim=dim,
)
return torch.unique_consecutive(
self, return_inverse=return_inverse, return_counts=return_counts, dim=dim
)
@_handle_torch_function_and_wrap_type_error_to_not_implemented
def __rsub__(self, other):
返回 _C.
_变量函数.
反向子集(self, other)
@_handle_torch_function_and_wrap_type_error_to_not_implemented
def __rdiv__(self, other):
返回 self.
相互() *
其他
__rtruediv__ = __rdiv__
__itruediv__ = _C.TensorBase.__idiv__
__pow__ = 角色(
可调用[
["torch._C.TensorBase", 联合[
"张量", int, float, bool,
复杂]],
"张量",
]
处理 torch 函数并将类型错误包装为未实现(
_C.TensorBase.幂
),
)
__ipow__ = 处理 torch 函数并将类型错误包装为未实现(
_C.TensorBase.pow_
)
@_handle_torch_function_and_wrap_type_error_to_not_implemented
def __rmod__(self, other):
返回
PyTorch.
剩余(other, self)
def 格式化(self,
格式说明):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
格式化, (self,), self,
格式规范)
如果 self.
维度() == 0
和
不 self.
是否元数据
和
类型(self)
是
张量:
返回 self.
项目().
格式化(
格式规范)
返回
对象.
格式化(self,
格式规范)
@_handle_torch_function_and_wrap_type_error_to_not_implemented
def __rpow__(self, other):
返回
PyTorch.pow(other, self)
@_handle_torch_function_and_wrap_type_error_to_not_implemented
def __floordiv__(self, other):
返回
PyTorch.
向下取整除(self, other)
@_handle_torch_function_and_wrap_type_error_to_not_implemented
def __rfloordiv__(self, other):
返回
PyTorch.
向下取整除(other, self)
@_handle_torch_function_and_wrap_type_error_to_not_implemented
def __rlshift__(self, other):
返回
PyTorch.
按位左移(other, self)
@_handle_torch_function_and_wrap_type_error_to_not_implemented
def __rrshift__(self, other):
返回
PyTorch.
位右移(other, self)
@_handle_torch_function_and_wrap_type_error_to_not_implemented
def __rmatmul__(self, other):
返回
PyTorch.
矩阵乘法(other, self)
__pos__ = _C.TensorBase.正向
负 = _C.TensorBase.
负
绝对值 = _C.TensorBase.
绝对值
def __len__(self):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.__len__, (self,), self)
如果 self.
维度() == 0:
抛出
类型错误(
"0 维张量的 len()")
如果
PyTorch._C.
获取跟踪状态():
警告.
警告(
使用 len 获取张量形状可能会导致跟踪不正确。
建议的使用方法是 tensor.shape[0]。
传递不同形状的张量可能会导致错误或静默给出。
"结果不正确。",
分类=
PyTorch.
算子.
跟踪警告,
栈级别=2,
)
返回 self.
形状[0]
def __iter__(self):
# NB: 我们在这里使用 'imap' 而不是 'map',这样在 Python 2 中我们得到一个
# 生成器,并且不会立即执行所有索引。这可以
# 节省我们的工作,并且也有助于保持跟踪顺序的确定性
# (例如,如果您对 hiddens 进行 zip(*hiddens),急切映射将强制所有
# 隐藏层[0]的索引在隐藏层[1]之前,而生成器
# 地图将交错它们。
# 注意:我们故意在这里跳过了 __torch_function__ 分发。
# See gh-54457
如果 self.
维度() == 0:
抛出
类型错误(
"迭代一个 0 维张量")
如果
PyTorch._C.
_获取追踪状态():
警告.
警告(
"迭代张量可能会导致追踪结果不正确。"
"传递不同形状的张量不会改变执行的迭代次数(可能会导致错误或静默地给出错误的结果)。"
"迭代次数执行(可能会导致错误或静默地给出错误的结果)。"
"请在此处不要处理 __torch_function__,因为这是用户的默认行为。",
分类=
PyTorch.
算子.
跟踪警告,
栈级别=2,
)
返回
迭代(self.
解绑(0))
def __哈希__(self):
# 请在此处不要处理 __torch_function__,因为这是用户的默认行为。
实现处理大多数功能的机制很可能会出错。
可以通过定义此方法在用户处轻松覆盖。
如需,可进行子类化。
返回 id(self)
def __dir__(self):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.__dir__, (self,), self)
张量方法 =
目录(self.
类)
张量方法.
删除(
易挥发的)
# 已弃用
属性 =
列表(self.
字典.
键())
键 =
张量方法 + attrs
# 仅在密集、CUDA 张量中可用的属性
如果 (
不 self.
是否为 CUDA)
或者 self.is_sparse:
键.
删除("__cuda_array_interface__")
返回
排序(
键)
# Numpy 数组接口,以支持 `numpy.asarray(tensor) -> ndarray`
__数组优先级__ = 1000
# 优先使用 Tensor 操作而非 NumPy
def __数组__(self,
数据类型=
无):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
__数组__, (self,), self,
数据类型=
数据类型)
如果 dtype
是
无:
返回 self.numpy()
否则:
返回 self.numpy().astype(
数据类型,
复制=False)
# 将完成的 Numpy 数组再次包裹在合适的张量中,以支持例如
`numpy.sin(tensor) -> tensor` 或 `numpy.greater(tensor, 0) -> ByteTensor`
def __数组包装__(self,
数组):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
__数组包装__, (self,), self,
数组=
数组
)
如果
数组.dtype == bool:
torch 没有内置的 bool 张量
数组 =
数组.astype(
uint8)
返回
PyTorch.
从 NumPy 转换(
数组)
def 包含(self,
元素:
任何, /) -> bool:
r检查 `元素` 是否存在于张量中
参数:
元素(张量或标量):要检查的元素
检查是否存在于当前张量中
"""
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
包含, (self,), self,
元素)
如果 isinstance(
元素, (
PyTorch.
张量,
数字,
PyTorch.SymInt,
PyTorch.SymFloat,
PyTorch.
符号布尔值)
):
类型提示不理解 __contains__ 结果数组
返回 bool((
元素 == self).
任何().
项目())
# 类型:忽略[联合属性]
抛出
运行时错误(
f"Tensor.__contains__ 只支持 Tensor 或标量,但你传递了"{
类型(
元素)}
。
)
@property
def __cuda_array_interface__(self):
CUDA 张量的数组视图描述。
参考:
https://numba.pydata.org/numba-doc/latest/cuda/cuda_array_interface.html
"""
如果 has_torch_function_unary(self):
# TODO mypy 不支持@property 属性,参考:https://github.com/python/mypy/issues/6185
返回 handle_torch_function(
张量.__cuda_array_interface__.__get__,
# 类型:忽略[已定义]
(self,),
self,
)
对于不支持的张量,将引发 AttributeError 异常
如果没有 "__cuda_array_interface__" 属性,则表示不是 CUDA 张量类型。
如果
不 self.
是否为 CUDA:
抛出
属性错误(
f无法在非 CUDA 张量类型上获取 "__cuda_array_interface__":{self.
类型()} "
如果需要 CUDA 数据,请使用 tensor.cuda() 将张量复制到设备内存。
)
如果 self.is_sparse:
抛出
属性错误(
f"无法在稀疏类型上获取 __cuda_array_interface__:"{self.
类型()} "
"请使用 Tensor.to_dense() 首先将张量转换为稠密张量。"
)
运行时错误,匹配 tensor.__array__() 的行为。
如果 self.
需要梯度:
抛出
运行时错误(
"无法在需要求导的 Variable 上获取 __cuda_array_interface__。"
"如果不需要梯度,请使用 var.detach() 获取不需要求导的 Variable。"
)
类型字符串 = _dtype_to_typestr(self.
数据类型)
元素大小 = self.
元素大小()
形状 =
元组(self.
形状)
如果 self.
连续的():
# __cuda_array_interface__ v2 要求省略 strides
# (未设置或设置为 None)对于 C-连续数组。
步长 =
无
否则:
步长 =
元组(s *
元素大小 for s
在 self.
步长())
数据指针 = self.
数据指针()
如果 self.
元素数量() > 0
否则 0
数据 = (
数据指针, False)
只读为假
返回
字典(
类型字符串=
类型字符串,
形状=
形状,
步长=
步伐,
数据=
数据,
版本=2)
[文档] def 存储类型(self):
r"""存储类型() -> 类型
返回底层存储的类型。
"""
如果有 torch_function_unary(self):
返回 handle_torch_function(Tensor.storage_type, (self,), self)
torch.storage._warn_typed_storage_removal()
return self._typed_storage()._get_legacy_storage_class()
[文档] def refine_names(self, *names):
r"""根据 :attr:`names` 优化 :attr:`self` 的维度名称。
优化是一种特殊的重命名方式,可以将未命名的维度“提升”。
一个“无名称”维度可以被细化为任何名称;一个已命名的维度只能被
细化为相同的名称。
因为命名张量可以与未命名的张量共存,所以细化名称
为编写既适用于命名张量又适用于未命名张量的命名张量感知代码提供了一种
命名和未命名的张量。
attr:`names` 可能包含最多一个省略号(``...``)。
省略号贪婪地展开;它就地展开以填充
attr:`names` 到与 `self.dim()` 相同的长度,使用名称从
对应于 `self.names` 的索引。
Python 2 不支持省略号,但可以使用字符串字面量
(`'...'`)代替。
参数:
输出张量的名称(字符串的可迭代对象):期望的输出张量名称。最多可以包含一个省略号。
可以包含一个省略号。
示例::
>>> imgs = torch.randn(32, 3, 128, 128)
>>> named_imgs = imgs.refine_names('N', 'C', 'H', 'W')
>>> named_imgs.names
('N', 'C', 'H', 'W')
>>> tensor = torch.randn(2, 3, 5, 7, 11)
>>> tensor = tensor.refine_names('A', ..., 'B', 'C')
>>> tensor.names
('A', None, None, 'B', 'C')
.. 警告::
命名张量 API 是实验性的,可能会发生变化。
"""
如果有 torch_function_unary(self):
返回 handle_torch_function(Tensor.refine_names, (self,), self, *names)
names = resolve_ellipsis(names, self.names, "refine_names")
return super().refine_names(names)
[文档] def align_to(self, *names):
r"""调整 :attr:`self` 张量的维度以匹配顺序
在 :attr:`names` 中指定的,为任何新的名称添加一维。
使用此方法之前,:attr:`self` 的所有维度都必须命名。
结果张量是原始张量上的视图。
attr:`self` 的所有维度名称都必须存在于 :attr:`names` 中。
attr:`names` 可能包含不在 ``self.names`` 中的额外名称;
输出张量对于每个新名称都有一个大小为 1 的维度。
attr:`names` 可能最多包含一个省略号(``...``)。
省略号展开后等于 :attr:`self` 的所有维度名称。
那些在 :attr:`names` 中未提及的,按照它们出现的顺序
在 :attr:`self` 中。
Python 2 不支持省略号,但可以使用字符串字面量
(``'...'``)代替。
Args:
names (字符串的可迭代对象): 输出张量的期望维度顺序。最多可包含一个省略号,该省略号将展开为所有未提及的维度名称,即:attr:`self`。
输出张量的期望维度顺序。最多可包含一个省略号,该省略号将展开为所有未提及的维度名称,即:attr:`self`。
输出张量的期望维度顺序。最多可包含一个省略号,该省略号将展开为所有未提及的维度名称,即:attr:`self`。
示例::
>>> tensor = torch.randn(2, 2, 2, 2, 2, 2)
>>> named_tensor = tensor.refine_names('A', 'B', 'C', 'D', 'E', 'F')
# 将 F 和 E 维度移到前面,其余维度保持顺序
>>> 命名张量对齐到('F', 'E', ...)
.. 警告::
命名张量 API 是实验性的,可能会更改。
"""
if has_torch_function_unary(self):
return handle_torch_function(Tensor.align_to, (self,), self, *names)
ellipsis_idx = single_ellipsis_index(names, "align_to")
if ellipsis_idx is None:
return super().align_to(names)
return super().align_to(
[name for name in names if not is_ellipsis(name)], ellipsis_idx
)
[文档] def unflatten(self, dim, sizes): # type: ignore[override]
r"""
unflatten(dim, sizes) -> Tensor
查看 :func:`torch.unflatten`.
"""
如果有 torch_function_unary(self)函数
返回 handle_torch_function(Tensor.unflatten, (self,), self, dim, sizes)
如果 sizes 为空
raise RuntimeError("unflatten: 大小必须非空")
names = None
if isinstance(sizes, OrderedDict) or (
isinstance(sizes, (tuple, list)) and isinstance(sizes[0], (tuple, list))
):
names, sizes = unzip_namedshape(sizes)
return super().unflatten(dim, sizes, names)
else:
return super().unflatten(dim, sizes)
[文档] def rename_(self, *names, **rename_map):
"""原地版本 of :meth:`~Tensor.rename`."""
if has_torch_function_unary(self):
return handle_torch_function(
Tensor.rename_(self,), self, *names, **rename_map
)
# Note [rename_ / rename API]
Python API 与 C++ API 的实现方式不同。在 Python 中:
1) tensor.rename(*names) 接受一个可变参数列表的名称。
2) tensor.rename(**rename_map) 接受一个名称到重命名的映射。
C++ 是静态的,这使得实现类似的行为变得困难。
return update_names(self, names, rename_map, inplace=True)
[文档] def rename(self, *names, **rename_map):
"""重命名 :attr:`self` 的维度名称。
有两种主要用法:
`self.rename(**rename_map) 返回一个具有维度的张量视图`
重命名为映射中指定的:`rename_map`。
返回一个张量视图,重命名所有
使用 `:attr:`names` 定位维度。
使用 `self.rename(None)` 来删除张量上的名称。
不能同时指定位置参数 :attr:`names` 和关键字参数 :attr:`rename_map`。
attr:`rename_map`。
示例::
>>> imgs = torch.rand(2, 3, 5, 7, names=('N', 'C', 'H', 'W'))
>>> renamed_imgs = imgs.rename(N='batch', C='channels')
>>> renamed_imgs.names
('batch', 'channels', 'H', 'W')
>>> renamed_imgs = imgs.rename(None)
>>> renamed_imgs.names
(None, None, None, None)
>>> renamed_imgs = imgs.rename('batch', 'channel', 'height', 'width')
>>> 重命名图片文件名
('批次', '通道', '高度', '宽度')
.. 警告::
命名张量 API 是实验性的,可能会发生变化。
"""
如果有 torch_function_unary(self):
返回 handle_torch_function(
Tensor.rename, (self,), self, *names, **rename_map
)
# 请见笔记 [重命名_ / 重命名 API]
返回 update_names(self, names, rename_map, inplace=False)
[文档] def to_sparse_coo(self):
将张量转换为:ref:`坐标格式 `.
示例::
>>> dense = torch.randn(5, 5)
>>> 稀疏矩阵 = 稠密矩阵.to_sparse_coo()
>>> 稀疏矩阵._nnz()
25
"""
返回 self.to_sparse()
[文档] def
维度排序(
self, *, 模糊性检查:
联合[bool,
列表[
PyTorch.
内存格式]] =
假
):
""
dim_order(ambiguity_check=False) -> tuple
返回唯一确定的描述维度排序的 int 元组
自身的物理布局。
维度顺序表示稠密张量在内存中的布局方式,
从最外层维度到最内层维度。
注意,维度顺序不一定总是唯一确定的。
如果 `ambiguity_check` 为 True,当维度顺序无法唯一确定时,此函数将引发 RuntimeError;
如果 `ambiguity_check` 是一个内存格式的列表,当张量无法解释为给定的内存格式之一,或者无法唯一确定时,此函数将引发 RuntimeError;
如果 `ambiguity_check` 为 False,它将返回一个合法的维度顺序(s)而无需检查其唯一性。
如果 `ambiguity_check` 为 False,它将返回一个合法的维度顺序(s)而无需检查其唯一性。
否则将引发 TypeError。
参数:
ambiguity_check (bool 或 List[torch.memory_format]):维度顺序模糊性检查方法。
示例:
>>> torch.empty((2, 3, 5, 7)).dim_order()
(0, 1, 2, 3)
>>> torch.empty((2, 3, 5, 7)).transpose(1, 2).dim_order()
(0, 2, 1, 3)
>>> torch.empty((2, 3, 5, 7), memory_format=torch.channels_last).dim_order()
(0, 2, 3, 1)
>>> torch.empty((1, 2, 3, 4)).dim_order()
(0, 1, 2, 3)
>>> 尝试:
... torch.empty((1, 2, 3, 4)).dim_order(ambiguity_check=True)
... except RuntimeError as e:
... print(e)
张量维度顺序不唯一,或无法映射到给定的内存格式之一。
>>> torch.empty((1, 2, 3, 4)).dim_order(
... 模糊性检查=[torch.contiguous_format, torch.channels_last]
... ) # 可以映射到连续格式
(0, 1, 2, 3)
>>> 尝试:
... torch.empty((1, 2, 3, 4)).dim_order(ambiguity_check="ILLEGAL")
... except TypeError as e:
... print(e)
ambiguity_check 参数必须是布尔值或内存格式的列表。
..警告::
dim_order 矩阵 API 是实验性的,可能会更改。
"""
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.dim_order, (self,), self)
如果 self.is_sparse:
抛出
属性错误(
f"无法在稀疏类型上获取 dim_order:"{self.
类型()} "
"首先使用 Tensor.to_dense()转换为稠密张量。"
)
# 稳定性检查数据类型
如果
不 isinstance(
稳定性检查, bool):
如果
不 isinstance(
稳定性检查,
列表):
抛出
类型错误(
"ambiguity_check 参数必须是布尔值或内存格式的列表。"
)
for 内存格式
在 ambiguity_check:
如果
不 isinstance(
内存格式,
PyTorch.
内存格式):
抛出
类型错误(
"ambiguity_check 参数必须是布尔值或内存格式的列表。"
)
def 无效的唯一内存格式(
张量,
有效的内存格式):
""
如果张量无法唯一映射到给定的任何内存格式,则返回 True,否则返回 False。
"""
合法性 = 0
for 内存格式
在
有效的内存格式:
如果
张量.
是否连续(
内存格式=
内存格式):
合法性数量 += 1
返回 n_legality != 1
def has_multiple_dim_order(张量):
""
如果给定的张量存在多个合法的维度顺序,则返回 True,否则返回 False。
当满足以下任一条件时,张量被认为具有多个合法的维度顺序:
单例维度:张量中至少有一个单例维度。
由于它们的大小为 1,它们不会影响内存偏移(步长 * 索引)。
这为零,因为索引始终为零)。因此,它们可以放置在维度顺序中的任何位置,而不会改变数据访问方式。
因此,它们可以放置在维度顺序中的任何位置,而不会改变数据访问方式。
* 相同步长:步长反映了张量在内存中的存储方式。
如果两个维度具有相同的步长,交换这两个维度不会
改变数据访问方式,从而导致多个正确的维度顺序。
"""
大小 =
张量.
尺寸()
步伐 =
张量.
步长()
# 检查是否有重复的步伐
存在重复步伐 =
任何(
早期 ==
后来 for
更早,
后来
在 zip(
步伐, strides[1
])
)
# 检查是否存在任何单例维度
has_singleton_dims = 任何(
大小 == 1 for
大小
在
尺寸)
返回
具有重复步长
或者
具有单例维度
有效的内存格式 = (
模糊性检查
如果 isinstance(
模糊性检查,
列表)
否则
输入文本为空,请提供需要翻译的文本
)
检查多个维度顺序 = (
模糊性检查
如果 isinstance(
模糊性检查, bool)
否则
真实
)
如果 (
检查多维度顺序
和
具有多维度顺序(self)
) 和
无效的唯一内存格式(self,
有效的内存格式):
抛出
运行时错误(
张量维度顺序不唯一,或无法映射到给定的内存格式之一。
)
导入 torch._prims_common as
工具
返回
元组(
工具.compute_elementwise_output_logical_to_physical_perm(self))
def _update_names(self, names, 原地):
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量._update_names, (self,), self, names,
内置
)
# 请参阅注释 [重命名_ / 重命名 API]
如果
原地:
返回
超级().
重命名_(names)
否则:
返回
超级().
重命名(names)
@classmethod
def __torch_function__(类,
函数,
类型,
参数=(), kwargs=
无):
""
这个 __torch_function__ 实现包装了子类,以便
子类上调用的方法返回子类实例而不是
一个 `torch.Tensor` 实例。
这一结果的一个推论是,你需要为 torch.Tensor 提供覆盖
实现子类 __torch_function__ 的方法。
我们建议始终调用 `super().__torch_function__` 作为基类
当执行上述操作时。
虽然不是强制性的,但我们建议将`__torch_function__`设为类方法。
"""
如果 kwargs
是
无:
kwargs = {}
如果
不
所有(
派生类(
类, t) for t
在
类型):
返回 NotImplemented
替换为 _C.
禁用 TorchFunction 子类():
返回 =
函数(*
参数, **kwargs)
如果
函数
在
获取默认不换行函数():
返回
返回
否则:
返回
转换(
返回,
类)
__torch_dispatch__ = _C.禁用 torch 分发实现
def __dlpack__(self, 流=
无):
""
创建一个 DLpack `胶囊 https://data-apis.org/array-api/latest/design_topics/data_interchange.html#data-interchange`
将当前张量导出到其他库中。
此函数将从 `from_dlpack` 方法中调用。
消费胶囊的库将调用此方法。`from_dlpack` 作为规范的一部分将流传递给此方法。
流作为规范的一部分传递给此方法。
参数:
流(整数或 None):表示 CUDA 流的 Python 整数,可选
指向 CUDA 流的指针。在创建胶囊之前,当前流与此流同步,并且胶囊与张量共享存储,因此从该流访问是安全的
这使得从该流访问胶囊是安全的,因为胶囊与张量共享存储
因此,从该流访问胶囊是安全的
两个流。如果传入 None 或-1,则不执行同步。
如果为 1(在 CUDA 上)或 0(在 ROCM 上),则使用默认流。
用于同步。
"""
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.
dlpack, (self,), self,
流)
DLPack 胶囊无法捕获 PyTorch 的所有语义
因此,我们禁止导出会失去其属性的张量
# 需要梯度并且设置了共轭位。
如果 self.
需要梯度:
抛出
运行时错误(
"无法导出需要梯度的张量,请使用 tensor.detach()"
)
如果 self.
是连词():
抛出
运行时错误(
"无法导出设置了共轭位的张量")
如果 self.
布局 !=
PyTorch.strided:
抛出
运行时错误(
"无法导出布局不是 torch.strided 的张量"
)
如果
流
是
不
无
和
类型(
流)
是
不 int:
CUDA/ROCm 中的流指针是唯一编号的,并且可以
从它们的整数值中检索。
抛出
类型错误(
流必须是 ``int`` 或 ``none``)
如果...否则
流
是
不
无
和
流 != -1:
如果 self.
设备.
类型 ==
cuda:
# 注意:此逻辑处理默认值的特殊情况
流必须与 from_dlpack 保持同步
torch/utils/dlpack.py
如果
流 == 1
和
PyTorch.
版本.hip
是
无:
流 =
PyTorch.cuda.
默认流()
如果...否则
流 == 0
和
PyTorch.
版本.hip
是
不
无:
流 =
PyTorch.cuda.
默认流()
否则:
流 =
PyTorch.cuda.
外部流(
流)
# 仅在不同流上同步
同步流 =
PyTorch.cuda.current_stream()
如果
流 !=
同步流:
事件 =
PyTorch.cuda.
活动()
事件.
记录(
同步流)
流.
等待事件(
事件)
如果 self.
设备.
类型 == "xla":
导入 torch_xla
导入 torch_xla.utils.dlpack as xla_dlpack
如果 (
长度(torch_xla.real_devices()) <= 0
或者 "cuda"
不
在 torch_xla.real_devices()[0].
小写()
):
抛出
运行时错误(
无法导出非 CUDA 上的 XLA 张量到 dlpack。
)
返回 xla_dlpack.
转换为 dlpack(self)
返回
PyTorch.
转换为 dlpack(self)
def __dlpack_device__(self) -> 元组[
枚举.
整数枚举, int
]
如果 has_torch_function_unary(self):
返回 handle_torch_function(
张量.__dlpack_device__, (self,), self)
来自 torch.utils.dlpack
导入
DL 设备类型
设备 = self.
设备
索引 =
设备.
索引
如果
设备.
索引
是
不
无
否则 0
火炬设备类型 =
设备.
类型
如果
火炬设备类型 == "cuda"
和
PyTorch.
版本.hip
是
不
无:
设备类型 =
深度学习设备类型.kDLROCM
如果...否则
火炬设备类型 ==
cpu
和 self.is_pinned():
设备类型 =
DL 设备类型.kDLCPUPinned
如果...否则
火炬设备类型 ==
cuda:
设备类型 =
DL 设备类型.kDLGPU
如果...否则
火炬设备类型 == "cpu":
设备类型 =
DL 设备类型.kDLCPU
如果...否则
torch 设备类型 ==
XPU:
设备类型 =
DL 设备类型.
kDL 单 API
如果...否则 self.
设备.
类型 ==
privateuse1:
设备类型 =
DL 设备类型.
kDL 扩展设备
如果...否则
火炬设备类型 == "xla":
导入 torch_xla
如果 (
长度(torch_xla.
真实设备()) <= 0
或者 "cuda"
不
在 torch_xla.
真实设备()[0].
小写()
):
抛出
值错误(f
"未知设备类型"{torch_device_type}
用于 Dlpack)
设备类型 =
DL 设备类型.kDLGPU
否则:
抛出
值错误(f
"未知设备类型"{
火炬设备类型} for Dlpack")
返回 (
设备类型,
索引)
__module__ = torch
def _convert(返回,
类):
如果
类
是
张量:
返回
返回
如果 isinstance(
返回,
张量)
和
不 isinstance(
返回,
类):
返回 =
返回.
作为子类(
类)
如果 isinstance(
返回, (
元组,
列表)):
也处理像 namedtuple 这样的东西
返回 =
类型(
返回)(
转换(r,
类) for r
在
返回)
返回
返回