zoukankan      html  css  js  c++  java
  • python科学计算_numpy_ufunc

    ufunc简介

    ufunc指universal function,是一种能够对数组中的所有元素进行操作的函数,ufunc是针对数组进行操作的函数,对一个数组进行重复的运算时,使用ufunc比math库中的函数效率要高很多,然而由于ufunc会对数组做一些特殊操作,所以在单一值的函数处理上就比math库中的效率要低;

    在使用ufunc时,注意千万不要用循环遍历,而是应该使用列表推导式,否则就不叫ufunc了,而是对每一个元素分别运算,失去了ufunc的意义;

    ufunc的结果可以直接保存到原始数组中,这样可以节省内存消耗;

    常用ufunc

    1. 四则运算

    ufunc支持全部四则运算,并且保留习惯的运算符,和数值运算使用一样,但是注意操作的是数组;

    两个数组的四则运算表示对两个数组中的元素分别进行四则运算,所以进行四则运算的数组形状必须相同(其实也可以不同,numpy会对形状不同的数组进行广播操作);

    避免写出一些复杂的表达式,如:

    x = a * b + c

    上述表达式在内存中的过程相当于:

    t = a * b
    x = t + c
    del t

    在其中会由一个中间变量t的内存消耗,为了避免该消耗,应该将表达式写成:

    x = a * b
    x += c

    2. 比较运算

    ufunc中也可以用完整的比较运算:> 、< 、 == 、 >= 、 <= 、 !=

    比较运算返回的结果是一个布尔数组,每个元素为两个数组对应元素的比较结果。

    3. 逻辑运算

    由于python中的逻辑运算:and、or、not使用的是关键字,无法被重载,所以numpy中的逻辑运算只能通过响应的ufunc函数进行;

    这些函数都以logical_开头:np.logical_and、np.logical_or、np.logical_not、np.logical_xor

    如果直接对两个布尔数组进行 and、or、not操作,则会对数组中的每个元素进行操作,对应的正确操作应该为逻辑谓词:存在和所有,

    在numpy中的对应函数为:np.any()、np.all()

    4. 位运算

    位运算使用 &,~,|,^ 分别做按位与、按位反、按位或、按位异或;

    自定义ufunc

    将一些只对单一值操作的函数(以下称标量函数)进行转换,得到对应的ufunc,可以使用numpy中的两个函数:frompyfunc和vectorize

    np.frompyfunc(func, nin, nout)函数需要指定三个参数,依次为:标量函数、输入参数个数、返回值个数;

    np.frompyfunc的返回值其类型均为object,通过astype()方法可以将类型做出相应的转换;

    np.vectorize(func, otypes=[])函数指定两个参数,依次为:标量参数、返回值的类型列表;

    广播broadcasting

    ufunc函数在对两个数组进行计算时,如果两个数组的形状不相同,则会进行广播处理,其处理的规则为:

    1. 让所有数组都向其中维数最多的数组看齐,shape属性中不足的部分都通过在前面加1补齐;

    2. 输出数组的shape属性是输入数组shape属性在各轴上的最大值;

    3. 如果输入数组的某个轴长度为1或与输出数组对应轴的长度相同,这个数组就能够用来计算,否则出错;

    4. 当输入数组的某个轴长度为1时,沿着此轴运算时都用此轴上的第一组值;

    如:

    a = np.array(0,60,10).reshape(-1,1)
    b = np.array(0,5)

    两个数组,其中a.shape = (6,1), b.shape = (5,),广播处理过程为:

    1. b数组向a数组看齐,并且在shape属性前面加1,此时,b.shape = (1,5)

    2. 输出数组的shape为(6,5),是数组shape各轴上的最大值;

    3. a.shape = (6,1),0轴与输出数组长度相同,1轴为1,可以用来计算;b.shape = (1,5),0轴为1,1轴与输出数组长度相同,可以用来计算;

    4. a数组的1轴长度为1,故a数组在1轴上的值都沿用 a[:,0]的值;b数组的0轴长度为1,故b数组0轴上的值都沿用 b[0,:]的值,此时,a,b数组可以看做:

     a = array([[0,  0,  0,  0,  0],
                     [10,10,10,10,10],
                     [20,20,20,20,20],
                     [30,30,30,30,30],
                     [40,40,40,40,40],
                     [50,50,50,50,50]])

     b = array([[0, 1, 2, 3, 4],
                      [0, 1, 2, 3, 4],
                      [0, 1, 2, 3, 4],
                      [0, 1, 2, 3, 4],
                      [0, 1, 2, 3, 4],
                      [0, 1, 2, 3, 4]])

    此时,a和b数组就可以进行相应的ufunc操作了;

    numpy在内部真正运算时,并不会对数组进行重复的填充操作,这样太浪费空间;

    事实上,numpy还提供了一个常用的网格对象来进行常用的广播操作:ogrid和mgrid

    其中,np.ogrid必须对其进行切片操作,并且返回一个数组,数组的每个值都是一个只有单一轴的数组,如:

    np.ogrid[:5,:4] = 
    [array([[0],
    [1],
    [2],
    [3],
    [4]]), array([[0, 1, 2, 3]])]

    而np.mgrid则是填充后的结果(由于比较消耗内存,应该使用ogrid代替):

    np.mgrid[:5,:5] = 

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

    [[0, 1, 2, 3],
    [0, 1, 2, 3],
    [0, 1, 2, 3],
    [0, 1, 2, 3],
    [0, 1, 2, 3]]])

    ufunc函数方法

    对只有一个输入、一个输出的ufunc函数对象,numpy中有一些特定的方法以供调用

    1. <op>.reduce(array, axis=0, dtype=None):和python中的reduce()类似,该方法沿着axis指定轴进行reduce操作,如:

       np.add.reduce([1,2,3])   # 返回6

       np.add.reduce([[1,2,3],[4,5,6]],axis=1)  # 返回[6,15]

       np.add.reduce([1,2,3],[4,5,6])  #返回 [5,7,9]

    2. <op>.accumulate()功能和reduce相同,但是该方法会返回每一步的结果,并且返回一个和原数组形状相同的结果数组;

    3. <op>.reduceat(array, indices=[]):indices参数指定一系列的起始和终止位置,当indices的最后一个元素小于倒数第二个时,会将该值作为新的起始值,而终止值为数组最大长度;

        计算规则为:

        if indices[i] < indices[i+1]:
            result = <op>.reduce(a[indices[i]:indices[i+1]])
        else:
            result[i] = a[indices[i]]

       若最后一个元素小于倒数第二个,则:

       result[i] = <op>.reduce(a[indices[-1]:])

    4. <op>.outer(array1,array2):方法对两个参数数组中每两个元素的组合依次进行运算,结果数组的形状为两个数组形状的组合,如第一个数组的形状为(2,3),第二个数组的形状为(4,5),则结果数组的形状为(2,3,4,5),如:

        np.multiply.outer([1,2,3,4],[2,3,4])

        array([[ 2, 3, 4],
        [ 4, 6, 8],
        [ 6, 9, 12],
        [ 8, 12, 16]])

  • 相关阅读:
    springboot文件上传: 单个文件上传 和 多个文件上传
    Eclipse:很不错的插件-devStyle,将你的eclipse变成idea风格
    springboot项目搭建:结构和入门程序
    POJ 3169 Layout 差分约束系统
    POJ 3723 Conscription 最小生成树
    POJ 3255 Roadblocks 次短路
    UVA 11367 Full Tank? 最短路
    UVA 10269 Adventure of Super Mario 最短路
    UVA 10603 Fill 最短路
    POJ 2431 Expedition 优先队列
  • 原文地址:https://www.cnblogs.com/lyon2014/p/4696989.html
Copyright © 2011-2022 走看看