zoukankan      html  css  js  c++  java
  • some code about numpy and notes about copy&broadcasting

    import numpy as np
    np.__version__ #版本
    
    #由于python的list不要求存储同样的类型,但是效率不高。
    
    L = [i for i in range(10)]
    L[5] = "Asuka"
    
    #而调用array的效率相比更好,但是它没有将数据当做向量或者矩阵,不支持基本运算,会报错。
    #建议用numpy中的array,array是numpy中最核心的结构。
    nparr = np.array([i for i in range(10)])
    
    nparr[5] = 100.0 #单纯赋值无法修改整体的dtype
    nparr.dtype #数据类型改变数据类型
    nparr2 = np.array([1, 2, 3.0])  #有一个为float类型,整体即float类型
    nparr2.dtype
    
    #修改数据类型
    nparr2 = nparr2.astype('int')   #转为int
    
    np.zeros(10)     #0向量
    np.zeros(10, dtype=float)
    np.zeros((3, 5))     #0矩阵
    np.zeros(shape=(3, 5), dtype=int)
    
    np.ones(10)     #单位向量
    np.ones((3, 5))    #单位矩阵
    
    np.full((3, 5), 666)    #填充666
    np.full(fill_value=666, shape=(3, 5))
    
    np.arange(0, 20, 2)     # 2为step,而且与range相比,是可以用小数的
    np.arange(0,10,1.5)
    
    np.linspace(0, 20, 11)    #等分
    
    np.random.randint(0, 10)     #0~10之间的随机数
    np.random.randint(0, 10, size=10)      #长度为10的向量
    np.random.randint(0, 10, size=(3,5))    #矩阵
    np.random.seed(666)   #随机种子,再次调用时会产生相同的随机数
    np.random.random()     #返回在[0.0,1.0]之间的随机浮点数
    np.random.random((3,5))
    
    np.random.normal()     #均值为0,方差为1,符合正态分布的一个数
    np.random.normal(10, 100)    #均值为10,方差为100
    np.random.normal(0, 1, (3, 5))
    
    # 查询操作
    ① np.random.normal?
    ② help(np.random.normal)
    
    X = np.arange(15).reshape((3, 5))
    X.ndim    #维度
    X.shape     #形状
    X.size     #大小
    
    X[:2, :3]
    X[:2][:3] # 与前者结果不同,在numpy中使用","做多维索引
    X[:2, ::2]
    X[::-1, ::-1]
    
    subX = X[:2, :3].copy()    #副本,数据的变动不会影响原始数据
    
    X.reshape(5, 3)     #换形状
    X.reshape(3, -1)
    X.reshape(5, -1)
    
    # 向量合并
    x = np.array([1, 2, 3])
    y = np.array([3, 2, 1])
    z = np.array([666, 666, 666])
    np.concatenate([x, y, z])
    
    # 矩阵合并
    A = np.array([[1, 2, 3],[4, 5, 6]])
    np.concatenate([A, A])      # 纵向合并
    np.concatenate([A, A], axis=1)    #横向合并
    
    # 但是,concatenate是无法直接对向量和矩阵进行合并的,要讲向量转成矩阵在合并,如下:
    np.concatenate([A, z.reshape(1, -1)])
    
    # 这里顺便补充一下矩阵转向量的操作:
    A.ravel()
    
    # numpy提供了更便捷的vstack与hstack直接进行垂直or水平合并
    np.vstack([A, z])
    B = np.full((2,2), 100)
    np.hstack([A, B])
    
    # 向量分割
    x = np.arange(10)
    x1, x2 = np.split(x, [5])      # 01234|56789
    x1, x2, x3 = np.split(x, [3, 7])   # 012|3456|789
    
    # 矩阵分割
    A = np.arange(16).reshape((4, 4))
    A1, A2 = np.split(A, [2])    #垂直方向
    A1, A2 = np.split(A, [2], axis=1)     #水平方向
    
    #当然,numpy也提供了直接分割的方法:vsplit/hsplit
    upper, lower = np.vsplit(A, [2]).
    left, right = np.hsplit(A, [2])
    
    #每个数都乘2
    import numpy as np
    L = np.arange(10)
    %%time
    A = np.array(2*e for e in L)   #11ms
    %%time 
    A = 2 * L    #大概3ms的亚子,这样快
    
    X = np.arange(1, 16).reshape((3, 5))
    X + 1   #全部元素+1,减乘除同理
    X // 2   #除且取整
    X ** 2  #平方
    X % 2  #取模
    1 / X    #倒数
    np.abs(X)  #绝对值
    np.exp(X)  #exp
    np.exp2(X)   #以2为底,X为幂
    np.power(3, X)    #以3为底,X为幂
    np.log(X)    #lnx
    np.log2(X)
    np.log10(X)
    
    # 矩阵运算
    A = np.arange(4).reshape(2, 2)
    B = np.full((2, 2), 10)
    A * B    # 对应位置的元素相乘
    A.dot(B)  # 矩阵乘法
    A.T  # 转置
    invA = np.linalg.inv(A)  #逆矩阵
    invA.dot(A)    #原矩阵*逆矩阵=单位阵,前提是方阵,如果不是方阵,则error
    
    # 对于非方阵,需要提及伪逆,即非方阵的求逆
    X = np.arange(16).reshape((2, 8))
    pinvX = np.linalg.pinv(X)
    X.dot(pinvX)
    
    # 向量与矩阵的运算
    
    v = np.array([1, 2])
    A = np.arange(4).reshape(2, 2)
    v + A   #每一行都加上v,其内在机理是 np.vstack([v] * A.shape[0]) + A
    np.tile(v, (2, 1)) + A   #也可这么写,可以称之为扩展操作。
    np.tile(v, (2, 2))
    v * A     # 对应位置的元素相乘
    v.dot(A)    #1×2的v与2×2的A相乘
    A.dot(v)    #2×2的A和转置后2×1的v相乘
    
    # 聚合函数
    import numpy as np
    X = np.arange(16).reshape(4,-1)  
    np.sum(X)    #求和
    np.sum(X, axis=0)    #按列求和
    np.sum(X, axis=1)    #按行求和
    np.prod(X)    # X中各元素乘积
    np.mean(X)   #均值
    np.median(X)    #中位数
    big_array = np.random.rand(1000000)
    np.percentile(big_array, q=50)   #百分位数
    for percent in [0, 25, 50, 75, 100]: #打印四分位数
      print(np.percentile(big_array, q=percent))
    np.var(big_array)    #方差
    np.std(big_array)    #标准差
    x = np.random.normal(0, 1, 1000000)    #正态分布
    np.mean(x)
    np.std(x)
    
    np.argmin(x)   #最小值的索引
    np.argmax(x)   #最大值的索引
    
    x = np.arange(16)
    np.random.shuffle(x)    #乱序
    np.sort(x)    #排序,但是x并未改变
    x.sort()     #排序
    np.argsort(x)   # 排序索引
    np.partition(x, 3)    #对指定的标准点3的两侧分别进行排序
    np.argpartition(x, 3)     #对指定的标准点3的两侧分别进行排序的索引
    
    #对于矩阵
    X = np.random.randint(10, size=(4,4))
    np.argsort(X, axis=1)     #水平方向的排序的索引
    np.argpartition(X, 2, axis=1)     #带标准点2的水平方向的排序的索引
    
    #判断
    import numpy as np
    x = np.arange(16)
    np.random.shuffle(x)
    np.count_nonzero( x <= 3)    #统计满足条件的元素数
    np.sum(x <= 3)         #统计满足条件的元素数
    np.sum((x > 3) & (x < 10))     #不能是&&
    np.sum((x % 2 == 0) | (x > 10))        #统计满足条件的元素数
    np.sum(~(x == 0))       #统计满足条件的元素数
    np.any(x == 0)
    np.any(x < 0)
    np.all(x > 0)
    np.all(x >= 0)
    X = x.reshape(4, -1)
    np.all(X > 0, axis=1)
    np.sum(X % 2 == 0, axis=0)
    np.sum(X % 2 == 0, axis=1)
     

      此外,补充一些关于复制以及广播的知识叭。

      复制的话,上面的代码中,我们用到了一个copy(),这个正经点称之为深复制,通过这种方式,我们创建副本。当然,除了copy()以外,和复制相关的还有两种操作:赋值引用(即无复制)view()(视图,也称为浅复制)

      这三者之中,

      赋值引用,不会创建数组对象的副本,一个数组的任何变化都会反映到另一个数组上

    import numpy as np 
    #无复制 不会创建数组对象的副本,一个数组的任何变化都会反映到另一个数组上
    a = np.arange(6)  
    print('我们的数组a是:')
    print(a)
    print('调用 id() 函数:')  
    print(id(a))  
    print('赋值引用操作,得到b为:') 
    b = a 
    print(b)
    print('b拥有相同id():')  # 使用与原始数组相同的id
    print(id(b))
    print('修改b的形状:') 
    b.shape =  3,2
    print(b)
    print('a的形状也改变了:') 
    print(a)

      view()创建视图,新数据的维数更改不会更改原始数据的维数,但是数组的切片会影响原始数据

    # 浅复制与视图 新数据的维数更改不会更改原始数据的维数
    # 最开始a是个 3X2 的数组
    a = np.arange(6).reshape(3,2)  
    print('数组 a:' )
    print(a)
    print('创建a的视图:' )
    b = a.view()  
    print(b)
    print('两个数组的 id() 不同:')  
    print('a的id():')  
    print(id(a))
    print('b的id():')  
    print(id(b))  
    # 修改b的形状,并不会修改a
    b.shape =  2,3  
    print('b的形状:')  
    print(b) 
    print('a的形状:')  
    print(a)
    # 但是数组的切片也会创建视图
    a = np.array([[10,10],  [2,3],  [4,5]])  
    print('我们的数组:')
    print(a)
    print('创建切片:')
    s = a[:,  :2]  
    print(s)

      copy()创建副本,是一个数据的完整的拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置

    # 深复制 深复制创建的副本是数组及其数据的完整副本,不与原始数组共享 
    a = np.array([[10,10],  [2,3],  [4,5]])  
    print('数组a:')  
    print(a)
    print('创建a的深层副本:')
    b = a.copy()  
    print('数组b:')  
    print(b) 
    # b与a不共享任何内容  
    print('我们能够写入b来写入a吗?')
    print(b is a)
    print('修改b的内容:') 
    b[0,0]  =  100  
    print('修改后的数组b:') 
    print(b)
    print('a 保持不变:')
    print(a)

       广播(Broadcasting)可以解决不同形状的矩阵(或向量)之间的运算问题。因为在运算的过程中,不同形状的矩阵(或向量)之间无法进行基本运算,但是在numpy中,是比较宽容的,只要满足一般规则,这个运算的允许的。

    import numpy as np
    A = np.array([[1, 2, 3],
                        [4, 5, 6]])
    b = np.array([1, 2, 3])
    C = A + b
    C

      如此例,二维数组和一维数组相加时,二维上进行了两次加运算。

      广播的原则:整体而言,两个不同形状的矩阵(或者向量)进行基本运算,看两个矩阵(或者向量)的倒序维数。如果倒序维数是一致的,则“小矩阵”经过复制扩展,和“大矩阵”进行基本运算。

      

      但是,像下面这样的,b无法broadcasting后和A进行运算,会报错的。

      

  • 相关阅读:
    Excel导出到浏览器(个人备份)
    关于js性能
    关于JQuery(最后一点动画效果*)
    Python 2.7 学习笔记 内置语句、函数、标准库
    Python 2.7 学习笔记 模块和包
    Python 2.7 学习笔记 异常处理
    Python 2.7 学习笔记 字典(map)的使用
    Python 2.7 学习笔记 元组的使用
    Python 2.7 学习笔记 列表的使用
    Python 2.7 学习笔记 条件与循环语句
  • 原文地址:https://www.cnblogs.com/cruelty_angel/p/11641829.html
Copyright © 2011-2022 走看看