【PyTorch与深度学习】1、PyTorch介绍与张量的创建

课程地址
最近做实验发现自己还是基础框架上掌握得不好,于是开始重学一遍PyTorch框架,这个是课程笔记

1. 张量Tensor

张量是一种特殊的数据结构,与数组和矩阵非常相似。在 PyTorch 中,我们使用张量对模型的输入和输出以及模型的参数进行编码。张量与NumPy 的ndarray类似,不同之处在于张量可以在 GPU 或其他硬件加速器上运行。事实上,张量和 NumPy 数组通常可以共享相同的底层内存(原地操作),从而无需复制数据。张量还针对自动微分进行了优化。
PyTorch导入包的过程:

import torch
import numpy as np

1.1 创建张量

1.1.1 从列表中创建一个张量tensor

data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)

x_data的结果:
tensor([[1, 2],
[3, 4]])

创建一个浮点型的列表:

import torch
import numpy as np
data = [[1, 2.0],[3, 4]]
x_data = torch.tensor(data)
print(x_data)
print(type(x_data))  # 打印存储张量的变量的类型
print(x_data.dtype)  # 打印张量中每一个元素的类型

运行结果:
tensor([[1., 2.],
[3., 4.]])
<class ‘torch.Tensor’>
torch.float32

1.1.2 从numpy数组中创建张量tensor

import torch
import numpy as np
a = np.random.normal((2, 3)) # 按正态分布创建一个ndarray
tensor_a = torch.tensor(a)
print(tensor_a)

运行结果:
tensor([0.5312, 3.4150], dtype=torch.float64)

import torch
import numpy as np
a = np.random.normal((2, 3)) # 按正态分布创建一个ndarray
tensor_a = torch.from_numpy(a)
print(tensor_a)

运行结果:
tensor([2.1416, 2.2480], dtype=torch.float64)

【提问】上述两种方式从numpy数组中创建的tensor有何不同?
【chatGPT回答】在PyTorch中,从numpy数组创建张量主要有两种方式:torch.Tensor() 和 torch.from_numpy()。这两种方法虽然都可以从numpy数组转换成PyTorch张量,但它们之间有一些重要的不同点:

  1. 内存共享
  • torch.from_numpy(): 这个方法创建的张量与原始的numpy数组共享相同的内存。这意味着如果你修改了numpy数组的内容,相应的PyTorch张量的内容也会随之改变,反之亦然。这种方法效率很高,因为它避免了数据复制,但也需要注意数据在numpy数组和张量间是同步的。
  • torch.Tensor():使用这个构造函数时(或者 torch.tensor(),它更加推荐用于创建新张量),PyTorch会创建一个复制了numpy数组数据的新张量。这种方式不会与原始numpy数组共享内存,因此,修改原numpy数组不会影响到PyTorch张量,反之亦然。
  1. 数据类型自动转换:
  • torch.Tensor(): 在使用这个方法时,PyTorch通常会自动推断出一个合适的数据类型。如果numpy数组的数据类型与PyTorch默认的数据类型不匹配,PyTorch可能会自动转换数据到一个新的数据类型。
  • torch.from_numpy(): 使用这种方法时,创建的PyTorch张量将直接采用numpy数组的数据类型。不会进行数据类型的自动转换。
    用法:
  • torch.Tensor():这是一个更一般的构造函数,可用于从列表、numpy数组等创建张量,但因为它涉及到数据的复制,可能不如 > - torch.from_numpy() 高效。
  • torch.from_numpy(): 专门用于从numpy数组直接创建张量,效率更高,因为避免了数据复制。

总结来说,选择哪种方式取决于你是否需要原始数据和张量之间的内存共享以及对数据类型的处理方式。如果你希望避免不必要的数据复制并且可以管理内存共享带来的副作用,torch.from_numpy() 是一个更好的选择。如果你需要从一个数组创建一个独立的张量,并可能需要转换数据类型,torch.Tensor() 或 torch.tensor() 可能更适合你的需求。

