Learning Natural Language Inference using Bidirectional LSTM Model and Inner-Attention

تغییرات پروژه از تاریخ 1396/11/21 تا حالا
** یادگیری استنتاج در زبان‌های طبیعی با استفاده از روش‌های LSTM دوطرفه و Inner-Attention**
*لینک پیاده‌سازی این مقاله در گیت هاب : https://github.com/morteza73/NLP_SNLI
توضیح : پیاده‌سازی این مقاله در اینترنت وجود نداشت و این پیاده سازی، توسط اینجانب و با توجه و کمک گرفتن از دیگر پروژه‌های مربوط به حوزه پردازش متن و بخصوص مقالاتی که در مورد استفاده از مجموعه‌داده SNLI است و استفاده از داکیومنت سایت keras به زبان پایتون ورژن 3 و با ابزار keras نوشته شده است.*
# مقدمه
تصور کنید جمله‌ای مشاهده می‌شود (عقیده[^Premises]). این جمله مفهومی را می‌رساند که ما را از موضوعی مطلع می‌سازد. حال جمله‌ای دیگر را در نظر بگیرید که بعد از جمله اولیه، بیان می‌شود (فرضیه[^Hypothesis]). 3 نوع استنتاج از جمله دوم نسبت به جمله اول می‌توان به دست آورد. یعنی ممکن است جمله دوم با توجه به جمله اول درست باشد، یا غلط باشد و یا نتوان نسبت به صحت یا اشتباه بودن آن اظهار نظر کرد. به طور مثال جملات زیر را در نظر بگیرید: 

عقیده : پسر در محیطی پوشیده از چمن حرکت می‌کند.
1. پسر داخل اتاق است (اشتباه).
2. پسر بیرون از خانه است (صحیح).
3. پسر داخل پارک است (نامعلوم).

همانطور که در مثال بالا مشاهده می‌شود، 3 وضعیت اشتباه، صحیح و نامعلوم می‌توان با توجه به جمله دوم برداشت کرد.

