torch.Storage()是什么?和torch.Tensor()有什么区别?

简介: torch.Storage()是什么?和torch.Tensor()有什么区别?

一、介绍

       torch.Tensor()大家都很熟悉,torch中操作的数据类型都是Tensor。Storage在实际使用中却很少接触,但它却非常重要,因为Tensor真正的数据存储在Storage中,接下来我将结合代码简单的介绍一下Storage。

 官方文档:PACKAGE参考 - torch.Storage - 《PyTorch中文文档》

       Storage的位置:torch.Storage()

       官方解释:

一个torch.Storage是一个单一数据类型的连续一维数组。

每个torch.Tensor都有一个对应的、相同数据类型的存储。

二、真正的数据存在Storage中

       我们可以用 torch.Tensor()新建一个Tensor,并且规定形状。一个Tensor分为头信息区和存储区(Storage)。信息区主要保存张量的形状(size)、步长(stride)、数据类型(dtype)等信息。真正的数据保存在存储区。


       代码如下:

import torch
 
data1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
tensor_data1 = torch.Tensor(data1)
print("tensor_data1.size():", tensor_data1.size())
print("tensor_data1.dtype:", tensor_data1.dtype)
print("tensor_data1.storage():", tensor_data1.storage())
 
# 输出如下:
# tensor_data1.size(): torch.Size([3, 3])
# tensor_data1.dtype: torch.float32
# tensor_data1.storage():  1.0
#  2.0
#  3.0
#  4.0
#  5.0
#  6.0
#  7.0
#  8.0
#  9.0

       可以看到Tensor有size、type等属性,真正的数据存在Storage中。

三、Storage是连续一维数组

       Tensor无论形状如何,torch.Storage都是一个单一数据类型的连续一维数组。我们可以直接创建一个Storage对象,但是想要进行计算梯度、反向传播、正向传播等操作,还是需要将Storage转换成Tensor。

       代码如下:

import torch
 
data1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
storage_date1 = torch.Storage(data1)
# Storage转Tensor
tensor_data1 = torch.Tensor(storage_date1)
print("storage_date1:", storage_date1)
 
# storage_date1:  1.0
#  2.0
#  3.0
#  4.0
#  5.0
#  6.0
#  7.0
#  8.0
#  9.0
# [torch.storage._TypedStorage(dtype=torch.float32, device=cpu) of size 9]


四、每个Tensor都有一个对应的Storage

       Tensor有如下几种数据类型:

class DoubleTensor(Tensor): ...
class FloatTensor(Tensor): ...
class LongTensor(Tensor): ...
class IntTensor(Tensor): ...
class ShortTensor(Tensor): ...
class HalfTensor(Tensor): ...
class CharTensor(Tensor): ...
class ByteTensor(Tensor): ...
class BoolTensor(Tensor): ...

       每种Tensor都有对应类型的Storage,使用torch.Tensor()新建默认是FloatTensor。

import torch
 
data1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
tensor_data1 = torch.Tensor(data1)
tensor_data331 = tensor_data1.view(3, 3, 1)
print("id(tensor_data1) == id(tensor_data331):", id(tensor_data1) == id(tensor_data331))
print("id(tensor_data1.storage()) == id(tensor_data331.storage()):", id(tensor_data1.storage()) == id(tensor_data331.storage()))
 
# id(tensor_data1) == id(tensor_data331): False
# id(tensor_data1.storage()) == id(tensor_data331.storage()): True

      可以看到,虽然我将tensor_data1变换了形状付给另外一个变量,但是数据的内容并没有变,两个变量引用的是相同的数据存储

       而且我发现一个有意思的事情,一旦创建了Tensor,它的Storage数值是不变的。即使改变数据类型,它的真实值也不会变。比如下面这个例子,我将float的数据类型变成int,再变回float,它的小数也不会丢,内存地址也不会变:

import torch
 
data1 = [[1.1, 2.1, 3.1], [4.1, 5.1, 6.1], [7.1, 8.1, 9.1]]
tensor_data1 = torch.Tensor(data1)
tensor_data_int = tensor_data1.int()
tensor_data_f = tensor_data1.float()
print("tensor_data1:", tensor_data1.storage())
print("tensor_data_int:", tensor_data_int.storage())
print("tensor_data_f:", tensor_data_f.storage())
# 两个Tensor内存地址肯定不一样,因为是两个对象
print("id(tensor_data_int) == id(tensor_data_f):", id(tensor_data_int) == id(tensor_data_f))
# 虽然数据类型不一样,但是两个Storage内存地址一样,因为类型其实是跟着Tensor走的
print("id(tensor_data_int.storage()) == id(tensor_data_f.storage()):", id(tensor_data_int.storage()) == id(tensor_data_f.storage()))
 
