2017-04-22 5 views
1

言って、私は次のように2人の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]] 

を、私はそれらのうちの最初の2行を抽出したいです。私はtf.nn.embedding_lookup_sparseに結果を渡すことができるように、0以外の項目のインデックスと値をSparseTensorとする必要があります。これどうやってするの?

私のアプリケーションは: TensorFlowでは非常に単純ですが、単語埋め込みを使用したいと思います。しかし今、私は疎な埋め込みを使用したい、すなわち、一般的な言葉のために、彼らは独自の埋め込みを持っています。まれな単語の場合、それらの埋め込みは一般的な単語の埋め込みのまばらな線形結合です。 スパースな埋め込みがどのように構成されているかを示すために2つの料理本が必要です。前述の例では、料理本は次のように言っています。最初の単語については、埋め込みはウェイト1.0で埋め込まれています。事は第二の言葉に似ています。最後の単語については、この単語の埋め込みは最初の2つの単語の埋め込みの線形結合であり、対応する重みはそれぞれ0.3と0.7であることを示します。 私は行を抽出し、最後の埋め込みを得るためにインデックスと重みをtf.nn.embedding_lookup_sparseに送ります。 TensorFlowでどうすればいいですか?

または、私はそれを回避する必要があります。つまり、私のデータを前処理し、TensorFlowから料理本を扱いますか?

答えて

1

私はこの地域についての詳細を知っているし、ここで彼は渡されたものだ、ここでエンジニアの一人でチェックする:私たちは、このの効率的な実装を持っているかどうかわからないけど、ここではない

dynamic_partitionを使用してopsを収集する最適な実装。

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とgatherの巧妙な組み合わせを使用します。アイデアは、SparseTensorを形成しないでください。代わりに、密な 'indices'と' values'配列に対して 'dynamic_partition'と' gather'を実行してください。 – soloice

+0

これは多くの助けになります!ちなみに、このコードは1行でしか動作しないようです。どのように複数の行を抽出することができます(重複あり)?言って、私が第1、第3、第3行を抽出したいのですか?つまり、入力文では、いくつかの単語が複数回現れることがあります。私は 'sparse_slice'を何回か実行でき、' tf.concat'を使ってそれらを連結することができますが、もっと良い方法はありますか? – soloice

+0

最後に私はそれを得た。私は同様に密な 'indices'と' values'でパーティションを実行することができます。私は明日、 'tf.gather'を大量に使う解決策を投稿します。 – soloice

0

大雑把に直接にtf.SparseTensorindicesweights配列の代わりに、DOから適切な値を収集するために、1つの必要性を話します。私は以下のコードを投稿します。インデックスが同じ行を記述していると仮定すると、開始インデックスと終了インデックスを使用して識別できます。

# 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) 
関連する問題