1.1.3 从其他张量创建张量tensor

新张量保留参数张量的属性(形状、数据类型),除非显式覆盖。

import torch
import numpy as np
data = [[1, 2], [3, 4]]
x_data = torch.tensor(data)
x_ones = torch.ones_like(x_data) # 创建一个和x_data张量大小一样的全为1的张量
print(f"Ones Tensor: \n {x_ones} \n")

x_ones = torch.zeros_like(x_data) # 创建一个和x_data张量大小一样的全为0的张量
print(f"Zeros Tensor: \n {x_ones} \n")

x_rand = torch.rand_like(x_data, dtype=torch.float) # 创建一个和x_data张量大小一样的全为随机数的张量
print(f"Random Tensor: \n {x_rand} \n")

运行结果:
Ones Tensor:
tensor([[1, 1],
[1, 1]])

Zeros Tensor:
tensor([[0, 0],
[0, 0]])

Random Tensor:
tensor([[0.5124, 0.8001],
[0.8218, 0.9406]])

1.1.4 使用随机值或常数创建张量tensor

shape是张量维度的元组,如果将shape 改成列表也是可以的,但是不能写成集合{2,3},那样会报错。在下面的函数中,它确定输出张量的维数。

import torch
import numpy as np
shape = (2,3,)  # 张量维度的元组,最后一个逗号能去掉,这是一个2×3的张量
rand_tensor = torch.rand(shape)  # 按shape的维度大小创建一个随机值的张量
ones_tensor = torch.ones(shape)  # 按shape的维度大小创建一个全为1的张量
zeros_tensor = torch.zeros(shape)  # 按shape的维度大小创建一个全为0的张量

print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")

运行结果:
Random Tensor:
tensor([[0.0758, 0.3495, 0.7840],
[0.9438, 0.8045, 0.4455]])

Ones Tensor:
tensor([[1., 1., 1.],
[1., 1., 1.]])

Zeros Tensor:
tensor([[0., 0., 0.],
[0., 0., 0.]])

1.2 张量的属性

张量属性描述了它们的形状、数据类型以及存储它们的设备。

import torch
import numpy as np
tensor = torch.rand(3,4)

print(f"张量的维度: {tensor.shape}")
print(f"张量的元素的数据类型: {tensor.dtype}")
print(f"存储当前张量的设备: {tensor.device}")

运行结果:
张量的维度: torch.Size([3, 4])
张量的元素的数据类型: torch.float32
存储当前张量的设备: cpu

1.3 张量的操作

PyTorch有 100 多种张量运算,包括算术、线性代数、矩阵操作(转置、索引、切片)、采样等。这些操作中的每一个都可以在 GPU 上运行(速度通常高于 CPU)。默认情况下,张量是在 CPU 上创建的。我们需要使用 .to方法显式地将张量移动到 GPU(在检查 GPU 可用性之后)。请记住,跨设备复制大张量在时间和内存方面可能会很昂贵!

import torch
import numpy as np
tensor = torch.rand(3,4)

# 将张量移动到GPU(显卡)中,如果有独立显卡,可以移动
if torch.cuda.is_available():
    tensor = tensor.to("cuda")

正常运行代码不报错证明能移动到GPU中

1.3.1 常见的张量操作

(1) is_tensor:如果当前对象是 PyTorch 张量,则返回 True 。

import torch
import numpy as np
tensor = torch.rand(3,4)

print(torch.is_tensor(tensor))

运行结果:
True
(2)is_complex:如果当前的数据类型input是复数类型,即torch.complex64或torch.complex128,则返回 True。
(3)is_floating_point:如果当前的数据类型input是浮点数据类型,即torch.float64、torch.float32、torch.float16或torch.bfloat16,则返回 True。
(4)is_nonzero:input如果是单元素张量且在类型转换后不等于 0,则返回 True。

import torch
import numpy as np
a = torch.tensor(1.0)  # 单一浮点数张量1.0
print(a)
print(torch.is_nonzero(a))  # 打印True就表明a张量是一个非0的标量

