我有一个名为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'
也就是说,它不是单独传递矩阵的每一行。相反,它传递的是矩阵的每个条目(不是我想要的)。
如何改变这一点以获得所需的行为?
答案 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,均值和先验将不会被向量化。