پردازش زبان طبیعی جذاب است! قسمت سوم

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

توضیح پیش بینی های مدل

در این مجموعه ها ما یاد می گیریم که چگونه برنامه هایی بنویسیم که متن های انگلیسی نوشته شده توسط بشر را متوجه شوند. در قسمت اول، یاد گرفتیم که چگونه از یک پایپ لاین NLP برای متوجه شدن یک جمله با جدا ساختن گرامر آن با سختی و زحمت، استفاده کنیم. در قسمت دوم ما دیدیم که همیشه هم نیاز نداریم تا کار سخت تجزیه گرامر جمله را انجام دهیم. در عوض ما می توانیم با قالب بندی سوال خود به عنوان یک مساله کلاسه بندی متن، تقلب کنیم. اگر ما بتوانیم یک قسمتی از متن را به  دسته ی صحیحی طبقه بندی کنیم، به این معناست که ما به نوعی متوجه شدیم که متن چه می گوید.

برای مثال, ما می توانیم معنا ی نظرات مربوط به رستوران ها را با آموزش یک کلاسه بند برای پیش بینی یک درجه بندی ستاره ای ( از ۱ تا ۵ ) فقط بر پایه متن نظر، استخراج کنیم :

کلاسه بندی نظرات رستوران
“درک” نظرات رستوران با کلاسه بندی متن تحت عنوان “۱ ستاره” ، “۲ ستاره” ، “۳ ستاره” ، “۴ ستاره” یا “۵ ستاره”.

اگر یک کلاسه بند بتواند نظرات هر رستورانی را بخواند و به طور قابل اعتمادی، یک درجه بندی ستاره ای به آن نسبت دهد که به طور دقیقی بازتاب دهد که یک فرد به طور مثبت یا منفی راجع به رستوران تعریف می کند، این کار تایید می کند که ما توانسته ایم معنا و مفهوم را از متن انگلیسی استخراج کنیم!

ولی اشکال استفاده از یک کلاسه بند این است که ما معمولاً هیچ نظری راجع به اینکه چرا مدل هر بخش از متن را این گونه طبقه بندی می کند, نداریم . کلاسه بند یک جعبه سیاه است.

مشکل قابل تفسیر بودن مدل مدت ها به عنوان یک چالش در یادگیری ماشین بوده است. بعضی اوقات داشتن مدلی که به خوبی کار می کند ولی ندانستن چگونگی کارکرد آن، به اندازه کافی خوب نیست. ولی به لطف تکنیک های جدیدی مانند LIME ، ما حالا راه هایی برای دیدن درون این جعبه سیاه داریم. بیایید یاد بگیریم چگونه متوجه شویم که مدل ما به چه چیزی فکر می کند!

کلاسه بندی متن ، یک راه تقلب برای متوجه شدن زبان است

در قسمت دوم، ما یک کلاسه بند متن ساختیم که می تواند متن نظرات رستوران ها را بخواند و پیش بینی کند که نظر دهنده چقدر آن را پسندیده یا نپسندیده است.

برای انجام این کار ما میلیون ها نظر رستوران از Yelp.com جمع آوری کردیم و بعد یک کلاسه بند متن با استفاده از fastText فیسبوک آموزش دادیم که بتواند به راحتی هر نظر را به عنوان یک ستاره ۲ ستاره ۳ ستاره ۴ ستاره یا ۵ ستاره کلاسه بندی می کند:

آموزش مدل کلاسه بندی متن با نظرات رستوران

سپس ما از مدل آموزش دیده برای خواندن نظرات جدید رستوران ها و پیش بینی این که کاربر چقدر رستوران را  پسندیده است، استفاده کردیم:

کلاسه بندی نظر منفی رستوران

این بیشتر شبیه یک قدرت جادویی است! با استفاده از تعداد زیادی از داده ها و یک الگوریتم کلاسه بندی آماده ، ما یک کلاسه بند ساختیم که به نظر می رسد که بتواند انگلیسی را متوجه شود. و بهتر از همه اینکه ما به همه این ها را بدون نوشتن حتی یک خط کد برای تجزیه ساختار جمله انگلیسی و گرامر، دست یافتیم:

خب مشکل حل شد درست است؟ ما یک جعبه سیاه جادویی ساختیم که می تواند زبان بشر را متوجه شود. چه کسی اهمیت می دهد که چگونه کار می کند!

ولی به چه کسی می توانید اطمینان کنید؟

فقط به خاطر اینکه ما یک مدل از نوع جعبه سیاه داریم که به نظر می رسد کار می کند، دلیل نمی شود که ما کورکورانه به آن اعتماد کنیم! مدل های کلاسه بندی تمایل دارند تا ساده ترین ویژگی ها را در داده هایی که می توانند برای کلاسه بندی استفاده کنند، پیدا کنند. به همین خاطر، واقعا ساده و آسان است که یک کلاسه بند را به صورت تصادفی ایجاد کنیم که اینگونه جلوه می کند که کار می کند ولی در واقع به آن گونه که ما فکرش را می کنیم، کار نمی کند.

برای مثال, شاید کاربرانی که عاشق رستوران هستند، تمایل داشته باشند تا یک نظر کوتاه مانند این بنویسند “I love this place!” ولی کاربرانی که از یک رستوران به شدت متنفر هستند، صفحه ها گله و شکایت خواهند نوشت زیرا آن ها بسیار عصبانی هستند. چگونه بدانیم که مدل کلاسه بند ما واقعاً لغات موجود در نظر را متوجه می شود و نظرات را به طرز ساده ای و بر اساس طول آن ها طبقه بندی نمی کند؟

جواب این است که ما نمی دانیم! درست شبیه یک دانش آموز تنبل، ممکن است که کلاسه بند ما هم یک راه میانبر را انتخاب کند و واقعا چیز مفیدی یاد نگیرد. برای رسیدن به اطمینان در مدل, نیاز است تا ما قادر به درک این باشیم که چرا آن کلاسه بند یک پیش بینی را انجام می دهد.

نگاه به درون یک مدل یادگیری ماشین پیچیده

برای انواع مدل های یادگیری ماشین مانند رگرسیون خطی ، ما می توانیم به خود مدل نگاه کنیم و به سادگی متوجه شویم که چرا مدل یک پیش بینی را ارائه می دهد. برای مثال, تصور کنید که ما مدلی داشتیم که قیمت یک خانه را فقط طبق اندازه خانه، پیش بینی می کرد:

پیش بینی قیمت خانه

مدل، ارزش مالی خانه را با برداشتن اندازه خانه بر حسب مساحت و ضرب آن در وزن ۴۰۰ پیش بینی می کند. به عبارت دیگر خود مدل به ما می گوید که فضای هر فوت مربع ارزش ۴۰۰ دلار در ارزش اضافه می باشد. مدل های خطی مانند این را  بسیار آسان می توان متوجه شد زیرا  وزن ها  توضیح داده شده اند. ولی در بسیاری از مدل های یادگیری ماشین مدرن مانند fastText تعداد زیادی از متغیر ها و وزن ها در مدل برای درک انسان از چیزی که در حال رخ دادن است، وجود دارند.

