Chú ý là một phương pháp để tổng hợp một tập các vectơ thành một vectơ, thường thông qua một vectơ tra cứu . Thông thường, là đầu vào của mô hình hoặc trạng thái ẩn của các bước thời gian trước đó hoặc trạng thái ẩn xuống một cấp (trong trường hợp các LSTM xếp chồng).viuvi
Kết quả thường được gọi là vectơ bối cảnh , vì nó chứa bối cảnh phù hợp với bước thời gian hiện tại.c
Vectơ bối cảnh bổ sung này sau đó cũng được đưa vào RNN / LSTM (nó có thể được nối đơn giản với đầu vào ban đầu). Do đó, bối cảnh có thể được sử dụng để giúp dự đoán.c
Cách đơn giản nhất để làm điều này là tính toán vectơ xác suất và trong đó là phép nối của tất cả các trước đó . Một vectơ tra cứu phổ biến là trạng thái ẩn hiện tại .p=softmax(VTu)c=∑ipiviVviuht
Có nhiều biến thể về điều này, và bạn có thể làm mọi thứ phức tạp như bạn muốn. Ví dụ, thay vì sử dụng làm nhật ký, người ta có thể chọn thay vào đó, trong đó là một mạng thần kinh tùy ý.vTiuf(vi,u)f
Một cơ chế chú ý chung cho các mô hình tuần tự sử dụng , trong đó là các trạng thái ẩn của bộ mã hóa và là ẩn hiện tại trạng thái của bộ giải mã. q và cả Wp=softmax(qTtanh(W1vi+W2ht))vhtqW s là tham số.
Một số bài báo thể hiện các biến thể khác nhau về ý tưởng chú ý:
Mạng con trỏ sử dụng sự chú ý đến các đầu vào tham chiếu để giải quyết các vấn đề tối ưu hóa tổ hợp.
Mạng thực thể định kỳ duy trì trạng thái bộ nhớ riêng cho các thực thể (người / đối tượng) khác nhau trong khi đọc văn bản và cập nhật trạng thái bộ nhớ chính xác bằng cách chú ý.
Các mô hình máy biến áp cũng sử dụng rộng rãi sự chú ý. Công thức chú ý của họ hơi chung chung hơn và cũng liên quan đến các vectơ chính ki : trọng số chú ý p thực sự được tính giữa các khóa và tra cứu, và bối cảnh sau đó được xây dựng với vi .
Dưới đây là một triển khai nhanh chóng của một hình thức chú ý, mặc dù tôi không thể đảm bảo tính chính xác ngoài thực tế là nó đã vượt qua một số thử nghiệm đơn giản.
RNN cơ bản:
def rnn(inputs_split):
bias = tf.get_variable('bias', shape = [hidden_dim, 1])
weight_hidden = tf.tile(tf.get_variable('hidden', shape = [1, hidden_dim, hidden_dim]), [batch, 1, 1])
weight_input = tf.tile(tf.get_variable('input', shape = [1, hidden_dim, in_dim]), [batch, 1, 1])
hidden_states = [tf.zeros((batch, hidden_dim, 1), tf.float32)]
for i, input in enumerate(inputs_split):
input = tf.reshape(input, (batch, in_dim, 1))
last_state = hidden_states[-1]
hidden = tf.nn.tanh( tf.matmul(weight_input, input) + tf.matmul(weight_hidden, last_state) + bias )
hidden_states.append(hidden)
return hidden_states[-1]
Với sự chú ý, chúng tôi chỉ thêm một vài dòng trước khi trạng thái ẩn mới được tính:
if len(hidden_states) > 1:
logits = tf.transpose(tf.reduce_mean(last_state * hidden_states[:-1], axis = [2, 3]))
probs = tf.nn.softmax(logits)
probs = tf.reshape(probs, (batch, -1, 1, 1))
context = tf.add_n([v * prob for (v, prob) in zip(hidden_states[:-1], tf.unstack(probs, axis = 1))])
else:
context = tf.zeros_like(last_state)
last_state = tf.concat([last_state, context], axis = 1)
hidden = tf.nn.tanh( tf.matmul(weight_input, input) + tf.matmul(weight_hidden, last_state) + bias )
mã đầy đủ