중간 크기가 충분하고 항목이 균일하게 분포되어있는 경우 조금 저장하는 알고리즘입니다. 가장 작은 합계는 일반적으로 두 가지 작은 용어에서 나올 것이라는 사실을 이용합니다.
import numpy as np
def min_plus_product(A,B):
B = np.transpose(B)
Y = np.zeros((len(B),len(A)))
for i in range(len(B)):
Y[i] = (A + B[i]).min(1)
return np.transpose(Y)
def min_plus_product_opt(A,B, chop=None):
if chop is None:
# not sure this is optimal
chop = int(np.ceil(np.sqrt(A.shape[1])))
B = np.transpose(B)
Amin = A.min(1)
Y = np.zeros((len(B),len(A)))
for i in range(len(B)):
o = np.argsort(B[i])
Y[i] = (A[:, o[:chop]] + B[i, o[:chop]]).min(1)
if chop < len(o):
idx = np.where(Amin + B[i, o[chop]] < Y[i])[0]
for j in range(chop, len(o), chop):
if len(idx) == 0:
break
x, y = np.ix_(idx, o[j : j + chop])
slmin = (A[x, y] + B[i, o[j : j + chop]]).min(1)
slmin = np.minimum(Y[i, idx], slmin)
Y[i, idx] = slmin
nidx = np.where(Amin[idx] + B[i, o[j + chop]] < Y[i, idx])[0]
idx = idx[nidx]
return np.transpose(Y)
A = np.random.random(size=(1000,1000))
B = np.random.random(size=(1000,2000))
print(np.allclose(min_plus_product(A,B), min_plus_product_opt(A,B)))
import time
t = time.time();min_plus_product(A,B);print('naive {}sec'.format(time.time()-t))
t = time.time();min_plus_product_opt(A,B);print('opt {}sec'.format(time.time()-t))
샘플 출력 :
True
naive 7.794037580490112sec
opt 1.65810227394104sec
입력 한도는 얼마나됩니까? 'min_plus_product'의 속도와'dot '을 사용하는 일반 매트릭스 곱셈의 속도는 어떻게 다릅니 까? – user2357112
* "... 큰 행렬에 대해서는 속도가 느립니다"* @ user2357112와 같은 질문 : 행렬의 일반적인 크기는 얼마입니까? –
나는 A 10000 by 100과 B 100 by 20000으로 테스트를했고, 광산은 135s, np.dot는 1.95s를 얻었다. 내 행렬은 때로는 이것보다 더 클 수 있습니다. – Rael