Подход № 1
Мы могли бы использовать np.triu_indices
, чтобы получить эти попарные индексы перестановки, а затем просто выполнить поэлементное умножение массивов с индексированными строками-
r,c = np.triu_indices(d,1)
res = X[r]*X[c]
Подход № 2
Для эффективности памяти и, следовательно, производительности, особенно для больших массивов, нам лучше нарезать входной массив и запустить один цикл скаждая итерация работает с порциями данных, например:
n = d-1
idx = np.concatenate(( [0], np.arange(n,0,-1).cumsum() ))
start, stop = idx[:-1], idx[1:]
L = n*(n+1)//2
res_out = np.empty((L,X.shape[1]), dtype=X.dtype)
for i,(s0,s1) in enumerate(zip(start,stop)):
res_out[s0:s1] = X[i] * X[i+1:]
Чтобы получить Z
напрямую и, таким образом, избежать всех этих объединений, мы могли бы изменить ранее опубликованный подход, например так: *
n = d-1
N = len(X)
idx = 2*N + np.concatenate(( [0], np.arange(n,0,-1).cumsum() ))
start, stop = idx[:-1], idx[1:]
L = n*(n+1)//2
Z_out = np.empty((2*N + L,X.shape[1]), dtype=X.dtype)
Z_out[:N] = X
Z_out[N:2*N] = X**2
for i,(s0,s1) in enumerate(zip(start,stop)):
Z_out[s0:s1] = X[i] * X[i+1:]