PyTorch实战-实现神经网络图像分类基础Tensor最全操作详解(一)

目录

前言

一、PyTorch数据结构-Tensor

1.什么是Tensor

2.数据Tensor使用场景

3.张量形态

标量(0D 张量)

 向量(1D 张量)

矩阵(2D张量)

3D 张量与高维张量

二、Tensor的创建

1. 从列表或NumPy数组创建

 2. 使用特定的初始化方法

 3. 从已有的Tensor创建

 三、Tensor的形状操作

1.查看大小和维度

2. 改变 Tensor 的形状

3. 移除和增加Tensor 的维度

 4.交换Tensor 维度

 5.拼接和堆叠Tensor

  6.拆分Tensor

 四、Tensor索引和切片

1.索引

 2.切片

3.通过索引和切片修改 Tensor

(1).修改单个元素的值

 (2).修改整行或整列

4.高级索引

(1).使用列表作为索引

 (2).使用布尔值作为索引(掩码)

 (3).使用 torch 的索引函数

点关注,防走丢,如有纰漏之处,请留言指教,非常感谢


前言

PyTorch可以说是三大主流框架中最适合初学者学习的了,相较于其他主流框架,PyTorch的简单易用性使其成为初学者们的首选。这样我想要强调的一点是,框架可以类比为编程语言,仅为我们实现项目效果的工具,也就是我们造车使用的轮子,我们重点需要的是理解如何使用Torch去实现功能而不要过度在意轮子是要怎么做出来的,那样会牵扯我们太多学习时间。以后就出一系列专门细解深度学习框架的文章,但是那是较后期我们对深度学习的理论知识和实践操作都比较熟悉才好开始学习,现阶段我们最需要的是学会如何使用这些工具。

深度学习的内容不是那么好掌握的,包含大量的数学理论知识以及大量的计算公式原理需要推理。且如果不进行实际操作很难够理解我们写的代码究极在神经网络计算框架中代表什么作用。不过我会尽可能将知识简化,转换为我们比较熟悉的内容,我将尽力让大家了解并熟悉神经网络框架,保证能够理解通畅以及推演顺利的条件之下,尽量不使用过多的数学公式和专业理论知识。以一篇文章快速了解并实现该算法,以效率最高的方式熟练这些知识。


博主专注数据建模四年,参与过大大小小数十来次数学建模,理解各类模型原理以及每种模型的建模流程和各类题目分析方法。此专栏的目的就是为了让零基础快速使用各类数学模型、机器学习和深度学习以及代码,每一篇文章都包含实战项目以及可运行代码。博主紧跟各类数模比赛,每场数模竞赛博主都会将最新的思路和代码写进此专栏以及详细思路和完全代码。希望有需求的小伙伴不要错过笔者精心打造的专栏。

一文速学-数学建模常用模型


 


一、PyTorch数据结构-Tensor

1.什么是Tensor

Tensor是PyTorch中最基本的数据结构,可以看作是一个多维数组(矩阵的扩展)。与NumPy中的数组类似,与其不同的是ndarrays不能使用GPU加速计算但Tensor可以在GPU上运行,这使得它在深度学习领域特别强大,归根结底还是得依赖庞大的算力支持我们才能尽可能得到更加精准的数据,通常我们叫它张量。

2.数据Tensor使用场景

没有引入张量这个概念之前,大家其实就在很多场景接触到了这些数据。了解到张量以后大家自然而然的就会明白了。张量这一概念的核心在于,它是一个数据容器。它包含的数据几乎总是数值数据,因此它是数字的容器。你可能对矩阵很熟悉,它是二维张量。张量是矩阵向任意维度的推广[注意,张量的维度(dimension)通常叫作轴(axis)]。

以下是一些常见的使用场景:

  • 神经网络的构建和训练:神经网络的输入、权重、输出、梯度等都是以Tensor的形式表示。PyTorch、TensorFlow等深度学习框架都是基于Tensor进行运算的。
  • 图像处理:图像通常以多维数组的形式表示,例如RGB图像可以表示为高度、宽度和3个颜色通道的Tensor。
  • 自然语言处理:在处理文本数据时,可以将文本编码成Tensor,每个单词可以映射为一个数字或一个词向量。
  • 时间序列分析:例如股票价格、天气数据等,可以表示成时间、特征维度的Tensor。
  • 推荐系统:用户-物品交互矩阵可以表示为一个二维的Tensor。
  • 强化学习:在Q-learning等算法中,状态、动作、奖励等信息都可以用Tensor表示。
  • 计算机视觉任务:如目标检测、分割、人脸识别等任务,输入图像、特征图、目标框坐标等都可以用Tensor表示。视频为5D张量,形状为 (samples, frames, height, width, channels) 或 (samples,frames, channels, height, width) ,图片4D张量形状为 (samples, height, width, channels) 或 (samples, channels,height, width) 。
  • 自动驾驶和机器人控制:传感器数据(如摄像头、激光雷达等)可以表示成Tensor,用于训练和实时控制。
  • 生成对抗网络(GAN):GAN中的生成器和判别器都是基于神经网络和Tensor进行训练和推断的。
  • 聚类和降维:在数据挖掘和特征工程中,Tensor可以用于聚类、主成分分析(PCA)等算法。

