前言

本文主要来自于笔者在百度飞桨平台的学习笔记与总结,以及自己的一些编码实践。文末都会给出可以执行的示例代码。

Numpy介绍

NumPy(Numerical Python的简称)是高性能科学计算和数据分析的基础包。构建神经网络模型时,通常会使用NumPy实现数据预处理和一些模型指标的计算,数据可以很方便的和ndarray数组进行相互转换。

  • ndarray数组:一个具有矢量算术运算和复杂广播能力的多维数组,具有快速且节省空间的特点;
  • 对整组数据进行快速运算的标准数学函数(无需编写循环);
  • 线性代数、随机数生成以及傅里叶变换功能;
  • 读写磁盘数据、操作内存映射文件。

本质上,NumPy期望用户在执行“向量”操作时,像使用“标量”一样轻松。

a = np.array([1, 2, 3, 4])
b = np.array([1, 20, 30, 40])
c = a + b
print(c)

ndarray数组是NumPy的基础数据结构,可以灵活、高效地处理多个元素的操作。本节主要从如下五部分展开介绍:

  • 为什么引入ndarray数组
  • 如何创建ndarray数组
  • ndarray数组的基本运算
  • ndarray数组的切片和索引
  • ndarray数组的统计运算

1.1 为什么引入ndarray数组

Python中的list列表也可以非常灵活的处理多个元素的操作,但效率却非常低。与之比较,ndarray数组具有如下特点:

  • ndarray数组中所有元素的数据类型相同、数据地址连续,批量操作数组元素时速度更快。而list列表中元素的数据类型可能不同,需要通过寻址方式找到下一个元素。

  • ndarray数组支持广播机制,矩阵运算时不需要写for循环。

  • NumPy底层使用C语言编写,内置并行计算功能,运行速度高于Python代码。

案例1:实现a+1的计算

# Python原生的list
# 假设有两个list
a = [1, 2, 3, 4, 5]
b = [2, 3, 4, 5, 6]

# 完成如下计算
# 对a的每个元素 + 1
# a = a + 1 不能这么写,会报错
# a[:] = a[:] + 1 也不能这么写,也会报错
for i in range(5):
    a[i] = a[i] + 1

[2, 3, 4, 5, 6]

# 使用ndarray
import numpy as np
a = np.array([1, 2, 3, 4, 5])
a = a + 1
a

array([2, 3, 4, 5, 6])

案例2:实现c=a+b的计算

# 计算 a和b中对应位置元素的和,是否可以这么写?
a = [1, 2, 3, 4, 5]
b = [2, 3, 4, 5, 6]
c = a + b
# 检查输出发现,不是想要的结果
c

[1, 2, 3, 4, 5, 2, 3, 4, 5, 6]

# 使用for循环,完成两个list对应位置元素相加
c = []
for i in range(5):
    c.append(a[i] + b[i])
c

[3, 5, 7, 9, 11]

# 使用numpy中的ndarray完成两个ndarray相加
import numpy as np
a = np.array([1, 2, 3, 4, 5])
b = np.array([2, 3, 4, 5, 6])
c = a + b 
c

array([ 3, 5, 7, 9, 11])

通过上面的两个案例可以看出,在不写for循环的情况下,ndarray数组就可以非常方便的完成数学计算。在编写矢量或者矩阵的程序时,可以像编写普通数值一样,使得代码极其简洁。

另外,ndarray数组还提供了广播机制,它会按一定规则自动对数组的维度进行扩展以完成计算。如下面例子所示,1维数组和2维数组进行相加操作,ndarray数组会自动扩展1维数组的维度,然后再对每个位置的元素分别相加。

# 自动广播机制,1维数组和2维数组相加

# 二维数组维度 2x5
# array([[ 1,  2,  3,  4,  5],
#         [ 6,  7,  8,  9, 10]])
d = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
# c是一维数组,维度5
# array([ 4,  6,  8, 10, 12])
c = np.array([ 4,  6,  8, 10, 12])
e = d + c
e

array([[ 5, 8, 11, 14, 17], [10, 13, 16, 19, 22]])