a = torch.tensor(0)  # 单一浮点数张量0
print(a)
print(torch.is_nonzero(a))  #  打印False就表明a张量是一个值为0的标量

运行结果:
tensor(1.)
True
tensor(0)
False

(5)numel:返回张量中的元素总数input。

import torch
import numpy as np

a = torch.rand([2, 2])  # 创建一个2X2的随机值张量
print(torch.numel(a))  # 返回2X2张量的元素个数4

运行结果:
4

1.3.2 常见的创建张量的操作

(1)tensor:通过复制构造一个没有自动求导过的张量,使用这个构造函数时(或者 torch.tensor(),它更加推荐用于创建新张量),PyTorch会创建一个复制了numpy数组数据的新张量。这种方式不会与原始numpy数组共享内存,因此,修改原numpy数组不会影响到PyTorch张量,反之亦然。

import torch
import numpy as np

b = np.array([1, 1.2])
a = torch.tensor(b)
print(a)

运行结果:
tensor([1.0000, 1.2000], dtype=torch.float64)
(2)as_tensor:转换data为张量,共享数据并保留 自动求导的历史记录(如果可能)。
如果data已经是具有请求的 dtype 和设备的张量,则data返回其本身,但如果data是具有不同 dtype 或设备的张量,则将其复制,就像使用 data.to(dtype=dtype, device=device)一样。如果data是具有相同数据类型和设备的 NumPy 数组(ndarray),则使用 构造张量torch.from_numpy()。

import torch
import numpy as np

# a默认在CPU中创建,t从a中创建,二者共享数据,所以修改一个,两个都变
a = np.array([1, 2, 3])
t = torch.as_tensor(a)
print(t)
t[0] = -1
print(a)

# 但是将t送入GPU后,a在CPU,t在GPU,修改t,a不变
a = np.array([1, 2, 3])
t = torch.as_tensor(a, device=torch.device('cuda'))
print(t)
t[0] = -1
print(a)

运行结果:
tensor([1, 2, 3], dtype=torch.int32)
[-1 2 3]
tensor([1, 2, 3], device=‘cuda:0’, dtype=torch.int32)
[1 2 3]
(3)from_numpy:从numpy.ndarray.创建一个张量, 这个方法创建的张量与原始的numpy数组共享相同的内存。这意味着如果你修改了numpy数组的内容,相应的PyTorch张量的内容也会随之改变,反之亦然。这种方法效率很高,因为它避免了数据复制,但也需要注意数据在numpy数组和张量间是同步的。

import torch
import numpy as np

a = np.array([1, 2, 3])
t = torch.from_numpy(a)
# a 和 t是共享相同的内存的,修改t,a也被修改
print(t)
t[0] = -1
print(a)

运行结果:
tensor([1, 2, 3], dtype=torch.int32)
[-1 2 3]
(4)zeros:返回一个全为0的张量,主要参数是整型序列,用来记录生成的张量的维度大小,
关键字参数

  • out ( Tensor ,可选) – 输出张量。
  • dtype ( torch.dtype, 可选) – 返回张量所需的数据类型。默认值:如果None,则使用全局默认值,通过 torch.set_default_dtype()这个API规定的。
  • layout ( torch.layout, 可选) – 返回张量的所需布局。默认:torch.strided。
  • device (torch.device, 可选) –返回张量所需的设备。默认值:如果None,则使用当前设备作为默认张量类型(请参阅torch.set_default_device())。
  • device对于CPU 张量类型,将是 CPU;对于 CUDA 张量类型,将是当前 CUDA 设备。
  • require_grad ( bool ,可选) – 自动求导 是否应记录对返回张量的操作。默认:False。
import torch
import numpy as np

a = torch.zeros(5, 5)
print(a)
print(a.dtype)

torch.set_default_dtype(torch.float64)  # 设置默认的数据类型为float64
a = torch.zeros(5, 5)
print(a)
print(a.dtype)

