Python 使用numexpr的欧几里德范数
我需要用numexpr重写这段代码,它在计算矩阵数据[rows x cols]和向量[1 x cols]的欧几里德范数矩阵Python 使用numexpr的欧几里德范数,python,pytables,euclidean-distance,numexpr,Python,Pytables,Euclidean Distance,Numexpr,我需要用numexpr重写这段代码,它在计算矩阵数据[rows x cols]和向量[1 x cols]的欧几里德范数矩阵 d = ((data-vec)**2).sum(axis=1) 怎样才能做到呢?也许还有另一种更快的方法 问题是我使用hdf5,并从中读取数据矩阵。 例如,此代码给出错误:对象未对齐 #naive numpy solution, can be parallel? def test_bruteforce_knn(): h5f = tables.open_file(f
d = ((data-vec)**2).sum(axis=1)
怎样才能做到呢?也许还有另一种更快的方法
问题是我使用hdf5,并从中读取数据矩阵。
例如,此代码给出错误:对象未对齐
#naive numpy solution, can be parallel?
def test_bruteforce_knn():
h5f = tables.open_file(fileName)
t0= time.time()
d = np.empty((rows*batches,))
for i in range(batches):
d[i*rows:(i+1)*rows] = ((h5f.root.carray[i*rows:(i+1)*rows]-vec)**2).sum(axis=1)
print (time.time()-t0)
ndx = d.argsort()
print ndx[:k]
h5f.close()
#using some tricks (don't work error: objects are not aligned )
def test_bruteforce_knn():
h5f = tables.open_file(fileName)
t0= time.time()
d = np.empty((rows*batches,))
for i in range(batches):
d[i*rows:(i+1)*rows] = (np.einsum('ij,ij->i', h5f.root.carray[i*rows:(i+1)*rows],
h5f.root.carray[i*rows:(i+1)*rows])
+ np.dot(vec, vec)
-2 * np.dot(h5f.root.carray[i*rows:(i+1)*rows], vec))
print (time.time()-t0)
ndx = d.argsort()
print ndx[:k]
h5f.close()
使用numexpr:似乎numexpr不理解h5f.root.carray[i*行:(i+1)*行]它必须重新分配吗
import numexpr as ne
def test_bruteforce_knn():
h5f = tables.open_file(fileName)
t0= time.time()
d = np.empty((rows*batches,))
for i in range(batches):
ne.evaluate("sum((h5f.root.carray[i*rows:(i+1)*rows] - vec) ** 2, axis=1)")
print (time.time()-t0)
ndx = d.argsort()
print ndx[:k]
h5f.close()
有一种潜在的快速方法(对于非常大的阵列)仅使用NumPy,这在scikit learn中使用:
def squared_row_norms(X):
# From http://stackoverflow.com/q/19094441/166749
return np.einsum('ij,ij->i', X, X)
def squared_euclidean_distances(data, vec):
data2 = squared_row_norms(data)
vec2 = squared_row_norms(vec)
d = np.dot(data, vec.T).ravel()
d *= -2
d += data2
d += vec2
return d
这是基于(x-y)²=x²+y²-2xy的事实,即使对于向量也是如此
测试:
简介:
>>> data = np.random.randn(1000, 40)
>>> vec = np.random.randn(1, 40)
>>> %timeit ((data - vec)**2).sum(axis=1)
10000 loops, best of 3: 114 us per loop
>>> %timeit squared_euclidean_distances(data, vec)
10000 loops, best of 3: 52.5 us per loop
使用numexpr也是可能的,但它似乎并没有为1000点提供任何加速(在10000点时,也没有更好):
有一种潜在的快速方法(对于非常大的阵列)仅使用NumPy,这在scikit learn中使用:
def squared_row_norms(X):
# From http://stackoverflow.com/q/19094441/166749
return np.einsum('ij,ij->i', X, X)
def squared_euclidean_distances(data, vec):
data2 = squared_row_norms(data)
vec2 = squared_row_norms(vec)
d = np.dot(data, vec.T).ravel()
d *= -2
d += data2
d += vec2
return d
这是基于(x-y)²=x²+y²-2xy的事实,即使对于向量也是如此
测试:
简介:
>>> data = np.random.randn(1000, 40)
>>> vec = np.random.randn(1, 40)
>>> %timeit ((data - vec)**2).sum(axis=1)
10000 loops, best of 3: 114 us per loop
>>> %timeit squared_euclidean_distances(data, vec)
10000 loops, best of 3: 52.5 us per loop
使用numexpr也是可能的,但它似乎并没有为1000点提供任何加速(在10000点时,也没有更好):
谢谢,平方欧几里得距离确实工作得更快,请看我的更新,无法管理numexpr版本。谢谢,平方欧几里得距离确实工作得更快,请看我的更新,无法管理numexpr版本。