1.2 创建ndarray数组

创建ndarray数组最简单的方式就是使用array函数,它接受一切序列型的对象(包括其他数组),然后产生一个新的含有传入数据的NumPy数组。下面通过实例体会下arrayarangezerosones四个主要函数的用法。

  • array:创建嵌套序列(比如由一组等长列表组成的列表),并转换为一个多维数组。
# 导入numpy
import numpy as np

# 从list创建array 
a = [1,2,3,4,5,6]  # 创建简单的列表
b = np.array(a)    # 将列表转换为数组
b

array([1, 2, 3, 4, 5, 6])

  • arange:创建元素从0到10依次递增2的数组。
# 通过np.arange创建
# 通过指定start, stop (不包括stop),interval来产生一个1维的ndarray
a = np.arange(0, 10, 2)
a

array([0, 2, 4, 6, 8])

  • zeros:创建指定长度或者形状的全0数组。
# 创建全0的ndarray
a = np.zeros([3,3])
a

array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])

  • ones:创建指定长度或者形状的全1数组。
# 创建全1的ndarray
a = np.ones([3,3])
a

array([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]])

1.3 查看ndarray数组的属性

ndarray的属性包括shapedtypesizendim等,通过如下代码可以查看ndarray数组的属性。

  • shape:数组的形状 ndarray.shape,1维数组(N, ),二维数组(M, N),三维数组(M, N, K)。
  • dtype:数组的数据类型。
  • size:数组中包含的元素个数 ndarray.size,其大小等于各个维度的长度的乘积。
  • ndim:数组的维度大小,ndarray.ndim, 其大小等于ndarray.shape所包含元素的个数。
a = np.ones([3, 3])
print('a, dtype: {}, shape: {}, size: {}, ndim: {}'.format(a.dtype, a.shape, a.size, a.ndim))

a, dtype: float64, shape: (3, 3), size: 9, ndim: 2

import numpy as np
b = np.random.rand(10, 10)
b.shape

(10, 10)

b.size

100

b.ndim

2

b.dtype

dtype(‘float64’)

1.4 改变ndarray数组的数据类型和形状

创建ndarray之后,可以对其数据类型或形状进行修改,代码如下所示。

# 转化数据类型
b = a.astype(np.int64)
print('b, dtype: {}, shape: {}'.format(b.dtype, b.shape))

# 改变形状
c = a.reshape([1, 9])
print('c, dtype: {}, shape: {}'.format(c.dtype, c.shape))

b, dtype: int64, shape: (3, 3)
c, dtype: float64, shape: (1, 9)

    a = np.ones([3, 3])
    print('a, dtype:{} ,shape: {}'.format(a.dtype, a.shape))
    print(a)
    b = a.astype(np.int64)
    print('b, dtype:{} ,shape: {}'.format(b.dtype, b.shape))
    print(b)
    c = a.reshape([1, 9])
    print('c, dtype:{} ,shape: {}'.format(b.dtype, b.shape))
    print(c)

注意:reshape()如果某个维度传-1,则表示这个维度的大小会根据数组的总元素数量和其他维度的大小自动计算,以保持数组的原有元素数量不变。
示例:

    arr = np.array([
        [[1, 2, 3], [4, 5, 6]], [[11, 22, 33], [44, 55, 66]],
        [[1.1, 2.2, 3.3], [4.4, 5.5, 6.6]], [[11.11, 22.22, 33.33], [44.44, 55.55, 66.66]]
    ])
    print(arr)
    print(arr.shape)
    print(arr.reshape(arr.shape[0], -1))
[[[ 1.    2.    3.  ]
  [ 4.    5.    6.  ]]

 [[11.   22.   33.  ]
  [44.   55.   66.  ]]

 [[ 1.1   2.2   3.3 ]
  [ 4.4   5.5   6.6 ]]

 [[11.11 22.22 33.33]
  [44.44 55.55 66.66]]]
