>source
numpy에서 다음 슬라이싱과 같은 텐서의 슬라이싱을하고 싶습니다. 어떻게해야합니까?

# numpy array
a = np.reshape(np.arange(60), (3,2,2,5))
idx = np.array([0, 1, 0])
N = np.shape(a)[0]
mask = a[np.arange(N),:,:,idx]

# I have tried several solutions, but only the following success.
# tensors
import tensorflow as tf
import numpy as np

a = tf.cast(tf.constant(np.reshape(np.arange(60), (3,2,2,5))), tf.int32)
idx2 = tf.constant([0, 1, 0])
fn = lambda i: a[i][:,:,idx2[i]]
idx = tf.range(tf.shape(a)[0])
masks = tf.map_fn(fn, idx)
with tf.Session() as sess:
    print(sess.run(a))
    print(sess.run(tf.shape(masks)))
    print(sess.run(masks))

이를 달성하는 간단한 방법이 있습니까?

tf.gather 함수를 사용할 수 있습니까  또는 tf.gather_nd  이것을 달성하기 위해? 많은 감사합니다!


  • 답변 # 1

    1. 다른 방법

    가장 좋은 방법인지 확실하지 않지만 더 빠릅니다. tf.boolean_mask 를 사용할 수 있습니다   tf.map_fn 대신 .

    import tensorflow as tf
    import numpy as np
    a = tf.cast(tf.constant(np.reshape(np.arange(60), (3,2,2,5))), tf.int32)
    idx2 = tf.constant([0, 1, 0])
    fn = lambda i: a[i,:,:][:,:,idx2[i]]
    idx = tf.range(tf.shape(a)[0])
    masks = tf.map_fn(fn, idx)
    # new method
    idx = tf.one_hot(idx2,depth=a.shape[-1])
    masks2 = tf.boolean_mask(tf.transpose(a,[0,3,1,2]), idx)
    with tf.Session() as sess:
        print('tf.map_fn version:\n',sess.run(masks))
        print('tf.boolean_mask version:\n',sess.run(masks2))
    # print
    tf.map_fn version:
     [[[ 0  5]
      [10 15]]
     [[21 26]
      [31 36]]
     [[40 45]
      [50 55]]]
    tf.boolean_mask version:
     [[[ 0  5]
      [10 15]]
     [[21 26]
      [31 36]]
     [[40 45]
      [50 55]]]
    
    

    2. 성능 비교

    벡터화 방법 1000 회 반복시 0.07s 소요  그리고 tf.map_fn 방법 1000 반복에는 0.85s 가 필요합니다  내 8GB GPU 메모리에. 벡터화 방법은 tf.map_fn() 보다 훨씬 빠릅니다. .

    import datetime
    ...
    with tf.Session() as sess:
        start = datetime.datetime.now()
        for _ in range(1000):
            sess.run(masks)
        end = datetime.datetime.now()
        print('tf.map_fn version cost time(seconds) : %.2f' % ((end - start).total_seconds()))
        start = datetime.datetime.now()
        for _ in range(1000):
            sess.run(masks2)
        end = datetime.datetime.now()
        print('tf.boolean_mask version cost time(seconds) : %.2f' % ((end - start).total_seconds()))
    # print
    tf.map_fn version cost time(seconds) : 0.85
    tf.boolean_mask version cost time(seconds) : 0.07
    
    
    나는 a 의 모양으로 성능 차이가 더 분명해질 것이라고 믿습니다.  

  • 답변 # 2

    다른 방법 사용 tf.gather_nd :

    import tensorflow as tf
    import numpy as np
    
    a = tf.cast(tf.constant(np.reshape(np.arange(60), (3,2,2,5))), tf.int32)
    idx = tf.range(tf.shape(a)[0])
    idx2 = tf.constant([0,1,0])
    indices = tf.stack([idx, idx2], axis=1)
    a = tf.transpose(a, [0,3,1,2])
    masks = tf.gather_nd(a, indices)
    with tf.Session() as sess:
        print(sess.run(a))
        print(sess.run(tf.shape(masks)))
        print(sess.run(masks))
    
    

관련 자료

  • 이전 python - 별도의 열에 정렬되지 않은 중복 제거
  • 다음 php - 소스 페이지에서 mp4 URL을 얻는 방법?