numpy -- ndarray

来源:互联网 发布:汉诺塔非递归算法c语言 编辑:程序博客网 时间:2024/05/16 23:58

NumPy提供了两种基本的对象:ndarray(N-dimensional array object)和 ufunc(universal function object)。ndarray(下文统一称之为数组)是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数。


1.创建

1.1.创建时指定元素类型

import numpy as npa = np.array([[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]])b = np.array([[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]], dtype='str')print (a)print ('---')print (b)# 输出 [[ 1  2  3  4] [ 4  5  6  7] [ 7  8  9 10]]---[['1' '2' '3' '4'] ['4' '5' '6' '7'] ['7' '8' '9' '10']]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

1.2.转换数据类型: .astype

# 接上面数据b = b.astype(int)print (b)# 输出 [[ 1  2  3  4] [ 4  5  6  7] [ 7  8  9 10]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

1.3. array数组的数据类型

bool -- True , Falseint -- int16 , int32 , int64float -- float16 , float32 , float64string -- string , unicode
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

1.4.查询矩阵的大小: .shape

import numpy as npa = np.array([1, 2, 3, 4])b = np.array([[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]])print (a.shape)print ('---')print (b.shape)# 输出 (4,)---(3, 4)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

(4, )shape有一个元素即为一维数组,数组中有4个元素 
(3, 4)shape有两个元素即为二维数组,数组为3行4列

通过修改数组的shape属性,在保持数组元素个数不变的情况下,改变数组每个轴的长度。下面的例子将数组b的shape改为(4, 3),从(3, 4)改为(4, 3)并不是对数组进行转置,而只是改变每个轴的大小,数组元素在内存中的位置并没有改变:

b.shape = 4, 3print (b)# 输出 [[ 1  2  3] [ 4  4  5] [ 6  7  7] [ 8  9 10]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

当某个轴的元素为-1时,将根据数组元素的个数自动计算该轴的长度,下面程序将数组b的shape改为了(2, 6):

b.shape = 2, -1print (b)# 输出 [[ 1  2  3  4  4  5] [ 6  7  7  8  9 10]]
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

组元不需要圆括号虽然我们经常在Python中用圆括号将组元括起来,但是其实组元的语法定义只需要用逗号隔开即可,例如 x,y=y,x。

1.5.使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape保持不变:

a = np.array((1, 2, 3, 4))b = a.reshape((2, 2))b# 输出 array([[1, 2],       [3, 4]])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

1.6. 复制

(1) = 
a和b共享数据存储内存区域,因此修改其中任意一个数组的元素都会同时修改另外一个数组或矩阵的内容:

a[2] = 100 # 将数组a的第3个元素改为100,数组d中的2即第三个元素也发生了改变b# 输出 array([[1, 2],       [100, 4]])
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
import numpy as npa = np.arange(12)b = aprint (a)print (b)print (b is a) # 判断b是a?# 输出 [ 0  1  2  3  4  5  6  7  8  9 10 11]    [ 0  1  2  3  4  5  6  7  8  9 10 11]    Trueb.shape = 3, 4print (a.shape)# 输出 (3, 4)print (id(a))print (id(b))# 输出 2239367199840    2239367199840
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

(2) .view()

 浅复制,a和b共享数据区域,但是可以有不同的表现形式(维度),改变b的shape,a的不会受到影响,而=复制会同时改变a和b的shape。

  (a 和 b 数据是相同的,只是解析数据的方式不同而已)

# The view method creates a new array object that looks at the same data.import numpy as npa = np.arange(12)b = a.view() # b是新创建出来的数组,但是b和a共享数据b is a # 判断b是a?# 输出 Falseprint (b)# 输出 [ 0  1  2  3  4  5  6  7  8  9 10 11]b.shape = 2, 6 # 改变b的shape,a的shape不会受影响print (a.shape)print (b)# 输出 (12,)[[ 0  1  2  3  4  5] [ 6  7  8  9 10 11]]b[0, 4] = 1234 # 改变b第1行第5列元素为1234,a对应位置元素受到影响print (b)# 输出 [[   0    1    2    3 1234    5]         [   6    7    8    9   10   11]]print (a)# 输出 [   0    1    2    3 1234    5    6    7    8    9   10   11]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

(3) .copy()

深复制

# The copy method makes a complete copy of the array and its data.import numpy as npa = np.arange(12)a.shape = 3, 4a[1, 0] = 1234c = a.copy()c is ac[0, 0] = 9999 # 改变c元素的值,不会影响a的元素print (c)print (a)# 输出 [[9999    1    2    3] [1234    5    6    7] [   8    9   10   11]][[   0    1    2    3] [1234    5    6    7] [   8    9   10   11]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