# tensor_data1:  1.100000023841858
#  2.0999999046325684
#  3.0999999046325684
#  4.099999904632568
#  5.099999904632568
#  6.099999904632568
#  7.099999904632568
#  8.100000381469727
#  9.100000381469727
# [torch.storage._TypedStorage(dtype=torch.float32, device=cpu) of size 9]
# tensor_data_int:  1
#  2
#  3
#  4
#  5
#  6
#  7
#  8
#  9
# [torch.storage._TypedStorage(dtype=torch.int32, device=cpu) of size 9]
# tensor_data_f:  1.100000023841858
#  2.0999999046325684
#  3.0999999046325684
#  4.099999904632568
#  5.099999904632568
#  6.099999904632568
#  7.099999904632568
#  8.100000381469727
#  9.100000381469727
# [torch.storage._TypedStorage(dtype=torch.float32, device=cpu) of size 9]
# id(tensor_data_int) == id(tensor_data_f): False
# tensor_data_int.storage().type(): torch.int32 torch.float32
# id(tensor_data_int.storage()) == id(tensor_data_f.storage()): True
相关文章
|
机器学习/深度学习 资源调度
【机器学习】高斯分布-概率密度函数
【1月更文挑战第23天】【机器学习】高斯分布-概率密度函数
【机器学习】高斯分布-概率密度函数
|
6月前
|
数据采集 机器学习/深度学习 人工智能
AI 十大论文精讲(二):GPT-3 论文全景解析——大模型 + 提示词如何解锁 “举一反三” 能力?
摘要 2020年发表的《Language Models are Few-Shot Learners》(GPT-3论文)开创了AI新时代。该论文突破性地证明:当Transformer模型参数规模扩大到1750亿时,仅通过文本交互即可实现任务无关的少样本学习。GPT-3采用"预训练+提示词"的新范式,无需微调就能在翻译、问答等40+任务上展现强大性能。论文系统验证了模型在语言建模、闭卷问答等9类任务中的表现,其中在LAMBADA长文本任务上准确率达86.4%,较此前最优提升18.4%。这一研
1004 152
|
5月前
|
存储 NoSQL Java
从单机到集群:Redis部署全攻略
本文全面解析Redis四种核心部署方式:单机版部署简单适合开发测试;主从复制实现读写分离和数据备份;哨兵模式提供自动故障转移能力;Redis Cluster集群支持分片存储和横向扩展。文章详细阐述了每种方案的原理、部署步骤、Java代码实现及适用场景,并给出生产环境选型指南。通过对比各方案优缺点,帮助开发者根据业务需求(数据量、并发量、可用性要求等)选择最佳部署方式,同时提供参数优化建议和常见问题解决方案。
369 2
|
缓存 网络协议
Jmeter如何对UDP协议进行测试?
`jmeter-plugins`是JMeter的插件管理器,用于管理和组织所有插件。访问[官网](https://jmeter-plugins.org/install/Install/)下载并放置于`lib/ext`目录下,重启JMeter后可在“选项”中看到插件管理器。
585 1
Jmeter如何对UDP协议进行测试?
|
人工智能 测试技术 决策智能
玩转智能体魔方!清华推出AgentSquare模块化搜索框架,开启AI智能体高速进化时代
清华大学研究团队提出模块化LLM智能体搜索(MoLAS)框架AgentSquare,将LLM智能体设计抽象为规划、推理、工具使用和记忆四大模块,实现模块间的轻松组合与替换。通过模块进化和重组机制,AgentSquare显著提升了智能体的适应性和灵活性,并在多个基准测试中表现出色,平均性能提高17.2%。此外,该框架还具备可解释性,有助于深入理解智能体架构对任务性能的影响。论文地址:https://arxiv.org/abs/2410.06153
531 10
|
消息中间件 人工智能 安全
秒级灾备恢复:Kafka 2025 AI自愈集群下载及跨云Topic迁移终极教程
Apache Kafka 2025作为企业级实时数据中枢,实现五大革新:量子安全传输(CRYSTALS-Kyber抗量子加密算法)、联邦学习总线(支持TensorFlow Federated/Horizontal FL框架)、AI自愈集群(MTTR缩短至30秒内)、多模态数据处理(原生支持视频流、3D点云等)和跨云弹性扩展(AWS/GCP/Azure间自动迁移)。平台采用混合云基础设施矩阵与软件依赖拓扑设计,提供智能部署架构。安装流程涵盖抗量子安装包获取、量子密钥配置及联邦学习总线设置。
|
编译器 API 调度
JAX 中文文档(十二)(1)
JAX 中文文档(十二)
371 0
|
JavaScript BI 数据处理
computed 与 method 结合使用的示例
【10月更文挑战第15天】Computed 与 Method 的结合使用为 Vue 应用的开发提供了更多的可能性和灵活性。通过合理运用,可以更好地处理数据计算和逻辑操作,提高应用的性能和可维护性。在实际开发中,要根据具体需求和场景,巧妙地将两者结合起来,以达到最佳效果。
248 3
|
网络协议 Ubuntu Linux
用Qemu模拟vexpress-a9 (三)--- 实现用u-boot引导Linux内核
用Qemu模拟vexpress-a9 (三)--- 实现用u-boot引导Linux内核
1129 1

热门文章

最新文章