1、什么是张量
张量是一个多维的数据容器,可以包含标量、向量、矩阵以及更高维度的数据。在数学上,张量可以被视为一个有序的数组,每个元素都可以通过索引来访问。张量的维度(也称为阶或秩)定义了其形状,即每个维度的大小。
- 0维张量:也称为标量(Scalar),是最基本的数据单元,没有维度,只有一个数值。
- 1维张量:通常称为向量(Vector),可以看作是标量的有序列表,常用于表示数据点或特征。
- 2维张量:称为矩阵(Matrix),在数学和物理学中广泛使用,用于表示线性变换、统计数据等。
- 多维张量:当数据的维度超过两个时,我们称之为多维张量。它们可以表示复杂的数据结构,如图像、视频帧或高维数据集。
-
import torch # 0维张量:标量 scalar = torch.tensor(7) print(scalar.ndim) # 输出0 # 1维张量:向量 vector = torch.tensor([7, 7]) print(vector.ndim) # 输出1 # 2维张量:矩阵 matrix = torch.tensor([[7, 8], [9, 10]]) print(matrix.ndim) # 输出2 # 多维张量 tensor = torch.tensor([[[1, 2, 3], [3, 6, 9], [2, 4, 5]]]) print(tensor.ndim) # 输出3
2、张量的创建
2.1 基本创建方式
(1). 根据已有数据创建张量
(2). 根据形状创建张量
import torch
# 从Python列表创建张量
tensor_from_list = torch.tensor([1, 2, 3, 4, 5])
import numpy as np
# 从NumPy数组创建张量
np_array = np.array([1, 2, 3, 4, 5])
tensor_from_numpy = torch.from_numpy(np_array)
# 创建一个形状为(3, 4)的未初始化张量
tensor_empty = torch.empty(3, 4)
# 创建一个形状为(3, 4)的全0张量
tensor_zeros = torch.zeros(3, 4)
# 创建一个形状为(3, 4)的全1张量
tensor_ones = torch.ones(3, 4)
# 创建一个形状为(3, 4)的全指定值张量,这里指定值为7
tensor_full = torch.full((3, 4), 7)
# 创建一个形状为(3, 4)的随机张量
tensor_rand = torch.rand(3, 4)
# 或者,创建一个与已有张量形状相同,元素值随机的张量
tensor_rand_like = torch.rand_like(tensor_zeros)
# 创建一个形状为(3, 4)的标准正态分布随机张量
tensor_randn = torch.randn(3, 4)
# 或者,创建一个与已有张量形状相同,元素值从标准正态分布随机的张量
tensor_randn_like = torch.randn_like(tensor_zeros)
2.2 创建线性和随机张量
(1) 线性张量
创建线性张量: 线性张量通常指的是张量中的元素是按照某种线性规律排列的。在PyTorch中,可以使用torch.arange
或torch.linspace
来创建这样的张量。
使用torch.arange
创建从起始值到结束值的线性序列张量:
import torch
# 假设我们想要从0开始到9结束,步长为1的线性张量
linear_tensor = torch.arange(10) # 等同于 torch.arange(start=0, end=10, step=1)
使用torch.linspace
创建在指定范围内均匀分布的线性张量:
# 从0到1创建10个均匀分布的线性张量
linear_tensor_even = torch.linspace(start=0, end=1, steps=10)
(2) 随机张量
随机张量是指张量中的元素是随机生成的。PyTorch提供了多种方法来创建随机张量。
使用torch.rand
创建在[0, 1)区间内均匀分布的随机张量:
# 创建一个形状为(3, 4)的随机张量
random_tensor_uniform = torch.rand(3, 4)
使用torch.randn
创建标准正态分布(均值为0,标准差为1)的随机张量:
# 创建一个形状为(3, 4)的标准正态分布随机张量
random_tensor_normal = torch.randn(3, 4)
使用torch.randint
创建指定范围内的随机整数张量:
# 创建一个形状为(3, 4)的随机整数张量,整数范围从0到9
random_tensor_int = torch.randint(0, 10, (3, 4))
2.3 创建01张量
(1) 全0张量
(2) 全1张量
(3) 全指定值张量
import torch
# 指定张量的形状,例如创建一个形状为(3, 4)的全0张量
shape = (3, 4)
tensor_zeros = torch.zeros(shape)
# 同样指定形状,创建一个形状为(3, 4)的全1张量
tensor_ones = torch.ones(shape)
# 假设我们想要创建一个全值为5的形状为(3, 4)的张量
value = 5
tensor_full = torch.full(shape, value)
torch.zeros函数创建一个元素全为0的张量,torch.ones函数创建一个元素全为1的张量,而torch.full函数创建一个元素全为指定值的张量。所有这些函数都需要指定张量的形状。
3、张量与Numpy之间的转换
张量和NumPy数组是深度学习与科学计算中常用的两种数据结构。它们在某些方面相似,但也有一些关键的区别。以下是张量与NumPy数组之间的转换方法和它们之间的一些联系:
张量与NumPy数组的相似之处
多维数组:张量和NumPy数组都是多维数组,可以存储和操作多维数据。
数据类型:它们都支持多种数据类型,如整数、浮点数等。
内存布局:张量和NumPy数组在内存中都是连续存储的,这使得它们可以高效地进行数学运算。
张量与NumPy数组的区别
库支持:NumPy是一个独立的科学计算库,而张量是深度学习框架(如PyTorch和TensorFlow)的一部分。
自动微分:深度学习框架中的张量支持自动微分,这对于训练神经网络至关重要。NumPy数组不支持自动微分。
GPU加速:深度学习框架的张量可以在GPU上运行,提供并行计算能力。NumPy数组默认在CPU上运行,但可以通过其他库(如CuPy)实现GPU加速。
张量与NumPy数组的转换
在PyTorch中,张量和NumPy数组之间的转换非常直接:
import numpy as np
import torch
# 创建一个NumPy数组
np_array = np.array([1, 2, 3, 4, 5])
# 将NumPy数组转换为PyTorch张量
tensor = torch.from_numpy(np_array)
注意:这种转换方式会创建一个与原始NumPy数组共享内存的张量。对张量或数组的修改会反映在另一个上。
从PyTorch张量到NumPy数组:
# 假设tensor是一个PyTorch张量
# 将PyTorch张量转换为NumPy数组
np_array = tensor.numpy()
注意:如果张量是在GPU上创建的,使用.numpy()
方法之前需要确保将其转移到CPU上,例如使用tensor.cpu()
。
使用场景
- 科学计算:当需要进行复杂的数学运算和数据分析时,NumPy是一个更好的选择。
- 深度学习:在构建和训练神经网络时,使用深度学习框架的张量更为合适,因为它们提供了自动微分和其他深度学习特有的功能。
4、张量的数值计算
张量的数值计算是深度学习框架中的核心功能之一。在PyTorch中,你可以对张量执行各种基本的数学运算,包括但不限于:
-
基本算术运算:
- 加法:
torch.add(x, y)
- 减法:
x - y
或torch.sub(x, y)
- 乘法:
x * y
或torch.mul(x, y)
- 除法:
x / y
或torch.div(x, y)
- 指数:
torch.exp(x)
- 对数:
torch.log(x)
- 幂运算:
torch.pow(x, n)
或x ** n
- 加法:
-
元素级运算:
- 元素相加:
x.add(y)
或torch.add(x, y, out=z)
- 元素相乘:
x.mul(y)
- 元素相加:
-
矩阵运算:
- 矩阵乘法:
torch.mm(a, b)
或a @ b
- 矩阵乘法(支持广播):
torch.matmul(a, b)
- 点乘:
torch.dot(a, b)
- 矩阵乘法:
-
比较操作:
- 等于:
x == y
- 不等于:
x != y
- 大于:
x > y
- 小于:
x < y
- 等于或大于:
x >= y
- 等于或小于:
x <= y
- 等于:
-
逻辑运算:
- 逻辑与:
x & y
- 逻辑或:
x | y
- 逻辑非:
~x
- 逻辑与:
-
最大/最小值操作:
- 最大值:
torch.max(x, y)
或x.max()
- 最小值:
torch.min(x, y)
或x.min()
- 逐元素最大值:
torch.max(x, other)
- 逐元素最小值:
torch.min(x, other)
- 最大值:
-
累积和/累积积运算:
- 累积和:
torch.cumsum(x, dim)
- 累积积:
torch.cumprod(x, dim)
- 累积和:
-
求和、平均、标准差和方差:
- 求和:
torch.sum(x, dim)
- 平均值:
torch.mean(x, dim)
- 标准差:
torch.std(x, dim)
- 方差:
torch.var(x, dim)
- 求和:
-
索引和切片:
- 索引:
x[index]
- 切片:
x[start:stop:step]
- 索引:
-
转置和置换:
- 转置:
x.t()
或x.transpose(0, 1)
- 置换:
x.permute(dims)
- 转置:
-
广播:
- PyTorch支持广播机制,允许不同形状的张量进行数学运算。
这些操作可以组合使用,以实现复杂的数学计算。下面是一个简单的示例,演示了如何使用PyTorch进行一些基本的数值计算:
import torch
# 创建两个张量
x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor([4.0, 5.0, 6.0])
# 元素级加法
z_add = torch.add(x, y)
# 矩阵乘法
a = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
b = torch.tensor([[2.0, 0.0], [1.0, 2.0]])
z_matmul = torch.mm(a, b)
# 求和
z_sum = torch.sum(x)
# 求平均值
z_mean = torch.mean(x)
# 标准差
z_std = torch.std(x)
print(z_add)
print(z_matmul)
print(z_sum)
print(z_mean)
print(z_std)
5.2 自动求导
-
创建需要求导的张量:
- 确保张量是浮点类型,并且需要有
grad_fn
属性,这意味着它可以进行梯度计算。
- 确保张量是浮点类型,并且需要有
-
执行计算:
- 对张量进行操作,创建一个计算图。
-
调用
.backward()
:- 在需要计算梯度的张量上调用
.backward()
方法,这将计算梯度并存储在.grad
属性中。
- 在需要计算梯度的张量上调用
-
获取梯度:
- 使用
.grad
属性来访问梯度。
- 使用
下面是一个简单的示例,演示了如何使用PyTorch进行自动求导:
import torch
# 创建一个需要求导的张量,要求是浮点类型
x = torch.tensor([3.0], requires_grad=True)
# 执行一些操作,例如y = 2 * x ** 2
y = 2 * x ** 2
# 计算y关于x的导数,调用backward()方法
y.backward()
# 访问x的梯度
print(x.grad) # 输出: tensor([12.])
5.3 张量的操作函数
PyTorch提供了大量的张量操作函数,可以用于各种数据处理和模型训练任务。
-
基本数学运算:
torch.add(x, y)
: 元素级加法。torch.sub(x, y)
: 元素级减法。torch.mul(x, y)
: 元素级乘法。torch.div(x, y)
: 元素级除法。
-
指数和对数函数:
torch.exp(x)
: 对每个元素计算自然指数。torch.log(x)
: 对每个元素计算自然对数。
-
三角函数:
torch.sin(x)
: 正弦函数。torch.cos(x)
: 余弦函数。torch.tan(x)
: 正切函数。
-
取模和绝对值:
torch.fmod(x, y)
: 元素级取模。torch.abs(x)
: 绝对值。
-
最大/最小值操作:
torch.max(x, y)
: 元素级最大值。torch.min(x, y)
: 元素级最小值。torch.amax(x, dim)
: 沿着指定维度的最大值。torch.amin(x, dim)
: 沿着指定维度的最小值。
-
求和、平均、标准差和方差:
torch.sum(x, dim)
: 沿着指定维度求和。torch.mean(x, dim)
: 沿着指定维度求平均。torch.std(x, dim)
: 沿着指定维度的标准差。torch.var(x, dim)
: 沿着指定维度的方差。
-
累积和/累积积:
torch.cumsum(x, dim)
: 累积和。torch.cumprod(x, dim)
: 累积积。
-
矩阵乘法:
torch.mm(a, b)
: 矩阵乘法。torch.matmul(a, b)
: 矩阵乘法,支持广播。
-
点乘和向量乘法:
torch.dot(a, b)
: 点乘。torch.cross(a, b, dim)
: 向量叉乘。
-
转置和置换:
x.t()
或torch.transpose(x, dim0, dim1)
: 转置。x.permute(dims)
: 置换维度。
-
索引和切片:
x[index]
: 索引。x[start:stop:step]
: 切片。
-
条件操作:
torch.where(condition, x, y)
: 条件索引。
-
逻辑运算:
torch.eq(x, y)
: 元素级等于。torch.ne(x, y)
: 元素级不等于。torch.lt(x, y)
: 元素级小于。torch.gt(x, y)
: 元素级大于。
-
广播:
- PyTorch自动处理广播,允许不同形状的张量进行运算。
-
扩展张量:
x.unsqueeze(dim)
: 在指定维度增加一个维度。x.squeeze(dim)
: 在指定维度移除一个维度。
-
填充张量:
torch.full_like(x, fill_value)
: 创建一个与x形状相同,填充特定值的张量。
-
随机采样:
torch.randn_like(x)
: 创建一个形状与x相同,元素值从标准正态分布中随机采样的张量。
import torch
# 创建一个张量
x = torch.tensor([[1.0, 2.0], [3.0, 4.0]], requires_grad=True)
# 基本数学运算
y = torch.tensor([[5.0, 6.0], [7.0, 8.0]])
z_add = torch.add(x, y) # 加法
z_sub = torch.sub(x, y) # 减法
z_mul = torch.mul(x, y) # 乘法
z_div = torch.div(x, y) # 除法
# 指数和对数函数
z_exp = torch.exp(x) # 指数
z_log = torch.log(x) # 对数
# 三角函数
z_sin = torch.sin(x) # 正弦
z_cos = torch.cos(x) # 余弦
# 取模和绝对值
z_mod = torch.fmod(x, torch.tensor(2.0)) # 取模
z_abs = torch.abs(x - y) # 绝对值
# 最大/最小值操作
z_max = torch.max(x, y) # 元素级最大值
amax_result = x.max(dim=0) # 沿着指定维度的最大值
# 求和、平均、标准差和方差
sum_result = torch.sum(x, dim=0) # 沿着指定维度求和
mean_result = torch.mean(x, dim=0) # 沿着指定维度求平均
# 矩阵乘法
a = torch.randn(2, 3)
b = torch.randn(3, 2)
z_matmul = torch.mm(a, b) # 矩阵乘法
# 转置和置换
z_transpose = x.t() # 转置
z_permute = x.permute(1, 0) # 置换维度
# 索引和切片
index_result = x[0, 1] # 索引
slice_result = x[0:2, 0:2] # 切片
# 条件操作
condition = x > 2
select_result = torch.where(condition, x, y) # 条件索引
# 逻辑运算
eq_result = torch.eq(x, y)
ne_result = torch.ne(x, y)
lt_result = torch.lt(x, y)
gt_result = torch.gt(x, y)
# 广播
x_unsqueezed = x.unsqueeze(0) # 增加维度以匹配广播
z_broadcast = x_unsqueezed + y # 广播后的加法
# 扩展张量
z_unsqueeze = x.unsqueeze(0) # 在第0维增加一个维度
z_squeeze = x_unsqueeze.squeeze(0) # 移除第0维
# 填充张量
z_full = torch.full_like(x, 10) # 创建一个与x形状相同,填充值为10的张量
# 随机采样
z_randn = torch.randn_like(x) # 创建一个与x形状相同,元素值从标准正态分布中随机采样的张量
# 打印结果
print("Addition:", z_add)
print("Exponential:", z_exp)
print("Sum:", sum_result)
print("Transpose:", z_transpose)
print("Broadcast:", z_broadcast)
结语
在本文中,我们探讨了张量作为机器学习中的核心数据结构的重要性和基本使用方法。从0维的标量到多维的张量,我们了解了如何在PyTorch框架中创建和操作这些数据结构。张量不仅仅是数据的容器,它们是实现深度学习算法的基石。
通过本文的学习,读者应该能够理解张量的不同维度和它们在实际应用中的意义。我们也看到了如何通过简单的代码示例来创建和打印张量的维度信息。这些基础操作是进一步学习更高级的张量操作和深度学习模型构建的前提。
随着对张量操作的深入理解,你将能够更有效地利用它们进行复杂的数学运算和算法实现。在未来的文章中,我们将继续深入探讨张量的各种高级特性和应用,包括但不限于张量的广播、索引、切片以及与深度学习模型的集成。
希望本文能够帮助你建立对张量基本使用的认识,并激发你进一步探索机器学习和深度学习的兴趣。记住,实践是学习的关键,所以不要犹豫,开始编写你自己的代码,体验张量的强大功能吧!