总的来说,Tensor作为多维数组,适用于几乎所有涉及到大规模数值计算和深度学习的领域。

这里借助numpy给大家更加直观的认识张量。

3.张量形态

标量(0D 张量)

一个只包含单个数字的张量被称为标量(scalar),也叫做标量张量、零维张量或0D张量。在NumPy中,一个float32或float64类型的数字就是一个标量张量(或标量数组)。你可以通过查看一个NumPy张量的ndim属性来了解它的轴数。标量张量具有0个轴(ndim == 0)。轴的数量也被称为阶数(rank)。以下是一个NumPy标量的例子。

import numpy as np
x = np.array(1)
print("数组中轴的个数:{}".format(x.ndim))
print(x)

数组中轴的个数:0
1

 向量(1D 张量)

  数字组成的数组叫作向量(vector)或一维张量(1D 张量)。一维张量只有一个轴。下面是一个 Numpy 向量。

x = np.array([1, 4, 7, 10, 13])
print("数组中轴的个数:{}".format(x.ndim))
print(x)

数组中轴的个数:1
[ 1  4  7 10 13]

这里需要注意一下,这个数组成为5D向量但不是5D张量,前者是数量上的数量,后者是轴的数量,大家不要搞混。

矩阵(2D张量)

 向量组成的数组叫作矩阵(matrix)或二维张量(2D 张量)。矩阵有 2 个轴(通常叫作行和列)。你可以将矩阵直观地理解为数字组成的矩形网格。下面是一个 Numpy 矩阵。

x = np.array([[1, 8, 21, 3, 78],[8, 12, 13, 32, 11],[7, 3, 5, 6, 2]])
print("数组中轴的个数:{}".format(x.ndim))
print(x)

数组中轴的个数:2
[[ 1  8 21  3 78][ 8 12 13 32 11][ 7  3  5  6  2]]

3D 张量与高维张量

将多个矩阵组合成一个新的数组,可以得到一个 3D 张量,你可以将其直观地理解为数字组成的立方体。下面是一个 Numpy 的 3D 张量。

x = np.array([[[5, 78, 2, 34, 0],[6, 79, 3, 35, 1],[7, 80, 4, 36, 2]],[[5, 78, 2, 34, 0],[6, 79, 3, 35, 1],[7, 80, 4, 36, 2]],[[5, 78, 2, 34, 0],[6, 79, 3, 35, 1],[7, 80, 4, 36, 2]]])
print(x.ndim)
print(x)

3
[[[ 5 78  2 34  0][ 6 79  3 35  1][ 7 80  4 36  2]][[ 5 78  2 34  0][ 6 79  3 35  1][ 7 80  4 36  2]][[ 5 78  2 34  0][ 6 79  3 35  1][ 7 80  4 36  2]]]

 以后我们接触到相应的数据进行张量转换的时候大家会了解的更为清晰,那么我们现在知道张量的基础概念和形式了,可以尝试着用Torch进行创建。

二、Tensor的创建

在PyTorch中,我们可以通过多种方式创建Tensor:

1. 从列表或NumPy数组创建

import torch
import numpy as np# 从列表创建
tensor_from_list = torch.Tensor([1, 2, 3, 4])# 从NumPy数组创建
numpy_array = np.array([1, 2, 3, 4])
tensor_from_numpy = torch.Tensor(numpy_array)
tensor_from_numpy

tensor([1., 2., 3., 4.])

 2. 使用特定的初始化方法

# 创建一个形状为(3, 2)的随机Tensor
random_tensor = torch.randn(3, 2)# 创建一个全零的Tensor
zero_tensor = torch.zeros(3, 2)# 创建一个全1的Tensor
ones_tensor = torch.ones(3, 2)
# 创建一个从 0 到 9 的等差数列
tensor5 = torch.arange(0, 10, 1)
# 创建一个从 0 到 1 的 5 个数的均匀间隔的数列
tensor6 = torch.linspace(0, 1, 5)
print(tensor6)
print(random_tensor)
print(zero_tensor)
print(ones_tensor)
print(tensor5)
print(tensor6)

