机器学习 - Python - numpy.einsum()

本文介绍了numpy库中的np.einsum函数,它用于执行各种复杂的张量运算,包括对角线元素提取、矩阵转置、向量内积、矩阵向量乘法、张量收缩等,并通过实例展示了其在处理多维数组时的灵活性和效率。
摘要由CSDN通过智能技术生成

机器学习记录

np.einsum()是numpy中的一个万能函数,可以进行广泛的张量积运算。它通过一系列缩写表示法,计算多维数组之间的相乘积。

import numpy as np
a = np.arange(25).reshape(5,5)
b = np.arange(5)
c = np.arange(6).reshape(2,3)
a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])
b
array([0, 1, 2, 3, 4])
c
array([[0, 1, 2],
       [3, 4, 5]])
# 对角线之和
np.einsum('ii', a)
60
# 对角线之和
np.trace(a)
60
# 对角线之和
np.einsum(a, [0, 0])
60
# 对角线向量
np.einsum('ii->i', a)
array([ 0,  6, 12, 18, 24])
# 对角线向量
np.diag(a)
array([ 0,  6, 12, 18, 24])
# 对角线上元素 组成的向量
np.einsum(a, [0, 0], [0])
array([ 0,  6, 12, 18, 24])
# Sum over an axis (requires explicit form):
# 对一个轴求和(需要明确的形式):
# 每行元素和 组成的向量
np.einsum('ij->i', a)
array([ 10,  35,  60,  85, 110])
np.einsum(a, [0,1], [0])
array([ 10,  35,  60,  85, 110])
np.sum(a, axis=1)
array([ 10,  35,  60,  85, 110])
np.einsum('...j->...', a)
array([ 10,  35,  60,  85, 110])
np.einsum(a, [Ellipsis,1], [Ellipsis])
array([ 10,  35,  60,  85, 110])
# 每列元素和 组成的向量
np.einsum('ij->j', a)
array([50, 55, 60, 65, 70])
np.einsum(a, [1,0], [0])
array([50, 55, 60, 65, 70])
np.sum(a, axis=0)
array([50, 55, 60, 65, 70])
# Compute a matrix transpose, or reorder any number of axes:
# 矩阵转置
np.einsum('ji', c)
array([[0, 3],
       [1, 4],
       [2, 5]])
np.einsum('ij->ji', c)
array([[0, 3],
       [1, 4],
       [2, 5]])
np.einsum(c, [1,0])
array([[0, 3],
       [1, 4],
       [2, 5]])
np.transpose(c)
array([[0, 3],
       [1, 4],
       [2, 5]])
# Vector inner products:
# 向量内积:
# 1. 向量, 2. 元素自己相乘和求和
np.einsum('i,i', b, b)
30
np.einsum(b, [0], b, [0])
30
np.inner(b,b)
30
# Matrix vector multiplication:
# 矩阵向量乘法:
np.einsum('ij,j', a, b)
array([ 30,  80, 130, 180, 230])
np.einsum(a, [0,1], b, [1])
array([ 30,  80, 130, 180, 230])
np.dot(a, b)
array([ 30,  80, 130, 180, 230])
np.einsum('...j,j', a, b)
array([ 30,  80, 130, 180, 230])
# Broadcasting and scalar multiplication:
# 矩阵乘以系数
np.einsum('..., ...', 3, a)
array([[ 0,  3,  6,  9, 12],
       [15, 18, 21, 24, 27],
       [30, 33, 36, 39, 42],
       [45, 48, 51, 54, 57],
       [60, 63, 66, 69, 72]])
np.einsum(',ij', 3, c)
array([[ 0,  3,  6],
       [ 9, 12, 15]])
np.einsum(3, [Ellipsis], c, [Ellipsis])
array([[ 0,  3,  6],
       [ 9, 12, 15]])
np.multiply(3, c)
array([[ 0,  3,  6],
       [ 9, 12, 15]])
# Vector outer product:
# 向量外积:
# a0*b0 + a0*b1 + a0*b2 +...
# a1*b0 + a1*b1 + a1*b2 +...
# ...
np.einsum('i,j', np.arange(2)+1, b)
array([[0, 1, 2, 3, 4],
       [0, 2, 4, 6, 8]])
np.einsum(np.arange(2)+1, [0], b, [1])
array([[0, 1, 2, 3, 4],
       [0, 2, 4, 6, 8]])
np.outer(np.arange(2)+1, b)
array([[0, 1, 2, 3, 4],
       [0, 2, 4, 6, 8]])
# Tensor contraction:
# 张量收缩:
a = np.arange(60.).reshape(3,4,5)
b = np.arange(24.).reshape(4,3,2)
np.einsum('ijk,jil->kl', a, b)
array([[4400., 4730.],
       [4532., 4874.],
       [4664., 5018.],
       [4796., 5162.],
       [4928., 5306.]])
np.einsum(a, [0,1,2], b, [1,0,3], [2,3])
array([[4400., 4730.],
       [4532., 4874.],
       [4664., 5018.],
       [4796., 5162.],
       [4928., 5306.]])
np.tensordot(a,b, axes=([1,0],[0,1]))
array([[4400., 4730.],
       [4532., 4874.],
       [4664., 5018.],
       [4796., 5162.],
       [4928., 5306.]])
# Writeable returned arrays
# 可写返回数组
# 设置 元素的值
a = np.zeros((3, 3))
np.einsum('ii->i', a)[:] = 1
a
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
# Example of ellipsis use
# 省略号使用示例
a = np.arange(6).reshape((3,2))
b = np.arange(12).reshape((4,3))
np.einsum('ki,jk->ij', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
np.einsum('ki,...k->i...', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
np.einsum('k...,jk', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
a = np.ones(64).reshape(2,4,8)
a
array([[[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]],

       [[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]]])
for iteration in range(500):
    _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a)
a
array([[[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]],

       [[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]]])
for iteration in range(500):
    _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize='optimal')
a
array([[[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]],

       [[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]]])
for iteration in range(500):
    _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize='greedy')
a
array([[[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]],

       [[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]]])
path = np.einsum_path('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize='optimal')[0]
for iteration in range(500):
    _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize=path)
a
array([[[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]],

       [[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]]])

官方文档

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值