【深度学习】S1 预备知识 P1 张量

2024-02-13 07:52

本文主要是介绍【深度学习】S1 预备知识 P1 张量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 张量
  • 创建第一个张量
    • 张量的下载与引入
    • 创建第一个张量
  • 张量的大小和形状
    • 张量的形状
    • 张量的大小
  • 改变张量的形状
  • 创建特殊张量
  • 张量的基本运算
    • 按元素运算
    • 张量连结
    • 逻辑运算
    • 张量求和
  • 张量的广播机制
  • 张量的索引与切片
    • 索引、切片访问张量
    • 通过切片方式节省内存占用
  • 张量转换为其他对象

张量

张量(Tensor)是深度学习中用于表示和处理多维数据的数据结构。张量与 Numpy 类似,但是不同的是深度学习框架专门为张量提供了丰富的操作API,包括创建张量、数据转换、数学运算、索引和切片等,使张量可以使用 GPU 加速,大大提高处理大量数据时的计算速度;同时提供自动微分 Autograd,自动计算和应用梯度。

简单的说,张量(Tensor)就是为深度学习框架量身定制的数据结构。使用张量,深度学习在处理数据和模型计算上更加方便和高效。


创建第一个张量

张量的下载与引入

张量是深度学习框架的数据结构,读者首先需要选择一种深度学习框架(TensorFlow、PyTorch…)并下载,本博文基于 PyTorch 深度学习框架。

  1. 下载 PyTorch 框架:
# 首先下载PyTorch框架
pip install torch==1.12.0
pip install torchvision==0.13.0
# 本bash执行于Anaconda Prompt
  1. 引入 Tensor 张量:
# 建议读者使用PyCharm或者VSCode IDE工具
import torch

创建第一个张量

第一个张量我们使用 arange 创建一个行向量 x:

x = torch.arange(12)
print(x)
tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

x 为创建的包含 12 个整数元素的张量。


张量的大小和形状

张量的形状

通过张量的 shape 属性来访问张量的形状。

print(x.shape)
torch.Size([12])

张量的大小

如果只想知道张量中元素的数量,可以使用 numel() 函数。

print(x.numel())
12

改变张量的形状

如果只想改变张量的形状而不改变张量元素数量和值,可以通过使用 reshape() 函数。

y = x.reshape(3,4)
print(y)
tensor([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11]])

把张量x从形状(12,)的行向量转换为形状为(3,4)的矩阵y。新的张量形状发生改变,但是元素值并没有改变。

张量的转换也支持自动计算维度的功能,比如:

# 下列 z_1, z_2 张量同上述 reshape(3, 4) 函数功能
z_1 = x.reshape(-1, 4)
z_2 = x.reshape(3, -1)

创建特殊张量

有时,我们希望创建全0、全1张量,或者从特定随机分布中随机采样的数字来初始化矩阵,如下。

创建全 0 张量:

# 创建一个形状为 (2, 3, 4) 、值全部为 0 的三维张量
import torch
x_1 = torch.zeros(2,3,4)
print(x_1)
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.]]])

创建全 1 张量:

import torch
x_2 = torch.ones(2,3,4)
print(x_2)
print(x_2.shape)
tensor([[[1., 1., 1., 1.],[1., 1., 1., 1.],[1., 1., 1., 1.]],[[1., 1., 1., 1.],[1., 1., 1., 1.],[1., 1., 1., 1.]]])
torch.Size([2, 3, 4])

创建正态分布随机采样张量:
创建一个形状为(3,4)的张量,其中每个元素从均值为 0, 标准差为 1 的标准高斯分布中随机采样。

import torch
x = torch.randn(3,4)
print(x)
tensor([[ 0.8532, -0.9053, -0.6921,  0.9674],[-0.8108, -1.4881, -0.0434,  0.1967],[-1.7507, -0.4498,  1.3718, -0.6994]])

张量的基本运算

按元素运算

数学运算中最常见的标准算数运算符(+,-,*,/和**)。将两个张量数组作为输入,按元素运算将二元运算符应用于两个数组中的每对位置对应的元素:

import torchx = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
print("x+y=", x+y, "\nx-y=", x-y, "\nx*y=", x*y, "\nx/y=", x/y, "\nx**y=", x**y)
x+y= tensor([ 3.,  4.,  6., 10.]) 
x-y= tensor([-1.,  0.,  2.,  6.]) 
x*y= tensor([ 2.,  4.,  8., 16.]) 
x/y= tensor([0.5000, 1.0000, 2.0000, 4.0000]) 
x**y= tensor([ 1.,  4., 16., 64.])

按元素计算很重要的一点就是两个张量的形状 shape 必须相同,否则将因找不到对应位置的张量从而无法计算。

张量连结

除了按元素计算外,还可以将多个张量连结在一起 cat(tensors, dim=),端对端叠起来形成更大的张量。

import torchx = torch.arange(12).reshape(3, 4)
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(torch.cat((x,y), dim=1))

将张量 x(3,4)与张量 y(3,4)横向连结形成更大的张量,形状(3,8)。

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

dim=0 的连结结果将为形状(6,4)。

