我想解决下一个问题:我有一个值矩阵,每个值代表一个电影的评级,我有下一个函数返回一个值(距离):
def getDistanceBetween2Movies(movie1, movie2):
return np.linalg.norm(X[movie1]-X[movie2])
这个功能运行正常,所以我想得到一个列表,其中包含从一个指定电影到其他电影的所有距离,我就是这样做的,并且它可以正常工作
#Vector of indices of movies without our new user's one
moviesInd = np.arange(n_movies)
myMovie = 1
#Vectorizing our function
vfunc = np.vectorize(getDistanceBetween2Movies)
arrayDistances = vfunc(myMovie,moviesInd)
closestValue = np.min(arrayDistances)
closestIndex = np.argmin(arrayDistances)
print("Movie: " + str(closestIndex))
print("Distance: " + str(closestValue))
所以现在的问题是如何获得一个矩阵,其中包含从每部电影到其他电影的所有距离,我正在尝试再次对此函数进行矢量化,以便将相同的操作移动n_movies次并将其收集到列表或数组中
def getVectorDistances(i):
vector = np.arange(n_movies)
vFunc = np.vectorize(getDistanceBetween2Movies)
return vFunc(i, vector)
moviesInd = np.arange(n_movies)
vFunc = np.vectorize(getVectorDistances)
print(vFunc(moviesInd))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-34-01b95a280035> in <module>()
6 moviesInd = np.arange(n_movies)
7 vFunc = np.vectorize(getVectorDistances)
----> 8 print(vFunc(moviesInd))
9
10
c:\users\regis\appdata\local\programs\python\python36-32\lib\site-packages\numpy\lib\function_base.py in __call__(self, *args, **kwargs)
2737 vargs.extend([kwargs[_n] for _n in names])
2738
-> 2739 return self._vectorize_call(func=func, args=vargs)
2740
2741 def _get_ufunc_and_otypes(self, func, args):
c:\users\regis\appdata\local\programs\python\python36-32\lib\site-packages\numpy\lib\function_base.py in _vectorize_call(self, func, args)
2816
2817 if ufunc.nout == 1:
-> 2818 res = array(outputs, copy=False, subok=True, dtype=otypes[0])
2819 else:
2820 res = tuple([array(x, copy=False, subok=True, dtype=t)
ValueError: setting an array element with a sequence.
这就是我所做的,但它不起作用而且我被困住了。
提前谢谢
答案 0 :(得分:1)
由于你正在计算矩阵行之间的差异,我们试图对下面的双循环
进行矢量化a = numpy.arange(25).reshape(5, 5)
y = numpy.zeros(5, 5)
for i in range(len(a)):
for j in range(len(a)):
y[i, j] = numpy.linalg.norm(a[i, :] - a[j, :])
第一步是对行差异进行矢量化
a[i, :] - a[j, :] # difference between rows `i` and `j`
通过计算矩阵行的“外部差异”,产生3D张量:
x = a[:, None, :] - a[None, :, :]
x.shape # (5, 5, 5)
之后,行i
和j
的差异可以在张量的相应位置找到:
x[i, j, :] # difference between rows `i` and `j`
循环变为
for i in range(len(a)):
for j in range(len(a)):
y[i, j] = numpy.linalg.norm(x[i, j, :])
但是,由于我们现在只迭代x
的前两个轴,我们可以用向numpy.linalg.norm()
的矢量化调用替换双循环:
y = numpy.linalg.norm(x, axis=-1)
并在相应位置再次获取行i
和j
的距离
y[i, j] # distance between rows `i` and `j`
答案 1 :(得分:0)
我认为您可以使用原始vfunc
而无需嵌套它。 vectorize
期望一个接受标量的函数。它根据需要广播输入,以将标量集传递给函数。
标量输入正在弄乱第二级矢量化。
但是看看我们可以用第一个矢量化做什么:
In [389]: def getDistanceBetween2Movies(movie1, movie2):
...: return np.linalg.norm(X[movie1]-X[movie2])
...:
In [390]: X = np.arange(20)
你的2个标量的函数值:
In [391]: getDistanceBetween2Movies(1,2)
Out[391]: 1.0
In [393]: getDistanceBetween2Movies(1,10)
Out[393]: 9.0
In [394]: vfunc = np.vectorize(getDistanceBetween2Movies)
带有标量和数组的 vectorize
,有效[getDistanceBetween2Movies(i,j) for j in movielist]
:
In [395]: vfunc(1,np.arange(5))
Out[395]: array([ 1., 0., 1., 2., 3.])
但是我可以给它两个数组,一个是列向量。这最终会进行outer
评估:
In [396]: vfunc(np.arange(5)[:,None], np.arange(5))
Out[396]:
array([[ 0., 1., 2., 3., 4.],
[ 1., 0., 1., 2., 3.],
[ 2., 1., 0., 1., 2.],
[ 3., 2., 1., 0., 1.],
[ 4., 3., 2., 1., 0.]])
将该输出与这两个数组之间的简单广播差异进行比较:
In [397]: np.arange(5)[:,None]-np.arange(5)
Out[397]:
array([[ 0, -1, -2, -3, -4],
[ 1, 0, -1, -2, -3],
[ 2, 1, 0, -1, -2],
[ 3, 2, 1, 0, -1],
[ 4, 3, 2, 1, 0]])
vectorize
不会提高直接迭代的速度,但它可以更容易地评估复杂的标量函数,尤其是如果您需要相互广播的多个输入。
正如@Nils所示,您可能不需要使用vectorize
。