(4, 2, 3)
[[ 1.    2.    3.    4.    5.    6.  ]
 [11.   22.   33.   44.   55.   66.  ]
 [ 1.1   2.2   3.3   4.4   5.5   6.6 ]
 [11.11 22.22 33.33 44.44 55.55 66.66]]

1.5 ndarray数组的基本运算

1.5.1 标量和ndarray数组之间的运算

标量和ndarray数组之间的运算主要包括除法、乘法、加法和减法运算,具体代码如下所示。

# 标量除以数组,用标量除以数组的每一个元素
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
1. / arr

array([[1. , 0.5 , 0.33333333], [0.25 , 0.2 , 0.16666667]])

# 标量乘以数组,用标量乘以数组的每一个元素
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
2.0 * arr

array([[ 2., 4., 6.], [ 8., 10., 12.]])

# 标量加上数组,用标量加上数组的每一个元素
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
2.0 + arr

array([[3., 4., 5.], [6., 7., 8.]])

# 标量减去数组,用标量减去数组的每一个元素
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
2.0 - arr

array([[ 1., 0., -1.], [-2., -3., -4.]])

1.5.2 两个ndarray数组之间的运算

两个ndarray数组之间的运算主要包括减法、加法、乘法、除法和开根号运算,具体代码如下所示。

# 数组 减去 数组, 用对应位置的元素相减
arr1 = np.array([[1., 2., 3.], [4., 5., 6.]])
arr2 = np.array([[11., 12., 13.], [21., 22., 23.]])
arr1 - arr2

array([[-10., -10., -10.], [-17., -17., -17.]])

# 数组 加上 数组, 用对应位置的元素相加
arr1 = np.array([[1., 2., 3.], [4., 5., 6.]])
arr2 = np.array([[11., 12., 13.], [21., 22., 23.]])
arr1 + arr2

array([[12., 14., 16.], [25., 27., 29.]])

# 数组 乘以 数组,用对应位置的元素相乘
arr1 * arr2

array([[ 11., 24., 39.], [ 84., 110., 138.]])

# 数组 除以 数组,用对应位置的元素相除
arr1 / arr2

array([[0.09090909, 0.16666667, 0.23076923], [0.19047619, 0.22727273, 0.26086957]])

# 数组开根号,将每个位置的元素都开根号
arr ** 0.5

array([[1. , 1.41421356, 1.73205081], [2. , 2.23606798, 2.44948974]])

1.6 ndarray数组的索引和切片

在编写模型过程中,通常需要访问或者修改ndarray数组某个位置的元素,则需要使用ndarray数组的索引。有些情况下可能需要访问或者修改一些区域的元素,则需要使用ndarray数组的切片。

ndarray数组的索引和切片的使用方式与Python中的list类似。通过[ -n , n-1 ]的下标进行索引,通过内置的slice函数,设置其start,stopstep参数进行切片,从原数组中切割出一个新数组。

ndarray数组的索引是一个内容丰富的主题,因为选取数据子集或单个元素的方式有很多。下面从一维数组和多维数组两个维度介绍索引和切片的方法。

1.6.1 一维ndarray数组的索引和切片

从表面上看,一维数组跟Python列表的功能类似,它们重要区别在于:数组切片产生的新数组,还是指向原来的内存区域,数据不会被复制,视图上的任何修改都会直接反映到源数组上。将一个标量值赋值给一个切片时,该值会自动传播到整个选区。

# 1维数组索引和切片
a = np.arange(30)
a[10]

10

a = np.arange(30)
b = a[4:7]
b

array([4, 5, 6])

#将一个标量值赋值给一个切片时,该值会自动传播到整个选区。
a = np.arange(30)
a[4:7] = 10
a

array([ 0, 1, 2, 3, 10, 10, 10, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29])

# 数组切片产生的新数组,还是指向原来的内存区域,数据不会被复制。
# 视图上的任何修改都会直接反映到源数组上。
a = np.arange(30)
arr_slice = a[4:7]
arr_slice[0] = 100
a, arr_slice

(array([ 0, 1, 2, 3, 100, 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]), array([100, 5, 6]))

