2017-04-22 10 views
1

말, 나는 다음과 같은 두 가지 SparseTensor의 경우 :TensorFlow에서 SparseTensor의 행을 선택하려면 어떻게해야합니까?

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

[[1.0, 0, 0, 0], 
[1.0, 0, 0, 0], 
[0.3, 0.7, 0, 0]] 

을하고 내가 그들을 밖으로 처음 두 행을 추출합니다. 난 tf.nn.embedding_lookup_sparse 결과를 전달할 수 있도록 SparseTensor s로 0이 아닌 항목의 인덱스와 값이 필요합니다. 어떻게해야합니까?

내 응용 프로그램 : 나는 TensorFlow에서 아주 직설적 인 단어 삽입을 원합니다. 하지만 이제는 희소물을 사용하고 싶습니다. 즉 일반적인 단어의 경우에는 고유 한 포함이 있습니다. 희소 한 낱말을 위해, 그들의 embeddings는 일반적인 낱말의 embeddings의 희소 한 선형 조합이다. 그래서 스파 스 삽입이 어떻게 구성되어 있는지 알려면 두 권의 요리 책이 필요합니다. 앞의 예에서 요리 책은 다음과 같이 말합니다. 첫 번째 단어의 경우, 그것의 삽입은 weight 1.0으로 자체 embedding으로 구성됩니다. 두 번째 단어는 상황이 비슷합니다. 마지막 단어는 다음과 같이 말합니다 :이 단어의 삽입은 처음 두 단어의 삽입의 선형 결합이며, 해당 가중치는 각각 0.3과 0.7입니다. 행을 추출한 다음 색인 및 가중치를 tf.nn.embedding_lookup_sparse으로 입력하여 최종 포함을 가져와야합니다. TensorFlow에서 어떻게 할 수 있습니까?

또는 TensorFlow에서 내 데이터를 사전 처리하고 요리 책을 처리해야합니다. 우리는 이것의 효율적인 구현이있는 경우

나는 잘 모르겠지만, 여기되지 않습니다 : 내가 여기에이 지역에 대해 자세히 알고, 여기에 엔지니어 중 하나를 체크

답변

1

그가 전달 무엇 dynamic_partition을 사용하고 op를 수집하는 최적의 구현.

엔지니어는 그 지적에 대해 여러 너무 행, 덕분에 도움이 예에 전송 : 업데이트

def sparse_slice(indices, values, needed_row_ids): 
    num_rows = tf.shape(indices)[0] 
    partitions = tf.cast(tf.equal(indices[:,0], needed_row_ids), tf.int32) 
    rows_to_gather = tf.dynamic_partition(tf.range(num_rows), partitions, 2)[1] 
    slice_indices = tf.gather(indices, rows_to_gather) 
    slice_values = tf.gather(values, rows_to_gather) 
    return slice_indices, slice_values 

with tf.Session().as_default(): 
    indices = tf.constant([[0,0], [1, 0], [2, 0], [2, 1]]) 
    values = tf.constant([1.0, 1.0, 0.3, 0.7], dtype=tf.float32) 
    needed_row_ids = tf.constant([1]) 
    slice_indices, slice_values = sparse_slice(indices, values, needed_row_ids) 
    print(slice_indices.eval(), slice_values.eval()) 

!

def sparse_slice(indices, values, needed_row_ids): 
    needed_row_ids = tf.reshape(needed_row_ids, [1, -1]) 
    num_rows = tf.shape(indices)[0] 
    partitions = tf.cast(tf.reduce_any(tf.equal(tf.reshape(indices[:,0], [-1, 1]), needed_row_ids), 1), tf.int32) 
    rows_to_gather = tf.dynamic_partition(tf.range(num_rows), partitions, 2)[1] 
    slice_indices = tf.gather(indices, rows_to_gather) 
    slice_values = tf.gather(values, rows_to_gather) 
    return slice_indices, slice_values 

with tf.Session().as_default(): 
    indices = tf.constant([[0,0], [1, 0], [2, 0], [2, 1]]) 
    values = tf.constant([1.0, 1.0, 0.3, 0.7], dtype=tf.float32) 
    needed_row_ids = tf.constant([0, 2]) 
+0

아, 알 수 있습니다. 그것은 dynamic_partition과 collect의 똑똑한 조합을 사용합니다. 아이디어는 SparseTensor를 형성하지 마십시오. 대신에,'dynamic_partition'과'gather'를 밀도가 높은'indices'와'values' 배열에 대해서 수행하십시오. – soloice

+0

많은 도움이됩니다. 그건 그렇고,이 코드는 단일 행에 대해서만 작동하는 것 같습니다. 어떻게 중복 된 행을 추출 할 수 있습니까? 말하자면, 1, 3, 3 행을 추출하고 싶습니까? 즉, 입력 된 문장에 여러 단어가 여러 번 나타날 수 있습니다. 나는'sparse_slice'를 여러 번 실행할 수 있고'tf.concat'을 사용하여 연결하는 것이 좋지만 더 좋은 방법이 있습니까? – soloice

+0

마침내 얻었습니다. 마찬가지로 조밀 한'indices'와'values'에 파티션을 수행 할 수 있습니다. 나는 내일 tf.gather를 많이 사용하는 해결책을 게시 할 것이다. – soloice

0

