2016-01-19 64 views
82
tf.nn.embedding_lookup(params, ids, partition_strategy='mod', name=None) 

Tôi không thể hiểu nhiệm vụ của chức năng này. Nó giống như một bảng tra cứu? Có nghĩa là trả về các tham số tương ứng với mỗi id (trong id)?Chức năng tf.nn.embedding_lookup hoạt động như thế nào?

Ví dụ: trong mô hình skip-gram nếu chúng tôi sử dụng tf.nn.embedding_lookup(embeddings, train_inputs), thì đối với mỗi train_input nó sẽ tìm thấy cách nhúng tương ứng?

Trả lời

96

embedding_lookup chức năng truy xuất các hàng của dây chuyền params. Hành vi này tương tự như việc sử dụng lập chỉ mục với các mảng ở dạng khối. Ví dụ.

matrix = np.random.random([1024, 64]) # 64-dimensional embeddings 
ids = np.array([0, 5, 17, 33]) 
print matrix[ids] # prints a matrix of shape [4, 64] 

params tranh luận cũng có thể là một danh sách các tensors trong trường hợp này ids sẽ được phân phối trong tensors. Ví dụ: với danh sách 3 tensors [2, 64], hành vi mặc định là chúng sẽ đại diện cho ids: [0, 3], [1, 4], [2, 5].

partition_strategy kiểm soát cách thức số ids được phân phối trong danh sách. Việc phân vùng rất hữu ích cho các vấn đề quy mô lớn hơn khi ma trận có thể quá lớn để giữ một mảnh.

+11

Tại sao họ gọi nó theo cách này chứ không phải 'select_rows'? –

+8

@LenarHoyt vì ý tưởng về tra cứu này xuất phát từ Word Embeddings. và các "hàng" là các biểu diễn (nhúng) của các từ, vào một không gian vectơ - và hữu ích trong chính chúng. Thường thì nhiều hơn so với mạng thực tế. –

+2

Làm thế nào để tensorflow tìm hiểu cấu trúc nhúng? Chức năng này có quản lý quá trình đó không? – vgoklani

139

Có, chức năng này khó hiểu, cho đến khi bạn nhận được điểm.

Ở dạng đơn giản nhất, nó tương tự như tf.gather. Nó trả về các phần tử của params theo các chỉ mục được chỉ định bởi ids.

Ví dụ (giả sử bạn đang ở trong tf.InteractiveSession())

params = tf.constant([10,20,30,40]) 
ids = tf.constant([0,1,2,3]) 
print tf.nn.embedding_lookup(params,ids).eval() 

sẽ trở [10 20 30 40], bởi vì phần tử đầu tiên (chỉ số 0) của params là 10, yếu tố thứ hai của params (chỉ số 1) là 20, vv .

Tương tự,

params = tf.constant([10,20,30,40]) 
ids = tf.constant([1,1,3]) 
print tf.nn.embedding_lookup(params,ids).eval() 

sẽ trở [20 20 40].

Nhưng embedding_lookup nhiều hơn thế. Đối số params có thể là một danh sách của tensors, thay vì một tensor đơn.

params1 = tf.constant([1,2]) 
params2 = tf.constant([10,20]) 
ids = tf.constant([2,0,2,1,2,3]) 
result = tf.nn.embedding_lookup([params1, params2], ids) 

Trong trường hợp này, các chỉ số, quy định tại ids, tương ứng với các yếu tố của tensors theo một chiến lược phân vùng, nơi mà các chiến lược phân vùng mặc định là 'mod'.

Trong chiến lược 'mod', chỉ mục 0 tương ứng với phần tử đầu tiên của tensor đầu tiên trong danh sách. Chỉ mục 1 tương ứng với phần tử đầu tiên của giây thứ hai tensor. Chỉ mục 2 tương ứng với các thành phần đầu tiên của thứ ba tensor, v.v.Chỉ cần chỉ mục i tương ứng với phần tử đầu tiên của (i + 1) th tensor, cho tất cả các chỉ mục 0..(n-1), giả định tham số là danh sách các n tensors.

Bây giờ, chỉ mục n không thể tương ứng với tensor n + 1, vì danh sách params chỉ chứa n tensors. Vì vậy, chỉ số n tương ứng với yếu tố thứ hai của thiết bị đầu tiên. Tương tự, chỉ số n+1 tương ứng với phần tử thứ hai của tensor thứ hai vv

Vì vậy, trong các mã

params1 = tf.constant([1,2]) 
params2 = tf.constant([10,20]) 
ids = tf.constant([2,0,2,1,2,3]) 
result = tf.nn.embedding_lookup([params1, params2], ids) 

chỉ số 0 tương ứng với phần tử đầu tiên của tensor đầu tiên: 1

index 1 tương ứng với phần tử đầu tiên của thiết bị thứ hai: 10

chỉ mục 2 tương ứng với phần tử thứ hai của bộ kéo đầu tiên: 2

chỉ số 3 tương ứng với phần tử thứ hai của tensor thứ hai: 20

Như vậy, kết quả sẽ là:

[ 2 1 2 10 2 20] 
+4

lưu ý: bạn có thể sử dụng 'partition_strategy = 'div'' và sẽ nhận' [10, 1, 10, 2, 10, 20] ', tức là' id = 1' là phần tử thứ hai của tham số đầu tiên. Về cơ bản: 'partition_strategy = mod' (mặc định) ' id% len (params) ': chỉ số của tham số trong params ' id // len (params) ': chỉ mục của phần tử trong tham số trên ' partition_strategy = * div * 'theo cách khác xung quanh –

+2

@ asher-stern bạn có thể giải thích tại sao chiến lược" mod "được mặc định không? dường như chiến lược "div" tương tự như việc cắt tensor tiêu chuẩn (các hàng chọn lọc theo các chỉ số đã cho). Có một số vấn đề về hiệu suất trong trường hợp "div" không? – svetlovva

0

Thêm vào câu trả lời Asher Stern, params là hiểu như là một phân vùng của một lớn nhúng tensor. Nó có thể là một tensor duy nhất đại diện cho các tensor nhúng hoàn chỉnh, hoặc một danh sách các X tensors tất cả các hình dạng giống nhau ngoại trừ kích thước đầu tiên, đại diện cho tensors nhúng sharded.

Hàm tf.nn.embedding_lookup được viết xem xét thực tế là nhúng (params) sẽ lớn. Do đó chúng tôi cần partition_strategy.

2

Một cách khác để nhìn vào nó là, giả sử rằng bạn làm phẳng ra tensors một mảng chiều, và sau đó bạn đang thực hiện một tra cứu

(ví dụ) Tensor0 = [1,2,3], Tensor1 = [4,5,6], Tensor2 = [7,8,9]

Bộ kéo căng được làm phẳng sẽ như sau: [1,4,7,2,5,8,3,6,9]

Bây giờ khi bạn làm một tra cứu của [0,3,4,1,7] nó sẽ năng suất [1,2,5,4,6]

(i, e) nếu giá trị tra cứu là 7 cho ví dụ, và chúng tôi có 3 tensors (hoặc một tensor với 3 hàng) sau đó,

7/3: (Reminder là 1, Quotient là 2) yếu tố Vì vậy, lần thứ 2 của Tensor1 sẽ được hiển thị, đó là 6

1

Khi params tensor có kích thước cao, các id chỉ đề cập đến thứ nguyên hàng đầu. Có thể điều đó hiển nhiên đối với hầu hết mọi người nhưng tôi phải chạy đoạn mã sau đây để hiểu rằng:

embeddings = tf.constant([[[1,1],[2,2],[3,3],[4,4]],[[11,11],[12,12],[13,13],[14,14]], 
          [[21,21],[22,22],[23,23],[24,24]]]) 
ids=tf.constant([0,2,1]) 
embed = tf.nn.embedding_lookup(embeddings, ids, partition_strategy='div') 

with tf.Session() as session: 
    result = session.run(embed) 
    print (result) 

Chỉ cần thử chiến lược 'div' và cho một tensor, nó không có sự khác biệt.

Đây là kết quả:

[[[ 1 1] 
    [ 2 2] 
    [ 3 3] 
    [ 4 4]] 

[[21 21] 
    [22 22] 
    [23 23] 
    [24 24]] 

[[11 11] 
    [12 12] 
    [13 13] 
    [14 14]]] 
6

Vâng, mục đích của tf.nn.embedding_lookup() chức năng là để thực hiện một tra cứu trong ma trận nhúng và trả lại embeddings (hoặc trong thuật ngữ đơn giản đại diện vector) của từ ngữ.

Ma trận nhúng đơn giản (vocabulary_size x embedding_dimension) sẽ trông giống như bên dưới. (Tức là mỗi từ sẽ được đại diện bởi một vector số, vì vậy tên word2vec)


Nhúng Matrix

the 0.418 0.24968 -0.41242 0.1217 0.34527 -0.044457 -0.49688 -0.17862 
like 0.36808 0.20834 -0.22319 0.046283 0.20098 0.27515 -0.77127 -0.76804 
between 0.7503 0.71623 -0.27033 0.20059 -0.17008 0.68568 -0.061672 -0.054638 
did 0.042523 -0.21172 0.044739 -0.19248 0.26224 0.0043991 -0.88195 0.55184 
just 0.17698 0.065221 0.28548 -0.4243 0.7499 -0.14892 -0.66786 0.11788 
national -1.1105 0.94945 -0.17078 0.93037 -0.2477 -0.70633 -0.8649 -0.56118 
day 0.11626 0.53897 -0.39514 -0.26027 0.57706 -0.79198 -0.88374 0.30119 
country -0.13531 0.15485 -0.07309 0.034013 -0.054457 -0.20541 -0.60086 -0.22407 
under 0.13721 -0.295 -0.05916 -0.59235 0.02301 0.21884 -0.34254 -0.70213 
such 0.61012 0.33512 -0.53499 0.36139 -0.39866 0.70627 -0.18699 -0.77246 
second -0.29809 0.28069 0.087102 0.54455 0.70003 0.44778 -0.72565 0.62309 