# 通过copy给新数组创建不同的内存空间
a = np.arange(30)
arr_slice = a[4:7]
arr_slice = np.copy(arr_slice)
arr_slice[0] = 100
a, arr_slice

(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, 25, 26, 27, 28, 29]), array([100, 5, 6]))

1.6.2 多维ndarray数组的索引和切片

多维ndarray数组的索引和切片具有如下特点:

  • 在多维数组中,各索引位置上的元素不再是标量而是多维数组。
  • 以逗号隔开的索引列表来选取单个元素。
  • 在多维数组中,如果省略了后面的索引,则返回对象会是一个维度低一点的ndarray。

多维ndarray数组的索引代码如下所示。

# 创建一个多维数组
a = np.arange(30)
arr3d = a.reshape(5, 3, 2)
arr3d

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, 25], [26, 27], [28, 29]]])

# 只有一个索引指标时,会在第0维上索引,后面的维度保持不变
arr3d[0]

array([[0, 1], [2, 3], [4, 5]])

# 两个索引指标
arr3d[0][1]

array([2, 3])

# 两个索引指标
arr3d[0, 1]

array([2, 3])

多维ndarray数组的切片代码如下所示。

# 创建一个数组

a = np.arange(24)
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])

# reshape成一个二维数组
a = a.reshape([6, 4])
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]])

# 使用for语句生成list
[k for k in range(0, 6, 2)]

[0, 2, 4]

# 结合上面列出的for语句的用法
# 使用for语句对数组进行切片
# 下面的代码会生成多个切片构成的list
# k in range(0, 6, 2) 决定了k的取值可以是0, 2, 4
# 产生的list的包含三个切片
# 第一个元素是a[0 : 0+2],
# 第二个元素是a[2 : 2+2],
# 第三个元素是a[4 : 4+2]
slices = [a[k:k+2] for k in range(0, 6, 2)]
slices

[array([[0, 1, 2, 3], [4, 5, 6, 7]]), array([[ 8, 9, 10, 11], [12, 13, 14, 15]]), array([[16, 17, 18, 19], [20, 21, 22, 23]])]

slices[0]

array([[0, 1, 2, 3], [4, 5, 6, 7]])

轴翻转切片:
::-1:-1在切片操作中有不同的含义:

::-1 表示对整个轴进行切片,并以步长 -1 反转该轴的顺序。这个切片从起始位置到结束位置,以步长 -1 遍历,即反向读取整个轴上的元素。

arr = [0, 1, 2, 3, 4]
reversed_arr = arr[::-1]  
# 输出 [4, 3, 2, 1, 0]

:-1 表示对整个轴进行切片,但只选择到倒数第一个元素之前的部分(不包括最后一个元素)。
这个切片从起始位置到倒数第一个元素,但不包括最后一个元素。

arr = [0, 1, 2, 3, 4]
sliced_arr = arr[:-1]  
# 输出 [0, 1, 2, 3]

总结
::-1 是用来反转整个轴的元素顺序。
:-1 是用来选择整个轴的元素,直到倒数第一个元素之前的部分。
因此,::-1 适用于需要反转顺序的场景,而:-1 适用于需要排除最后一个元素的场景。

1.7 ndarray数组的统计方法

可以通过数组上的一组数学函数对整个数组或某个轴向的数据进行统计计算。主要包括如下统计方法:

  • mean:计算算术平均数,零长度数组的mean为NaN。
  • stdvar:计算标准差和方差,自由度可调(默认为n)。
  • sum :对数组中全部或某轴向的元素求和,零长度数组的sum为0。
  • maxmin:计算最大值和最小值。
  • argminargmax:分别为最大和最小元素的索引。
  • cumsum:计算所有元素的累加。
  • cumprod:计算所有元素的累积。

说明:

sum、mean以及标准差std等聚合计算既可以当做数组的实例方法调用,也可以当做NumPy函数使用。


# 计算均值,使用arr.mean() 或 np.mean(arr),二者是等价的
arr = np.array([[1,2,3], [4,5,6], [7,8,9]])
arr.mean(), np.mean(arr)

(5.0, 5.0)

