One-hot向量的3维组合

3 Dimensional Combination of One-hot Vectors

我需要在 python 中创建所有 3x1 单热向量对的 3 维列表,但我在生成数组时遇到了问题。我正在尝试使用 np.arange 来做到这一点,但我还没有完全做到这一点。比如我的one-hot vector是:A=[1,0,0] B=[0,1,0] and C=[0,0,1]。我需要的输出是三维数组 [[A,A],[A,B],[A,C],[B,A],[B,B],[B,C],[C,A],[C,B],[C,C]] 也就是一个 9x2x3 的数组,由 one-hot 向量对的所有组合组成。

您可以使用 itertools.product:

import itertools as it
combos = [c for c in it.product([A, B, C], repeat=2)]
# combos = [([1, 0, 0], [1, 0, 0]),
#           ([1, 0, 0], [0, 1, 0]),
#           ([1, 0, 0], [0, 0, 1]),
#           ([0, 1, 0], [1, 0, 0]),
#           ([0, 1, 0], [0, 1, 0]),
#           ([0, 1, 0], [0, 0, 1]),
#           ([0, 0, 1], [1, 0, 0]),
#           ([0, 0, 1], [0, 1, 0]),
#           ([0, 0, 1], [0, 0, 1])]

由于我不熟悉 numpy,这里有一个 one/two 线性解决方案。

为了简单起见,我们将采用 A='a'B='b'C='c'

鉴于您所有的 'hot vector'(不确定它们是什么,但无论如何)都存储在一个向量中:

>>> options = [A,B,C]
>>> result = [x,y for x in options for y in options]
>>> print(result)
[['a', 'a'], ['b', 'a'], ['c', 'a'],
 ['a', 'b'], ['b', 'b'], ['c', 'b'],
 ['a', 'c'], ['b', 'c'], ['c', 'c']]

注意打印结果中的换行符是为了使其适合屏幕大小

方法 #1

这是一种 NumPy 方法,用于创建这些成对索引组合的网格 -

# Create input array from those vectors
a = np.array([A,B,C])
n = len(a)

# Create grid of indices
r,c = np.mgrid[:n,:n]

# Index for final output
out = a[np.c_[c.ravel().T,r.ravel()]]

样本输入、输出-

In [365]: A = [1,0,0]
     ...: B = [0,1,0]
     ...: C = [0,0,1]

In [367]: out
Out[367]: 
array([[[1, 0, 0],
        [1, 0, 0]],

       [[0, 1, 0],
        [1, 0, 0]],

       [[0, 0, 1],
        [1, 0, 0]],

       [[1, 0, 0],
        [0, 1, 0]],

       [[0, 1, 0],
        [0, 1, 0]],

       [[0, 0, 1],
        [0, 1, 0]],

       [[1, 0, 0],
        [0, 0, 1]],

       [[0, 1, 0],
        [0, 0, 1]],

       [[0, 0, 1],
        [0, 0, 1]]])

方法 #2(性能)

我们可以利用输入是单热向量这一事实来提高性能,特别是通过初始化输出数组并将其分配给其中的大量长度更长的向量。使用 one-hotness 的技巧是使用 argmax 为每个向量获取那些单值唯一索引。我们将使用这些索引仅在那些特定位置分配到输出中。实施将是 -

def multidim_hotvectors(a): # a is input list of vectors = [A,B,C]
    n = len(a)
    idx = np.array([np.argmax(i) for i in a])
    putval = (idx[:,None] == np.arange(n)).astype(int)
    out = np.zeros((n,n,2,n),dtype=int)
    out[:,:,0,:] = putval[:,None,:]
    out[:,:,1,:] = putval
    out.shape = (n**2,2,-1)
    return out

运行时测试

a = [A,B,C]-

的其他方法
# @Engineero's soln
np.array([c for c in itertools.product(a, repeat=2)])

# @B. M.'s soln
np.array(list(itertools.product(a,a)))

设置单热向量输入列表的函数-

def create_input_list_vectors(L):
    d = (np.random.choice(L,L,replace=0)[:,None] == range(L)).astype(int)
    return list(map(list,d))

计时 -

In [359]: a = create_input_list_vectors(L=5)

In [360]: %timeit np.array([c for c in itertools.product(a, repeat=2)])
     ...: %timeit np.array(list(itertools.product(a,a)))
     ...: %timeit multidim_hotvectors(a)
10000 loops, best of 3: 29.4 µs per loop
10000 loops, best of 3: 27.8 µs per loop
10000 loops, best of 3: 30.5 µs per loop

In [361]: a = create_input_list_vectors(L=20)

In [362]: %timeit np.array([c for c in itertools.product(a, repeat=2)])
     ...: %timeit np.array(list(itertools.product(a,a)))
     ...: %timeit multidim_hotvectors(a)
1000 loops, best of 3: 966 µs per loop
1000 loops, best of 3: 967 µs per loop
10000 loops, best of 3: 125 µs per loop

In [363]: a = create_input_list_vectors(L=100)

In [364]: %timeit np.array([c for c in itertools.product(a, repeat=2)])
     ...: %timeit np.array(list(itertools.product(a,a)))
     ...: %timeit multidim_hotvectors(a)
10 loops, best of 3: 98.6 ms per loop
10 loops, best of 3: 98.1 ms per loop
100 loops, best of 3: 3.94 ms per loop

你可以用 itertools 来做:

A,B,C=np.eye(3,dtype=int)
import itertools 
l=list(itertools.product((A,B,C),(A,B,C)))
a923=np.array(l)

或直接在 numpy 中:

points=np.array([
[1,0,0],
[0,1,0],
[0,0,1]])
n,dim=points.shape
indices=np.indices((n,n))

# indice.T :
# array([[[0, 0],
#         [1, 0],
#         [2, 0]],
# 
#        [[0, 1],
#         [1, 1],
#         [2, 1]],
# 
#        [[0, 2],
#         [1, 2],
#         [2, 2]]])

res = points[indices.T].reshape(n*n,2,dim)