Numpy数组与向量参数的广播用法

2 投票
2 回答
614 浏览
提问于 2025-04-16 06:06

在numpy中,能不能用向量作为参数来进行数组广播?

举个例子,我知道我可以这样做:

def bernoulli_fraction_to_logodds(fraction):
    if fraction == 1.0:
        return inf
    return log(fraction / (1 - fraction))
bernoulli_fraction_to_logodds = numpy.frompyfunc(bernoulli_fraction_to_logodds, 1, 1)

这样就能对整个数组进行操作。如果我有一个函数,它接收一个包含两个元素的向量,并返回一个同样包含两个元素的向量。我能不能把一个包含多个两个元素向量的数组传给它?比如:

def beta_ml_fraction(beta):
    a = beta[0]
    b = beta[1]
    return a / (a + b)
beta_ml_fraction = numpy.frompyfunc(beta_ml_fraction, 1, 1)

可惜的是,这样做是不行的。有没有类似于from_py_func的函数可以用呢?当向量是两个元素的时候,我可以找到解决办法,但如果是n个元素的向量呢?

因此,输入(2,3)应该返回0.4,而输入[[2,3], [3,3]]应该返回[0.4, 0.5]

2 个回答

4

我觉得 frompyfunc 可能做不到这个,不过我也可能错了。

关于 np.vectorize,有位叫 A. M. Archibald 的人写道:

实际上,任何通过 Python 代码来“组合两个数”的操作都会很慢。Python 循环慢并不是因为它的循环结构慢,而是因为执行 Python 代码本身就慢。所以说,vectorize 有点像是个小把戏——它实际上并没有运行得更快,但用起来很方便。

所以 np.frompyfunc(和 np.vectorize)其实只是语法上的一种简化——它们并没有让 Python 函数运行得更快。在意识到这一点后,我对 frompyfunc 的兴趣几乎降到了零。

Python 的循环并没有什么难懂的地方,所以要么直接使用循环,要么重写函数,真正利用 numpy(通过编写真正的向量化公式)。

import numpy as np

def beta_ml_fraction(beta):    
    a = beta[:,0]
    b = beta[:,1]
    return a / (a + b)


arr=np.array([(2,3)],dtype=np.float)
print(beta_ml_fraction(arr))
# [ 0.4]

arr=np.array([(2,3),(3,3)],dtype=np.float)
print(beta_ml_fraction(arr))
# [ 0.4  0.5]
1

在处理二维向量数组时,我喜欢把x和y的部分放在第一个索引位置。为此,我经常使用transpose()这个函数。

def beta_ml_fraction(beta):
        a = beta[0]
        b = beta[1]
   return a / (a + b)

arr=np.array([(2,3),(3,3)],dtype=np.float) 
print(beta_ml_fraction(arr.transpose()))
# [ 0.4  0.5]

这种方法的好处是,处理多维的二维向量数组会变得更简单。

x = np.arange(18,dtype=np.float).reshape(2,3,3)
print(x)
#array([[[  0.,   1.,   2.],
#        [  3.,   4.,   5.],
#        [  6.,   7.,   8.]],
#
#       [[  9.,  10.,  11.],
#        [ 12.,  13.,  14.],
#        [ 15.,  16.,  17.]]])
print(beta_ml_fraction(x))
#array([[ 0.        ,  0.09090909,  0.15384615],
#       [ 0.2       ,  0.23529412,  0.26315789],
#       [ 0.28571429,  0.30434783,  0.32      ]])

撰写回答