1.7.查询维度: .ndim

import numpy as npa = np.array([[5, 10, 15],       [20, 25, 30],       [35, 40, 45]])a.ndim# 输出 2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

1.8.查询元素个数: .size

import numpy as npa = np.array([[5, 10, 15],       [20, 25, 30],       [35, 40, 45]])a.size# 输出 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

1.9.创建0矩阵: .zeros

np.zeros((3, 4)) # 创建3行4列的0矩阵np.zeros((3, 4), dtype=np.str) # 可以在创建的时候指定数据类型
  • 1
  • 2
  • 1
  • 2

1.10.创建1矩阵: .ones

np.noes((3, 4)) # 创建3行4列的1矩阵
  • 1
  • 1

1.11.区间内按等差创建矩阵: .arange

np.arange(10, 30, 5) # 10开始到30,没加5生成一个元素# 输出array([10, 15, 20, 25])# 可以通过修改shape属性改变维度,参考上文np.arange(0, 2, 0.3) # 0开始到2,没加0.3生成一个元素# 输出array([0, 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])np.arange(12).reshape(3, 4) # 从0开始每加1共生成12个元素,并通过reshape设定矩阵大小为3行4列# 输出array([[0, 1, 2, 3],             [4, 5, 6, 7],             [8, 9, 10, 11]])np.random.random((2, 3)) # 生成2行3列矩阵,元素为0-1之间的随机值
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

1.12.区间内按元素个数取值: .linspace

from numpy import pinp.linspace(0, 2*pi, 100) # 0到2*pi,取100个值

2. 结构

下面让我们来看看ndarray数组对象是如何在内存中储存的。如图2.1所示,关于数组的描述信息保存在一个数据结构中,这个结构引用两个对象:一块用于保存数据的存储区域和一个用于描述元素类型的dtype对象。

_images/numpy_memory_struct.png

图2.1 ndarray数组对象在内存中的储存方式

数据存储区域保存着数组中所有元素的二进制数据,dtype对象则知道如何将元素的二进制数据转换为可用的值。数组的维数、大小等信息都保存在ndarray数组对象的数据结构中。图中显示的是如下数组的内存结构:

>>> a = np.array([[0,1,2],[3,4,5],[6,7,8]], dtype=np.float32)

  • 1
  • 2

strides中保存的是当每个轴的下标增加1时,数据存储区中的指针所增加的字节数。例如图中的strides为12,4,即第0轴的下标增加1时,数据的地址增加12个字节:即a[1,0]的地址比a[0,0]的地址要高12个字节,正好是3个单精度浮点数的总字节数;第1轴下标增加1时,数据的地址增加4个字节,正好是单精度浮点数的字节数。

如果strides中的数值正好和对应轴所占据的字节数相同的话,那么数据在内存中是连续存储的。然而数据并不一定都是连续储存的,前面介绍过通过下标范围得到新的数组是原始数组的视图,即它和原始视图共享数据存储区域:

>>> b = a[::2,::2]>>> barray([[ 0.,  2.],       [ 6.,  8.]], dtype=float32)>>> b.strides(24, 8)

由于数组b和数组a共享数据存储区,而b中的第0轴和第1轴都是数组a中隔一个元素取一个,因此数组b的strides变成了24,8,正好都是数组a的两倍。 对照前面的图很容易看出数据0和2的地址相差8个字节,而0和6的地址相差24个字节。

元素在数据存储区中的排列格式有两种:C语言格式和Fortan语言格式。在C语言中,多维数组的第0轴是最上位的,即第0轴的下标增加1时,元素的地址增加的字节数最多;而Fortan语言的多维数组的第0轴是最下位的,即第0轴的下标增加1时,地址只增加一个元素的字节数。在NumPy中,元素在内存中的排列缺省是以C语言格式存储的,如果你希望改为Fortan格式的话,只需要给数组传递order="F"参数:

>>> c = np.array([[0,1,2],[3,4,5],[6,7,8]], dtype=np.float32, order="F")>>> c.strides(4, 12)

3. 运算

3.1.求和 .sum() 
3.2.求最大值 .max() 
3.3.求最小值 .min() 
3.4.求平均值 .mean()

import numpy as nptest1 = np.array([[5, 10, 15],            [20, 25, 30],            [35, 40, 45]])test1.sum()# 输出 225test1.max()# 输出 45test1.min()# 输出 5test1.mean()# 输出 25.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3.5.矩阵行求和 .sum(axis=1)