tensor([0.0000, 0.2500, 0.5000, 0.7500, 1.0000])
tensor([[ 0.9255,  1.3031],[-1.2245, -0.5758],[-1.2821, -0.3471]])
tensor([[0., 0.],[0., 0.],[0., 0.]])
tensor([[1., 1.],[1., 1.],[1., 1.]])
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
tensor([0.0000, 0.2500, 0.5000, 0.7500, 1.0000])

 3. 从已有的Tensor创建

# 从已有的Tensor创建新的Tensor(共享内存)
new_tensor = torch.Tensor(random_tensor.size())
print(new_tensor)

tensor([[0., 0.],[0., 0.],[0., 1.]])

 三、Tensor的形状操作

1.查看大小和维度

有两个函数size()和shape都可以查看:

random_tensor.size()
#random_tensor.shape 二者结果一致

torch.Size([3, 2])

2. 改变 Tensor 的形状

# 创建一个大小为 (2, 3) 的 Tensor
tensor = torch.arange(6).view(2, 3)
# 或者使用 reshape
# tensor = torch.arange(6).reshape(2, 3)
print(tensor)

tensor([[0, 1, 2],[3, 4, 5]])

3. 移除和增加Tensor 的维度

# squeeze 用于移除大小为 1 的维度
tensor = torch.arange(6).view(1, 2, 3)
squeezed_tensor = tensor.squeeze()
print(squeezed_tensor)# unsqueeze 用于增加维度
tensor = torch.arange(6).view(2, 3)
unsqueeze_tensor = tensor.unsqueeze(0)
print(unsqueeze_tensor)

tensor([[0, 1, 2],[3, 4, 5]])
tensor([[[0, 1, 2],[3, 4, 5]]])

 4.交换Tensor 维度

# 交换维度
tensor = torch.arange(6).view(2, 3)
transposed_tensor = tensor.transpose(0, 1)  # 交换维度 0 和 1
print(transposed_tensor)

tensor([[0, 3],[1, 4],[2, 5]])

 5.拼接和堆叠Tensor

# cat 用于在指定维度上连接多个 Tensor
tensor1 = torch.arange(3)
tensor2 = torch.arange(3, 6)
concatenated_tensor = torch.cat((tensor1, tensor2), dim=0)
print(concatenated_tensor)# stack 用于在新的维度上堆叠多个 Tensor
stacked_tensor = torch.stack((tensor1, tensor2), dim=0)
print(stacked_tensor)

  6.拆分Tensor

原Tensor:

tensor = torch.arange(10).view(2, 5)
print(tensor)

 拆分结果

# split 用于在指定维度上拆分 Tensor
tensor = torch.arange(10).view(2, 5)
split_tensors = torch.split(tensor, 2, dim=1)
print(split_tensors)# chunk 用于在指定维度上将 Tensor 拆分成相等的几块
chunked_tensors = torch.chunk(tensor, 2, dim=0)
print(chunked_tensors)

 

(tensor([[0, 1],[5, 6]]), tensor([[2, 3],[7, 8]]), tensor([[4],[9]]))
(tensor([[0, 1, 2, 3, 4]]), tensor([[5, 6, 7, 8, 9]]))

 四、Tensor索引和切片

1.索引

import torch# 创建一个二维 Tensor
tensor = torch.Tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])# 访问单个元素
print(tensor[0, 0])  # 输出 1# 访问某一行
print(tensor[1])  # 输出 [4, 5, 6]# 访问某一列
print(tensor[:, 1])  # 输出 [2, 5, 8]# 使用逗号分隔访问多个不连续的元素
print(tensor[0, 0], tensor[1, 1], tensor[2, 2])  # 输出 1, 5, 9

 

tensor(1.)
tensor([4., 5., 6.])
tensor([2., 5., 8.])
tensor(1.) tensor(5.) tensor(9.)

 2.切片

# 使用切片获取子张量
print(tensor[0:2, 1:3])  # 输出 [[2, 3], [5, 6]]# 使用步长获取间隔元素
print(tensor[::2])  # 输出 [[1, 2, 3], [7, 8, 9]]# 使用负数索引倒序访问
print(tensor[-1])  # 输出 [7, 8, 9]

 

tensor([[2., 3.],[5., 6.]])
tensor([[1., 2., 3.],[7., 8., 9.]])
tensor([7., 8., 9.])

