【问题标题】:How can I turn this function into a unfunc without for loops?如何在没有 for 循环的情况下将此函数转换为 unfunc?
【发布时间】:2015-06-24 06:22:59
【问题描述】:

我正在尝试根据一系列值(y 轴与 x 轴)绘制我创建的函数。

我要计算的运算在“矩阵乘法”中很常见:

r^T * C * r 

其中 r^T 的形状应为 (1,100),r 的形状应为 (100,1),而 C 是形状为 (100,100) 的矩阵(或 ndarray 形状 100,100)。使用numpy.dot() 相乘,输出应该是单个值。

该函数只有一个输入,可以是一组数据。

import numpy as np

# The user first sets the values used by the function
# Not "true code", because input() too complex for the question at hand

r = data                        # an numpy ndarray of 100 values, (100,)
original_matrix =  M            # set matrix, such that M.shape = (100, 100)
param = array of data           # EITHER an array of values, shape (50,), 
                                # OR one value, i.e. a 32/64-bit float
                                # e.g. parameters = np.array of 50 values

def function(param):
    # using broadcasting, "np.sum(param * original_matrix for i in r)"
    new_matrix = np.sum(param[:, None, None] * original_matrix, axis=0)
    # now perform r^T * C * r
    return np.dot( r.transpose(), np.dot( new_matrix,  r) )

调用函数

function(param)

产生 一个 值,格式为 = numpy.float64

我想根据一系列值绘制这个函数,即我需要这个函数来输入一个 np.array 并输出一个 np.cdarray,必须像 NumPy 中的其他 ufuncs。该函数将评估 ndarray 中的每个元素,并将其绘制为函数。

例如,

import pylab

X = np.arange(100)
Y = sin(X)
pylab.plot(X, Y)

输出

鉴于我的原始函数(仅是数组“参数”的函数)导致np.float64 格式,我如何将这个函数转换为ufunc?我想根据 x 轴上的参数在 y 轴上绘制我的函数。

【问题讨论】:

  • x 轴上的参数是什么意思?您是否有要迭代并查找 y 值的参数数组列表?
  • 希望帖子现在更清楚了。该函数仅依赖于参数数组param。 y 轴是这个函数,function(param),针对值数组“param”绘制。为了讨论,请param = np.arange(50)

标签: python arrays numpy plot


【解决方案1】:

如果您将函数更改为采用单个参数而不是数组怎么办?

那你就可以了

X = range(50)
Y = [function(x) for x in X]
pylab.plot(X, Y)

【讨论】:

  • For 循环往往会减慢 Python 的速度,以至于无法管理大型数据集,即使使用 NumPy 也是如此。
【解决方案2】:

我可以提供两种解决方案

  • 您可以(几乎)使用np.vectorize 将任何函数设为ufunc,它处理数字以及像np.sin 函数这样的np.arrays

    def my_func_1(param):
        # using broadcasting, "np.sum(param * original_matrix for i in r)"
        new_matrix = np.sum(param * original_matrix[None,:,:], axis=0)
        # now perform r^T * C * r
        return np.dot( r.transpose(), np.dot( new_matrix,  r) )
    
    my_vec_func_1 = np.vectorize(my_func_1)
    

    请注意,np.vectorize 并没有真正矢量化您的代码......如果数组作为参数传递,我只是自动创建一个 forloop。使用它并没有在运行时获得收益...请参阅下面的时间安排。

  • 您可以定义一个真正的向量化函数,它(对于以下代码)采用一维列表或np.arrays 作为参数:

    def my_vec_func_2(param):
        param = np.asarray(param)
        new_matrix = np.sum(param[:,None,None,None] * original_matrix[None,None,:,:],axis=1)
        return np.dot(r, np.dot(new_matrix,r).transpose())
    

    真正的矢量化代码通常比forloops 快得多。为什么在这种情况下增益如此之小我无法解释这种情况......

时间

我使用以下代码测试运行时

import numpy as np
from numpy.random import randint

r = randint(10,size=(100))                       # an numpy ndarray of 100 values, (100,)
original_matrix =  randint(30,size=(100,100)) 

timeit my_vec_func_1(np.arange(10000))
1 loops, best of 3: 508 ms per loop

timeit my_vec_func_2(np.arange(10000))
1 loops, best of 3: 488 ms per loop

timeit [my_func_1(x) for x in np.arange(10000)]
1 loops, best of 3: 505 ms per loop

【讨论】:

    猜你喜欢
    • 2019-02-16
    • 2015-02-12
    • 2020-10-01
    • 2015-02-22
    • 2023-04-01
    • 1970-01-01
    • 2019-03-18
    • 2017-03-18
    • 2021-02-17
    相关资源
    最近更新 更多