test1 = np.array([[5, 10, 15],            [20, 25, 30],            [35, 40, 45]])test1.sum(axis=1)# 输出 array([30, 75, 120])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

3.6.矩阵列求和 .sum(axis=0)

test1 = np.array([[5, 10, 15],            [20, 25, 30],            [35, 40, 45]])test1.sum(axis=0)# 输出 array([60, 75, 90])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

3.7.矩阵乘法

import numpy as npa = np.array([[1, 2],              [3, 4]])b = np.array([[5, 6],              [7, 8]])print (a*b) # 对应位置元素相乘print (a.dot(b)) # 矩阵乘法print (np.dot(a, b)) # 矩阵乘法,同上# 输出 [[5 12]       [21 32]]      [[19 22]       [43 50]]      [[19 22]       [43 50]]  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

3.8.元素求平方: a**2

a = np.range(4)print (a)print (a**2)# 输出 [0, 1, 2, 3]      [0, 1, 4, 9]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

3.9.元素求e的n次幂: np.exp(test) 
元素开根号: np.sqrt(test)

import numpy as nptest = np.arange(3)print (test)print (np.exp(test)) #e的n次幂print (np.sqrt(test)) #开根号# 输出 [0 1 2]    [1. 2.71828183 7.3890561]    [0 1. 1.41421356]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3.10.向下取整: .floor()

import numpy as nptest = np.floor(10*np.random.random((3, 4)))print (test)# 输出 [[ 3.  8.  7.  0.]     [ 5.  9.  8.  2.]     [ 3.  0.  9.  0.]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.11.平坦化数组: .ravel()

# 二维n行n列转换为一维数组test.ravel()# 输出 array([ 3.,  8.,  7.,  0.,  5.,  9.,  8.,  2.,  3.,  0.,  9.,  0.]) # 数据接上面,下同
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

3.12.矩阵转置: .T

test.shape = (6, 2)print (test)# 输出 [[ 3.  8.] [ 7.  0.] [ 5.  9.] [ 8.  2.] [ 3.  0.] [ 9.  0.]]test.T # test的转置# 输出 array([[ 3.,  7.,  5.,  8.,  3.,  9.],       [ 8.,  0.,  9.,  2.,  0.,  0.]])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3.13.矩阵拼接按行: np.vstack((a, b)) 
矩阵拼接按列: np.hstack((a, b))

import numpy as npa = np.floor(10*np.random.random((2, 2)))b = np.floor(10*np.random.random((2, 2)))print (a)print ('---')print (b)print ('---')print (np.vstack((a, b))) # 按行拼接,也就是竖方向拼接print ('---')print (np.hstack((a, b))) # 按列拼接,也就是横方向拼接# 输出 [[ 5.  3.] [ 8.  0.]]---[[ 3.  0.] [ 6.  3.]]---[[ 5.  3.] [ 8.  0.] [ 3.  0.] [ 6.  3.]]---[[ 5.  3.  3.  0.] [ 8.  0.  6.  3.]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

3.14.矩阵分割按列: np.hsplit(a, 3) 和 np.hsplit(a, (3, 4))

import numpy as npa = np.floor(10*np.random.random((2, 12)))print (a)# 输出 [[ 6.  7.  5.  7.  9.  1.  2.  3.  1.  9.  5.  7.] [ 6.  5.  2.  0.  1.  7.  8.  2.  7.  0.  5.  9.]]print (np.hsplit(a, 3)) # 按列分割,也就是横方向分割,参数a为要分割的矩阵,参数3为分成三份print ('---')print (np.hsplit(a, (3, 4))) # 参数(3, 4)为在维度3前面也就是第4列前切一下,在维度4也就是第5列前面切一下# 输出 [array([[ 6.,  7.,  5.,  7.],       [ 6.,  5.,  2.,  0.]]), array([[ 9.,  1.,  2.,  3.],       [ 1.,  7.,  8.,  2.]]), array([[ 1.,  9.,  5.,  7.],       [ 7.,  0.,  5.,  9.]])]---[array([[ 6.,  7.,  5.],       [ 6.,  5.,  2.]]), array([[ 7.],       [ 0.]]), array([[ 9.,  1.,  2.,  3.,  1.,  9.,  5.,  7.],       [ 1.,  7.,  8.,  2.,  7.,  0.,  5.,  9.]])]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.15.矩阵分割按行: np.vsplit(a, 3) 和 np.vsplit(a, (3, 4))