3.通过索引和切片修改 Tensor

(1).修改单个元素的值

# 创建一个二维 Tensor
tensor = torch.Tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 修改单个元素的值
tensor[0, 0] = 0
tensor

 

tensor([[0., 2., 3.],[4., 5., 6.],[7., 8., 9.]])

 (2).修改整行或整列

整行修改:

# 创建一个二维 Tensor
tensor = torch.Tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 修改整行或整列
tensor[1] = torch.Tensor([10, 11, 12])
tensor

 整列修改:

# 创建一个二维 Tensor
tensor = torch.Tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 修改整行或整列
tensor[:, 2] = torch.Tensor([30, 31, 32])
tensor

 

tensor([[ 1.,  2., 30.],[ 4.,  5., 31.],[ 7.,  8., 32.]])

4.高级索引

(1).使用列表作为索引

idx = [0, 2]
print(tensor[idx])  # 输出第 0 和第 2 行

 

tensor([[ 1.,  2., 30.],[ 7.,  8., 32.]])

 (2).使用布尔值作为索引(掩码)

mask = tensor > 5
print(tensor[mask])  # 输出所有大于 5 的元素

 

tensor([30., 31.,  7.,  8., 32.])

 (3).使用 torch 的索引函数

# 使用 torch 的索引函数
idx = torch.LongTensor([0, 2])
print(torch.index_select(tensor, 0, idx))  # 输出第 0 和第 2 行

 

tensor([[ 1.,  2., 30.],[ 7.,  8., 32.]])

点关注,防走丢,如有纰漏之处,请留言指教,非常感谢

以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见。


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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5.10.WebRTC接口宏

那今天呢?我给大家介绍一下web rtc的接口宏,那之所以在现成的章节中要介绍接口宏。是由于接口在调用的过程中啊,会发生线程的切换,所以把接口宏这部分知识我们放在线程这一章还算比较合适的。 那另外呢,我们对于接口…

分库分表---理论

目录 一、垂直切分 1、垂直分库 2、垂直分表 3、垂直切分优缺点 二、水平切分 1、水平分库 2、水平分表 3、水平切分优缺点 三、数据分片规则 1、Hash取模分表 2、数值Range分表 3、一致性Hash算法 四、分库分表带来的问题 1、分布式事务问题 2、跨节点关联查询…

IT运维:利用数据分析平台采集Windows event log数据

概述 本文将介绍如何借助Winlogbeat和Vector在鸿鹄里采集Windows event log数据,使技术人员能够在鸿鹄里更便捷和高效地分析Windows event log数据。 操作步骤 Winlogbeat是一个开源的日志数据采集器,专门用于采集Windows操作系统中的event log数据。它可…

C语言之指针进阶篇(3)

目录 思维导图 回调函数 案例1—计算器 案例2—qsort函数 关于qsort函数 演示qsort函数的使用 案例3—冒泡排序 整型数据冒泡排序 回调函数搞定各类型冒泡排序 cmp_int比较大小 cmp传参数 NO1. NO2. 解决方案 交换swap 总代码 今天我们学习指针难点之回调函数…

支付宝小程序排名优化,一个小白的成长手记

那是一个风和日丽的周末早上,阳光透过窗帘洒进屋内,温暖了我的双脚。这是我加入新公司的第一个周末,我坐在桌前,满怀激情地准备开发我的第一个支付宝小程序。【名即薇】 经过两天两夜的奋战,我终于完成了一个初版的支付宝小程序。是一个集美食资讯、餐厅点评、外卖订餐于一体的…

连nil切片和空切片一不一样都不清楚?那BAT面试官只好让你回去等通知了。

连nil切片和空切片一不一样都不清楚?那BAT面试官只好让你回去等通知了。 问题 package mainimport ("fmt""reflect""unsafe" )func main() {var s1 []ints2 : make([]int,0)s4 : make([]int,0)fmt.Printf("s1 pointer:%v, s2 p…

两种方法教你在postman设置请求里带动态token

问题描述 在使用postman调试接口时,遇到一些需要在请求里加上token的接口,若token出现变化,需要手动修改接口的token值,带来重复的工作量,翻看postman使用手册后,我发现了两种方法可以解决这个问题。 01 …

MySQL之数据类型

目录 一、MySQL数据类型分类 二、数值类型 1、整数类型 2、bit类型 3、小数类型 三、字符串类型 1、char 2、varchar 3、char和varchar比较 四、日期和时间类型 五、enum和set 一、MySQL数据类型分类 MySQL 数据类型可以大致分为以下三类: 数值类型:用于…

git快速查看某个文件修改的所有commit

1. git blame file git blame 可以显示历史修改的每一行记录,有时候我们只想了解某个文件一共提交几次commit,只显示commit列表,这种方式显然不满足要求。 2.git log常规使用 (1)显示整个project的所有commit (2)显示某个文件的所有commit 这是git log不添加参数的常规…

.Net MVC 使用Areas后存在相同Controller时报错的解决办法; 从上下文获取请求的Area名及Controller名

先来说个额外的问题:如何在请求上下文(比如过滤器的中)获取请求对应的Area和Controller 名字?(假设请求上下文对象为 filterContext ): 1. 获取Area名: (string)filterContext.RouteData.DataTo…

Windows下防火墙端口配置

在电脑或者服务器上部署某个应用后,如果需要对外提供服务可能就需要在主机防火墙上设置开启需要的端口,那么具体怎样操作呢 1.打开windows防火墙 2.设置防火墙入站规则 如下图“高级安全Windows Defender 防火墙”页面,点击左侧“入站规则”…

并联电容器交流耐压试验方法

对被试并联电容器两极进行充分放电。 检查电容器外观、 污秽等情况, 判断电容器是否满足试验要求状态。 用端接线将并联电容器两极短接连接湖北众拓高试工频耐压装置高压端, 外壳接地。 接线完成后经检查确认无误, 人员退出试验范围。 接入符合测试设备的工作电源,…

[Linux]进程间通信--管道

[Linux]进程间通信–管道 文章目录 [Linux]进程间通信--管道进程间通信的目的实现进程间通信的原理匿名管道匿名管道的通信原理系统接口管道特性管道的协同场景管道的大小 命名管道使用指令创建命名管道使用系统调用创建命名管道 进程间通信的目的 数据传输:一个进…

【多线程】常见的锁策略

常见的锁策略 1. 乐观锁 vs 悲观锁2. 读写锁 vs 普通互斥锁3. 重量级锁 vs 轻量级锁4. 自旋锁(Spin Lock)vs 挂起等待锁5. 公平锁 vs 非公平锁6. 可重入锁 vs 不可重入锁7. Synchronized8. 相关面试题 1. 乐观锁 vs 悲观锁 悲观锁: 总是假设…

GStreamer MIME类型

MIME type的全称是 Multipurpose Internet Mail Extensions (MIME) ,可以标志一个文件的类型。 Table of Audio Types Media Type Description All audio types. audio/* All audio types channels integer channel-mask bitmask format string layou…

NLP机器翻译全景:从基本原理到技术实战全解析

目录 一、机器翻译简介1. 什么是机器翻译 (MT)?2. 源语言和目标语言3. 翻译模型4. 上下文的重要性 二、基于规则的机器翻译 (RBMT)1. 规则的制定2. 词典和词汇选择3. 限制与挑战4. PyTorch实现 三、基于统计的机器翻译 (SMT)1. 数据驱动2. 短语对齐3. 评分和选择4. PyTorch实现…

MybatisPlus分页插件使用

一. 效果展示 二. 代码编写 2.1 pom <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version> </dependency>2.2 添加配置类 Configuration MapperScan(…

软考知识汇总--结构化开发方法

文章目录 1 结构化开发2 耦合3 内聚4 设计原则5 系统文档6 数据流图6.1 数据流图的基本图形元素 7 数据字典 1 结构化开发 结构化方法总的指导思想是自顶向下、逐层分解&#xff0c;它的基本原则是功能的分解与抽象。它是软件工程中最早出现的开发方法&#xff0c;特别适合于数…

U3D外包开发框架及特点

U3D&#xff08;Unity3D&#xff09;是一款流行的跨平台游戏开发引擎&#xff0c;用于创建2D和3D游戏以及交互性应用程序。U3D有许多常用的开发框架和库&#xff0c;这些框架和库可以扩展其功能&#xff0c;使开发人员更轻松地构建游戏和应用程序。以下是一些常用的U3D开发框架…

Si3262 一款低功耗刷卡+触摸+mcu 三合一SOC芯片

Si3262是-款高度集成的低功耗soC芯片&#xff0c;其集成了基于RISC-V 核的低功耗MCU和工作在13.56MHz的非接触式读写器模块。 该芯片ACD模式下刷卡距离可达4-5cm&#xff08;天线决定&#xff09;&#xff0c;适用于智能门锁&#xff0c;电子锁&#xff0c;柜锁&#xff0c;桑拿…