逻辑运算

通过逻辑运算构建张量,对于两个张量的每个位置,如果对照位置相同,则对应位置值为 True,否则为 False;

import torchx = torch.arange(12).reshape(3, 4)
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])print("x:", x)
print("y:", y)
print("x==y:", x==y)
x: tensor([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11]])
y: tensor([[2., 1., 4., 3.],[1., 2., 3., 4.],[4., 3., 2., 1.]])
x==y: tensor([[False,  True, False,  True],[False, False, False, False],[False, False, False, False]])

张量求和

如果想对张量中所有元素进行求和,使用 sum() 函数;

print("x:", x)
print(x.sum())
x: tensor([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11]])
tensor(66)

张量的广播机制

在上述张量的基本运算中,我们很多操作都规定需要两个张量保持相同的形状才能完成运算。但是在广播机制中,则不同。张量的广播机制用于扩展张量,虽然不要求两个向量完全相同,但是要求两个向量要分别满足形状:(x, y)与(y, z)方才可以进行运算。

e . g . e.g. e.g.

import torcha = torch.arange(3).reshape(3, 1)
b = torch.arange(2).reshape(1, 2)print("a=", a)
print("b=", b)
print("a+b=", a+b)
print("a*b=", a*b)
a= tensor([[0],[1],[2]])
b= tensor([[0, 1]])
a+b= tensor([[0, 1],[1, 2],[2, 3]])
a*b= tensor([[0, 0],[0, 1],[0, 2]])

上述张量的广播机制操作中,我们将张量 a(3,1)与张量 b(1,2)广播扩展为一个更大的张量,形状(3,2)。


张量的索引与切片

索引、切片访问张量

如 Python 中数组一样,张量中的元素支持通过索引访问。与其他数组一样,张量中第一个元素的索引值为 0,最后一个元素的索引值为 -1。

import torchx = torch.arange(12)
print("x=", x)
print("x[0]=", x[0], "\nx[-1]=", x[-1])
# 通过切片方式访问张量中的元素值
print("x[1:3]=", x[1:3])
x= tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
x[0]= tensor(0) 
x[-1]= tensor(11)
x[1:3]= tensor([1, 2])

当然张量的操作支持通过索引改变其中元素的值;

import torchx = torch.arange(12)
print(x)
x[-2] = 22
print(x)
tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 22, 11])

通过切片方式节省内存占用

在张量中,运行一些操作可能会导致需要为新结果分配内存。在深度学习框架张量中,我们可以通过 id() 函数来访问一个张量占用内存的物理位置。

import torchx = torch.arange(12)
print(id(x))
x = x + 1
print(id(x))
2606440820144
2606440818944

打印发展张量 x 在计算前后更换了占用的内存位置,或者说,新计算后为张量 x 新分配了内存空间存储其结果。

这种新分配内存空间不仅产生了不必要的内存占用,还会因为其他引用旧的内存位置导致出错。为了避免这种错误,通过切片方式原地更新;

import torchx = torch.arange(12)
print(id(x))
x[:] = x + 1
print(id(x))
2296319225264
2296319225264

观察发现,运算前后占用的内存地址空间相同。


张量转换为其他对象

Torch 张量与 Numpy 数组共享底层内存,可以就地操作转换;

张量转换为数组:
a.item(), float(a), int(a)

import torcha = torch.arange(12)
b = a.numpy()
print(type(a), type(int(a[1])), type(b))
<class 'torch.Tensor'> <class 'int'> <class 'numpy.ndarray'>

数组转换为张量:

import numpy as np
import torchx = np.arange(12)
y = torch.tensor(x)
print(type(x), type(y))
<class 'numpy.ndarray'> <class 'torch.Tensor'>

以上内存便是预备知识的第一部分张量的相关介绍;
如有任何问题,请联系或者留言;

2024.2.12

这篇关于【深度学习】S1 预备知识 P1 张量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/704945

相关文章

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

最新Spring Security实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)

《最新SpringSecurity实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)》本章节介绍了如何通过SpringSecurity实现从配置自定义登录页面、表单登录处理逻辑的配置,并简单模拟... 目录前言改造准备开始登录页改造自定义用户名密码登陆成功失败跳转问题自定义登出前后端分离适配方案结语前言

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

国内环境搭建私有知识问答库踩坑记录(ollama+deepseek+ragflow)

《国内环境搭建私有知识问答库踩坑记录(ollama+deepseek+ragflow)》本文给大家利用deepseek模型搭建私有知识问答库的详细步骤和遇到的问题及解决办法,感兴趣的朋友一起看看吧... 目录1. 第1步大家在安装完ollama后,需要到系统环境变量中添加两个变量2. 第3步 “在cmd中

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

Python与DeepSeek的深度融合实战

《Python与DeepSeek的深度融合实战》Python作为最受欢迎的编程语言之一,以其简洁易读的语法、丰富的库和广泛的应用场景,成为了无数开发者的首选,而DeepSeek,作为人工智能领域的新星... 目录一、python与DeepSeek的结合优势二、模型训练1. 数据准备2. 模型架构与参数设置3

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动