بیایید به یک مثال که fastText چگونه متن را کلاسه بندی می کند نگاه کنیم تا بفهمیم چرا متوجه شدن آن تقریباً غیر ممکن است. بیاید از مدلمان بخواهیم تا یک درجه بندی ستاره های به این جمله نسبت دهد “I didn’t love this place :(” :

ابتدا، fastText متن را به بخش های جداگانه خواهد شکست:

کلاسه بندی متن توکن سازی

بعد، fastText معنی هر یک از این بخش ها را جستجو خواهد کرد. وقتی کلاسه بند برای اولین بار آموزش دید، fastText مجموعه ای از اعداد (که بردار لغت نام دارد) را به هر لغت که در داده آموزشی حداقل یکبار ظاهر شده نسبت می دهد. این اعداد، “معنی” هر لغت ها به عنوان یک نقطه در یک فضای ۱۰۰ بعدی خیالی، کد نگاری می کنند. نظریه اینگونه است که لغاتی که مفاهیم مشابهی را نمایش می دهند، مجموعه مشابهی از اعدادی که نمایش دهنده ی آن ها هستند را خواهند داشت و لغاتی که معنی های بسیار متفاوتی دارند مجموعه ای بسیار متفاوتی از اعدادی که  نمایش دهنده ی آن ها هستند را خواهند داشت.

اینجا نگاهی داریم بر اعداد واقعی از fastText که معنی هر قسمت را در جمله ما نمایش می دهند:

بردار لغت ها کلاسه بندی متن
معنی هر لغت توسط صد ارزش، کدگذاری شده است. فقط ۱۵ تای اول یا بیشتر در اینجا نشان داده شده اند، ولی تصور کنید که نمودار به فعالیت خود ادامه دهد تا همه ۱۰۰ ارزش را نشان دهد.

سپس، fastText از ستون های عمودی اعداد نمایش دهنده هر لغت میانگین می گیرد تا یک نمایش ۱۰۰ عددی از معنای کل جمله که بردار سند نام دارد ، به وجود آورد  :

بردار سند کلاسه بندی متن
صد ارزشی که جمله “I didn’t love this place :(” را نمایش می دهند، میانگینی از ۱۰۰ ارزشی هستند که هر لغت را نمایش می دهند. این نمایش یک” بردار سند” نام دارد.

نهایتاً این ۱۰۰ ارزشی که جمله را نمایش می دهند، به عنوان یک ورودی به مدل کلاسه بند خطی می باشند که درجه بندی ستاره ای نهایی را نسبت می دهد:

رمز نگاری جمله کلاسه بندی متن

با وجود این که درجه بندی نهایی توسط یک کلاسه بند خطی نشان داده شده است, مدل درجه بندی را بر پایه ۱۰۰ عدد ظاهراً تصادفی که در واقع از ۹۰۰ عدد متفاوت مشتق شده اند، نشانه گذاری می کند. تقریباً برای یک انسان غیر ممکن است که به صورت برگشتی متوجه شود آن اعداد چه چیزی را نمایش می دهند و ما  چرا این نتیجه را دریافت کرده ایم.

انسان ها نمی توانند تجسم کنند گوشه ای از میلیون ها نقطه در فضاهای ۱۰۰بعدی چه چیزی وجود دارد.

این یک مشکل خیلی بزرگ در یادگیری ماشین است. اگر ما از یک مدل یادگیری ماشین برای انجام کار مهمی استفاده می کنیم، نمی توانیم کورکورانه قبول کنیم که آن به خوبی و به طرز صحیحی کار می کند . و حتی اگر ما مدل  را روی  یک مجموعه داده  آزمایشی، تست کنیم و از این سنجش یک امتیاز خوب بگیریم، نمی دانیم که مدل ما روی داده ای که با مجموعه داده آزمایشی ما کاملا متفاوت است, چگونه رفتار خواهد کرد.

خب اگر یک مدل بسیار پیچیده است و ما نمی توانیم آن را متوجه شویم، چطور امکان دارد که ما پیش بینی های آن را توضیح  دهیم؟

ما به یک بدلکار نیاز داریم!

در سال  ۲۰۱۶مارکو تالیو ریبریتو، سامر سینگ و کارلوس جسترین یک مقاله با عنوان “من چرا باید به شما اعتماد کنم”؟  منتشر کردند که رویکرد جدیدی برای درک مدل های پیچیده که LIME نام دارد، تولید کرد ( LIME شکل اختصاری Local Interpretable  Model- Agnostic Explanation می باشد ).

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

استفاده از تکنیک lime برای شبیه سازی مدل اصلی

ولی این احتمال یک سوال واضح را به وجود می آورد – چرا یک مدل ساده به عنوان یک جانشین قابل اعتماد برای یک مدل پیچیده کار می کند؟ پاسخ این است که  با وجود این که که مدل ساده نمی تواند همه منطق مدل پیچیده برای پیش بینی ها را به دست آورد، نیازی نیز به آن ندارد! تنها به این نیاز داریم مدل ساده حداقل بتواند از منطقی که مدل پیچیده از آن برای یک پیش بینی استفاده می کند، تقلید کند.

ترفند این کار در این است که چگونه مدل جانشین را آموزش می دهیم. به جای آموزش آن در کل مجموعه داده که ما مدل اصلی را با آن آموزش می دادیم، فقط نیاز داریم آن را روی تعداد کافی از داده ها آموزش دهیم، در نتیجه مدل می تواند به طرز صحیحی یک جمله را کلاسه بندی کند – “I didn’t love this place :(” . تا زمانی که مدل این جمله را با استفاده از همان منطق یکسان مدل  اصلی کلاسه بندی می کند، به عنوان یک مدل جانشین برای توضیح پیش بینی عمل خواهد کرد.

برای ایجاد داده به منظور آموزش مدل جانشین، ما تعداد زیاد و متفاوتی از جمله “I didn’t love this place :(” را به مدل اصلی می دهیم:

پیش بینی متن با مدل fastText آموزش دیده
مستند سازی منطق کلاسه بند پیچیده fastText با درخواست از آن برای پیش بینی هایی برای هزاران نوع مختلف برای این جمله ما “I didn’t love this place :(”.

ما از مدل درخواست خواهیم کرد تا جمله را با حذف کلمات مختلف بارها و بارها کلاسه بندی کند،, تا ببینیم چگونه پاک شدن هر لغت پیش بینی نهایی را تحت تاثیر قرار می دهد. با درخواست از کلاسه بند برای پیش بینی تعداد مختلفی از جمله یکسان، ما این که چگونه مدل جمله را متوجه می شود را بررسی می کنیم.

سپس ما گونه های مختلف جمله و نتایج پیش بینی کلاسه بند را به عنوان داده آموزشی جهت آموزش مدل جانشین جدید, استفاده خواهیم کرد:

روش line مدل جایگزین کلاسه بندی متن
مدل جانشین آموزش دیده است تا پیش بینی های یکسان را که مدل واقعی برای همه گونه های مختلف جمله ما انجام داده است, جایگذاری کند.

و بعد، ما می توانیم پیش بینی اصلی را با نگاه کردن به وزن های مدل جانشین ساده، توضیح دهیم. زیرا مدل جانشین کلاسه بند خطی ساده است که پیش بینی ها را با نسبت دادن یک وزن به هر لغت، به وجود می آورد، ما می توانیم به راحتی به وزن هایی که به هر لغت نسبت داده شده است، نگاه کنیم تا متوجه شویم که هرلغت چگونه پیش بینی نهایی را تحت تاثیر قرار داده است.

توضیحی که ما برای پیش بینی ایجاد خواهیم کرد، چیزی شبیه به این است:

تاثیر کلمات بر پیش بینی مدل کلاسه بندی متن

هر چقدر که رنگ قرمز تیره تر باشد، وزنی که لغت دراین جمله برای گرفتن درجه بندی” ۲ ستاره “داشته، بیشتر است . ما می بینیم که عبارت” دوست نداشتم” و ایموجی صورت اخمو سهم بزرگی داشتند و کلمات دیگر تاثیری نداشتند. با توجه به این، به نظر می رسد که مدل لغات صحیح را سنجش می کند،  و ما می توانیم به پیش بینی اعتماد داشته باشیم.

به خاطر داشته باشید که فقط به این خاطر که ما در حال توضیح دادن این پیش بینی بر این پایه که  هر لغت چقدر نتیجه را تحت تاثیر قرار داده است، هستیم، به این معنی نیست که مدل fastText فقط تک لغت ها را در نظر می گیرد. فقط به این معناست که در این مورد خاص، لغاتی که در این متن ظاهر می شوند, بیشتر اهمیت دارند .خب با وجود اینکه مدل fastText بسیار پیچیده است و در پیش بینی های خود ترتیب لغات را نیز در نظر می گیرد، نیازی نیست تا توضیح این پیش بینی آنقدر پیچیده شود. این یکی از دیدگاه های LIME می باشد.

LIME مرحله به مرحله

بیایید یک مثال واقعی از الگوریتم LIME را در نظر بگیریم تا یک پیش بینی واقعی از کلاسه بند fastText خودمان را توضیح دهیم. ولی برای اینکه همه چیز را جذاب تر کنیم، بیایید متن نظر خود را کمی گسترش دهیم. به جای اینکه فقط جمله “I didn’t love this place :(” را داشته باشیم، بیایید نظر رستوران خود را به این سه جمله, گسترش دهیم:

I didn’t love this place 🙁 The food wasn’t very good and I didn’t like the service either. Also, I found a bug in my food.

اول ما خواهیم دید که مدل fastText ما چند ستاره به این بررسی نسبت خواهد داد، و بعد ما ازLIME برای توضیح اینکه چگونه ما این پیش بینی را به دست آوردیم، استفاده خواهیم کرد.

گام ۱ : ایجاد پیش بینی اولیه توسط fastText

گام اول برای وارد کردن این نظر به کلاسه بند fastText می باشد. اینجا امتیازات ممکن را می بینید که ما از fastText برای هر عدد ممکن از ستاره ها، به دست آوردیم:

احتمالات پیش بینی

بسیار عالی، مدل به نظر ما دو ستاره با ۷۴ درصد احتمال صحت داد. اینگونه به نظر می رسد که صحیح است، آن هم بر پایه متن  و اینکه  چگونه مردم تمایل به امتیاز دهی به نظرات Yelp دارند، ولی ما هنوز هم نمی دانیم که چگونه به این پیش بینی رسیده است. بیایید برای یافتن پاسخ است از LIME استفاده کنیم!

گام ۲ : ایجاد انواع مختلفی از نظر

گام اول در LIME ایجاد هزاران نوع مختلف از متن است که ما لغات مختلف را از متن حذف کنیم.  اینجا برخی از ۵ هزار انواع مختلفی را می بینید که LIME به صورت خودکار از نظر ما به وجود خواهد آورد:

انواع مختلف جمله نظر رستوران

گام ۳ : پیش بینی ها را توسط مدل اصلی به وجود آورید

گام بعدی اجرای این هزاران نوع مختلف از متن در مدل کلاسه بندی fastText اصلی ما است تا ببینیم چگونه هر کدام را کلاسه بندی می کند:

پیش بینی برای انواع مختلف جمله

ما نتیجه پیش بینی را برای هر نوع مختلف متن ذخیره خواهیم کرد تا از آن به عنوان یک داده آموزشی برای مدل جایگزین استفاده کنیم.

گام ۴ : آموزش مدل جایگزین

داده ای که ما در مرحله دوم به وجود آوردیم،  مجموعه داده آموزشی جدید ما می شود. ما از آن برای آموزش یک کلاسه بند خطی که از رفتار کلاسه بند اصلی تقلید می کند، استفاده خواهیم کرد. ما انواع مختلف جمله را به کلاسه بند می دهیم و از آن می خواهیم تا همان درجه بندی ستاره ای را پیش بینی کند.

به صورت پیش فرض، LIME کلاسه بند خطی جایگزین را با استفاده از پیاده سازی کلاسه بندی مرزی رگراسیون که در کتابخانه scikit- learn قرار داده شده است, می سازد. ولی شما اگر خواستید، می توانید LIME  را برای استفاده از یک الگوریتم کلاسه بندی متفاوت، پیکر بندی کنید. و هر نوع از کلاسه بند خطی باید تا زمانی که یک وزن به هر لغت در متن نسبت دهد، درست کار کند.

گام ۵ : مدل جایگزین را با توضیح پیش بینی اصلی، امتحان کنید

حالا که مدل جایگزین آموزش دیده است، ما می توانیم پیش بینی را با نگاه کردن به هر لغت  از متن اصلی که بیشترین وزن را در مدل دارد، توضیح دهیم.

LIME می تواند یک تجسم کلمه ای از هر کلمه ای که در پیش بینی, بیشترین اثر را داشته است، ایجاد کند:

تاثیر کلمات در پیش بینی
حرف “t” بیشترین اثر را داشته است. این به این خاطر است که t از didn’t آمده است و برای مدل نشانه ای است که شما در حال منفی کردن لغت بعدی آن هستید.

این لغات به خودی خود به ما یک تصویر عالی از اینکه چه چیزی در مدل اتفاق می افتد، نمی دهند. ولی LIME همچنین می تواند یک تجسم تولید کند که هر لغت را بر پایه اینکه آن چقدر پیش بینی را به صورت مثبت یا منفی تحت تاثیر قرار داده ، به صورت رنگی کد نگاری کند:

تاثیر کلمات در پیش بینی جمله

در این نمودار، لغات سبز باعث می شوند تا کلاسه بند فکر کند که نظر بیشتر منفی بوده است درحالیکه لغات آبی باعث می شوند که بررسی بیشتر مثبت به نظر برسد.

می توانیم ببینیم که کلمه “good” به خودی خود یک سیگنال مثبت است ولی  عبارت “food wasn’t very good” یک سیگنال بسیار منفی است. و t یک نوع سیگنال منفی است زیرا آن کلمه “good” را خنثی می کند. ما همچنین می توانیم ببینیم که کلمه bug یعنی حشره، یک سیگنال منفی است – که در نظر رستورانی، منطقی به نظر می رسد!

طبق این توضیح, ما یک نظر خیلی بهتر داریم که چرا کلاسه بند به این نظر یک امتیاز پایین داد. و به لطف LIME ما می توانیم همان کار را با هر نظر دیگری انجام دهیم – حتی آن هایی که پیچیده تر از این مثال ساده هستند.

اینجا یک نظر رستوران واقعی را می بینید که من آن را نوشته ام و مدل fastText ما به طرز صحیحی آن را به عنوان یک بررسی ۴ ستاره ای  پیش بینی می کند:

نظر منفی به رستوران

از دیدگاه NLP تجزیه این نظر بسیار اذیت کننده و سخت است. همه جملات تعدادی توصیف کننده دارند. ولی به نظر می رسد که کلاسه بندfastTex t ما، آن را  به درستی متوجه می شود و به درستی ۴ ستاره را پیش بینی می کند. بیایید ببینیم چرا.

اینجا تجسمی از LIME را می بینید:

متن هایلایت شده

تنظیمات LIME پیش فرض از رنگ های رندوم برای تجسم استفاده می کند، پس در این تصویر، رنگ بنفش نشان دهنده حالت مثبت است. در کلاسه بند عبارات مثبتی مانند “pretty great” ، “good food”  و “comfy” به عنوان سیگنال هایی هستند که این بررسی  را مثبت نشان می دهند. همچنین کلماتی مانند “cool” و “reasonable” را نیز به عنوان سیگنال های مثبت انتخاب می کند. همه آن ها منطقی به نظر می رسند!

ولی به خاطر داشته باشید که این توضیح به این معنا نیست که همه ی  آنچه که مهم است، عباراتی  مانند “pretty great” و “good food” که در این متن ظاهر شده اند، هستند. بلکه به این معناست که آن لغات در متن داده شده، اهمیت بیشتری دارند. این یک تمایز مهم است که باید هنگام نگاه کردن به این تجسم، در خاطر داشته باشید.

خودتان LIME را امتحان کنید

شما می توانید این کار را خودتان امتحان کنید. بعد از این که کلاسه بند fastText را که در قسمت دوم خواندیم, آموزش دادید، می توانید از کد زیر برای توضیح یک نظر رستوران توسط LIME استفاده کنید.

قبل از اجرای این کد, شما نیاز دارید تا LIME را نصب کنید:

pip3 install lime

شما می توانید به سادگی این کد را اجرا کنید. وقتی که اجرای آن تمام شد، یک تصویر از پیش بینی باید به صورت خودکار در مرورگر شما باز شود .

شما می توانید دقیقا همین کار را برای هر کلاسه بند fastText دیگر بکار ببرید. فقط مسیر را در خط ۲۲ به روز رسانی کنید، اسامی برچسب در خط ۳۴ و متن برای توضیح در خط ۶۰ می باشند. و اگر کلاسه بند شما بیش از ۱۰ کلاس ممکن داشته باشد, عدد را به خط ۴۸ اضافه کنید.

اگر این مطلب را دوست داشتید، دیدگاه خود را در قسمت نظرات با ما به اشتراک بگذارید.

بیشتر بخوانید :

منبع Medium

درباره‌ی احمدرضا جعفری

همچنین ببینید

آیا می خواهید در زمینه یادگیری ماشین استخدام شوید؟

آیا می خواهید در زمینه یادگیری ماشین استخدام شوید؟

مسیر های شغلی زیادی در حوزه یادگیری ماشین وجود دارد، اما از کجا بفهمیم که …

3 نظر

  1. سلام. لینک مقاله ی اصلی رو هم میشه قرار بدین؟ ممنون از ترجمه‌ی خوبتون.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *