• 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]])

  • 相关阅读:
    Spring Boot 内嵌Tomcat的端口号的修改
    仅显示INPUT下边框
    2015面试记三
    2015面试记二
    2015面试记一
    最近工作学习心得体会
    Tomcat批处理文件小结
    启动Tomcat一闪而过——分析及解决过程
    WIN7安装及配置JDK
    Firefox下载文件时中文名乱码问题
  • 原文地址:https://www.cnblogs.com/lyon2014/p/4696989.html
Copyright © 2020-2023  润新知