import numpy as npa = np.floor(10*np.random.random((12, 2)))print (a)# 输出 [[ 5.  4.] [ 8.  7.] [ 3.  1.] [ 6.  0.] [ 4.  4.] [ 4.  5.] [ 2.  4.] [ 7.  3.] [ 1.  6.] [ 6.  9.] [ 2.  1.] [ 3.  0.]]print (np.vsplit(a, 3)) # 按行分割,也就是横竖方向分割,参数a为要分割的矩阵,参数3为分成三份print ('---')print (np.vsplit(a, (3, 4))) # 参数(3, 4)为在维度3前面也就是第4行前切一下,在维度4也就是第5行前面切一下# 输出 [array([[ 5.,  4.],       [ 8.,  7.],       [ 3.,  1.],       [ 6.,  0.]]), array([[ 4.,  4.],       [ 4.,  5.],       [ 2.,  4.],       [ 7.,  3.]]), array([[ 1.,  6.],       [ 6.,  9.],       [ 2.,  1.],       [ 3.,  0.]])]---[array([[ 5.,  4.],       [ 8.,  7.],       [ 3.,  1.]]), array([[ 6.,  0.]]), array([[ 4.,  4.],       [ 4.,  5.],       [ 2.,  4.],       [ 7.,  3.],       [ 1.,  6.],       [ 6.,  9.],       [ 2.,  1.],       [ 3.,  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
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

3.16.查找并修改矩阵特定元素 

利用==判断数组或矩阵中是否存在某个值

这里写图片描述

将判断结果赋给某个变量

这里写图片描述

一次判断多个条件

这里写图片描述


例如下面代码中,x_data是我代码中的一个矩阵,但是矩阵数据中有缺失值是用?表示的,我要做一些数据处理,就需要把?换掉,比如换成0
x_data[x_data == '?'] = 0


4. 其他

注意:NumPy和Matlab不一样,对于多维数组的运算,缺省情况下并不使用矩阵运算,如果你希望对数组进行矩阵运算的话,可以调用相应的函数。

matrix对象

numpy库提供了matrix类,使用matrix类创建的是矩阵对象,它们的加减乘除运算缺省采用矩阵方式计算,因此用法和matlab十分类似。但是由于NumPy中同时存在ndarray和matrix对象,因此用户很容易将两者弄混。这有违Python的“显式优于隐式”的原则,因此并不推荐在较复杂的程序中使用matrix。下面是使用matrix的一个例子:

>>> a = np.matrix([[1,2,3],[5,5,6],[7,9,9]])>>> a*a**-1matrix([[  1.00000000e+00,   1.66533454e-16,  -8.32667268e-17],        [ -2.77555756e-16,   1.00000000e+00,  -2.77555756e-17],        [  1.66533454e-16,   5.55111512e-17,   1.00000000e+00]])

因为a是用matrix创建的矩阵对象,因此乘法和幂运算符都变成了矩阵运算,于是上面计算的是矩阵a和其逆矩阵的乘积,结果是一个单位矩阵。

矩阵的乘积可以使用dot函数进行计算。对于二维数组,它计算的是矩阵乘积,对于一维数组,它计算的是其点积。当需要将一维数组当作列矢量或者行矢量进行矩阵运算时,推荐先使用reshape函数将一维数组转换为二维数组:

>>> a = array([1, 2, 3])>>> a.reshape((-1,1))array([[1],       [2],       [3]])>>> a.reshape((1,-1))array([[1, 2, 3]])


补充: dot 运算

dot 对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为内积);对于二维数组,计算的是两个数组的矩阵乘积;对于多维数组,它的通用计算公式如下,即结果数组中的每个元素都是:数组a的最后一维上的所有元素与数组b的倒数第二位上的所有元素的乘积和:

dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])

下面以两个3为数组的乘积演示一下dot乘积的计算结果:

首先创建两个3维数组,这两个数组的最后两维满足矩阵乘积的条件:

>>> a = np.arange(12).reshape(2,3,2)>>> b = np.arange(12,24).reshape(2,2,3)>>> c = np.dot(a,b)

dot乘积的结果c可以看作是数组a,b的多个子矩阵的乘积:

>>> np.alltrue( c[0,:,0,:] == np.dot(a[0],b[0]) )True>>> np.alltrue( c[1,:,0,:] == np.dot(a[1],b[0]) )True>>> np.alltrue( c[0,:,1,:] == np.dot(a[0],b[1]) )True>>> np.alltrue( c[1,:,1,:] == np.dot(a[1],b[1]) )True
原创粉丝点击