این مبحث در جلسه ۱۳ام از کلاس مباحث ویژه ۲ تدریس و بررسی شده است +ویدئوی جلسه در آپارات + اسلایدها
توجه (Attention) درواقع یک وکتور است که معمولا خروجیهای یک لایه تماممتصل (Dense) با تابع فعالساز Softmax است. Attention به ماشین مترجم کمک میکند تا تمامی اطلاعاتی که زبان مبدا دارد را بررسی کرده و کلمه خروجی را بر اساس کلمه فعلی در حال کار و کل متن -یا جمله- انتخاب کند. درواقع Attention این امکان را به مترجم ماشینی میدهد تا در محدودههای محلی و عمومی متمرکز شود و عمل ترجمه را علاوه بر توجه به مکان فعلی کلمه، با در نظر داشتن کل جمله انجام دهد.
ترجمه
ترجمه انسان
برای مثال یک مترجم زبان را در نظر بگیرید؛ این مترجم برای ترجمه یک کتاب ابتدا کل کتاب را نمیخواند و بعد شروع به ترجمه کند، همچنین برای ترجمه کل کتاب کلمه به کلمه شروع به ترجمه نمیکند. چرا که در حالت اول به دلیل دادههای زیادی که به دست میآید دچار از دست رفت اطلاعات میشویم و در حالت دوم، درکی از جمله -به عنوان واحد اولیه یک متن- بدست میآید و نه لزوما ترتیب کلمات زبان مبدا و مقصد برابر است که ترجمه مناسبی باشد. بنابراین برای ترجمه صحیح قسمت به قسمت (برای مثال نیمجمله به نیمجمله) متن را خوانده و اقدام به ترجمه آن میکنیم.
ترجمه ماشین
برای بررسی میزان شباهت ترجمه ماشینی به ترجمه توسط یک فرد واقعی، معیاری به نام معیار Blue Score تعریف شده است که با داشتن چند ترجمه صحیح یک متن که توسط مترجمان حرفهای ترجمه شده است و مقایسه ترجمه ماشین با آنها امتیازی که امکان مقایسه این ترجمه را میدهد تعیین میکند. در نمودار زیر تغییرات Blue Score نسبت به طول توالی در نظر گرفته شده روی متن را مشاهده میکنید:
مشاهده میکنید که همانطور که گفته شد با کوتاه بودن طول توالی حروف (ترجمه کلمه به کلمه) امتیاز ترجمه پایین و با طولانی بودن آن (برای مثال ترجمه پاراگراف به پاراگراف) نیز امتیاز ترجمه پایین است و تنها در بازهای طول توالی حروف است که امتیاز ترجمه به حداکثر خود میرسد.
پیادهسازی ترجمه ماشین
به دلیل ذات جمله که از تعداد متفاوتی کلمه تشکیل میشود، شبکههای RNN برای مدلکردن احتمال شرطی میان کلمات معرفی شدند. اما شبکههای RNN عادی در این مدل کردن دچار مشکل میشدند:
- در دنیای واقعی، طول ورودی و خروجی میتوانند کاملا متفاوت باشند. درحالیکه شبکههای RNN ساده تنها میتوانند مسائل با طول ثابت را حل کنند.
- این شبکههای از فراموشی تدریجی رنج میبرند که بدین معنی است که آموزش مدل هنگامی که جملات به اندازه کافی طولانی هستند به شدت دشوار میشود.
استفاده از Attention در ترجمه ماشینی
عمل ترجمه نیازدارد طول ورودیها و خروجیها متغیر و اختیاری باشند، برای برطرف کردن مشکلات بالا، مدل encoder-decoder به وجود آمد.
برای مثال فرض کنید میخواهیم جمله Jane visite l’Afrique en septembre را با استفاده از یک مدل دوطرفه (Bidirectional) از نوع LSTM یا GRU که در آنها هر قسمت (State) هم از قسمتهای قبلی و هم از قسمتهای بعدی آپدیت میشود ترجمه کنیم.
پس برای شروع، جمله زبان مبدا را به این مدل دوطرفه میدهیم. از آنجایی که طول جملات زبان مبدا و مقصد لزوما برابر نیستند، از خروجی مستقیم مدل (y) استفاده نکرده و میخواهیم خروجی این شبکه را به شبکهای دیگر بدهیم تا جملات زبان مقصد را تولید کند.
در اینجا هرقسمت ، یک تجسم (representation) از کلمه فعلی با درصد زیاد و درصد کمی از کلمات قبلی و بعدی -چراکه مدل یک مدل دوطرفه بوده- تولید میکند.
حال میخواهیم میزان تاثیر هرکدام از گامهای زمانی (Time step) ورودی بر گامهای خروجی را مشخص کنیم. برای اینکار از تمامی قسمتهای شبکه اول (شبکهای که یک تجسم از متن زبان مبدا میساخت) به یک شبکه LSTM یک طرفه به صورت وزندار ورودی میدهیم. که وزن یاد شده در واقع همان Attention ما است.
بنابراین هر قسمت شبکه بالا علاوه بر کلمه قبلی از تمامی قسمتهای شبکه پایین نیز ورودی دارد. هدف شبکه بالا این است که یادبگیرد برای ترجمه هر کلمه از چه کلمات زبان مبدا با چه وزنی باید ویژگیهای خود را استخراج کند. در این پیادهسازی وزنها، نقش Attention داشته و این مورد را مشخص میکنند.
پس تا اینجای کار، زبان مبدا را به عنوان رودی به یک شبکه LSTM دوطرفه دادیم، به ازای هر کلمه تعدادی ویژگی بدست آورد که در این ویژگیها هم کلمه جاری و هم کلمات قبلی و بعدی موثر بودند. حال می خواهیم ببینیم برای تولید اولین گامزمانی (Time step) زبان مقصد، چه ورودیهایی علاوه بر State گام قبلی نیاز دارد.
State هر گام زبان مبدا را ترکیبی از State گامهای قبل و بعد دانسته و با <‘a<t میشناسیم و میدانیم که مجموع ضرایب گامهای شبکه پایین برای هر گام در شبکه بالا برابر یک است.
همچنین Context هر گام در شبکه بالا به صورت مجموع حاصلضرب هر ضریب در state مربوط به آن گام در شبکه پایین خواهد بود.
Attention یا درواقع ضرایب آلفا در فرمول بالا، به صورت زیر محاسبه خواهد شد. درواقع میخواهیم که شبکه خود یاد بگیرد که برای مشخص کردن خروجی به چه میزان از ورودی گام قبلی تاثیر بپذیرد و به چه میزان از زبان مبدا.
در شبکه decoder در هر گام زمانی، از گام زمانی قبلی یک State به عنوان ورودی داشتیم.فرض کنید برای مشخص کردن وزنها، اگر برای گامهای شبکه decoder یک شبکه تماممتصل داشته باشیم، که از state قبلی () و stateهای گام متناظر در شبکه پایین (
) ورودی داشته باشد. اگر خروجی این شبکه را e در نظر بگیریم،
نشان میدهد که برای گام t از زبان مقصد به چه میزان بایدبه گام ‘t از زبان مبدا توجه شود.
بنابراین Attention را به صورت یک مدل تماممتصل آموزش میدهیم تا مدل بهترین ضرایب برای تشخیص تاثیر گامهای زمان مبدا در زبان مقصد را یادبگیرد.
نمونه پیادهسازی
برای مثال مدل مترجم زیر را در نظر بگیرید:
لایه Attention به صورت زیر پیادهسازی میشود:
در ابتدا تعدادی از توابع مشترک و اولیه را تعریف میکنیم. یک تکرارگر (Repeator) تعریف میکنیم که وظیفهاش تکرار وکتور دادهشده به تعداد گامهای ورودی (Tx) است وبرای این استفاده میشود که برای محاسبه context هر گام زبان مقصد، state اش با state تمامی گامهای زبان مبدا ترکیب میشد. همچنین یک Concatenator تعریف کردیم که این عمل ترکیب را انجام دهد. همچنین دولایه تماممتصل (Dense) برای محاسبه ضرایب مناسب و یک تابع dotor برای اعمال عمل عمل ضرب نقطهای استفاده خواهد شد:
1 2 3 4 5 6 7 8 |
from keras.layers import Concatenate, RepeatVector, Dense, Dot # Defined shared layers as global variables repeator = RepeatVector(Tx) concatenator = Concatenate(axis=-1) densor1 = Dense(10, activation = "tanh") densor2 = Dense(1, activation = "relu") activator = Activation(softmax, name='attention_weights') # We are using a custom softmax(axis = 1) loaded in this notebook dotor = Dot(axes = 1) |
سپس، تابع one_step_attention را برای محاسبه Attention یک گام به صورت زیر مینویسیم که در آن ورودی a در واقع stateهای شبکه زبان مبدا و s_prev، درواقع state گام قبلی شبکه زبان مقصد است :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# GRADED FUNCTION: one_step_attention def one_step_attention(a, s_prev): """ Performs one step of attention: Outputs a context vector computed as a dot product of the attention weights "alphas" and the hidden states "a" of the Bi-LSTM. Arguments: a -- hidden state output of the Bi-LSTM, numpy-array of shape (m, Tx, 2*n_a) s_prev -- previous hidden state of the (post-attention) LSTM, numpy-array of shape (m, n_s) Returns: context -- context vector, input of the next (post-attetion) LSTM cell """ ### START CODE HERE ### # Use repeator to repeat s_prev to be of shape (m, Tx, n_s) so that you can concatenate it with all hidden states "a" (≈ 1 line) s_prev = repeator(s_prev) # Use concatenator to concatenate a and s_prev on the last axis (≈ 1 line) concat = concatenator([a, s_prev]) # Use densor1 to propagate concat through a small fully-connected neural network to compute the "intermediate energies" variable e. (≈1 lines) e = densor1(concat) # Use densor2 to propagate e through a small fully-connected neural network to compute the "energies" variable energies. (≈1 lines) energies = densor2(e) # Use "activator" on "energies" to compute the attention weights "alphas" (≈ 1 line) alphas = activator(energies) # Use dotor together with "alphas" and "a" to compute the context vector to be given to the next (post-attention) LSTM-cell (≈ 1 line) context = dotor([alphas, a]) ### END CODE HERE ### return context |
این تابع مطابق شکل بالا با استفاده از توابع کمکی نوشته شده، با اعمال تابع Softmax به خروجی شبکههای تماممتصل و محاسبه ضرایب آلفا، context ورودی گام زبان مقصد را با استفاده از ضرب نقطهای ضرایب آلفا در a محاسبه میکند.
شبکه های اجتماعی