在深度学习领域,张量是一种非常核心的数据结构,它是标量、向量和矩阵等数学概念的高维扩展。PyTorch作为一款流行的深度学习框架,提供了丰富的张量操作API,帮助研究人员和开发者有效地实现复杂的数学运算和神经网络模型。在本文中,我们将探索PyTorch中的张量运算,包括基础的加减乘除,以及更高级的点乘和叉乘等操作。
在PyTorch中,张量(Tensor)是一个多维数组,用于存储数值型数据。通过张量,我们可以表示标量(0维张量)、向量(1维张量)、矩阵(2维张量)等各种形式的数据。
文章目录
- [1. 创建张量](#1. 创建张量)
- [2. 张量的加减乘除](#2. 张量的加减乘除)
- [3. 向量点积](#3. 向量点积)
- [4. 实践应用示例](#4. 实践应用示例)
- 结语
1. 创建张量
更复杂的张量创建方案以后再写,这里仅分享简单的通过torch.tensor()
函数直接创建张量::
python
import torch
# 创建一个标量(0维张量)
scalar = torch.tensor(5)
# 创建一个向量(1维张量)
vector = torch.tensor([1, 2, 3])
# 创建一个矩阵(2维张量)
matrix = torch.tensor([[1, 2], [3, 4]])
# 创建一个3维张量
tensor3d = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
2. 张量的加减乘除
张量之间的基本运算包括加法、减法、乘法和除法。这些运算可以应用于标量、向量、矩阵以及更高维度的张量。
一般来说对于mini-batch场景都可以直接不考虑批次影响直接运算。对于矩阵乘法这还包括torch.bmm()
场景(NLP中输入往往是[batch_size, word_num, embedding_size]
就符合这个场景)。
这里只介绍了比较简单的场景,还没有介绍广播机制。
加法
- 尺寸相同的张量相加,就是逐元素相加:
python
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]])
print(tensor1 + tensor2)
输出:
tensor([[ 8, 10, 12],
[14, 16, 18]])
- 张量加数字就是每个元素上加这个数字:
python
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(tensor1 + 1)
输出:
tensor([[2, 3, 4],
[5, 6, 7]])
减法
- 尺寸相同的张量相减,就是逐元素相加:
python
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]])
print(tensor1 - tensor2)
输出:
tensor([[-6, -6, -6],
[-6, -6, -6]])
- 张量加数字就是每个元素上加这个数字:
python
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(tensor1 - 1)
输出:
tensor([[0, 1, 2],
[3, 4, 5]])
乘法
-
元素乘法(Hadamard乘法/哈达玛积) :尺寸相同的张量相乘,逐元素相乘
pythontensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]]) tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]]) print(tensor1 * tensor2)
或者:
pythontensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]]) tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]]) print(torch.mul(tensor1, tensor2))
输出:
tensor([[ 7, 16, 27], [40, 55, 72]])
-
张量乘数字:逐元素相乘
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]]) print(tensor1 * 2)
-
矩阵乘法 :二元张量
pythontensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]]) tensor2 = torch.tensor([[7, 8, 9, 10], [11, 12, 13, 14], [15, 16, 17, 18]]) print(tensor1 @ tensor2)
或者:
pythontensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]]) tensor2 = torch.tensor([[7, 8, 9, 10], [11, 12, 13, 14], [15, 16, 17, 18]]) print(torch.mm(tensor1, tensor2))
或者:
pythontensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]]) tensor2 = torch.tensor([[7, 8, 9, 10], [11, 12, 13, 14], [15, 16, 17, 18]]) print(torch.matmul(tensor1, tensor2))
输出:
tensor([[ 74, 80, 86, 92], [173, 188, 203, 218]])
mini-batch矩阵乘法
torch.matmul()
和torch.bmm()
在mini-batch矩阵乘法时的效果相同:
python
tensor1 = torch.randn((8, 2, 3))
tensor1[0, :, :] = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor2 = torch.randn((8, 3, 4))
tensor2[0, :, :] = torch.tensor(
[[7, 8, 9, 10], [11, 12, 13, 14], [15, 16, 17, 18]]
)
tensor3 = torch.bmm(tensor1, tensor2)
print(tensor3.size())
print(tensor3)
tensor4 = torch.matmul(tensor1, tensor2)
print(tensor4.size())
print(tensor4)
输出:
torch.Size([8, 2, 4])
tensor([[[ 7.4000e+01, 8.0000e+01, 8.6000e+01, 9.2000e+01],
[ 1.7300e+02, 1.8800e+02, 2.0300e+02, 2.1800e+02]],
[[-7.4121e-01, 4.5700e-01, 4.8753e-01, -1.5857e+00],
[-1.3277e+00, -3.1067e-01, 6.9044e-02, -1.5349e+00]],
[[-7.9833e-01, 6.2960e-02, 9.2492e-01, -1.0725e+00],
[-2.3740e+00, 1.4807e+00, -3.7188e-01, -6.8096e-01]],
[[-1.3164e+00, 1.8683e-01, -2.4655e+00, 2.8674e+00],
[ 1.1632e+00, -1.1536e+00, 7.8646e-01, 2.8742e-01]],
[[ 2.9451e-01, 2.8613e+00, 1.0916e-01, 3.3683e+00],
[-5.0816e+00, -4.6865e+00, -2.4027e+00, -5.5370e+00]],
[[ 7.5808e-01, -1.0055e-01, 1.6402e-01, -1.6499e-01],
[ 3.0521e-01, 2.2200e-01, 8.0074e-01, 9.8477e-01]],
[[-5.3240e-01, -1.5062e+00, 4.1627e-02, -7.6117e-01],
[-9.1952e-01, 7.5713e-01, -1.8531e+00, 1.9099e+00]],
[[ 3.5094e+00, 2.4735e+00, 1.9523e+00, 2.4074e+00],
[ 2.4156e-01, 5.4852e+00, 3.9815e+00, -1.8851e+00]]])
torch.Size([8, 2, 4])
tensor([[[ 7.4000e+01, 8.0000e+01, 8.6000e+01, 9.2000e+01],
[ 1.7300e+02, 1.8800e+02, 2.0300e+02, 2.1800e+02]],
[[-7.4121e-01, 4.5700e-01, 4.8753e-01, -1.5857e+00],
[-1.3277e+00, -3.1067e-01, 6.9044e-02, -1.5349e+00]],
[[-7.9833e-01, 6.2960e-02, 9.2492e-01, -1.0725e+00],
[-2.3740e+00, 1.4807e+00, -3.7188e-01, -6.8096e-01]],
[[-1.3164e+00, 1.8683e-01, -2.4655e+00, 2.8674e+00],
[ 1.1632e+00, -1.1536e+00, 7.8646e-01, 2.8742e-01]],
[[ 2.9451e-01, 2.8613e+00, 1.0916e-01, 3.3683e+00],
[-5.0816e+00, -4.6865e+00, -2.4027e+00, -5.5370e+00]],
[[ 7.5808e-01, -1.0055e-01, 1.6402e-01, -1.6499e-01],
[ 3.0521e-01, 2.2200e-01, 8.0074e-01, 9.8477e-01]],
[[-5.3240e-01, -1.5062e+00, 4.1627e-02, -7.6117e-01],
[-9.1952e-01, 7.5713e-01, -1.8531e+00, 1.9099e+00]],
[[ 3.5094e+00, 2.4735e+00, 1.9523e+00, 2.4074e+00],
[ 2.4156e-01, 5.4852e+00, 3.9815e+00, -1.8851e+00]]])
除法
- 逐元素相除
python
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]])
print(tensor1 / tensor2)
输出:
tensor([[0.1429, 0.2500, 0.3333],
[0.4000, 0.4545, 0.5000]])
- 张量除以数字:逐元素相除
python
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(tensor1 / 2)
输出:
tensor([[0.5000, 1.0000, 1.5000],
[2.0000, 2.5000, 3.0000]])
3. 向量点积
torch.dot()
只支持一维向量点积^1^
python
vector1 = torch.tensor([1, 2, 3])
vector2 = torch.tensor([4, 5, 6])
print(torch.dot(vector1, vector2))
4. 实践应用示例
假设我们有一批文本数据编码后的向量,我们想要计算这些向量之间的相似度。一种方法是使用向量的点乘来计算:
python
text_vector1 = torch.tensor([0.1, 0.2, 0.3])
text_vector2 = torch.tensor([0.4, 0.5, 0.6])
similarity = torch.dot(text_vector1, text_vector2)
此外,如果我们处理的是图片数据,我们可能需要对图片的像素值进行标准化处理,这就需要用到张量的乘法和除法运算:
python
image_tensor = torch.tensor([[[0.1, 0.2], [0.3, 0.4]], [[0.5, 0.6], [0.7, 0.8]]])
norm_factor = torch.tensor(255.0)
normalized_image = image_tensor / norm_factor
通过这些示例,我们可以看到张量运算在处理各种类型的数据时的强大能力和灵活性。
结语
PyTorch张量运算是深度学习编程中的基石,掌握这些基础和高级运算对于高效实现和优化神经网络模型至关重要。希望本文能帮助你更好地理解和使用PyTorch进行张量运算,从而在你的研究和项目中取得更好的成果。