# 求和
arr.sum(), np.sum(arr)

(45, 45)

# 求最大值
arr.max(), np.max(arr)

(9, 9)

# 求最小值
arr.min(), np.min(arr)

(1, 1)

# 指定计算的维度
# 沿着第1维求平均,也就是将[1, 2, 3]取平均等于2,[4, 5, 6]取平均等于5,[7, 8, 9]取平均等于8
arr.mean(axis = 1)

array([2., 5., 8.])

# 沿着第0维求和,也就是将[1, 4, 7]求和等于12,[2, 5, 8]求和等于15,[3, 6, 9]求和等于18
arr.sum(axis=0)

array([12, 15, 18])

# 沿着第0维求最大值,也就是将[1, 4, 7]求最大值等于7,[2, 5, 8]求最大值等于8,[3, 6, 9]求最大值等于9
arr.max(axis=0)

array([7, 8, 9])

# 沿着第1维求最小值,也就是将[1, 2, 3]求最小值等于1,[4, 5, 6]求最小值等于4,[7, 8, 9]求最小值等于7
arr.min(axis=1)

array([1, 4, 7])

# 计算标准差
arr.std()

2.581988897471611

# 计算方差
arr.var()

6.666666666666667

# 找出最大元素的索引
arr.argmax(), arr.argmax(axis=0), arr.argmax(axis=1)

(8, array([2, 2, 2]), array([2, 2, 2]))

# 找出最小元素的索引
arr.argmin(), arr.argmin(axis=0), arr.argmin(axis=1)

(0, array([0, 0, 0]), array([0, 0, 0]))

1.8维度变化

np.squeeze 的作用是从数组的形状中移除单维度条目,也就是将数组中维度长度为1的轴移除,从而降低数组的维度。

import numpy as np

arr = np.array([[[[1, 2]],
                  [[3, 4]],
                  [[5, 6]]]])
print("原始数组:")
print(arr)
print("原始数组形状:", arr.shape)

# 使用 np.squeeze 去掉长度为1的维度
arr_squeezed = np.squeeze(arr)

print("去掉长度为1的维度后的数组:")
print(arr_squeezed)
print("去掉长度为1的维度后的数组形状:", arr_squeezed.shape)
原始数组:
[[[[1 2]]

  [[3 4]]

  [[5 6]]]]
原始数组形状: (1, 3, 1, 2)
去掉长度为1的维度后的数组:
[[[1 2]
  [3 4]
  [5 6]]]
去掉长度为1的维度后的数组形状: (3, 2)

示例代码合集

import numpy as np


def func1():
    a = np.array([1, 2, 3, 4])
    b = np.array([1, 20, 30, 40])
    c = a + b
    print(c)


def func2():
    # 原生list
    print("use list...")
    a = [1, 2, 3, 4, 5]
    b = [2, 3, 4, 5, 6]
    for i in range(5):
        a[i] = a[i] + 1
    print(a)
    c = []
    for i in range(5):
        c.append(a[i] + b[i])
    print(c)
    # 使用ndarray
    print("use ndarray...")
    a = np.array([1, 2, 3, 4, 5])
    a = a + 1
    print(a)
    d = a + b
    print(d)

    e = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
    f = np.array([4, 6, 8, 10, 12])
    print(e + f)


def func3():
    a = [1, 2, 3, 4, 5, 6]
    b = np.array(a)
    print(b)
    a = np.arange(0, 10, 2)
    print(a)
    c = np.zeros([3, 3, 4])
    print(c)
    a = np.ones([3, 3])
    print(a)


def func4():
    a = np.ones([3, 3])
    print('a, dtype: {}, shape: {}, size: {}, ndim: {}'.format(a.dtype, a.shape, a.size, a.ndim))
    b = np.random.rand(10, 10)
    print(b)


def func5():
    a = np.ones([3, 3])
    print('a, dtype:{} ,shape: {}'.format(a.dtype, a.shape))
    print(a)
    # 转化数据类型
    b = a.astype(np.int64)
    print('b, dtype:{} ,shape: {}'.format(b.dtype, b.shape))
    print(b)
    # 改变形状
    c = a.reshape([1, 9])
    print('c, dtype:{} ,shape: {}'.format(b.dtype, b.shape))
    print(c)