tôi chia nhúng trên ma trận và chỉ được tải từ trong vocab sẽ là từ vựng của chúng tôi và các vectơ tương ứng trong mảng emb.

vocab = ['the','like','between','did','just','national','day','country','under','such','second'] 

emb = np.array([[0.418, 0.24968, -0.41242, 0.1217, 0.34527, -0.044457, -0.49688, -0.17862], 
    [0.36808, 0.20834, -0.22319, 0.046283, 0.20098, 0.27515, -0.77127, -0.76804], 
    [0.7503, 0.71623, -0.27033, 0.20059, -0.17008, 0.68568, -0.061672, -0.054638], 
    [0.042523, -0.21172, 0.044739, -0.19248, 0.26224, 0.0043991, -0.88195, 0.55184], 
    [0.17698, 0.065221, 0.28548, -0.4243, 0.7499, -0.14892, -0.66786, 0.11788], 
    [-1.1105, 0.94945, -0.17078, 0.93037, -0.2477, -0.70633, -0.8649, -0.56118], 
    [0.11626, 0.53897, -0.39514, -0.26027, 0.57706, -0.79198, -0.88374, 0.30119], 
    [-0.13531, 0.15485, -0.07309, 0.034013, -0.054457, -0.20541, -0.60086, -0.22407], 
    [ 0.13721, -0.295, -0.05916, -0.59235, 0.02301, 0.21884, -0.34254, -0.70213], 
    [ 0.61012, 0.33512, -0.53499, 0.36139, -0.39866, 0.70627, -0.18699, -0.77246 ], 
    [ -0.29809, 0.28069, 0.087102, 0.54455, 0.70003, 0.44778, -0.72565, 0.62309 ]]) 


emb.shape 
# (11, 8) 

Nhúng Lookup trong TensorFlow

Bây giờ chúng ta sẽ xem làm thế nào chúng ta có thể thực hiện nhúng tra cứu đối với một số câu đầu vào tùy ý.

In [54]: from collections import OrderedDict 

# embedding as TF tensor (for now constant; could be tf.Variable() during training) 
In [55]: tf_embedding = tf.constant(emb, dtype=tf.float32) 

# input for which we need the embedding 
In [56]: input_str = "like the country" 

# build index based on our `vocabulary` 
In [57]: word_to_idx = OrderedDict({w:vocab.index(w) for w in input_str.split() if w in vocab}) 

# lookup in embedding matrix & return the vectors for the input words 
In [58]: tf.nn.embedding_lookup(tf_embedding, list(word_to_idx.values())).eval() 
Out[58]: 
array([[ 0.36807999, 0.20834 , -0.22318999, 0.046283 , 0.20097999, 
     0.27515 , -0.77126998, -0.76804 ], 
     [ 0.41800001, 0.24968 , -0.41242 , 0.1217 , 0.34527001, 
     -0.044457 , -0.49687999, -0.17862 ], 
     [-0.13530999, 0.15485001, -0.07309 , 0.034013 , -0.054457 , 
     -0.20541 , -0.60086 , -0.22407 ]], dtype=float32) 

Quan sát cách chúng tôi đã nhận embeddings từ ma trận nhúng gốc của chúng tôi (bằng lời nói) bằng cách sử dụng chỉ số của từ trong vốn từ vựng của chúng tôi.

Thông thường, việc tra cứu nhúng được thực hiện bởi lớp đầu tiên (được gọi là Lớp nhúng) sau đó chuyển các nhúng này tới các lớp RNN/LSTM để xử lý tiếp.


Side Lưu ý: Thông thường từ vựng cũng sẽ có một đặc biệt unk token. Vì vậy, nếu một mã thông báo từ câu đầu vào của chúng tôi không có trong từ vựng của chúng tôi, thì chỉ mục tương ứng với unk sẽ được tra cứu trong ma trận nhúng.


P.S. Lưu ý rằng embedding_dimension là một hyperparameter rằng người ta phải điều chỉnh cho các ứng dụng của họ, nhưng mô hình phổ biến như Word2VecGloVe sử dụng 300 vector chiều cho đại diện cho mỗi từ.

Bonus Readingword2vec skip-gram model

1

Kể từ khi tôi cũng bị hấp dẫn bởi chức năng này, tôi sẽ cung cấp hai xu của tôi.

Cách tôi xem trong trường hợp 2D cũng giống như phép nhân ma trận (thật dễ dàng để khái quát hóa các thứ nguyên khác).

Cân nhắc từ vựng có ký hiệu N. Sau đó, bạn có thể đại diện cho một biểu tượng x dưới dạng vectơ kích thước Nx1, được mã hóa một lần.

Nhưng bạn muốn có một đại diện của biểu tượng này không phải là một vector của Nx1, nhưng như một với kích thước MX1, gọi y.

Vì vậy, để chuyển đổi x vào y, bạn có thể sử dụng và nhúng ma trận E, với kích thước MxN:

y = Ex.

Đây thực chất là những gì tf.nn.embedding_lookup (thông số, id, ...) đang thực hiện, với sắc thái ids chỉ là một số đại diện cho vị trí của số 1 trong mã hóa một lần nóng vector x.

Các vấn đề liên quan