<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های م. فتحی</title>
        <link>https://virgool.io/feed/@mojino</link>
        <description>مدرس آنالیز‌داده | یادگیری ماشین | یادگیری عمیق در مجتمع فنی تهران</description>
        <language>fa</language>
        <pubDate>2026-06-16 05:01:15</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/179275/avatar/1GCHM0.jpg?height=120&amp;width=120</url>
            <title>م. فتحی</title>
            <link>https://virgool.io/@mojino</link>
        </image>

                    <item>
                <title>شروع به کار با ATT&amp;CK: اطلاعات تهدید</title>
                <link>https://virgool.io/@mojino/%D8%B4%D8%B1%D9%88%D8%B9-%D8%A8%D9%87-%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-attck-%D8%A7%D8%B7%D9%84%D8%A7%D8%B9%D8%A7%D8%AA-%D8%AA%D9%87%D8%AF%DB%8C%D8%AF-trgohedzmrsy</link>
                <description>از زمان راه‌اندازی بلاگ Medium خود در سال گذشته، چندین پست با شما به اشتراک گذاشته‌ایم درباره موضوعاتی مثل ATT&amp;CKcon 2018، برنامه‌های ما برای سال 2019، و یک تصویری جذاب برای نقشه‌های راه ما — امیدواریم این مطالب برای شما مفید بوده باشد. با این حال، وقتی با شما صحبت کردیم، متوجه شدیم که لازم است کمی عقب برویم و روی یک سوال مهم تمرکز کنیم که بسیاری از شما پرسیده‌اید: چطور می‌توانم با ATT&amp;CK شروع کنم؟با توجه به این موضوع، ما یک مینی‌سری جدید از پست‌های بلاگ را شروع می‌کنیم که هدف آن پاسخ دادن به همین سوال برای چهار مورد استفاده کلیدی است: اطلاعات تهدید، شناسایی و تحلیل، شبیه‌سازی حمله و تست نفوذ، و ارزیابی و مهندسی. اگر هنوز ندیده‌اید، وب‌سایت خود را بازسازی کرده‌ایم تا محتوا را بر اساس این موارد استفاده به اشتراک بگذاریم، و امید ما این است که این پست‌های بلاگ به این منابع اضافه شوند.ATT&amp;CK می‌تواند برای هر سازمانی مفید باشد که می‌خواهد به سمت دفاع مبتنی بر تهدید حرکت کند، بنابراین می‌خواهیم ایده‌هایی برای شروع به اشتراک بگذاریم، صرف‌نظر از اینکه تیم شما چقدر پیشرفته است. هر یک از این پست‌ها را در سطوح مختلف ارائه خواهیم کرد:سطح 1: برای کسانی که تازه شروع کرده‌اند و منابع زیادی ندارند،سطح 2: برای تیم‌های میانی که در حال رشد و بلوغ هستند، وسطح 3: برای تیم‌های پیشرفته‌تر امنیت سایبری که منابع بیشتری دارند.امروز این سری را با بحث درباره اطلاعات تهدید شروع می‌کنیم، زیرا بهترین مورد استفاده است (شوخی کردم، بقیه تیمم! 😉). تابستان گذشته، یک مرور کلی ارائه دادم درباره اینکه چگونه می‌توانید از ATT&amp;CK برای پیشبرد اطلاعات تهدید سایبری استفاده کنید، و در این پست، بر آن پایه ساخته و مشاوره عملی برای شروع ارائه خواهم داد.سطح 1اطلاعات تهدید سایبری در مورد دانستن فعالیت‌های دشمنان شما و استفاده از آن اطلاعات برای بهبود تصمیم‌گیری است. برای سازمانی که تنها چند تحلیلگر دارد و می‌خواهد از ATT&amp;CK برای اطلاعات تهدید استفاده کند، یکی از راه‌های شروع این است که یک گروه مشخص که برای شما مهم است را انتخاب کرده و رفتارهای آن‌ها را طبق ساختار ATT&amp;CK بررسی کنید.می‌توانید گروهی را انتخاب کنید که در وب‌سایت ما نقشه‌گذاری شده است، بر اساس اینکه قبلاً چه کسانی را هدف قرار داده‌اند. همچنین، بسیاری از ارائه‌دهندگان اشتراک اطلاعات تهدید نیز به ATT&amp;CK ارجاع می‌دهند، بنابراین می‌توانید از اطلاعات آن‌ها به عنوان مرجع استفاده کنید.مثال: اگر شما یک شرکت دارویی هستید، می‌توانید در نوار جستجوی ما یا در صفحه گروه‌ها بررسی کنید که APT19 یکی از گروه‌هایی است که قبلاً بخش شما را هدف قرار داده است.جستجوی عبارت &quot;داروسازی&quot;توضیحات گروه APT19از آنجا، می‌توانید صفحه آن گروه را باز کنید تا تکنیک‌هایی که استفاده کرده‌اند را مشاهده کنید (براساس گزارش‌های متن‌باز که ما آن‌ها را نقشه‌گذاری کرده‌ایم) و اطلاعات بیشتری درباره آن‌ها کسب کنید. اگر درباره تکنیکی اطلاعات بیشتری نیاز دارید چون با آن آشنا نیستید، مشکلی نیست — همه اطلاعات در وب‌سایت ATT&amp;CK موجود است. می‌توانید همین روند را برای هر یک از نمونه‌های نرم‌افزاری که گروه استفاده کرده و ما آن‌ها را در وب‌سایت ATT&amp;CK جداگانه پیگیری می‌کنیم، تکرار کنید.مثال: یکی از تکنیک‌های استفاده شده توسط APT19، Registry Run Keys/Startup Folder است.حالا چگونه می‌توانیم این اطلاعات را عملیاتی کنیم، که هدف اصلی اطلاعات تهدید همین است؟ آن را با مدافعان خود به اشتراک بگذارید، چون این گروه بخش شما را هدف قرار داده و می‌خواهید از خود دفاع کنید. در این روند، می‌توانید برای ایده‌هایی درباره شناسایی و کاهش تکنیک‌ها به وب‌سایت ATT&amp;CK مراجعه کنید.مثال: به مدافعان خود اطلاع دهید که APT19 از کلید اجرای خاصی در رجیستری استفاده کرده است. البته ممکن است آن‌ها کلید دیگری را استفاده کنند. اگر توصیه‌های شناسایی این تکنیک را بررسی کنید، مشاهده می‌کنید که پیشنهاد می‌شود رجیستری را برای کلیدهای جدیدی که انتظار ندارید در محیط خود ببینید، مانیتور کنید. این می‌تواند موضوع گفتگوی بسیار خوبی با مدافعان شما باشد.ایده‌های شناسایی برای تکنیک Registry Run Keys / Startup Folderبه طور خلاصه، یک روش ساده برای شروع استفاده از ATT&amp;CK برای اطلاعات تهدید این است که به یک گروه دشمن مشخص که برای شما مهم است نگاه کنید. شناسایی برخی رفتارهایی که آن‌ها استفاده کرده‌اند، به شما کمک می‌کند مدافعان خود را درباره نحوه شناسایی این گروه مطلع کنید.سطح 2اگر تیمی از تحلیلگران تهدید دارید که به طور منظم اطلاعات درباره دشمنان را بررسی می‌کنند، گام بعدی می‌تواند این باشد که خودتان اطلاعات را به ATT&amp;CK نقشه‌گذاری کنید، به جای استفاده از نقشه‌هایی که دیگران قبلاً ایجاد کرده‌اند. اگر گزارشی درباره یک حادثه که سازمان شما تجربه کرده است دارید، این می‌تواند یک منبع داخلی عالی برای نقشه‌گذاری به ATT&amp;CK باشد، یا می‌توانید از یک گزارش خارجی مانند یک پست وبلاگ استفاده کنید. برای شروع، می‌توانید تنها با یک گزارش شروع کنید.مثال: این یک بخش از گزارش FireEye است که به ATT&amp;CK نقشه‌گذاری شده است. (https://www.fireeye.com/blog/threat-research/2014/11/operation_doubletap.html)ممکن است نقشه‌گذاری به ATT&amp;CK در ابتدا ترسناک به نظر برسد، زیرا همه صدها تکنیک را نمی‌شناسید. در اینجا یک فرآیند پیشنهادی برای کمک به شما آمده است:درک ATT&amp;CK — با ساختار کلی ATT&amp;CK آشنا شوید: تاکتیک‌ها (اهداف فنی دشمن)، تکنیک‌ها (چگونگی رسیدن به اهداف)، و روش‌ها (پیاده‌سازی‌های خاص تکنیک‌ها). به صفحه Getting Started و مقاله فلسفه ما نگاه کنید.شناسایی رفتار — درباره اقدام دشمن به شکل کلی‌تر از فقط شاخص اتمی (مانند یک آدرس IP) فکر کنید. برای مثال، بدافزار در گزارش فوق «یک اتصال SOCKS5 برقرار می‌کند». عمل برقراری اتصال یک رفتار است که دشمن انجام داده است.تحقیق درباره رفتار — اگر با رفتار آشنا نیستید، ممکن است نیاز به تحقیقات بیشتری داشته باشید. در مثال ما، کمی تحقیق نشان می‌دهد که SOCKS5 یک پروتکل لایه 5 (لایه نشست) است.ترجمه رفتار به تاکتیک — هدف فنی دشمن برای آن رفتار را در نظر بگیرید و تاکتیکی مناسب انتخاب کنید. خوشبختانه در ATT&amp;CK Enterprise تنها 12 تاکتیک وجود دارد. برای مثال اتصال SOCKS5، برقراری اتصال برای ارتباط بعدی، تحت تاکتیک Command and Control قرار می‌گیرد.تعیین تکنیک مرتبط با رفتار — این کمی پیچیده است، اما با مهارت تحلیل و مثال‌های وب‌سایت ATT&amp;CK قابل انجام است. اگر در سایت برای SOCKS جستجو کنید، تکنیک Standard Non-Application Layer Protocol (T1095) نمایش داده می‌شود و با مطالعه توضیحات، می‌بینید که این همان جایی است که رفتار شما می‌تواند قرار گیرد.مقایسه نتایج با دیگر تحلیلگران — ممکن است تفسیر شما از یک رفتار با تحلیلگر دیگر متفاوت باشد. این طبیعی است و در تیم ATT&amp;CK هم اتفاق می‌افتد! توصیه می‌کنم نقشه‌گذاری خود را با تحلیلگر دیگر مقایسه کرده و تفاوت‌ها را بررسی کنید.برای تیم‌های CTI که چند تحلیلگر دارند، نقشه‌گذاری اطلاعات به ATT&amp;CK توسط خودشان می‌تواند راهی عالی برای اطمینان از به دست آوردن مرتبط‌ترین اطلاعات باشد. سپس می‌توانید اطلاعات دشمن نقشه‌گذاری‌شده به ATT&amp;CK را به مدافعان خود منتقل کنید تا دفاع آن‌ها را بهبود ببخشید، همان‌طور که در بالا توضیح داده شد.سطح 3اگر تیم CTI شما پیشرفته است، می‌توانید اطلاعات بیشتری را به ATT&amp;CK نگاشت کنید و سپس از آن اطلاعات برای اولویت‌بندی دفاع‌های خود استفاده کنید. با استفاده از فرآیند بالا، می‌توانید هم اطلاعات داخلی و هم خارجی را به ATT&amp;CK نگاشت کنید، از جمله:داده‌های پاسخ به رخداد (Incident Response)گزارش‌های OSINT یا اشتراک‌های اطلاعات تهدیدهشدارهای لحظه‌ای (Real-time Alerts)اطلاعات تاریخی سازمان شماوقتی این داده‌ها را نگاشت کردید، می‌توانید کارهای جالبی برای مقایسه گروه‌ها و اولویت‌بندی تکنیک‌های رایج انجام دهید. برای مثال، به این نمای ماتریسی از ATT&amp;CK Navigator نگاه کنید که قبلاً به اشتراک گذاشته بودم و شامل تکنیک‌هایی است که در وب‌سایت ATT&amp;CK نگاشت کرده‌ایم.تکنیک‌هایی که فقط توسط APT3 استفاده شده‌اند با رنگ آبی مشخص شده‌اند.تکنیک‌هایی که فقط توسط APT29 استفاده شده‌اند با رنگ زرد مشخص شده‌اند.تکنیک‌هایی که توسط هر دو گروه استفاده شده‌اند با رنگ سبز مشخص شده‌اند.(تمام این اطلاعات فقط بر اساس داده‌های عمومی موجود است که ما نگاشت کرده‌ایم، و تنها بخشی از فعالیت‌های واقعی این گروه‌ها را شامل می‌شود.)تکنیک‌های APT3 + APT29شما باید گروه‌ها و تکنیک‌هایی را که برای سازمان شما و تهدیدات اصلی آن اهمیت دارند جایگزین کنید. برای کمک به ساخت لایه‌های Navigator مشابه مثال بالا، یک راهنمای گام‌به‌گام ارائه شده که توضیح می‌دهد چگونه می‌توانید این ماتریس را ایجاد کنید، به همراه یک ویدیوی آموزشی که قابلیت‌های Navigator را نیز معرفی می‌کند.راهنمای گام‌به‌گام مقایسه لایه‌هامنبعhttps://medium.com/mitre-attack/getting-started-with-attack-cti-4eb205be4b2f</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Tue, 12 May 2026 09:51:46 +0330</pubDate>
            </item>
                    <item>
                <title>IRQL: زبان جست‌وجوی پاسخ به رخدادها</title>
                <link>https://virgool.io/@mojino/irql-%D8%B2%D8%A8%D8%A7%D9%86-%D8%AC%D8%B3%D8%AA-%D9%88%D8%AC%D9%88%DB%8C-%D9%BE%D8%A7%D8%B3%D8%AE-%D8%A8%D9%87-%D8%B1%D8%AE%D8%AF%D8%A7%D8%AF%D9%87%D8%A7-gadxwucsp9ud</link>
                <description>یک گویش یکپارچه و کاربرپسند برای Kusto (KQL) که شکار تهدیدهای امنیتی را سریع‌تر، سازگارتر و خواناتر می‌سازد.با خوشحالی معرفی می‌کنم IRQL — مجموعه‌ای از توابع Kusto که برای پنهان‌کردن آشفتگی لاگ‌های امنیتی گوناگون و ارائه تجربه‌ای تمیز و بیانگر هدف در کوئری‌ها طراحی شده‌اند.این زبان توسط سار ران، جان لمبرت و دیانا دامنووا ساخته شده است و کوئری‌های طولانی و شکننده‌ی KQL را به خطوط لوله‌ای خوانا، قابل استفاده‌ی مجدد و قابل درک برای انسان‌ها و مدل‌های زبانی (LLMها)چرا IRQL اهمیت دارد تلمتری امنیتی به‌طور ذاتی آشفته و نامنظم است:یک مفهوم واحد ممکن است با ده‌ها نام ستون مختلف ظاهر شود (ipAddress، ClientIp، callerIpAddress و…).جدول‌ها در کلاسترها و دیتابیس‌های متفاوتی قرار دارند.الگوهای تکراری join و enrichment مدام کپی می‌شوند و با تغییر اسکیما به‌راحتی از کار می‌افتند.کوئری‌ها طولانی، سخت برای بازبینی و از نظر ذهنی پرهزینه می‌شوند.IRQL این مشکل را با پنهان کردن جزئیات فنی پشت توابع معنایی و پایدار حل می‌کند. نتیجه:اسکیما یکپارچه (EnvTime، ClientIp، Username، Hostname، Url و غیره)سلکتورهای قابل‌استفاده مجدد که می‌دانند داده‌ها کجا هستند و چگونه باید join شوندنام‌های مبتنی بر نیت مانند Get_Event_SignIn، Extract_Email_Sender_Domain، Enrich_Ip_Employeeترکیب‌پذیری روان با تحلیل‌های جدولی و گراف‌محور (از طریق توابع Lift-To-Graph)نتیجه نهایی چیست؟ یادگیری سریع‌تر، خطاهای کمتر، پشتیبانی بهتر از کوئری‌نویسی با کمک هوش مصنوعی، و شکار تهدیداتی که بیشتر شبیه یک روایت هستند تا یک اسکریپت.قبل و بعد: یک بررسی واقعیتفاوت در عمل — شناسایی اپلیکیشن‌هایی که دسته‌های جدیدی از user-agent را مشاهده می‌کنند (نشانه‌ای از سرقت توکن یا فعالیت AiTM):نسخه خام KQL (طولانی، مکانیکی، شامل منطق درون‌خطی و joinهای متعدد)(~۶۰ خط شامل یک طبقه‌بند بزرگ user-agent، unionهای دستی، چندین بازه زمانی و joinهای صریح)نسخه IRQL (تمیز، خوانا، حدود ۱۵ خط):let minimumAppThreshold = 100;
let timeframe = 1d;
let lookback = 7d;

let SignInsToday    = Get_Event_SignIn(timeframe, 0d);
let SignInsBaseline = Get_Event_SignIn(lookback + timeframe, timeframe);

let Baseline =
    SignInsBaseline
    | invoke Extract_SignIn_UserAgent_Category()
    | summarize RequestCount = count() by AppId, AppDisplayName, UserAgentCategory;

SignInsToday
| invoke Extract_SignIn_UserAgent_Category()
| invoke Enrich_App_New_UserAgent_Category(Baseline, minimumAppThreshold)
| project EnvTime, Username, AppDisplayName, AppId, UserAgentCategory, UserAgent, BaselineCategories
| summarize count() by Username, AppDisplayName, AppId, UserAgentCategory, UserAgentهمان منطق — با وضوح نیت به‌مراتب بیشتر.دسته‌بندی توابعIRQL توابع را در گروه‌های مشخصی سازمان‌دهی می‌کند:تابع All_*_Selectors (Get_ / Get— داده‌ها را از جدول‌های منبع با یک اسکیما یکنواخت و استاندارد استخراج می‌کنند.تابع Extractors (Extract_*) — ستون‌های جدیدی مشتق می‌کنند (مثلاً استخراج دامنه از URL یا ایمیل).تابع Enrichers (Enrich_*) — اطلاعات تکمیلی مانند داده‌های کارمندان یا رویدادهای شبکه را به‌صورت left join اضافه می‌کنند.نسخه‌های گراف (Extract_Node_، Enrich_Node_، Enrich_Graph_*) — همان قابلیت‌ها، اما این‌بار روی گراف‌هایی که توسط توابع Lift_To_Graph ساخته شده‌اند.غنی‌سازی خارجی — شامل گزارش‌های فایل از VirusTotal و فهرست آسیب‌پذیری‌های شناخته‌شده و مورد سوءاستفاده CISA، آماده برای استفاده.نمونه‌های واقعی شکار تهدیداین مجموعه شامل چندین مثال کامل (end-to-end) روی دیتاست‌های عمومی KC7 (JoJo’s Hospital / Valdy Times) است:تحلیل کمپین فیشینگ بر اساس رتبه سازمانی گیرندگانبررسی فعالیت‌های پس از نفوذ (post-exploitation) از یک فایل مخربتحلیل دامنه‌های مشکوک به‌صورت گراف تعاملیاین مثال‌ها نشان می‌دهند که IRQL چگونه به‌صورت طبیعی به کوئری‌های قدرتمند و قابل نگهداری زنجیره می‌شود.خودتان امتحان کنیداین توابع به‌صورت زنده روی دیتاست‌های باز KC7 در دسترس هستند:Cluster: https://kc7001.eastus.kusto.windows.netDatabases: JoJosHospital و ValdyTimesمی‌توانید کل کاتالوگ، تعریف توابع و مثال‌ها را مستقیماً از Gist کپی کنید:IRQL.md در GitHubاین ابزار همچنین به‌خوبی با توابع مکمل Lift to Graph برای تحلیل‌های بصری ترکیب می‌شود.مشارکت کنیدIRQL طوری طراحی شده که به‌عنوان یک زبان مشترک رشد کند. آن را در محیط خود پیاده‌سازی کنید، با منابع داده خود گسترش دهید، و به ساخت زبانی یکپارچه‌تر برای عملیات امنیتی کمک کنید.تشکر ویژه از نویسندگان برای متن‌باز کردن این پروژه — این یک گام واقعی رو به جلو برای مقیاس‌پذیر و قابل‌دسترس کردن شکار تهدید است.نظر شما چیست؟ دیدگاه‌ها، سوال‌ها یا اولین کوئری‌های IRQL خود را در بخش نظرات به اشتراک بگذارید. بیایید تحلیل امنیتی را قدم‌به‌قدم ساده‌تر کنیم. 🚀شکار موفق!منبعhttps://rodtrent.substack.com/p/irql-incident-response-query-language</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Sat, 02 May 2026 12:50:39 +0330</pubDate>
            </item>
                    <item>
                <title>امنیت شبکه: شروع با QUIC و HTTP/3</title>
                <link>https://virgool.io/@mojino/%D8%A7%D9%85%D9%86%DB%8C%D8%AA-%D8%B4%D8%A8%DA%A9%D9%87-%D8%B4%D8%B1%D9%88%D8%B9-%D8%A8%D8%A7-quic-%D9%88-http3-sl8kimofzwqi</link>
                <description>به جنگجویان سایبری آینده خوش آمدید!برای دهه‌ها، ترافیک HTTP سنتی بر روی TCP، که به آن HTTP/1 و HTTP/2 گفته می‌شود، به عنوان ستون فقرات وب عمل کرده است و ما ابزارهایی برای تجزیه و تحلیل، رهگیری و بهره‌برداری از آن داریم. اما امروزه، HTTP/3 در حال افزایش است و به طور فزاینده‌ای در وب مورد استفاده قرار می‌گیرد. در سال 2022، حدود 22% از تمام وب‌سایت‌ها از HTTP/3 استفاده می‌کردند؛ در سال 2025، این عدد به تقریباً 40% افزایش یافته است. و به عنوان جنگجویان سایبری، ما باید از این تغییرات جلوتر باشیم.در این مقاله، به طور مختصر به آنچه که در پس پرده HTTP/3 است می‌پردازیم و چگونگی ارتباط با آن را بررسی می‌کنیم. بیایید شروع کنیم!HTTP/3 چیست؟HTTP/3 جدیدترین تکامل از پروتکل انتقال ابرمتن (Hypertext Transfer Protocol) است — سیستمی که به مرورگرها، برنامه‌ها و API‌ها اجازه می‌دهد داده‌ها را در اینترنت منتقل کنند. چیزی که آن را متمایز می‌کند، ترک کردن TCP است، پروتکل انتقال قدیمی که از اولین روزهای وب، موتور آن بوده است.TCP (پروتکل کنترل انتقال) قابل اعتماد است اما انعطاف‌پذیری کمی دارد. این پروتکل برای دقت ساخته شده است، نه سرعت، به گونه‌ای که اطمینان حاصل می‌شود که همه داده‌ها به‌طور صحیح می‌رسند، حتی اگر این باعث کندی اتصال شود. هر جلسه نیاز به یک دست دادن چند مرحله‌ای دارد و اگر یک بسته تاخیر پیدا کند، همه بسته‌ها باید منتظر بمانند. این ممکن بود برای ایمیل قابل قبول باشد، اما برای ترافیک وب مدرن مناسب نیست.برای غلبه بر این محدودیت‌ها، HTTP/3 از QUIC (اتصالات سریع UDP اینترنت) استفاده می‌کند، یک پروتکل انتقال ساخته شده بر روی UDP که برای اینترنت سریع، موبایلی و حساس به تأخیر طراحی شده است. QUIC تأخیر دست دادن را کاهش می‌دهد، از انسداد سرصفحه جلوگیری می‌کند و تقریباً تمام ارتباطات را به‌طور پیش‌فرض رمزنگاری می‌کند — از همان ابتدا.پس از سال‌ها توسعه، IETF (سازمان مهندسی اینترنت) در سال 2022 HTTP/3 را به‌طور رسمی استاندارد کرد. امروزه این پروتکل در مرورگرهای اصلی، پلتفرم‌های ابری و تعداد فزاینده‌ای از سرورهای وب به‌طور گسترده پیاده‌سازی شده است.QUIC چیست؟ترافیک وب سنتی یک الگوی قابل پیش‌بینی دنبال می‌کند. یک کلاینت یک دست دادن سه‌مرحله‌ای TCP را آغاز می‌کند، سپس یک دست دادن TLS را بر روی آن ارتباط انجام می‌دهد و در نهایت درخواست‌های HTTP را ارسال می‌کند. QUIC این فرایند را به یک دست دادن واحد کاهش می‌دهد که شامل توافق حمل و نقل و رمزنگاری است. اولین بار که یک کلاینت به سرور متصل می‌شود، می‌تواند یک اتصال امن را تنها در یک گردش زمان (round trip) برقرار کند. در اتصالات بعدی، QUIC می‌تواند با استفاده از شناسایی ارتباطات، بازگشت زمان صفر (zero round-trip time) را انجام دهد، به این معنی که کلاینت می‌تواند داده‌های رمزنگاری‌شده را در همان بسته اول ارسال کند.این پروتکل تقریباً تمام چیزها را رمزنگاری می‌کند به جز یک شناسه حداقلی برای اتصال. برخلاف TLS بر روی TCP که در آن می‌توان هدرهای TCP، شماره‌های توالی و تاییدیه‌ها را در متن‌خوانا مشاهده کرد، QUIC شماره‌های بسته، تاییدیه‌ها و حتی فریم‌های بسته شدن اتصال را رمزنگاری می‌کند. این رویکرد رمزنگاری پیش‌فرض به‌طور قابل توجهی متاداده موجود برای تجزیه و تحلیل ترافیک را کاهش می‌دهد.QUIC همچنین قابلیت مهاجرت اتصال را پیاده‌سازی می‌کند، که به اتصال اجازه می‌دهد از تغییرات شبکه بگذرد. اگر کاربر از WiFi به سیگنال سلولی سوئیچ کند یا آدرس IP او به دلیل تجدید DHCP تغییر کند، اتصال QUIC با استفاده از شناسه‌های ارتباطی باقی می‌ماند و دیگر نیازی به استفاده از چهار تایی از آدرس IP مبدا، پورت مبدا، آدرس IP مقصد و پورت مقصد نیست.دست دادن (Handshake) در QUICفرایند زمانی آغاز می‌شود که کلاینت بسته اولیه (Initial packet) خود را ارسال می‌کند. این پیام اول شامل نسخه‌های QUIC پشتیبانی‌شده توسط کلاینت، مجموعه‌های رمزنگاری موجود، یک عدد تصادفی تازه تولید شده و شناسه اتصال است — یک شناسه تصادفی که حتی اگر آدرس IP کلاینت تغییر کند، ثابت باقی می‌ماند. داخل این بسته اولیه، کلاینت پیامی از نوع TLS 1.3 (ClientHello) را به همراه پارامترهای حمل و نقل QUIC و مواد رمزنگاری اولیه لازم برای آغاز مذاکره کلید قرار می‌دهد. اگر کلاینت قبلاً به سرور متصل شده باشد، ممکن است حتی داده‌های زودهنگام برنامه مانند یک درخواست HTTP را به‌منظور ذخیره کردن یک گردش زمان اضافی در بسته گنجانده باشد.سپس سرور با مجموعه‌ای از اطلاعات خود پاسخ می‌دهد. یکی از نسخه‌های QUIC و مجموعه‌های رمزنگاری کلاینت را انتخاب کرده، یک عدد تصادفی خود را فراهم می‌کند و شناسه اتصال سمت سرور را به همراه پارامترهای حمل و نقل QUIC ارسال می‌کند. داخل این پاسخ، TLS 1.3 ServerHello قرار دارد که مواد رمزنگاری لازم برای استخراج کلیدهای مشترک را شامل می‌شود. سرور همچنین زنجیره گواهی کامل خود را ارسال می‌کند — گواهی سرور به همراه مراجع گواهی میان‌راه (Intermediate Certificate Authorities) که آن را امضا کرده‌اند — و ممکن است داده‌های HTTP زودهنگام را ارسال کند.پس از اینکه کلاینت پاسخ سرور را دریافت کرد، فرآیند اعتبارسنجی گواهی را آغاز می‌کند. آن داده‌های گواهی و امضای همراه آن را استخراج کرده، مرجع گواهی صادرکننده (CA) را شناسایی می‌کند و از گواهی ریشه مناسب در مخزن اعتماد خود برای اعتبارسنجی گواهی‌های میان‌راه و در نهایت گواهی سرور استفاده می‌کند. برای انجام این کار، داده‌های گواهی دریافتی را با استفاده از الگوریتم مشخص شده در گواهی هش می‌کند و سپس بررسی می‌کند که آیا این هش محاسبه‌شده با هشی که می‌توان آن را با استفاده از کلید عمومی مرجع گواهی صادرکننده (CA) تایید کرد، مطابقت دارد یا خیر. اگر مقادیر مطابقت داشتند و گواهی برای دوره زمانی فعلی و نام دامنه استفاده‌شده معتبر باشد، کلاینت می‌تواند به این نتیجه برسد که سرور واقعی است. در این مرحله، با استفاده از زمان‌بندی کلید TLS، کلاینت کلیدهای اتصال QUIC را استخراج کرده و پیام Finished خود را درون یک بسته QUIC دیگر ارسال می‌کند. با تکمیل این تبادل، اتصال به‌طور کامل برای داده‌های رمزنگاری‌شده برنامه آماده می‌شود.از این لحظه به بعد، تمام ترافیک بین کلاینت و سرور با استفاده از کلیدهای جلسه ایجاد شده رمزنگاری می‌شود. برخلاف مدل سنتی TCP که با TLS ترکیب می‌شود، QUIC نیازی به فاز جداگانه‌ای برای دست دادن (TLS handshake) ندارد. در عوض، TLS به‌طور مستقیم در داخل دست دادن QUIC ادغام شده است، که به پروتکل این امکان را می‌دهد که سفرهای زمان اضافی را حذف کند. یکی از مزایای عمده این طراحی این است که هم سرور و هم کلاینت می‌توانند داده‌های واقعی برنامه — مانند درخواست‌ها و پاسخ‌های HTTP — را در داخل خود دست دادن گنجانده و ارسال کنند. در نتیجه، اعتبارسنجی گواهی و برقراری اتصال به‌طور همزمان با تبادل اولیه داده‌های واقعی انجام می‌شود، که باعث می‌شود QUIC سریع‌تر و کارآمدتر از مدل قدیمی TCP+TLS باشد.چگونه شبکه QUIC کار می‌کند؟تصویر زیر ساختار اصلی یک شبکه مبتنی بر QUIC را نشان می‌دهد. همان‌طور که نشان داده شده است، درخواست‌ها، پاسخ‌ها و دیگر داده‌های برنامه‌ای HTTP/3 همه از طریق جریان‌های QUIC عبور می‌کنند. این جریان‌ها در چندین لایه منطقی محصور می‌شوند قبل از اینکه از طریق شبکه منتقل شوند.آناتومی یک جریان QUICیک دیتاگرام UDP به عنوان محفظه حمل و نقل خارجی عمل می‌کند. این دیتاگرام حاوی یک هدر با اطلاعات مربوط به پورت‌های مبدا و مقصد، همراه با اطلاعات طول و بررسی صحت (checksum)، است و یک یا چند بسته QUIC را حمل می‌کند. این واحد اصلی است که بین کلاینت و سرور در شبکه منتقل می‌شود.یک بسته QUIC واحدی است که درون یک دیتاگرام UDP قرار دارد و هر دیتاگرام ممکن است یک یا چند بسته QUIC داشته باشد. هر بسته QUIC شامل یک هدر QUIC به همراه یک یا چند فریم QUIC است.هدر QUIC حاوی متاداده‌ای در مورد بسته است و در دو فرمت مختلف وجود دارد. هدر بلند (long header) در زمان راه‌اندازی اتصال استفاده می‌شود، در حالی که هدر کوتاه (short header) پس از برقراری اتصال به کار می‌رود. هدر کوتاه شامل شناسه اتصال، شماره بسته و مرحله کلید است که نشان‌دهنده کلیدهای رمزنگاری در حال استفاده است و از چرخش کلید پشتیبانی می‌کند. شماره‌های بسته به طور مداوم برای هر اتصال و مرحله کلید افزایش می‌یابند.یک فریم کوچک‌ترین واحد ساختاری درون یک بسته QUIC است. این فریم شامل نوع فریم، شناسه جریان، آفست و بخشی از داده‌های جریان است. اگرچه داده‌های یک جریان در چندین فریم پخش شده است، اما می‌توان آن‌ها را با استفاده از شناسه اتصال، شناسه جریان و آفست در ترتیب صحیح دوباره سرهم کرد.یک جریان یک کانال داده یک‌طرفه یا دوطرفه درون یک اتصال QUIC است. هر اتصال QUIC می‌تواند از چندین جریان مستقل پشتیبانی کند که هر کدام توسط شناسه منحصر به فرد خود شناسایی می‌شود. اگر یک بسته QUIC گم شود، تنها جریان‌های حمل‌شده در آن بسته تحت تأثیر قرار می‌گیرند، در حالی که تمام دیگر جریان‌ها بدون وقفه ادامه خواهند داشت. این استقلال است که باعث می‌شود انسداد سرصفحه (head-of-line blocking) که در HTTP/2 مشاهده می‌شود، در QUIC از بین برود. جریان‌ها می‌توانند توسط هر نقطه انتهایی ایجاد شوند و می‌توانند در هر دو جهت عمل کنند.HTTP/3 در مقایسه با HTTP/2 و HTTP/1: چه تغییراتی به‌وجود آمده است؟برای درک اهمیت HTTP/3، ابتدا لازم است محدودیت‌های نسخه‌های قبلی آن را در نظر بگیریم.HTTP/1.1، پروتکلی اصلی که هنوز توسط میلیون‌ها وب‌سایت استفاده می‌شود، تنها یک درخواست را در هر اتصال TCP پردازش می‌کند. این باعث می‌شود که مرورگرها مجبور شوند برای بارگذاری یک صفحه واحد، اتصالات زیادی باز و بسته کنند که منجر به بی‌کارآمدی، عملکرد پایین‌تر و حساسیت زیاد به مشکلات شبکه می‌شود.HTTP/2 بهبودهای عمده‌ای را معرفی کرد، از جمله مولتی‌پلکسیگ (multiplexing)، که به درخواست‌های متعدد اجازه می‌دهد تا یک اتصال TCP واحد را به اشتراک بگذارند، همچنین فشرده‌سازی هدرها و ارسال اطلاعات توسط سرور (server push). این تغییرات افزایش‌های قابل توجهی به همراه داشت، اما پروتکل هنوز به TCP وابسته است، که یک محدودیت اساسی دارد: اگر یک بسته به تأخیر بیفتد، تمام مسیر اتصال متوقف می‌شود. این پدیده که به آن انسداد سرصفحه (head-of-line blocking) گفته می‌شود، در HTTP/2 قابل اجتناب نیست. HTTP/3 این محدودیت را با جایگزین کردن TCP با یک لایه حمل و نقل پیشرفته‌تر حل می‌کند. ساخته شده بر پایه QUIC، HTTP/3 جلسات رمزنگاری شده را سریع‌تر برقرار می‌کند، که معمولاً تنها نیاز به یک گردش زمان (round-trip) به جای سه یا بیشتر دارد. این پروتکل انسداد سرصفحه (head-of-line blocking) را با دادن کنترل جریان مستقل به هر جریان، از بین می‌برد، به این معنی که سایر جریان‌ها حتی اگر یک بسته از دست برود، همچنان ادامه می‌دهند. HTTP/3 می‌تواند جلسات را از طریق تغییرات IP یا شبکه حفظ کند، از دست دادن بسته‌ها را به طور نرم‌تری بازیابی کند و حتی از کنترل ترافیک سفارشی برای سازگاری با حجم‌های مختلف کاری پشتیبانی کند.به طور خلاصه، HTTP/3 تنها نسخه‌ای بهبودیافته از HTTP/2 نیست. بلکه یک پروتکل کاملاً بازطراحی شده است که برای غلبه بر محدودیت‌های نسل‌های قبلی ایجاد شده است، به ویژه برای کاربران موبایل، برنامه‌های حساس به تأخیر و ترافیک توزیع‌شده در سطح جهانی.شروع کار با HTTP/3نسخه‌های مدرن curl (7.66.0 و نسخه‌های جدیدتر با پشتیبانی از HTTP/3) می‌توانند آزمایش کنند که آیا یک سرور از QUIC و HTTP/3 پشتیبانی می‌کند یا نه. در اینجا نحوه بررسی یک سرور آمده است:kali&gt; curl –http3 -I https://www.example.comاین دستور تلاش می‌کند که با استفاده از HTTP/3 بر روی QUIC متصل شود، اما اگر QUIC پشتیبانی نشود، به HTTP/2 یا HTTP/1.1 بازمی‌گردد.علاوه بر این، دیدن اینکه ترافیک QUIC چگونه در دنیای واقعی به نظر می‌رسد، مفید است. یکی از ساده‌ترین روش‌ها برای این کار استفاده از Wireshark است، ابزاری محبوب برای تجزیه و تحلیل بسته‌های شبکه. حتی اگر QUIC بیشتر بار داده خود را رمزنگاری کند، Wireshark می‌تواند همچنان انواع بسته‌های QUIC، نسخه‌ها و برخی متاداده‌ها را شناسایی کند، که به ما کمک می‌کند تا درک کنیم چگونه یک اتصال QUIC برقرار می‌شود.برای شروع، Wireshark را باز کنید و به وب‌سایتی که از QUIC پشتیبانی می‌کند مراجعه کنید. Cloudflare مثال خوبی است زیرا به طور گسترده‌ای HTTP/3 و پروتکل QUIC را پیاده‌سازی کرده است. QUIC معمولاً بر روی پورت UDP 443 اجرا می‌شود، بنابراین ساده‌ترین فیلتر برای تأیید این که ترافیک QUIC را مشاهده می‌کنید، به شرح زیر است:udp.port == 443این فیلتر تمام ترافیک UDP روی پورت 443 را نشان می‌دهد، که تقریباً همیشه با QUIC در وب‌سایت‌های مدرن مرتبط است.QUIC در مراحل مختلف اتصال از انواع بسته‌های مختلف استفاده می‌کند. حتی اگر محتوا رمزنگاری شده باشد، Wireshark همچنان می‌تواند این انواع بسته‌ها را شناسایی کند.برای نمایش فقط بسته‌های Initial، که اولین بسته‌هایی هستند که هنگام شروع یک اتصال QUIC توسط کلاینت تبادل می‌شوند، از دستور زیر استفاده کنید:quic.long.packet_type == 0بسته‌های Initial بخشی از مرحله دست دادن (handshake) QUIC هستند. این بسته‌ها تا حدی شبیه به پیام‌های “ClientHello” و “ServerHello” در TLS هستند، با این استثناء کهQUIC  دست دادن را در خود پروتکل تعبیه کرده است.اگر می‌خواهید بسته‌های Handshake را مشاهده کنید، که پس از بسته‌های Initial ادامه می‌دهند و دست دادن رمزنگاری را تکمیل می‌کنند، از دستور زیر استفاده کنید:quic.long.packet_type == 2این بسته‌ها کمک می‌کنند تا اتصال امن تکمیل شود قبل از اینکه QUIC به بسته‌های رمزنگاری‌شده &quot;هدر کوتاه&quot; برای داده‌های معمولی (مانند درخواست‌ها و پاسخ‌های HTTP/3) تغییر وضعیت دهد.همچنین، QUIC نسخه‌های مختلفی دارد و سرورها اغلب از بیش از یک نسخه پشتیبانی می‌کنند. برای مشاهده بسته‌هایی که از نسخه خاصی استفاده می‌کنند، دستور زیر را امتحان کنید:quic.version == 0x00000001این دستور به نسخه 1 از QUIC اشاره دارد، که در RFC 9000 استاندارد شده است. با بررسی اینکه کدام نسخه از QUIC در ترافیک مشاهده می‌شود، می‌توانید متوجه شوید که سرور از کدام نسخه پشتیبانی می‌کند و آیا از نسخه استاندارد یا نسخه‌های پیش‌نویس قدیمی‌تر استفاده می‌کند.خلاصهQUIC تنها یک به‌روزرسانی تدریجی نیست — بلکه یک بازآفرینی کامل از نحوه عملکرد ارتباطات اینترنتی مدرن است. در حالی که پشته سنتی TCP + TLS + HTTP/2 برای سال‌ها به خوبی از ما حمایت کرده است، هیچ‌گاه برای واقعیت‌های اینترنت امروزی طراحی نشده بود: تأخیرهای جهانی، تغییرات مداوم در ارتباطات موبایلی، و نیاز رو به رشد به عملکرد بالا و امنیت قوی. QUIC از ابتدا ساخته شده است تا این چالش‌ها را برطرف کند، و آن را سریع‌تر، مقاوم‌تر و امن‌تر برای وب مدرن می‌سازد.ادامه دهید به بازگشت، جنگجویان سایبری آینده‌نگر، همان‌طور که ما به کاوش در مورد چگونگی بازنویسی پروتکل‌های اساسی اینترنت ادامه می‌دهیم.منبعhttps://hackers-arise.com/network-security-get-started-with-quic-and-http-3/</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Wed, 22 Apr 2026 11:23:58 +0330</pubDate>
            </item>
                    <item>
                <title>درک بصری آنتروپی متقاطع دودویی / زیان لگاریتمی</title>
                <link>https://virgool.io/@mojino/%D8%AF%D8%B1%DA%A9-%D8%A8%D8%B5%D8%B1%DB%8C-%D8%A2%D9%86%D8%AA%D8%B1%D9%88%D9%BE%DB%8C-%D9%85%D8%AA%D9%82%D8%A7%D8%B7%D8%B9-%D8%AF%D9%88%D8%AF%D9%88%DB%8C%DB%8C-%D8%B2%DB%8C%D8%A7%D9%86-%D9%84%DA%AF%D8%A7%D8%B1%DB%8C%D8%AA%D9%85%DB%8C-y0okh5la8twl</link>
                <description>دانیل گودوی 21 نوامبر 2018مقدمهاگر در حال آموزش یک طبقه‌بندی‌کننده دودویی هستید، به احتمال زیاد از آنتروپی متقاطع دودویی یا زیان لگاریتمی (binary cross-entropy / log loss) به عنوان تابع زیان استفاده می‌کنید. آیا تا به حال به این فکر کرده‌اید که استفاده از این تابع زیان دقیقاً به چه معناست؟ با توجه به سهولت استفاده از کتابخانه‌ها و چارچوب‌های امروزی، به راحتی ممکن است معنای واقعی تابع زیان مورد استفاده نادیده گرفته شود.انگیزهمن به دنبال یک پست وبلاگی بودم که مفاهیم پشت آنتروپی متقاطع دودویی / زیان لگاریتمی را به شکلی بصری، واضح و مختصر توضیح دهد تا بتوانم آن را به دانشجویانم در دوره علوم داده نشان دهم. از آنجا که نتوانستم منبعی مناسب پیدا کنم، تصمیم گرفتم خودم این کار را انجام دهم.یک مسئله طبقه‌بندی سادهبیایید با 10 نقطه تصادفی شروع کنیم: x = [-2.2, -1.4, -0.8, 0.2, 0.4, 0.8, 1.2, 2.2, 2.9, 4.6] این تنها ویژگی ماست: x.اکنون، به نقاطمان رنگ‌هایی اختصاص می‌دهیم: قرمز و سبز. این‌ها برچسب‌های ما هستند.بنابراین، مسئله طبقه‌بندی ما بسیار ساده است: با توجه به ویژگی x، باید برچسب آن را پیش‌بینی کنیم: قرمز یا سبز. از آنجا که این یک طبقه‌بندی دودویی است، می‌توانیم مسئله را این‌گونه نیز مطرح کنیم: «آیا نقطه سبز است؟» یا حتی بهتر، «احتمال سبز بودن نقطه چقدر است؟» در حالت ایده‌آل، نقاط سبز باید احتمال 1.0 (برای سبز بودن) داشته باشند، در حالی که نقاط قرمز باید احتمال 0.0 (برای سبز بودن) داشته باشند. در این چارچوب، نقاط سبز به کلاس مثبت (بله، سبز هستند) تعلق دارند، در حالی که نقاط قرمز به کلاس منفی (خیر، سبز نیستند) تعلق دارند.اگر مدلی را برای انجام این طبقه‌بندی آموزش دهیم، این مدل برای هر یک از نقاط، احتمالی برای سبز بودن پیش‌بینی می‌کند. با توجه به اطلاعاتی که درباره رنگ نقاط داریم، چگونه می‌توانیم ارزیابی کنیم که احتمالات پیش‌بینی‌شده چقدر خوب (یا بد) هستند؟ این دقیقاً هدف تابع زیان است! تابع زیان باید برای پیش‌بینی‌های بد مقادیر بالایی و برای پیش‌بینی‌های خوب مقادیر پایینی برگرداند. برای یک طبقه‌بندی دودویی مثل مثال ما، تابع زیان معمول، آنتروپی متقاطع دودویی / زیان لگاریتمی است.تابع زیان: آنتروپی متقاطع دودویی / زیان لگاریتمیاگر این تابع زیان را جستجو کنید، با فرمول زیر مواجه خواهید شد:آنتروپی متقاطع دودویی / زیان لگاریتمی که در آن y برچسب است (1 برای نقاط سبز و 0 برای نقاط قرمز) و p(y) احتمال پیش‌بینی‌شده سبز بودن نقطه برای تمام N نقطه است. با خواندن این فرمول، متوجه می‌شوید که برای هر نقطه سبز (y=1)، لگاریتم احتمال سبز بودن (log(p(y))) به زیان اضافه می‌شود. برعکس، برای هر نقطه قرمز (y=0)، لگاریتم احتمال قرمز بودن (log(1-p(y))) به زیان اضافه می‌شود. این فرمول خیلی پیچیده نیست، اما چندان شهودی هم به نظر نمی‌رسد.علاوه بر این، آنتروپی چه ربطی به این موضوع دارد؟ چرا اصلاً از لگاریتم احتمالات استفاده می‌کنیم؟ این‌ها سؤالات درستی هستند و امیدوارم در بخش «ریاضیات را نشان بده» در ادامه به آن‌ها پاسخ دهم. اما پیش از رفتن به سراغ فرمول‌های بیشتر، اجازه دهید یک نمایش بصری از فرمول بالا به شما نشان دهم...محاسبه زیان - به روش بصریابتدا، نقاط را بر اساس کلاس‌هایشان، مثبت یا منفی، جدا می‌کنیم، همان‌طور که در شکل زیر نشان داده شده است.اکنون، یک رگرسیون لجستیک را برای طبقه‌بندی نقاطمان آموزش می‌دهیم. رگرسیون مناسب‌شده یک منحنی سیگموید است که احتمال سبز بودن یک نقطه را برای هر مقدار x نشان می‌دهد.به صورت زیر است:سپس، برای تمام نقاط متعلق به کلاس مثبت (سبز)، احتمالات پیش‌بینی‌شده توسط طبقه‌بندی‌کننده ما چیست؟ این‌ها میله‌های سبز زیر منحنی سیگموید، در مختصات x مربوط به نقاط هستند.تا اینجا همه‌چیز خوب است! اما نقاط متعلق به کلاس منفی چطور؟ به یاد داشته باشید، میله‌های سبز زیر منحنی سیگموید نشان‌دهنده احتمال سبز بودن یک نقطه هستند. پس احتمال قرمز بودن یک نقطه چیست؟ البته میله‌های قرمز بالای منحنی سیگموید!با کنار هم قرار دادن همه این‌ها، چیزی شبیه به این به دست می‌آید: میله‌ها نشان‌دهنده احتمالات پیش‌بینی‌شده مرتبط با کلاس واقعی هر نقطه هستند!خب، حالا احتمالات پیش‌بینی‌شده را داریم... وقت آن است که با محاسبه آنتروپی متقاطع دودویی / زیان لگاریتمی آن‌ها را ارزیابی کنیم! این احتمالات تنها چیزی هستند که نیاز داریم، پس بیایید محور x را حذف کنیم و میله‌ها را کنار هم قرار دهیم.خب، میله‌های آویزان دیگر معنایی ندارند، پس بیایید آن‌ها را دوباره مرتب کنیم.از آنجا که هدف ما محاسبه زیان است، باید پیش‌بینی‌های بد را جریمه کنیم، درست است؟ اگر احتمال مرتبط با کلاس واقعی 1.0 باشد، زیان آن باید صفر باشد. برعکس، اگر این احتمال پایین باشد، مثلاً 0.01، زیان باید بسیار زیاد باشد!معلوم می‌شود که گرفتن لگاریتم منفی احتمال برای این منظور به خوبی کار می‌کند (چون لگاریتم مقادیر بین 0.0 و 1.0 منفی است، ما لگاریتم منفی را می‌گیریم تا مقدار مثبتی برای زیان به دست آید).در واقع، دلیل استفاده از لگاریتم به تعریف آنتروپی متقاطع برمی‌گردد، لطفاً برای جزئیات بیشتر بخش «ریاضیات را نشان بده» را در ادامه بررسی کنید.نمودار زیر تصویر واضحی به ما می‌دهد - هرچه احتمال پیش‌بینی‌شده کلاس واقعی به صفر نزدیک‌تر شود، زیان به صورت نمایی افزایش می‌یابد.عادلانه است! بیایید لگاریتم منفی احتمالات را بگیریم - این‌ها زیان‌های مربوط به هر یک از نقاط هستند. در نهایت، میانگین تمام این زیان‌ها را محاسبه می‌کنیم.و تمام! ما با موفقیت آنتروپی متقاطع دودویی / زیان لگاریتمی این مثال ساده را محاسبه کردیم. مقدار آن 0.3329 است!کد را نشان بدهاگر می‌خواهید مقدار به‌دست‌آمده را دوباره بررسی کنید، کافی است کد زیر را اجرا کنید و خودتان ببینید:from sklearn.linear_model import LogisticRegression
from sklearn.metrics import log_loss
import numpy as np

x = np.array([-2.2, -1.4, -.8, .2, .4, .8, 1.2, 2.2, 2.9, 4.6])
y = np.array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])

logr = LogisticRegression(solver=&#039;lbfgs&#039;)
logr.fit(x.reshape(-1, 1), y)

y_pred = logr.predict_proba(x.reshape(-1, 1))[:, 1].ravel()
loss = log_loss(y, y_pred)

print(&#039;x = {}&#039;.format(x))
print(&#039;y = {}&#039;.format(y))
print(&#039;p(y) = {}&#039;.format(np.round(y_pred, 2)))
print(&#039;Log Loss / Cross Entropy = {:.4f}&#039;.format(loss))ریاضیات را نشان بده (واقعاً؟!)جدا از شوخی، این پست قصد ندارد خیلی ریاضی‌محور باشد... اما برای شما خوانندگانی که می‌خواهید نقش آنتروپی و لگاریتم را در این موضوع درک کنید، برویم جلو.اگر می‌خواهید عمیق‌تر به نظریه اطلاعات، شامل آنتروپی، آنتروپی متقاطع و خیلی مفاهیم دیگر بپردازید، پست کریس اولا را ببینید؛ بسیار دقیق و کامل است!توزیعبیایید با توزیع نقاطمان شروع کنیم. چون y نشان‌دهنده کلاس‌های نقاط ماست (ما ۳ نقطه قرمز و ۷ نقطه سبز داریم)، توزیع آن، که آن را q(y) می‌نامیم، به این شکل است:آنتروپیآنتروپی معیاری از عدم قطعیتی است که با یک توزیع معین q(y) همراه است.اگر همه نقاطمان سبز بودند، عدم قطعیت آن توزیع چه می‌شد؟ صفر، درست است؟ چون هیچ شکی درباره رنگ یک نقطه وجود نداشت: همیشه سبز بود! پس آنتروپی صفر است!از طرف دیگر، اگر دقیقاً نصف نقاط سبز و نصف دیگر قرمز بودند، این بدترین حالت ممکن است، نه؟ هیچ مزیتی در حدس زدن رنگ یک نقطه نداشتیم: کاملاً تصادفی بود! در این حالت، آنتروپی با فرمول زیر محاسبه می‌شود (ما دو کلاس داریم — قرمز یا سبز — پس پایه ۲):برای هر حالت میانی دیگر، می‌توانیم آنتروپی توزیع q(y) را با فرمول زیر محاسبه کنیم، که C تعداد کلاس‌هاست:پس اگر توزیع واقعی یک متغیر تصادفی را بدانیم، می‌توانیم آنتروپی‌اش را محاسبه کنیم. اما اگر این‌طور باشد، چرا اصلاً زحمت آموزش یک طبقه‌بندی‌کننده را بکشیم؟ ما که توزیع واقعی را می‌دانیم...اما اگر ندانیم چه؟ آیا می‌توانیم توزیع واقعی را با توزیع دیگری، مثلاً p(y)، تقریب بزنیم؟ البته که می‌توانیم!آنتروپی متقاطعفرض کنیم نقاطمان از توزیع دیگری p(y) پیروی می‌کنند. اما ما می‌دانیم که در واقع از توزیع واقعی (ناشناخته) q(y) می‌آیند، درست است؟اگر آنتروپی را این‌گونه محاسبه کنیم، در واقع داریم آنتروپی متقاطع بین دو توزیع را محاسبه می‌کنیم:اگر به طور معجزه‌آسایی p(y) را کاملاً با q(y) منطبق کنیم، مقدار آنتروپی متقاطع و آنتروپی یکسان خواهد شد.چون این تقریباً هرگز اتفاق نمی‌افتد، آنتروپی متقاطع مقداری بزرگ‌تر از آنتروپی محاسبه‌شده روی توزیع واقعی خواهد داشت.این تفاوت بین آنتروپی متقاطع و آنتروپی نامی دارد...واگرایی کولبک-لیبلر (Kullback-Leibler Divergence)واگرایی کولبک-لیبلر یا به اختصار «واگرایی KL»، معیاری از ناهمسانی بین دو توزیع است:این یعنی هرچه p(y) به q(y) نزدیک‌تر شود، واگرایی و در نتیجه آنتروپی متقاطع کمتر خواهد شد.پس باید یک p(y) خوب پیدا کنیم... اما این دقیقاً کاری نیست که طبقه‌بندی‌کننده ما باید انجام دهد؟! و واقعاً هم همین کار را می‌کند! به دنبال بهترین p(y) ممکن می‌گردد، یعنی آن که آنتروپی متقاطع را کمینه کند.تابع زیاندر طول آموزش، طبقه‌بندی‌کننده از هر یک از N نقطه در مجموعه آموزشی برای محاسبه زیان آنتروپی متقاطع استفاده می‌کند و در واقع توزیع p(y) را برازش می‌دهد! چون احتمال هر نقطه ۱/N است، آنتروپی متقاطع به این شکل می‌شود:شکل‌های ۶ تا ۱۰ را یادتان هست؟ ما باید آنتروپی متقاطع را روی احتمالات مربوط به کلاس واقعی هر نقطه محاسبه کنیم. یعنی استفاده از میله‌های سبز برای نقاط کلاس مثبت (y=1) و میله‌های قرمز آویزان برای نقاط کلاس منفی (y=0) یا به زبان ریاضی:گام نهایی، محاسبه میانگین تمام نقاط در هر دو کلاس مثبت و منفی است:در نهایت، با کمی دستکاری، می‌توانیم هر نقطه‌ای را، چه از کلاس مثبت و چه منفی، زیر یک فرمول واحد بیاوریم:و تمام! دوباره به فرمول اصلی آنتروپی متقاطع دودویی / زیان لگاریتمی رسیدیم.سخن پایانیواقعاً امیدوارم این پست توانسته باشد نور تازه‌ای بر مفهومی بیندازد که اغلب بدون توجه پذیرفته می‌شود، یعنی آنتروپی متقاطع دودویی به عنوان تابع زیان. همچنین امیدوارم کمی نشان داده باشد که یادگیری ماشین و نظریه اطلاعات چقدر به هم مرتبط هستند.</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Tue, 11 Nov 2025 14:59:17 +0330</pubDate>
            </item>
                    <item>
                <title>چرا روایت‌گری با داده برای کسب‌وکارها و تحلیل‌گران داده اهمیت دارد</title>
                <link>https://virgool.io/@mojino/%DA%86%D8%B1%D8%A7-%D8%B1%D9%88%D8%A7%DB%8C%D8%AA-%DA%AF%D8%B1%DB%8C-%D8%A8%D8%A7-%D8%AF%D8%A7%D8%AF%D9%87-%D8%A8%D8%B1%D8%A7%DB%8C-%DA%A9%D8%B3%D8%A8-%D9%88%DA%A9%D8%A7%D8%B1%D9%87%D8%A7-%D9%88-%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%DA%AF%D8%B1%D8%A7%D9%86-%D8%AF%D8%A7%D8%AF%D9%87-%D8%A7%D9%87%D9%85%DB%8C%D8%AA-%D8%AF%D8%A7%D8%B1%D8%AF-pcdskfm9fqg9</link>
                <description>داده، آیندهٔ کسب‌وکار را هدایت می‌کند — و این‌طور می‌توانی برای آن آینده آماده شوی.✍️ نوشته: راشی دسای📅 ۱۰ نوامبر ۲۰۲۵برای هر سازمانی که با داده کار می‌کند — چه کوچک چه بزرگ — چیزی که واقعاً مسیر آینده را تعیین می‌کند، درک درست از آن داده‌هاست.به‌عنوان یک متخصص در زمینه‌ی داده یا تحلیل کسب‌وکار، نقش شما فراتر از تولید گزارش است؛ شما این قدرت را دارید که داده‌های خام را به روایت‌هایی تبدیل کنید که الهام‌بخش اقدام هستند.همه‌مان آن حس را می‌شناسیم: ساعت‌ها صرف ساخت داشبورد، گزارش شاخص‌های عملکرد یا تنظیم فایل‌های اکسل می‌کنیم، اما در نهایت ذی‌نفعان ما هنوز نمی‌توانند آن اعداد را به تصمیم‌های معنادار تبدیل کنند.اینجاست که روایتگری وارد می‌شود!با ذهنیت، ابزارها و رویکرد درست، می‌توانید از فرمول‌ها و نمودارها فراتر بروید و داده را به شکلی بیان کنید که استدلال‌های تجاری قوی‌تری بسازد، چابکی را افزایش دهد و هماهنگی میان تیم‌ها را تقویت کند.خیلی وقت‌ها تحلیل‌گران، داده را فقط به‌صورت ردیف‌ها و ستون‌هایی در یک فایل اکسل یا گزارش‌های سنگین به اشتراک می‌گذارند. پنج سال پیش خود من همین‌طور بودم: تمام اطلاعات موجود بود، اما تقریباً هیچ اقدامی بر اساس آن انجام نمی‌شد چون مصرف‌کنندگان داده نمی‌توانستند «نکته‌ی اصلی» را پیدا کنند.حالا این را مقایسه کنید با یک اسلاید جمع‌بندی قدرتمند: یک عنوان شفاف، تصاویر گویا، و یک پیشنهاد محکم و مختصر بر اساس داده‌های تحلیل‌شده — همان داده حالا ارزشمند، قابل اقدام و متقاعدکننده شده است.این همان تفاوت بین گزارش دادن اعداد و روایتگری با داده‌هاست.از تجربه‌ی من در همکاری با رهبران حوزه‌ی داده و حدود پنج سال فعالیت به‌عنوان مشاور تحلیل داده، یاد گرفته‌ام که روایتگری با داده همان چیزی است که اطلاعات خام را به بینش تبدیل می‌کند.در این مقاله، هدفم این است که روش‌های عملی را به اشتراک بگذارم تا بتوانید روایتگری با داده را آغاز کنید و تصمیم‌هایی هوشمندانه‌تر، سریع‌تر و مطمئن‌تر بگیرید — بدون آنکه در میان اعداد گم شوید.چطور می‌توانید به‌عنوان متخصص داده روایتگری را شروع کنید؟با پرسیدن سؤال‌های درست آغاز کنیدبسیاری از تحلیل‌گران، داده را صرفاً یک مؤلفه‌ی فنی می‌دانند، در حالی که می‌تواند بسیار فراتر از آن باشد.به داده به چشم شریک تصمیم‌سازی نگاه کنید. وقتی چنین دیدگاهی پیدا کنید، تحلیل شما به اقدام متصل می‌شود.برای شروع، این پرسش‌ها را بپرسید:چه تصمیمی می‌خواهم بگیرم؟چه داده‌هایی می‌توانند به این تصمیم کمک کنند؟چه بینش‌هایی کم دارم که مانع رسیدن به هدف می‌شوند؟این تغییر دیدگاه، نخستین گام برای حرکت از «گزارش‌دهی» به‌سوی «راهنمایی تصمیم‌های هوشمند» است.روی داده‌ی درست تمرکز کنید (نه همه‌ی داده‌ها)یکی از بزرگ‌ترین اشتباهاتی که باید از آن پرهیز کنیم، غرق شدن در داده‌های زیاد است.اعداد بیشتر لزوماً به معنی بینش بهتر نیستند.مهارت شما در این است که تشخیص دهید کدام داده بیشترین ارزش را دارد، نویزها را فیلتر کنید و روی اطلاعاتی تمرکز کنید که مستقیماً به هدف شما کمک می‌کنند.چگونه شاخص‌های قابل اقدام را تشخیص دهیماهداف خود را مشخص کنید: آیا به دنبال رشد هستید؟ کارایی؟ رضایت مشتری؟از شاخص‌های پیش‌نگر استفاده کنید: به‌جای تمرکز بر عملکرد گذشته، به علائمی نگاه کنید که موفقیت آینده را پیش‌بینی می‌کنند (مثلاً تعامل مشتری امروز می‌تواند حفظ او در آینده را پیش‌بینی کند).ساده نگه دارید: اگر یک شاخص کمکی به تصمیم‌گیری نمی‌کند، احتمالاً فقط نویز است.برای مثال، یک گزارش فروش ممکن است شامل ۲۰۰ ستون و هزاران ردیف باشد، اما به‌جای دنبال کردن همه‌چیز، پرسش‌های دقیق‌تر این است که:کدام مشتریان سریع‌تر به پول تبدیل می‌شوند؟ کدام استراتژی‌ها معاملات را زودتر می‌بندند؟ چه الگوهایی بیشترین درآمد را ایجاد می‌کنند؟اینجاست که اقدام واقعی اتفاق می‌افتد.در تیم خود فرهنگ داده‌محور بسازیدشما تحلیل‌گر داده هستید، اما اگر اعضای تیم‌تان را نیز به استفاده از داده ترغیب کنید، تأثیرتان چند برابر می‌شود.وقتی همه ارزش روایتگری با داده را درک کنند، تصمیم‌ها مؤثرتر خواهند شد.چطور تیمی داده‌محور بسازیمروایتگری را تشویق کنید: از اعضای تیم بخواهید نتایج خود را نه فقط با اعداد، بلکه با زمینه، روند و پیشنهادات عملی ارائه دهند.سادگی را حفظ کنید: داشبوردها و گزارش‌هایی بسازید که برای افراد غیر‌فنی نیز قابل درک باشند.در جلسات از داده بپرسید: هنگام بحث درباره‌ی چالش‌ها یا فرصت‌ها، سؤال کنید: «داده در این باره چه می‌گوید؟»تیمی که در هر سطح از داده استفاده می‌کند، بسیار چابک‌تر و مؤثرتر تصمیم می‌گیرد.فراتر از داده بروید و اثرگذاری را بیان کنیدتحلیل داده نباید فقط درباره‌ی اعداد باشد؛ باید روایتی بسازد که منجر به اقدام شود.برای تبدیل تحلیل به روایت‌های قدرتمند کسب‌وکاری:چرخه‌های تصمیم‌گیری روایی بسازید: به‌جای انتظار برای داده‌های کامل، از چرخه‌های کوچک و تکرارشونده استفاده کنید تا داده را بررسی و روایت خود را اصلاح کنید. نتایج کوتاه‌مدت را با روندهای بلندمدت مقایسه کنید تا نشان دهید هر تصمیم چگونه به تصویر بزرگ‌تر کمک می‌کند.از تحلیل پیش‌بینانه استفاده کنید: مدل‌های پیش‌بینی، داده‌های تاریخی را به داستان‌های آینده‌نگر تبدیل می‌کنند. مثلاً شرکت‌های خرده‌فروشی از الگوهای فروش برای پیش‌بینی رفتار مشتری و طراحی کمپین‌هایی استفاده می‌کنند که با نیاز آینده سازگار باشند.از هوش مصنوعی و خودکارسازی بهره ببرید: ابزارهای هوش مصنوعی می‌توانند مجموعه‌داده‌های بزرگ را سریع تحلیل کنند و بینش‌هایی کشف کنند که انسان‌ها دیرتر متوجه می‌شوند. خودکارسازی هم باعث می‌شود تحلیل‌گران بر «چرایی» پشت اعداد تمرکز کنند — یعنی ساخت بینش‌هایی که الهام‌بخش تصمیم‌های مطمئن و مؤثر است.برنامه‌ی اقدام شما برای شروع روایتگری با دادهبرای اینکه بینش‌های شما واقعاً در ذهن مخاطبان بنشیند، باید از چارچوب صرفاً تحلیلی فراتر بروید و مثل یک راوی فکر کنید:اهداف کسب‌وکار را مشخص کنید: مسئله یا فرصت تصمیم‌گیری را به‌وضوح تعریف کنید. با ذی‌نفعان مصاحبه کنید و زمینه‌ی تجاری را بشناسید تا در انتخاب داده راهنمایتان باشد.روایت خود را تعریف کنید: هر داستان عالی با هدفی مشخص شروع می‌شود. تعیین کنید چه تصمیم یا پرسشی را می‌خواهید تحت تأثیر قرار دهید.داده‌ی شکل‌دهنده‌ی روایت را انتخاب کنید: نه همه‌ی داده‌ها ارزش استفاده دارند. مشخص کنید چه اعداد و روندهایی توضیح می‌دهند «چه اتفاقی افتاده» و «چرا».شکاف‌هایی که ممکن است روایت را تغییر دهند کجاست؟آیا بر شاخص‌های آینده‌نگر تمرکز دارید یا فقط داده‌های گذشته؟داده را کاوش و تجسم کنید: منابع، داشبوردها و ابزارهای تحلیلی را بررسی کنید تا الگوها و تم‌ها را کشف کنید. تحلیل درست می‌تواند تأثیر بالقوه‌ی هر گزینه را کمی‌سازی کرده و انتخاب را عینی‌تر کند.چرایی را بیان کنید، نه فقط چیستی را: اعداد می‌گویند چه اتفاقی افتاده، اما داستان توضیح می‌دهد چرا اهمیت دارد. یافته‌ها را به بینش‌هایی تبدیل کنید که مخاطب بتواند با آن ارتباط برقرار کند.روایت را منتشر و اثر آن را دنبال کنید: برنامه‌ای روشن برای به‌اشتراک‌گذاری داستان داده‌ای خود طراحی کنید و شاخص‌هایی برای ارزیابی اثر آن تعیین کنید. از بازخوردها برای اصلاح داستان و سنجش اقداماتی که الهام گرفته‌اند استفاده کنید.بهترین رهبران فقط داده جمع‌آوری نمی‌کنند؛ بلکه آن را برای تصمیم‌گیری‌های هوشمند و مطمئن به کار می‌برند.با تغییر ذهنیت، تمرکز بر اعداد درست، ایجاد فرهنگ داده‌محور و پرهیز از اشتباهات رایج، می‌توانید داده‌های خام را به اقدام تجاری شفاف و مؤثر تبدیل کنید.آماده‌اید داده را در خدمت خودتان بگیرید؟از همین امروز با یک تصمیم شروع کنید — و بگذارید روایتگری مسیر را نشان دهد.پایان مقاله.راشی یک متخصص داده از شیکاگو است که عاشق تحلیل داده و ساخت روایت‌های داده‌ای برای انتقال بینش‌هاست. او مشاور تحلیل داده در حوزه‌ی سلامت است و در آخر هفته‌ها با یک فنجان قهوه درباره‌ی داده می‌نویسد. ☕</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Tue, 11 Nov 2025 11:40:14 +0330</pubDate>
            </item>
                    <item>
                <title>فصل 1. سازماندهی داده ها: موقعیت ، دامنه ، عمل و اعتبار</title>
                <link>https://virgool.io/mojino/%D9%81%D8%B5%D9%84-1-%D8%B3%D8%A7%D8%B2%D9%85%D8%A7%D9%86%D8%AF%D9%87%DB%8C-%D8%AF%D8%A7%D8%AF%D9%87-%D9%87%D8%A7-%D9%85%D9%88%D9%82%D8%B9%DB%8C%D8%AA-%D8%AF%D8%A7%D9%85%D9%86%D9%87-%D8%B9%D9%85%D9%84-%D9%88-%D8%A7%D8%B9%D8%AA%D8%A8%D8%A7%D8%B1-ds8ls9d1rsrz</link>
                <description>تحلیل امنیتی فرآیند استفاده از داده‌ها برای تصمیم‌گیری‌های امنیتی است. تصمیمات امنیتی معمولاً مخل و محدودکننده هستند—مخل به این دلیل که چیزی را اصلاح می‌کنید، و محدودکننده به این دلیل که رفتارها را محدود می‌کنید. تحلیل امنیتی مؤثر نیازمند اتخاذ تصمیم درست و متقاعد کردن مخاطبی شکاک به درستی این تصمیم است. پایه‌های این تصمیمات، داده‌های باکیفیت و استدلال باکیفیت هستند؛ در این فصل به هر دو مورد پرداخته می‌شود.نظارت امنیتی در شبکه‌های مدرن نیازمند کار با حسگرهای متعددی است که انواع مختلفی از داده‌ها را تولید می‌کنند و توسط افراد مختلف برای اهداف گوناگون ایجاد شده‌اند. حسگر می‌تواند هر چیزی باشد، از یک دستگاه شنود شبکه تا گزارش‌های فایروال؛ چیزی که اطلاعات شبکه شما را جمع‌آوری می‌کند و می‌تواند برای قضاوت درباره امنیت شبکه استفاده شود.می‌خواهم نکته‌ای بسیار مهم را برجسته کنم: داده‌های منبع باکیفیت برای تحلیل امنیتی خوب ضروری هستند. علاوه بر این، تلاش برای به‌دست آوردن منبع داده‌ای باکیفیت و پایدار در ادامه فرآیند تحلیل نتیجه می‌دهد—می‌توانید از الگوریتم‌های ساده‌تر (و سریع‌تر) برای شناسایی پدیده‌ها استفاده کنید، تأیید نتایج آسان‌تر خواهد بود و زمان کمتری برای تطبیق و بررسی دوباره اطلاعات صرف خواهید کرد.حالا که مشتاق جمع‌آوری داده‌های باکیفیت هستید، سؤال واضحی پیش می‌آید: داده باکیفیت چیست؟ پاسخ این است که جمع‌آوری داده‌های امنیتی یک تعادل بین بیان‌گری(expressiveness) و سرعت(speed) است—داده‌های ضبط بسته (pcap) از یک پورت span می‌توانند نشان دهند که آیا کسی در حال اسکن شبکه شما است، اما ترافیک غیرقابل خواندنی از سرور HTTPS که نظارت می‌کنید، چندین ترابایت تولید خواهد کرد. گزارش‌های سرور HTTPS اطلاعاتی درباره دسترسی به فایل‌ها ارائه می‌دهند، اما هیچ اطلاعاتی درباره تعاملات FTP ندارند. سؤالاتی که می‌پرسید نیز به موقعیت بستگی دارد—نحوه برخورد با یک تهدید مداوم پیشرفته (APT) به میزان ریسکی که با آن مواجه هستید بستگی دارد و این ریسک با زمان تغییر می‌کند.با این حال، می‌توانیم اهداف اساسی برای داده‌های امنیتی تعیین کنیم. ما می‌خواهیم داده‌ها تا حد ممکن اطلاعات را با کمترین حجم بیان کنند—بنابراین داده‌ها باید در قالبی فشرده باشند و اگر حسگرهای مختلف یک رویداد را گزارش کنند، این توضیحات نباید زائد باشند. می‌خواهیم داده‌ها تا حد ممکن در زمان مشاهده دقیق باشند، بنابراین اطلاعاتی که گذرا هستند (مانند رابطه بین آدرس‌های IP و نام‌های دامنه) باید در زمان جمع‌آوری ثبت شوند. همچنین می‌خواهیم داده‌ها بیان‌گر باشند؛ یعنی زمان و تلاشی که تحلیلگر برای تطبیق اطلاعات صرف می‌کند، کاهش یابد. در نهایت، می‌خواهیم هرگونه استنباط یا تصمیم در داده‌ها قابل پاسخگویی باشد؛ برای مثال، اگر هشداری به دلیل یک قاعده ایجاد شود، می‌خواهیم تاریخچه و منشأ آن قاعده را بدانیم.اگرچه نمی‌توانیم برای همه این معیارها بهینه‌سازی کنیم، می‌توانیم از آن‌ها به‌عنوان راهنما برای متعادل کردن این نیازها استفاده کنیم. نظارت مؤثر نیازمند مدیریت حسگرهای متعدد با انواع مختلف است که داده‌ها را به شکل‌های متفاوتی پردازش می‌کنند. برای کمک به این موضوع، حسگرها را بر اساس سه ویژگی دسته‌بندی می‌کنم:موقعیت حسگر (Vantage):  مکان قرارگیری حسگرها در شبکه. حسگرهایی با موقعیت برتر مختلف، بخش‌های متفاوتی از یک رویداد را می‌بینند.حوزه (Domain):  اطلاعاتی که حسگر ارائه می‌دهد، چه در سطح میزبان، یک سرویس روی میزبان یا شبکه. حسگرهایی با موقعیت برتر یکسان اما حوزه‌های متفاوت، داده‌های مکمل درباره یک رویداد ارائه می‌دهند. برای برخی رویدادها، ممکن است فقط از یک حوزه اطلاعات دریافت کنید. برای مثال، نظارت بر میزبان تنها راه برای فهمیدن دسترسی فیزیکی به یک میزبان است.اقدام (Action):  نحوه گزارش اطلاعات توسط حسگر. ممکن است داده‌ها را فقط ضبط کند، رویدادها را ارائه دهد یا ترافیکی که داده‌ها را تولید می‌کند، دستکاری کند. حسگرهایی با اقدامات مختلف ممکن است با یکدیگر تداخل داشته باشند.این دسته‌بندی دو هدف دارد. اول، راهی برای تجزیه و طبقه‌بندی حسگرها بر اساس نحوه برخورد آن‌ها با داده‌ها فراهم می‌کند. حوزه، توصیفی کلی از مکان و نحوه جمع‌آوری داده‌هاست. دیدگاه به ما اطلاع می‌دهد که مکان حسگر چگونه بر جمع‌آوری تأثیر می‌گذارد. اقدام توضیح می‌دهد که حسگر چگونه داده‌ها را دستکاری می‌کند. این ویژگی‌ها با هم چالش‌هایی که جمع‌آوری داده برای اعتبار نتیجه‌گیری‌های تحلیلگر ایجاد می‌کند، تعریف می‌کنند.اعتبار ایده‌ای از طراحی آزمایش است و به قوت یک استدلال اشاره دارد. استدلال معتبر استدلالی است که نتیجه آن به‌صورت منطقی از مقدماتش دنبال شود؛ استدلال‌های ضعیف می‌توانند از چندین جهت به چالش کشیده شوند و طراحی آزمایش بر شناسایی این چالش‌ها تمرکز دارد. دلیل اهمیت این موضوع برای افراد امنیتی به نکته‌ای در مقدمه بازمی‌گردد: تحلیل امنیتی درباره متقاعد کردن مخاطبی است که تمایلی به ارزیابی منطقی یک تصمیم امنیتی و انتخاب پذیرش یا رد آن دارد. درک اعتبار و چالش‌های آن، نتایج بهتر و تحلیل‌های واقع‌بینانه‌تری تولید می‌کند.به طور خلاصه:موقعیت حسگر: حسگر کجا ایستاده؟دامنه: حسگر به چه چیزی نگاه می‌کند؟اقدام: حسگر با اطلاعاتی که بدست آورده  چه کاری انجام می‎‌دهد؟اعتبار: چقدر می‌توانیم به نتیجه‌ یا خروجی مطمئن باشیم؟این‌ها کمک می‌کند بفهمید داده‌های چطور جمع شده‌اند و چقدر می‌توانیم  برای تصمیم‌گیری به آن‌ها اعتماد کنیم.دامنه (Domain)اکنون به بررسی دقیق‌تر مفاهیم دامنه، موقعیت و اقدام می‌پردازیم. دامنه حسگر به نوع داده‌هایی اشاره دارد که حسگر تولید کرده و گزارش می‌دهد. از آنجا که حسگرها شامل ابزارهایی مانند آنتی‌ویروس نیز می‌شوند و گاه منطق پشت پیام‌هایشان چندان شفاف نیست، تحلیلگر باید آگاه باشد که این ابزارها ممکن است با پیش‌داوری‌های خاص خود همراه باشند.جدول 1-1 چهار دسته اصلی دامنه را که در این کتاب به کار رفته‌اند، تشریح می‌کند. این جدول دامنه‌ها را بر اساس مدل رویداد و نوع حسگر تقسیم‌بندی کرده و توضیحات بیشتری در پی می‌آید.حسگرهای دامنه شبکه: این حسگرها داده‌های خود را از نوعی ضبط بسته، مانند pcap، سرآیند بسته‌ها یا ساختارهایی نظیر NetFlow به دست می‌آورند. داده‌های شبکه دیدی گسترده از شبکه فراهم می‌کنند، اما در مقایسه با حجم داده‌های جمع‌آوری‌شده، اطلاعات مفید کمتری دارند. این داده‌ها باید تفسیر شوند، قابل خواندن باشند و معنادار باشند؛ زیرا ترافیک شبکه مملو از اطلاعات غیرضروری است.حسگرهای دامنه سرویس: حسگرهای دامنه سرویس داده‌های خود را از سرویس‌ها به دست می‌آورند. نمونه‌هایی از این سرویس‌ها شامل برنامه‌های سروری مانند nginx یا apache (سرورهای HTTP) و همچنین فرآیندهای داخلی نظیر syslog و فرآیندهایی که توسط آن مدیریت می‌شوند، است. داده‌های سرویس اطلاعاتی درباره آنچه واقعاً رخ داده ارائه می‌دهند، اما این کار از طریق تفسیر داده‌ها و ارائه یک مدل رویداد انجام می‌شود که ممکن است تنها به‌صورت غیرمستقیم با واقعیت مرتبط باشد. علاوه بر این، برای جمع‌آوری داده‌های سرویس، باید از وجود سرویس آگاه باشید، که با توجه به تمایل تولیدکنندگان سخت‌افزار به گنجاندن وب‌سرور در هر پورت باز، گاهی به‌طور شگفت‌انگیزی دشوار است.حسگرهای دامنه میزبان: حسگرهای دامنه میزبان اطلاعاتی درباره وضعیت میزبان جمع‌آوری می‌کنند. برای اهداف ما، این نوع ابزارها در دو دسته جای می‌گیرند: سیستم‌هایی که اطلاعاتی درباره وضعیت سیستم، مانند فضای دیسک، ارائه می‌دهند و سیستم‌های تشخیص نفوذ مبتنی بر میزبان، مانند نظارت بر یکپارچگی فایل(FIM) یا سیستم‌های آنتی‌ویروس. این حسگرها اطلاعاتی درباره تأثیر اقدامات بر میزبان فراهم می‌کنند، اما ممکن است با مشکلات زمانی مواجه شوند؛ بسیاری از سیستم‌های مبتنی بر وضعیت در فواصل زمانی ثابت هشدار می‌دهند و سیستم‌های تشخیص نفوذ اغلب از کتابخانه‌های امضای بزرگ استفاده می‌کنند که به‌صورت نامنظم به‌روزرسانی می‌شوند.دامنه فعال: این دامنه شامل حسگرهایی است که تحت کنترل تحلیلگر عمل می‌کنند، مانند اسکن برای یافتن آسیب‌پذیری‌ها، ابزارهای نقشه‌برداری مانند traceroute یا حتی برقراری ارتباط ساده با یک وب‌سرور جدید برای درک عملکرد آن. داده‌های فعال همچنین شامل سیگنال‌دهی (beaconing) و اطلاعاتی است که برای اطمینان از وقوع یک رویداد ارسال می‌شوند.موقعیت حسگر(Vantage)موقعیت حسگر به بسته‌هایی اشاره دارد که حسگر قادر به مشاهده آن‌هاست. این موقعیت از تعامل بین محل قرارگیری حسگر و ساختار مسیریابی شبکه تعیین می‌شود. برای درک عواملی که بر موقعیت اثر می‌گذارند، به شکل 1-1 توجه کنید. این شکل حسگرهای مختلفی را با حروف بزرگ مشخص کرده است:A: رابط میان روتر و اینترنت را نظارت می‌کند.B: رابط میان روتر و سوئیچ را زیر نظر دارد.C: رابط میان روتر و میزبان با آدرس IP 128.2.1.1 را بررسی می‌کند.D: میزبان 128.1.1.1 را نظارت می‌کند.E: پورت span سوئیچ را رصد می‌کند (پورت span همه ترافیک عبوری از سوئیچ را ضبط می‌کند).F: رابط میان سوئیچ و هاب را نظارت می‌کند.G: گزارش‌های HTTP روی میزبان 128.1.1.2 را جمع‌آوری می‌کند.H: همه ترافیک TCP روی هاب را شنود می‌کند.شکل 1-1. نقاط برتر یک شبکه ساده و یک نمودار گرافیهر یک از این حسگرها موقعیت متفاوتی دارند و بر اساس آن، ترافیک متفاوتی را مشاهده می‌کنند. می‌توانید موقعیت یک شبکه را با تبدیل آن به یک گراف ساده گره و لینک (مانند گوشه شکل 1-1) تخمین بزنید و سپس لینک‌هایی که بین گره‌ها عبور می‌کنند را ردیابی کنید. هر لینک می‌تواند ترافیکی را که از آن عبور می‌کند ثبت کند. برای مثال، در شکل 1-1:حسگر A تنها ترافیک میان شبکه و اینترنت را می‌بیند و مثلاً ترافیک بین 128.1.1.1 و 128.2.1.1 را مشاهده نمی‌کند.حسگر B هر ترافیکی را که از آدرس‌های زیرین خود آغاز یا به آن‌ها ختم شود (مانند 128.2.1.1 یا اینترنت) می‌بیند.حسگر C تنها ترافیک مربوط به 128.2.1.1 را مشاهده می‌کند.حسگر D، مانند C، فقط ترافیک مربوط به 128.1.1.1 را می‌بیند.حسگر E هر ترافیکی را که بین پورت‌های سوئیچ جابه‌جا شود (مانند ترافیک 128.1.1.1 یا 128.1.1.2 به هر مقصد دیگر) می‌بیند.حسگر F زیرمجموعه‌ای از آنچه E می‌بیند را مشاهده می‌کند، یعنی فقط ترافیک 128.1.1.3 تا 128.1.1.32 که به بیرون از هاب می‌رود.حسگر G خاص است، زیرا تنها گزارش‌های HTTP/S (پورت‌های 80 و 443) را برای 128.1.1.2 می‌بیند.حسگر H هر ترافیکی را که مبدأ یا مقصد آن بین 128.1.1.3 تا 128.1.1.32 باشد، مشاهده می‌کند.هیچ حسگری به‌تنهایی کل شبکه را پوشش نمی‌دهد. علاوه بر این، باید با ترافیک تکراری کنار آمد. برای مثال، اگر حسگرهای H و E را فعال کنید، ترافیک از 128.1.1.3 به 128.1.1.1 را دو بار خواهید دید. انتخاب موقعیت‌های مناسب نیازمند ایجاد تعادل بین پوشش کامل ترافیک و اجتناب از غرق شدن در داده‌های تکراری است.انتخاب موقعیت حسگر (Vantage)هنگام نصب و پیکربندی ابزارهای نظارتی در یک شبکه، تعیین موقعیت حسگر (vantage) فرآیندی سه‌مرحله‌ای است: تهیه نقشه شبکه، شناسایی موقعیت‌های بالقوه برای نصب حسگرها، و سپس تعیین پوشش بهینه.مرحله اول: تهیه نقشه شبکه اولین گام شامل تهیه نقشه‌ای از شبکه و نحوه اتصال اجزای آن، همراه با فهرستی از موقعیت‌های بالقوه برای نصب حسگرها است. شکل ۱-۱ نسخه‌ای ساده‌شده از چنین نقشه‌ای را نشان می‌دهد.مرحله دوم: تعیین موقعیت حسگر هر مکان این مرحله شامل شناسایی تمام مکان‌های قابل تنظیم برای نصب حسگرها در شبکه و سپس تعیین دامنه دید هر یک از این موقعیت‌ها است. این دامنه دید می‌تواند به‌صورت مجموعه‌ای از ترکیب‌های آدرس IP و پورت بیان شود. جدول ۱-۲ نمونه‌ای از این فهرست را برای شکل ۱-۱ نشان می‌دهد. استفاده از گراف می‌تواند تخمین اولیه‌ای از آنچه هر موقعیت حسگر مشاهده می‌کند ارائه دهد، اما برای مدل‌سازی دقیق‌تر، نیاز به اطلاعات عمیق‌تری درباره مسیریابی و سخت‌افزار شبکه است. برای مثال، هنگام کار با روترها، ممکن است موقعیت‌هایی وجود داشته باشند که دید آن‌ها نامتقارن باشد (توجه کنید که ترافیک در جدول ۱-۲ همگی متقارن است). برای اطلاعات بیشتر، به بخش «مبانی لایه‌بندی شبکه» در صفحه ۱۹ مراجعه کنید.مرحله سوم: انتخاب موقعیت‌های حسگر بهینه آخرین گام، انتخاب موقعیت‌های حسگر بهینه از فهرست تهیه‌شده است. هدف، انتخاب مجموعه‌ای از موقعیت‌ها است که نظارت را با حداقل افزونگی (redundancy) فراهم کنند. برای مثال، حسگر E مجموعه‌ای کامل‌تر از داده‌های حسگر F ارائه می‌دهد، بنابراین دلیلی برای استفاده از هر دو وجود ندارد. انتخاب موقعیت‌های حسگر معمولاً با مقداری افزونگی همراه است که گاهی می‌توان با استفاده از قوانین فیلتر کردن آن را محدود کرد. برای نمونه، برای تنظیم حسگرها برای ترافیک بین میزبان‌های ۱۲۸.۱.۱.۳–۳۲، باید موقعیت H تنظیم شود، اما این ترافیک در موقعیت‌های E، F، B و A نیز ظاهر خواهد شد. اگر حسگرهای این موقعیت‌ها طوری تنظیم شوند که ترافیک ۱۲۸.۱.۱.۳–۳۲ را گزارش نکنند، مسئله افزونگی برطرف می‌شود.اقدامات: حسگرها با داده‌ها چه می‌کنند؟ اقدام یک حسگر، نحوه تعامل آن با داده‌های جمع‌آوری‌شده را توصیف می‌کند. بسته به حوزه کاری، حسگرها می‌توانند اقدامات متفاوتی انجام دهند که هر یک تأثیری متفاوت بر اعتبار خروجی دارند:گزارش (Report) حسگرهای گزارش‌دهنده صرفاً اطلاعاتی درباره تمام پدیده‌هایی که مشاهده می‌کنند ارائه می‌دهند. این حسگرها ساده هستند و برای ایجاد خط مبنا (baselining) اهمیت دارند. همچنین برای توسعه امضاها و هشدارها برای پدیده‌هایی که حسگرهای کنترلی هنوز برای شناسایی آن‌ها پیکربندی نشده‌اند، مفیدند. نمونه‌های حسگرهای گزارش‌دهنده شامل جمع‌آوری‌کننده‌های NetFlow، ابزار tcpdump و لاگ‌های سرور هستند.رویداد (Event) حسگرهای رویداد برخلاف حسگرهای گزارش‌دهنده، از چندین منبع داده استفاده می‌کنند تا رویدادی را تولید کنند که خلاصه‌ای از بخشی از آن داده‌ها باشد. برای مثال، یک سیستم تشخیص نفوذ مبتنی بر میزبان (IDS) ممکن است تصویر حافظه را بررسی کند، امضای بدافزار را در حافظه بیابد و رویدادی تولید کند که نشان‌دهنده به خطر افتادن میزبان توسط بدافزار است. در حالت‌های پیشرفته، حسگرهای رویداد مانند جعبه‌های سیاهی عمل می‌کنند که بر اساس فرآیندهای داخلی طراحی‌شده توسط متخصصان، رویداد تولید می‌کنند. این حسگرها شامل سیستم‌های تشخیص نفوذ (IDS) و آنتی‌ویروس‌ها (AV) هستند.کنترل (Control) حسگرهای کنترلی مانند حسگرهای رویداد، از چندین منبع داده استفاده می‌کنند و پیش از واکنش، قضاوتی درباره داده‌ها انجام می‌دهند. اما برخلاف حسگرهای رویداد، حسگرهای کنترلی هنگام تولید رویداد، ترافیک را اصلاح یا مسدود می‌کنند. این حسگرها شامل سیستم‌های پیشگیری از نفوذ (IPS)، فایروال‌ها، سیستم‌های ضد هرزنامه و برخی سیستم‌های آنتی‌ویروس هستند.اقدام یک حسگر نه‌تنها بر نحوه گزارش داده‌ها تأثیر می‌گذارد، بلکه بر نحوه تعامل آن با داده‌های مشاهده‌شده نیز اثر دارد. حسگرهای کنترلی می‌توانند ترافیک را اصلاح یا مسدود کنند.شکل ۱-۲ نشان می‌دهد که حسگرهای با سه نوع اقدام مختلف چگونه با داده‌ها تعامل می‌کنند. این شکل کار سه حسگر را نشان می‌دهد: R (حسگر گزارش‌دهنده)، E (حسگر رویداد) و C (حسگر کنترلی). حسگرهای رویداد و کنترلی سیستم‌های تطبیق امضا هستند که به بردار حمله  واکنش نشان می‌دهند. هر حسگر بین اینترنت و یک هدف واحد قرار گرفته است.حسگر R (گزارش‌دهنده) صرفاً ترافیک مشاهده‌شده را گزارش می‌کند. در این مورد، هم ترافیک عادی و هم ترافیک حمله را بدون تأثیر بر ترافیک گزارش می‌دهد و به‌طور مؤثری داده‌های مشاهده‌شده را خلاصه می‌کند. حسگر E (رویداد) در حضور ترافیک عادی کاری انجام نمی‌دهد، اما هنگام مشاهده ترافیک حمله، رویدادی تولید می‌کند. این حسگر ترافیک را متوقف نمی‌کند؛ فقط رویداد را ارسال می‌کند. حسگر C (کنترلی) هنگام مشاهده ترافیک حمله، رویدادی تولید می‌کند و به ترافیک عادی واکنشی نشان نمی‌دهد. اما علاوه بر این، حسگر C ترافیک غیرعادی را از رسیدن به هدف مسدود می‌کند. اگر حسگر دیگری در مسیر پس از C قرار داشته باشد، ترافیکی که C مسدود کرده را هرگز نخواهد دید.شکل 1-2. سه عمل سنسور مختلفاعتبار و اقدام اعتبار (Validity) مفهومی است که در طراحی آزمایش‌ها استفاده می‌شود. اعتبار یک استدلال به قدرت آن استدلال و میزان معقول بودن ارتباط بین مقدمه و نتیجه اشاره دارد. استدلال‌های معتبر ارتباط قوی دارند، در حالی که استدلال‌های با اعتبار ضعیف به‌راحتی قابل چالش هستند.برای تحلیلگران امنیتی، اعتبار نقطه شروع خوبی برای شناسایی چالش‌هایی است که تحلیل آن‌ها با آن مواجه خواهد شد (و قطعاً چالش‌هایی وجود خواهد داشت). آیا مطمئن هستید که حسگر درست کار می‌کند؟ آیا این تهدید واقعی است؟ چرا باید این سیستم حیاتی را به‌روزرسانی کنیم؟ امنیت در اکثر سازمان‌ها یک مرکز هزینه است و شما باید بتوانید هزینه‌هایی که اعمال می‌کنید را توجیه کنید. اگر نتوانید به چالش‌های داخلی پاسخ دهید، در برابر چالش‌های خارجی نیز موفق نخواهید بود.این بخش مقدمه‌ای کوتاه درباره اعتبار است. من در طول کتاب به این موضوع بازمی‌گردم و چالش‌های خاص را در زمینه‌های مختلف بررسی می‌کنم. ابتدا می‌خواهم واژگان کاری را معرفی کنم و با چهار دسته اصلی که در تحقیقات استفاده می‌شوند شروع کنم. در ادامه این دسته‌ها را به‌صورت خلاصه معرفی می‌کنم و سپس در بخش‌های بعدی به‌طور عمیق‌تر بررسی می‌کنم. چهار نوع اعتبار که در نظر می‌گیریم عبارت‌اند از:اعتبار داخلی (Internal) اعتبار داخلی یک استدلال به رابطه علت و معلولی اشاره دارد. اگر آزمایشی را به‌صورت «اگر A را انجام دهم، B اتفاق می‌افتد» توصیف کنیم، اعتبار داخلی به این موضوع می‌پردازد که آیا A به B مرتبط است یا خیر، و آیا عوامل دیگری وجود دارند که ممکن است بر این رابطه تأثیر بگذارند و مورد توجه قرار نگرفته باشند.اعتبار خارجی (External) اعتبار خارجی به قابلیت تعمیم نتایج یک آزمایش به دنیای واقعی اشاره دارد. آزمایشی با اعتبار خارجی قوی، داده‌ها و روش‌های آزمایش آن منعکس‌کننده دنیای واقعی هستند.اعتبار آماری (Statistical) اعتبار آماری به استفاده صحیح از روش‌ها و تکنیک‌های آماری در تفسیر داده‌های جمع‌آوری‌شده اشاره دارد.اعتبار سازه‌ای (Construct) سازه سیستمی رسمی برای توصیف یک رفتار است که می‌توان آن را آزمایش یا چالش کرد. برای مثال، اگر بخواهم ثابت کنم کسی در حال انتقال فایل در شبکه است، ممکن است حجم داده منتقل‌شده را به‌عنوان سازه استفاده کنم. اعتبار سازه‌ای به این موضوع می‌پردازد که آیا این سازه‌ها معنادار هستند، آیا دقیق‌اند، آیا قابل‌تکرارند و آیا می‌توان آن‌ها را به چالش کشید.در طراحی آزمایش‌ها، اعتبار اثبات نمی‌شود، بلکه به چالش کشیده می‌شود. این وظیفه پژوهشگر است که نشان دهد اعتبار مورد توجه قرار گرفته است. این موضوع چه برای دانشمندی که آزمایش انجام می‌دهد و چه برای تحلیلگر امنیتی که تصمیم مسدودسازی را توضیح می‌دهد، صادق است. شناسایی چالش‌های اعتبار مسئله‌ای مرتبط با تخصص است—اعتبار یک مسئله پویا است و حوزه‌های مختلف از زمان توسعه این مفهوم، تهدیدهای متفاوتی برای اعتبار شناسایی کرده‌اند.برای مثال، جامعه‌شناسان دسته اعتبار خارجی را به زیرمجموعه‌های اعتبار جمعیتی (population validity) و اعتبار زیست‌محیطی (ecological validity) تقسیم کرده‌اند. اعتبار جمعیتی به قابلیت تعمیم نمونه‌گیری جمعیت به کل جهان اشاره دارد و اعتبار زیست‌محیطی به قابلیت تعمیم محیط آزمایش به واقعیت اشاره می‌کند. به‌عنوان پرسنل امنیتی، ما نیز باید چالش‌های مشابهی را برای اعتبار داده‌هایمان در نظر بگیریم که از رفتارهای پیچیده مهاجمان ناشی می‌شوند.اعتبار داخلیاعتبار داخلی یک استدلال به رابطه علت و معلولی در یک آزمایش اشاره دارد. یک آزمایش زمانی از اعتبار داخلی قوی برخوردار است که بتوان به‌طور معقول پذیرفت که نتیجه مشاهده‌شده ناشی از علتی است که آزمایشگر فرض کرده است. در مورد اعتبار داخلی، تحلیلگر امنیتی باید به‌ویژه به مسائل زیر توجه کند:زمان‌بندی زمان‌بندی در اینجا به فرآیند جمع‌آوری داده‌ها و ارتباط آن با پدیده مشاهده‌شده اشاره دارد. همبستگی بین داده‌های امنیتی و رویدادها نیازمند درک روشنی از چگونگی و زمان جمع‌آوری داده‌هاست. این موضوع به‌ویژه هنگام مقایسه داده‌هایی مانند NetFlow (که زمان‌بندی جریان‌ها تحت تأثیر مسائل مدیریت حافظه نهان جمع‌آوری‌کننده جریان قرار می‌گیرد) یا داده‌های نمونه‌برداری‌شده مانند وضعیت سیستم، چالش‌برانگیز است. برای رفع این مسائل زمان‌بندی، باید از ثبت دقیق سوابق شروع کرد—یعنی نه‌تنها درک چگونگی جمع‌آوری داده‌ها، بلکه اطمینان از هماهنگی و یکپارچگی اطلاعات زمانی در سراسر سیستم.ابزارها و تجهیزات تحلیل صحیح نیازمند اعتبارسنجی این است که سیستم‌های جمع‌آوری داده، اطلاعات مفیدی (یعنی داده‌هایی که بتوانند به‌طور معناداری با داده‌های دیگر همبسته شوند) جمع‌آوری می‌کنند و اصلاً داده‌ای جمع‌آوری می‌شود. آزمایش و ممیزی منظم سیستم‌های جمع‌آوری داده برای تمایز بین حملات واقعی و اشکالات در جمع‌آوری داده ضروری است.انتخاب مسائل انتخاب به تأثیر انتخاب هدف یک آزمایش بر کل آزمایش اشاره دارد. برای تحلیلگران امنیتی، این شامل پرسش‌هایی درباره مأموریت یک سیستم (آیا برای تحقیق است؟ بازاریابی؟)، مکان قرارگیری سیستم در شبکه (قبل از منطقه غیرنظامی‌شده (DMZ)، رو به بیرون یا رو به داخل؟) و مسائل مربوط به تحرک (دسکتاپ؟ لپ‌تاپ؟ سیستم‌های نهفته؟) می‌شود.تاریخچه مسائل تاریخچه به رویدادهایی اشاره دارد که در حین انجام تحلیل بر آن تأثیر می‌گذارند. برای مثال، اگر تحلیلگری در حال بررسی تأثیر فیلترهای هرزنامه باشد و همزمان یک ارائه‌دهنده بزرگ هرزنامه غیرفعال شود، او باید بررسی کند که آیا نتایج به‌دست‌آمده ناشی از فیلتر است یا نتیجه یک اثر جهانی.بلوغ بلوغ به اثرات بلندمدت یک آزمایش بر موضوع آزمایش اشاره دارد. به‌ویژه در تحلیل‌های طولانی‌مدت، تحلیلگر باید تأثیر تخصیص پویا بر هویت را در نظر بگیرد—برای مثال، در یک شبکه DHCP، می‌توان انتظار داشت که با انقضای اجاره‌ها، رابطه آدرس‌های IP با دارایی‌ها تغییر کند. تخصیص DNS به‌صورت چرخشی یا شبکه‌های توزیع محتوا (CDN) نیز منجر به روابط متفاوتی بین درخواست‌های HTTP می‌شود.آزمایش‌های طبیعیآزمایش طبیعی نوعی آزمایش است که در آن پژوهشگر به گروهی متکی است که در معرض نوعی پدیده طبیعی (در طول زمان یا مکان) قرار گرفته و گروه‌ها را بر اساس این مواجهه مقایسه می‌کند. نمونه McColo که در فصل پانزدهم ذکر شده، مثال خوبی از این نوع تحلیل است—این تحلیل از یک پروژه جمع‌آوری داده بلندمدت بهره برد که به‌طور اتفاقی در زمان غیرفعال شدن McColo در حال اجرا بود تا تأثیر آن را بررسی کند. جمع‌آوری داده‌های بلندمدت برای آزمایش‌های طبیعی مناسب است، بنابراین توجه به تقویم برای رویدادهای امنیتی قابل‌توجه، راه مفیدی برای مطالعه تأثیر (یا عدم تأثیر) آن‌ها بر داده‌هاست.اعتبار خارجیاعتبار خارجی به توانایی تعمیم نتایج یک تحلیل به گروه‌های گسترده‌تر از گروه نمونه مورد بررسی اشاره دارد. اگر نتیجه‌ای از اعتبار خارجی قوی برخوردار باشد، می‌توان آن را به دسته‌های وسیع‌تری فراتر از گروه نمونه تعمیم داد. در تحلیل‌های امنیتی، اعتبار خارجی به‌ویژه چالش‌برانگیز است، زیرا درک جامعی از رفتار کلی شبکه‌ها نداریم—مشکلی که دهه‌هاست ادامه دارد.راه اصلی برای دستیابی به اعتبار خارجی، اطمینان از این است که داده‌های انتخاب‌شده نماینده کل جمعیت هدف باشند و روش‌های اعمال‌شده (مانند آزمایش‌ها یا اقدامات) در کل مجموعه یکسان باشند. برای مثال، اگر مطالعه‌ای روی دانشجویان انجام می‌شود، باید عواملی مثل درآمد، پیشینه و سطح تحصیلات در نظر گرفته شود و آزمایش به‌صورت یکسان برای همه اجرا شود. با این حال، تا زمانی که دانش رفتار ترافیک شبکه پیشرفت نکند و مدل‌های باکیفیتی برای توصیف رفتار عادی شبکه ایجاد نشود، تعیین اینکه آیا مدل‌ها نمونه‌ای واقع‌بینانه را نشان می‌دهند یا خیر، عملاً غیرممکن است. در حال حاضر، بهترین روش برای رفع این مشکل، استفاده از مجموعه‌های داده (corpora) اضافی است. در علوم کامپیوتر، سنت دیرینه‌ای برای جمع‌آوری مجموعه‌های داده برای تحلیل وجود دارد؛ این مجموعه‌ها اگرچه لزوماً نماینده کامل نیستند، اما بهتر از هیچ هستند.مقدمه‌ای کوتاه درباره مجموعه‌های داده امنیت اطلاعاتتحقیقات امنیت اطلاعات همیشه به دنبال مجموعه‌های داده باکیفیت است. یکی از مهم‌ترین مقالات اولیه در زمینه تشخیص نفوذ، مطالعه آزمایشگاه لینکلن در سال ۱۹۹۹ (رجوع کنید به بخش «مطالعات بیشتر» در صفحه ۱۶)، به‌طور گسترده به مشکل تولید داده پرداخته و مجموعه داده‌ای را ایجاد کرده که سال‌هاست توسط محققان استفاده می‌شود. وزارت امنیت داخلی ایالات متحده برنامه‌ای به نام IMPACT را پشتیبانی می‌کند که به‌عنوان کاتالوگ و بازار داده‌های امنیتی عمل می‌کند.چندین سازمان تحقیقاتی نیز داده تولید و به اشتراک می‌گذارند. از منابع برجسته می‌توان به CAIDA، مرکز تحلیل داده‌های کاربردی اینترنت دانشگاه UCSD، اشاره کرد. CAIDA مجموعه‌های مختلفی از داده‌های نقشه‌برداری شبکه را تولید و جمع‌آوری می‌کند. نیروی دریایی ایالات متحده مجموعه‌های داده‌ای از تمرین سالانه دفاع سایبری نگهداری می‌کند و CERT یک مخزن SiLK از یک تمرین گذشته دارد. کنفرانس تجسم‌سازی امنیتی (VizSec) نیز به مجموعه‌های داده جالبی اشاره می‌کند. بهترین منبع واحد برای همه این مجموعه‌ها در حال حاضر توسط مایک اسکونزو (Mike Sconzo) نگهداری می‌شود؛ سایت Security Repo او لینک‌هایی به مجموعه‌های داده و اشاره‌هایی به چندین مخزن برای داده‌های میزبان، سرویس و شبکه ارائه می‌دهد.این مجموعه‌های داده برای آموزش و تحلیل اکتشافی داده بسیار مناسب‌اند، اما چند نکته مهم باید ذکر شود. اول اینکه، این داده‌ها به محض جمع‌آوری و انتشار، قدیمی می‌شوند—باید به زمان انتشار مجموعه داده توجه کنید، زیرا حسگرها، شبکه و اینترنت ممکن است از زمان جمع‌آوری داده به‌طور قابل‌توجهی تغییر کرده باشند. همچنین، اطلاعاتی مانند مکان قرارگیری حسگرها تقریباً هیچ‌گاه در دسترس نیست، که بر داده‌های مشاهده‌شده تأثیر می‌گذارد.همه این‌ها بر این فرض استوار است که شما به نتیجه‌ای عمومی نیاز دارید. اگر نتایج را بتوان تنها به یک شبکه خاص (مثلاً شبکه‌ای که تحت نظارت شماست) محدود کرد، اعتبار خارجی مشکل کمتری ایجاد می‌کند.اعتبار سازه‌ایهنگام انجام یک تحلیل، شما ساختاری رسمی ایجاد می‌کنید تا آنچه را که به دنبالش هستید توصیف کنید. این ساختار رسمی ممکن است یک نظرسنجی باشد (مثلاً: «روی مقیاس ۱ تا ۱۰ بگویید سیستم شما چقدر مشکل دارد؟») یا یک معیار اندازه‌گیری (مثل تعداد بایت بر ثانیه به سمت سایت http://www.evilland.com). این ساختار رسمی، که به آن «سازه» می‌گویند، روشی است که تحلیل خود را ارزیابی می‌کنید.سازه‌های شفاف و دقیق برای انتقال معنای نتایج تحلیل بسیار مهم هستند. اگرچه این موضوع ممکن است ساده به نظر برسد، اما شگفت‌انگیز است که اختلاف نظر بر سر سازه‌ها چقدر سریع می‌تواند به تصمیم‌گیری‌های علمی یا تجاری مهم منجر شود. برای مثال، سؤال «یک بات‌نت چقدر بزرگ است؟» را در نظر بگیرید. یک متخصص امنیت شبکه ممکن است بگوید بات‌نت شامل تمام دستگاه‌هایی است که با یک سرور فرمان و کنترل (C&amp;C) خاص ارتباط برقرار می‌کنند. یک متخصص جرم‌شناسی دیجیتال ممکن است استدلال کند که بات‌نت با وجود هش یکسان بدافزار روی دستگاه‌های مختلف تعریف می‌شود. اما یک مأمور اجرای قانون ممکن است بگوید بات‌نت توسط یک گروه جنایی خاص اداره می‌شود.اعتبار آماریاعتبار نتیجه‌گیری آماری به استفاده صحیح از ابزارهای آماری مربوط است. این موضوع در فصل یازدهم به‌طور مفصل بررسی خواهد شد.مسائل مربوط به مهاجم و حملهدر نهایت، باید تأثیر منحصربه‌فرد آزمایش‌های امنیتی را در نظر بگیریم. آزمایش و تحلیل امنیتی با چالش خاصی همراه است، زیرا موضوع تحلیل ما—یعنی مهاجم—از ما متنفر است و می‌خواهد ما شکست بخوریم. به همین دلیل، باید چالش‌هایی را که از سوی مهاجم بر اعتبار سیستم وارد می‌شود، بررسی کنیم. این چالش‌ها شامل مسائل مربوط به به‌روز بودن، منابع و زمان‌بندی، و سیستم تشخیص هستند:به‌روز بودن هنگام ارزیابی یک سیستم دفاعی، باید بررسی کنید که آیا این دفاع در برابر استراتژی‌های فعلی یا قابل پیش‌بینی مهاجمان، منطقی و مؤثر است. تعداد زیادی آسیب‌پذیری در فهرست آسیب‌پذیری‌های مشترک (CVE؛ به فصل هفتم مراجعه کنید) وجود دارد، اما اکثر بهره‌برداری‌ها در دنیای واقعی از تعداد بسیار محدودی از این آسیب‌پذیری‌ها استفاده می‌کنند. با حفظ آگاهی قوی از محیط تهدیدات کنونی (به فصل هفدهم مراجعه کنید)، می‌توانید روی استراتژی‌های مرتبط‌تر تمرکز کنید.منابع و زمان‌بندی سؤالات مربوط به منابع و زمان‌بندی به این موضوع می‌پردازند که آیا یک سیستم تشخیص یا آزمایش می‌تواند در صورتی که مهاجم سرعت حمله را کم یا زیاد کند یا حمله را بین چندین میزبان تقسیم کند، دور زده شود. برای مثال، اگر سیستم دفاعی شما فرض کند که مهاجم با یک آدرس خارجی ارتباط برقرار می‌کند، چه اتفاقی می‌افتد اگر مهاجم بین مجموعه‌ای از آدرس‌ها چرخش کند؟ اگر دفاع شما فرض کند که مهاجم یک فایل را به‌سرعت منتقل می‌کند، چه می‌شود اگر مهاجم این کار را با حوصله و در طول ساعت‌ها یا حتی روزها انجام دهد؟تشخیص در نهایت، سؤالات مربوط به سیستم تشخیص به این موضوع می‌پردازند که چگونه یک مهاجم می‌تواند خود سیستم تشخیص شما را هدف حمله قرار دهد یا آن را دستکاری کند. برای مثال، اگر از یک مجموعه داده آموزشی برای تنظیم یک حسگر استفاده می‌کنید، آیا حملاتی که ممکن است در این مجموعه داده وجود داشته باشند را در نظر گرفته‌اید؟ اگر سیستم شما به نوعی اعتماد (مانند آدرس IP، رمزهای عبور یا فایل‌های اعتبارسنجی) وابسته است، در صورت به خطر افتادن این اعتماد چه اتفاقی می‌افتد؟ آیا مهاجم می‌تواند با حمله‌ای مانند حمله توزیع‌شده انکار سرویس (DDoS) یا بارگذاری بیش از حد سیستم تشخیص شما، آن را مختل کند، و در این صورت، پیامدهای آن چیست؟</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Tue, 02 Sep 2025 09:31:30 +0330</pubDate>
            </item>
                    <item>
                <title>فصل 21 - شبکه‌های عصبی</title>
                <link>https://virgool.io/mojino/%D9%81%D8%B5%D9%84-21-%D8%B4%D8%A8%DA%A9%D9%87-%D9%87%D8%A7%DB%8C-%D8%B9%D8%B5%D8%A8%DB%8C-wi5kv6rnvgzq</link>
                <description>21.0 مقدمهدر هسته‌ی شبکه‌های عصبی ساده، واحدی به نام نود یا نورون قرار دارد. هر نورون یک یا چند ورودی دریافت می‌کند، هر ورودی را در یک پارامتر (به نام وزن) ضرب می‌کند، مقادیر وزن‌دار شده را به همراه یک مقدار بایاس (معمولاً صفر) جمع می‌کند و سپس این مقدار را به یک تابع فعال‌سازی می‌فرستد. خروجی این فرآیند به نورون‌های دیگر در لایه‌های عمیق‌تر شبکه عصبی (در صورت وجود) منتقل می‌شود.شبکه‌های عصبی را می‌توان به صورت مجموعه‌ای از لایه‌های متصل به هم تصور کرد که ویژگی‌های یک مشاهده را از یک طرف به مقدار هدف (مثلاً کلاس مشاهده) در طرف دیگر متصل می‌کنند. شبکه‌های عصبی فیدفوروارد (که به آن‌ها پرسپترون چندلایه نیز گفته می‌شود) ساده‌ترین نوع شبکه‌های عصبی مصنوعی هستند که در کاربردهای واقعی استفاده می‌شوند. نام &quot;فیدفوروارد&quot; از این واقعیت می‌آید که مقادیر ویژگی‌های یک مشاهده به صورت &quot;رو به جلو&quot; در شبکه حرکت می‌کنند و هر لایه به ترتیب این ویژگی‌ها را تغییر می‌دهد تا خروجی شبکه به مقدار هدف نزدیک شود یا با آن برابر شود.به طور خاص، شبکه‌های عصبی فیدفوروارد شامل سه نوع لایه هستند:1. لایه ورودی: در ابتدای شبکه قرار دارد و هر واحد در این لایه، مقدار یک ویژگی از مشاهده را نگه می‌دارد. برای مثال، اگر یک مشاهده 100 ویژگی داشته باشد، لایه ورودی شامل 100 واحد خواهد بود.2. لایه خروجی: در انتهای شبکه قرار دارد و خروجی لایه‌های میانی (به نام لایه‌های مخفی) را به مقادیری تبدیل می‌کند که برای وظیفه موردنظر مفید هستند. برای مثال، در یک مسئله طبقه‌بندی باینری، می‌توان از یک لایه خروجی با یک واحد استفاده کرد که با استفاده از تابع سیگموید خروجی خود را به مقداری بین 0 و 1 تبدیل می‌کند تا احتمال کلاس پیش‌بینی‌شده را نشان دهد.3. لایه‌های مخفی: بین لایه‌های ورودی و خروجی قرار دارند و به ترتیب ویژگی‌های لایه ورودی را به چیزی تبدیل می‌کنند که پس از پردازش توسط لایه خروجی، شبیه به کلاس هدف باشد. شبکه‌های عصبی با تعداد زیادی لایه مخفی (مثلاً 10، 100 یا 1000 لایه) به عنوان شبکه‌های عمیق شناخته می‌شوند و فرآیند آموزش این شبکه‌ها به نام یادگیری عمیق شناخته می‌شود.شبکه‌های عصبی معمولاً با مقداردهی اولیه تمام پارامترها به مقادیر تصادفی کوچک از یک توزیع گاوسی یا یکنواخت ایجاد می‌شوند. پس از اینکه یک مشاهده یا معمولاً مجموعه‌ای از مشاهدات به نام بچ(batch) از شبکه عبور کرد، مقدار خروجی با مقدار واقعی مشاهده با استفاده از یک تابع زیان مقایسه می‌شود. این فرآیند به نام انتشار رو به جلو(forward propagation) شناخته می‌شود. سپس الگوریتمی به صورت عقب‌گرد(back propagation) در شبکه حرکت می‌کند و میزان مشارکت هر پارامتر در خطای بین مقدار پیش‌بینی‌شده و مقدار واقعی را شناسایی می‌کند. این فرآیند به نام انتشار عقب‌گرد شناخته می‌شود. در هر پارامتر، الگوریتم بهینه‌سازی مشخص می‌کند که هر وزن چقدر باید تنظیم شود تا خروجی بهبود یابد.شبکه‌های عصبی با تکرار فرآیند انتشار رو به جلو و عقب‌گرد برای هر مشاهده در داده‌های آموزشی چندین بار یاد می‌گیرند. هر بار که تمام مشاهدات از شبکه عبور کنند، یک دوره (epoch) نامیده می‌شود و آموزش معمولاً شامل چندین دوره است. در این فرآیند، مقادیر پارامترها با استفاده از روشی به نام گرادیان کاهشی به‌تدریج بهینه می‌شوند تا خروجی موردنظر به دست آید.در این فصل، ما از همان کتابخانه پایتون که در فصل قبل استفاده کردیم، یعنی پایتورچ (PyTorch)، برای ساخت، آموزش و ارزیابی انواع شبکه‌های عصبی استفاده خواهیم کرد. پایتورچ به دلیل APIهای خوش‌ساخت و نمایش بصری عملیات‌های تنسوری سطح پایین که شبکه‌های عصبی را پشتیبانی می‌کنند، در حوزه یادگیری عمیق بسیار محبوب است. یکی از ویژگی‌های کلیدی پایتورچ، اتوگراد (autograd) است که به طور خودکار گرادیان‌های موردنیاز برای بهینه‌سازی پارامترهای شبکه پس از انتشار رو به جلو و عقب‌گرد را محاسبه و ذخیره می‌کند.شبکه‌های عصبی ساخته‌شده با کد پایتورچ می‌توانند هم با CPU (مثلاً روی لپ‌تاپ) و هم با GPU (روی کامپیوترهای تخصصی یادگیری عمیق) آموزش ببینند. در دنیای واقعی با داده‌های واقعی، معمولاً آموزش شبکه‌های عصبی با GPU لازم است، زیرا فرآیند آموزش برای شبکه‌های پیچیده و داده‌های بزرگ روی GPU بسیار سریع‌تر از CPU است. با این حال، تمام شبکه‌های عصبی در این کتاب به اندازه کافی کوچک و ساده هستند که می‌توانند روی لپ‌تاپ با CPU در چند دقیقه آموزش ببینند. فقط توجه داشته باشید که وقتی شبکه‌های بزرگ‌تر و داده‌های آموزشی بیشتری داشته باشیم، آموزش با CPU به طور قابل‌توجهی کندتر از GPU خواهد بود.21.1 استفاده از Autograd در پایتورچمشکلمی‌خواهید از ویژگی‌های اتوگراد (Autograd) پایتورچ برای محاسبه و ذخیره گرادیان‌ها پس از انجام انتشار رو به جلو و عقب‌گرد استفاده کنید.راه‌حلتنسورهایی ایجاد کنید که گزینه requires_grad آن‌ها روی True تنظیم شده باشد:# Import libraries
import torch

# Create a torch tensor that requires gradients
t = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)

# Perform a tensor operation simulating &quot;forward propagation&quot;
tensor_sum = t.sum()

# Perform back propagation
tensor_sum.backward()

# View the gradients
t.gradخروجی: tensor([1., 1., 1.])توضیحاتاتوگراد یکی از ویژگی‌های اصلی پایتورچ و عامل مهمی در محبوبیت آن به‌عنوان یک کتابخانه یادگیری عمیق است. توانایی محاسبه، ذخیره و تجسم آسان گرادیان‌ها، پایتورچ را برای محققان و علاقه‌مندانی که شبکه‌های عصبی را از ابتدا می‌سازند، بسیار بصری و کاربردی می‌کند.پایتورچ از یک گراف غیرمدور جهت‌دار (DAG) برای ثبت تمام داده‌ها و عملیات محاسباتی انجام‌شده روی آن داده‌ها استفاده می‌کند. این قابلیت بسیار مفید است، اما به این معناست که باید مراقب باشیم چه عملیاتی را روی داده‌های پایتورچ که نیاز به محاسبه گرادیان دارند، اعمال می‌کنیم. هنگام کار با اتوگراد، نمی‌توانیم به‌راحتی تنسورها را به آرایه‌های نام‌پای (NumPy) تبدیل کنیم و دوباره برگردانیم بدون اینکه گراف را بشکنیم، عبارتی که برای توصیف عملیاتی استفاده می‌شود که از اتوگراد پشتیبانی نمی‌کنند:import torch
tensor = torch.tensor([1.0,2.0,3.0], requires_grad=True) 
tensor.numpy() خروجی:RuntimeError: Can&#039;t call numpy() on Tensor that requires grad. 
Use tensor.detach().numpy() instead. برای تبدیل این تنسور به یک آرایه نام‌پای، باید متد ()detach را روی آن فراخوانی کنیم، که این کار گراف را می‌شکند و در نتیجه توانایی ما برای محاسبه خودکار گرادیان‌ها را از بین می‌برد. اگرچه این کار می‌تواند مفید باشد، اما باید توجه داشت که جدا کردن (detaching) تنسور باعث می‌شود پایتورچ نتواند گرادیان را به‌صورت خودکار محاسبه کند.21.2 پیش‌پردازش داده‌ها برای شبکه‌های عصبیمشکلمی‌خواهید داده‌ها را برای استفاده در یک شبکه عصبی پیش‌پردازش کنید.راه‌حلهر ویژگی را با استفاده از StandardScaler کتابخانه سایکیت-لرن (scikit-learn) استاندارد کنید:# Load libraries
from sklearn import preprocessing import numpy as np

# Create feature
features = np.array([[-100.1, 3240.1],
                     [-200.2, -234.1],
                     [5000.5,  150.1],
                     [6000.6, -125.1],
                     [9000.9, -673.1]])

# Create scaler
scaler = preprocessing.StandardScaler()

features = scaler.fit_transform(features)

# Convert to a tensor
features_standardized_tensor = torch.from_numpy(features)

# Show features
features_standardized_tensorخروجی:tensor([[-100.1000, 3240.1000], 
        [-200.2000, -234.1000],
        [5000.5000, 150.1000],
        [6000.6000, -125.1000],
        [9000.9000, -673.1000]], dtype=torch.float64) توضیحاتاگرچه این دستورالعمل بسیار شبیه به دستورالعمل 4.2 است، اما به دلیل اهمیت بالای آن برای شبکه‌های عصبی، ارزش تکرار دارد. معمولاً پارامترهای یک شبکه عصبی در ابتدا به‌صورت اعداد تصادفی کوچک مقداردهی (ایجاد) می‌شوند. شبکه‌های عصبی اغلب زمانی که مقادیر ویژگی‌ها بسیار بزرگ‌تر از مقادیر پارامترها باشند، عملکرد ضعیفی از خود نشان می‌دهند. علاوه بر این، از آنجا که مقادیر ویژگی‌های یک مشاهده در هنگام عبور از واحدهای مختلف ترکیب می‌شوند، مهم است که همه ویژگی‌ها در یک مقیاس یکسان باشند.به همین دلایل، بهترین روش (هرچند نه همیشه ضروری، مثلاً وقتی همه ویژگی‌ها باینری هستند) این است که هر ویژگی را استاندارد کنیم تا مقادیر آن میانگین 0 و انحراف معیار 1 داشته باشند. این کار به‌راحتی با استفاده از StandardScaler سایکیت-لرن قابل انجام است.با این حال، اگر نیاز دارید این عملیات را پس از ایجاد تنسورهایی با requires_grad=True انجام دهید، باید این کار را به‌صورت داخلی در پایتورچ انجام دهید تا گراف محاسباتی شکسته نشود. اگرچه معمولاً ویژگی‌ها را قبل از شروع آموزش شبکه استاندارد می‌کنید، اما دانستن چگونگی انجام این کار در پایتورچ نیز ارزشمند است:# Load library
import torch

# Create features
torch_features = torch.tensor([[-100.1, 3240.1],
                               [-200.2, -234.1], 
                               [5000.5, 150.1],
                               [6000.6, -125.1],
                               [9000.9, -673.1]], requires_grad=True)

# Compute the mean and standard deviation
mean = torch_features.mean(0, keepdim=True) 
standard_deviation = torch_features.std(0, unbiased=False, keepdim=True)

# Standardize the features using the mean and standard deviation
torch_features_standardized = torch_features - mean
torch_features_standardized /= standard_deviation

# Show standardized features
torch_features_standardized خروجی:tensor([[-1.1254, 1.9643], 
        [-1.1533, -0.5007], 
        [ 0.2953, -0.2281], 
        [ 0.5739, -0.4234], 
        [ 1.4096, -0.8122]], grad_fn=&lt;DivBackward0&gt;) 21.3 طراحی یک شبکه عصبیمشکلمی‌خواهید یک شبکه عصبی طراحی کنید.راه‌حلاز کلاس nn.Module پایتورچ برای تعریف یک معماری ساده شبکه عصبی استفاده کنید:# Import libraries
import torch
import torch.nn as nn
 
# Define a neural network
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.fc1 = nn.Linear(10, 16) 
        self.fc2 = nn.Linear(16, 16) 
        self.fc3 = nn.Linear(16, 1) 

    def forward(self, x): 
        x = nn.functional.relu(self.fc1(x)) 
        x = nn.functional.relu(self.fc2(x)) 
        x = nn.functional.sigmoid(self.fc3(x)) 
        return x

# Initialize the neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
loss_criterion = nn.BCELoss() 
optimizer = torch.optim.RMSprop(network.parameters())

# Show the network
network خروجی:SimpleNeuralNet( 
    (fc1): Linear(in_features=10, out_features=16, bias=True) 
    (fc2): Linear(in_features=16, out_features=16, bias=True) 
    (fc3): Linear(in_features=16, out_features=1, bias=True) 
) توضیحاتشبکه‌های عصبی از لایه‌هایی از واحدها تشکیل شده‌اند. با این حال، تنوع زیادی در انواع لایه‌ها و نحوه ترکیب آن‌ها برای تشکیل معماری شبکه وجود دارد. اگرچه الگوهای معماری رایجی وجود دارند (که در این فصل به آن‌ها خواهیم پرداخت)، حقیقت این است که انتخاب معماری مناسب بیشتر یک هنر است و موضوع تحقیقات زیادی است.برای ساخت یک شبکه عصبی فیدفوروارد در پایتورچ، باید تصمیم‌های متعددی درباره معماری شبکه و فرآیند آموزش بگیریم. به یاد داشته باشید که هر واحد در لایه‌های مخفی:تعدادی ورودی دریافت می‌کند.هر ورودی را با یک مقدار پارامتر (وزن) ضرب می‌کند.تمام ورودی‌های وزن‌دار را به همراه یک مقدار بایاس (معمولاً صفر) جمع می‌کند.اغلب یک تابع (به نام تابع فعال‌سازی) روی آن اعمال می‌کند.خروجی را به واحدهای لایه بعدی منتقل می‌کند.ابتدا، برای هر لایه در لایه‌های مخفی و خروجی، باید تعداد واحدها و تابع فعال‌سازی را مشخص کنیم. به طور کلی، هرچه تعداد واحدها در یک لایه بیشتر باشد، شبکه قادر به یادگیری الگوهای پیچیده‌تر خواهد بود. با این حال، تعداد زیاد واحدها ممکن است باعث بیش‌برازش (overfitting) شبکه به داده‌های آموزشی شود که به عملکرد در داده‌های آزمایشی آسیب می‌رساند.برای لایه‌های مخفی، یک تابع فعال‌سازی محبوب، واحد خطی اصلاح‌شده (ReLU) است:که در آن z مجموع ورودی‌های وزن‌دار و بایاس است. اگر z بزرگ‌تر از صفر باشد، تابع فعال‌سازی مقدار z را برمی‌گرداند؛ در غیر این صورت، صفر برمی‌گرداند. این تابع فعال‌سازی ساده دارای ویژگی‌های مطلوبی است (که بحث در مورد آن‌ها خارج از دامنه این کتاب است) و به همین دلیل در شبکه‌های عصبی بسیار محبوب است. با این حال، باید بدانیم که ده‌ها تابع فعال‌سازی دیگر نیز وجود دارند.دوم، باید تعداد لایه‌های مخفی در شبکه را مشخص کنیم. لایه‌های بیشتر به شبکه اجازه می‌دهند روابط پیچیده‌تری را یاد بگیرند، اما این کار هزینه محاسباتی بیشتری دارد.سوم، باید ساختار تابع فعال‌سازی (در صورت وجود) برای لایه خروجی را تعریف کنیم. ماهیت تابع خروجی اغلب به هدف شبکه بستگی دارد. الگوهای رایج برای لایه خروجی عبارتند از:طبقه‌بندی باینری: یک واحد با تابع فعال‌سازی سیگموید.طبقه‌بندی چندکلاسه: k واحد (که k تعداد کلاس‌های هدف است) و تابع فعال‌سازی سافت‌مکس(softmax).رگرسیون: یک واحد بدون تابع فعال‌سازی.چهارم، باید یک تابع زیان تعریف کنیم (تابعی که میزان تطابق مقدار پیش‌بینی‌شده با مقدار واقعی را می‌سنجد)؛ این نیز اغلب به نوع مسئله بستگی دارد:طبقه‌بندی باینری: آنتروپی متقاطع باینری(Binary cross-entropy).طبقه‌بندی چندکلاسه: آنتروپی متقاطع دسته‌ای(Categorical cross-entropy).رگرسیون: خطای میانگین مربعات(Mean square error).پنجم، باید یک بهینه‌ساز تعریف کنیم، که به طور شهودی می‌توان آن را به‌عنوان استراتژی ما برای &quot;گشتن&quot; در تابع زیان برای یافتن مقادیر پارامتری در نظر گرفت که کمترین خطا را تولید می‌کنند. انتخاب‌های رایج برای بهینه‌سازها شامل گرادیان کاهشی تصادفی(stochastic gradient descent)، گرادیان کاهشی تصادفی با تکانه(stochastic gradient descent with momentum)، انتشار میانگین مربعات ریشه(root mean square propagation)، و تخمین لحظه تطبیقی(adaptive moment estimation) است.ششم، می‌توانیم یک یا چند معیار برای ارزیابی عملکرد، مانند دقت (accuracy)، انتخاب کنیم.در مثال ما، از فضای نام torch.nn.Module برای ساخت یک شبکه عصبی ساده و متوالی استفاده می‌کنیم که قادر به انجام طبقه‌بندی باینری است. روش استاندارد پایتورچ برای این کار، ایجاد یک کلاس فرزند است که از کلاس torch.nn.Module ارث می‌برد، معماری شبکه را در متد init تعریف می‌کند و عملیات ریاضی که می‌خواهیم در هر عبور رو به جلو انجام شود را در متد forward کلاس تعریف می‌کند. روش‌های زیادی برای تعریف شبکه‌ها در پایتورچ وجود دارد، و اگرچه در این مورد از روش‌های تابعی برای توابع فعال‌سازی (مانند nn.functional.relu) استفاده می‌کنیم، می‌توانیم این توابع فعال‌سازی را به‌عنوان لایه نیز تعریف کنیم. اگر بخواهیم همه چیز را در شبکه به‌عنوان لایه تعریف کنیم، می‌توانیم از کلاس Sequential استفاده کنیم:# Import libraries
import torch

# Define a neural network using Sequential
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.sequential = torch.nn.Sequential( 
            torch.nn.Linear(10, 16), 
            torch.nn.ReLU(), 
            torch.nn.Linear(16,16), 
            torch.nn.ReLU(), 
            torch.nn.Linear(16, 1), 
            torch.nn.Sigmoid() 
        ) 
    
    def forward(self, x): 
        x = self.sequential(x) 
        return x

# Instantiate and view the network
SimpleNeuralNet() خروجی:SimpleNeuralNet( 
  (sequential): Sequential( 
    (0): Linear(in_features=10, out_features=16, bias=True) 
    (1): ReLU() 
    (2): Linear(in_features=16, out_features=16, bias=True) 
    (3): ReLU()
    (4): Linear(in_features=16, out_features=1, bias=True)
    (5): Sigmoid()
  )
)در هر دو حالت، شبکه یک شبکه عصبی دو لایه است (هنگام شمارش لایه‌ها، لایه ورودی را حساب نمی‌کنیم زیرا هیچ پارامتری برای یادگیری ندارد) که با استفاده از مدل متوالی پایتورچ تعریف شده است. هر لایه متراکم (dense) یا کاملاً متصل (fully connected) است، به این معنی که تمام واحدها در لایه قبلی به تمام واحدها در لایه بعدی متصل هستند.در لایه مخفی اول، out_features=16 تنظیم شده است، به این معنی که این لایه شامل 16 واحد است. این واحدها دارای توابع فعال‌سازی ReLU هستند که در متد forward کلاس تعریف شده‌اند:x = nn.functional.relu(self.fc1(x))لایه اول شبکه ما اندازه (10, 16) دارد، که به لایه اول می‌گوید انتظار داشته باشد هر مشاهده از داده‌های ورودی 10 مقدار ویژگی داشته باشد. این شبکه برای طبقه‌بندی باینری طراحی شده است، بنابراین لایه خروجی تنها یک واحد با تابع فعال‌سازی سیگموید دارد که خروجی را به مقداری بین 0 و 1 محدود می‌کند (که نشان‌دهنده احتمال تعلق یک مشاهده به کلاس 1 است).21.4 آموزش یک طبقه‌بند دودوییمسئلهمی‌خواهید یک شبکه عصبی طبقه‌بند دودویی را آموزش دهید.راه‌حلاز PyTorch برای ساخت یک شبکه عصبی پیش‌خور (feedforward) استفاده کنید و آن را آموزش دهید.# Import libraries
import torch
import torch.nn as nn 
import numpy as np
from torch.utils.data import DataLoader, TensorDataset 
from torch.optim import RMSprop
from sklearn.datasets import make_classification 
from sklearn.model_selection import train_test_split 

# Create training and test sets
features, target = make_classification(n_classes=2, n_features=10, n_samples=1000) 
features_train, features_test, target_train, target_test = train_test_split( 
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float() 
y_train = torch.from_numpy(target_train).float().view(-1, 1) 
x_test = torch.from_numpy(features_test).float() 
y_test = torch.from_numpy(target_test).float().view(-1, 1)

# Define a neural network using Sequential
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.sequential = torch.nn.Sequential( 
             torch.nn.Linear(10, 16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16,16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16, 1), 
             torch.nn.Sigmoid() 
         ) 
    def forward(self, x): 
        x = self.sequential(x) 
        return x

# Initialize neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
criterion = nn.BCELoss() 
optimizer = RMSprop(network.parameters())

# Define data loader
train_data = TensorDataset(x_train, y_train) 
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Compile the model using torch 2.0&#039;s optimizer
network = torch.compile(network)

# Train neural network
epochs = 3
for epoch in range(epochs):
    for batch_idx, (data, target) in enumerate(train_loader): 
        optimizer.zero_grad() 
        output = network(data) 
        loss = criterion(output, target) 
        loss.backward() 
        optimizer.step() 
     print(&quot;Epoch:&quot;, epoch+1, &quot;\tLoss:&quot;, loss.item())

# Evaluate neural network
with torch.no_grad(): 
    output = network(x_test) 
    test_loss = criterion(output, y_test) 
    test_accuracy = (output.round() == y_test).float().mean() 
    print(&quot;Test Loss:&quot;, test_loss.item(), &quot;\tTest Accuracy:&quot;, test_accuracy.item()) خروجی:Epoch: 1 Loss: 0.19006995856761932 
Epoch: 2 Loss: 0.14092367887496948 
Epoch: 3 Loss: 0.03935524448752403
Test Loss: 0.06877756118774414 Test Accuracy: 0.9700000286102295 توضیحاتدر دستورالعمل 21.3، نحوه ساخت یک شبکه عصبی با استفاده از مدل Sequential در PyTorch توضیح داده شد. در این دستورالعمل، ما همان شبکه عصبی را با استفاده از 10 ویژگی و 1000 نمونه داده تقلبی برای طبقه‌بندی، که با تابع make_classification از scikit-learn تولید شده‌اند، آموزش می‌دهیم.شبکه عصبی استفاده‌شده در اینجا همان شبکه‌ای است که در دستورالعمل 21.3 توضیح داده شد (برای جزئیات بیشتر به آن دستورالعمل مراجعه کنید). تفاوت در این است که در آنجا فقط شبکه را ایجاد کردیم و آن را آموزش ندادیم.در پایان، از ()with torch.no_grad برای ارزیابی شبکه استفاده می‌کنیم. این دستور مشخص می‌کند که نباید گرادیان‌ها برای عملیات تنسور در این بخش از کد محاسبه شوند. از آنجا که گرادیان‌ها فقط در فرآیند آموزش مدل استفاده می‌شوند، نمی‌خواهیم گرادیان‌های جدیدی برای عملیات خارج از فرآیند آموزش (مانند پیش‌بینی یا ارزیابی) ذخیره شوند.متغیر epochs تعداد دوره‌های (epochs) مورد استفاده برای آموزش داده‌ها را مشخص می‌کند.batch_size تعداد نمونه‌هایی را تعیین می‌کند که قبل از به‌روزرسانی پارامترها از طریق شبکه منتشر می‌شوند.سپس، برای تعداد دوره‌های مشخص‌شده، شبکه را با استفاده از متد forward برای عبور رو به جلو و سپس عبور رو به عقب برای به‌روزرسانی گرادیان‌ها، آموزش می‌دهیم.نتیجه، یک مدل آموزش‌دیده است.21.5 آموزش یک طبقه‌بندی‌کننده چندکلاسیمسئلهمی‌خواهید یک شبکه عصبی طبقه‌بندی‌کننده چندکلاسی را آموزش دهید.راه‌حلاز PyTorch برای ساخت یک شبکه عصبی پیش‌خور (feedforward) با لایه خروجی دارای تابع فعال‌سازی softmax استفاده کنید.# Import libraries
import torch
import torch.nn as nn 
import numpy as np
from torch.utils.data import DataLoader, TensorDataset 
from torch.optim import RMSprop
from sklearn.datasets import make_classification 
from sklearn.model_selection import train_test_split

N_CLASSES=3 
EPOCHS=3

# Create training and test sets
features, target = make_classification(n_classes=N_CLASSES, n_informative=9, 
    n_redundant=0, n_features=10, n_samples=1000) 
features_train, features_test, target_train, target_test = train_test_split( 
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0) 
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float() 
y_train = torch.nn.functional.one_hot(torch.from_numpy(target_train).long(),
    num_classes=N_CLASSES).float() 
x_test = torch.from_numpy(features_test).float() 
y_test = torch.nn.functional.one_hot(torch.from_numpy(target_test).long(),
    num_classes=N_CLASSES).float()

# Define a neural network using Sequential
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.sequential = torch.nn.Sequential( 
            torch.nn.Linear(10, 16), 
            torch.nn.ReLU(),
            torch.nn.Linear(16,16),
            torch.nn.ReLU(),
            torch.nn.Linear(16,3), 
            torch.nn.Softmax()
        )
   def forward(self, x):
       x = self.sequential(x)
       return x

# Initialize neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
criterion = nn.CrossEntropyLoss()
optimizer = RMSprop(network.parameters())

# Define data loader
train_data = TensorDataset(x_train, y_train)
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Compile the model using torch 2.0&#039;s optimizer
network = torch.compile(network)

# Train neural network
for epoch in range(EPOCHS):
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()
        output = network(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
    print(&quot;Epoch:&quot;, epoch+1, &quot;\tLoss:&quot;, loss.item())

# Evaluate neural network
with torch.no_grad():
    output = network(x_test)
    test_loss = criterion(output, y_test)
    test_accuracy = (output.round() == y_test).float().mean()
    print(&quot;Test Loss:&quot;, test_loss.item(), &quot;\tTest Accuracy:&quot;,
        test_accuracy.item())خروجی:Epoch: 1 Loss: 0.8022041916847229
Epoch: 2 Loss: 0.775616466999054
Epoch: 3 Loss: 0.7751263380050659
Test Loss: 0.8105319142341614 Test Accuracy: 0.8199999928474426توضیحاتدر این راه‌حل، ما شبکه عصبی مشابهی با طبقه‌بندی‌کننده دوکلاسی (باینری) از مثال قبلی ساختیم، اما با تغییراتی قابل توجه. در داده‌های طبقه‌بندی که تولید کردیم، تعداد کلاس‌ها را ۳ تعیین کردیم (N_CLASSES=3). برای مدیریت طبقه‌بندی چندکلاسی، از تابع زیان ()nn.CrossEntropyLoss استفاده کردیم که انتظار دارد هدف (target) به‌صورت one-hot encoded باشد. برای این کار، از تابع torch.nn.functional.one_hot استفاده کردیم که نتیجه‌اش یک آرایه one-hot encoded است؛ در این آرایه، موقعیت عدد ۱ نشان‌دهنده کلاس مربوط به یک مشاهده است.# View target matrix
y_train خروجی:tensor([[1., 0., 0.],
        [0., 1., 0.],
        [1., 0., 0.],
        ...,
        [0., 1., 0.],
        [1., 0., 0.],
        [0., 0., 1.]]) از آنجا که این یک مسئله طبقه‌بندی چندکلاسی است، از یک لایه خروجی با اندازه ۳ (یکی برای هر کلاس) استفاده کردیم که شامل تابع فعال‌سازی softmax است. تابع softmax آرایه‌ای از ۳ مقدار تولید می‌کند که مجموع آن‌ها برابر با ۱ است. این ۳ مقدار نشان‌دهنده احتمال تعلق یک مشاهده به هر یک از ۳ کلاس است.همان‌طور که در این مثال اشاره شد، از تابع زیان مناسب برای طبقه‌بندی چندکلاسی، یعنی تابع زیان دسته‌ای متقاطع (categorical cross-entropy loss) با نام ()nn.CrossEntropyLoss استفاده کردیم.21.6 آموزش یک مدل رگرسیونمسئلهمی‌خواهید یک شبکه عصبی برای انجام رگرسیون آموزش دهید.راه‌حلبا استفاده از PyTorch یک شبکه عصبی پیش‌خور (feedforward) بسازید که دارای یک واحد خروجی بدون تابع فعال‌سازی باشد.# Import libraries
import torch
import torch.nn as nn 
import numpy as np
from torch.utils.data import DataLoader, TensorDataset 
from torch.optim import RMSprop
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split

EPOCHS=5

# Create training and test sets
features, target = make_regression(n_features=10, n_samples=1000) 
features_train, features_test, target_train, target_test = train_test_split( 
    features, target, test_size=0.1, random_state=1)

# Set random seed 
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float()
y_train = torch.from_numpy(target_train).float().view(-1,1)
x_test = torch.from_numpy(features_test).float()
y_test = torch.from_numpy(target_test).float().view(-1,1)

# Define a neural network using `Sequential`
class SimpleNeuralNet(nn.Module):
    def __init__(self):
        super(SimpleNeuralNet, self).__init__()
        self.sequential = torch.nn.Sequential(
            torch.nn.Linear(10, 16),
            torch.nn.ReLU(),
            torch.nn.Linear(16,16),
            torch.nn.ReLU(),
            torch.nn.Linear(16,1),
        )
    def forward(self, x):
        x = self.sequential(x)
        return x

# Initialize neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
criterion = nn.MSELoss()
optimizer = RMSprop(network.parameters())

# Define data loader
train_data = TensorDataset(x_train, y_train)
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Compile the model using torch 2.0&#039;s optimizer
network = torch.compile(network)

# Train neural network
for epoch in range(EPOCHS):
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()
        output = network(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
    print(&quot;Epoch:&quot;, epoch+1, &quot;\tLoss:&quot;, loss.item())

# Evaluate neural network
with torch.no_grad():
    output = network(x_test)
    test_loss = float(criterion(output, y_test))
    print(&quot;Test MSE:&quot;, test_loss)خروجی:Epoch: 1 Loss: 10764.02734375 
Epoch: 2 Loss: 1356.510009765625 
Epoch: 3 Loss: 504.9664306640625 
Epoch: 4 Loss: 199.11314392089844 
Epoch: 5 Loss: 191.20834350585938 
Test MSE: 162.24497985839844 توضیحاتمی‌توان یک شبکه عصبی را برای پیش‌بینی مقادیر پیوسته (به جای احتمالات کلاس) طراحی کرد. در مورد طبقه‌بندی باینری (دستور 21.4)، ما از یک لایه خروجی با یک واحد و تابع فعال‌سازی سیگموید استفاده کردیم تا احتمالی بین 0 و 1 برای کلاس 1 تولید شود. تابع سیگموید باعث محدود شدن خروجی به بازه 0 تا 1 می‌شود. اما اگر این تابع فعال‌سازی را حذف کنیم، خروجی می‌تواند یک مقدار پیوسته باشد.علاوه بر این، چون هدف ما رگرسیون است، باید از یک تابع زیان مناسب و معیار ارزیابی مناسب استفاده کنیم، در اینجا خطای میانگین مربعات (MSE):که در آن n تعداد مشاهدات است، y_i مقدار واقعی هدف برای مشاهده i است، و hat{y}_i مقدار پیش‌بینی‌شده توسط مدل برای y_i است.در نهایت، چون در اینجا از داده‌های شبیه‌سازی‌شده با تابع make_regression از scikit-learn استفاده شده، نیازی به استانداردسازی ویژگی‌ها نبود. اما باید توجه داشت که در تقریباً تمام موارد واقعی، استانداردسازی ویژگی‌ها ضروری است.21.7 انجام پیش‌بینی‌هامسئلهمی‌خواهید از یک شبکه عصبی برای انجام پیش‌بینی استفاده کنید.راه‌حلبا استفاده از PyTorch یک شبکه عصبی پیش‌خور (feedforward) بسازید و سپس با استفاده از متد forward پیش‌بینی‌ها را انجام دهید.# Import libraries
import torch
import torch.nn as nn 
import numpy as np
from torch.utils.data import DataLoader, TensorDataset 
from torch.optim import RMSprop
from sklearn.datasets import make_classification 
from sklearn.model_selection import train_test_split 

# Create training and test sets
features, target = make_classification(n_classes=2, n_features=10, n_samples=1000) 
features_train, features_test, target_train, target_test = train_test_split( 
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float() 
y_train = torch.from_numpy(target_train).float().view(-1, 1) 
x_test = torch.from_numpy(features_test).float() 
y_test = torch.from_numpy(target_test).float().view(-1, 1)

# Define a neural network using Sequential
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.sequential = torch.nn.Sequential( 
             torch.nn.Linear(10, 16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16,16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16, 1), 
             torch.nn.Sigmoid() 
         ) 
    def forward(self, x): 
        x = self.sequential(x) 
        return x

# Initialize neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
criterion = nn.BCELoss() 
optimizer = RMSprop(network.parameters())

# Define data loader
train_data = TensorDataset(x_train, y_train) 
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Compile the model using torch 2.0&#039;s optimizer
network = torch.compile(network)

# Train neural network
epochs = 3
for epoch in range(epochs):
    for batch_idx, (data, target) in enumerate(train_loader): 
        optimizer.zero_grad() 
        output = network(data) 
        loss = criterion(output, target) 
        loss.backward() 
        optimizer.step() 
     print(&quot;Epoch:&quot;, epoch+1, &quot;\tLoss:&quot;, loss.item())

# Evaluate neural network
with torch.no_grad(): 
    predicted_class = network.forward(x_train).round()

predicted_class[0]خروجی:Epoch: 1 Loss: 0.19006995856761932 
Epoch: 2 Loss: 0.14092367887496948 
Epoch: 3 Loss: 0.03935524448752403 
tensor([1.]) 
توضیحاتانجام پیش‌بینی در PyTorch ساده است. پس از آموزش شبکه عصبی، می‌توانیم از متد forward (که در فرآیند آموزش نیز استفاده شده) استفاده کنیم. این متد مجموعه‌ای از ویژگی‌ها را به عنوان ورودی می‌گیرد و یک گذر رو به جلو (forward pass) در شبکه انجام می‌دهد. در این راه‌حل، شبکه عصبی برای طبقه‌بندی باینری تنظیم شده است، بنابراین خروجی پیش‌بینی‌شده، احتمال تعلق به کلاس 1 است. مشاهداتی که مقادیر پیش‌بینی‌شده آن‌ها بسیار نزدیک به 1 باشد، به احتمال زیاد متعلق به کلاس 1 هستند، و مشاهداتی که مقادیر پیش‌بینی‌شده آن‌ها بسیار نزدیک به 0 باشد، به احتمال زیاد متعلق به کلاس 0 هستند. به همین دلیل، از متد round استفاده می‌کنیم تا این مقادیر را به 1 و 0 برای طبقه‌بندی باینری تبدیل کنیم.21.8 نمایش تاریخچه آموزشمسئلهشما می‌خواهید «نقطه بهینه» در امتیاز خطا و یا دقت یک شبکه عصبی را پیدا کنید.راه‌حلاز Matplotlib استفاده کنید تا خطای مجموعه آموزشی و آزمایشی را در هر دوره (epoch) به‌صورت بصری نمایش دهید.# Import libraries
import torch
import torch.nn as nn 
from torch.utils.data import DataLoader, TensorDataset 
from torch.optim import RMSprop
from sklearn.datasets import make_classification 
from sklearn.model_selection import train_test_split 

import numpy as np
import matplotlib.pyplot as plt

# Create training and test sets
features, target = make_classification(n_classes=2, n_features=10, n_samples=1000) 
features_train, features_test, target_train, target_test = train_test_split( 
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float() 
y_train = torch.from_numpy(target_train).float().view(-1, 1) 
x_test = torch.from_numpy(features_test).float() 
y_test = torch.from_numpy(target_test).float().view(-1, 1)

# Define a neural network using Sequential
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.sequential = torch.nn.Sequential( 
             torch.nn.Linear(10, 16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16,16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16, 1), 
             torch.nn.Sigmoid() 
         ) 
    def forward(self, x): 
        x = self.sequential(x) 
        return x

# Initialize neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
criterion = nn.BCELoss() 
optimizer = RMSprop(network.parameters())

# Define data loader
train_data = TensorDataset(x_train, y_train) 
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Compile the model using torch 2.0&#039;s optimizer
network = torch.compile(network)

# Train neural network
epochs = 8
train_losses = []
test_losses = []
for epoch in range(epochs):
    for batch_idx, (data, target) in enumerate(train_loader): 
        optimizer.zero_grad() 
        output = network(data) 
        loss = criterion(output, target) 
        loss.backward() 
        optimizer.step() 
     

    with torch.no_grad(): 
        train_output = network(x_train)
        train_loss = criterion(output, target)
        train_losses.append(train_loss.item())
    
        test_output = network(x_test)
        test_loss = criterion(test_output, y_test)
        test_losses.append(test_loss.item())

# Visualize loss history
epochs = range(0, epochs)
plt.plot(epochs, train_losses, &quot;r--&quot;)
plt.plot(epochs, test_losses, &quot;b-&quot;)
plt.legend([&quot;Training Loss&quot;, &quot;Test Loss&quot;])
plt.xlabel(&quot;Epoch&quot;)
plt.ylabel(&quot;Loss&quot;)
plt.show();خروجی:توضیحاتوقتی یک شبکه عصبی تازه ساخته شده است، عملکرد ضعیفی دارد. با یادگیری شبکه عصبی روی داده‌های آموزشی، خطای مدل هم در مجموعه آموزشی و هم در مجموعه آزمایشی معمولاً کاهش می‌یابد. اما در نقطه‌ای خاص، شبکه عصبی ممکن است شروع به «حفظ کردن» داده‌های آموزشی کند و بیش‌ازحد برازش (overfit) شود. وقتی این اتفاق می‌افتد، خطای آموزشی ممکن است همچنان کاهش یابد، اما خطای آزمایشی شروع به افزایش می‌کند. بنابراین، در بسیاری از موارد، یک «نقطه بهینه» وجود دارد که در آن خطای آزمایشی (که بیشتر به آن اهمیت می‌دهیم) در پایین‌ترین سطح خود قرار دارد. این اثر در راه‌حل نشان داده شده است، جایی که خطای آموزشی و آزمایشی در هر دوره به‌صورت بصری نمایش داده می‌شود. توجه کنید که خطای آزمایشی در حدود دوره ششم کمترین مقدار را دارد، اما پس از آن، خطای آموزشی به حالت ثابت می‌رسد، در حالی که خطای آزمایشی شروع به افزایش می‌کند. از این نقطه به بعد، مدل در حال بیش‌برازش است.21.9 کاهش بیش‌برازش با منظم‌سازی وزن‌هامسئلهمی‌خواهید با منظم‌سازی وزن‌های شبکه، بیش‌برازش را کاهش دهید.راه‌حلسعی کنید پارامترهای شبکه را جریمه کنید، که به آن منظم‌سازی وزن‌ها (weight regularization) نیز گفته می‌شود.# Import libraries
import torch
import torch.nn as nn
import numpy as np
from torch.utils.data import DataLoader, TensorDataset
from torch.optim import RMSprop
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# Create training and test sets
features, target = make_classification(n_classes=2, n_features=10, n_samples=1000) 
features_train, features_test, target_train, target_test = train_test_split( 
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float() 
y_train = torch.from_numpy(target_train).float().view(-1, 1) 
x_test = torch.from_numpy(features_test).float() 
y_test = torch.from_numpy(target_test).float().view(-1, 1)

# Define a neural network using Sequential
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.sequential = torch.nn.Sequential( 
             torch.nn.Linear(10, 16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16,16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16, 1), 
             torch.nn.Sigmoid() 
         ) 
    def forward(self, x): 
        x = self.sequential(x) 
        return x

# Initialize neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
criterion = nn.BCELoss()
optimizer = torch.optim.Adam(network.parameters(), lr=1e-4, weight_decay=1e-5)

# Define data loader
train_data = TensorDataset(x_train, y_train) 
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Compile the model using torch 2.0&#039;s optimizer
network = torch.compile(network)

# Train neural network
epochs = 100
train_losses = []
test_losses = []
for epoch in range(epochs):
    for batch_idx, (data, target) in enumerate(train_loader): 
        optimizer.zero_grad() 
        output = network(data) 
        loss = criterion(output, target) 
        loss.backward() 
        optimizer.step() 
     

# Evaluate neural network
with torch.no_grad():
    output = network(x_test)
    test_loss = criterion(output, y_test)
    test_accuracy = (output.round() == y_test).float().mean()
    print(&quot;Test Loss:&quot;, test_loss.item(), &quot;\tTest Accuracy:&quot;,
        test_accuracy.item())خروجی:Test Loss: 0.4030887186527252 Test Accuracy: 0.9599999785423279 توضیحاتیکی از راه‌های مقابله با بیش‌برازش در شبکه‌های عصبی، جریمه کردن پارامترها (یعنی وزن‌ها) است به‌گونه‌ای که مقادیر آن‌ها کوچک شوند. این کار باعث ایجاد مدلی ساده‌تر می‌شود که کمتر در معرض بیش‌برازش قرار می‌گیرد. این روش به نام منظم‌سازی وزن‌ها یا وزن‌کاهی (weight decay) شناخته می‌شود. به‌طور خاص، در منظم‌سازی وزن‌ها، یک جریمه (مانند نرم L2) به تابع خطا اضافه می‌شود.در PyTorch، می‌توانیم منظم‌سازی وزن‌ها را با افزودن weight_decay=1e-5 به بهینه‌ساز (optimizer) اعمال کنیم، جایی که منظم‌سازی انجام می‌شود. در این مثال، مقدار 1e-5 تعیین می‌کند که چقدر وزن‌های بزرگ‌تر جریمه شوند. مقادیر بزرگ‌تر از ۰ در PyTorch نشان‌دهنده استفاده از منظم‌سازی L2 است.21.10 کاهش بیش‌برازش با توقف زودهنگاممسئلهمی‌خواهید با توقف آموزش در زمانی که امتیازهای مجموعه آموزشی و آزمایشی از هم فاصله می‌گیرند، بیش‌برازش را کاهش دهید.راه‌حلاز PyTorch Lightning استفاده کنید تا استراتژی‌ای به نام توقف زودهنگام (early stopping) را پیاده‌سازی کنید.# Import libraries
import torch
import torch.nn as nn
import numpy as np
from torch.utils.data import DataLoader, TensorDataset
from torch.optim import RMSprop
import lightning as pl
from lightning.pytorch.callbacks.early_stopping import EarlyStopping
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# Create training and test sets
features, target = make_classification(n_classes=2, n_features=10, n_samples=1000) 
features_train, features_test, target_train, target_test = train_test_split( 
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float() 
y_train = torch.from_numpy(target_train).float().view(-1, 1) 
x_test = torch.from_numpy(features_test).float() 
y_test = torch.from_numpy(target_test).float().view(-1, 1)

# Define a neural network using Sequential
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.sequential = torch.nn.Sequential( 
             torch.nn.Linear(10, 16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16,16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16, 1), 
             torch.nn.Sigmoid() 
         ) 
    def forward(self, x): 
        x = self.sequential(x) 
        return x

class LightningNetwork(pl.LightningModule):
    def __init__(self, network):
        super().__init__()
        self.network = network
        self.criterion = nn.BCELoss()
        self.metric = nn.functional.binary_cross_entropy

    def training_step(self, batch, batch_idx):
        # training_step defines the train loop.
        data, target = batch
        output = self.network(data)
        loss = self.criterion(output, target)
        self.log(&quot;val_loss&quot;, loss)
        return loss
  
    def configure_optimizers(self):
        return torch.optim.Adam(self.parameters(), lr=1e-3)

# Define data loader
train_data = TensorDataset(x_train, y_train) 
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Initialize neural network
network = LightningNetwork(SimpleNeuralNet())

# Train network
trainer = pl.Trainer(callbacks=[EarlyStopping(monitor=&quot;val_loss&quot;, mode=&quot;min&quot;,
    patience=3)], max_epochs=1000)
trainer.fit(model=network, train_dataloaders=train_loader)خروجی:GPU available: False, used: False
TPU available: False, using: 0 TPU cores IPU available: False, using: 0 IPUs
HPU available: False, using: 0 HPUs 

  | Name      | Type            | Params
----------------------------------------------
0 | network   | SimpleNeuralNet | 465
1 | criterion | BCELoss         | 0
----------------------------------------------
465 Trainable params
0 Non-trainable params
465 Total params
0.002 Total estimated model params size (MB)
/usr/local/lib/python3.10/site-packages/lightning/pytorch/trainer/
connectors/data_connector.py:224: PossibleUserWarning:
The dataloader, train_dataloader, does not have many workers which
may be a bottleneck. Consider increasing the value of the `num_workers`
argument (try 7 which is the number of cpus on this machine)
in the `DataLoader` init to improve performance.
rank_zero_warn(
/usr/local/lib/python3.10/site-packages/lightning/pytorch/trainer/
trainer.py:1609: PossibleUserWarning: The number of training batches (9)
is smaller than the logging interval Trainer(log_every_n_steps=50).
Set a lower value for log_every_n_steps if you want to see logs
for the training epoch.
rank_zero_warn(
Epoch 23: 100%|███████████████| 9/9 [00:00&lt;00:00, 59.29it/s, loss=0.147, v_num=5]توضیحاتهمان‌طور که در بخش 21.8 بحث شد، معمولاً در چند دوره (epoch) ابتدایی آموزش، خطای مجموعه آموزشی و آزمایشی هر دو کاهش می‌یابد. اما در نقطه‌ای، شبکه شروع به «حفظ کردن» داده‌های آموزشی می‌کند، که باعث می‌شود خطای آموزشی همچنان کاهش یابد، در حالی که خطای آزمایشی شروع به افزایش می‌کند. به همین دلیل، یکی از رایج‌ترین و مؤثرترین روش‌ها برای مقابله با بیش‌برازش، نظارت بر فرآیند آموزش و توقف آن در زمانی است که خطای آزمایشی شروع به افزایش می‌کند. این استراتژی به نام توقف زودهنگام شناخته می‌شود.در PyTorch، می‌توانیم توقف زودهنگام را به‌صورت یک تابع callback پیاده‌سازی کنیم. توابع callback، توابعی هستند که در مراحل خاصی از فرآیند آموزش، مثلاً در پایان هر دوره، اجرا می‌شوند. با این حال، PyTorch به‌صورت پیش‌فرض کلاسی برای توقف زودهنگام ارائه نمی‌دهد، بنابراین در اینجا از کتابخانه محبوب PyTorch Lightning استفاده می‌کنیم که این قابلیت را به‌صورت آماده ارائه می‌دهد. PyTorch Lightning یک کتابخانه سطح بالا برای PyTorch است که ویژگی‌های مفید زیادی را فراهم می‌کند. در راه‌حل ما، ازEarlyStopping(monitor=&quot;val_loss&quot;, mode=&quot;min&quot;, patience=3) استفاده شده است تا مشخص کنیم که می‌خواهیم خطای آزمایشی (validation loss) را در هر دوره نظارت کنیم، و اگر این خطا پس از سه دوره (به‌صورت پیش‌فرض) بهبود نیابد، آموزش متوقف شود.اگر از callback توقف زودهنگام را استفاده نمی‌کردیم، مدل تا پایان حداکثر تعداد دوره‌ها (مثلاً 1000 دوره) بدون توقف خودکار به آموزش ادامه می‌داد.# Train network
trainer = pl.Trainer(max_epochs=1000) 
trainer.fit(model=network, train_dataloaders=train_loader) خروجی:GPU available: False, used: False
TPU available: False, using: 0 TPU cores
IPU available: False, using: 0 IPUs
HPU available: False, using: 0 HPUs

  | Name      | Type            | Params
----------------------------------------------
0 | network   | SimpleNeuralNet | 465
1 | criterion | BCELoss         | 0
----------------------------------------------
465 Trainable params
0 Non-trainable params
465 Total params
0.002 Total estimated model params size (MB)
Epoch 999: 100%|████████████| 9/9 [00:01&lt;00:00, 7.95it/s, loss=0.00188, v_num=6]
`Trainer.fit` stopped: `max_epochs=1000` reached.
Epoch 999: 100%|████████████| 9/9 [00:01&lt;00:00, 7.80it/s, loss=0.00188, v_num=6]21.11 کاهش بیش‌برازش با دراپ‌اوتمسئلهمی‌خواهید بیش‌برازش را کاهش دهید.راه‌حلبا استفاده از دراپ‌اوت (dropout)، نویز را به معماری شبکه خود اضافه کنید.# Load libraries
import torch
import torch.nn as nn
import numpy as np
from torch.utils.data import DataLoader, TensorDataset
from torch.optim import RMSprop
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# Create training and test sets
features, target = make_classification(n_classes=2, n_features=10, n_samples=1000) 
features_train, features_test, target_train, target_test = train_test_split( 
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float() 
y_train = torch.from_numpy(target_train).float().view(-1, 1) 
x_test = torch.from_numpy(features_test).float() 
y_test = torch.from_numpy(target_test).float().view(-1, 1)

# Define a neural network using Sequential
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.sequential = torch.nn.Sequential( 
             torch.nn.Linear(10, 16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16,16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16, 1), 
             torch.nn.Dropout(0.1), # Drop 10% of neurons
             torch.nn.Sigmoid() 
         ) 
    def forward(self, x): 
        x = self.sequential(x) 
        return x

# Initialize neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
criterion = nn.BCELoss()
optimizer = RMSprop(network.parameters())

# Define data loader
train_data = TensorDataset(x_train, y_train) 
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Compile the model using torch 2.0&#039;s optimizer
network = torch.compile(network)

# Train neural network
epochs = 3
for epoch in range(epochs):
    for batch_idx, (data, target) in enumerate(train_loader): 
        optimizer.zero_grad() 
        output = network(data) 
        loss = criterion(output, target) 
        loss.backward() 
        optimizer.step() 
     print(&quot;Epoch:&quot;, epoch+1, &quot;\tLoss:&quot;, loss.item())

# Evaluate neural network
with torch.no_grad():
    output = network(x_test)
    test_loss = criterion(output, y_test)
    test_accuracy = (output.round() == y_test).float().mean()
    print(&quot;Test Loss:&quot;, test_loss.item(), &quot;\tTest Accuracy:&quot;,
        test_accuracy.item())خروجی:Epoch: 1 Loss: 0.18791493773460388 
Epoch: 2 Loss: 0.17331615090370178 
Epoch: 3 Loss: 0.1384529024362564
Test Loss: 0.12702330946922302 Test Accuracy: 0.9100000262260437 
توضیحاتدراپ‌اوت یک روش رایج برای منظم‌سازی شبکه‌های عصبی کوچک‌تر است. در این روش، هر بار که یک دسته (batch) از داده‌ها برای آموزش آماده می‌شود، درصدی از واحدها (نرون‌ها) در یک یا چند لایه به‌صورت تصادفی با صفر ضرب می‌شوند (یعنی حذف یا «دراپ» می‌شوند). در این حالت، هر دسته روی همان شبکه (با پارامترهای یکسان) آموزش می‌بیند، اما هر دسته با نسخه‌ای کمی متفاوت از معماری شبکه روبه‌رو می‌شود.دراپ‌اوت به این دلیل مؤثر است که با حذف تصادفی واحدهای هر دسته، واحدهای شبکه را مجبور می‌کند تا مقادیر پارامترهایی را یاد بگیرند که در معماری‌های مختلف شبکه عملکرد خوبی داشته باشند. به عبارت دیگر، این روش باعث می‌شود واحدهای شبکه در برابر اختلالات (نویز) در واحدهای مخفی دیگر مقاوم شوند و این کار از حفظ کردن صرف داده‌های آموزشی توسط شبکه جلوگیری می‌کند.می‌توان دراپ‌اوت را هم به لایه‌های مخفی و هم به لایه ورودی اعمال کرد. وقتی لایه ورودی حذف می‌شود، مقدار ویژگی‌های آن برای آن دسته به شبکه وارد نمی‌شود.در PyTorch، می‌توانیم دراپ‌اوت را با افزودن یک لایه nn.Dropout به معماری شبکه پیاده‌سازی کنیم. هر لایه nn.Dropout درصدی از واحدهای لایه قبلی را در هر دسته، بر اساس یک هایپرپارامتر تعریف‌شده توسط کاربر، حذف می‌کند.21.12 ذخیره پیشرفت آموزش مدلمسئلهبا توجه به اینکه آموزش یک شبکه عصبی ممکن است زمان زیادی طول بکشد، می‌خواهید پیشرفت آموزش را ذخیره کنید تا در صورت وقفه در فرآیند آموزش، کار از دست نرود.راه‌حلاز تابع torch.save استفاده کنید تا مدل را پس از هر دوره (epoch) ذخیره کنید.# Load libraries
import torch
import torch.nn as nn
import numpy as np
from torch.utils.data import DataLoader, TensorDataset
from torch.optim import RMSprop
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# Create training and test sets
features, target = make_classification(n_classes=2, n_features=10, n_samples=1000) 
features_train, features_test, target_train, target_test = train_test_split( 
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float() 
y_train = torch.from_numpy(target_train).float().view(-1, 1) 
x_test = torch.from_numpy(features_test).float() 
y_test = torch.from_numpy(target_test).float().view(-1, 1)

# Define a neural network using Sequential
class SimpleNeuralNet(nn.Module): 
    def __init__(self): 
        super(SimpleNeuralNet, self).__init__() 
        self.sequential = torch.nn.Sequential( 
             torch.nn.Linear(10, 16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16,16), 
             torch.nn.ReLU(), 
             torch.nn.Linear(16, 1), 
             torch.nn.Dropout(0.1), # Drop 10% of neurons
             torch.nn.Sigmoid() 
         ) 
    def forward(self, x): 
        x = self.sequential(x) 
        return x

# Initialize neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
criterion = nn.BCELoss()
optimizer = RMSprop(network.parameters())

# Define data loader
train_data = TensorDataset(x_train, y_train) 
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Compile the model using torch 2.0&#039;s optimizer
network = torch.compile(network)

# Train neural network
epochs = 5

for epoch in range(epochs):
    for batch_idx, (data, target) in enumerate(train_loader): 
        optimizer.zero_grad() 
        output = network(data) 
        loss = criterion(output, target) 
        loss.backward() 
        optimizer.step() 
        # Save the model at the end of every epoch
        torch.save(
            {
                &#039;epoch&#039;: epoch,
                &#039;model_state_dict&#039;: network.state_dict(),
                &#039;optimizer_state_dict&#039;: optimizer.state_dict(),
                &#039;loss&#039;: loss,
            },
           &quot;model.pt&quot;
         )
     print(&quot;Epoch:&quot;, epoch+1, &quot;\tLoss:&quot;, loss.item())خروجی:Epoch: 1 Loss: 0.18791493773460388 
Epoch: 2 Loss: 0.17331615090370178 
Epoch: 3 Loss: 0.1384529024362564 
Epoch: 4 Loss: 0.1435958743095398 
Epoch: 5 Loss: 0.17967987060546875 توضیحاتدر دنیای واقعی، آموزش شبکه‌های عصبی ممکن است ساعت‌ها یا حتی روزها طول بکشد. در این مدت، مشکلات زیادی ممکن است رخ دهد: کامپیوتر ممکن است خاموش شود، سرورها ممکن است از کار بیفتند، یا یک دانشجوی بی‌ملاحظه لپ‌تاپ شما را ببندد.برای رفع این مشکل، می‌توانیم از torch.save استفاده کنیم تا مدل را پس از هر دوره ذخیره کنیم. به‌طور خاص، پس از هر دوره، مدل را در مکان مشخص‌شده‌ای مثل model.pt (آرگومان دوم تابع torch.save) ذخیره می‌کنیم. اگر فقط یک نام فایل (مثل model.pt) مشخص کنیم، این فایل در هر دوره با آخرین مدل بازنویسی می‌شود.همان‌طور که می‌توانید تصور کنید، می‌توانیم منطق بیشتری اضافه کنیم، مثلاً مدل را هر چند دوره یک‌بار ذخیره کنیم، یا فقط زمانی مدل را ذخیره کنیم که خطا کاهش یافته باشد. حتی می‌توانیم این رویکرد را با روش توقف زودهنگام (early stopping) در PyTorch Lightning ترکیب کنیم تا مطمئن شویم مدل در هر دوره‌ای که آموزش متوقف شود، ذخیره می‌شود.21.13 تنظیم شبکه‌های عصبیمسئلهمی‌خواهید بهترین هایپرپارامترها را برای شبکه عصبی خود به‌صورت خودکار انتخاب کنید.راه‌حلاز کتابخانه تنظیم Ray با PyTorch استفاده کنید.# Load libraries
from functools import partial
import numpy as np
import os
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.optim import RMSprop
from torch.utils.data import random_split, DataLoader, TensorDataset
from ray import tune
from ray.tune import CLIReporter
from ray.tune.schedulers import ASHAScheduler
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# Create training and test sets
features, target = make_classification(n_classes=2, n_features=10,
    n_samples=1000)
features_train, features_test, target_train, target_test = train_test_split(
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float()
y_train = torch.from_numpy(target_train).float().view(-1, 1)
x_test = torch.from_numpy(features_test).float()
y_test = torch.from_numpy(target_test).float().view(-1, 1)

# Define a neural network using `Sequential`
class SimpleNeuralNet(nn.Module):
    def __init__(self, layer_size_1=10, layer_size_2=10):
        super(SimpleNeuralNet, self).__init__()
        self.sequential = torch.nn.Sequential(
            torch.nn.Linear(10, layer_size_1),
            torch.nn.ReLU(),
            torch.nn.Linear(layer_size_1, layer_size_2),
            torch.nn.ReLU(),
            torch.nn.Linear(layer_size_2, 1),
            torch.nn.Sigmoid()
        )
    def forward(self, x):
        x = self.sequential(x)
        return x

config = {
    &quot;layer_size_1&quot;: tune.sample_from(lambda _: 2 ** np.random.randint(2, 9)),
    &quot;layer_size_2&quot;: tune.sample_from(lambda _: 2 ** np.random.randint(2, 9)),
    &quot;lr&quot;: tune.loguniform(1e-4, 1e-1),
}

scheduler = ASHAScheduler(
    metric=&quot;loss&quot;,
    mode=&quot;min&quot;,
    max_t=1000,
    grace_period=1,
    reduction_factor=2
)

reporter = CLIReporter(
    parameter_columns=[&quot;layer_size_1&quot;, &quot;layer_size_2&quot;, &quot;lr&quot;],
    metric_columns=[&quot;loss&quot;]
)

# Train neural network
def train_model(config, epochs=3):
    network = SimpleNeuralNet(config[&quot;layer_size_1&quot;], config[&quot;layer_size_2&quot;])
    
    criterion = nn.BCELoss()
    optimizer = optim.SGD(network.parameters(), lr=config[&quot;lr&quot;], momentum=0.9)
    
    train_data = TensorDataset(x_train, y_train)
    train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

    # Compile the model using torch 2.0&#039;s optimizer
    network = torch.compile(network)

    for epoch in range(epochs):
        for batch_idx, (data, target) in enumerate(train_loader):
            optimizer.zero_grad()
            output = network(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
            tune.report(loss=(loss.item()))
result = tune.run(
    train_model,
    resources_per_trial={&quot;cpu&quot;: 2},
    config=config,
    num_samples=1,
    scheduler=scheduler,
    progress_reporter=reporter
)

best_trial = result.get_best_trial(&quot;loss&quot;, &quot;min&quot;, &quot;last&quot;)
print(&quot;Best trial config: {}&quot;.format(best_trial.config))
print(&quot;Best trial final validation loss: {}&quot;.format(
    best_trial.last_result[&quot;loss&quot;]))
best_trained_model = SimpleNeuralNet(best_trial.config[&quot;layer_size_1&quot;],
    best_trial.config[&quot;layer_size_2&quot;])خروجی:== Status == 
Current time: 2023-03-05 23:31:33 (running for 00:00:00.07)
Memory usage on this node: 1.7/15.6 GiB
Using AsyncHyperBand: num_stopped=0 
Bracket: 
Iter 512.000:None | 
Iter 256.000:None | 
Iter 128.000:None | 
Iter 64.000: None | 
Iter 32.000: None | 
Iter 16.000: None | 
Iter 8.000:  None | 
Iter 4.000:  None | 
Iter 2.000:  None | 
Iter 1.000:  None
Resources requested: 2.0/7 CPUs, 0/0 GPUs, 0.0/8.95 GiB heap, 0.0/4.48 GiB objects
Result logdir: /root/ray_results/train_model_2023-03-05_23-31-33
Number of trials: 1/1 (1 RUNNING) توضیحاتدر بخش‌های 12.1 و 12.2، به استفاده از تکنیک‌های انتخاب مدل در scikit-learn برای شناسایی بهترین هایپرپارامترهای یک مدل scikit-learn پرداختیم. اگرچه به‌طور کلی رویکرد scikit-learn را می‌توان برای شبکه‌های عصبی نیز به‌کار برد، اما کتابخانه تنظیم Ray یک API پیشرفته ارائه می‌دهد که به شما امکان می‌دهد آزمایش‌ها را روی CPU و GPU برنامه‌ریزی کنید.هایپرپارامترهای یک مدل اهمیت زیادی دارند و باید با دقت انتخاب شوند. با این حال، انجام آزمایش برای انتخاب هایپرپارامترها می‌تواند هم پرهزینه و هم زمان‌بر باشد. بنابراین، تنظیم خودکار هایپرپارامترهای شبکه‌های عصبی راه‌حل نهایی نیست، اما در شرایط خاصی ابزار مفیدی به شمار می‌رود.در راه‌حل ما، جست‌وجویی برای پارامترهای مختلف، مانند اندازه لایه‌ها و نرخ یادگیری بهینه‌ساز، انجام دادیم. best_trial.config پارامترهایی را در تنظیمات Ray نشان می‌دهد که منجر به کمترین خطا و بهترین نتیجه آزمایش شده‌اند.21.14 تجسم شبکه‌های عصبیمسئلهمی‌خواهید معماری یک شبکه عصبی را به‌سرعت تجسم کنید.راه‌حلاز تابع make_dot در کتابخانه torch_viz استفاده کنید:# Load libraries
import torch
import torch.nn as nn
import numpy as np
from torch.utils.data import DataLoader, TensorDataset
from torch.optim import RMSprop
from torchviz import make_dot
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# Create training and test sets
features, target = make_classification(n_classes=2, n_features=10,
    n_samples=1000)
features_train, features_test, target_train, target_test = train_test_split(
    features, target, test_size=0.1, random_state=1)

# Set random seed
torch.manual_seed(0)
np.random.seed(0)

# Convert data to PyTorch tensors
x_train = torch.from_numpy(features_train).float()
y_train = torch.from_numpy(target_train).float().view(-1, 1)
x_test = torch.from_numpy(features_test).float()
y_test = torch.from_numpy(target_test).float().view(-1, 1)

# Define a neural network using `Sequential`
class SimpleNeuralNet(nn.Module):
    def __init__(self):
        super(SimpleNeuralNet, self).__init__()
        self.sequential = torch.nn.Sequential(
            torch.nn.Linear(10, 16),
            torch.nn.ReLU(),
            torch.nn.Linear(16, 16),
            torch.nn.ReLU(),
            torch.nn.Linear(16, 1),
            torch.nn.Sigmoid()
        )
    def forward(self, x):
        x = self.sequential(x)
        return x
# Initialize neural network
network = SimpleNeuralNet()

# Define loss function, optimizer
criterion = nn.BCELoss()
optimizer = RMSprop(network.parameters())

# Define data loader
train_data = TensorDataset(x_train, y_train)
train_loader = DataLoader(train_data, batch_size=100, shuffle=True)

# Compile the model using torch 2.0&#039;s optimizer
network = torch.compile(network)

# Train neural network
epochs = 3
for epoch in range(epochs):
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()
        output = network(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
make_dot(output.detach(), params=dict(
    list(
        network.named_parameters()
        )
      )
    ).render(
        &quot;simple_neural_network&quot;,
        format=&quot;png&quot;
)خروجی:&#039;simple_neural_network.png&#039; اگر تصویری که روی دستگاه ما ذخیره شده است را باز کنیم، می‌توانیم موارد زیر را ببینیم:توضیحاتکتابخانه torchviz توابع کاربردی ساده‌ای را ارائه می‌دهد تا به‌سرعت شبکه‌های عصبی را تجسم کرده و آن‌ها را به‌صورت تصویر ذخیره کنیم.</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Wed, 27 Aug 2025 10:40:10 +0330</pubDate>
            </item>
                    <item>
                <title>فصل 20 -تنسورها با کتابخانه پایتورچ</title>
                <link>https://virgool.io/mojino/%D9%81%D8%B5%D9%84-20-%D8%AA%D9%86%D8%B3%D9%88%D8%B1%D9%87%D8%A7-%D8%A8%D8%A7-%DA%A9%D8%AA%D8%A7%D8%A8%D8%AE%D8%A7%D9%86%D9%87-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D8%B1%DA%86-mwzvkbclbmb8</link>
                <description>20.0 مقدمههمان‌طور که NumPy یک ابزار پایه‌ای برای دستکاری داده‌ها در مجموعه ابزارهای یادگیری ماشین است، PyTorch نیز یک ابزار اساسی برای کار با تنسورها در مجموعه ابزارهای یادگیری عمیق محسوب می‌شود. پیش از پرداختن به یادگیری عمیق، باید با تنسورهای PyTorch آشنا شویم و عملیات‌های متعددی مشابه آنچه در فصل اول با NumPy انجام دادیم، پیاده‌سازی کنیم.اگرچه PyTorch تنها یکی از چندین کتابخانه یادگیری عمیق است، اما در میان دانشگاه‌ها و صنعت از محبوبیت قابل‌توجهی برخوردار است. تنسورهای PyTorch بسیار شبیه به آرایه‌های چندبعدی NumPy هستند. با این حال، این تنسورها امکان انجام عملیات روی GPUها (سخت‌افزارهای تخصصی برای یادگیری عمیق) را نیز فراهم می‌کنند. در این فصل، با اصول اولیه تنسورهای PyTorch و عملیات‌های رایج سطح پایین آشنا خواهیم شد.20.1 ایجاد یک تنسورمشکلنیاز به ایجاد یک تنسور دارید.راه‌حلاز PyTorch برای ایجاد یک تنسور استفاده کنید:# Load library 
import torch

# Create a vector as a row
tensor_row = torch.tensor([1, 2, 3])

# Create a vector as a column
tensor_column = torch.tensor(
    [
        [1],
        [2],
        [3]
    ]
)توضیحاتساختار داده اصلی در PyTorch، تنسور است و از بسیاری جهات، تنسورها دقیقاً مشابه آرایه‌های چندبعدی NumPy هستند که در فصل اول استفاده کردیم. درست مانند بردارها و آرایه‌ها، این تنسورها می‌توانند به‌صورت افقی (یعنی ردیف‌ها) یا عمودی (یعنی ستون‌ها) نمایش داده شوند.20.2 ایجاد تنسور از NumPyمشکلنیاز به ایجاد تنسورهای PyTorch از آرایه‌های NumPy دارید.راه‌حلاز تابع from_numpy در PyTorch استفاده کنید:# Import libraries
import numpy as np
import torch

# Create a NumPy array
vector_row = np.array([1, 2, 3])

# Create a tensor from a NumPy array
tensor_row = torch.from_numpy(vector_row)
توضیحاتهمان‌طور که می‌بینیم، PyTorch از نظر نحوی بسیار شبیه به NumPy است. علاوه بر این، به‌راحتی امکان تبدیل آرایه‌های NumPy به تنسورهای PyTorch را فراهم می‌کند که می‌توان از آن‌ها روی GPUها و سایر سخت‌افزارهای شتاب‌دهنده استفاده کرد. در زمان نگارش این متن، در مستندات PyTorch بارها به NumPy اشاره شده است و PyTorch حتی راهکاری ارائه می‌دهد که تنسورهای PyTorch و آرایه‌های NumPy بتوانند از حافظه یکسانی استفاده کنند تا سربار (overhead) کاهش یابد.20.3 ایجاد تنسور پراکنده(Sparse)مشکلبا داده‌هایی که تعداد کمی مقادیر غیرصفر دارند، می‌خواهید آن‌ها را به‌صورت کارآمد با یک تنسور نمایش دهید.راه‌حلاز تابع to_sparse در PyTorch استفاده کنید:# Import libraries
import torch

# Create a tensor
tensor = torch.tensor(
 [
  [0, 0],
  [0, 1],
  [3, 0]
 ]
)

# Create a sparse tensor from a regular tensor
sparse_tensor = tensor.to_sparse()توضیحاتتنسورهای پراکنده روش‌های کارآمدی از نظر حافظه برای نمایش داده‌هایی هستند که بیشتر شامل صفرها می‌شوند. در فصل اول، از scipy برای ایجاد یک ماتریس پراکنده فشرده‌شده به‌صورت ردیفی (CSR) استفاده کردیم که دیگر یک آرایه NumPy نبود.کلاس torch.Tensor به ما امکان می‌دهد هم ماتریس‌های معمولی و هم ماتریس‌های پراکنده را با استفاده از یک شیء یکسان ایجاد کنیم. اگر نوع دو تنسوری که تازه ایجاد کردیم را بررسی کنیم، می‌بینیم که هر دو در واقع از یک کلاس یکسان هستند:print(type(tensor)) 
print(type(sparse_tensor))خروجی:&lt;class &#039;torch.Tensor&#039;&gt; 
&lt;class &#039;torch.Tensor&#039;&gt;20.4 انتخاب عناصر در یک تنسورمشکلنیاز به انتخاب عناصر خاصی از یک تنسور دارید.راه‌حلاز ایندکس‌گذاری و برش‌دهی مشابه NumPy برای بازگرداندن عناصر استفاده کنید:# Load library
import torch

# Create vector tensor
vector = torch.tensor([1, 2, 3, 4, 5, 6])

# Create matrix tensor
matrix = torch.tensor(
    [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]
    ]
)

# Select third element of vector
vector[2]خروجی:tensor(3) # Select second row, second column
matrix[1,1] خروجی:tensor(5) توضیحاتمانند آرایه‌های NumPy و تقریباً همه چیز در پایتون، تنسورهای PyTorch از ایندکس‌گذاری مبتنی بر صفر استفاده می‌کنند. هم ایندکس‌گذاری و هم برش‌دهی پشتیبانی می‌شوند. یک تفاوت کلیدی این است که ایندکس‌گذاری یک تنسور PyTorch برای بازگرداندن یک عنصر منفرد، همچنان یک تنسور برمی‌گرداند، نه مقدار خود شیء (که می‌توانست به‌صورت عدد صحیح یا اعشاری باشد).نحو برش‌دهی نیز با NumPy هم‌خوانی دارد و در PyTorch اشیائی از نوع تنسور برمی‌گرداند:# Select all elements of a vector 
vector[:]خروجی:array([1, 2, 3, 4, 5, 6])همه چیز را تا عنصر سوم انتخاب کنید:# Select everything up to and including the third element
vector[:3] خروجی:tensor([1, 2, 3]) بعد از عنصر سوم همه چیز را انتخاب کنید:# Select everything after the third element
vector[3:] خروجی:tensor([4, 5, 6]) آخرین عنصر را انتخاب کنید:# Select the last element
vector[-1] خروجی:tensor(6) دو ردیف اول و تمام ستون های یک ماتریس را انتخاب کنید:# Select the first two rows and all columns of a matrix
matrix[:2,:] خروجی:tensor([[1, 2, 3], [4, 5, 6]]) همه ردیف ها و ستون دوم را انتخاب کنید:# Select all rows and the second column
matrix[:,1:2] خروجی:tensor([[2], [5], [8]]) یک تفاوت مهم این است که تنسورهای PyTorch هنوز از گام‌های منفی (negative steps) در برش‌دهی پشتیبانی نمی‌کنند. بنابراین، تلاش برای معکوس کردن یک تنسور با استفاده از برش‌دهی منجر به خطا می‌شود:# Reverse the vector
vector[::-1] خروجی:ValueError: step must be greater than zero به‌جای آن، اگر بخواهیم یک تنسور را معکوس کنیم، می‌توانیم از متد flip استفاده کنیم:vector.flip(dims=(-1,)) خروجی:tensor([6, 5, 4, 3, 2, 1]) 20.5 توصیف یک تنسور  مشکل  می‌خواهید شکل، نوع داده، قالب و سخت‌افزاری که یک تنسور از آن استفاده می‌کند را توصیف کنید.  راه‌حل  ویژگی‌های shape، dtype، layout و device تنسور را بررسی کنید:  # Load library 
import torch

# Create a tensor
tensor = torch.tensor([[1,2,3], [1,2,3]])

# Get the shape of the tensor
tensor.shapeخروجی:torch.Size([2, 3]) نوع داده موارد موجود در تانسور را دریافت کنید:# Get the data type of items in the tensor
tensor.dtype خروجی:torch.int64 قالب تانسور را دریافت کنید# Get the layout of the tensor
tensor.layout خروجی:torch.strided دستگاه مورد استفاده تانسور را دریافت کنید:# Get the device being used by the tensor
tensor.device خروجی:device(type=&#039;cpu&#039;) توضیحات  تنسورهای PyTorch ویژگی‌های مفیدی برای جمع‌آوری اطلاعات درباره یک تنسور ارائه می‌دهند، از جمله:  - شکل (Shape): ابعاد تنسور را نشان می‌دهد.  - نوع داده (Dtype): نوع داده اشیاء درون تنسور را مشخص می‌کند.  - قالب (Layout): نحوه چیدمان حافظه را نشان می‌دهد (رایج‌ترین آن strided است که برای تنسورهای متراکم استفاده می‌شود).  - دستگاه (Device): سخت‌افزاری که تنسور روی آن ذخیره شده است (CPU یا GPU) را مشخص می‌کند.  تفاوت کلیدی بین تنسورها و آرایه‌ها در ویژگی‌هایی مانند device است، زیرا تنسورها امکان استفاده از گزینه‌های شتاب‌دهنده سخت‌افزاری مانند GPU را فراهم می‌کنند.20.6 اعمال عملیات بر روی عناصر  مشکل  می‌خواهید یک عملیات را بر روی تمام عناصر یک تنسور اعمال کنید.  راه‌حل  از قابلیت پخش (broadcasting) در PyTorch استفاده کنید:  # Load library 
import torch

# Create a tensor
tensor = torch.tensor([1, 2, 3])

# Broadcast an arithmetic operation to all elements in a tensor
tensor * 100خروجی:tensor([100, 200, 300]) توضیحات  عملیات‌های پایه در PyTorch از پخش (broadcasting) بهره می‌برند تا این عملیات‌ها را با استفاده از سخت‌افزارهای شتاب‌دهنده مانند GPU به‌صورت موازی انجام دهند. این موضوع برای عملگرهای ریاضی پشتیبانی‌شده در پایتون (+، -، ×، /) و سایر توابع داخلی PyTorch صدق می‌کند. برخلاف NumPy، PyTorch شامل متد vectorize برای اعمال یک تابع به تمام عناصر یک تنسور نیست. بااین‌حال، PyTorch تمامی ابزارهای ریاضی لازم برای توزیع و شتاب‌دهی به عملیات‌های معمول موردنیاز در جریان‌های کاری یادگیری عمیق را فراهم می‌کند.20.7 یافتن مقادیر حداکثر و حداقل  مشکل  نیاز به یافتن مقدار حداکثر یا حداقل در یک تنسور دارید.  راه‌حل  از متدهای max و min در PyTorch استفاده کنید:  # Load library
import torch

# Create a tensor
torch.tensor([1,2,3])

# Find the largest value
tensor.max()خروجی:tensor(3) یافتن کوچکترین مقدار:# Find the smallest value
tensor.min() خروجی:tensor(1) توضیحات  متدهای max و min یک تنسور به ما کمک می‌کنند تا بزرگ‌ترین یا کوچک‌ترین مقادیر موجود در آن تنسور را پیدا کنیم. این متدها به همان شکل برای تنسورهای چندبعدی نیز کار می‌کنند:# Create a multidimensional tensor
tensor = torch.tensor([[1,2,3],[1,2,5]])

# Find the largest value
tensor.max() خروجی:tensor(5) 20.8 تغییر شکل تنسورها  مشکل  می‌خواهید شکل (تعداد ردیف‌ها و ستون‌ها) یک تنسور را بدون تغییر مقادیر عناصر آن تغییر دهید.  راه‌حل  از متد reshape در PyTorch استفاده کنید:  # Load library
import torch

# Create 4x3 tensor
tensor = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])

# Reshape tensor into 2x6 tensor
tensor.reshape(2, 6) 
خروجی:tensor([[ 1, 2, 3,  4,  5,  6], 
        [ 7, 8, 9, 10, 11, 12]])توضیحات  تغییر شکل تنسور در حوزه یادگیری عمیق امری رایج است، زیرا نورون‌های یک شبکه عصبی اغلب به تنسورهایی با شکل خاص نیاز دارند. از آنجا که شکل موردنیاز یک تنسور ممکن است بین نورون‌های مختلف در یک شبکه عصبی تغییر کند، داشتن درک عمیق از ورودی‌ها و خروجی‌ها در یادگیری عمیق مفید است.  20.9 ترانهاده کردن یک تنسور  مشکل  نیاز به ترانهاده کردن یک تنسور دارید.  راه‌حل  از متد mT استفاده کنید:  # Load library
import torch

# Create a two-dimensional tensor
tensor = torch.tensor([[[1,2,3]]])

# Transpose it
tensor.mT خروجی:tensor([[1],
        [2],
        [3]])توضیحات  ترانهاده کردن در PyTorch کمی متفاوت از NumPy است. متد T که برای آرایه‌های NumPy استفاده می‌شود، در PyTorch تنها برای تنسورهای دوبعدی پشتیبانی می‌شود و در زمان نگارش این متن، برای تنسورهای با اشکال دیگر منسوخ شده است. متد mT که برای ترانهاده کردن دسته‌ای از تنسورها استفاده می‌شود، ترجیح داده می‌شود، زیرا برای ابعاد بیشتر از دو مقیاس‌پذیر است.  روش دیگری برای ترانهاده کردن تنسورهای PyTorch با هر شکلی، استفاده از متد permute است:  tensor.permute(*torch.arange(tensor.ndim - 1, -1, -1))خروجی:tensor([[1], [2], [3]]) این متد برای تنسورهای یک‌بعدی نیز کار می‌کند (که در آن مقدار تنسور ترانهاده‌شده همانند تنسور اصلی است).  20.10 مسطح کردن یک تنسور  مشکل  نیاز به تبدیل یک تنسور به یک‌بعدی دارید.  راه‌حل  از متد flatten استفاده کنید:  # Load library
import torch

# Create tensor
tensor = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# Flatten tensor
tensor.flatten() خروجی: tensor([1, 2, 3, 4, 5, 6, 7, 8, 9])توضیحات  مسطح کردن یک تنسور تکنیکی مفید برای تبدیل یک تنسور چندبعدی به یک‌بعدی است.  20.11 محاسبه ضرب داخلی  مشکل  نیاز به محاسبه ضرب داخلی دو تنسور دارید.  راه‌حل  از متد dot استفاده کنید:  # Load library
import torch

# Create one tensor
tensor_1 = torch.tensor([1, 2, 3])

# Create another tensor
tensor_2 = torch.tensor([4, 5, 6])

# Calculate the dot product of the two tensors
tensor_1.dot(tensor_2) خروجی:tensor(32)توضیحات  محاسبه ضرب داخلی دو تنسور عملیاتی رایج است که هم در حوزه یادگیری عمیق و هم در فضای بازیابی اطلاعات کاربرد دارد. شاید به خاطر بیاورید که در بخش‌های قبلی کتاب، از ضرب داخلی دو بردار برای انجام جستجوی مبتنی بر شباهت کسینوسی استفاده کردیم. انجام این کار در PyTorch روی GPU (به‌جای استفاده از NumPy یا scikit-learn روی CPU) می‌تواند بهبود عملکرد چشمگیری در مسائل بازیابی اطلاعات به همراه داشته باشد.  20.12 ضرب تنسورها  مشکل  نیاز به ضرب دو تنسور دارید.  راه‌حل  از عملگرهای حسابی پایه پایتون استفاده کنید:  # Load library
import torch

# Create one tensor
tensor_1 = torch.tensor([1, 2, 3])

# Create another tensor
tensor_2 = torch.tensor([4, 5, 6])

# Multiply the two tensors
tensor_1 * tensor_2 خروجی:tensor([ 4, 10, 18])توضیحات  PyTorch از عملگرهای حسابی پایه مانند ×، +، - و / پشتیبانی می‌کند. اگرچه ضرب تنسورها احتمالاً یکی از رایج‌ترین عملیات‌ها در یادگیری عمیق است، دانستن این نکته مفید است که تنسورها همچنین می‌توانند جمع، تفریق یا تقسیم شوند.  - جمع یک تنسور با تنسور دیگر:  tensor_1 + tensor_2خروجی: tensor([5, 7, 9]) - تفریق یک تنسور از تنسور دیگر:  tensor_1 - tensor_2خروجی: tensor([-3, -3, -3]) - تقسیم یک تنسور بر تنسور دیگر:tensor_1 / tensor_2خروجی:tensor([0.2500, 0.4000, 0.5000]) </description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Mon, 11 Aug 2025 14:58:32 +0330</pubDate>
            </item>
                    <item>
                <title>فصل 17 - ماشین بردار پشتیبان</title>
                <link>https://virgool.io/mojino/%D9%81%D8%B5%D9%84-17-%D9%85%D8%A7%D8%B4%DB%8C%D9%86-%D8%A8%D8%B1%D8%AF%D8%A7%D8%B1-%D9%BE%D8%B4%D8%AA%DB%8C%D8%A8%D8%A7%D9%86-q45hn1rwmewi</link>
                <description>17.0 مقدمهبرای درک ماشین‌های بردار پشتیبان (SVM)، ابتدا باید مفهوم ابرصفحه‌ها را درک کنیم. به طور رسمی، ابرصفحه یک زیرفضای n-1 بعدی در یک فضای n-بعدی است. اگرچه این تعریف ممکن است پیچیده به نظر برسد، اما در واقع بسیار ساده است. برای مثال، اگر بخواهیم یک فضای دوبعدی را تقسیم کنیم، از یک ابرصفحه یک‌بعدی (یعنی یک خط) استفاده می‌کنیم. اگر بخواهیم یک فضای سه‌بعدی را تقسیم کنیم، از یک ابرصفحه دوبعدی (مانند یک ورق کاغذ یا ملافه) استفاده می‌کنیم. ابرصفحه به سادگی تعمیمی از این مفهوم به n بعد است.ماشین‌های بردار پشتیبان داده‌ها را با یافتن ابرصفحه‌ای که حاشیه بین کلاس‌ها را در داده‌های آموزشی بیشینه می‌کند، طبقه‌بندی می‌کنند. در یک مثال دوبعدی با دو کلاس، می‌توانیم ابرصفحه را به صورت پهن‌ترین &quot;نوار&quot; مستقیم (یعنی خطی با حاشیه‌ها) تصور کنیم که دو کلاس را از هم جدا می‌کند.در این فصل، به آموزش ماشین‌های بردار پشتیبان در موقعیت‌های مختلف پرداخته و به بررسی عمیق‌تر نحوه گسترش این روش برای حل مشکلات رایج می‌پردازیم.17.1 آموزش یک طبقه‌بندی‌کننده خطیمسئلهشما نیاز دارید مدلی را برای طبقه‌بندی مشاهدات آموزش دهید.راه‌حلاز یک طبقه‌بندی‌کننده بردار پشتیبان (SVC) استفاده کنید تا ابرصفحه‌ای را پیدا کنید که حاشیه بین کلاس‌ها را بیشینه کند.# Load libraries
from sklearn.svm import LinearSVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np

# Load data with only two classes and two features
iris = datasets.load_iris()
features = iris.data[:100,:2]
target = iris.target[:100]

# Standardize features
scaler = StandardScaler()
features_standardized = scaler.fit_transform(features)

# Create support vector classifier
svc = LinearSVC(C=1.0)

# Train model
model = svc.fit(features_standardized, target)بحثLinearSVC در کتابخانه scikit-learn یک طبقه‌بندی‌کننده بردار پشتیبان (SVC) ساده را پیاده‌سازی می‌کند. برای درک شهودی از عملکرد SVC، بیایید داده‌ها و ابرصفحه را ترسیم کنیم. اگرچه SVC‌ها در ابعاد بالا به خوبی کار می‌کنند، در این راه‌حل ما تنها دو ویژگی را بارگذاری کردیم و زیرمجموعه‌ای از مشاهدات را انتخاب کردیم تا داده‌ها فقط شامل دو کلاس باشند. این کار به ما امکان می‌دهد مدل را به صورت بصری نمایش دهیم. به یاد داشته باشید که SVC تلاش می‌کند ابرصفحه‌ای را پیدا کند—که در دو بعد یک خط است—که حاشیه بین کلاس‌ها را بیشینه کند. در کد زیر، دو کلاس را در یک فضای دوبعدی ترسیم کرده و سپس ابرصفحه را رسم می‌کنیم:# Load library
from matplotlib import pyplot as plt

# Plot data points and color using their class
color = [&quot;black&quot; if c == 0 else &quot;lightgrey&quot; for c in target]
plt.scatter(features_standardized[:,0], features_standardized[:,1], c=color)

# Create the hyperplane
w = svc.coef_[0]
a = -w[0] / w[1]
xx = np.linspace(-2.5, 2.5)
yy = a * xx - (svc.intercept_[0]) / w[1]

# Plot the hyperplane
plt.plot(xx, yy)
plt.axis(&quot;off&quot;), plt.show();
در این نمایش بصری، تمام مشاهدات کلاس ۰ به رنگ سیاه و مشاهدات کلاس ۱ به رنگ خاکستری روشن هستند. ابرصفحه، مرز تصمیم‌گیری است که مشخص می‌کند مشاهدات جدید چگونه طبقه‌بندی می‌شوند. به طور خاص، هر مشاهده‌ای که بالای خط باشد به عنوان کلاس ۰ و هر مشاهده‌ای که زیر خط باشد به عنوان کلاس ۱ طبقه‌بندی می‌شود. می‌توانیم این را با ایجاد یک مشاهده جدید در گوشه بالا-چپ نمایش بصری‌مان آزمایش کنیم، که باید به عنوان کلاس ۰ پیش‌بینی شود:# Create new observation
new_observation = [[ -2, 3]]

# Predict class of new observation
svc.predict(new_observation)خروجی:array([0])چند نکته درباره SVC‌ها قابل توجه است. اول، برای ساده‌سازی نمایش بصری، مثال ما به یک مورد دودویی (یعنی فقط دو کلاس) محدود شد؛ با این حال، SVC‌ها می‌توانند با چندین کلاس نیز به خوبی کار کنند. دوم، همان‌طور که نمایش بصری ما نشان می‌دهد، ابرصفحه به طور ذاتی خطی است (یعنی منحنی نیست). در این مثال این موضوع مشکلی ایجاد نکرد، زیرا داده‌ها به صورت خطی قابل تفکیک بودند، به این معنی که یک ابرصفحه می‌توانست دو کلاس را به طور کامل از هم جدا کند. اما در دنیای واقعی، این حالت به ندرت پیش می‌آید.معمولاً نمی‌توانیم کلاس‌ها را به طور کامل از هم جدا کنیم. در چنین موقعیت‌هایی، تعادلی بین بیشینه کردن حاشیه ابرصفحه و کمینه کردن خطای طبقه‌بندی وجود دارد. در SVC، این خطا توسط پارامتر C کنترل می‌شود. C یک پارامتر تنظیم‌پذیر در SVC است که جریمه‌ای برای طبقه‌بندی نادرست یک نقطه داده اعمال می‌کند. وقتی C کوچک است، طبقه‌بندی‌کننده با نقاط داده‌ای که به اشتباه طبقه‌بندی شده‌اند مشکلی ندارد (باعث بایاس بالا اما واریانس پایین می‌شود). وقتی C بزرگ است، طبقه‌بندی‌کننده برای اشتباهات طبقه‌بندی جریمه سنگینی می‌پردازد و بنابراین تمام تلاش خود را می‌کند تا هیچ داده‌ای به اشتباه طبقه‌بندی نشود (باعث بایاس پایین اما واریانس بالا می‌شود).در scikit-learn، مقدار C توسط پارامتر C تعیین می‌شود و به طور پیش‌فرض برابر با ۱.۰ است. باید C را به عنوان یک ابرپارامتر الگوریتم یادگیری در نظر بگیریم و با استفاده از تکنیک‌های انتخاب مدل که در فصل دوازدهم بحث شده‌اند، آن را تنظیم کنیم.17.2 مدیریت کلاس‌های غیرقابل تفکیک خطی با استفاده از کرنل‌هامسئلهشما نیاز دارید یک طبقه‌بندی‌کننده بردار پشتیبان را آموزش دهید، اما کلاس‌های شما به صورت خطی قابل تفکیک نیستند.راه‌حلاز یک ماشین بردار پشتیبان با استفاده از توابع کرنل برای ایجاد مرزهای تصمیم‌گیری غیرخطی استفاده کنید:# Load libraries
from sklearn.svm import SVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np

# Set randomization seed
np.random.seed(0)

# Generate two features
features = np.random.randn(200, 2)

# Use an XOR gate (you don&#039;t need to know what this is) to generate
# linearly inseparable classes
target_xor = np.logical_xor(features[:, 0] &gt; 0, features[:, 1] &gt; 0)
target = np.where(target_xor, 0, 1)

# Create a support vector machine with a radial basis function kernel
svc = SVC(kernel=&quot;rbf&quot;, random_state=0, gamma=1, C=1)

# Train the classifier
model = svc.fit(features, target)
بحثتوضیح کامل ماشین‌های بردار پشتیبان خارج از محدوده این کتاب است. با این حال، توضیح مختصری احتمالاً برای درک ماشین‌های بردار پشتیبان و کرنل‌ها مفید خواهد بود. به دلایلی که بهتر است در جای دیگری آموخته شوند، یک طبقه‌بندی‌کننده بردار پشتیبان می‌تواند به صورت زیر نمایش داده شود:که در آن β0 بایاس است، Ѕ مجموعه تمام مشاهدات بردار پشتیبان، α پارامترهای مدل هستند که باید آموخته شوند، xi و ´xi جفت‌هایی از دو مشاهده بردار پشتیبان هستند. مهم‌تر از همه، K یک تابع کرنل است که شباهت بین xi و ´xi را مقایسه می‌کند. اگر توابع کرنل را درک نمی‌کنید، نگران نباشید. برای اهداف ما، فقط کافی است بدانید که (1) K نوع ابرصفحه‌ای که برای جداسازی کلاس‌های ما استفاده می‌شود را تعیین می‌کند، و (2) ما با استفاده از کرنل‌های مختلف، ابرصفحه‌های متفاوتی ایجاد می‌کنیم. برای مثال، اگر بخواهیم یک ابرصفحه خطی ساده مانند آنچه در دستورالعمل 17.1 ایجاد کردیم داشته باشیم، می‌توانیم از کرنل خطی استفاده کنیم:که در آن p تعداد ویژگی‌هاست. اما اگر بخواهیم یک مرز تصمیم‌گیری غیرخطی داشته باشیم، کرنل خطی را با یک کرنل پلی‌نومیال جایگزین می‌کنیم:که در آن d درجه تابع کرنل پلی‌نومیال است. به طور جایگزین، می‌توانیم از یکی از رایج‌ترین کرنل‌ها در ماشین‌های بردار پشتیبان، یعنی کرنل تابع پایه شعاعی (RBF)، استفاده کنیم:که در آن γ یک ابرپارامتر است و باید بزرگ‌تر از صفر باشد. نکته اصلی توضیحات بالا این است که اگر داده‌های غیرقابل تفکیک خطی داشته باشیم، می‌توانیم کرنل خطی را با یک کرنل جایگزین کنیم تا یک مرز تصمیم‌گیری ابرصفحه غیرخطی ایجاد کنیم.می‌توانیم شهود پشت کرنل‌ها را با نمایش یک مثال ساده درک کنیم. این تابع، که بر اساس کاری از سباستین راشکا طراحی شده، مشاهدات و مرز تصمیم‌گیری ابرصفحه را در یک فضای دوبعدی ترسیم می‌کند. لازم نیست نحوه کار این تابع را درک کنید؛ من آن را اینجا آورده‌ام تا بتوانید خودتان آزمایش کنید:# Plot observations and decision boundary hyperplane 
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt

def plot_decision_regions(X, y, classifier):
    cmap = ListedColormap((&quot;red&quot;, &quot;blue&quot;))
    xx1, xx2 = np.meshgrid(np.arange(-3, 3, 0.02), np.arange(-3, 3, 0.02))
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.1, cmap=cmap)

    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],
                    alpha=0.8, c=cmap(idx),
                    marker=&quot;+&quot;, label=cl)در راه‌حل ما، داده‌هایی داریم که شامل دو ویژگی (یعنی دو بعد) و یک بردار هدف با کلاس هر مشاهده است. مهم است که کلاس‌ها به گونه‌ای تخصیص داده شده‌اند که به صورت خطی قابل تفکیک نیستند. یعنی هیچ خط مستقیمی نمی‌توان کشید که دو کلاس را از هم جدا کند. ابتدا، بیایید یک طبقه‌بندی‌کننده ماشین بردار پشتیبان با کرنل خطی ایجاد کنیم:# Create support vector classifier with a linear kernel
svc_linear = SVC(kernel=&quot;linear&quot;, random_state=0, C=1)

# Train model
svc_linear.fit(features, target) خروجی:SVC(C=1, kernel=&#039;linear&#039;, random_state=0) سپس، از آنجا که فقط دو ویژگی داریم، در یک فضای دوبعدی کار می‌کنیم و می‌توانیم مشاهدات، کلاس‌های آن‌ها و ابرصفحه خطی مدل‌مان را نمایش دهیم:# Plot observations and hyperplane 
plot_decision_regions(features, target, classifier=svc_linear)
plt.axis(&quot;off&quot;), plt.show();همان‌طور که می‌بینیم، ابرصفحه خطی ما در جداسازی دو کلاس عملکرد بسیار ضعیفی داشت! حالا، بیایید کرنل خطی را با یک کرنل تابع پایه شعاعی جایگزین کنیم و از آن برای آموزش یک مدل جدید استفاده کنیم:# Create a support vector machine with a radial basis function kernel 
svc = SVC(kernel=&quot;rbf&quot;, random_state=0, gamma=1, C=1)

# Train the classifier
model = svc.fit(features, target)و سپس مشاهدات و ابرصفحه را نمایش دهیم:# Plot observations and hyperplane 
plot_decision_regions(features, target, classifier=svc)
plt.axis(&quot;off&quot;), plt.show();با استفاده از کرنل تابع پایه شعاعی، می‌توانیم یک مرز تصمیم‌گیری ایجاد کنیم که در مقایسه با کرنل خطی، کار بسیار بهتری در جداسازی دو کلاس انجام می‌دهد. این انگیزه اصلی استفاده از کرنل‌ها در ماشین‌های بردار پشتیبان است.در scikit-learn، می‌توانیم کرنلی که می‌خواهیم استفاده کنیم را با استفاده از پارامتر kernel انتخاب کنیم. پس از انتخاب کرنل، باید گزینه‌های مناسب کرنل را مشخص کنیم، مانند مقدار d (با استفاده از پارامتر degree) در کرنل‌های پلی‌نومیال، و مقدار γ (با استفاده از پارامتر gamma) در کرنل‌های تابع پایه شعاعی. همچنین باید پارامتر جریمه C را تنظیم کنیم. هنگام آموزش مدل، در اکثر موارد باید همه این‌ها را به عنوان ابرپارامترها در نظر بگیریم و از تکنیک‌های انتخاب مدل برای شناسایی ترکیبی از مقادیر آن‌ها که مدلی با بهترین عملکرد را تولید می‌کند، استفاده کنیم.17.3 ایجاد احتمالات پیش‌بینی‌شدهمسئلهشما نیاز دارید احتمالات پیش‌بینی‌شده برای کلاس‌های یک مشاهده را بدانید.راه‌حلدر scikit-learn، هنگام استفاده از SVC، گزینه probability=True را تنظیم کنید، مدل را آموزش دهید، سپس از predict_proba برای مشاهده احتمالات کالیبره‌شده استفاده کنید.# Load libraries
from sklearn.svm import SVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np

# Load data
iris = datasets.load_iris()
features = iris.data
target = iris.target

# Standardize features
scaler = StandardScaler()
features_standardized = scaler.fit_transform(features)

# Create support vector classifier object
svc = SVC(kernel=&quot;linear&quot;, probability=True, random_state=0)

# Train classifier
model = svc.fit(features_standardized, target)

# Create new observation
new_observation = [[.4, .4, .4, .4]]

# View predicted probabilities
model.predict_proba(new_observation)خروجی:array([[0.00541761, 0.97348825, 0.02109414]]) 
توضیحاتبسیاری از الگوریتم‌های یادگیری نظارت‌شده که بررسی کرده‌ایم، از تخمین‌های احتمالی برای پیش‌بینی کلاس‌ها استفاده می‌کنند. برای مثال، در الگوریتم k-نزدیک‌ترین همسایه، کلاس‌های k همسایه یک مشاهده به‌عنوان رأی‌هایی برای محاسبه احتمال تعلق آن مشاهده به یک کلاس خاص در نظر گرفته می‌شوند. سپس کلاسی با بالاترین احتمال پیش‌بینی می‌شود. اما در SVC، استفاده از یک ابرسطح برای ایجاد مناطق تصمیم‌گیری به‌طور طبیعی احتمالی برای تعلق یک مشاهده به یک کلاس خاص ارائه نمی‌دهد. با این حال، می‌توان با چند ملاحظه، احتمالات کالیبره‌شده را تولید کرد. در SVC با دو کلاس، از مقیاس‌بندی پلات (Platt scaling) استفاده می‌شود. در این روش، ابتدا SVC آموزش داده می‌شود و سپس یک رگرسیون لجستیک جداگانه با اعتبارسنجی متقاطع آموزش داده می‌شود تا خروجی‌های SVC را به احتمالات نگاشت کند:که در آن A و B بردارهای پارامتر هستند و f(x) فاصله نشان‌شده مشاهده iام از ابرسطح است. برای بیش از دو کلاس، نسخه گسترش‌یافته‌ای از مقیاس‌بندی پلات استفاده می‌شود.از نظر عملی، ایجاد احتمالات پیش‌بینی‌شده دو مشکل اصلی دارد. اول، به دلیل آموزش یک مدل دوم با اعتبارسنجی متقاطع، تولید احتمالات پیش‌بینی‌شده می‌تواند زمان آموزش مدل را به‌طور قابل‌توجهی افزایش دهد. دوم، چون احتمالات پیش‌بینی‌شده با استفاده از اعتبارسنجی متقاطع تولید می‌شوند، ممکن است همیشه با کلاس‌های پیش‌بینی‌شده مطابقت نداشته باشند. به‌عنوان مثال، ممکن است یک مشاهده به‌عنوان کلاس 1 پیش‌بینی شود اما احتمال پیش‌بینی‌شده برای کلاس 1 کمتر از 0.5 باشد.در scikit-learn، احتمالات پیش‌بینی‌شده باید هنگام آموزش مدل تولید شوند. این کار با تنظیم probability=True در SVC امکان‌پذیر است. پس از آموزش مدل، می‌توان با استفاده از predict_proba احتمالات تخمینی برای هر کلاس را استخراج کرد.17.4 شناسایی بردارهای پشتیبانمسئلهشما باید مشخص کنید کدام مشاهدات، بردارهای پشتیبانِ hyperplane تصمیم‌گیری هستند.راه‌حلمدل را آموزش دهید، سپس از support_vectors_ استفاده کنید:# Load libraries 
from sklearn.svm import SVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np

# Load data with only two classes
iris = datasets.load_iris()
features = iris.data[:100,:]
target = iris.target[:100]

# Standardize features
scaler = StandardScaler()
features_standardized = scaler.fit_transform(features)

# Create support vector classifier object
svc = SVC(kernel=&quot;linear&quot;, random_state=0)

# Train classifier
model = svc.fit(features_standardized, target)

# View support vectors
model.support_vectors_خروجی:array([[-0.5810659 , 0.42196824, -0.80497402, -0.50860702],
       [-1.52079513, -1.67737625, -1.08231219, -0.86427627], 
       [-0.89430898, -1.4674418 , 0.30437864, 0.38056609],
       [-0.5810659 , -1.25750735, 0.09637501, 0.55840072]]) بحثماشین‌های بردار پشتیبان (SVM) نام خود را از این واقعیت گرفته‌اند که hyperplane تصمیم‌گیری توسط تعداد نسبتاً کمی از مشاهدات، که به آن‌ها بردارهای پشتیبان گفته می‌شود، تعیین می‌شود. به‌طور شهودی، می‌توان تصور کرد که این hyperplane توسط این بردارهای پشتیبان &quot;حمل&quot; می‌شود. بنابراین، این بردارهای پشتیبان برای مدل ما بسیار مهم هستند. برای مثال، اگر یک مشاهده که بردار پشتیبان نیست را از داده‌ها حذف کنیم، مدل تغییری نمی‌کند؛ اما اگر یک بردار پشتیبان را حذف کنیم، hyperplane دیگر حاشیه حداکثری نخواهد داشت.پس از آموزش یک SVC، کتابخانه scikit-learn گزینه‌های متعددی برای شناسایی بردارهای پشتیبان ارائه می‌دهد. در راه‌حل ما، از support_vectors_ برای نمایش ویژگی‌های واقعی مشاهداتِ بردارهای پشتیبان (چهار بردار در مدل ما) استفاده کردیم. به‌عنوان جایگزین، می‌توانیم ایندکس‌های بردارهای پشتیبان را با استفاده از support_ مشاهده کنیم:model.support_ خروجی:array([23, 41, 57, 98], dtype=int32) همچنین، می‌توانیم از n_support_ برای یافتن تعداد بردارهای پشتیبان متعلق به هر کلاس استفاده کنیم:model.n_support خروجی:array([2, 2], dtype=int32) 17.5 مدیریت کلاس‌های نامتوازنمسئلهشما باید یک طبقه‌بندی‌کننده ماشین بردار پشتیبان (SVM) را در حضور کلاس‌های نامتوازن آموزش دهید.راه‌حلبا استفاده از class_weight جریمه‌ی اشتباه در طبقه‌بندی کلاس کوچک‌تر را افزایش دهید:# Load libraries 
from sklearn.svm import SVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np

# Load data with only two classes
iris = datasets.load_iris()
features = iris.data[:100,:]
target = iris.target[:100]

# Make class highly imbalanced by removing first 40 observations
features = features[40:,:]
target = target[40:]

# Create target vector indicating if class 0, otherwise 1
target = np.where((target == 0), 0, 1)

# Standardize features
scaler = StandardScaler()
features_standardized = scaler.fit_transform(features)

# Create support vector classifier
svc = SVC(kernel=&quot;linear&quot;, class_weight=&quot;balanced&quot;, C=1.0, random_state=0)

# Train classifier
model = svc.fit(features_standardized, target)بحثدر ماشین‌های بردار پشتیبان، C یک هایپرپارامتر است که جریمه‌ی اشتباه در طبقه‌بندی یک مشاهده را تعیین می‌کند. یکی از روش‌های مدیریت کلاس‌های نامتوازن در ماشین‌های بردار پشتیبان، وزن‌دهی به C بر اساس کلاس‌ها است، به‌طوری که:که در آن C جریمه‌ی اشتباه در طبقه‌بندی است، wj وزنی است که به‌صورت معکوس با فراوانی کلاس j متناسب است، و Ck مقدار C برای کلاس k است. ایده کلی این است که جریمه‌ی اشتباه در طبقه‌بندی کلاس‌های اقلیت را افزایش دهیم تا از &quot;غلبه&quot; کلاس اکثریت بر آن‌ها جلوگیری شود.در کتابخانه scikit-learn، هنگام استفاده از SVC، می‌توانیم مقادیر Ck را به‌صورت خودکار با تنظیم class_weight=&quot;balanced&quot; مشخص کنیم. آرگومان balanced به‌صورت خودکار کلاس‌ها را وزن‌دهی می‌کند به‌گونه‌ای که:که در آن wj وزن کلاس j، n تعداد کل مشاهدات، nj تعداد مشاهدات در کلاس j، و k تعداد کل کلاس‌ها است.</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Mon, 04 Aug 2025 15:35:43 +0330</pubDate>
            </item>
                    <item>
                <title>بررسی بستر اطلاعات تهدید - OpenCti</title>
                <link>https://virgool.io/@mojino/%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C-%D8%A8%D8%B3%D8%AA%D8%B1-%D8%A7%D8%B7%D9%84%D8%A7%D8%B9%D8%A7%D8%AA-%D8%AA%D9%87%D8%AF%DB%8C%D8%AF-opencti-mdowcsqmhaoy</link>
                <description>چی هست؟مدتی است که به فکر پیاده‌سازی یک پلتفرم هوش تهدید سایبری برای استفاده شخصی‌ام هستم. ایده اولیه این بود که از MISP استفاده کنم، چون به خوبی شناخته شده است و در این حوزه بسیار قوی عمل می‌کند. اما اخیراً چیزهای خوبی درباره OpenCTI شنیده‌ام. این پلتفرم به مراتب کمتر از MISP بالغ و پرکاربرد است، بنابراین احتمالاً در این مرحله به اندازه MISP صیقل‌یافته نیست. با این حال، OpenCTI ظاهر بصری جذاب و کاربرپسندی دارد و به نظر پلتفرم جالبی می‌آید. گزینه دیگر YETI است، اما هنوز حتی نگاهی به آن نینداخته‌ام.چرا؟سؤالم بسیار بهتر شد. من علاقه‌مند به دنبال کردن فعالیت‌های تهدیدات سایبری به‌روز هستم و تا حالا عمدتاً این کار را از طریق دنبال کردن فیدهای RSS انجام داده‌ام. مدتی است که به فکر استفاده از یک پلتفرم هوش تهدید سایبری (CTI) هستم تا ببینم آیا می‌توانم از آن برای همین منظور با دسترسی به اطلاعات بیشتر استفاده کنم. علاوه بر این، من به یادگیری علاقه دارم. خیلی در زمینه هوش تهدید (TI) عمیق نشده‌ام، اما اخیراً علاقه‌ام به این موضوع بیشتر شده است. دوست دارم بهتر بفهمم که این پلتفرم‌ها چگونه کار می‌کنند و چه کارهایی می‌توانم با آن‌ها انجام دهم.در نهایت، فکر می‌کنم که پلتفرم هوش تهدید فقط یک پلتفرم برای دریافت اطلاعات تهدید است. احتمالاً به منابع داده‌ای جذاب دسترسی نخواهم داشت و به داده‌های متن‌باز وابسته خواهم بود، که ممکن است این فیدها آن‌قدر دیر به دستم برسند که عملاً بی‌فایده باشند. یا شاید فقط شامل شاخص‌های تهدید (IoCs) باشند و اطلاعات واقعی ارائه ندهند، که این برای عملیات امنیتی عالی است، اما برای یک فرد، کاربرد محدودی دارد.شاید در واقع سریع‌تر باشد که به خواندن اخبار از طریق فیدهای RSS ادامه دهم. یک گزینه این است که فیدهای RSS را با پلتفرم CTI ادغام کنم، که ظاهراً با پلتفرمی مثل MISP ممکن است، اما اگر همه‌چیز به فیدهای RSS خلاصه شود، چرا زحمت بکشم؟ با راه‌حل فعلی‌ام هم می‌توانم با آن‌ها به‌روز بمانم. در نهایت، ممکن است این کار بی‌نتیجه باشد، اما باید امتحان کنم.نحوه نصب کردنمن قصد دارم OpenCTI را روی سرور قدیمی و خوب Unraid خودم به‌صورت Docker نصب کنم. Docker به‌خاطر سادگی و علاقه روزافزون من به این محصول انتخاب شده است. دستورالعمل‌های نصب در مستندات OpenCTI موجود است که نحوه انجام این کار را توضیح می‌دهد. با رویکرد Docker مشکل خاصی در نصب وجود نداشت. و در عرض چند دقیقه، کار تمام شد. یک پلتفرم CTI تمیز و آماده.در آنجا ما آن را داریم. Opencti تمیز.حالا کار اصلی شروع می‌شود. حالا چه چیزی را باید با این محصول ادغام کنم؟ اصلاً چه چیزهایی می‌توانم ادغام کنم و آیا این کار منطقی است؟ادغام یا یکپارچه سازیبرای شروع، در رابط کاربری گرافیکی (GUI) گشتی زدم و متوجه شدم که امکان ایجاد ادغام‌ها مستقیماً در آنجا وجود ندارد. در آنجا لیستی از منابع مختلف CTI وجود دارد، فکر می‌کنم، و می‌توانیم آن‌ها را به نسخه‌های عمومی (Community Editions) فیلتر کنیم. این منابع در دسته‌های مختلفی طبقه‌بندی شده‌اند:جریان‌های زنده OpenCTIمجموعه‌های TAXIIکانکتورها - وارد کردن دادهکانکتورها - غنی‌سازیمصرف‌کنندگان جریانوارد کردن فایل‌هاصادر کردن فایل‌هاادغام‌های بومی شخص ثالثبعضی از این‌ها واضح‌تر از بقیه بودند. جریان‌های زنده OpenCTI و مجموعه‌های TAXII در مجموع فقط سه مورد داشتند، بنابراین به نظر کمی ناامیدکننده می‌آمد. اما در بخش وارد کردن داده و غنی‌سازی، تعداد خوبی کانکتور وجود دارد، حتی در نسخه عمومی.لیست کانکتورهای عمومیبعضی از این‌ها از بقیه جذاب‌تر هستند. ظاهراً اکثر این‌ها تصاویر Docker آماده‌ای دارند که باید اجرا کنم و در این مرحله تصمیم گرفتم یک ماشین مجازی (VM) اختصاصی برای OpenCTI ایجاد کنم. مدیریت کانتینرها در Unraid واقعاً آن‌قدرها عالی نیست، بنابراین این تصمیم باعث شد که دسته‌بندی تمام کانتینرهای مرتبط در یک VM برایم راحت‌تر شود. می‌دانم، این راه‌حل خیلی بهینه نیست.من به‌نوعی این رویکرد را دوست دارم. عاشق کار کردن با Docker هستم و این روش ممکن است ساخت ادغام‌های خودم را هم آسان‌تر کند، چون نمونه‌های زیادی وجود دارد. به هر حال، بسیاری از فیدها همچنان نیاز به دسترسی پولی دارند، بنابراین حتی اگر کانکتورها نسخه‌های عمومی (Community Editions) باشند، خود فیدها رایگان نیستند. برای مثال، فید Valhalla فقط با اشتراک پولی قابل دسترسی است - بنابراین به نظر می‌رسد که فیدهای پشتیبانی‌شده توسط عموم عمدتاً هم توسط عموم ساخته شده‌اند، اما این به این معنی نیست که محتوا رایگان است. بعداً باید بررسی کنم که آیا کانکتورهای «پشتیبانی‌شده توسط شرکا و Filigran» واقعاً رایگان هستند یا نه. فیدهای IoC واقعاً اولویت اصلی من نیستند، چون عملاً کاری با آن‌ها ندارم، مگر اینکه متادیتا هم شاملشان باشد. اکثر فیدها به نظر می‌رسد فقط درباره IoCها باشند، بنابراین مطمئن نیستم که این برای اهداف من کارساز باشد یا نه. با این حال، تصمیم گرفتم کمی تصادفی شروع به ادغام کنم. هرچه بیشتر، بهتر، درست است؟ (نه، واقعاً نه).کانکتور AlienVaultپیکربندی کانکتور بسیار آسان است. تمام چیزی که نیاز دارید اساساً کلید API OpenCTI، آدرس OpenCTI (فراموش نکنید IP و پورت را اضافه کنید) و سپس کلید API خودتان از AlienVault است. تمام تغییرات در فایل docker-compose.yml انجام می‌شود و سپس می‌توانید کانتینر را با docker-compose اجرا کنید. ایمج از Docker Hub گرفته می‌شود، بنابراین حتی اگر کد منبع و تصویر Docker در GitHub موجود باشند، اینجا واقعاً استفاده نمی‌شوند. این خبر خوبی است، چون احتمالاً می‌توانم تمام کانکتورها را در یک فایل docker-compose واحد جمع کنم، که دوست دارم. می‌توان آن‌ها را به فایل docker-compose‌ای که خود OpenCTI را اجرا می‌کند اضافه کرد، اما من ترجیح می‌دهم آن را از کانکتورها جدا نگه دارم.کانکتور AlienVault پالس‌ها را وارد می‌کند. این کار ممکن است کمی طول بکشد.حالا که کانکتور AlienVault راه‌اندازی شده، با اشتیاق منتظرم تا فرآیند وارد کردن داده‌ها تمام شود و ببینم چه نوع داده‌هایی در پلتفرم OpenCTI نمایش داده می‌شود. به‌خصوص کنجکاو هستم که ببینم داده‌ها چگونه در پلتفرم ساختاربندی شده‌اند. با این حال، به نظر می‌رسد کانکتور مدام کرش می‌کند. خیلی حوصله دیباگ کردن نداشتم، بنابراین آن را متوقف کردم و تاریخ اولیه را به ابتدای سال ۲۰۲۳ تغییر دادم. شاید مشکل به تایم‌اوت‌های API مربوط باشد.این کار مشکل را حل نکرد. خطاها را بررسی کردم و خطای خیلی کلی‌ای مثل «Errorno 3 - دوباره امتحان کنید» گرفتم. در GitHub هم شانس نیاوردم. با این حال، گفته شده بود که تمام کانکتورها نیاز به دسترسی به RabbitMQ دارند که به‌عنوان بخشی از پلتفرم OpenCTI میزبانی می‌شود. بنابراین پورت‌های کانتینر RabbitMQ را باز کردم، اما این هم هیچ تأثیری نداشت. به‌طور عجیبی، کانکتور Malware Bazaar بدون مشکل کار کرد، بنابراین این موضوع کمی مرموز بود.برای دیباگ کردن، پیکربندی را به‌عنوان یک کانتینر اضافی به فایل docker-compose.yml اصلی OpenCTI اضافه کردم. این کار ظاهراً مشکل را حل کرد. بعد از این تغییر شروع به کار کرد. شاید دسترسی به RabbitMQ واقعاً به‌خوبی کار نمی‌کرد. دلیل احتمالی این است که مهارت‌های محدود من در Docker باعث شده بود RabbitMQ برای کانتینرهای دیگر در دسترس نباشد. همچنین ممکن است به‌خاطر تنبلی‌ام در ری‌استارت نکردن کانتینرهای ثانویه بعد از تغییرات اولیه باشد. به هر حال، تصمیم گرفتم با این روش پیش بروم چون حالا کار می‌کرد.داشبورد پس از اضافه کردن برخی از داده هاحالا داشبورد خیلی جذاب‌تر شده است. وارد کردن داده‌ها کمی طول می‌کشد، احتمالاً چون داده‌ها در حال تجزیه و سپس وارد شدن به Elasticsearch هستند. گزارش‌های تحلیلی، IoCها، تهدیدات، آسیب‌پذیری‌ها و غیره از فیدهای AlienVault شروع به ورود کرده‌اند.مثالی از گزارش تجزیه و تحلیل وارد شده از AlienVaultفکر می‌کنم این با تمام روابطی که نمایش می‌دهد خیلی جالب است. در واقع فکر می‌کنم واقعاً فوق‌العاده است و تا حالا رابط کاربری و امکاناتش را دوست دارم. نمایش داده‌ها و همبستگی بین آن‌ها خیلی خوب است.ادغام‌های بیشترمتوجه شدم که برای کاربردی شدن پلتفرم برای من، احتمالاً به تعداد زیادی کانکتور سفارشی اضافی نیاز است. قبل از اینکه به سراغ این مسیر بروم، به بررسی کانکتورهای آماده ادامه دادم. در حین فعال‌سازی موارد مختلف، به چیزی به نام کانکتور Obstracts برخوردم. این خیلی جالب به نظر می‌رسید؛ می‌توانستید فیدهای RSS را با سرویس Obstracts دریافت کنید و سپس از طریق یک API آن‌ها را به OpenCTI وارد کنید. متأسفانه دسترسی با API هزینه نسبتاً بالایی دارد، بنابراین این گزینه واقعاً برایم مناسب نبود. با این حال، علاوه بر AlienVault، موارد زیر را فعال کردم:دیتاست‌های OpenCTI: این‌ها کم‌وبیش دیتاست‌هایی هستند که به پلتفرم وارد می‌شوند. شامل اطلاعات پایه مثل بخش‌های صنعتی است.OpenCTI Mitre: این هم مشابه است، اطلاعات پایه را از MITRE ATT&amp;CK وارد می‌کند.آسیب‌پذیری‌های شناخته‌شده CISA: این خیلی جالب است و همان‌طور که از اسمش پیداست، همه‌چیز را توضیح می‌دهد.NVD Common Vulnerabilities and Exposures: عاشق این آسیب‌پذیری‌ها هستم.Malpedia: IoCها و غیره. متأسفانه حسابی ندارم، بنابراین فقط موارد TLP:WHITE.Maltiverse: IoCها و غیره، در سطح رایگان، مطمئن نیستم که اصلاً مفید باشد.Abuse.ch Threat Fox: IoCها.Abuse.ch UrlHaus: IoCهای URL.شاید بعداً:TweetFeed: این برایم جالب و جدید است. IoCها را از توییت‌ها جمع‌آوری می‌کند.TAXII2: جمع‌آوری‌کننده عمومی TAXII2.Urlscanفرضم این است که برای علاقه کلی‌ام، AlienVault، NVD CVE و آسیب‌پذیری‌های شناخته‌شده CISA بیشترین ارزش را دارند. فیدهای مبتنی بر IoC کمی برایم بی‌اهمیت هستند، مگر اینکه بتوانید پلتفرم CTI را به راه‌حل‌های فنی متصل کنید. با این حال، پتانسیلی در ارائه آمار بدافزارها از این فیدها وجود دارد که برایم جالب است. می‌دانید، قبلاً یک راه‌حل مبتنی بر ELK برای این منظور ساخته‌ام و هنوز هم کار می‌کند. شاید اگر OpenCTI خوب عمل کند، بتوانم آن را کنار بگذارم.نبود گزارش‌های هوش تهدید کمی آزاردهنده است. AlienVault این گزارش‌ها را ارائه می‌دهد، اما تقریباً تنها منبعی است که از منابع ادغام‌شده چنین چیزی ارائه می‌کند. بقیه یا پشتیبانی‌کننده هستند یا IoCهای فنی‌تر ارائه می‌دهند. Pulsedive هوش تهدید رایگان بسیار جالبی ارائه می‌دهد. قبلاً برای برخی از پروژه‌هایم از آن استفاده کرده‌ام. متأسفانه کانکتور آماده‌ای برای Pulsedive وجود ندارد. چند گزینه برای انجام این کار وجود دارد، اما متأسفانه اکثر یا همه آن‌ها نیاز به مجوز PRO پولی دارند. قیمت مجوز PRO برای استفاده غیرتجاری کاملاً ارزان است، ۲۹ یورو در ماه. با این حال، نمی‌دانم چه داده‌هایی در آن گنجانده شده است. به هر حال، کانکتورها باید ساخته شوند چون گزینه آماده‌ای وجود ندارد.در این مرحله به نظر می‌رسد که ادغام‌های بیشتر نیاز به کارهای زیادی دارد. خیلی علاقه‌مندم که فیدهای RSS را به گزارش‌هایی در OpenCTI تبدیل کنم و به‌صورت خودکار گزارش‌های جذابی از آن‌ها بسازم. اما چون این کار زمان زیادی می‌طلبد، این گزینه را بعداً بررسی خواهم کرد.کانکتورهای فعلیو آخرین نکته قبل از ادامه دادن - این پلتفرم حسابی حافظه می‌بلعد. من به VM هشت گیگابایت حافظه اختصاص دادم و همه‌اش را مصرف کرد و احتمالاً به همین دلیل در رابط کاربری کمی لگ دارد. حافظه را به ۱۲ گیگابایت افزایش می‌دهم تا ببینم کافی است یا نه.ادغام‌های غنی‌سازیحالا به غنی‌سازی می‌رسیم. این‌ها برای غنی‌سازی داده‌ها استفاده می‌شوند. گزینه‌های زیادی به‌صورت پیش‌فرض ارائه شده‌اند. این برای یک پلتفرم CTI تولیدی خیلی خوب است، اما برای اهداف من، غنی‌سازی معمولاً کمتر اهمیت دارد. بیشتر از روی کنجکاوی و برای آزمایش، تصمیم گرفتم چند ادغام را امتحان کنم.با این‌ها شروع کردم:Hatching TriageCrowdsecShodan InternetDBبه جای Shodan معمولی، Shodan InternetDB را انتخاب کردم تا به‌طور تصادفی از سهمیه محدود Shodanم که ممکن است برای اهداف دیگر نیاز داشته باشم، استفاده نکنم.غنی‌سازی Shodan InternetDB در حال انجام استبه نظرم این خیلی جالب است. اما ادغام CrowdSec کار نمی‌کند، خطایی درباره استفاده از API نسخه ۱ داده شد. سندباکس Hatching Triage کار می‌کند و آرتیفکت‌ها را به‌خوبی غنی‌سازی می‌کند وقتی به سندباکس ارسال می‌شوند.وقتی از غنی‌سازی Hatching Triage استفاده می‌شود، نتایج تحلیل به‌صورت کامنت به آرتیفکت‌ها اضافه می‌شوند. روابط هم به تکنیک‌های مرتبط دیگر اضافه می‌شوند. این را خیلی دوست دارم و فکر می‌کنم واقعاً عالی است. به نظر می‌رسد به‌خوبی هم کار می‌کند.مثال غنی‌سازی یک آرتیفکت توسط Hatching Triageدر ادامه بررسی ادغام‌های غنی‌سازی بیشتر، تصمیم گرفتم VirusTotal و Sophos را هم امتحان کنم. Sophos Intelix حتی برای حساب رایگان سهمیه خوبی ارائه می‌دهد. تنها نکته آزاردهنده این است که نیاز به حساب AWS دارد.با اینکه SophosLabs Intelix در سطح رایگان درخواست‌های زیادی ارائه می‌دهد، من غنی‌سازی خودکار را فعال نکردم چون نمی‌خواهم با سورپرایزهای ناخواسته مواجه شوم. همچنین یک بودجه «صفر هزینه» به AWS اضافه کردم تا اگر هزینه‌ای در AWS ایجاد شود، امیدوارم به من هشدار دهد. کاش می‌شد این را طوری محدود کرد که وقتی به آستانه خاصی رسید، تمام چیزهایی که هزینه دارند متوقف شوند.به هر حال، این به من اجازه داد پشتیبانی Sophos را اضافه کنم و همچنین دو کانکتور VirusTotal را اضافه کردم، حتی اگر API در سطح رایگان محدود باشد. متأسفانه به نظر می‌رسد ادغام VirusTotal کاملاً خراب است. یک درخواست رفع اشکال (PR) برای یک اصلاح ساده وجود دارد، اما فایل docker-compose روی نسخه خاصی از تصویر تنظیم شده بود. آن را به آخرین نسخه تغییر دادم. مشکل حل نشد چون نسخه ۵.۸.۷ قبلاً آخرین بود، بنابراین آن را به حالت rolling تغییر دادم. حالا کار می‌کند!کانکتور Sophos هم کار نمی‌کند، شاید در حالت بتا باشد یا چیزی شبیه به آن. با این یکی هم شانس نیاوردم، راه‌حل ساده‌ای وجود نداشت و فعلاً حوصله دیباگ کردن نداشتم.استفاده از پلتفرمکاربردهای زیادی برای چنین پلتفرمی وجود دارد، از ادغام با SIEMها و سایر ابزارهای امنیتی برای دریافت خودکار IoCها، مسدودسازی، اجازه دادن، تحلیل تهدیدات، تحلیل IoCها و موارد دیگر. من در مورد خود پلتفرم‌ها حرفه‌ای نیستم و این را برای به‌دست آوردن اطلاعات بیشتر درباره تهدیداتی که سازمان‌ها ممکن است با آن مواجه شوند، ساختم. برای این مورد استفاده، مشکل کمبود داده‌ها را دارم وقتی به منابع رایگان وابسته هستم. داده‌های فنی IoC از منابع رایگان به وفور یافت می‌شود، اما گزارش‌های معنی‌دار کمتر هستند. البته باید اضافه کنم که IoCها هم ممکن است بهترین نباشند. مطمئنم که بسیاری از فروشندگان امنیتی که IoCهای خودشان را جمع‌آوری می‌کنند بهتر هستند و این پلتفرم‌ها برای مفید بودن نیاز به دریافت داده توسط SOC دارند.واقعاً دوست دارم داده‌هایی از پست‌های وبلاگ، مقالات خبری و منابع مشابه که با بازیگران تهدید، بدافزارها، تکنیک‌ها و همه آن چیزهای جذاب مرتبط هستند، اضافه کنم. داده‌های AlienVault برای این منظور عالی هستند، اما فقط یک منبع هستند. متأسفانه سایر منابع رایگان واقعاً در این مورد کمکی نمی‌کنند.حالا به استفاده واقعی می‌رسیم. اولین چیزی که می‌خواهم ببینم، گزارش‌های اخیر هستند. این‌ها در بخش Analysis -&gt; Reports ابزار لیست شده‌اند.نمایش گزارش‌هابه یک گزارش تصادفی نگاه کردم تا ببینم چه شکلی است. قبلاً یک تصویر از این نما بود، اما باز هم یکی دیگر!نمای کلی یک گزارشاین یک نمای کلی از گزارش است تا بتوانید تصمیم بگیرید که آیا علاقه‌مند به دانستن بیشتر هستید یا خیر. معمولاً لینک‌های اضافی به منابع خارجی درباره مقالات وجود دارد که می‌توانید اطلاعات بیشتری از آن‌ها پیدا کنید. همچنین اطلاعات اضافی در تب‌های دیگر وجود دارد، حالا به تب Knowledge نگاه می‌کنیم:تب Knowledge از یک گزارشاین یک گراف جذاب است که می‌توانید با آن تعامل کنید. روابط بین مشاهدات و موجودیت‌ها را نشان می‌دهد. قبلاً گراف‌های مشابهی دیده‌ام، اما تجربه‌ام نشان داده که کاربرد این‌ها محدود است. با این حال، این یکی از بهترین کاربردهای این نوع بصری‌سازی‌هاست که دیده‌ام، به‌راحتی می‌توانید روابط بین یک IoC و تکنیک‌ها را ببینید.با نگاه به تب‌های دیگر، موجودیت‌ها و مشاهدات را دارید. همچنین تب Content وجود دارد که تا حالا همیشه خالی بوده و تب Data که آن هم خالی بوده است.موجودیت‌ها و مشاهدات نشان‌داده‌شده در تصویراین‌ها جالب هستند. اطلاعات بیشتری درباره تکنیک‌هایی که در این حمله خاص مشاهده شده‌اند و شاخص‌های مرتبط با آن‌ها به دست می‌آورید. وقتی به دنبال اطلاعات سطح بالا هستید، این ممکن است خیلی جذاب نباشد، اما برای شکار در راه‌حل فنی انتخابی‌تان می‌تواند به‌راحتی استفاده شود. البته وقتی به شکار تهدید مبتنی بر TTP می‌روید، باید مقالات را کمی بیشتر تحلیل کنید.یک افزودنی خوب، غنی‌سازی است. اگر بخواهید اطلاعات بیشتری از یک فایل داشته باشید، می‌توانید آن را با ادغام‌های دیگر غنی‌سازی کنید. به‌عنوان مثال، یک هش را در نظر بگیرید.نمونه غنی‌شده توسط VirusTotal در سمت راست. خروجی کامل JSON از API VirusTotal هم به‌صورت کامنت در دسترس است، اگر لازم باشد. همچنین لینک به VirusTotal به‌عنوان مرجع خارجی اضافه شده است.این داده‌ها خوب هستند. در صورت نیاز در محیط تولیدی می‌توان آن را به‌صورت خودکار غنی‌سازی کرد که برچسب‌های زیادی اضافه می‌کند. این‌ها برای جستجوی اطلاعات عالی هستند. متأسفانه، من مجوزی ندارم که اجازه دانلود نمونه از API VirusTotal را بدهد. این می‌توانست به آرتیفکت‌هایی تبدیل شود که در یک سندباکس تحلیل شوند. این کار می‌توانست TTPهای جذاب بدافزار استفاده‌شده را نشان دهد و سپس به‌صورت کلی‌تر برای شکار تهدید استفاده شود. در محیط سازمانی احتمالاً این امکان‌پذیر است.در این مثال خاص، گزارش اصلی اطلاعاتی ارائه می‌دهد که می‌توان آن‌ها را به پرس‌وجوهای شکار تبدیل کرد:بدافزار از پسوندهای دوگانه استفاده می‌کند - .xls.exe و .pdf.exe.گفته شده که بدافزار دستورات کشف را اجرا می‌کند و یک ارتباط C2 برقرار می‌کند.هدر درخواست وب سفارشی: Cookie: 3rd_eye=[client_hash value]بررسی یک تهدید خاصمورد استفاده دیگری که برایم جالب است، بررسی یک تهدید خاص است. به‌عنوان مثال، Qbot را در نظر بگیرید. جستجو برای Qakbot ۱۳ نتیجه می‌دهد که اولین آن صفحه بدافزار QakBot است. این صفحه، حداقل در تئوری، باید شامل تمام اطلاعات دیگری باشد که از جستجوی قبلی به دست آمده است. صفحه شامل اطلاعاتی درباره بدافزار QakBot است، اگرچه صفحه اصلی عمدتاً فقط اطلاعات کلی و آمار است.صفحه کلی QakBotصفحه Knowledge اطلاعات زیادی درباره QakBot دارد. شامل مرور کلی داده‌ها، اطلاعات درباره قربانیان در صورت وجود، آسیب‌پذیری‌های مشاهده‌شده مرتبط با QakBot، گراف MITRE ATT&amp;CK از تکنیک‌های استفاده‌شده توسط آن، مشاهدات و اطلاعات زیاد دیگر است. همه این‌ها برای همه تهدیدات موجود نیستند و به‌خصوص چون منابع داده در پیاده‌سازی من محدود هستند، فقط مقدار محدودی داده وجود دارد.با این حال، تعداد زیادی مشاهده در دسترس است. در مجموع ۳۸۳۰ مشاهده مرتبط با QakBot یافت شده است. نمی‌دانم این‌ها چگونه نگاشت شده‌اند، اما حدسم این است که بر اساس برچسب استفاده‌شده است. شاید روش پیچیده‌تری باشد، اما کمی تنبل هستم که این اطلاعات را پیدا کنم، ببخشید.ترکیبی از برخی نماها در تب Knowledgeتب Analysis شامل گزارش‌هایی درباره QakBot است. این‌ها شامل انواع مقاله‌ها/گزارش‌هایی هستند که به‌نحوی درباره QakBot صحبت کرده‌اند. این می‌تواند معدن طلایی از اطلاعات برای ایجاد قابلیت‌های تشخیص یا پرس‌وجوهای شکار تهدید باشد. البته هنوز باید مقالات را تحلیل کنید، اما اگر منابع داده خوبی داشته باشید، شاید حداقل یک مکان واحد برای بررسی داشته باشید.تب Indicators شامل شاخص‌ها است. درک من این است که این‌ها بیشتر IoCها هستند، چون مشاهدات نوعی «IoCهای تأییدنشده» هستند. بنابراین شاخص‌ها کمتر مستعد خطای مثبت کاذب (False Positive) هستند. شاید اشتباه کنم. این برای این مثال کافی است.نتیجه‌گیریپلتفرم OpenCTI به نظر یک پلتفرم CTI بسیار جذاب می‌آید. رابط کاربری عالی و زیبایی دارد که وقتی حافظه کافی به آن بدهید، خیلی خوب کار می‌کند. روابط بین اشیاء مختلف عالی است و دریافت حداقل برخی از داده‌ها کاملاً آسان شده است. ایده کانکتورها را دوست دارم، فقط کاش تعداد بیشتری از آن‌ها در دسترس بود.برای استفاده من، این پلتفرم عالی می‌شد اگر می‌توانستم گزارش‌های بیشتری وارد کنم. این بزرگ‌ترین مشکلی است که در حال حاضر برای اهداف شخصی‌ام با آن دارم. دوست دارم اطلاعات بیشتری به این محصول وارد شود.وقتی صحبت از استفاده واقعی از ابزار می‌شود، فکر می‌کنم می‌تواند افزودنی خیلی خوبی برای یک سازمان باشد. شاید به دنبال پلتفرمی برای ذخیره هوش تهدید سایبری هستید و نمی‌خواهید هزینه گزافی برای یک راه‌حل تجاری بپردازید. شاید بتوانید پول را صرف وارد کردن برخی فیدهای تجاری به پلتفرم کنید، به جای پرداخت برای خود پلتفرم. برای این منظور فکر می‌کنم این خیلی خیلی خوب است - استفاده آسان، درک آسان و جستجوی اطلاعات از آن آسان است. می‌توانید به‌راحتی داده‌های خودتان را از طریق رابط کاربری اضافه کنید. اگر یک حادثه داشته باشید، می‌توانید اطلاعات مربوط به آن حادثه خاص را در ابزار ذخیره کنید. می‌توانید اطلاعات زیادی اضافه کنید که بعداً قابل جستجو هستند.فکر می‌کنم این می‌تواند راه‌حل خوبی حداقل برای یک سازمان کوچک باشد. اگرچه اگر به دنبال یک پلتفرم CTI متن‌باز باشید، فکر می‌کنم MISP هنوز اولین گزینه است، مگر اینکه به‌نحوی ثابت شود که بدتر است. با این حال، MISP خیلی پیچیده‌تر است، اما گزینه‌های بیشتری به‌صورت پیش‌فرض ارائه می‌دهد. برای آدم تنبلی مثل من، فکر می‌کنم OpenCTI می‌تواند گزینه بهتری باشد (مگر اینکه واقعاً نتوانم فیدهای RSS را وارد کنم).در مورد انتقادها چه؟ خب، مستنداتش خیلی ضعیف است. مستندات می‌توانند در بسیاری از سطوح، در واقع تقریباً در همه سطوح، بهبود یابند. راهنمای استقرار نسبتاً خوب کار می‌کند، اما حتی آنجا هم چیزهای کوچکی هست که می‌توان بهبود داد. ادغام‌ها و عملکرد کانکتورهای مختلف اصلاً مستند نشده‌اند. اگر مستنداتی وجود داشته باشد، پراکنده است. باید برچسب‌گذاری واضحی از کارهایی که می‌توانید با هر کدام انجام دهید وجود داشته باشد. برخی مستندات کاملاً غایب هستند و فقط گفته شده که در آینده اضافه خواهند شد.بعد، تعداد کانکتورهای موجود محدود است. بسیاری از چیزهای مفید در کانکتورها غایب هستند، اما البته می‌توانید خودتان آن‌ها را توسعه دهید. با این حال، به نظر نمی‌رسد این کار خیلی ساده باشد. فکر می‌کنم وارد کردن فیدهای RSS باید کاملاً آسان باشد و برای این نوع ابزار ارزش زیادی اضافه می‌کند، به‌خصوص برای تیم‌های کوچک‌تر که ممکن است بودجه‌ای برای فیدهای تجاری جذاب نداشته باشند.احتمالاً بعداً درباره این پلتفرم بیشتر می‌نویسم، چون امیدوارم چیزهای بیشتری به آن اضافه کنم و تجربه بیشتری در استفاده از آن به دست بیاورم. از اینکه خواندید، ممنون!</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Mon, 28 Jul 2025 21:51:32 +0330</pubDate>
            </item>
                    <item>
                <title>شکار تهدید چیست؟ یک استراتژی امنیت سایبری</title>
                <link>https://virgool.io/@mojino/%D8%B4%DA%A9%D8%A7%D8%B1-%D8%AA%D9%87%D8%AF%DB%8C%D8%AF-%DA%86%DB%8C%D8%B3%D8%AA-%DB%8C%DA%A9-%D8%A7%D8%B3%D8%AA%D8%B1%D8%A7%D8%AA%DA%98%DB%8C-%D8%A7%D9%85%D9%86%DB%8C%D8%AA-%D8%B3%D8%A7%DB%8C%D8%A8%D8%B1%DB%8C-rw9qwp4ahrwu</link>
                <description>شکار تهدید به یکی از جنبه های مهم امنیت سایبری تبدیل شده است، زیرا سازمان ها در تلاش برای شناسایی و کاهش حوادث امنیتی هستند که سیستم های خودکار ممکن است از دست داده باشند.بله، تعریف شکار تهدید می تواند متفاوت باشد، و به طور کلی شامل ترکیبی از فرآیندهای دستی و ماشینی است که توسط حس کنجکاوی انسان و تشخیص الگو هدایت می شوند. هدف نهایی شکار تهدید نه تنها یافتن حوادث امنیتی بیشتر بلکه بهبود قابلیت‌های تشخیص خودکار در طول زمان است.در این مقاله، ما به پیچیدگی‌های شکار تهدید، از جمله هدف، مزایا، معایب و چارچوب‌های مختلف موجود برای کمک به چالش‌های شما می‌پردازیم.شکار تهدید چیست؟احتمالاً اولین سؤالی که مردم در مورد شکار تهدید می‌پرسند این است که &quot;این دقیقا چیست؟&quot; گاهی اوقات به نظر می رسد که اگر از 10 نفر مختلف بخواهید شکار تهدید را تعریف کنند، 15 پاسخ متفاوت دریافت خواهید کرد! برای اهداف ما، محبوب‌ترین تعریف احتمالاً بهترین است: شکار تهدید نامی برای هر فرآیند دستی یا ماشینی برای یافتن حوادث امنیتی است که سیستم‌های تشخیص خودکار نتوانسته‌اند تشخیص بدهند.نکته کلیدی در اینجا این است که اگرچه ما اغلب از رایانه‌ها، اتوماسیون و تکنیک‌های یادگیری ماشینی برای کمک به شناسایی و فیلتر کردن رویدادهای مورد علاقه استفاده می‌کنیم، شکار همیشه توسط یک انسان هدایت می‌شود. کنجکاوی، تخیل و توانایی ما برای استنباط الگوی فعالیت‌های مخرب حتی زمانی که قبلاً هرگز با آن‌ها برخورد نکرده‌ایم، فراتر از توانایی های فناوری امروزی است.این تعریف زمینه‌های زیادی را در بر می‌گیرد ( شامل اصول اولیه ای مانند جستجوی شاخص های بد شناخته شده، از طریق ایجاد تکنیک های نوآورانه و پیشرفته تجزیه و تحلیل داده ها). مدل بلوغ شکار مراحل مختلفی را که قابلیت شکار سازمان ممکن است مشغول کند را نشان می دهد و به عنوان نقشه راه برای بهبود شکار تهدید در طول زمان عمل می کند.هدف از شکار تهدید…؟با توجه به تعریف ما، تعریف هدف واقعی شکار تهدید آسان به نظر می رسد، درست است؟ ممکن است فکر کنید: &quot;هدف از شکار تهدید، یافتن حوادث امنیتی بیشتر است!&quot;اگرچه این دقیقاً همان روشی است که برخی سازمان ها به آن می پردازند، من اینجا هستم تا به شما بگویم: این بهترین راه برای فکر کردن در مورد شکار تهدید نیست.از آنجایی که شکار تهدید به مشارکت انسان نیاز دارد، هزینه نسبتاً بالایی دارد. با توجه به حجم و سرعت داده‌های امنیتی که به اکثر سازمان‌ها وارد می‌شود، بررسی انسانی نه تنها گران است، بلکه کاملاً دور از ذهن است. اگر می‌خواهیم ادامه دهیم، به تشخیص خودکار خوب نیز نیاز داریم و اینجاست که شکار تهدید مطرح می‌شود.به شکار به عنوان راهی برای یافتن حوادث امنیتی بیشتر با استفاده از انسان های گران قیمت فکر نکنید. در عوض، به شکار تهدید به عنوان راهی برای بهبود تشخیص خودکار خود در طول زمان فکر کنید. هنگامی که یک شکارچی روش جدیدی برای تشخیص رفتار مخرب پیدا می کند، هدف این است که بفهمد چگونه این تشخیص را خودکار کند. به این ترتیب دفعه بعد فعالیت مخرب هشدار داده می شود و به سرعت به آن پاسخ داده می شود.ایجاد حوادث امنیتی جدید در طول فرآیند شکار در واقع یک مزیت ثانویه است، بیشتر به عنوان محصول جانبی شکار، نه هدف مورد نظر آن.باید شکار کنم؟ دلایل شکار تهدیدالبته، مطمئناً مجبور نیستید به دنبال تهدید باشید. فقط شما می توانید با اطمینان تصمیم بگیرید. اگر آن را نادیده بگیرید، تشخیص‌های امنیتی خودکار شما بهبود نمی‌یابند - در یک لحظه گیر می‌کنند. در همین حال، عوامل تهدید مدام در حال بهبود روش های خود هستند.برای اکثر سازمان ها، شکار تهدید به شدت توصیه می شود. این به چند دلیل است. پیشگیری از نفوذ 100٪ درست کار نمی کند. به علاوه، مهاجمان با تکنیک‌های پنهانی که استفاده می‌کنند اغلب می‌توانند از شناسایی فرار کنند.مهمتر از آن، مهاجمان با سرعت هشدار دهنده ای در حال نوآوری هستند که منجر به جریان دائمی حملات جدید و به روز می شود. شکار یک راه موثر برای کمک به دفاع شما است.جوانب مثبت و منفی شکار تهدیدبنابراین می توانیم فواید و معایب شکار را خلاصه کنیم. مزایا عبارتند از:وضعیت امنیتی بهبود یافته. شکار تهدید می‌تواند به سازمان‌ها کمک کند تا نقاط ضعف قوانین شناسایی، پلتفرم‌ها و جمع‌آوری داده‌ها را شناسایی و کاهش دهند.شهود و خلاقیت انسان را مهار می کند. بر خلاف محصولات تشخیص خودکار، که فقط می توانند در مورد آنچه برنامه ریزی شده اند هشدار دهند، شکار تهدید یک فرآیند انسان محور است. انسان ها در شناسایی الگوها، حتی در مواجهه با داده های ناقص یا مبهم، بسیار خوب هستند.امنیت را در حالت هجومی قرار می دهد. برخلاف برنامه‌های سنتی تشخیص حادثه، که کاملاً واکنشی(Reactive) هستند، شکار تهدید یک رویکرد پیشکنشانه(Proactive) برای شناسایی عوامل تهدید در شبکه شما است که ممکن است قبلاً به خوبی آنها را شناسایی نکرده باشید.البته بزرگترین اشکال این است که شکار منابع زیادی نیاز دارد. شکار تهدید می‌تواند زمان‌بر باشد و به مهارت‌ها و مهارت‌های تخصصی نیاز دارد.روندهای شکار تهدیدیکی از آخرین ملاحظات: علاقه به شکار تهدید به طور پیوسته در چند سال اخیر افزایش یافته است. البته این تعجب آور نیست، زیرا نقض امنیتی، حملات و مقررات حریم خصوصی از ویژگی های معمولی در اخبار یک کشور هستند. افراد بیشتری از تهدیدات روزمره آگاه هستند.یکی از راه‌های مشاهده این علاقه رو به رشد، Google Trends است که نشان می‌دهد یک موضوع خاص هر چند وقت یکبار محبوب است. در دهه گذشته، ما شاهد این هستیم که افراد بیشتری در سراسر جهان به دنبال موضوعاتی در مورد «شکار تهدید» (خط آبی با شیب تند) و «شکار تهدید سایبری» (پایین، خط قرمز) هستند.فریمورک و انواع شکارخوب پس برای شکار آماده هستید، اما از کجا شروع کنید؟ فریمورک شکار تهدید سیستمی از فرآیندهای قابل انطباق و تکراری است که طراحی شده است تا اکتشافات شکار شما را قابل اعتمادتر و کارآمدتر کند.تعدادی فریمورک وجود دارد که قابل توجه ترین آنها موارد زیر است.مدل مرجع شکار تهدید Sqrrl (2015)فریمورک Sqrrl که در سه قسمت (قسمت 1، قسمت 2، قسمت 3) منتشر شده است، نه تنها اولین مورد بود، بلکه یکی از تأثیرگذارترین فریمورک‌های شکار تهدید باقی می ماند. این فرآیند شکار مبتنی بر فرضیه را به عنوان یک حلقه با چهار مرحله تعریف می کند:ایجاد فرضیه (Create hypothesis)از طریق ابزارها و تکنیک ها تحقیق کنید (Investigate via tools &amp; techniques)الگوها و TTPهای جدید را کشف کنید (Uncover new patterns &amp; TTPs)اطلاع رسانی و غنی سازی تجزیه و تحلیل خودکار (Inform &amp; enrich automated analytics)شکار هدفمند ادغام اطلاعات تهدید TaHiTI (2018)فریمورک TaHiTI که توسط کنسرسیومی از موسسات مالی معروف به انجمن پرداخت هلندی ایجاد شده است، یکی دیگر از فریمورک‌های رایج شکار تهدید است. می‌توانیم تاهیتی را به صورت زیر خلاصه کنیم:بر اساس اجزای از فریمورک Sqrrl، مانند مدل بلوغ شکار. افزودن نوع جدیدی از شکار، معروف به شکار بدون ساختار یا داده محور.ارائه راهنمایی دقیق تر در مورد فرآیند شکار و معیارهای بالقوه برای موفقیت برنامه شکار.آماده، اجرا و عمل با دانش PEAK 2023فریمورک شکار تهدید PEAK شامل تجربه به دست آمده و درس های آموخته شده در چند سال گذشته شکار تهدید می شود. فریمورک PEAK:نوع سومی از شکار را اضافه می کند، شکار تهدید به کمک ماشین (Machine-Assisted ThreatHunting)، که در زیر نمایش داده می شود.حتی راهنمایی‌های دقیق تری را برای اجرای هر نوع شکار ارائه می دهد.این فریمورک فروشنده و ابزار آگنوستیک با یکی از سازندگان اصلی فریمورک Sqrrl که در بالا ذکر شد ایجاد شده است.فریمورک PEAK شامل سه نوع شکار مجزا است. این نمودار فرآیند شکار تهدید به کمک مدل (M-ATH) را نشان می دهد.از تهدید نترسید، شروع به شکار کنیدشکار تهدید یک رویکرد پیشگیرانه برای امنیت سایبری است که از شهود و خلاقیت انسان برای شناسایی و مقابله با حوادث امنیتی استفاده می‌کند که در غیر این صورت ممکن است شناسایی نشده باشند. با گنجاندن شکار تهدید در اقدامات امنیتی سازمان خود، می توانید: وضعیت امنیتی کلی خود را بهبود بخشید.از قدرت تشخیص الگوی انسان محور استفاده کنید.در نهایت قابلیت‌های تشخیص خودکار خود را تقویت کنید.در حالی که شکار تهدید می‌تواند منابع زیادی نیاز داشته باشد، مزایای جلوتر ماندن از حملات احتمالی آن را به یک روش بسیار توصیه شده برای اکثر سازمان‌ها تبدیل می‌کند. برای شروع، یک فریمورک شکار تهدید مانند مدل مرجع شکار تهدید Sqrrl، TaHiTI یا PEAK را در نظر بگیرید، که می تواند رویکردی ساختاریافته و کارآمد برای تلاش‌های شکار تهدید شما ارائه دهد.منبعترجمه آزاد از مقاله What Is Threat Hunting? A Cybersecurity Strategy نویسنده: David Biancoتاریخ انتشار: April 26, 2023آدرس وب‌سایت: https://www.splunk.com/en_us/blog/learn/threat-hunting.html</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Wed, 21 Aug 2024 11:27:39 +0330</pubDate>
            </item>
                    <item>
                <title>تولد شبکه عصبی پرسپترون</title>
                <link>https://virgool.io/@mojino/%D8%AA%D9%88%D9%84%D8%AF-%D8%B4%D8%A8%DA%A9%D9%87-%D8%B9%D8%B5%D8%A8%DB%8C-%D9%BE%D8%B1%D8%B3%D9%BE%D8%AA%D8%B1%D9%88%D9%86-oidznaulmdov</link>
                <description>معرفیتوسعه پرسپترون توسط فرانک روزنبلات(Frank Rosenblatt’s Perceptron) در اواخر دهه 1950 نقطه عطف مهمی در زمینه هوش مصنوعی بود. پرسپترون، یک مدل شبکه عصبی ساده بود که مفهوم یادگیری کامپیوتری را معرفی کرد و الهام‌بخش تحقیقات بیشتر در یادگیری ماشین و شبکه‌های عصبی شد. این مقاله مفاهیم اساسی پشت پرسپترون و اجرای آن را برای درک سهم درخشان فرانک روزنبلات در هوش مصنوعی بررسی می‌کند.مقدمه ای بر نورون مصنوعی پرسپترونبرای درک اهمیت پرسپترون فرانک روزنبلات، باید زمینه تاریخی توسعه آن را در نظر بگیریم. در اواخر دهه 1950، رایانه‌ها به عنوان ابزارهای قدرتمندی برای کاربردهای علمی و مهندسی ظاهر شدند و محققان را به کشف امکان استفاده از آنها برای شبیه سازی فرآیندهای شناختی انسان سوق داد. اقدامات روزنبلات بر اساس پیشرفت‌های قبلی در این زمینه، به ویژه مفاهیم شبکه های عصبی و نورون های مصنوعی بود.پرسپترون روزنبلات تأثیر عمیقی بر حوزه هوش مصنوعی داشت. پرسپترون یکی از اولین مدل هایی بود که یادگیری ماشین را شرح داد. این مدل نشان داد که یک الگوریتم ساده می تواند پارامترهای خود را بر اساس داده‌های ورودی برای بهبود عملکرد خود تطبیق دهد و راه را برای الگوریتم‌های یادگیری پیچیده‌تر هموار کند. پرسپترون در زمینه‌هایی مانند تشخیص کاراکتر، پردازش تصویر و تشخیص گفتار کاربردهایی پیدا کرد و پایه و اساس برنامه‌های کاربردی یادگیری ماشین امروزی را گذاشت. در حالی که پرسپترون نویدبخش بود، اما در توانایی‌هایش، به ویژه در رسیدگی به مسائل غیر خطی، محدود بود. این محدودیت منجر به شک و تردید و کاهش علاقه به شبکه های عصبی، معروف به &quot;زمستان هوش مصنوعی&quot; شد.پرسپترون چیست؟پرسپترون مدلی از یک نورون بیولوژیکی است. یک یا چند ورودی یا محرک را می‌گیرد و یک خروجی باینری تولید می‌کند. اجزای اصلی پرسپترون عبارتند از:ورودی و وزن(Input and weights): هر ورودی با وزنی مرتبط است که سهم آن را در خروجی پرسپترون تعیین می‌کند. این وزن‌ها پارامترهایی هستند که پرسپترون در طول فرآیند یادگیری آنها را تنظیم می‌کند.تابع فعال‌سازی(Activation Function): مجموع وزنی ورودی‌ها از طریق یک تابع فعال‌سازی، معمولاً یک تابع مرحله‌ای، منتقل می‌شود. اگر مجموع از آستانه معینی فراتر رود، پرسپترون 1 را تولید می‌کند.      در غیر این صورت 0 را به خروجی می‌دهد.الگوریتم یادگیری(Learning Algorithm): پرسپترون با تنظیم وزن‌های خود بر اساس خطای خروجی خود نسبت به خروجی مورد نظر، یاد می‌گیرد. روزنبلات قانون یادگیری پرسپترون را به عنوان روشی ساده برای به روز رسانی وزن‌ها معرفی کرد.چه زمانی باید از پرسپترون استفاده کرد؟پرسپترون‌ها از انواع ساده‌تر الگوریتم‌های یادگیری ماشینی هستند که برای کار بر روی مجموعه داده‌های قابل جداسازی خطی طراحی شده‌اند. تفکیک پذیری خطی یک مفهوم اساسی در یادگیری ماشین و تشخیص الگو است. این به ویژگی یک مجموعه داده اشاره دارد که در آن دو کلاس یا دسته از نقاط داده را می توان با یک خط مستقیم (در فضای دو بعدی)، یک ابر صفحه (در فضای با ابعاد بالاتر)، یا به طور کلی یک مرز تصمیم گیری خطی از هم جدا کرد. مجموعه داده‌های قابل جداسازی خطی در مسائل ساده استاندارد هستند که در آن کلاس‌ها می‌توانند به طور مجزا از هم جدا شوند. به عنوان مثال، مجموعه داده ای از سیب و پرتقال، زمانی که با استفاده از ویژگی هایی مانند وزن و رنگ ترسیم می شود، اغلب می تواند با یک خط مستقیم از هم جدا شود.تفکیک پذیری خطی یک مفهوم اساسی است زیرا بر انتخاب الگوریتم ها و تکنیک ها برای حل مسائل طبقه بندی تأثیر می گذارد. هنگام برخورد با داده‌های قابل جداسازی خطی، اغلب می‌توان از الگوریتم‌های ساده‌تری مانند رگرسیون لجستیک یا ماشین‌های بردار پشتیبان خطی (SVM) استفاده کرد. برای داده‌های غیرخطی قابل تفکیک، مدل‌های پیچیده‌تر مانند SVM‌های غیرخطی و مدل‌های یادگیری عمیق یا مبتنی بر درخت برای ثبت الگوهای اساسی در داده‌ها ضروری هستند. درک تفکیک پذیری خطی یک مجموعه داده یک گام مهم در مهندسی ویژگی و فرآیند انتخاب مدل در یادگیری ماشین است.الگوریتم یادگیریالگوریتم یادگیری پرسپترون یک الگوریتم ساده و اساسی است که برای کارهای طبقه بندی باینری استفاده می شود که در آن می خواهید نقاط داده را به دو کلاس جدا کنید.مراحل:1. با مقداردهی اولیه وزن ها و سوگیری ها شروع کنید. می توانید این مقادیر را روی مقادیر کوچک تصادفی تنظیم کنید.2. برای هر مثال آموزشی، داده‌های ورودی را به پرسپترون می‌دهید. ورودی شامل بردار ویژگی ها (x1, x2, …, xn) است.3. یک پیش‌بینی با مجموعه وزن‌ها و مقادیر سوگیری(bias) انجام دهید.4. پیش‌بینی را از مقدار هدف کم کنید تا مشخص شود که آیا نیاز به افزایش یا کاهش وزن‌ها و مقادیر سوگیری داریم.5. سپس، وزن را با نرخ یادگیری(learning rate) برای هر ورودی در مثال تمرینی که به اشتباه پیش‌بینی شده بود، افزایش یا کاهش می‌دهیم (بر اساس 4).6. مراحل 3 تا 5 را برای تمام مثال های آموزشی برای تعداد ثابتی از تکرارها (دوران) تکرار کنید.پیاده سازی پرسپترون در پایتونبیایید با اعلام کلاس خود و سازنده شروع کنیم، که دو آرگومان را برای کمک به پیکربندی مدل می‌پذیرد. نرخ یادگیری بر سرعت یادگیری پارامترها توسط مدل حاکم است. استدلال epochs تعریف می کند که الگوریتم چند تلاش برای یادگیری روابط بین ورودی و خروجی دارد.ما به روشی نیاز داریم که به الگوریتم دستور دهد تا از داده های آموزشی ما یاد بگیرد. روش تناسب به ما این امکان را می دهد. وزن و سوگیری ویژگی کلاس را مقداردهی اولیه می کنیم. متغیر وزن آرایه ای به طول برابر با تعداد ورودی های مدل ما خواهد بود. از دو حلقه for برای تکرار بر روی تعداد دوره ها و داده های آموزشی استفاده می شود. در هر تکرار، الگوریتم وزن‌ها و عبارات بایاس را برای تصحیح خطاهای یافت شده تنظیم می‌کند. این تا زمانی که تمام نمونه های آموزشی و دوره ها اجرا شوند ادامه خواهد داشت.روش پیش‌بینی مجموع حاصل از وزن‌ها و ورودی‌ها را می‌گیرد و عبارت بایاس را برای هر تمرین z اضافه می‌کند. مجموع متعاقباً به تابع فعال سازی منتقل می شود.ما همچنین باید یک تابع فعال سازی را اعلام کنیم که طبقه بندی را بر اساس مجموع دریافتی از روش &quot;پیش بینی&quot; انجام می دهد.پس از اتمام کلاس باید به این شکل باشد.آموزش پرسپترون و ارزیابی عملکرد آنبرای ارزیابی مدل خود، نیاز به جمع آوری داده هایی داریم که به صورت خطی قابل تفکیک هستند. ما از مجموعه داده های گل زنبق برای ایجاد نمونه های آموزشی و آزمایشی استفاده خواهیم کرد. مجموعه داده Iris یکی از معروف ترین و پرکاربردترین مجموعه داده ها در یادگیری ماشینی و آمار است. این مجموعه داده کوچکی است که شامل اندازه گیری ویژگی های مختلف سه گونه مختلف گل زنبق است. ما برای اهداف خود این سه کلاس را به دو کلاس تبدیل می کنیم. این مجموعه داده اغلب برای تمرین و نشان دادن تکنیک های مختلف طبقه بندی و تجزیه و تحلیل داده ها استفاده می شود.ما از ستون‌های طول و عرض کاسبرگ برای پیش‌بینی اینکه گل &quot;Iris-setosa&quot; یا گونه‌ای متفاوت از زنبق است استفاده می‌کنیم.بیایید داده ها را وارد کنیم و آن ها را به آموزش و آزمایش تقسیم کنیم:اکنون باید یک نمونه از کلاس پرسپترون ایجاد کنیم. دوره ها را روی 10 و نرخ یادگیری را روی 0.1 تنظیم کنید. پس از ایجاد نمونه، مدل را با استفاده از پارتیشن های آموزشی برازش می کنیم.این مدل در مجموعه داده آزمایشی عملکرد خوبی دارد. بیایید نتایج خود را ترسیم کنیم تا ببینیم مجموعه داده های آزمایش ما چقدر قابل تفکیک است.نتیجه‌گیریپرسپترون فرانک روزنبلات یک دستاورد پیشگام در تاریخ هوش مصنوعی بود. در حالی که محدودیت هایی داشت، مفهوم یادگیری را به ماشین ها معرفی کرد و زمینه را برای پیشرفت های بعدی در شبکه های عصبی و یادگیری ماشینی فراهم کرد. پرسپترون به عنوان گواهی بر اهمیت ایده های ساده و اساسی در پیشبرد پیشرفت در هوش مصنوعی عمل می کند. امروزه، شبکه‌های عصبی، از جمله مدل‌های یادگیری عمیق، وجود خود را مدیون آغاز فروتن پرسپترون هستند، و این همچنان یک فصل مهم در داستان هوش مصنوعی است.</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Sun, 19 May 2024 18:54:10 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت بین میانگین‌گیری میکرو و ماکرو چیست؟</title>
                <link>https://virgool.io/@mojino/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-%D8%A8%DB%8C%D9%86-%D9%85%DB%8C%D8%A7%D9%86%DA%AF%DB%8C%D9%86-%DA%AF%DB%8C%D8%B1%DB%8C-%D9%85%DB%8C%DA%A9%D8%B1%D9%88-%D9%88-%D9%85%D8%A7%DA%A9%D8%B1%D9%88-%DA%86%DB%8C%D8%B3%D8%AA-scopua2eockq</link>
                <description>در زمینه ارزیابی عملکرد هر مدل یادگیری ماشینی، اصطلاحات &quot;میکرو&quot; و &quot;ماکرو&quot; به روش‌های مختلف محاسبه معیارهای عملکرد، مانند دقت، پوشش و امتیاز F1 برای چندین کلاس اشاره دارند. در اینجا توضیحی از این مفاهیم ارائه می‌شود:میانگین خرد (Micro-Averaging)میانگین میکرو مشارکت‌های همه کلاس‌ها را برای محاسبه معیار  میانگین جمع‌آوری می‌کند. این روش با هر نمونه به طور مساوی برخورد می‌کند، به این معنا که تعداد مثبت‌های درست، مثبت‌های کاذب و منفی‌های  کاذب را برای همه کلاس‌ها جمع‌آوری کرده و سپس معیارها را محاسبه می‌کند.مورد استفاده:میانگین میکرو به‌ویژه برای مواجهه با مجموعه‌داده‌های نامتعادل که در آن برخی کلاس‌ها بسیار بیشتر از سایرین هستند، مفید است. این روش به معنای عملکرد کلی سیستم با وزن‌دهی کلاس‌ها براساس فراوانی آن‌ها اشاره دارد.فرمول محاسبه:میانگین کلان (Macro-Averaging)میانگین ماکرو معیار را برای هر کلاس به طور مستقل محاسبه  کرده و سپس میانگین این مقادیر را می‌گیرد. این روش با هر کلاس به طور  مساوی برخورد می‌کند، بدون توجه به تعداد نمونه‌ها در هر کلاس.مورد استفاده:میانگین ماکرو زمانی مفید است که بخواهید عملکرد را به طور مساوی برای همه کلاس‌ها اندازه‌گیری کنید، که می‌تواند نشان دهد مدل چقدر در کلاس‌های کمتر فراوان عملکرد دارد. این به ویژه در مواردی که عملکرد کلاس‌های اقلیتی مهم است.فرمول محاسبه:مثال:فرض کنید یک مسئله طبقه‌بندی چندکلاسه با سه کلاس (الف، ب و ج) داریم:کلاس الف : 50 نمونهکلاس ب : 30 نمونهکلاس ج : 20 نمونهفرض کنید معیارهای عملکرد زیر را داریم:کلاس الف : دقت=0.9 و پوشش=0.8کلاس ب:  دقت=0.7 و پوشش=0.6کلاس ج: دقت=0.8 و پوشش=0.7محاسبه میانگین میکروتعداد مثبت‌های درست، مثبت‌های کاذب و منفی‌های کاذب را برای همه کلاس‌ها جمع‌آوری کرده و سپس دقت، پوشش و F1-score را محاسبه می‌کنید، مانند مقادیر بالامحاسبه میانگین ماکرومیانگین دقت، پوشش و F1-score برای هر کلاس را طبق فرمول محاسبه می‌کنید:دقت ماکرو: 3/(0.9+0.7+0.8)=0.8پوشش ماکرو:3/ (0.8+0.6+0.7)​≈0.7معیار F1-Score ماکرو : F1-score را برای هر کلاس محاسبه کرده و سپس میانگین آن‌ها را بگیرید.نتیجه‌گیری:تفاوت بین میانگین کلان و خرد در این است که میانگین کلان به هر دسته وزن مساوی می دهد در حالی که میانگین خرد به هر نمونه وزن مساوی می دهد. اگر تعداد نمونه های یکسانی برای هر کلاس داشته باشیم، هر دو Macro و Micro امتیاز یکسانی را ارائه می دهند.میانگین میکرو تحت تأثیر توزیع نمونه‌های کلاس‌ها قرار می‌گیرد و برای محاسبه عملکرد کلی زمانی که کلاس‌ها نامتعادل هستند، بهتر عمل می‌کند.میانگین ماکرو با همه کلاس‌ها به طور مساوی برخورد می‌کند و برای درک عملکرد در هر کلاس به طور مستقل، به ویژه زمانی که عملکرد در کلاس‌های اقلیتی مهم است، مفید است.</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Sat, 18 May 2024 15:11:56 +0330</pubDate>
            </item>
                    <item>
                <title>حاشیه نویسی سطح جمله در مقابل حاشیه نویسی سطح عبارت</title>
                <link>https://virgool.io/@mojino/%D8%AD%D8%A7%D8%B4%DB%8C%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%B3%D8%B7%D8%AD-%D8%AC%D9%85%D9%84%D9%87-%D8%AF%D8%B1-%D9%85%D9%82%D8%A7%D8%A8%D9%84-%D8%AD%D8%A7%D8%B4%DB%8C%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%B3%D8%B7%D8%AD-%D8%B9%D8%A8%D8%A7%D8%B1%D8%AA-gxutqiflnpsy</link>
                <description>sentence annotation وقتی که با حاشیه‌نویسی متن در زمینه‌ی پردازش زبان طبیعی (NLP) یا تحلیل  زبان‌شناسی سر و کار داریم، حاشیه‌نویسی در سطح جمله (sentence-level annotation) و حاشیه‌نویسی در سطح  عبارت (phrase-level annotation) اهداف متفاوتی دارند و به شکل‌های متفاوتی اعمال می‌شوند. در اینجا  یک مقایسه‌ی دقیق ارائه می‌شود:حاشیه‌نویسی در سطح جملهحاشیه‌نویسی در سطح جمله شامل برچسب‌گذاری یا علامت‌گذاری کل جملات با  برچسب‌ها یا دسته‌های خاص است. این نوع حاشیه‌نویسی برای وظایفی که زمینه  یا معنای کل جمله مهم است، مفید می‌باشد.کاربردها:تحلیل احساسات: برچسب‌گذاری جملات به عنوان مثبت، منفی یا خنثی.طبقه‌بندی متن: اختصاص دادن یک موضوع یا دسته به جمله، مانند اسپم (SPAM) یا غیر اسپم.تشخیص خطای گرامری: علامت‌گذاری جملات به عنوان گرامری صحیح یا نادرست.تقسیم‌بندی جملات: شناسایی مرزهای جملات در یک متن.مثال:جمله: &quot;فیلم به شدت خسته‌کننده بود.&quot;احساس: منفیحاشیه‌نویسی در سطح عبارتحاشیه‌نویسی در سطح عبارت شامل برچسب‌گذاری بخش‌ها یا قطعات خاصی در یک  جمله می‌شود. این می‌تواند شامل کلمات، تکه‌های کلمات یا واحدهای نحوی  باشد. حاشیه‌نویسی در سطح عبارت دقیق‌تر است و برای وظایفی که نیاز به درک ساختار و اجزای داخل جملات دارند، مفید است.کاربردها:شناسایی نام‌های موجود (Named Entity Recognition - NER): شناسایی و طبقه‌بندی نام‌های خاص (مثلاً افراد، سازمان‌ها، مکان‌ها) در یک جمله.برچسب‌گذاری نقش‌های دستوری: اختصاص نقش‌های دستوری (مثلاً اسم، فعل، صفت) به کلمات یا عبارات.تحلیل نحوی: علامت‌گذاری ساختار نحوی یک جمله، مانند گروه اسمی (NP)، گروه فعلی (VP)، و غیره.استخراج اطلاعات: شناسایی قطعات خاصی از اطلاعات در یک جمله، مانند تاریخ‌ها، قیمت‌ها، یا مقادیر.مثال:جمله: &quot;باراک اوباما در هاوایی به دنیا آمد.&quot;نام‌های موجود: [باراک اوباما] (شخص)، [هاوایی] (مکان)نقش‌های دستوری: [باراک اوباما] (گروه اسمی)، [به دنیا آمد] (گروه فعلی)، [در هاوایی] (گروه حرف اضافه‌ای)مقایسه کلی:از نظر جزئیات:سطح جمله: کلی و متمرکز بر معنای کلی یا دسته‌ی جمله.سطح عبارت: دقیق و متمرکز بر اجزای خاص یا عناصر داخل جملهاز نظر کاربردها:سطح جمله: مناسب برای وظایفی که زمینه‌ی کل جمله مهم است، مانند تحلیل احساسات و طبقه‌بندی متن.سطح عبارت: مناسب برای وظایفی که نیاز به تحلیل دقیق اجزای جمله دارند، مانند شناسایی نام‌های موجود، تحلیل نحوی، و برچسب‌گذاری نقش‌های دستوریاز نظر پیچیدگی:سطح جمله: معمولاً ساده‌تر و سریع‌تر برای حاشیه‌نویسی چون شامل کل جملات می‌شود.سطح عبارت: پیچیده‌تر و زمان‌برتر به دلیل نیاز به شناسایی و برچسب‌گذاری چندین عنصر داخل هر جملهاز نظر ابزارها و روش‌ها:سطح جمله: ابزارها ممکن است شامل دسته‌بندی‌کننده‌های متن یا مدل‌های تحلیل احساسات باشند.سطح عبارت: ابزارها ممکن است شامل مدل‌های شناسایی نام‌های موجود، تحلیل‌گرهای نحوی، یا برچسب‌گذارهای نقش‌های دستوری باشندبه طور خلاصه، انتخاب بین حاشیه‌نویسی در سطح جمله و حاشیه‌نویسی در سطح  عبارت بستگی به نیازهای خاص وظیفه دارد. حاشیه‌نویسی در سطح جمله نمای کلی و  جامع‌تری ارائه می‌دهد و برای وظایفی که درک کل جمله ضروری است، مناسب است. حاشیه‌نویسی در سطح عبارت، از سوی دیگر، دید دقیق‌تر و جزئی‌تری ارائه  می‌دهد که برای وظایفی که نیاز به تحلیل عمیق اجزای جمله دارند، ضروری است.</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Sat, 18 May 2024 11:48:38 +0330</pubDate>
            </item>
                    <item>
                <title>حمله منع سرویس Slowloris چیست؟</title>
                <link>https://virgool.io/@mojino/%D8%AD%D9%85%D9%84%D9%87-%D9%85%D9%86%D8%B9-%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-slowloris-%DA%86%DB%8C%D8%B3%D8%AA-tvmtjl2txz2k</link>
                <description>اسلولوریس یک حمله منع سرویس  است که به مهاجم اجازه می‌دهد با باز کردن همزمان چندین  ارتباط HTTP و حفظ کردن این ارتباط بین مهاجم و قربانی، باعث از پا درآمدن سرور قربانی می‌شود.حمله Slowloris چگونه کار می کند؟اسلولوریس یک حمله در لایه کاربرد(Application layer) است که با استفاده از درخواست‌های خرد HTTP عمل می‌کند. عملکرد حمله با باز کردن ارتباط با وب سرور قربانی شروع می‌شود و تا حداکثر زمانی که می‌تواند این ارتباط را حفظ می‌کند.اسلولوریس یک ابزار حمله است که به مهاجم اجازه می‌دهد بدون استفاده از پهنای باند زیاد، سرور قربانی را از کار بیاندازد. برخلاف حملات DDoS که مبتنی بر مصرف پهنای باند هستند مانند NTP amplification ، این نوع حمله از پهنای باند کمی استفاده می‌کند و در عوض با درخواست‌های که کندتراز حالت عادی به نظر می‌رسند اما از ترافیک معمولی تقلید می‌کنند منابع سرور را اشغال می‌کند. این حمله در دسته‌بندی حملات low and slow قرار می‌گیرد.سرورها توانایی مدیریت ارتباطات(threads) همزمان زیادی را دارند و به طور معمول تلاش می‌کنند یک ارتباط را هرچند کند باشد زنده نگه دارند. در این حمله سرور منتظر تکمیل درخواست کند مهاجم است که قرار نیست کامل شود. وقتی از حداکثر ظرفیت ارتباطات سرور استفاده می‌شود، سرور قربانی به ارتباطات جدید پاسخ نمی‌دهد و حمله منع سرویس رخ می‌دهد.حمله Slowloris در 4 مرحله رخ می دهد:مهاجم ابتدا چندین ارتباط با سرور قربانی ایجاد می‌کند، این کار را به صورت ارسال درخواست‌های خرد headers انجام می‌دهد.سرور قربانی برای هر درخواست ورودی یک ارتباط باز می‌کند، با این هدف که پس از اتمام ارتباط آن را ببندد. همچنین به منظور کارآمدی سرور، در صورتی که یک ارتباط بیش ازحد طول بکشد، سرور به صورت خودکار این ارتباط را می‌بندد و  thread را آزاد می‌کند.برای جلوگیری از قطع ارتباط توسط قربانی، مهاجم به طور دوره‌ای درخواست‌های خرد header را برای قربانی ارسال می‌کند تا ارتباط زنده نگه داشته شود. در اصل به قربانی می‌گوید: &quot;من هنوز اینجا هستم! من فقط کند هستم، لطفا منتظر من باشید.&quot;سرور قربانی هرگر نمی‌تواند هیچ یک از این ارتباطات ناقص را در حالی که منتظر خاتمه درخواست است، آزاد کند. هنگامی که همه thread ها موجود در حال استفاده هستند، سرور قادر به پاسخگویی به درخواست‌های جدید که از ترافیک معمولی ایجاد می‌شود، نخواهد بود و در نتیجه درخواست رد می‌شود.نکته کلیدی در پشت حمله اسلولوریس توانایی آن در ایجاد اختلال گسترده با مصرف بسیار کم پهنای باند است.چگونه اثر یک حمله Slowloris کاهش می یابد؟برای سرورهای وب که در برابر حمله اسلولوریس آسیب‌پذیر هستند، راه‌هایی برای کاهش برخی از تاثیرات وجود دراد. گزینه‌های کاهش اثر برای سرورهای آسیب‌پذیر را می‌توان به 3 دسته کلی تقسیم کرد:افزایش در دسترس بودن سرور - افزایش حداکثر تعداد پذیرش درخواست کلاینت به طوری که که تعداد ارتباطات که مهاجم ایجاد می‌کند باعث اتمام ظرفیت سرور نشود. البته به طور واقع‌بینانه، یک مهاجم می‌تواند تعداد درخواست‌ها را برای غلبه بر ظرفیت سرور افزایش دهد.اعمال محدودیت در نرخ درخواست‌های ورودی - محدود کردن دسترسی بر اساس فاکتورهای استفاده خاص به کاهش حمله Slowloris کمک می کند. تکنیک هایی مانند محدود کردن حداکثر تعداد ایجاد ارتباطات مجاز برای یک آدرس IP، محدود کردن سرعت انتقال آهسته، و محدود کردن حداکثر زمانی که کلاینت مجاز است متصل بماند، همگی رویکردهایی برای محدود کردن اثربخشی حملات low and slow هستند.حفاظت مبتنی بر ابر - از سرویسی استفاده کنید که می تواند به عنوان یک پروکسی معکوس(reverse proxy) عمل کند و از سرور مبدا محافظت کند.منبع:https://www.cloudflare.com/learning/ddos/ddos-attack-tools/slowloris</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Wed, 16 Aug 2023 14:34:40 +0330</pubDate>
            </item>
                    <item>
                <title>اصطلاح Traffic Shaping به چه معنی است؟</title>
                <link>https://virgool.io/@mojino/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD-traffic-shaping-%D8%A8%D9%87-%DA%86%D9%87-%D9%85%D8%B9%D9%86%DB%8C-%D8%A7%D8%B3%D8%AA-ustehqgfq7kd</link>
                <description>شکل‌دهی ترافیک (همچنین به عنوان شکل‌دهی بسته شناخته می‌شود) یک تکنیک مدیریت پهنای باند است که جریان نوع خاصی از بسته‌های شبکه را به تاخیر می‌اندازد تا از عملکرد شبکه برای اپلیکشن با اولویت بالا اطمینان حاصل شود. شکل‌دهی ترافیک اساسا مقدار پهنای باند مصرفی اپلیکشن را می‌تواند محدود کند. این اقدام در درجه اول برای اطمینان حاصل کردن از کیفیت بالای خدمات برای ترافیک حیاتی و مهم در ارتباط با کسب و کار مربوطه استفاده می‌شود.رایج‌ترین نوع شکل‌دهی ترافیک، شکل‌دهی ترافیک مبتنی بر اپلیکیشن است. ابزارهایی وجود دارد که با توجه به ترافیک بسته ارسالی نوع اپلیکیشن را تشخیص می‌دهد و بر همین اساس سیاست‌های شکل‌دهی ترافیک اعمال می‌گردد. برای مثال، ممکن است بخواهید از شکل‌دهی مبتنی بر اپلیکیشن برای جلوگیری از اشتراک فایل به صورت peer-to-peer در شبکه استفاده کنید، حال آنکه میخواهید حداکثر پهنای باند را به اپلیکیشن Voice-over-IP که برای سازمان حیاتی است و همچنین به latency حساس است بدهید.بسیاری از پروتکل‌ اپلیکیشن‌ها از رمزنگاری برای دور زدن شکل‌دهی ترافیک مبتنی بر اپلیکیشن استفاده می‌کنند. برای جلوگیری از دور زدن اپلیکیشن‌ها از سیاست شکل‌دهی ترافیک، می‌توان از شکل‌دهی ترافیک مبتنی بر مسیر استفاده کرد. شکل‌دهی ترافیک مبتنی بر مسیر، سیاست‌های تنظیم بسته را بر اساس منبع و مقصد مورد نظر اعمال می‌کند.چرا Traffic Shaping مهم است؟منابع شبکه محدود، اولویت‌بندی پهنای باند را به یک ضرورت تبدیل کرده است. شکل‌دهی ترافیک یکی از مهم‌ترین تکنیک‌ها برای اطمینان داشتن از کیفیت بالای خدمات برای اپلیکیشن‌ها و داده‌های کسب و کار است.شکل‌دهی ترافیک یک نیاز ضروری برای فایروال شبکه است.روش محاسبه مقدار پهنای باند توسط Wireshrakدر صورتی که ویژگی شکل‌دهی ترافیک در شبکه فعال باشد، ما می‌توانیم با استفاده از مانیتور بسته شبکه در جهت خروجی outbound direction روی روتر WAN مقدار پهنای باند شبکه را محاسبه کنیم.</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Wed, 07 Jun 2023 14:32:05 +0330</pubDate>
            </item>
                    <item>
                <title>چگونه ترافیک TLS را با استفاده از Wireshark رمزگشایی کنیم؟</title>
                <link>https://virgool.io/@mojino/%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%AA%D8%B1%D8%A7%D9%81%DB%8C%DA%A9-tls-%D8%B1%D8%A7-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-wireshark-%D8%B1%D9%85%D8%B2%DA%AF%D8%B4%D8%A7%DB%8C%DB%8C-%DA%A9%D9%86%DB%8C%D8%AF-aijryoiav7h2</link>
                <description>اگر در حال خرید کردن از طریق وب‌سایت‌ها هستید، رمزنگاری چیز خوبی است، اما وقتی می خواهید یک شبکه را اداره کنید، این یک مشکل واقعی است. در این مقاله به بررسی نحوه رمزگشایی ترافیک HTTPs  با استفاده از ابزار Wireshark می‌پردازیم.اگر تا به حال از Wireshark برای نظارت بر ترافیک وب استفاده کرده اید، احتمالاً با مشکل  انتقال داده به صورت رمزگذاری شده روبرو شده اید. در حقیقت، بیشتر سایت ها برای ایمن نگه داشتن کاربران خود از رمزگذاری SSL یا Transport Layer Security (TLS) استفاده می کنند.استفاده از کلید pre-master secret key برای رمزگشایی TLSیکی از راه‌های که برای رمزگشایی TLS پیشنهاد می‌شود استفاده از pre-master secret key می‌باشد.یک pre-master secret key توسط کلاینت ایجاد می‌گردد تا سرور از طریق آن master key را جهت رمزنگاری ترافیک نشست منتقل کند. این استاندارد فعلی در رمزنگاری است و معمولاً از طریق Diffie-Hellman اجرا می‌شود.مرورگر شما می توان pre-master secret key  را که Wireshark برای رمزگشایی جلسات SSL و TLS از آن استفاده می کند ،در یک فایل ذخیره کند.در اینجا مراحل رمزگشایی SSL و TLS با یک pre-master secret key آورده شده است: تنظیم یک متغییر محیطی (environment variable)اجرای مرورگر و باز کردن یک سایت Https پیکربندی Wireshark ضبط (capture) و رمزگشایی کلیدهای نشست (session keys)پس از اتمام کار، شما قادر خواهید بود  بدون اینکه نیاز به دسترسی به سرور هدف داشته باشید نشست‌ای SSL و TLS را در Wireshark رمزگشایی کنید.تنظیم یک متغییر محیطی در سیستم‌عامل ویندوزدر سیستم‌عامل‌های ویندوز ، شما باید با استفاده از ابزار تنظیمات سیستم پیشرفته(Advanced system settings)، یک متغیر محیط را تنظیم کنید. این متغیر ، به نام SSLKEYLOGFILE ، حاوی مسیری است که pre-master secret key ذخیره می شوند.روی My Computer راست کلیک کنید و گزینه Properties را از منو انتخاب کنید، با این کار پنجره System به نمایش در خواهد آمد.سپس، بر روی Advanced system settings در منوی سمت چپ پنجره کلیک کنید تا پنجره System Properties باز گردد.در زبانه Advanced بر روی دکمه Environment Variables کلیک کنید.بر روی دکمه New در User variables کلیک کنید. در صورتی که بخواهید لاگ کلید SSL برای همه کاربران نمایش داده شود، شما می‌توانید در System variables این متغییر را بسازید. البته توصیه نمی‌کنم.در  زمینه Variable name نام زیر بنویسید:SSLKEYLOGFILEدر زمینه  Variable value، مسیر ذخیره فایل لاگ را مشخص کنید. همچنین میتوانید با استفاده از دکمه Browse file... فایل مدنظر خود را انتخاب کنید.نکته : در صورتی که بخواهید این متغییر را بر روی کل سیستم تعریف کنید، شما نیاز دارید که مسیر ذخیره فایل را به صورت wildcard تعیین کنید و یا در مکانی ذخیره کنید که تمامی کاربران به آن دسترسی داشته باشند. برای نمونه %USERPROFILE%\App Data\ssl-keys.log یا C:\ssl-keys.log.پس از اتمام کار بر روی دکمه Ok کلیک کنید.اجرای مرورگر و بررسی فایل لاگ قبل از اجرای wireshark و انجام پیکربندی آن شما باید یکبار مرورگر را باز کنید. این نکته خیلی مهم است که به منظور جمع‌آوری لاگ حتما یک سایتی که SSL آن فعال است را از طریق مرورر باز کنید. من اینجا از وب سرور خودم برای این کار استفاده کرده‌ام ولی محدودیتی برای انتخاب سایت وجود ندارد و سایتی که میخواهید را می‌توانید باز کنید.یکی از بزرگترین مزایای استفاده از یک pre-master shared key این است که شما نیازی به دسترسی به سرور برای رمزگشایی SSL ندارید.پیکربندی wireshark برای رمزگشایی TLSدر صورتی که مرورگر به درستی در فایل ایجادی pre-master keys  لاگ می‌کند، حال زمانی است که می‌توانید wireshark  را برای رمزگشایی پیکربندی کنید.ابزار wireshark را باز کنید و از منو Edit، سپس Preferences را کلیک کنید. در پنجره Preferences در لیست سمت چپ، منوی Protocols را انتخاب کنید و به دنبال منوی TLS باشید(در نسخه‌های قدیمی‌تر SSL بوده است).در لیست گزینه‌های پروتکل TLS، مسیر فایل ایجاد شده را در بخش(Pre)-Master-Secret log filename وارد کنید. سپس بر روی دکمه Ok کلیک کنید.ضبط نشست و رمزگشایی TLSمرحله آخر ضبط یک نشست آزمایشی و اطمینان از رمزگشایی Wireshark TLS با موفقیت است.یک ضبط نشست بدون فیلتر را شروع کنید ، پنجره آن را به کوچک کنید و مرورگر خود را باز کنید.برای تولید داده به یک سایت امن مراجعه کنید و فیلتر را روی پروتکل tls تنظیم کنید.روی بسته‌ای که داده رمز شده دارد کلیک کنید.در این مرحله، هر ترافیکی رمز شده(encrypted transmissions) که از pre-master secret  یا private key استفاده کرده باشد، با این روش  تمام داده‌های perfect forward enctyption (PFE) که از طریق Diffie-Hellman و یا comparable key تبادل می‌شوند، رمزگشایی می‌شود. پس از انتخاب یک frame داده رمزگذاری شده ، به packet byte view و به طور خاص زبانه های زیر packet byte view نگاه کنید. شما باید بتوانید Decrypted SSL را مشاهده کنید.همانطور که متوجه شدید همچنان نشست قابل خواندن نیست و هیچ کد html وجود ندارد. دلیل این امر وجود فشرده سازی پیش فرض Gzip در وب سرور‌هایی مانند Apache Server استزمانی که شما بر روی زبانه Uncompressed entity body کلیک می‌کنید، شما می‌توانید سورس کد سایت را مشاهده کنید.</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Wed, 17 May 2023 18:28:24 +0330</pubDate>
            </item>
                    <item>
                <title>پیاده‌سازی الگوریتم ژنتیک با استفاده از پایتون</title>
                <link>https://dataio.ir/پیادهسازی-الگوریتم-ژنتیک-با-استفاده-از-پایتون-q6d1lyptj7wu</link>
                <description>در این آموزش تکنیک‌ بهینه‌سازی الگوریتم ژنتیک در پایتون را بر اساس یک مثال ساده پیاده‌سازی می‌کنیم. سعی ما بر این است که خروجی معادله را حداکثر کنیم. در این آموزش از اعداد اعشاری برای نمایش ژن‌ها، عملگر برش (one point crossover) و عملگر جهش (uniform mutation) استفاده شده است.پیاده‌سازی الگوریتم ژنتیک با استفاده از پایتون بررسی اجمالی الگوریتم ژنتیکروندنما‌ (Flowchart) الگوریتم ژنتیک در تصویر زیر قابل مشاهده است. هر گام را به تفصیل در ادامه توضیح می‌دهیم.روندنما الگوریتم ژنتیکروش‌های مختلفی جهت نمایش (representation) ژن‌ها وجود دارد مانند: نمایش به صورت باینری،  اعشار،  صحیح و غیره. با هر نوع از این نمایش‌ها رفتار مختلفی می‌شود.عملگر جهش نیز انواع مختلفی دارد از جمله bit flip، swap، inverse، uniform ،non-uniform ،Gaussian shrink و غیره.همچنین  عملگر برش نیز انواع مختلفی دارد از جمله blend، one point، two points، uniform و غیره.این آموزش همه اینها را پیاده‌سازی نمی‌کند بلکه تنها یک نمونه از آن‌ها که در هر مرحله الگوریتم ژنتیک دخیل   هستند را پیاده سازی می‌کند.در این آموزش از نمایش اعشاری برای ژن‌ها، عملگر برش  one point و عملگر جهش  uniform استفاده شده است.همچنین در نظر داشته باشید در این مقاله فرض شده است که خواننده فهم و درک کافی از چگونگی اجرا الگوریتم ژنتیک دارد در غیر اینصورت پیشنهاد می‌شود مقالات زیر را مطالعه کنید: LinkedIn: https://www.linkedin.com/pulse/introduction-optimization-genetic-algorithm-ahmed-gad/KDnuggets: https://www.kdnuggets.com/2018/03/introduction-optimization-with-genetic-algorithm.htmlTowardsDataScience: https://towardsdatascience.com/introduction-to-optimization-with-genetic-algorithm-2f5001d9964bSlideShare: https://www.slideshare.net/AhmedGadFCIT/introduction-to-optimization-with-genetic-algorithm-gaشروع کدنویسی با پایتونمعادله‌ایی که قصد داریم آن را با پایتون پیاده‌سازی کنیم به اینصورت است.Y = w1x1 + w2x2 + w3x3 + w4x4 + w5x5 + w6x6معادله دارای ۶ ورودی (x1 to x6)  و ۶ وزن (w1 to w6) است و همانطور که نشان داده شده است مقادیر ورودی به این صورت می‌باشد (7,5,11,1,-4,2) = (x1,x2,x3,x4,x5,x6). ما به دنبال پیدا کردن پارامترهای (وزن‌ها) هستیم که جواب چنین معادله‌ایی را حداکثر (maximize) کند. ایده به حداکثر رساندن چنین معادله‌ایی به نظر ساده می‌رسد، ورودی مثبت با بزرگترین عدد مثبت ممکن ضرب شود و عدد منفی نیز با کوچکترین عدد منفی ممکن ضرب شود. اما ایده‌ایی که ما درصدد اجرای آن هستیم این است که چگونه الگوریتم ژنتیک این کار را انجام دهد تا بدانیم بهتر است از وزن مثبت با اعداد مثبت در ورودی استفاده شود یا وزن‌های منفی با اعداد منفی در ورودی مورد استفاده قرار بگیرد. بگذارید پیاده‌سازی الگوریتم ژنتیک را شروع کنیم.در ابتدا، اجازه دهید یک لیست با ۶ ورودی و یک متغییر جهت ذخیره تعداد وزن‌ها ایجاد کنیم:# Inputs of the equation.
 equation_inputs = [4,-2,3.5,5,-11,-4.7]
 # Number of the weights we are looking to optimize.
 num_weights = 6مرحله بعد تعریف جمعیت اولیه است. بر اساس تعداد وزن‌ها، هر کروموزوم (راه‌حل یا فرد نیز گفته می‌شود) در جمعیت دارای ۶ ژن است که به ازای هر وزن یک ژن داریم. اما سوال اینجایت که برای هر جمعیت چند راه‌حل وجود دارد؟ هیچ مقدار ثابتی برای آن وجود ندارد و ما می‌توانیم مقدار متناسب را با توجه به مسئله خود انتخاب کنیم. اینکار را می‌توانیم در کد قرار دهیم تا بتوانیم تغییرش دهیم.در مرحله بعد، ما یک متغییر ایجاد می‌کنیم که تعداد راه‌حل‌ها در هر جمعیت را در اختیارمان می‌گذارد. متغییر بعدی برای ذخیره اندازه جمعیت است و در نهایت متغییری جهت نگه داری جمعیت اولیه ایجاد می‌کنیم.import numpy

sol_per_pop = 8# Defining the population size.

pop_size = (sol_per_pop,num_weights) # The population will have sol_per_pop chromosome where each chromosome has num_weights genes.

#Creating the initial population.

new_population = numpy.random.uniform(low=-4.0, high=4.0, size=pop_size)بعد از وارد کردن کتابخانه numpy، ما می‌توانیم با استفاده تابع numpy.random.uniform جمعیت اولیه را به صورت تصادفی ایجاد کنیم.شکل آن به صورت (6,8)  خواهد بود. این به معنی ۸ کروموزوم است که هرکدام ۶ ژن (یکی برای هر وزن) دارند. پس از اجرای کد بالا، جمعیت به شرح زیر است:جمعیت اولیهتوجه داشته باشید که داده‌ها به صورت تصادفی تولید می‌شوند بنابراین با اجرای دوباره کد داده‌ها تغییر می‌کنند.بعد از آماده‌سازی جمعیت، مرحله بعدی با توجه به روندنما، نوشتن تابع برازش(fitness) است. ما قصد داریم بهترین افراد را از جمعیت کنونی به عنوان والد برای جفت‌گیری انتخاب کنیم.در مرحله بعد با استفاده از عملگرهای (crossover and mutation) فرزندان (نسل بعدی) را تولید می‌کنیم.این کار با استفاده از فرزندان و والدین انجام می‌شود. و این مراحل برای تعداد نسل‌هایی که می‌خواهدی تولید شوند تکرار می‌شود. کد بعدی این مراحل را پیاده‌سازی می‌کند:import ga

num_generations = 5

num_parents_mating = 4
for generation in range(num_generations):
     # Measuring the fitness of each chromosome in the population.
     fitness = ga.cal_pop_fitness(equation_inputs, new_population)
    # Selecting the best parents in the population for mating.
     parents = ga.select_mating_pool(new_population, fitness, num_parents_mating)                               
 
     # Generating next generation using crossover.
     offspring_crossover = ga.crossover(parents,
                                        offspring_size=(pop_size[0]-parents.shape[0], num_weights))
 
     # Adding some variations to the offsrping using mutation.
     offspring_mutation = ga.mutation(offspring_crossover)
# Creating the new population based on the parents and offspring.
     new_population[0:parents.shape[0], :] = parents
     new_population[parents.shape[0]:, :] = offspring_mutationتعداد نسل های تعریف شده در کد ۵ است که برای دیدن نتایج تمامی نسل‌ها در این آموزش کافی به نظر می‌رسد. یک ماژول به نام GA‌ وجود دارد که توابع پیاده‌سازی الگوریتم ژنتیک در آن قرار دارد.اولین مرحله این است که مقدار برازش (fitness value)  برای هر راه‌حل در بین جمعیت را با استفاده از تابع ga.cal_pop_fitness  محاسبه کند. کد این تابع در ماژول GA به صورت زیر است:def cal_pop_fitness(equation_inputs, pop):
     # Calculating the fitness value of each solution in the current population.
     # The fitness function calculates the sum of products between each input and its corresponding weight.
     fitness = numpy.sum(pop*equation_inputs, axis=1)
     return fitnessپارامترهای ورودی تابع برازش شامل جمعیت و مقادیر ورودی معادله(x1 تا x6)  می‌باشد.  این تابع هر مقدار ورودی معادله را با ژن مربوطه(وزن) ضرب می‌کند و در نهایت با هم جمع می‌کند. با توجه به تعداد راه‌حل‌ها (کروموزوم) در هر جمعیت، تعدادی SOPs (مجموع حاصلضرب) وجود خواهد داشت. پس با توجه به مقدار متغییر sol_per_pop که قبلا مقدار ۸ قرار داده‌ایم، مقادیر بازگشتی از تابع برازش ما  ۸ تا خواهد بود.توجه داشته باشید که هرچه مقدار برازش بالاتر باشد، راه‌حل بهتر خواهد بود.بعد از محاسبه مقادیر برازش برای تمام راه‌حل‌ها، گام بعدی انتخاب بهترین آن‌ها به عنوان والد است. این کار را با استفاده از تابع ga.select_mating_pool انجام می‌دهیم. پارامترهای این تابع شامل جمعیت،مقادیر برازش، و تعداد والد مورد نیاز است و خروجی این تابع والدهای انتخاب شده می‌باشد. این تایع در ماژول GA به صورت زیر پیاده‌سازی شده است:def select_mating_pool(pop, fitness, num_parents):    # Selecting the best individuals in the current generation as parents for producing the offspring of the next generation.    parents = numpy.empty((num_parents, pop.shape[1]))    for parent_num in range(num_parents):        max_fitness_idx = numpy.where(fitness == numpy.max(fitness))        max_fitness_idx = max_fitness_idx[0][0]        parents[parent_num, :] = pop[max_fitness_idx, :]        fitness[max_fitness_idx] = -99999999999    return parentsبر اساس تعداد والدین مورد نیاز، همانطور که در متغییر num_parents_mating مشخص کردیم، این تابع یک آرایه خالی برای نگه داشتن آن‌ها ایجاد می‌کند.parents = numpy.empty((num_parents, pop.shape[1]))با توجه به جمعیت فعلی، این تابع ایندکس بالاترین مقدار برازش را بدست می‌آورد.  بهترین راه‌حل برای انتخاب با توجه به این خط از کد بدست می‌آید:max_fitness_idx = numpy.where(fitness == numpy.max(fitness))برای بازیابی راه‌حلی که از این مقدار برازش برگزیده (با توجه به ایندکس بدست آمده) از کد دستوری زیر استفاده می‌کنیم:parents[parent_num, :] = pop[max_fitness_idx, :]برای جلوگیری از انتخاب مجدد چنین راه‌حلی، مقدار برازش را روی مقدار بسیار کمی تنظیم می‌کنیم که احتمالا  مجددا انتخاب نخواهد شد. این مقدار 99999999999− است. در نهایت آرایه‌ای از والدین انتخاب شده به عنوان مقدار بازگشتی تابع برگردانده می‌شود. که مطابق مثال به شرح زیر خواهد بود:توجه داشته باشید که این چهار والد بر اساس مقادیر برازش به ترتیب (18.24112489, 17.0688537, 15.99527402,  14.40299221) بهترین افراد در جمعیت فعلی هستند.گام بعدی استفاده از والدین انتخاب شده برای جفت‌گیری به منظور تولید فرزندان است.عملیات جفت‌گیری با عملگر برش (crossover) شروع می‌شود. تابع ga.crossover این عملیات را انجام می‌دهد. پارامترهای ورودی این تابع، والدین و اندازه فرزندان است.از اندازه فرزندان برای شناخت تعداد فرزندانی که باید از والدین تولید شوند استفاده می‌کنیم.این تابع در ماژول GA به صورت زیر پیاده‌سازی شده است.def crossover(parents, offspring_size):
     offspring = numpy.empty(offspring_size)
     # The point at which crossover takes place between two parents. Usually, it is at the center.
     crossover_point = numpy.uint8(offspring_size[1]/2)
 
     for k in range(offspring_size[0]):
         # Index of the first parent to mate.
         parent1_idx = k%parents.shape[0]
        # Index of the second parent to mate.
        parent2_idx = (k+1)%parents.shape[0]
        # The new offspring will have its first half of its genes taken from the first parent.
        offspring[k, 0:crossover_point] = parents[parent1_idx, 0:crossover_point]
        # The new offspring will have its second half of its genes taken from the second parent.
        offspring[k, crossover_point:] = parents[parent2_idx, crossover_point:]
     return offspringتابع با ایجاد یک آرایه خالی بر اساس اندازه فرزندان به صورت زیر شروع می‌شود:offspring = numpy.empty(offspring_size)از آنجایی که ما از برش تک نقطه‌ایی استفاده می‌کنیم، باید نقطه‌ای را که در آن می‌خواهیم برش اتفاق بیفتد را مشخص کنیم. این نقطه برای تقسیم کردن راه‌حل به دو نیمه مساوی استفاده می‌شود و به صورت زیر پیاده‌سازی شده است:crossover_point = numpy.uint8(offspring_size[1]/2)سپس باید دو والد را برای انجام عمل برش انتخاب کنیم. شاخص‌های این والدین مطابق با این دو خط در کد انتخاب می‌شوند:parent1_idx = k%parents.shape[0]
parent2_idx = (k+1)%parents.shape[0]والدین به روشی مشابه حلقه انتخاب می‌شوند.در ابتدا اندیس‌های ۰ و ۱ برای تولید فرزند انتخاب می‌شوند، اگر هنوز ظرفیت تولید فرزند وجود داشته باشد، والدین با اندیش ۱ و ۲ را برای تولید فرزند انتخاب می‌شوند. اگر به فرندان بیشتر نیاز باشد پس والدین با اندیس ۲ و ۳ را برای این کار انتخاب می‌کنیم. اندیس ۳ والد آخر ما است، اگر بازهم نیاز به تولید فرزند داریم پس والدین را با اندیس ۳ و ۰ را انتخاب می‌کنیم و الاآخر.راه‌حل‌ها پس از اعمال عملگر برش روی والد در متغییر فرزندان ذخیره می‌شوند که به شرح زیر است:گام بعدی اعمال عمگر پرش (mutation) روی نتایج ذخیره شده در متغییر فرزندان است. این کار با استفاده از تابع ga.mutation که در ماژول GA قرار دارد انجام می‌شود. پارامتر ورودی این تابع  فرزندانی که با استفاده از عملگر برش بدست آمده‌اند می‌باشد و پس از اعمال عملگر جهش یکنواخت فرزندان را به عنوان خروجی برمی‌گرداند.کد این تابع به شرح زیر می‌باشد:def mutation(offspring_crossover):
    
    # Mutation changes a single gene in each offspring randomly.

     for idx in range(offspring_crossover.shape[0]):

         # The random value to be added to the gene.

         random_value = numpy.random.uniform(-1.0, 1.0, 1)
         offspring_crossover[idx, 4] = offspring_crossover[idx, 4] + random_value
    return offspring_crossoverاین حلقه به ازای هر فرزند اجرا می‌شود به اینصورت که یک عدد تصادفی یکنواخت در بازه -۱ تا ۱ ایجاد می‌شود.random_value = numpy.random.uniform(-1.0, 1.0, 1)چنین عدد تصادفی پس از این خط با شاخص 4 فرزندان به ژن اضافه می شود:offspring_crossover[idx, 4] = offspring_crossover[idx, 4] + random_valueتوجه داشته باشید که این شاخص می تواند به هر شاخص دیگر تغییر یابد. فرزندان پس از اعمال جهش به شرح زیر است:چنین نتایجی  توسط تابع برمی‌گردد و  به متغیر offspring_crossover اضافه می‌شود.در این مرحله ، ما 4 فرزند از 4 والدین منتخب با موفقیت تولید کردیم و آماده هستیم تا جمعیت جدید از نسل بعدی را ایجاد کنیم.توجه داشته باشید که GA یک روش بهینه سازی مبتنی بر تصادف است. سعی می شود با اعمال برخی تغییرات تصادفی روی آنها ، راه حلهای فعلی را ارتقا دهد. از آنجا که چنین تغییراتی تصادفی هستند ، ما مطمئن نیستیم که آنها راه حل های بهتری را ارائه می دهند. به همین دلیل ، ترجیح داده می شود بهترین راه حل های قبلی (والدین) در جمعیت جدید حفظ شود. در بدترین حالت وقتی همه فرزندان جدید نسبت به والدین از این بدتر باشند ، ما به استفاده از چنین والدینی ادامه خواهیم داد. در نتیجه تضمین می کنیم که نسل جدید حداقل نتایج خوب قبلی را حفظ کرده و بدتر نمی شود. جمعیت جدید 4 راه حل اول خود را از والدین قبلی خواهد داشت. 4 راه حل آخر از فرزندان حاصل از اعمال متقاطع و جهش حاصل می شود:new_population[0:parents.shape[0], :] = parents
new_population[parents.shape[0]:, :] = offspring_mutationبا محاسبه برازش کلیه راه حل ها (والدین و فرزندان) از نسل اول ، برازش آنها به شرح زیر است:بالاترین برازش قبلی 18.24112489 بود اما اکنون 31.7328971158 است. این بدان معنی است که تغییرات تصادفی به سمت یک راه حل بهتر حرکت کردند. این عالی است. اما با گذشت نسل های بیشتری می توان چنین نتایج را افزایش داد. در زیر نتایج هر مرحله برای 4 نسل دیگر آورده شده است:بعد از 5 نسل فوق ، بهترین نتیجه حال حاضر دارای برازشی برابر با 44.8169235189 در مقایسه با بهترین نتیجه پس از نسل اول که 18.24112489 است.بهترین راه حل دارای وزن های زیر است:برداشتی آزاد از مقاله زیر:https://towardsdatascience.com/genetic-algorithm-implementation-in-python-5ab67bb124a6</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Sun, 26 Jul 2020 09:01:17 +0430</pubDate>
            </item>
                    <item>
                <title>نکاتی در مورد یادگیری‌های تنبل و کوشا در طبقه‌بندی داده</title>
                <link>https://dataio.ir/نکاتی-در-مورد-یادگیریهای-تنبل-و-کوشا-در-طبقهبندی-داده-xgevegh7m5rx</link>
                <description>الگوریتم‌های طبقه‌بندی (Classification) را می‌توان از منظر روش یادگیری روی داده‌های آموزشی، به ۲ گروه زیر دسته‌بندی کرد.یادگیری تنبل (Lazy Learner) یادگیری کوشا (Eager Learner) اکثر الگوریتم‌های طبقه‌بندی از روش یادگیری کوشا استفاده می‌کنند. یادگیری کوشا به این صورت عمل می‌کند که با استفاده از داده‌های آموزشی(Train) مدل طبقه‌بندی را می‌سازد، سپس این مدل، برای ارزیابی داده‌های آزمایشی(Test) مورد استفاده قرار می‌گیرد. اگر نتایج ارزیابی رضایت‌بخش باشد، از مدل بدست‌آمده جهت پیش‌بینی طبقه‌بند(classifications) داده‌های ناشناخته ورودی استفاده می‌شود.از این رو یادگیری کوشا پیش از این، بیشتر کار خود را در تدوین مدل انجام داده‌اند.یادگیری کوشا را می‌توان به این صورت نیز تعریف کرد :این متدها را چون تعمیم را قبل از مواجهه با نمونه جدید انجام می‌دهند کوشا می‌نامند.از طرف دیگر یادگیری تنبل هیچ مدلی را قبل از گرفتن داده‌های ناشناخته از ورودی نمی‌سازد و منتظر داده‌های طبقه‌بندی نشده می‌ماند و پس از دریافت شروع به ساخت مدل پیش‌بینی می‌کند.به دلیل اینکه به ازای هر پیش‌بینی داده ورودی باید کل مدل از اول ساخته شود، بنابراین می‌توان گفت یاگیری تنبل زمان زیادی صرف می‌کند.یادگیری تنبل را می‌توان به این صورت نیز تعریف کرد :این متدها برای اینکه چگونگی تعمیم روی نمونه‌های آموزشی را به زمانی که نمونه‌ی جدید ارائه می‌شود واگذار می‌کنند، تنبل خوانده می‌شود.آیا آنچه الگوریتم‌های تنبل می‌توانند یاد بگیرند با آنچه الگوریتم‌های کوشا می‌توانند یاد بگیرند تفاوت چشم‌گیری دارد؟بیاید ابتدا ۲ نوع تفاوت را مشخص کنیم. تفاوت در زمان محاسباتتفاوت در طبقه‌بندهای تولید شده برای نمونه‌های جدیدتفاوت‌های واضحی در زمان محاسبه‌ی الگوریتم‌های یادگیری تنبل و کوشا وجود دارد. برای مثال، متدهای تنبل در طول آموزش محاسبات کمتری لازم دارند. اما در هنگام پیش‌بینی ویژگی هدف برای نمونه‌ی جدید محاسبات زیادی انجام می‌دهند.سوال اساسی‌تر این است که آیا تفاوت‌های اساسی‌ای در بایاس‌های استقرایی الگوریتم‌های تنبل و الگوریتم‌های کوشا وجود دارد. از این نظر تفاوت‌های زیر بین متدهای تنبل و کوشا وجود دارد.در متدهای تنبل گاهی تصمیم‌گیری برای چگونگی تعمیم بر روی داده‌های آموزشی به نمونه‌ی آموزشی ارائه شده نیز وابسته می‌شود.متدهای کوشا این وابستگی را نمی‌توانند داشته باشند، زمانی که یک متد کوشا با یک نمونه جدید مواجه می‌شود، تخمین جهانی را انجام داده است.نکته کلیدی این است که یادگیری تنبل می‌تواند با ترکیب تخمین‌های موضعی (Local) تابع هدف را یاد بگیرد، در حالی که یادگیر کوشا فقط یک تخمین جهانی (Global) را با توجه به نمونه آموزشی یاد می‌گیرد. این تفاوت بین یادگیری کوشا و تنبل به تفاوت بین تخمین موضعی و جهانی تابع هدف بر می‌گردد.به طور خلاصه، متدهای تنبل حق انتخاب بین فرضیه‌ها یا تخمین‌های موضعی تابع هدف برای هر نمونه‌ی جدید را دارند. در حالی که متدهای کوشا محدودترند و باید با استفاده از یک فرضیه کل فضای نمونه را پوشش دهند. البته متدهای کوشا نیز می‌توانند از ترکیبی از تخمین‌های موضعی استفاده کنند(مانند شبکه‌های RBF). با این وجود،حتی این ترکیب تخمین‌های موضعی قابلیت کامل متدهای تنبل در تغییر بر اساس نمونه‌ی آموزشی مجهول را به یادگیر کوشا نمی‌دهد.</description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Sun, 26 Apr 2020 13:48:47 +0430</pubDate>
            </item>
                    <item>
                <title>مبانی یادگیری ماشین با الگوریتم K-نزدیکترین همسایگان</title>
                <link>https://dataio.ir/مبانی-یادگیری-ماشین-با-الگوریتم-k-نزدیکترین-همسایگان-h0bakaksew8a</link>
                <description>الگوریتم k-نزدیکترین همسایگان (KNN) یک الگوریتم یادگیری ماشین نظارت شده است که می‌تواند برای حل مسائل طبقه بندی و رگرسیون استفاده شود. در ادامه به تشریح آن می‌پردازیم.یادگیری نظارت شده در مقابل یادگیری بدون نظارتالگوریتم یادگیری ماشین نظارت شده (بر خلاف یک الگوریتم یادگیری ماشین بدون نظارت)  به داده های ورودی دارای برچسب متکی است تا بتواند به تابع یاد دهد که در هنگام برخورد با  داده‌های جدید بدون برچسب ، خروجی مناسبی را تولید کند.تصور کنید که کامپیوتر یک کودک است و ما سرپرست آن هستیم (به عنوان مثال والدین ، سرپرست یا معلم) و ما می خواهیم کودک (رایانه) یاد بگیرد که خوک چگونه به نظر می رسد. ما چندین تصویر مختلف را به کودک نشان خواهیم داد که برخی از آنها خوک و بقیه می توانند از هر چیزی (گربه ، سگ و غیره) باشند.وقتی خوک را می بینیم ، فریاد می زنیم: &quot;خوک!&quot; وقتی خوک نیست ، ما فریاد می زنیم &quot;نه، خوک نیست!&quot; بعد از چندین بار انجام این کار به همراه کودک ، ما از کودک یک عکس نشان می دهیم و از او درباره  &quot;خوک می پرسیم؟&quot;  (بیشتر اوقات) کودک بسته به نوع تصویر به درستی خواهند گفت &quot;خوک!&quot; یا &quot;نه ، خوک نیست!&quot;  این یادگیری ماشین نظارت شده است.خوکبرای حل مسائل  طبقه بندی یا رگرسیون از الگوریتم های یادگیری ماشین نظارت شده استفاده می شود.خروجی یک مسئله طبقه بندی یک مقدار گسسته است. به عنوان مثال، عبارت: &quot;آناناس را روی پیتزا دوست دارد&quot; و &quot;آناناس را روی پیتزا دوست ندارند&quot; گسسته هستند. حد وسطی وجود ندارد. همچنین مثال فوق در مورد  آموزش کودک برای شناسایی خوک  نیز نمونه دیگری از یک مسئله طبقه بندی است.جدول افرادی که آناناس روی پیتزا را دوست دارند به تفکیک سناین تصویر یک مثال ساده از داده طبقه بندی را نشان می دهد. ما یک پیش بینی کننده (یا مجموعه از پیش بینی کننده ها) و یک برچسب داریم. با توجه به تصویر ما سعی می کنیم پیش بینی کنیم که آیا کسی آناناس را روی پیتزا خود دوست دارد(1) یا نه (0) این کار را بر اساس سن‌شان(پیش‌بینی‌کننده) انجام می دهیم.نمایش دادن خروجی(برچسب) در یک الگوریتم طبقه‌بندی می‌تواند به صورت یک عدد صحیح مانند 1، 1- و 0 باشد. این یک روش استاندارد جهت نمایش خروجی است.توجه کنید که این اعداد تنها برای نمایش خروجی هستند و نباید عملیات ریاضی بر روی آنها انجام شود زیرا انجام چنین کاری بی‌معنی است.یک لحظه تصور کنید که جمع عبارات &quot;آناناس را دوست دارد&quot; + &quot;آناناس را دوست ندارد&quot; چه معنی می‌دهد؟ دقیقا. ما نمی‌توانیم آنها را با هم جمع کنیم، بنابراین اعدادی که تنها برای نمایش خروجی (برچسب) استفاده می‌شوند.خروجی یک مسئله رگرسیون بر خلاف مسئله طبقه‌بندی دارای یک عدد واقعی (صحیح یا اعشار) است. به عنوان مثال ، می‌توان از داده های موجود در جدول زیر استفاده کرد تا وزن افراد را با توجه به قد آنها تخمین زد.جدول بخشی از دیتاست SOCRداده های به کار رفته در تحلیل رگرسیون شبیه به داده های نشان داده شده در تصویر فوق خواهند بود. ما یک متغیر مستقل (یا مجموعه ای از متغیرهای مستقل)داریم و یک متغیر وابسته (چیزی که می خواهیم با توجه به متغیرهای مستقل خود حدس بزنیم) داریم. به عنوان مثال: می‌توان گفت ارتفاع متغیر مستقل است و وزن متغیر وابسته است.همچنین ، معمولا هر سطر با نام‌ یک نمونه، مشاهده یا نقطه داده خوانده می شود ، در حالی که هر ستون اغلب با نام پیش بینی کننده ، بعد ، متغیر مستقل یا ویژگی نامیده می شود.ستون برچسب شامل متغییرهای مستقل نمی‌شود.در الگوریتم یادگیری ماشین بدون نظارت داده‌های ورودی بدون هیچ برچسبی استفاده می‌شوند ، به عبارت دیگر، هیچ معلمی (برچسب) به کودک (رایانه) درست یا اشتباه را نمی‌گوید تا بتواند خود را اصلاح کند.برخلاف یادگیری نظارت شده که سعی در یادگیری تابعی دارد که به ما امکان می دهد با توجه به داده های جدید بدون برچسب، پیش بینی هایی را انجام دهیم ، یادگیری بدون نظارت سعی می کند ساختار اولیه داده ها را یاد بگیرد تا بینش بیشتری از داده ها به ما بدهد.الگوریتم K-نزدیکترین همسایهالگوریتم KNN فرض می‌کند که موارد مشابه نزدیک به یکدیگر هستند.                                                           &quot;کبوتر با کبوتر، باز با باز&quot;نمایش داده‌های شبیه به هم که معمولا در نزدیک یکدیگر هستنددر تصویر بالا توجه کنید که بیشتر اوقات ، نقاط داده های مشابه نزدیک به یکدیگر هستند. الگوریتم KNN ایده شباهت (فاصله ، مجاورت یا نزدیکی نیز گفته می‌شود) را با برخی از محاسبات ریاضی(محاسبه فاصله بین نقاط در نمودار) که در کودکی یاد گرفته ایم ، بدست می‌آورد.توجه: درک چگونگی محاسبه فاصله بین نقاط بر روی نمودار قبل از یادگیری الگوریتم KNN  ضروری است. اگر در مورد نحوه انجام این محاسبات ناآشنا هستید یا به آن احتیاج دارید ، &quot;فاصله بین دو نقطه&quot; را به طور کامل بخوانید ، و دوباره برگردید.روش های دیگری نیز برای محاسبه فاصله وجود دارد و بسته به مسئله‌ایی که ما حل می کنیم ، یک راه ممکن است ارجح باشد. با این حال ، فاصله مستقیم (که به آن فاصله اقلیدسی نیز گفته می شود) یک انتخاب محبوب و آشناست.الگوریتم KNNبارگذاری داده هامقداردهی اولیه K برای انتخاب تعداد همسایگانبرای هر نمونه از داده هافاصله بین نمونه پرس‌وجو و نمونه فعلی از داده ها را محاسبه کنیدفاصله و اندیس داده نمونه را به مجموعه مرتب شده اضافه كنيدمجموعه فاصله ها و شاخص های مرتب شده را از کوچکترین تا بزرگترین (به ترتیب صعودی) بر اساس فاصله‌ها مرتب کنیداولین ورودی های K را از مجموعه مرتب شده انتخاب کنیدبرچسب های ورودی K انتخاب شده را دریافت کنیددر صورت رگرسیون ، میانگین برچسب های K را برگردانیددر صورت طبقه بندی ، حالت برچسب های K را برگردانیداجرای KNN  https://gist.github.com/onelharrison/373d81dc21d43c3126f15d2d0867d80a انتخاب مقدار مناسب برای Kبرای انتخاب K مناسب برای داده های خود ، الگوریتم KNN را چندین بار با مقادیر مختلف K اجرا می کنیم و  مقدار Kایی را انتخاب می کنیم که مقدار خطا را کاهش می دهد و در عین حال توانایی الگوریتم را برای انجام دقیق پیش بینی ها در هنگام مواجهه با داده‌های جدیدافزایش می‌دهد.نکاتی که باید به خاطر داشته باشید: هرچه مقدار K را کاهش می‌دهیم و به 1 نزدیک می‌شود ، پیش‌بینی های ما از پایداری کمتری برخوردار می‌شود. برای مثال:  مقدار K = 1 را تصور کنید و ما یک نقطه پرس و جو داریم که توسط چندین قرمز و یک رنگ سبز احاطه شده است، منطقی است که ما فکر کنیم که نقطه پرس و جو به احتمال زیاد قرمز است ولی به‌خاطر اینکه نزدیک‌ترین همسایه به نقطه پرس‌وجو  رنگ سبز است  و همچنین مقدار k=1 است به طور اشتباه نقطه پرس و جو را سبز پیش بینی می کند.برعکس ، با افزایش مقدار K ، پیش بینی های ما به دلیل رای اکثریت / میانگین‌گیری ​​، پایدارتر می‌شوند. بنابراین ، به احتمال زیاد پیش بینی های دقیق تری انجام می دهیم.البته تا یک مقدار خاصی از K و بعد از آن مقدار ما شاهد افزایش فزاینده خطاها هستیم. در این مرحله است که می دانیم مقدار K را خیلی دور کرده ایم.  در مواردی که در بین برچسب ها اکثریت آراء را کسب می کنیم (مثلاً انتخاب حالت در یک مسئله طبقه بندی) ، ما معمولاً K را  یک عدد فرد اتخاب می‌کنیم رای حداکثری داشته باشیم. مزایا یکی از ساده‌ترین و آسان‌ترین الگوریتم جهت پیاده‌سازی است. نیازی به ساختن مدل ، تنظیم چندین پارامتر یا پیش فرض های اضافی نیست. الگوریتم همه کاره است. این می تواند برای طبقه بندی ، رگرسیون و جستجو استفاده شود (همانطور که در بخش بعدی خواهیم دید).معایببا افزایش تعداد نمونه ها و یا متغیرهای پیش بینی کننده / مستقل ، الگوریتم بطور قابل توجهی کندتر می‌شود.الگوریتم KNN در عملعیب اصلی KNN این است که با افزایش حجم داده به صورت قابل توجهی کند می‌شود و باعث می شود در محیط هایی که پیش بینی ها باید به سرعت انجام شود، غیرعملی شود. علاوه بر این ، الگوریتم های سریع‌تری وجود دارند که می توانند نتایج طبقه بندی و رگرسیون دقیق تری داشته باشند.با این حال، به شرط آنكه از منابع محاسباتی كافی برخوردار باشید، KNN  می تواند در حل مسائلی كه با استفاده از معیار مشابهت اشیاء انجام می‌شود، مفید باشد. نمونه‌ای از  استفاده از الگوریتم KNN در سیستم های توصیه‌کننده ( KNN-search) است.خلاصهالگوریتم k-نزدیکترین همسایگان (KNN) یک الگوریتم یادگیری ماشین ساده و نظارت شده است که می تواند برای حل هر دو مسئله طبقه بندی و رگرسیون استفاده شود. پیاده سازی و درک آن آسان است ، اما با بزرگ شدن اندازه داده‌های مورد استفاده کاهش سرعت قابل توجهی در آن به وجود می‌آید.الگوریتم KNN با پیدا کردن فاصله بین یک پرس و جو و تمام نمونه های موجود در داده و انتخاب تعداد نمونه‌های نزدیک مشخص شده به پرس و جو (توسط مقدار K) ، کار می کند ، سپس به بیشترین برچسب  (در صورت طبقه بندی) یا به میانگین برچسب ها (در مورد رگرسیون) رای می دهد.در مورد طبقه بندی و رگرسیون ، دیدیم که انتخاب درست K برای داده های ما با امتحان کردن چندین K و انتخاب یکی از مواردی که بهترین عملکرد را دارد ، انجام می شود.برداشتی آزاد از مقاله : https://towardsdatascience.com/machine-learning-basics-with-the-k-nearest-neighbors-algorithm-6a6e71d01761 </description>
                <category>م. فتحی</category>
                <author>م. فتحی</author>
                <pubDate>Sun, 26 Apr 2020 08:13:09 +0430</pubDate>
            </item>
            </channel>
</rss>