使用vectorize将函数应用于Numpy 2d数组

时间:2016-03-07 01:06:22

标签: numpy vectorization

我有一个名为X_valid的1000x784数据矩阵(10000个示例和784个特征),我想将以下函数应用于此矩阵中的每一行并获得数值结果:

def predict_prob(x_valid, cov, mean, prior):
    return -0.5 * (x_valid.T.dot(np.linalg.inv(cov)).dot(x_valid) + mean.T.dot(
    np.linalg.inv(cov)).dot(mean) + np.linalg.slogdet(cov)[1]) + np.log(
    prior)

x_valid只是一行数据)。我正在使用numpy的vectorize来执行以下代码:

v_predict_prob = np.vectorize(predict_prob)
scores = v_predict_prob(X_valid, covariance[num], means[num], priors[num])

covariance[num]means[num]priors[num]只是常量。)

但是,运行此命令时出现以下错误:

File "problem_5.py", line 48, in predict_prob
return -0.5 * (x_valid.T.dot(np.linalg.inv(cov)).dot(x_valid) + mean.T.dot(np.linalg.inv(cov)).dot(mean) + np.linalg.slogdet(cov)[1]) + np.log(prior)
AttributeError: 'numpy.float64' object has no attribute 'dot'

也就是说,它不是单独传递矩阵的每一行。相反,它传递的是矩阵的每个条目(不是我想要的)。

如何改变这一点以获得所需的行为?

3 个答案:

答案 0 :(得分:0)

我建议只使用for循环:

def v_predict_prob(X_valid, c, m, p):
    out = []
    for row in X_valid:
        out.append(predict_prob(row, c, m, p))
    return np.array(out)

引擎盖np.vectorize正在做同样的事情:http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.vectorize.html

答案 1 :(得分:0)

vectorize不是迭代的一般替代品,也不是声称更快。它主要简化了对numpy广播功能的访问。通常,您向量化的函数将采用标量输入,而不是行或1d数组。

我认为有一种方法可以配置vectorize将数组传递给您的函数而不是项目。

您要将x_valid描述为要逐行评估的2d。其他术语为“常数”和#39;您使用[num]选择的。这些常数是什么形状的?

你的功能将很多这些术语视为二维数组:

x_valid.T.dot(np.linalg.inv(cov)).dot(x_valid) + 
mean.T.dot(np.linalg.inv(cov)).dot(mean) + 
np.linalg.slogdet(cov)[1]) + np.log(prior)
仅当x_valid.T为2d时,

x_valid才有意义。如果是1d,则转置注意到。

np.linalg.inv(cov)仅在cov为2d时才有意义。

mean.T.dot...假设mean为2d。

np.linalg.slogdet(cov)[1]假设np.linalg.slogdet(cov)有2个或更多元素(或行)。

您需要告诉我们,在跳转到迭代或“矢量化”之前,该函数可以与一些真实数组一起使用。

答案 2 :(得分:0)

我知道这个问题有些过时,但是我想我会为2020年提供一个答案。 自numpy 1.12发行以来,存在一个新的可选参数“ signature”,该参数在大多数情况下应允许2D数组功能。另外,您将要“排除”这些常量,因为它们不会被向量化。

您需要更改的只是:

v_predict_prob = np.vectorize(predict_prob, exclude=['cov', 'mean', 'prior'], signature='(n)->()')

这表示该函数应该期望一个n-dim数组并输出一个标量,并且cov,均值和先验将不会被向量化。