pytorch----矩阵乘法

理论:

向量:

一行乘以一列: 内积: 结果一个数

一列乘以一行: 外积: 结果一个矩阵

 

 

矩阵:

点乘: *, mul: 对应元素相乘

叉乘: dot, matmul: 矩阵乘法  (而矩阵乘法又可以理解为向量内积, 外积的结合体)

  • 传统的矩阵乘法可以看成: 行向量组成一列, 列向量组成一行

 

 

 

关于广播机制的补充说明:

  • 广播机制是用在对应元素的:  加, 减, 乘, 除 

  • 能够进行广播机制的条件:  

    • 有一维为1
    • 少了一个维度
  • 广播机制的法则:

 

高维矩阵乘法:

  • 保证前n-2个维度是相等的

  • 最后两个维度用来做, 普通二维矩阵乘法

 

 

爱因斯坦求和约定:

tf说明了爱因斯坦求和约定的各种操作:  https://blog.csdn.net/bqw18744018044/article/details/103648093

1.矩阵转置

A = tf.random.uniform((3,4))
B = tf.einsum("ij->ji",A)
print(A.shape)
print(B.shape)
(3, 4)
(4, 3)

2.求和

A = tf.random.uniform((3,4))
print(tf.einsum("ij->",A)) # 所有元素求和
print(tf.einsum("ij->j",A).shape) # 列求和
print(tf.einsum("ij->i",A).shape) # 行求和
tf.Tensor(6.1462874, shape=(), dtype=float32)
(4,)
(3,)

3.乘积

A = tf.random.uniform((2,3))
B = tf.random.uniform((3,4))
print(tf.einsum("ik,kj->ij",A,B).shape) # 矩阵乘法
a = tf.random.uniform((3,))
b = tf.random.uniform((3,))
print(tf.einsum("i,i->",a,b).shape) # 内积
print(tf.einsum("i,j->ij",a,b).shape) # 外积
(2, 4)
()
(3, 3)

4.batch乘法

在深度学习中样本通常是成批次的送到模型中,因此往往需要对每个样本对应的矩阵进行乘法,而由于整个tensor的第1个维度为batch size,因此要实现batch乘法会比较复杂,而使用einsum就非常的简洁。

A = tf.random.uniform((32,128,100))
B = tf.random.uniform((32,100,50))
print(tf.einsum("bsd,bdi->bsi",A,B).shape)
(32, 128, 50)

5.张量缩约

将两个高维张量在某些维度相乘,并在这些维度上求和

A = tf.random.uniform((3,5,7,2,8))
B = tf.random.uniform((4,7,2,3,5))
print(tf.einsum("pqrst,urspq->pqrstu",A,B).shape)
(3, 5, 7, 2, 8, 4)

 

 

 







代码:

 

torch中的乘法:

一.矩阵乘

  • torch.matmul

  • 有各个维度的操作, 看官方文档就可以解决:
    • 向量的乘法:
    • 矩阵的乘法:
      • 如果维度对应(batch矩阵乘法):  n-2维不管(因为一样), 最后两维矩阵乘法
      • 如果维度不对应(广播矩阵乘法): n-2维需要满足广播机制, 最后两维矩阵乘法

二.对应元素相乘

  • torch.mul

  • 和普通标量也是对应元素相乘:

#输入张量和标量相乘
torch.mul(input, value, out=None)  

例:
>>> a = torch.randn(3)
>>> a

-0.9374
-0.5254
-0.6069
[torch.FloatTensor of size 3]

>>> torch.mul(a, 100)

-93.7411
-52.5374
-60.6908
[torch.FloatTensor of size 3]
  • 即便, 张量的形状不一样, 只要对应元素个数相同也是一样:

#两个张量相乘
torch.mul(input, other, out=None)




>>> a = torch.randn(4,4)
>>> a

-0.7280  0.0598 -1.4327 -0.5825
-0.1427 -0.0690  0.0821 -0.3270
-0.9241  0.5110  0.4070 -1.1188
-0.8308  0.7426 -0.6240 -1.1582
[torch.FloatTensor of size 4x4]

>>> b = torch.randn(2, 8)
>>> b

 0.0430 -1.0775  0.6015  1.1647 -0.6549  0.0308 -0.1670  1.0742
-1.2593  0.0292 -0.0849  0.4530  1.2404 -0.4659 -0.1840  0.5974
[torch.FloatTensor of size 2x8]

>>> torch.mul(a, b)