运行结果:
tensor([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
torch.float32
tensor([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
torch.float64
(5)zeros_like:返回一个用标量值0填充的张量,其大小与 相同input。(下面的与上面的类似,不试了)
(6)ones:返回一个用标量值1填充的张量,其形状由变量声明定义size(参数是int整型序列,写的是所要生成的张量的维度size。
(7)ones_like:返回一个用标量值1填充的张量,其大小与 相同input。
(8)arange:返回大小为 ⌈  start-end s t e p ⌉ \left\lceil\frac{\text { start-end}}{step}\right\rceil step start-end的1维张量,[start,end),左闭右开
参数:

  • start ( Number ) – 点集的起始值。默认:0。
  • end ( Number ) – 点集的结束值
  • step ( Number ) – 每对相邻点之间的间隙。默认:1。
import torch

a = torch.arange(5)  # step为1,默认从0开始
print(a)

a = torch.arange(start=2, end=5, step=2) 
print(a)

运行结果:
tensor([0, 1, 2, 3, 4])
tensor([2, 4])

(9)range:返回大小为 ⌊  end-start   step  ⌋ + 1 \left\lfloor\frac{\text { end-start }}{\text { step }}\right\rfloor+1  step  end-start +1的1维张量,

import torch

a = torch.range(start=0, step=1, end=5)  # step为1,默认从0开始
print(a)

运行结果:
tensor([0., 1., 2., 3., 4., 5.])

【PyTorch官方的说明】该函数已被弃用,并将在未来版本中删除,因为它的行为与 Python 的 range 内置函数不一致。相反,请使用torch.arange(),它会在 [start, end) 中生成值。

(10)linspace:创建一个从start到end的均匀分布,step为步长
(11)logspace:创建一个从 l o g 底数 s t a r t log_{底数}^{start} log底数start l o g 底数 e n d log_{底数}^{end} log底数end的一维张量,step为步长,base为底数
(12)eye:创建一个二维张量,对角线上全为1,其他全为0,只传一个参数默认是方阵

import torch

a = torch.eye(3)  # 只有一个参数,默认方阵
print(a)
a = torch.eye(3, 2)
print(a)

运行结果:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
tensor([[1., 0.],
[0., 1.],
[0., 0.]])

(13)full:创建一个大小size为的张量,并且这个张量是用value填充的。

import torch

a = torch.full((3, 2), 10)  # 3x2张量,填充值为10
print(a)

运行结果:
tensor([[10, 10],
[10, 10],
[10, 10]])

(14)full_like:根据已有的维度大小创建一个填充值为value的张量。

import torch

b = torch.tensor([[1, 2], [3, 4]])
a = torch.full_like(b, 10)  # 用10填充一个和b维度一样的tensor
print(a)

运行结果:
tensor([[10, 10],
[10, 10]])

1.3.3 索引、切片、连接等操作

(1)cat:连接给定维度中给定的张量序列。传入的是一个多个张量的列表,这些张量除了被连接的那个维度以外,需要有同样的张量,dim参数是指定在哪个维度将这两个张量连接起来。

import torch

a = torch.rand([2, 2])  # 2x2拼左边
print(a)
b = torch.rand([2, 3])  # 2x3拼右侧
print(b)
print(torch.cat([a, b], dim= 1))

运行结果:
tensor([[0.3435, 0.4823],
[0.3059, 0.4247]])
tensor([[0.2637, 0.9875, 0.9034],
[0.5850, 0.1321, 0.2106]])
tensor([[0.3435, 0.4823, 0.2637, 0.9875, 0.9034],
[0.3059, 0.4247, 0.5850, 0.1321, 0.2106]])

在0维度拼接相当于上下拼接(2维):

import torch

a = torch.rand([2, 2])
print(a)
b = torch.rand([3, 2])
print(b)
print(torch.cat([a, b], dim= 0))

运行结果:
tensor([[0.5723, 0.7480],
[0.7629, 0.4247]])
tensor([[0.5585, 0.0881],
[0.6640, 0.8015],
[0.8188, 0.3602]])
tensor([[0.5723, 0.7480],
[0.7629, 0.4247],
[0.5585, 0.0881],
[0.6640, 0.8015],
[0.8188, 0.3602]])

此处我去年看李沐老师视频的时候有一段写的和这个类似,但是比较详细:按特定轴求和

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/578982.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

8K+/月!学习就业一把梭,祝贺誉天数通陈同学收获心仪offer !

大家好&#xff0c;我是誉天数通的陈同学。 在武汉&#xff0c;网络运维圈的人应该都会听过誉天的名字。作为华为的授权培训合作伙伴&#xff0c;誉天不仅提供专业全面的工程师培训&#xff0c;还以其独特的环境和氛围吸引着无数有志于在网络领域发展的朋友。 一年前的我&#…

用坐标与碰撞检测效果

用pygame碰撞检测子弹 与 子弹 格子检查是否在墙内 结果差不了多少 输出的是碰撞点坐标 在计算角色与强的距离是 你用了几条射线 2024/4/26 13:20:48 在代码中&#xff0c;用于计算角色与墙之间距离的部分是通过投射多条射线来实现的。具体来说&#xff0c;在循环中&#xf…

IDEA插件

POJO to JSON —— 实体转Json Smart Input —— 自动切换中英文 Translation —— 翻译 Maven Helper —— 依赖管理 .ignore —— 忽略提交文件 enum-quick-generate —— 枚举代码生成 粘贴到项目包下

前端更优雅的使用 jsonp

前端更优雅的使用 jsonp 背景&#xff1a;最近项目中又使用到了 jsonp 这一项跨域的技术&#xff0c;&#xff08;主要还是受同源策略影响&#xff09;&#xff0c;下面有为大家提供封装好的函数及对应使用示例&#xff0c;欢迎大家阅读理解 文章目录 前端更优雅的使用 jsonp同…

基于车载点云数据的城市道路特征目标提取与三维重构

作者&#xff1a;邓宇彤&#xff0c;李峰&#xff0c;周思齐等 来源&#xff1a;《北京工业大学学报》 编辑&#xff1a;东岸因为一点人工一点智能公众号 基于车载点云数据的城市道路特征目标提取与三维重构本研究旨在弥补现有研究在处理复杂环境和大数据量上的不足&#xf…

Qt设置可执行程序图标,并打包发布

一、设置图标 图标png转ico: https://www.toolhelper.cn/Image/ImageToIco设置可执行程序图标 修改可执行程序图标 添加一个rc文件,操作如下,记得后缀改为rc 打开logo.rc文件添加代码IDI_ICON1 ICON DISCARDABLE "logo.ico"在项目pro后缀名的文件中添加代码 RC_…

系统盘空间不足调优方式1-APPData/大文件清理

作者&#xff1a;私语茶馆 1.前言 Windows系统盘&#xff08;C盘&#xff09;很容易剩余空间不足&#xff0c;这种情况下会非常影响Windows系统的运行&#xff0c;系统盘约束非常多&#xff0c;不方便在线扩容&#xff0c;因此规划和利用好系统盘是保障整体运行效率的关键。包…

机器人系统开发ros2-基础实践01-学会自定义一个机器人动作aciton实体类

您之前在了解操作教程中了解了action 。与其他通信类型及其各自的接口&#xff08;主题/消息和服务/srv&#xff09;一样&#xff0c;您也可以在包中自定义操作。本教程向您展示如何定义和构建可与您将在下一个教程中编写的action服务器和action 客户端一起使用的操作。 需要理…

Rust 实战练习 - 12. Axum Web 简单demo

Rust Web 历程 Rust 的异步框架tokio非他莫属&#xff0c;而web框架一直是悬而未决&#xff0c;说到底还是因为没有官方成熟的方案指引&#xff0c;大家各玩各的&#xff0c;互不兼容&#xff0c;白白浪费精力。 这个事情一直等到半官方组织tokio推出axum有了改善。但是市场上…

LeetCode455:分发饼干

题目描述 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&#xff0c;都有一个…

Orange3数据可视化(组件概览)

概要 大家见过Orange3提供的丰富数据可视化组件吗&#xff1f; Orange3为您提供了一系列生动的图表工具&#xff0c;包括树图、箱线图、小提琴图、分布图、散点图、折线图、条形图、筛图、马赛克图、自由投影、线性投影、雷达图、热力图、韦恩图、轮廓图、毕达哥拉斯树、毕达哥…

关于springboot内置tomcat最大请求数配置的一些问题

前言 springboot内置了tomcat。那么一个springboot web应用&#xff0c;最大的请求链接数是多少呢&#xff1f;很早以前就知道这个是有个配置&#xff0c;需要的时候&#xff0c;百度一下即可。但&#xff0c;事实并非如此&#xff0c;有几个问题我想大多数人还真不知道。比如…

强化学习-MAPPO算法解析与实践-Multi Agent Proximal Policy Optimization

一 算法简介 mappo 是一种将ppo算法扩展到多智能体情况的算法&#xff0c;在讨论过这种算法的论文中&#xff0c;比较有名和权威的是Nips2021上发表的《The Surprising Effectiveness of PPO in Cooperative》。比较遗憾的是&#xff0c;可能作者出于自己不是最早提出mappo算法…

Avalonia UI跨平台WPF

Avalonia是一个强大的框架&#xff0c;使开发人员能够使用.NET创建跨平台应用程序。 它使用自己的渲染引擎绘制UI控件&#xff0c;确保在Windows、macOS、Linux、Android、iOS和WebAssembly等不同平台上具有一致的外观和行为。 官网链接&#xff1a; 官网链接 文档链接&#…

mstsc 远程桌面由于以下原因之一无法连接到远程计算机

问题 想使用win自带的局域网远程工具mstsc远程连接电脑。如何连接&#xff1a;只需要两台电脑在同一个局域网内&#xff0c;然后使用被远程电脑的ip地址、Microsoft用户名和密码。 但是连接的时候会跳出来如下提示&#xff1a; 远程桌面由于以下原因之一无法连接到远程计算机…

【每日刷题】Day23

【每日刷题】Day23 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 2. 链表的回文结构_牛客题霸_牛客网 …

C++11新特性:lambda表达式

目录 1.lambda表达式 1.1 C98中的一个例子 1.2 lambda表达式 1.3 lamzbda表达式语法 1. lambda表达式各部分说明 2. 捕获列表说明 1.4 函数对象与lambda表达式 1.lambda表达式 1.1 C98中的一个例子 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0…

spring的常用注解

目录 1.前言 2.web url映射 2.1RequestMapping 2.2PostMapping 2.3GetMapping 3.参数接受和接口响应 3.1RequestParam 3.2RequstBoby 3.3ResponseBoby 3.4RestController 4.bean的存储 4.1Controller 4.2Service 4.3Repository 4.4Compontent 4.5Configuration …

判断n以内的素数个数的五种方法+时间对比

目录 方法一&#xff1a;暴力法 复杂度 方法二&#xff1a;跨度为6的倍数的优化 复杂度 方法三&#xff1a;埃氏筛法 复杂度 方法四&#xff1a;埃氏筛法的改良 复杂度 方法五&#xff1a;线性筛 复杂度 性能对比测试 练习 方法一&#xff1a;暴力法 就是写一个函…

Nacos 集群 On K8s 实践服务注册发现、服务动态配置

一、K8s 部署 Nacos 集群 安装规划 组件replicas类型mysql1StatefulSetnacos3StatefulSet 使用 k8s 版本为&#xff1a;v1.18.0 。 本次使用 OpenEBS 来作为存储引擎&#xff0c;OpenEBS 是一个开源的、可扩展的存储平台&#xff0c;它提供了一种简单的方式来创建和管理持久…
最新文章