یادگیری نورون مصنوعی
در دومین جلسه از دوره آموزش یادگیری عمیق رایگان هوسم میخواهیم نحوه یادگیری نورون مصنوعی را بررسی کنیم. نورون مصنوعی که در جلسه قبل معرفی کردیم، صرفا یک ماشین حساب بودند. آنها توانایی یاد گرفتن نداشتند. در این جلسه میخواهیم با پروسه یادگیری یک نورون آشنا شویم. مفاهیمی که در این جلسه بررسی میشوند عبارتند از بهینه سازی در شبکه عصبی ، تابع اتلاف در شبکه عصبی و نرخ یادگیری در شبکه عصبی. همچنین در این جلسه نحوه انجام محاسبات آموزش یک نورون را بررسی خواهیم کرد. با هوسم همراه باشید…
یادآوریِ ساختار نورون مصنوعی
در جلسه قبل با ساختار یک نورون مصنوعی آشنا شدیم. گفتیم که یک نورون مصنوعی ورودیها را دریافت کرده و به صورت وزندار با هم جمع میکند. سپس نتیجه را از یک تابع فعالساز عبور میدهد. در شکل زیر ساختار نورون مصنوعی که معرفی کردیم آورده شده است:
حالا بیایید با یک مثال نحوه یادگیری نورون مصنوعی را مرور کنیم. فرض کنید دادههای زیر به ما داده شده است:
همانطور که مشاهده میکنید نمونهها اعدادی از 2 تا 8 هستند. برچسبها یا labelها هم اعداد 4، 6، 8، … و 16 هستند. خب هدف ما چیست؟ هدف، یادگیری نورون مصنوعی است. یعنی نورون بتواند خروجیهای موردنظرمان یعنی اعداد 4، 6 و … را تولید کند. ما اینجا یک ورودی و یک خروجی داریم. شاید برایتان سوال باشد که چرا یک ورودی، در صورتی که ما 7 تا x داریم؟ در جواب باید بگوییم که ما 7 نمونه یا sample داریم نه 7 ورودی. دراینجا، ما یک ورودی و یک خروجی داریم. مثلا نمونه 2 منجر به خروجی 4 شده است. یا نمونه 7 منجر به خروجی 14 شده است.
نکته برچسب در شبکه عصبی یعنی چه؟ برچسب به معنای مقدار مطلوب است. یعنی مقدار درستی که ما میخواهیم نورون بتواند آن را تخمین بزند. برای اطلاعات بیشتر در مورد لیبل، پیشنهاد میکنیم آموزش یادگیری ماشین چیست را مطالعه بفرمایید.
برای ساده کردن مسئله، بایاس را صفر و تابع فعالساز را خطی در نظر میگیریم. در این صورت شکل 2 به صورت زیر خلاصه خواهد شد:
خب در اینجا نورون باید پارامتر w و b را طوری محاسبه میکرد که خروجی yp (خروجی پیشبینی شده توسط نورون) با خروجی yt (خروجی مطلوب) یکسان شود. یا اگر نتوانست یکسان شود، حداقل به yt نزدیک باشد! ما در جلسه قبل داشتیم: yp = w*x+b. گفتیم برای شروع باید یک مقدار اولیه به پارامترها اختصاص دهیم. بایاس را که صفر گذاشتیم، w را هم برابر با یک قرار میدهیم. به این کار مقداردهی اولیه (initialization) گفته میشود. در این صورت برای w=1 و b=0 مقدار yp به صورت زیر محاسبه خواهد شد:
ما مقادیر را محاسبه کردیم و در ستون yp از جدول بالا قرار دادیم. خب که چه؟ الان چه کار کنیم؟ صرفا با فرمولی که داشتیم 7 تا ورودی دادیم و 7 تا خروجی گرفتیم. حالا چطور قرار است یک نورون از این اعداد چیزی یاد بگیرد؟ آیا میتوان با مقایسه yp و yt به نتیجهای رسید؟ یعنی ما ببینیم که yp چقدر از yt دور هست. آنگاه بر اساس این فاصله وزنها را تغییر بدهیم تا به خروجی مطلوب برسیم. به نظرتان این گفته منطقی است؟
نکته در yp ، حرف p مخفف کلمه predicted یعنی پیشبینی شده و در yt حرف t مخفف کلمه target یعنی هدف است.
تابع اتلاف یا تابع هزینه یا تابع هدف در شبکه عصبی
احتمالا با سنسور دنده عقب اتومبیل آشنا هستید. این سنسور فاصله عقب ماشین را از مانعهای پشت ماشین میسنجد. سپس نتیجه را با بوق زدن به ما میفهماند. البته آدم را دیوانه هم میکند! 🤦♂️ اگر مانعی پشت ماشین نباشد، اصلا بوق نمیزند. اگر به مانعی نزدیک شویم شروع به بوق زدن متناوب میکند. و اگر دیگر خیلی خیلی به مانع نزدیک شویم تبدیل به بوق ممتد خواهد شد! در واقع سنسور دنده عقب فاصله میان اتومبیل ما و مانع را به بوق ممتد تبدیل میکند. بر اساس فاصله بین بوقها به ما میگوید که چقدر با مانع فاصله داریم. شاید سنسور دنده عقب اتومبیل را بتوان یک نوع تابع اتلاف محسوب کرد!
در شبکه عصبی برای محاسبه میزان فاصله میان خروجی پیش بینی شده توسط شبکه و خروجی مطلوب، از تابع اتلاف استفاده میشود. در بخش قبلی گفتیم که ما نیاز داریم بدانیم که خروجی پیشبینی شده یعنی yp چقدر از خروجی مطلوب یعنی yt دور هستند. یکی از راهحلها استفاده از تابع اتلاف است. تابع اتلاف، مقدار خروجی شبکه و مقدار خروجی مطلوب را دریافت کرده و فاصله میان آن دو را حساب میکند. به خروجی تابع اتلاف خطا یا Error گفته میشود. ایدهآل ما این است که خطا صفر باشد. حالا ممکن است هیچوقت این خطا صفر نشود! اما هرچقدر به صفر نزدیکتر باشد، یعنی خروجی شبکه به خروجی مطلوب ما نزدیکتر است.
توابع اتلاف انواع مختلفی دارند. ما در این جلسه تنها یک تابع اتلاف را معرفی میکنیم چون میخواهیم به صورت کلی با فرآیند آموزش شبکه آشنا شوید. در جلسات آینده به صورت جداگانه انواع توابع اتلاف را بررسی خواهیم کرد. یکی از سادهترین توابع اتلاف در شبکه عصبی، تابع MSE یا Mean Squared Error یا میانگین مربعات خطا است. فرمولی که برای MSE وجود دارد به شکل زیر است:
همانطور که مشاهده میکنید خروجی مطلوب یعنی yt از خروجی شبکه یعنی yp کم شده سپس به توان 2 رسانده شده است. به ازای هر نمونه، یک خروجی (yp) داریم. و به ازای هر خروجی، یک خطا خواهیم داشت. سپس مقدار خطای همه نمونهها با هم جمع شده و خطای میانگین شبکه محاسبه شده است. به این ترتیب ما درکی نسبی از عملکرد شبکه خواهیم داشت. به این شکل که هرچقدر خطا کمتر باشد، احتمالا عملکرد شبکه بهتر است و هرچقدر که خطا بیشتر باشد، شبکه عملکرد خوبی نخواهد داشت.
گفتیم MSE یک از سادهترین توابع اتلاف است که در این جلسه معرفی شد. توابع اتلاف دیگری نیز وجود دارند که بسته به مساله میتوانیم از آنها استفاده کنیم. چند تابع اتلاف رایج عبارتند از:
- میانگین مربعات خطا (MSE)
- میانگین قدرمطلق خطا (MAE)
- میانگین جذر مربعات خطا (RMSE)
- تابع اتلاف Hinge
- تابع اتلاف Binary Cross Entropy
- تابع اتلاف Multi Cross Entropy
- تابع اتلاف Triplet
- و … .
برگردیم به مثالی که داشتیم. اگر بخواهیم خطای MSE را برای شبکه خودمان محاسبه کنیم، باید بنویسیم:
خب میبینید شبکه تکنورونی ما خطای MSE برابر با 29 دارد. خطای زیادی است درست است؟ تا صفر فاصله خیلی زیادی وجود دارد. چطور این فاصله باید کم شود؟ سنسور دنده عقب را در نظر بگیرید. زمانی که بوق نمیزند ما با فشار بیشتری پدال گاز را فشار میدهیم. اما زمانی که شروع به بوق زدن میکند پایمان را کمی از پدال گاز برمیداریم تا سرعت کم شود. در نهایت اگر بوق ممتد بشنویم، سریعا خودرو را متوقف میکنیم. در اینجا هم ما به دنبال چنین چیزی هستیم. یعنی میخواهیم نورون، وزنها را طوری تغییر دهد که خطا به سمت صفر رود. اگر فاصله تا صفر زیاد باشد با سرعت بیشتری وزنها را تغییر دهد. اگر هم فاصله تا صفر کم باشد سرعت تغییر وزنها را کم کند. در نهایت آنقدر وزنها را تغییر دهد که به مقصد یعنی خطای صفر برسیم. در شبکه عصبی این کار بر عهده بهینهساز یا optimizer است. در بخش بعدی با مفهوم بهینهسازی آشنا خواهیم شد.
مقدار خطای MSE نورون برابر با 65.25 است.
الگوریتم های بهینه سازی در شبکه عصبی
بهینه سازی یک تابع در ریاضیات، معمولا به این معنا است که پارامترهای تابع مورد نظرمان را طوری انتخاب کنیم که آن تابع مینیمم یا ماکزیمم شود. در بخش قبل گفتیم هدفمان این است که وزنهای شبکه را طوری تغییر دهیم که تابع اتلاف صفر شود. خب پس یک الگوریتم بهینهسازی میتواند هدف ما را برآورده سازد. یک الگوریتم بهینهسازی روشی است که به صورت تکراری (iterative) انجام میشود تا یک راه حل بهینه حاصل شود. یعنی در شبکه عصبی ما به الگوریتمی نیاز داریم که وزنها را آنقدر تغییر دهد تا به کمترین اتلاف برسیم. پس لزومی ندارد که با یک بار تغییر وزن ها به جواب برسیم. در مسائل پیچیده ممکن است فرآیند بهینه سازی هزاران بار تکرار شود و در نهایت تازه به یک خطای قابل قبول برسد نه خطای صفر! به بیان ریاضی در شبکه عصبی ما انتظار داریم:
w(𝜏+1) = w(𝜏) + Δw(𝜏)
معادله 2
که در آن w(𝜏) مقدار وزن در iteration یا تکرار 𝜏ام ، w(𝜏+1( مقدار وزنها در تکرار (𝜏+1)ام و Δw(𝜏) مقدار تغییر وزنها در یک تکرار هست. معادله 2 میگوید در تکرار جدید، میخواهم وزنها را به اندازه Δw(𝜏) تغییر دهم. نکته اینجاست که همانند مثال ماشین که با افزایش صدای بوق، سرعت ما کم میشد، اینجا هم Δw(𝜏) به مرور با کاهش اتلاف کوچکتر میشود. دقت کنید Δw(𝜏) تابعی از 𝜏 است، یعنی تابعی از زمان یا تکرار هست. یعنی به مرور زمان تغییر میکند. الگوریتمهای بهینه سازی متعددی وجود دارند. چند الگوریتم بهینه سازی در شبکه عصبی عبارتند از:
- گرادیان کاهشی (Gradient Decent)
- گرادیان کاهشی با مومنتوم (Gradient Decent with Momentum)
- Adagrad
- RMSprop
- Adam
- و …
توجه در ادامه بهصورت مختصر درباره گرادیان کاهشی بهعنوان یک بهینه ساز خوب و ساده توضیح دادهایم. اگر توضیحات ادامه درباره گرادیان کاهشی را متوجه نشدید، یک پست جذاب را به شما پیشنهاد میدهیم. حتما به آموزش گرادیان کاهشی سر بزنید.
گرادیان کاهشی
الگوریتم گرادیان کاهشی سادهترین رویکرد را در استفاده از گرادیان برای آپدیت وزنها ارائه میدهد. رابطه ریاضی برای این بهینه ساز به شکل زیر است:
w(𝜏+1) = w(𝜏)− η∇E(w(𝜏))
معادله 3
که در آن η نرخ یادگیری و E(w(𝜏) خطا در iteration یا تکرارِ 𝜏 است. همانطور که مشاهده میکنید، گرادیان خطا در تکرارِ 𝜏 محاسبه شده و در η ضرب میشود. نتیجه در 1- ضرب خواهد شد. چرا؟ به شکل 4 نگاه کنید؛ چون ما میخواهیم مقدار خطا مینیمم شود. به همین دلیل باید در خلاف جهت گرادیان حرکت کنیم تا به نقطه مینیمم برسیم. الگوریتم گرادیان کاهشی میگوید با استفاده از وزن اولیه گرادیان خطا را محاسبه کن. سپس گرادیان خطا را در نرخ یادگیری ضرب کرده و مقدار به دست آمده را از وزنهای فعلی کم کن. در این نقطه تکرار یا iteration اول تمام شده و وارد تکرار دوم میشویم. در تکرار دوم، گرادیان خطا را با وزنهای جدید محاسبه کرده و در نرخ یادگیری ضرب میکنیم. سپس مقدار بدست آمده را از وزنها کم میکنیم. به همین ترتیب این فرآیند را تا آنجا ادامه میدهیم که خطا مینیمم شود. در شکل زیر این فرآیند به صورت فرضی نشان داده شده است.
نرخ یادگیری در شبکه عصبی چیست؟
نرخ یادگیری یا learning rate در شبکه عصبی، ضریبی است که به وسیله آن میتوان مقدارِ تغییر وزنها را تنظیم کرد. یعنی اگر نرخ یادگیری بزرگ انتخاب شود، با گامهای بلندتری به سمت مینیمم حرکت خواهیم کرد. اما اگر کوچک باشد، با گامهای کوچکتری به سمت مینیمم حرکت خواهیم کرد. شاید پیش خودتان بگویید که اگر اینطور است، چه لزومی دارد که نرخ یادگیری کوچک انتخاب شود. خب آن را مقداری بزرگ بگذاریم تا زودتر به نقطه مینیمم برسیم. اما موضوع به این سادگیها هم نیست. آیا در هنگام دنده عقب، بدون کاهش سرعت باوجود بوق هشدار همانطور به مسیرمان ادامه میدهیم؟!
اگر مقدار نرخ یادگیری خیلی بزرگ انتخاب شود، نباید انتظار داشت که الگوریتم بهینهسازی حتی همگرا شود! چرا؟ چون وزنها در حال پرش هستند همیشه! یعنی اتفاقی مشابه با تصویر زیر خواهد افتاد. مشاهده میکنید که اتلاف نه تنها کم نشده، بلکه افزایش هم یافته است.
اگر هم نرخ یادگیری خیلی کوچک انتخاب شود، فرآیند آموزش شبکه بسیار طولانی خواهد شد. مثلا شبکهای که با نرخ یادگیری مناسب یک ساعت آموزشش طول میکشد، در این حالت شاید یک روز کامل طول بکشد و باز هم به نتیجه موردنظرمان نرسد. در تصویر زیر، تاثیر مقدار نرخ یادگیری بر آموزش شبکه نشان داده شده است. در این تصویر مشاهده میکنید که انتخاب نرخ یادگیری باید متناسب با مسئله باشد. این مقدار مناسب بسته به کاربردهای مختلف متفاوت است و معمولا به صورت تجربی تعیین میشود.
مثال عددی آموزش نورون
بیایید در مثالی که مشغول حل آن بودیم مطالبی که در بخش قبل یاد گرفتیم را اعمال کنیم. یعنی وزن را با استفاده از گرادیان کاهشی تغییر دهیم. معادله (3) میگوید برای تغییر وزنها نیاز است ابتدا گرادیان اتلاف را محاسبه کنیم. اگر یادتان باشد ما از اتلاف MSE استفاده کردیم. حالا باتوجه به معادله 3، باید از این اتلاف نسبت به وزنها مشتق بگیریم:
دقت کنید که ما برای ساده شدن مسئله بایاس را صفر در نظر گرفتیم. نرخ یادگیری را نیز برابر با 0.01 درنظر میگیریم و شروع به حل مسئله میکنیم. در اولین iteration یا تکرار داریم:
این فرآیند را همچنان ادامه میدهیم تا زمانی که به نتیجه مطلوب برسیم:
مشاهده میکنید هر قدمی که پیش میرویم، مقدار اتلاف کم و کمتر شده و به عدد صفر نزدیکتر میشود. وزن تقریبا 2 به دست آمد. احتمالا خیلی از شما از اول میدانستید که وزن چه باید باشد. اما با حل این مثال متوجه شدید که یک نورون ساده چه محاسباتی میکند تا بفهمد وزن درست چه هست. یعنی فرآیند یادگیری نورون مصنوعی را از صفر تا صد خودتان محاسبه کردید. اگر نمودار اتلاف را رسم کنیم خواهیم داشت:
حالا نورون ما آموزش دیده است. مقدار w برابر با 1.999 بدست آمد. حالا نورون ما میتواند با وزن جدیدی که دارد، پیشبینیهای درستی انجام دهد. مثلا الان اگر به نورون ورودی 9 را یدهیم انتظار داریم خروجی 18 بدهد درست است؟ ببینیم نورون چه تخمینی میزند:
yp = w*x+b = 1.999*9 + 0 = 17.991
مشاهده میکنید که تقریبا نتیجه را درست حدس زده است. اگر بخواهیم دقیقا 18 را تخمین بزند چکار باید بکنیم؟ باید فرآیند بهینه سازی را انقدر ادامه دهیم تا یادگیری نورون مصنوعی ، کاملتر شده و وزن به عدد 2 نزدیکتر شود.
منابع آموزش یادگیری عمیق
در فهرست زیر، تعدادی از منابع خوب آموزش یادگیری عمیق را معرفی کردهایم.
- کتاب شبکه عصبی Haykin
- دوره آموزش یادگیری عمیق هوسم
در این پست نحوه یادگیری نورون مصنوعی را بررسی کردیم. امیدوارم این آموزش مورد توجه شما قرار گرفته باشد. نظرات و سوالات خود را پایین 👇 برایمان کامنت کنید. حتما سوالات شما پاسخ داده خواهد شد.
مطالب زیر را حتما مطالعه کنید
مدل nanoGPT
شگفتانگیزترین ایده هوش مصنوعی از نظر Andrej Karpathy
شبکه ویژن ترنسفورمر
شبکه اتوانکدر
شبکه عصبی mlp
شبکه ترنسفورمر
31 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
خیلی عالی بود دمتون گرم، نشون میده که نویسنده رو موضوع مسلط هست چون مثال دنده عقب خیلی مثال دلچسبی بود.
یه پیشنهاد داشتم تابع اتلاف رو پیشنهاد میکنم همون تابع هزینه یا cost function به عنوان معادل بیارید، چون اکثرا دیدم این اسم رو بکار میگیرند
ممنون 😊🙏🌹
درود بر شما و تمام دست اندرکاران
واقعا طریقه بیان و مثالها بسیار عالی هست . پیوستگی مطالب خیلی خوب بود و باعث فهم بهتر میشود ممنونم سالم و تندرست باشید
سلام وحید عزیز
خوشحالیم که از آموزشها راضی هستید.
ممنون از اینکه وقت گذاشتید و نظر خودتون رو بیان کردید. 🌹😊
در همین مثال اگر نورون ما دو ورودی داشت الگوریتم بهینه سازی چگونه میشد؟ الگوریتم بهینه سازی بر اساس w1 مشتق میگرفت یا بر اساس w2 ؟
یعنی در هر بار تکرار یکی از وزنها تغییر داده میشد یا هر دو ؟
عالی بود
سلام وقت بخیر. من زیاد با داده کاوی و … آشنایی ندارم. برای یک کاری از شبکه عصبی پرسپترون چندلایه استفاده کردم. آیا در واقع یادگیری عمیق انجام داده ام؟
بسیار عالی بود . تنتون سالم و خدا قوت
سلام وقت به خیر
در متن جایی که گفتید ما هفت نمونه داریم یعنی در اصل یک ورودی داریم؛ ممکنه مثالی بزنید از جایی که چند ورودی داریم یعنی با رسم شکل فرق بین تعداد ورودی و تعداد نمونه مشخص بشه
عالی بود. آموزش های زیادی دیدم این از همه بهتره
فقط من در قسمت فورمولهای ریاضی یه کم مشکل دارم و نتونستم کامل روند کار رو درک کنم. راهکاری پیشنهاد میدین ؟
سلام
دو پیشنهاد:
1- چندبار این جلسه رو مطالعه کنید. کاغذ و خودکار بردارید و این محاسبات رو یک بار از ابتدا تا انتها انجام بدید.
2- دوره یادگیری عمیق 2022. توی این دوره بیشتر درباره مباحث توضیح دادیم و میتونه مفید باشه.
موفق باشید
سلام
خیلی عالی بود.
سلام وقتتون بخیر؛ در ابتدای توضیحات گفتید:
همانطور که مشاهده میکنید ( * ورودیها ) اعداد 2 تا 8 هستند. برچسبها یا labelها هم اعداد 4، 6، 8، … و 16 هستند. خب هدف ما چیست؟ هدف یادگیری نورون مصنوعی است. یعنی نورون بتواند خروجیهای موردنظرمان یعنی اعداد 4، 6 و … را تولید کند. ما اینجا —-یک— ( * ورودی ) و یک خروجی داریم. شاید برایتان سوال باشد که چرا یک ورودی، در صورتی که ما 7 تا x داریم؟ در جواب باید بگوییم که ما 7 نمونه یا sample داریم نه 7 ورودی. دراینجا، ما یک ورودی و یک خروجی داریم. مثلا ( * ورودی 2 ) منجر به خروجی 4 شده است. یا ( *ورودی ) 7 منجر به خروجی 14 شده است.
بنظرم باید در ابتدای متن بجای کلمه ورودی از نمونه و در انتهای متن هم نمونه 2 و نمونه 7 استفاده بشه چون در همین متن چندین بار به تفاوت نمونه و ورودی تاکید شده و دقیقا داره همین مفهوم رو آموزش میده ولی دوباره بجای نمونه از ورودی استفاده شده.
ممنون از آموزش های عالیتون، خسته نباشید🙏🏻🌹
سلام
ما هم از شما بابت این دقت و تذکر سپاسگزاریم. قطعا با چنین پیشنهادهایی آموزش بهتر و با کیفیتتر میشه. پیشنهاد شما رو در بخش موردنظر اعمال کردیم.
ممنون 🙏🌹
سلام خدا قوت
ممنون از آموزشهای خوبتون. کاشکی همه ی شبکه های عمیق رو اینطور روان توضیح میدادید. و مفهوم آنها را میگفتید. متاسفانه در کتابها و مقالات مفاهیم کم توضیح داده م شوند. کار شما واقعا فوق العاده س. تشکر
سلام
پیشنهاد میکنیم جلسات بعدی آموزش یادگیری عمیق رایگان رو هم مطالعه بفرمایید. درمورد شبکه عصبی کانولوشن ، شبکه عصبی بازگشتی ، شبکه عصبی GAN و شبکه عصبی LSTM توضیح دادیم.
انشالله یک روز بتونیم درکنار دوره های آموزش ویدئویی، کتاب با متن روان و ساده هم منتشر کنیم.
واقعا خسته نباشید محتوای شما بسیار عالی و قابل فهم بود👌👌👌
خوشحالیم که آموزش برای شما مفید بوده. 🌹🙏
سلام. سپاس بابت آموزش خوبتون
سلام
ممنون 🌹🙏
واقعا خوب توضیح دادین … مثالتون عالی بود
سپاس 🌹🙏
خیلی ممنونم از اموزش عالیتان..
فکر کنم سطر اخر معادله 4 داخل پرانتز به جای عنصر اول، دبلیو باید قرار داده شود.
سلام
بررسی شد. نباید w داشته باشد.
سپاس 🌹🙏
سلام
خیلی عالی و روان توضیح دادین
بسیار مفید هستن برای من. ممنون⚘
سلام
سپاس 🌹🙏
سلام
در منابع آموزشی مختلف (کتابها و دورهها)، اینطور رایج هست که شبکه عصبی MLP توضیح داده میشه و بعد هم شبکههای جدیدتر مثل شبکه عصبی کانولوشن یا شبکه عصبی GAN گفته میشه. معمولا در مقالات مختلف هم کارها براساس این شبکههاست و کمتر درباره شبکه RBF صحبت میشه. به همین خاطر ماهم از آوردن این شبکه در بخش آموزش یادگیری عمیق خودداری کردیم.
اما درکل شبکه جالبی هست. انشالله بعدا یک پست جداگانه براش مینویسیم.
ممنون 🌹🙏
من هرکجای زندگیم به این صفحه رجوع میکنم مشکلاتم برطرف میشه:) حلال مشکلاته:)
سلام
خداروشکر 😃
ممنون 🌹🙏
سلام
عالی بود خیلی عالی. ممنون ازتون 🙂
خداوند بهتان خیر و نیکی و برکت عطا کند
سلام
سپاس بابت این همه دعای زیبا 🙏🌹