-0.0313 -0.0645 -0.8618 -0.6784
 0.0934 -0.0021 -0.0137 -0.3513
 1.1638  0.0149 -0.0346 -0.5068
-1.0304 -0.3460  0.1148 -0.6919
[torch.FloatTensor of size 4x4]

 

 

numpy中的矩阵乘法:

 

  • np.dot()和torch.matmul()----矩阵乘法, 对应元素相乘相加:

  • (reduce_sum其实和这里也有一定关系)
a=[[1,1,1],
  [2,2,2]]
at=torch.tensor(a)



c=[[3,3],
   [3,3],
   [3,3]]
ct=torch.tensor(c)



y1=np.dot(a,c)
y2=torch.matmul(at,ct)

  • 数组类型或者list类型:内积
In [2]:a = np.array([1,1,1])
In [3]:b = np.array([2,2,2])

In [4]:np.dot(a,b)
Out[4]: 6
  • 矩阵:矢量积,叉乘
  • 列表和矩阵不一样, 大小不合适会报错:
In [5]:c = np.array([[3,3,3],[4,4,4]])
In [6]:d = np.array([[5],[5],[5]])
In [7]:np.dot(c,d)
Out[7]: 
array([[45],
       [60]])
In [11]:g = np.mat([1,1,1])
In [12]:h = np.mat([2,2,2])
In [13]:np.dot(g,h)
Out[13]:报错

 

  • multiply和*----对应元素相乘(哈达码积):

In [2]:a = np.array([1,1,1])
In [3]:b = np.array([2,2,2])
In [14]:np.multiply(a,b)
Out[14]:array([2, 2, 2])
In [3]:b = np.array([2,2,2])
In [5]:c = np.array([[3,3,3],[4,4,4]])

In [15]:np.multiply(b,c)
Out[15]:
array([[6, 6, 6],
       [8, 8, 8]])

 

  • multiply():

  • 作用在任何类型(数组类型,矩阵类型,list类型),都为数量积|点积(即,矩阵对应元素相乘)
In [2]:a = np.array([1,1,1])
In [3]:b = np.array([2,2,2])
In [14]:np.multiply(a,b)
Out[14]:array([2, 2, 2])
In [3]:b = np.array([2,2,2])
In [5]:c = np.array([[3,3,3],[4,4,4]])

In [15]:np.multiply(b,c)
Out[15]:
array([[6, 6, 6],
       [8, 8, 8]])

 

  •  
  • *

  • 作用在数组类型时为点乘

  

In [2]:a = np.array([1,1,1])
In [3]:b = np.array([2,2,2])
In [16]:a*b
Out[16]:array([2, 2, 2])
  •  
  • 不能作用在list类型(会报错)

  

In [17]:[1,1,1]*[2,2,2]
Out[17]:报错

 

  • 点乘元素不对应(会报错)
In [5]:c = np.array([[3,3,3],[4,4,4]])
In [6]:d = np.array([[5],[5],[5]])

In [17]:c*d
Out[17]:报错
  •  
  • 作用在矩阵类型时为叉乘
  • In [8]:e = np.mat([[3,3,3],[4,4,4]])
    In [9]:f = np.mat([[5],[5],[5]])
    
    In [7]:e*f
    Out[7]: 
    matrix([[45],
           [60]])

 

 

乘法的交换率: 元素乘积 和 矩阵乘法 不能交换先后顺序:

  • ans1:  norm(e*e)w
  • ans2: (norm e)*e w
  • 结论:  先算元素乘积,后算矩阵乘法    和     先算矩阵乘法,后算元素乘积的结果   截然不同 
import numpy as np

normalization=np.array([[3,3,3],[3,3,3],[3,3,3]])
embedding=np.array([[0,0],[1,1],[2,2]])
w=np.array([[2,2],[2,2]])

e_e=np.multiply(embedding, embedding)
print("\n e_e:\n", ans1)
norm_e_e1=np.dot(normalization, e_e)
print("\n norm_e_e1:\n", ans1)
ans1=np.dot(norm_e_e0, w)
print("\n ans1:\n", ans1)

print("\n")

norm_e=np.dot(normalization,embedding)
print("\n norm_e:\n", ans1)
norm_e_e2=np.multiply(norm_e, embedding)
print("\n norm_e_e2:\n", ans1)
ans2=np.dot(norm_e_e, w)
print("\n ans2:\n", ans2)

 

 

 

おすすめ

転載: blog.csdn.net/weiwei935707936/article/details/110871209