def func6():
    arr = np.array([[1, 2, 3], [4, 5, 6]])
    # 标量除以数组,用标量除以数组的每一个元素
    print(1 / arr)
    print(2 * arr)
    print(2 + arr)
    print(2 - arr)


def func7():
    arr1 = np.array([[1, 2, 3], [4, 5, 6]])
    arr2 = np.array([[11., 12., 13.], [21., 22., 23.]])
    # 数组 减去 数组, 用对应位置的元素相减
    print(arr1 - arr2)
    print(arr1 + arr2)
    print(arr1 * arr2)
    print(arr1 / arr2)
    print(arr1 ** 0.5)


def func8():
    # 数组切片产生的新数组,还是指向原来的内存区域,数据不会被复制。
    # 视图上的任何修改都会直接反映到源数组上。
    a = np.arange(30)
    b = a[4:7]
    print(b)
    a[4:7] = 10
    print(a)
    a_slice = a[4:7]
    a_slice[0] = 100
    print(a)
    # 通过copy给新数组创建不同的内存空间
    a = np.arange(30)
    arr_slice = a[4:7]
    arr_slice = np.copy(arr_slice)
    arr_slice[0] = 100
    print(a)
    print(arr_slice)


def func9():
    a = np.arange(30)
    arr3d = a.reshape(5, 3, 2)
    print(arr3d)
    # 只有一个索引指标时,会在第0维上索引,后面的维度保持不变
    print("arr3d[0]:", arr3d[0])
    # 两个索引指标
    print("arr3d[0][1]:", arr3d[0][1])
    a = np.arange(24)
    a = a.reshape([6, 4])
    print(a)
    # 使用for语句生成list:[k for k in range(0, 6, 2)]
    # 结合上面列出的for语句的用法
    # 使用for语句对数组进行切片
    # 下面的代码会生成多个切片构成的list
    # k in range(0, 6, 2) 决定了k的取值可以是0, 2, 4
    # 产生的list的包含三个切片
    # 第一个元素是a[0 : 0+2],
    # 第二个元素是a[2 : 2+2],
    # 第三个元素是a[4 : 4+2]
    slices = [a[k:k + 2] for k in range(0, 6, 2)]
    print(slices)
    print(slices[0])


def func10():
    arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    # 计算均值,使用arr.mean() 或 np.mean(arr),二者是等价的
    print(arr.mean())
    print(np.mean(arr))
    # 求和
    print(arr.sum())
    print(np.sum(arr))
    # 求最大值
    print(arr.max())
    print(np.max(arr))
    # 求最小值
    print(arr.min())
    print(np.min(arr))
    # 指定计算的维度
    # 沿着第1维求平均,也就是将[1, 2, 3]取平均等于2,[4, 5, 6]取平均等于5,[7, 8, 9]取平均等于8
    print(arr.mean(axis=1))
    # 沿着第0维求和,也就是将[1, 4, 7]求和等于12,[2, 5, 8]求和等于15,[3, 6, 9]求和等于18
    print(arr.sum(axis=0))
    # 沿着第0维求最大值,也就是将[1, 4, 7]求最大值等于7,[2, 5, 8]求最大值等于8,[3, 6, 9]求最大值等于9
    print(arr.max(axis=0))
    # 沿着第1维求最小值,也就是将[1, 2, 3]求最小值等于1,[4, 5, 6]求最小值等于4,[7, 8, 9]求最小值等于7
    print(arr.min(axis=1))
    # 计算标准差
    print(arr.std())
    # 计算方差
    arr.var()
    # 找出最大元素的索引
    print(arr.argmax(), arr.argmax(axis=0), arr.argmax(axis=1))


if __name__ == "__main__":
    # func1()
    # func2()
    # func3()
    # func4()
    # func5()
    # func6()
    # func7()
    # func8()
    # func9()
    func10()

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