این مقاله با استفاده از روش‌های یادگیری عمیق LSTM دوطرفه و Inner-Attention به بررسی این موضوع پرداخته است.
**روش LSTM دوطرفه **: LSTM دوطرفه یکی از روش‌های یادگیری عمیق است که برای یادگیری داده‌های ترتیبی[^Sequential] مورد استفاده‌ قرار می‌گیرد. LSTM مدل بهبود یافته RNN است. در مدل RNN ممکن است داده‌هایی که در ابتدای فرآیند آموزش استفاده می‌شوند، با گذشت زمان تاثیر کمتری در روند آموزش داشته باشند. روش LSTM با استفاده از دروازه‌هایی[^Gates] برای یادگیری و فراموش‌ کردن داده‌ها، به نوعی به صورت حافظه‌‍دار عمل می‌کند. به این ترتیب با دور شدن از داده‌های اولیه، ممکن است تاثیر آن داده‌ها کم نشوند و به این ترتیب عملکرد بهتری مشاهده می‌شود. LSTM دوطرفه، به این صورت است که در زمان آموزش، یک بار از ابتدا به انتها داده‌ها مورد بررسی قرار می‌گیرد و وزن‌ها و مقادیر بایاس اصلاح می‌شوند، یک بار از انتها به ابتدا فرآیند آموزش انجام می‌شود و ماتریس‌های مربوطه تنظیم می‌شوند و در انتها این 2 گروه نرون، در کنار یکدیگر در قسمت خروجی قرار می‌گیرند. (یه طور مثال اگر 300 بعد داشته باشیم، خروجی این لایه 600 بعد است که 300 تای اول مربوط به LSTM از اول به آخر و 300تای دوم مربوط به LSTM از آخر به اول است).
![معماری biLSTM: داده‌های ترتیبی از x1 تا xn به عنوان ورودی در لایه ورودی قرار دارند. سپس در لایه بالاتر یک بار از ابتدا به سمت انتها و بار دیگر از انتها به سمت ابتدا یادگیری انجام می‌شود.](https://boute.s3.amazonaws.com/291-Capture2.PNG)

**روش Inner-Attention **: در این روش با مشاهده توجه جمله به اجزا، اهمیت هر نوع کلمه بررسی می‌شود و این میزان اهمیت در اصلاح وزن‌ها و بایاس‌ها مورد توجه قرار می‌گیرد. به طور مثال اگر دسته "اسم‌" اهمیت بیشتری نسبت به دسته "فعل" داشت، اصلاح وزن فعل‌ها به صورت خفیف‌تر انجام می‌شود.
![نمونه‌ای از اعمال Inner-Attention بر روی مجموعه داده، رنگ تیره‌‎تر به معنای وزن بیشتر و رنگ روشن‌تر به معنای وزن و تاثیر کمتر است.](https://boute.s3.amazonaws.com/291-Capture3.PNG)
معماری inner-attentionّ به شکل زیر است:
1. بر روی لایه biLSTM لایه MeanPooling با اندازه پنجره 2 صورت می‌گیرد(Ravg).
2. بالای لایه قبل، یک لایه با تاعع فعال‌سازی tanh قرار می‌گیرد که به عنوان ورودی، مجموع دو خروجی لایه Ravg و biLSTM را دریافت می‌کند(M).
3. بر روی لایه قبل، یک لایه با نام آلفا با تابع فعال‌سازی softmax قرار می‌گیرد که خروجی لایه قبل را به عنوان ورودی می‌گیرد.
4. به لایه جمله (sentence vector) ضرب خروجی دو لایه آلفا و خروجی biLSTM قرار می‌گیرد (این ضرب باعث می‌شود تاثیر لغات برای آموزش تغییر کند).
این مکانیزم به صورت زیر فرموله شده است: 
![فرمول‌های Inner-Attention](https://boute.s3.amazonaws.com/291-Capture5.PNG)
در زمان آموزش، 3 بردار وزن WhوWy و Wt نیز آموزش داده می‌شوند تا به درستی تاثیر لغات مختلف را تغییر دهند.
**مجموعه داده‌ها**
**SNLI**
برای آزمایش روش این مقاله، مجموعه داده‌ها از مجموعه‌ داده‌هایی که دانشگاه استنفورد[^http://nlp.stanford.edu/projects/snli/]  به همین منظور در سایت خود قرار داده است، استفاده شده است. این مجموعه داده به SNLI معروف است. مجموعه داده‌های این سایت به این صورت است که 550 هزار جمله دوتایی که دارای برچسب هستند، به عنوان داده‌ آموزش در فایل مربوطه وجود دارد. 
این مجموعه به صورت فایل Json در سایت دانشگاه استنفورد وجود دارد. این مجموعه داده شامل 3 بخش داده‌های آموزش، داده‌های آزمایش، داده‌های تست است. هر جمله‌ در قسمت عقیده این فایل، 3 بار با 3 برچسب و جمله فرضیه مختلف تکرار شده است.
این فایل ستون‌های مختلفی دارد که اطلاعات بیشتری مثل نقش کلمه در جمله و غیره را مشخص می‌کند که برای این مقاله تنها 3 ستون sentence1_binary_parse (جمله عقیده به همراه پرانتز) و sentence2_binary_parse (جمله فرضیه به همراه پرانتز) و gold_label (برچسب) استفاده شده ‌است.
برای عملیات و استفاده از این مجموعه داده، نیاز است که با استفاده از ابزارهای کار با متن (مانند حذف کردن پرانتزها، توکن کردن جمله و غیره)، جمله را برای استفاده در این معماری آماده کرد. این عملیات در قسمت پیاده‌سازی مقاله توضیح داده شده است.
**Glove**
در این مقاله از مجموعه داده Glove با ابعاد 300 بعدی، که در دانشگاه استنفورد[^https://nlp.stanford.edu/projects/glove/]  جمع آوری شده است، استفاده شده است. این مجموعه داده شامل یک بردار 300 بعدی با اعداد بین 0 تا 1 برای لغت‌های مختلف است. به این شکل که لغاتی که با همدیگر شباهت‌هایی دارند، در فضای برداری کنار یکدیگر قرار می‌گیرند.
این مجموعه داده در لایه‌های ابتدایی پیاده سازی این معماری، کمک می‌کند تا محاسبات با کیفیت بهتری انجام شود. به این صورت که جمله را به صورت آرایه‌ای از لغت‌ها دریافت می‌کند و به عنوان مقدار بازگشتی، آرایه‌ای دو بعدی که بعد دوم 300 بعد عدد بین 0 تا 1 است را بر می‌گرداند (به طور مثال در این مقاله، آرایه 42 تایی از لغات را می‌گیرد و آرایه 42 در 300 تایی از اعداد بین 0 تا 1 را بر می‌گرداند).
![نمونه‌ای از داده‌های Glove](https://boute.s3.amazonaws.com/291-Capture9.PNG)
 
**برچسب داده‌ها**

هر داده در مجموعه داده‌ها با 3 برچسب مختلف مشاهده می‌شود:
1. برچسب E[^Entailment] : نتیجه‌گیری درست است.
2. برچسب C[^Contradiction] : نتیجه‌گیری نادرست است.
3. برچسب N[^Neutral] : نتیجه‌گیری ممکن است درست باشد و ممکن است غلط باشد. در مورد صحت جمله دوم نمی‌توان نظر داد.
در عکس زیر نمونه‌ای از این 3 برچسب مشاهده می‌شود.
![نمونه‌ای از دسته‌بندی داده‌ها](https://boute.s3.amazonaws.com/291-Capture8.PNG)

این پژوهشگر در انتها مدلی را معرفی و آزمایش می‌کند که نسبت به بهترین مدل پیاده‌سازی در گذشته، 2 درصد بهتر عمل می‌کند.

# کارهای مرتبط
در گذشته مساله استنتاج دو جمله در حوزه رده‌بندها[^Classifiers] انجام شده است و ویژگی‌ها به صورت دستی انتخاب می‌شدند. این پژوهش‌ها دقت کمتری نسبت به این مقاله داشتند.
بسیاری از محققان از جمله باس و مارکت[1] از این روش‌ها استفاده می‌‌‎کردند که به علت پیچیدگی زیاد و محدودیت‌های رده‌بندها از آن‌ها استقبال زیادی نشد.
تن و دیگران [2] روش‌های LSTM را برای استخراج استنتاج از متن را معرفی کرده‌اند.
راکستکل و دیگران [3] با استفاده از مدل‎های توجه به نورون[^Neutral attention model]، دقت بهتری را در این حوزه به دست آورد.
استفاده از مکانیزم توجه و استفاده از biLSTM بر روی این مجموعه داده، حرکت باارزشی بود که در این مقاله انجام شده است. 

# متدولوژی ارائه شده در این مقاله
در این پژوهش از چارچوب‌های یادگیری عمیق برای تشخیص استنتاج متن ها استفاده شده است. در این روش از روش‌های انتخاب ویژگی و همچنین منابع خارجی استفاده نشده است. معماری روش ارائه شده در شکل زیر مشاهده می‌شود:
![معماری ارائه شده در این مقاله](https://boute.s3.amazonaws.com/291-Capture4.PNG)
در این روش، ابتدا biLSTM هم بر روی عقیده و هم بر روی فرضیه اعمال می‌شود. از رمزگذار Mean Pooling یک دید کلی در مورد اینکه جمله در ارتباط با چه چیزی صحبت می‌کند، نمایان می‌کند. با استفاده از این قسمت، به مدل ارائه شده، Inner-Attention در هر دو جمله تعمیم داده می‌شود. با این کار دقت عملکرد، به وسیله تمرکز بر روی نماینده‌های جمله (کلمه‌های کلیدی‌تر) بیشتر می‌شود. 
همچنین در این مقاله از تکنیک‌هایی برای دریافت ورودی استفاده شده است که باعث دریافت نتایج بهتر می‌شود. در ادامه به طور دقیق معماری این مقاله شرح داده می‌شود.

**روش ارائه شده**
در این روش، این مساله به عنوان یک مساله رده‌بندی 3 مسیره باناظر در نظر گرفته می‌شود. طراحی این معماری به شکلی است که دو رمزگذار جمله‌های دوتایی، وزن‌ها را در زمان آموزش با یکدیگر به اشتراک می‌گذارند. سپس نمایندگان دو جمله با یکدیگر ترکیب می‎‌شوند و "بردار ارتباط" را برای رده‌بند می‌سازند.
شکل معماری این مقاله شامل 3 بخش زیر است که در ادامه توضیح داده خواهد شد:
1. ماژول ورودی جمله‌ها
2. ماژول رمزگذاری جمله‌ها
3. ماژول ترکیب جمله‌ها

**1. ماژول ورودی جمله‌ها**
در این قسمت 4 استراتژی مختلف برای دریافت جمله‌ها به عنوان ورودی استفاده شده است:
4. معکوس‌ کردن عقیده [4]
5. دوبار تکرار کردن عقیده [5]
6.  دو بار تکرار کردن فرضیه
7. حذف کردن کلمات مشترک در عقیده و فرضیه
بعد از اینکه جمله‌ها به عنوان ورودی انتخاب شدند، این جمله‌ها با کمک ابزاری به نامه Tokenizer لغت به لغت جدا می‌شوند. بعد از این کار هر جمله به آرایه‌ای از لغات تبدیل شد، برای یکسان سازی تمام جملات، این مجموعه داده،به اندازه بیشترین لغت ممکن در یک جمله (در این مجموعه داده = 42) فضا اختصاص داده می‌شود و سپس آرایه لغات در اتنهای این آرایه قرار می‌گیرد.
به طور مثال اگر جمله "علی به مدرسه می‌رود." را داشته باشیم، Tokenizer یک آرایه 42تایی برای این جمله اختصاص می‌دهد و آرایه {"","", ... , "علی" , "به" , "مدرسه" , "می‌رود" , "."} را ذخیره می‌کند.
سپس با ابزار word_to_sequence این کلمات با توجه به اینکه چند بار در کل مجموعه داده تکرار شده‌اند، رتبه‌بندی شده و سپس به جای عبارت string یک آرایه شامل اعداد ذخیره می‌شود.
به طور مثال در آرایه قبل به این حالت می‌رسیم : {0,0,0, .... , 32, 53, 4 , 4053 , 1}.
نکته : در زمان آموزش، نگاشت بین این اعداد و لغات در tokenizer.word_index ذخیره می‌شود. به طور مثال { علی:32 , به:53 و ... }
تا این لحظه، برای هر جمله یک آرایه 42 تایی از اعداد مختلف را در اختیار داریم. 
با استفاده از Embedding، هر کلمه را در فضای برداری و با یک آرایه 300 تایی با اعداد بین 0 تا 1 نمایش می‌دهیم تا بتوان بر روی این مجموعه داده، عملیات یادگیری را انجام داد. Embedding با دو حالت مختلف استفاده می‌شود:
 -  با استفاده از مجموعه داده‌ کمکی (در این مقاله از Glove استفاده شده است) : در این حالت، یک مجموعه داده در اختیار داریم که لغات مشابه را در فضای برداری نزدیک هم قرار داده‌ است. به همین خاطر کلمه‌ها را بررسی می‌کنیم که آیا در این مجموعه داده وجود دارد یاخیر، اگر وجود داشت مقادیر آرایه 300 بعدی را از این مجموعه داده ذخیره می‌کنیم و در غیر این صورت این آرایه با اعداد تصادفی پر می‌شود.
 - بدون استفاده از مجموعه داده کمکی: مقادیر آرایه 300 بعدی به صورت تصادفی ذخیره می‌شود.

بعد از به دست آمدن آرایه 42 در 300تایی، این لایه به لایه biLSTM متصل می‌شود که خروجی این لایه 600 نرون است.

**2.ماژول رمزگذاری جمله‌ها**
در این قسمت، سعی می‌شود که نمایندگان هر جمله با کیفیت بهتری انتخاب شوند. به منظور انجام این کار، 2 استراتژی برای رمزگذاری جمله‌ها استفاده شده است، در مرحله اول از Average pooling بالای لایه biLSTM برای تولید بردار جمله استفاده شده است. سپس مکانیزم توجه بر روی همان جمله اعمال می‌شود، به این صورت که به دست آوردن وزن‌ کلمات با استفاده از ارجاع از جمله دوم به اول، از مشاهده نمایندگان جمله که در مراحل قبل تولید شده است، استفاده می‌شود. ایده این کار از نحوه عملکرد انسان‌ها به دست آمده است. به این صورت که انسان که یک عبارت را می‌خواند، با توجه به مطالعات گذشته‌اش کلمات بااهمیت را به خاطر می‌سپارد.
همانطور که در قسمت مقدمه گفته شد، معماری inner-attentionّ به شکل زیر است:
1. بر روی لایه biLSTM لایه MeanPooling با اندازه پنجره 2 صورت می‌گیرد(Ravg) (این لایه 2 جایگاه مختلف و بالای عقیده و فرضیه به صورت جداگانه قرار می‌‎گیرد. ورودی این لایه 600 بعد و خروجی این لایه 300 بعد دارد).
2. بالای لایه قبل، یک لایه با تاعع فعال‌سازی tanh قرار می‌گیرد که به عنوان ورودی، مجموع دو خروجی لایه Ravg و biLSTM را دریافت می‌کند(M) (در این قسمت، 2 لایه Ravg که یکی بالای عقیده و یکی بالای فرضیه بود، خروجی‌های خودر را کنار یکدیگر قرار می‌دهند(2*300) و این 600 بعد با خروجی biLSTM جمله که 600 بعد است جمع می‎شود. در نتیجه خروجی این لایه نیز 600 بعد است، این لایه نیز همانند Ravg دو بخش جداگانه یکی برای جمله عقیده و یکی برای جمله فرضیه مورد استفاده قرار می‌گیرد).
3. بر روی لایه قبل، یک لایه با نام آلفا با تابع فعال‌سازی softmax قرار می‌گیرد که خروجی لایه قبل را به عنوان ورودی می‌گیرد(ورودی 600 بعد و خروجی 600 بعد).
4. به لایه جمله (sentence vector) ضرب خروجی دو لایه آلفا و خروجی biLSTM قرار می‌گیرد (این ضرب باعث می‌شود تاثیر لغات برای آموزش تغییر کند، این لایه در خروجی 600 بعد دارد).
این مکانیزم به صورت زیر فرموله شده است: 
![فرمول‌های Inner-Attention](https://boute.s3.amazonaws.com/291-Capture5.PNG)
در زمان آموزش، 3 بردار وزن WhوWy و Wt نیز آموزش داده می‌شوند تا به درستی تاثیر لغات مختلف را تغییر دهند.

**3. ماژول ترکیب جمله‌ها**
بعد از ماژول رمزگذاری و ساخت بردار‌های جمله، 3 عمل ترکیب برای استخراج رابطه بین عقیده و فرضیه اتفاق می‌افتد:
1. ترکیب دو نماینده (قرار دادن خود لغات کنار هم. ورودی 42 بعدی)
2. ضرب المان‌ها  (به عنوان ورودی دو لایه 600 بعدی از بردار جمله فرضیه و عقیده دریافت می‌کند و خروجی 600 بعد دارد)
3. اختلاف المان‌ها (به عنوان ورودی دو لایه 600 بعدی از بردار جمله فرضیه و عقیده دریافت می‌کند و خروجی 600 بعد دارد)
این لایه 3 بخش بالا را در کنار یکدیگر قرار می‌دهد و در خروجی 1284 بعدی است.
این معماری ترکیب ابتدا توسط مو و دیگران [6] معرفی شده است. در انتها از SoftMax در بالای این لایه استفاده شده است تا خروجی به صورت غیر خطی برای رده‌بند مورد استفاده قرار بگیرد.

# پیاده‌سازی
پیاده‌سازی این مقاله به زبان پایتون نسخه 3 و به کمک ابزار keras انجام شده است. این پروژه در سایت گیت هاب[^ https://github.com/morteza73/NLP_SNLI] بارگذاری شده است.
در ابتدای فایل main.py تعدادی متغیر ثابت مانند MAX_EPOCHS  یا  BATCH_SIZE  مقداردهی شده است تا در قسمت‌های مختلف کد از این مقادیر استفاده شود.
تابع extract_tokens_from_binary_parse یک خط از مجموعه‌داده را دریافت می‌کند و سپس پرانتزها و حروف زاید را حذف می‌کند و به جای آن خط فاصله می‌گذارد. این تابع به همراه توابع get_data و yield_example وظیفه آماده‌سازی و ذخیره داده‌ها در غالب مناسب برای استفاده keras را انجام می‌دهد.
به این صورت که در مثال زیر، فایل json  تبدیل به یک ارایه 2 بعدی (3 در  550 هزار برای training) می‌شود که لغات را به صورت رشته ذخیره دارد:

	training = get_data('snli_1.0_train.jsonl')
	validation = get_data('snli_1.0_dev.jsonl')
	test = get_data('snli_1.0_test.jsonl')

در سطر اول، عقیده‌ها، در سطر دوم، فرضیه‌ها و در سطر سوم، برچسب‌ها قرار می‌گیرند.
جمله‌ها با کمک ابزاری به نامه Tokenizer لغت به لغت جدا می‌شوند. بعد از این کار هر جمله به آرایه‌ای از لغات تبدیل شد، برای یکسان سازی تمام جملات، این مجموعه داده،به اندازه بیشترین لغت ممکن در یک جمله (در این مجموعه داده = 42) فضا اختصاص داده می‌شود و سپس آرایه لغات در اتنهای این آرایه قرار می‌گیرد.

	tokenizer = Tokenizer(lower=False, filters='')
	tokenizer.fit_on_texts(training[0] + training[1])
	
	VOCAB = len(tokenizer.word_counts) + 1
	LABELS = {'contradiction': 0, 'neutral': 1, 'entailment': 2}


سپس با ابزار word_to_sequence این کلمات با توجه به اینکه چند بار در کل مجموعه داده تکرار شده‌اند، رتبه‌بندی شده و سپس به جای عبارت string یک آرایه شامل اعداد ذخیره می‌شود.

	to_seq = lambda X: pad_sequences(tokenizer.texts_to_sequences(X), maxlen=MAX_LEN)
	prepare_data = lambda data: (to_seq(data[0]), to_seq(data[1]), data[2]) 
	
	training = prepare_data(training) 
	validation = prepare_data(validation) 
	test = prepare_data(test)

با استفاده از Embedding، هر کلمه را در فضای برداری و با یک آرایه 300 تایی با اعداد بین 0 تا 1 نمایش می‌دهیم تا بتوان بر روی این مجموعه داده، عملیات یادگیری را انجام داد. در اینجا از مجموعه‌داده Glove نیز به عنوان کمک استفاده می‌شود که در کد با مقدار دودویی USE_GLOVE بخش مربوطه اجرا می‌شود. در زیر قسمتی از کد این قسمت را مشاهده می‌کنید که بر روی تمام لغاتی که tokenizer در زمان توکنایز کردن مجموعه‌داده مشاهده کرده است، جسجتجو انجام می‌شود که اگر در مجموعه داده Glove وجود داشت، بردار 300بعدی اعداد 0 تا 1 از Glove خوانده شود.

	for word, i in tokenizer.word_index.items(): 
		embedding_vector = embeddings_index.get(word) 
		if embedding_vector is not None: 
		# words not found in embedding index will be all-zeros. 
		embedding_matrix[i] = embedding_vector

سپس معماری این مقاله پیاده‌سازی شده است که قسمت به قسمت با کامنت توضیح داده شده است:

	#laye voroodi -> (42) 
	premise = keras.layers.Input(shape=(MAX_LEN,)) 
	hypothesis = keras.layers.Input(shape=(MAX_LEN,)) 
	
	#emale embedding : (42) -> (42,300) 
	prem = embed(premise) 
	hypo = embed(hypothesis) 
	
	#normalize kardane beine 0 ta 1 
	prem = BatchNormalization()(prem) 
	hypo = BatchNormalization()(hypo) 
	
	#emale biLSTM bar rooye prem va hypo: (42,300) -> (600) 
	bi_prem = Bidirectional(LSTM(input_dim=MAX_LEN,output_dim=300,return_sequences=False))(prem) 
	bi_prem = BatchNormalization()(bi_prem) bi_hypo = Bidirectional(LSTM(input_dim=MAX_LEN,output_dim=300,return_sequences=False))(hypo)
	bi_hypo = BatchNormalization()(bi_hypo) 
	
	########## piade sazie ghasmate inner attention 
	#amade size baraye emale meanPooling. reshape be in ellat ast ke 
	#tabe AveragePooling1D tensor3d be onvane voroodi mipazirad 
	# (600) -> (600,1) 
	bi_prem_reshape = keras.layers.Reshape((600,1))(bi_prem) 
	bi_hypo_reshape = keras.layers.Reshape((600,1))(bi_hypo) 
	
	# (600,1) -> (300,1) 
	meanPrem = keras.layers.AveragePooling1D(pool_size=2)(bi_prem_reshape) 
	meanHypo = keras.layers.AveragePooling1D(pool_size=2)(bi_hypo_reshape) 
	
	# (300,1) -> (300) 
	meanPrem = keras.layers.Reshape((300,))(meanPrem) 
	meanHypo = keras.layers.Reshape((300,))(meanHypo) 
	
	#kenare ham gozashtane 2 mean : (300) -> (600) 
	mean = keras.layers.concatenate([meanPrem,meanHypo]) 
	
	# mmm = W(y)*Y + W(h)*R(avg)*el 
	mPrem = keras.layers.Add()([bi_prem,mean*el])
	mHypo = keras.layers.Add()([bi_hypo,mean*el]) 
	mPrem.trainable = False 
	mHypo.trainable = False 
	
	# M = tanh(mmm) 
	# chon dar laye Add natoonestam activation ro tanh konam inja in karo kardam 
	mPrem = keras.layers.Dense(600,activation='tanh')(mPrem) 
	mHypo = keras.layers.Dense(600,activation='tanh')(mHypo) 
	
	#alpha = softmax(W(t) * M) 
	alphaPrem = keras.layers.Dense(600,activation='softmax')(mPrem) 
	alphaHypo = keras.layers.Dense(600,activation='softmax')(mHypo) 
	
	#ijade sentence vector 
	################ if inner attention work!!! ################# 
	# (600) * (600) 
	#sentence_prem = keras.layers.Multiply()([alphaPrem,bi_prem]) 
	#sentence_hypo = keras.layers.Multiply()([alphaHypo,bi_hypo]) 
	
	############### without inner attention!!! ################## 
	#khorooje meanPooling (ke rooye bilstm emal shod) 
	sentence_prem = bi_prem sentence_hypo = bi_hypo 
	
	#zarbe sentence vector ha 
	multiply = keras.layers.Multiply()([sentence_prem, sentence_hypo]) 
	
	#tafrighe sentence vector ha 
	subtracted = keras.layers.Subtract()([sentence_prem, sentence_hypo]) 
	
	#normalize kardan 
	multiply = BatchNormalization()(multiply) 
	subtracted = BatchNormalization()(subtracted)
	

سپس با دستور زیر، لایه‌ها کنار هم قرار می‌گیرند.

	concatenateLayer = keras.layers.concatenate([premise,multiply,subtracted,hypothesis],axis=-1)
	concatenateLayer = BatchNormalization()(concatenateLayer)

با دستور زیر، مقدار DropOut بر روی لایه 1284 بعدی اعمال می‌شود.

	concatenateLayer = Dropout(DP)(concatenateLayer)

لایه پیشبینی در زیر ایجاد می‌شود.

	pred = Dense(len(LABELS), activation='softmax')(concatenateLayer)

ورودی‌ها و خروجی به مدل معرفی می‌شود.

	model = keras.models.Model(inputs=[premise, hypothesis], outputs=pred)

عملیات مربوط به یادگیری و پیشبینی به همراه چاپ نتایج در زیر پیاده‌سازی شده است:

	model.compile(optimizer=OPTIMIZER, loss='categorical_crossentropy', metrics=['accuracy'])
	model.fit([training[0], training[1]], training[2], batch_size=BATCH_SIZE, nb_epoch=MAX_EPOCHS, validation_data=([validation[0], validation[1]], validation[2]))
	loss, acc = model.evaluate([test[0], test[1]], test[2], batch_size=BATCH_SIZE)
	print('Test loss / test accuracy = {:.4f} / {:.4f}'.format(loss, acc))

# آزمایش‌ها و نتایج
برای آزمایش معماری ارائه شده، تنظیماتی برای شبکه عصبی و داده‌ها در نظر گرفته شده است:
1. اندازه تعداد داده وارد شده برای یادگیری[^Batch size] = 128
2. میزان در نظر نگرفتن نورون‌ها در زمان یادگیری[^Dropout rate] = 25 درصد (این عمل تنها بر روی لایه آخر (1284 بعدی) اعمال می‌شود)
3. برای مقداردهی اولیه به وزن کلماتی که تا قبل از آن مرحله در داده‌های مجموعه‌داده Glove دیده نشدند، 300 بعد با وزنی رندمی با توزیع (0.05و0.05) در نظر گرفته می‌شود.
4. وزن‌ها بعد از آمدن هر داده، به روز نمی‌شوند. به این دلیل که تعداد داده‌هایی که نیاز به تنظیم وزن دارند کمتر شود و همچنین نمایندگان جمله نسبت به المان‌های جدید که تا به حال دیده نشده‌اند، عملکرد بهتری انجام دهند. 

همانطور که در بخش ماژول ورودی صحبت شد، 4 روش برای دریافت ورودی مورد استفاده قرار گرفته است. نتیجه استفاده از هر روش در جدول زیر نمایش داده شده است:
![نتیجه اعمال استراتژی برای ورودی داده‌ها](https://boute.s3.amazonaws.com/291-Capture6.PNG)

بعد از انجام معماری ارائه شده، نتایج با روش‌‌های روز که محققان دیگر انجام داده‌اند مورد بررسی قرار گرفته است. در ادامه توضیح مختصر در روش در نظر گرفته شده در پژوهش‌های روز دیگر و همچنین جدول نتایج نمایش داده شده است:

1. LSTM enc: 100D LSTM encoders + MLP[6].
2. GRU enc: 1024D GRU encoders + skip-thoughts + cat[7].
3. TBCNN enc: 300D Tree-based CNN encoders + cat[8].
4. SPINN enc: 300D SPINN-NP encoders + cat[9].
5. Static-Attention: 100D LSTM + static attention[3].
6. WbW-Attention: 100D LSTM+ word-by-word attention[3].
![نتیجه مقایسه با معماری‌های محققان دیگر](https://boute.s3.amazonaws.com/291-Capture7.PNG)

# نتیجه‌گیری
در این پژوهش، یک معماری biLSTM با توجه به Inner-Attention برای حل مسائل اسنتاج دو جمله‌ای یا RTE ارائه شد. Inner-Attention به این صورت عمل کرد که نحوه تعیین توجه در جمله را با استفاده از اهمیت لغت‌ها در جمله، محاسبه شود که نحوه عملکرد این قسمت در گزارش به طور دقیق نوشته شده است. این کار به همراه استراتژی‌های مختلف در فاز ورود داده‌ها در این پژوهش مورد استفاده قرار گرفته است و پیاده‌سازی این مقاله با زبان پایتون و به کمک ابزار keras انجام شده است. دقت عملکرد این معماری نسبت به مدل‌های پیشین 2 درصد بهبود یافته است.
# کارهای آینده
1. استفاده این روش در حوزه‌های دیگر (به جز RTE)، مانند سوال جواب، تشابه دو جمله و غیره.
2. تغییر در معماری شبکه عصبی (در لایه‌ها یا توابع فعال‌ساز) و بررسی نحوه تغییر عملکرد.
3. استفاده از مجموعه داده word2vec به جای glove و بررسی میزان بهبود عملکرد معماری.
3. این روش بر روی زبان‌های دیگر مانند فارسی انجام شود.

# مراجع

[1] Johan Bos and Katja Markert. 2005. Recognising textual entailment with logical inference. In Proceedings of the conference on Human Language Technology and EmpiricalMethods in Natural Language Processing, pages 628–635. Association for Computational Linguistics.
[2] Ming Tan, Bing Xiang, and Bowen Zhou. 2015. Lstm-based deep learning models for non-factoid answer selection. arXiv preprint arXiv:1511.04108.
[3] Tim Rockt¨aschel, Edward Grefenstette, Karl Moritz Hermann, Tom´aˇs Koˇcisk`y, and Phil Blunsom. 2015. Reasoning about entailment with neural attention. arXiv preprint arXiv:1509.06664.
[4] Ilya Sutskever, Oriol Vinyals, and Quoc V Le. 2014. Sequence to sequence learningwith neural networks. In Advances in neural information processing systems, pages 3104–3112.
[5] Wojciech Zaremba and Ilya Sutskever. 2014. Learning to execute. arXiv preprint arXiv:1410.4615.
[6] Samuel R Bowman, Gabor Angeli, Christopher Potts, and Christopher D Manning. 2015. A large annotated corpus for learning natural language inference. arXiv preprint arXiv:1508.05326.
[7] Ivan Vendrov, Ryan Kiros, Sanja Fidler, and Raquel Urtasun. 2015. Orderembeddings of images and language. arXiv preprint arXiv:1511.06361.
[8] Lili Mou, Men Rui, Ge Li, Yan Xu, Lu Zhang, Rui Yan, and Zhi Jin. 2015. Recognizing entailment and contradiction by tree-based convolution. arXiv preprint arXiv:1512.08422. [Pennington et al.2014] Jeffrey Pennington,
[9] Samuel R Bowman, Jon Gauthier, Abhinav Rastogi, Raghav Gupta, Christopher D Manning, and Christopher Potts. 2016. A fast unified model for parsing and sentence understanding. arXiv preprint arXiv:1603.06021.