机器学习:Jupyter Notebook中numpy的使用

一、Jupyter Notebook的魔法命令

 # 模块/方法 + ?或者help(模块/方法):查看模块/方法的解释文档;

 1)%run

 # 机械学习中主要应用两个魔法命令:%run、%timeit

 # 魔法命令格式:% + 命令

 # %run:将模块引用并在Jupyter Notebook中执行(这是与import的区别),模块被引用后,其内部的函数可以在Jupyter Notebook中直接被引用;

 # 格式:%run + 文件的地址 + 文件名

 2)%timeit

  1. 测试代码的性能,后面只能接一条语句/代码块,得出运行此条语句或代码块所用的时间;
  2. %timeit + 一条语句:测试该条语句运行所用时间;
  3. %%timeit:表示测试在该单元格内的全部代码运行时所用时间;
  4. %timeit、%%timeit,一般是将代码运行多遍,然后去取执行最快的几次的平均值;
  5. 如果%timeit和%%timeit后面的代码,每次运行的效率不同,则测量的结果又偏差;
  6. %time,返回只将代码运行一遍所用时间;但这样的测试结果不稳定,每次测得结果差异很大,但对于一次测试用时较长的代码/算法,测试差异可以忽略;

 3)其它

  • 命令 + ?:查看命令的文档;
  • 可以通过%lsmagic查看素有的魔法命令;
  • 机器学习算法中,scikit-learn中的函数封装的都是接收一个Numpy的矩阵,通常使用Pandas对数据进行预处理,将Pandas数据转换为Numpy的矩阵,再送给机械学习的算法;

二、numpy.array基础

 1)numpy.array的基础

  1. python的list数据非常灵活,运行效率较低,因为系统需要检测其中所有数据的类型;
  2. Python中的array模块,可以限定只存储一种数据类型:
import array
arr = array.array('i', [i for i in range(10)])
# 其中'i'表示数据类型为整数
print(type(arr[5]))
# 5
arr[5] = 'a'
# 报错,arr内的数据只能赋值为整数
  1. Python的array模块缺陷:1)中没有将数据看成向量或矩阵,因此也没有向量和矩阵相关的运算;2)只有一种数据类型,不够灵活使用;
  2. numpy模块的array方法,可以进行向量和矩阵的运算;
  3. numpy模块的array方法创建的数据,只能是整数,若将小数赋值给array方法创建的数据时,会自动转换为整数;
  4. 机械学习中所操作的大多数数值为浮点数;

 2)np.array的创建

  A、创建全0数组
  1. np.zeros(10):默认为float64类型的一维全0数组;
    array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
  2. np.zeros(10, dtype = int):数据类型为int的一维全0数组;
    array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
  3. np.zeros((3, 5)):默认fioat64类型的3行5列的矩阵;
    array([[0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0.]])
  4. np.zeros(shape = (3, 5), dtype = int)或者np.zeros( dtype = int, shape = (3, 5)):类型为int的3行5列的矩阵;
    array([[0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0]])
  
  B、创建全1的数组
  • np.ones(),操作方法同理全0矩阵的创建;
  
  C、创建所有值都相同的数组
  1. np.full((3, 5), 666)或者np.full(shape = (3, 5), fill_value = 666)或者np.full(fill_value = 666, shape = (3, 5)):默认为int;
    array([[666, 666, 666, 666, 666],
           [666, 666, 666, 666, 666],
           [666, 666, 666, 666, 666]])
  2. np.full(10, 666)或者np.full(shape = 10, fill_value = 666)或者np.full(fill_value = 666, shape = 10):
    array([666, 666, 666, 666, 666, 666, 666, 666, 666, 666])
  
  D、numpy中arange的用法:参数的用法与python中range的参数用法一样
  1. np.arange(0, 10):默认步长为1;
    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
  2. np.arange(10):默认起始值为0,默认步长为1;
    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
  3. np.arange(0, 10, 2):取值间隔为2;
    array([0, 2, 4, 6, 8])
  4. np.arange(0, 1, 0.2):步长可以为小数,0.2,而python中的range的参数,步长不能为小数;
    rray([0. , 0.2, 0.4, 0.6, 0.8])
  5. range()生成列表,np.arange()生成数组;
    
  E、numpy中linspace的用法,与arange类似
  • np.linspace(0, 20, 10):将0~20间的数等分10个点,首尾分别是0和20,此处10不是步长,而是将区间等分的点数(包含首尾数值);
    array([ 0.        ,  2.22222222,  4.44444444,  6.66666667,  8.88888889,
           11.11111111, 13.33333333, 15.55555556, 17.77777778, 20.        ])
  
  F、numpy中random的用法:生产随机int数random.randint()
  • 区间为前闭后开:[m,n);
  • 随机生成的数据给算法时,运行的结果不一致,导致调试困难;
  • 计算机中,所有的随机数都是伪随机数,都是随机算法实现的;推动算法生产随机数的是随机种子:同一个随机种子生产的随机数是一定的,再次调用该种子时可以得到上一次该种子生产的随机数;
  1. np.random.randint(0, 10):从0~10间随机生产一个z
    5
  2. np.random.randint(0, 10, 5):从0~10间随机生成5个int类型的数;
    array([8, 6, 3, 3, 6])
  3. np.random.randint(4, 8, size = 10):一般标出size = 10,提高代码可读性;
    array([6, 5, 6, 7, 4, 7, 7, 6, 5, 5])
  4. np.random.randint(4, 8, size = (3, 5)):从[4, 8)中,随机生成3行5列的矩阵;
    array([[7, 7, 5, 5, 5],
           [5, 7, 5, 7, 4],
           [6, 6, 4, 6, 5]])
  5. 随机种子的使用
    # Jupyter Notebook中实现的代码
    np.random.seed(666)
    np.random.randint(4, 8, size = (3, 5))
    # 设定随机种子,并生成随机数据
    np.random.seed(666)
    np.random.randint(4, 8, size = (3, 5))
    # 再次调用该种子,并再次生成原来格式的随机数据,所得到的数据与第一次随机生成的数据相同;
  G、numpy中random的使用:生成随机float数random.random()
  • 生成的float数为0~1的随机数
  • random.random()的操作格式与random.randint()一样;
    
  H、numpy中random的使用:随机生产满足正态分布的folat数;

   # 正态分布:均值为0,方差为1的分布规律;

  1. np.random.normal():默认为-1~1,默认均值为0方差为1,随机取一个数;
    -0.770927518770882
  2. np.random.normal(10, 100):默认均值为10方差为100,随机取一个数;
    -213.49687669162455
  3. np.random.normal(0, 1, (3, 5))或者np.random.normal(0, 1, size = (3, 5)):
    array([[ 1.42965241, -0.41407013, -1.32672274, -0.14880188,  0.34771289],
           [ 0.61030791, -1.17532603,  0.82985368, -0.30236752, -0.04327047],
           [ 0.06706965, -1.59102817,  0.01705112, -1.87296591, -0.96457904]])
  
  I、创建空矩阵
  1. np.empty(shape = (m, n), dtype = float):创建一个m行n列,数据类型为float的空矩阵;

 3)np.array的元素访问

  • np.aange(15).reshape(3, 5):将一维数组转换为多维数组;此处必须是3 X 5 = 15,数据总数不变;
    array([[ 0,  1,  2,  3,  4],
           [ 5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14]])
  A、array的基本属性

  # np.arange(15).reshape(3, 5) == np.arange(15).reshape(3, -1)

  1. array.ndim:返回array的维度;
  2. array.shape:返回array的行数和列数;
    # Jupyter Notebook中的代码
    import numpy as np
    
    x = np.arange(15).reshape(3, 5)
    x.shape
    # (3, 5)
  3. array.size:返回数组元素个数;
  
  B、numpy.array的数据访问
  1. 访问一维数组的一个:用 [ ] 进行引索,方式与python中访问列表元素一样;
  2. 访问一维数组的一段连续的数据:采用切片,方式与python中访问列表元素一样;
    import numpy as np
    arr = np.arange(10)
    print(arr[5:])
    # 输出:array([5, 6, 7, 8, 9])
    print(arr[::2])
    # 输出:array([0, 2, 4, 6, 8])
    print(arr[::-1])
    # 输出:array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
  3. 访问多维数组中的一个元素:arr[m, n],访问数组arr中第m + 1行与第n + 1列所对应的元素;
  4. 访问多维数组中的一段连续的元素:
    import numpy as np
    
    arr = np.arange(15).reshape(3, 5)
    print(arr[:2, :3])
    # 输出:array([[0, 1, 2],
                  [5, 6, 7]])
    print(arr[:2])
    # 输出:array([[0, 1, 2, 3, 4],
                  [5, 6, 7, 8, 9]])
    print(arr[:2, ::2])
    # 输出:array([[0, 2, 4],
                  [5, 7, 9]])
    print(arr[::-1, ::-1])
    # 输出:array([[14, 13, 12, 11, 10],
                  [ 9,  8,  7,  6,  5],
                  [ 4,  3,  2,  1,  0]]) 
  5. 由sub生成的子矩阵,是直接引用的原矩阵,并没有生成一个真实的矩阵,这样可提高数据的生成效率;
  6. 由sub生成的子矩阵更改是,子矩阵所引用(通过引用生成的子矩阵,而不是新建立)的矩阵也跟着更改;相同,更改矩阵后,引用它所生成的子矩阵也相应更改;
    arr = np.arange(15).reshape(3, 5)
    subarr = arr[:2, :3]
    print(subarr)
    # 输出:array([[0, 1, 2],
                  [5, 6, 7]])
    subarr[0, 0] = 100
    print(arr)
    # 输出:array([[100,   1,   2,   3,   4],
                [  5,   6,   7,   8,   9],
                 [ 10,  11,  12,  13,  14]])
    arr[0, 0] = 20
    print(subarr)
    # 输出:array([[20,  1,  2],
                  [ 5,  6,  7]]) 
  7. 子矩阵.copy():将子矩阵数据在磁盘中真实生成;再更改子矩阵时,对应的原矩阵不再跟着更改;

  4)numpy.array的合并

  #一维数组和向量都是一行,但向量是二位,可以通过reshape将一维数组转换为二位向量:arr.reshape(1, n);

  A、np.concatenate
  1. 连接两个一维数组:np.concatenate([arr1, arr2]),仍然为一维数组;
    import numpy as np
    
    a = np.array([1, 2, 3])
    b = np.array([4, 5, 6])
    c = np.concatenate([a, b])
    print(c)
    # 输出:array([1, 2, 3, 4, 5, 6])
  2. 连接两个二维数组:默认axis = 0,增加行数;axis = 1,增加列数; 当列数不相等的两个数组,只能连接增加列数;
    import numpy as np
    
    a = np.array([[1, 2, 3],
                  [4, 5, 6]])
    b1 = np.concatenate([a, a])
    print(b1)
    #array([[1, 2, 3],
            [4, 5, 6],
            [1, 2, 3],
            [4, 5, 6]])
    b2 = np.concatenate([a, a], axis = 1)
    print(b2)
    # array([[1, 2, 3, 1, 2, 3],
             [4, 5, 6, 4, 5, 6]])
  3. np.vstack([arr1, arr2]),两数组垂直相加,增加行数;
    a = np.arange(15).reshape(5, 3)
    b = np.arange(3)
    
    # 将b矩阵堆叠成和a矩阵行数相等;
    c = np.vstack([b] * a.shape[0])
    # array([[0, 1, 2],
             [0, 1, 2],
             [0, 1, 2],
             [0, 1, 2],
             [0, 1, 2]])
  4. np.hstack([arr1, arr2]),两数组水平相加,增加列数;
    import numpy as np
    
    # 创建全 1 向量:np.ones((m, n), dtype),(m, n) m 行 n 列,必须用tuple类型,不能用list类型,不然会报类型错误:data type not understood
    x = np.random.random(size=100).reshape(-1, 1)
    y = np.ones((len(x), 1), dtype = float) z = np.hstack([x, y])

  5)numpy.array的分割

  A、一维数组分割:分割点是数组中的数据的位号,而且必须为数组格式;
  1. 分成两断:
    a = np.arange(10)
    a1, a2 = np.aplit(a, [5])
    print(a1, a2)
    #array([0, 1, 2, 3, 4]) array([5, 6, 7, 8, 9])
  2.  分成多段:
    a = np.arange(10)
    a1, a2, a3 = np.aplit(a, [3, 6])
    print(a1, a2)
    #array([0, 1, 2]) array([4, 5, 6]) array([7, 8, 9])
  B、分割二位数组:
  1. 默认垂直分割,即axis = 0:把行数等分,若行数为奇数,第一个数组多一行;
    a = np.arange(15).reshape(3, 5)
    a1, a2 = np.split(a, [2])
    print(a1, a2)
    # array([[0, 1, 2, 3, 4],
               [5, 6, 7, 8, 9]])
    # array([[10, 11, 12, 13, 14]])
  2. 水平分割,axis = 1:与一维数组分割方式一样,分割点为第一行数据中的位号(序号);
    a = np.arange(15).reshape(3, 5)
    a1, a2 = np.split(a, [3], axis = 1)
    print(a1, a2)
    # array([[ 0,  1,  2],
             [ 5,  6,  7],
             [10, 11, 12]])
    # array([[ 3,  4],
             [ 8,  9],
             [13, 14]])
  3. 直接垂直分割:np.vsplit();
  4. 水平分割:np.hsplit(),不用指定axis的值;
  • #数据分割的意义:可以将数据集中的特征样本和标志分离开;

 

 6)numpy.array的具体运算

  A、numpy.array的加、减、乘、除法运算,array可以做为除数,也可以作为被除数

   #与数组中的每个元素相乘;

   #Python中的list直接与数字相乘,是把list中的数据复制对应次数,而不是与list数据中的每个数相乘;

   # np.array的运算比Python中的list的运算效率高很多;

  
  B、numpy.array的其它函数运算
  1. np.abs(array):向量中的所有元素取绝对值
  2. np.var(array):向量中所有元素的方差
  3. np.std(array):向量的均方差
  4. np.linalg.inv(array):矩阵的逆矩阵
  5. np.sin/cos/tan/cot(array):向量中的所有元素进行三角函数运算;
  6. np.mean(array):向量的平均值;
  7. np.exp(array):向量中的所有元素作为e的幂;
  8. np.power(3, array) == 3 ** array:向量中的所有元素作为3的幂;
  9. np.log5(array):对向量中的所有元素取5的对数;
  10. np.log(array):对向量中的所有元素取e的对数;
  11. len(array):返回矩阵的行数,或者向量的元素个数
  
  C、向量与矩阵之间的运算
  1. array.T:将矩阵转置;
  2. 向量 + 矩阵:
    a = np.arange(15).reshape(5, 3)
    b = np.arange(3)
    print(a + b)
    # array([[ 0,  2,  4],
             [ 3,  5,  7],
             [ 6,  8, 10],
             [ 9, 11, 13],
             [12, 14, 16]])
  3. 向量 * 矩阵:
    a = np.arange(15).reshape(5, 3)
    b = np.arange(3)
    print(a + b)
    # array([[ 0,  1,  4],
             [ 0,  4, 10],
             [ 0,  7, 16],
             [ 0, 10, 22],
             [ 0, 13, 28]])
  4. 矩阵与矩阵间的运算:必须满足矩阵运算的条件,与线性代数规则一样;格式:arr1.dot(arr2)、arr2.dot(arr1);
  5. 在numpy模块中,一维数组,即可以看成一行,也可以看做是一列;
  6. 求逆矩阵:np.linalg.inv(array);(逆矩阵必须满足一定的条件)
  7. 逆矩阵 * 原矩阵、原矩阵 * 逆矩阵 == 单位矩阵;
  8. 伪逆矩阵:一些没有逆矩阵的矩阵,可以求其伪逆矩阵:np.linalg.pinv(array),伪逆矩阵 * 原矩阵 == 伪单位矩阵(对角线的数为1,其余数不为0);

 

 7)numpy中的聚合运算

  # 聚合:将一组数合并成一个数;

  # Python中的sum()函数运算效率,远低于numpy.sum()方法;

  A、向量的聚合
  1. np.sum(array):将数组中的所有书相加;
  2. np.min/max(array):求数组中的最小值/最大值;
  3. 也可以:big_array.sum/min/max(),求值,只是方式不一样,但一般使用np.min(),增加代码的可读性;
   B、矩阵的聚合
  1. np.sum/min/max(array),对整个矩阵进行聚合;
  2. np.sum/min/max(array, axis = 1):对矩阵各行进行聚合;
    x = np.arange(16).reshape(4, 4)
    y = np.sum(x, axis = 1)
    print(y)
    # array([ 6, 22, 38, 54])
  3. np.sum/min/max(array, axis = 0):对矩阵各列进行聚合;
    x = np.arange(16).reshape(4, 4)
    y = np.sum(x, axis = 1)
    print(y)
    # array([24, 28, 32, 36])
  4. np.prod(array):将矩阵中所有元素相乘;
  5. np.prod(array + 1):先将矩阵中的所有元素都加1,再讲所有元素相乘;
  6. np.mean(array):求矩阵所有元素的平均值;
  7. np.median(array):求矩阵所有元素的中位数;
  8. np.percentile(big_array, q = 30):求百分位点的值,矩阵中30%的值都小于此数;
  9. np.percentile(big_array, q = 50) == np.median(array)、np.percentile(big_array, q = 100) == np.max(array);
  10. 一般看一组数的5个百分位点的值,就可大致看出此组数的分布情况:
    x = np.random.randint(0, 100, 200)
    for percent in [0, 25, 50, 75, 100]:
        print(np.percentile(x, q = percent))
  11. 求方差:np.var(big_array);
  12. 求标准差:np.std(big_array);

 

 8)numpy中的arg运算

  A、求数据的索引位置
  1. np.argmin/argmax(array):求矩阵中最小/大值在矩阵中的位置;
  
  B、排序和使用索引
  1. 出向量进行乱序处理:np.random.shuffle(array),将向量中的数据顺序打乱;
  2. 对向量中的数据进行排序处理:np.sort(array),此方法是返回了一个新的排好序的array,原来的array并没有改变;
  3. array.sort():对向量本身进行排序;
  4. np.sort(array):对矩阵进行排序,默认(axis = 1)每一行为一组数据单独排序;
  5. np.sort(array, axis = 0):对矩阵的每一列进行排序;
  6. np.argsort(array):对向量进行排序,返回一个新的数组,新的数组中为原数组元素排序号的元素序号;
    x1 = np.arange(15)
    np.random.shuffle(x1)
    x2 = np.argsort(x1)
    print(x1, x2)
    # array([ 3, 13,  4,  2,  8, 12,  6, 14, 11,  5,  1,  7, 10,  0,  9])
    # array([13, 10,  3,  0,  2,  9,  6, 11,  4, 14, 12,  8,  5,  1,  7],
          dtype=int64)
  7. np.partition(array, n):对数组中的数进行排序,小于n的数在左侧,大于n的数在右侧,左右两侧的数即不按大小顺序排列也不在按原来位置排列;一般多用于求数组中比某一值大/小的数;
    x1 = np.arange(15)
    np.random.shuffle(x1)
    x2 = np.argsort(x1)
    print(x1, x2)
    # array([ 4,  9, 10,  8, 11,  7, 13,  2,  5,  3,  6,  1,  0, 12, 14])
    # array([ 3,  2,  0,  1,  4,  5,  6,  7,  8, 10,  9, 11, 13, 12, 14])
  8. np.argpartition(array, n):返回x2数组中各元素在x1数组中的位置,与np.partition(array, n)的功能一样;
    x1 = np.arange(15)
    np.random.shuffle(x1)
    x2 = np.argsort(x1)
    print(x1, x2)
    # array([ 4,  9, 10,  8, 11,  7, 13,  2,  5,  3,  6,  1,  0, 12, 14])
    # array([ 3,  2,  0,  1,  4,  5,  6,  7,  8, 10,  9, 11, 13, 12, 14])
    # array([ 9,  7, 12, 11,  0,  8, 10,  5,  3,  2,  1,  4,  6, 13, 14],
          dtype=int64)
  9. np.argsort(array, axis = 1):对矩阵进行排序,返回各数据在原矩阵中的位置,axis默认为1,表示按进行排序;
  10. np.argsort(array, axis = 0):按列进行排序;规则同上;

 

 9)Numpy中的比较和Fancy Indexing

  A、索引一维数组中的任意数
  1. 索引是一维数组:ind = [1, 2, 5, 7, 8]
    x = np.arange(16)
    # 目标数在数组中对应的位置序号
    ind = [1, 2, 5, 7, 8]
    print(x[ind])
    # array([1, 2, 5, 7, 8])
  2. 索引是二维数组,则生成一个二维数组:ind = np.arange(4).reshape(2, 2);
    x = np.arange(16)
    # 目标数在数组中对应的位置序号
    ind = np.arange(4, 8).reshape(2, 2)
    print(x[ind])
    # array([[4, 5],
             [6, 7]])
  
  B、索引二位数组中的任意数
  1. 只索引其中的某几行:
    import numpy as np
    X = np.arange(16).reshape(4, -1)
    
    # 1)索引一行:X[2] == X[2, :]
    y1 = X[2]
    print(y1)
    # array([ 8,  9, 10, 11])
    
    # 2)索引某几行
    row = np.array([0, 1, 2])
    y2 = X[row]
    print(y2)
    # array([[ 0,  1,  2,  3],
             [ 4,  5,  6,  7],
             [ 8,  9, 10, 11]])
  2. 只索引其中的某几列:
    import numpy as np
    X = np.arange(16).reshape(4, -1)
    
    # 1)索引一列:X[:, 2]
    y1 = X[:, 2]
    print(y1)
    # array([ 2,  6, 10, 14])
    
    # 2)索引某几列:X[:, array]
    row = np.array([0, 1, 2])
    y2 = X[:, row]
    print(y2)
    # array([[ 0,  1,  2],
             [ 4,  5,  6],
             [ 8,  9, 10],
             [12, 13, 14]])
  3. 将目标数据在矩阵中的行号和列号,分别写在两个数组中:
    X = np.arange(16).reshape(4, -1)
    row = np.array([0, 1, 2])
    col = np.array([1, 2, 3])
    
    # 获取矩阵中的任意数据
    print(X[row, col])
    # array([1, 6, 11])
    
    # 获取矩阵中的某一行内的几个数据
    print(X[0, col])
    # array([1, 2, 3])
    
    # 获取矩阵中前两行数据中的某些数
    print(X[:2, col])
    # array([1, 2, 3],
            [5, 6, 7])
  4. 使用布尔数组进行引索:
    X = np.arange(16).reshape(4, -1)
    col = array([True, False, True, True])
    
    # 只对数组中为True的列/行进行引索
    print(X[1:3, col])
    # array([[4, 6, 7],
             [8, 10, 11]])
  C、比较
  1. array与一个数比较:将array中的所有数据与该数比较,返回布尔数组;
    x = np.arange(16)
    print(x < 5)
    # array([ True,  True,  True,  True,  True, False, False, False, False,
           False, False, False, False, False, False, False])
  2. array与array比较:两数组中的元素个数相等,对应元素进行比较,返回布尔数组;
    x1 = np.array([5, 4, 3, 2, 1])
    x2 = np.array([1, 2, 3, 4, 5])
    print(x1 > x2)
    # array([ True,  True, False, False, False])
  3. array经过运算后,与一个数或者另一个array比较:规则同理运算前的比较;
  4. np.sum(array < 5):获取array中小于5的数的个数;
  5. np.count_nonzero(array < 5):返回()内的布尔数组中非0元素的个数;
  6. np.any(array == 0):只要()内的布尔数组中有True,返回True,否则返回False;多用于查看array中是否有0元素;# np.any()的用法;
  7. np.all(array > 0):只有()内的布尔数组全为True,返回True,只要有一个False,则返回False;# np.all()的用法;
  8. np.sum(array % 2 == 0):获取矩阵中偶数的个数;
  9. np.sum(array % 2 == 0, axis = 1):获取矩阵每一行中偶数的个数;
  10. np.sum(array % 2 == 0, axis = 0):获取矩阵每一列中偶数的个数;
  11. np.sum((array >3) & (array < 10)):获取array中大于3且小于10的元素的个数;此处用“&”符号,相当于“and”;
  12. np.sum((array % 2 == 0) | (array > 10)):获取array中偶数与大于10的数的个数;此处用“|”符号,相当于“or”;
  13. np.sum(-(array == 0)):获取array中非0的数的个数;此处用“-”符号,相当于“not”;
  14. axis = 0:对矩阵中的每一列进行操作;axis = 1:对矩阵中的每一行进行操作;适用于所有方法;
  15. 二维矩阵的比较运算规则,与一维数组相同;