대략에 직접 tf.SparseTensor 조밀 indicesweights 배열 대신 DO에서 적절한 값을 수집 한 필요성을 말하기. 아래에 코드를 게시 할 것입니다. 인덱스가 동일한 행을 설명한다고 가정하면 시작 인덱스와 끝 인덱스를 사용하여 식별 할 수 있습니다.

# Suppose we have the following cookbook: 
# The first 3 rows are one-hot basis and these words have their own embeddings 
# The last 2 rows corresponds to rare words and their embeddings are linear combinations of common words. 
# Thus basis coefficients and weights are: 

# indices: 
#[[0, x, x] 
# [1, x, x] 
# [2, x, x] 
# [1, 2, x] 
# [0, 2, x]] 

# weights: 
#[[1.0, x, x] 
# [1.0, x, x] 
# [1.0, x, x] 
# [0.1, 0.9, x] 
# [0.7, 0.3, x]] 

# embedding basis (for word 0, word 1 and word 2 respectively): 
#[[1, 2, 3, 4, 5] 
# [6, 7, 8, 9, 10] 
# [11, 12, 13, 14, 15]] 

# Which implies, the embeddings for word 3 and word 4 are: 
# [6, 7, 8, 9, 10] * 0.1 + [11, 12, 13, 14, 15] * 0.9 = [ 10.5, 11.5, 12.5, 13.5, 14.5] 
# [1, 2, 3, 4, 5] * 0.7 + [11, 12, 13, 14, 15] * 0.3 = [ 4., 5., 6., 7., 8.] 


X = tf.constant(np.array(list(range(1, 16))).reshape((3, 5)), dtype=tf.float32) 

# For word i, its index range in sp_weights_vals and sp_ids_val is 
# [start_index_in_sp_indices[i], end_index_in_sp_indices[i]) 
# index_range_in_sp_indices[i] is the index range of word i 
# e.g.: For word 3, the relevant params are the 3rd and 4th ones (i.e.: interval [3, 5], including 3 and excluding 5) 
# Equivalent to [[0, 0], [1, 0], [2, 0], [3, 0], [3, 1], [4, 0], [4, 1]] 
start_index_in_sp_indices = [0, 1, 2, 3, 5] 
end_index_in_sp_indices = [1, 2, 3, 5, 7] 

word_ids_in_sentence = tf.placeholder(shape=[6], dtype=tf.int32) 
sp_shape = tf.placeholder(tf.int64) # mini-batch size * sparsity 


# Gather proper indices 
start_indices_in_sentence = tf.gather(start_index_in_sp_indices, word_ids_in_sentence) 
end_indices_in_sentence = tf.gather(end_index_in_sp_indices, word_ids_in_sentence) 
print(sess.run(start_indices_in_sentence, feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 
print(sess.run(end_indices_in_sentence, feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 


# Not supported due to complicated shape 
# elems = (start_indices_in_sentence, end_indices_in_sentence) 
# word_embedding_indices = tf.foldl(lambda a, x: tf.concat(a, tf.range(x[0], x[1])), elems, initializer=[]) 

print("*" * 50) 
indices_to_gather = [] 
sp_indices_to_feed = [] 
for i in range(6): 
    indices_to_gather.append(tf.range(start_indices_in_sentence[i], end_indices_in_sentence[i])) 
    sp_indices_to_feed.append(tf.stack(tf.map_fn(lambda x: (i, x), 
               tf.range(end_indices_in_sentence[i] - start_indices_in_sentence[i]), 
               dtype=(tf.int32, tf.int32)), 
            axis=1)) 

print("check indices to gather") 
print(sess.run(indices_to_gather, feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 
indices_to_gather = tf.concat(indices_to_gather, axis=0) 
print(sess.run(indices_to_gather, feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 

print("check indices to feed") 
print(sess.run(sp_indices_to_feed, feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 
sp_indices_to_feed = tf.to_int64(tf.concat(sp_indices_to_feed, axis=0)) 
print(sess.run(sp_indices_to_feed, feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 

# sp_indices_table = [[0, 0], [1, 0], [2, 0], [3, 0], [3, 1], [4, 0], [4, 1]] 
sp_ids_val_table = tf.constant(np.array([0, 1, 2, 1, 2, 0, 2], dtype=np.int32)) 
sp_weights_val_table = tf.constant(np.array([1.0, 1.0, 1.0, 0.1, 0.9, 0.7, 0.3], dtype=np.float32)) 


sp_ids_val_to_feed = tf.gather(sp_ids_val_table, indices_to_gather) 
sp_weights_val_to_feed = tf.gather(sp_weights_val_table, indices_to_gather) 



print(sess.run([sp_indices_to_feed], feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 
print(sess.run([sp_ids_val_to_feed], feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 
print(sess.run([sp_weights_val_to_feed], feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 


sp_ids = tf.SparseTensor(sp_indices_to_feed, sp_ids_val_to_feed, sp_shape) 
sp_weights = tf.SparseTensor(sp_indices_to_feed, sp_weights_val_to_feed, sp_shape) 
y = tf.nn.embedding_lookup_sparse(X, sp_ids, sp_weights, combiner="sum") 


word_embedding_indices = tf.concat(indices_to_gather, axis=0) 
print(sess.run(word_embedding_indices, feed_dict={word_ids_in_sentence: [1, 3, 2, 1, 4, 3]})) 
print("*" * 50) 

word_embeddings = sess.run(y, feed_dict={ 
    word_ids_in_sentence: [1, 3, 2, 1, 4, 3], 
    sp_shape: [6, 3]}) 
print(word_embeddings)