ध्यान केवल एक वेक्टर में वैक्टर vi सेट को एकत्र करने के लिए एक विधि है , अक्सर लुकअप वेक्टर u माध्यम से । आमतौर पर, vi या तो मॉडल या पिछले समय-चरणों के छिपे हुए राज्यों के लिए इनपुट है, या छिपे हुए राज्यों में एक स्तर नीचे है (स्टैक किए गए एलएसटीएम के मामले में)।
परिणाम को अक्सर संदर्भ वेक्टर c कहा जाता है , क्योंकि इसमें वर्तमान समय-चरण के संदर्भ प्रासंगिक होता है ।
इस अतिरिक्त संदर्भ सदिश c को तब RNN / LSTM में भी खिलाया जाता है (इसे मूल इनपुट के साथ संक्षिप्त किया जा सकता है)। इसलिए, संदर्भ का उपयोग भविष्यवाणी के साथ मदद करने के लिए किया जा सकता है।
यह करने के लिए सबसे आसान तरीका गणना संभावना वेक्टर है p=softmax(VTu) और c=∑ipivi जहां V सभी पिछले के संयोजन है vi । एक सामान्य लुकअप वेक्टर u वर्तमान में छिपी अवस्था ht ।
इस पर कई विविधताएं हैं, और आप चीजों को जितना चाहें उतना जटिल बना सकते हैं। उदाहरण के लिए, लॉग के रूप में vTiu का उपयोग करने के बजाय, कोई इसके बजाय f(vi,u) चुन सकता है , जहाँ f एक मनमाना तंत्रिका नेटवर्क है।
अनुक्रम करने वाली अनुक्रम मॉडल का उपयोग करता है के लिए एक आम ध्यान तंत्र p=softmax(qTtanh(W1vi+W2ht)) है, जहां v एनकोडर के छिपे हुए राज्य हैं, और ht वर्तमान छिपा राज्य है डिकोडर की। q और दोनों W s पैरामीटर हैं।
कुछ कागजात जो ध्यान विचार पर विभिन्न भिन्नताओं को दिखाते हैं:
पॉइंटर नेटवर्क कॉम्बीनेटरियल ऑप्टिमाइज़ेशन समस्याओं को हल करने के लिए संदर्भ इनपुट पर ध्यान देता है।
आवर्तक इकाई नेटवर्क पाठ पढ़ते समय विभिन्न संस्थाओं (लोगों / वस्तुओं) के लिए अलग-अलग मेमोरी स्टेट्स बनाए रखते हैं, और ध्यान का उपयोग करके सही मेमोरी स्टेट को अपडेट करते हैं।
ट्रांसफार्मर मॉडल भी ध्यान का व्यापक उपयोग करते हैं। ध्यान का उनका निर्माण थोड़ा अधिक सामान्य है और इसमें कुंजी वैक्टर ki भी शामिल हैं : ध्यान भार p वास्तव में कुंजियों और लुकअप के बीच गणना की जाती है, और संदर्भ तब vi साथ निर्मित होता है ।
यहां ध्यान के एक रूप का त्वरित कार्यान्वयन है, हालांकि मैं इस तथ्य से परे शुद्धता की गारंटी नहीं दे सकता कि यह कुछ सरल परीक्षणों से गुजरा।
मूल RNN:
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]
ध्यान देने के साथ, हम नए छिपे हुए राज्य की गणना करने से पहले केवल कुछ पंक्तियाँ जोड़ते हैं:
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 )
पूरा कोड