#import "assets/typst/templates/note.typ": note
#import "assets/typst/tools/tool.typ"

#let red_color = rgb(200, 0, 0, 255)
#let orange_color = rgb(220, 100, 0, 255)
#let yellow_color = rgb(130, 130, 0, 255)
#let green_color = rgb(0, 120, 0, 255)
#let blue_color = rgb(0, 100, 200, 255)
#let dark_blue_color = rgb(0, 0, 200, 255)
#let purple_color = rgb(150, 0, 150, 255)
#let gold_color = rgb(255, 215, 0)
#let brown_color = rgb(125, 50, 0)

#let dir = rtl

#show: doc => note(
    doc,
    paper: "a4",
    black_and_white: false,
    flipped: false,
    first_page_font_size: 10pt,
    font_size: 8pt,
    image_path: "../../images/basu_logo_logosource.ir.svg",
    image_width: 12em,
    topic: "جزوه درس یادگیری ماشین",
    authors_name: ("<NAME>"),
    professors_name: ("<NAME>"),
    faculty: "مهندسی کامپیوتر",
    date: [
        نیم سال تحصیلی #text(dir: ltr)[۱۴۰۳-۱]
    ],
    version: "v0.6.0",
    phase: none,
    info_color: blue_color,
    no_responsibility: true
)

#tool.introduce_sections()

#colbreak()

#tool.title("درباره کلاس", color: blue_color)
- قواعد و مقررات:
    + حضور در کلاس اجباری است.
    + انجام تمرین ها و پروژه ها در زمان مشخص شده.
    + باید برایشان گزارش نوشته شود.
    + کزارش شامل موارد زیر است:
        + تعریف مسأله
        + پیاده سازی
        + اجرای نمونه
    + میان ترم و پایان ترم کتبی خواهیم داشت.

- راه های ارتباطی:

    - آیدی تلگرام: #text(dir: ltr)[mansoorm\@]

    - کانال تلگرام: #text(dir: ltr)[mansoorm\_courses\@]
    - ایمیل ها:
        + <EMAIL>
        + <EMAIL>
#tool.title("فهرست مطالب", color: red_color)
#outline(title: none, indent: auto)

#colbreak()

= جلسه اول
== یادگیری ماشین
#tool.double_section()[
    #tool.simple_context()[
        یادگیری ماشین زیر شاخه ای از هوش مصنوعی است.
    ]
][
    #tool.tip()[
        ملاک درست بودن پاسخ، دادن جواب مورد انتظار کاربر است.
    ]
]

=== هوش
#tool.double_section()[
    #tool.definition()[
        هوش: معیار اندازه گیری میزان انطباق پاسخ با انتظار
        #v(2em)
    ]
][
    #tool.example()[
        دو عدد ادامه دنباله زیر را مشخص کنید.

        #text(dir: ltr)[۱, ۲, ۵, ۷, ۱۰, ..., ...]
    ]
]

#tool.true_answer()[
    در این مثال، معیار طراح سوال تعداد Ending point های هر عدد می باشد. بنابراین جواب به صورت زیر است:

    #text(dir: ltr)[۱, ۲, ۵, ۷, ۱۰, #text(fill: blue_color)[۱۲], #text(fill: blue_color)[۱۷]]
]

=== هوش مصنوعی
#tool.definition()[
    هوش مصنوعی: توانمندی کامپیوتر ها (ماشین ها) برای تولید پاسخ های مورد انتظار انسان.
]

#tool.double_section()[
    #tool.tip()[
        هوش مصنوعی از دید کاربر تعریف می شود.
    ]
][
    #tool.definition()[
        ماشین (کامپیوتر): به ابزاری که قابل برنامه ریزی است می گوییم.
    ]
]

=== رویکرد های هوش مصنوعی
==== مبتنی بر قانون (Rule based approach)
#tool.double_section()[
    #tool.definition()[
        در این روش مثلا از یک آدم متخصص در حوزه ای سوال می شود که چگونه کارش را انجام می دهد.
        بر این اساس یک سری پارامتر استخراج می کنیم و بر اساس آن ها برنامه ای را می نویسیم.
    ]
][
    #tool.example()[
        تشخیص انواع چند ضلعی ها #sym.arrow.l این که چند ضلعی مورد نظر مثلث متساوی الساقین است یا مربع است یا پنج ضلعی منتظم است یا ۱۰۰ ضلعی منتظم است یا #sym.dots .
    ]
]

#tool.true_answer()[
    روش تشخیص: به کمک اندازه زاویه ها و فاصله نقاط هر چند ضلعی، می توان نوع آن چند ضلعی را فهمید.

    مشکل روش: وقتی تعداد اضلاع و زاویه ها بالا رود، مشکل می شود.
]

==== مبتنی بر یادگیری (Learning based approach)
#tool.double_section()[
    #tool.definition()[
        در این روش الگوریتمی به کامپیوتر داده می شود تا خودش قاعده و قانون مسأله را به دست آورد.
    ]
][
    #tool.example()[
        تشخیص هواپیما #sym.arrow.l تعداد زیادی نمونه می آوریم.
        #v(1.55em)
    ]
]

#tool.true_answer()[
    #tool.custom_figure(
        image("images/ML/01_02.jpg"),
        caption: "نقاط شکل هواپیما را به صورتی که مشخص شده است، شماره گذاری می کنیم."
    )
    کد مرتبط:
    #tool.custom_figure(caption: "تشخیص هواپیما", kind: raw, inset: 1em)[
        ```
        R = {}
        for k = 1 to 16 {
            for j = k + 1 to 16 {
                flag = True
                for image = 1 to 10 {
                    if d_k(image) != d_j(image) {
                        flag = false
                    }
                }
                if flag == true {
                    R = R U <d_k, d_j>
                }
            }
        }               
        ```
    ]
]

#tool.tip()[
    یک مهندس یادگیری ماشین، دو مورد زیر را فراهم می کند:
    + نمونه ها (Examples)
    + الگوی قاعده (Rule template)
]

=== یادگیری (Training)
#tool.definition()[
    یادگیری (Training): فعالیتی که دو ورودی نمونه و الگو و همچنین خروجی قواعد را دارد، گویند.
    
    #tool.custom_figure(
        align(center)[
            #image("images/ML/01_01.png", width: 39%)
        ],
        caption: "گراف مربوط به فعالیت یادگیری",
        inset: 1em
    )
]

= جلسه دوم
#tool.double_section()[
    #tool.tip()[
        کار هایی که مهندس یادگیری ماشین به همراه فرد خبره در حوزه مرتبطش انجام می دهند:
        ML engineer + Domain expert:
        #text(dir: ltr)[
            + Data collection
            + Template building
            + Training
        ]
    ]
][
    #tool.tip()[
        در Machine learning نقش اصلی را ML engineer بر عهده دارد.
        در حالی که در Data mining و Deep learning نقش اصلی بر عهده ماشین است.
        #v(4.8em)
    ]
]

#tool.definition()[
    یادگیری ماشین: یعنی به کامپیوتر ها یاد بدهیم تا مسائل را حل کنند.
]

== مسائل پایه ای یادگیری ماشین
=== Supervised learning
==== Classification

#tool.question()[
    Spam detection در ایمیل:
    فرض کنیم می خواهیم ایمیل های اسپم را از غیر اسپم برای فردی یا سازمانی تشخیص دهیم.
]

#tool.true_answer()[
    مراحل انجام این کار به صورت زیر است:
    + کلی ایمیل جمع می کنیم و آن ها را برچسب گذاری می کنیم.
        مثلا به صورت زیر:

        #tool.custom_figure(caption: "برچسب گذاری ایمیل ها", kind: table, inset: 1em)[
            #table(
                columns: 2,
                inset: 1em,
                stroke: black,
                align: center,
                "Message",
                "Label: Spam",
                "Message 1",
                "Yes",
                "Message 2",
                "No",
                "Message 3",
                "Yes",
                [#sym.dots],
                [#sym.dots],
                "Message N",
                "No"
            )
        ]

    + متن را بررسی می کنیم.
        مثلا به صورت زیر:

        #tool.custom_figure(caption: "بررسی لغت های درون ایمیل ها از نظر اسپم بودن یا نبودن", kind: table, inset: 1em)[
            #table(
                columns: 4,
                inset: 1em,
                stroke: black,
                align: center,
                "Word",
                "F_Yes",
                "F_No",
                "Difference",
                "Rich",
                "56",
                "73",
                "56 - 73 = -17 < 0",
                "Click",
                "123",
                "15",
                "108",
                [#sym.dots.v],
                [#sym.dots.v],
                [#sym.dots.v],
                [#sym.dots.v]
            )
        ]

    در جدول بالا، ستون F_Yes به تعداد ایمیل های اسپمی که در متن آن ها کلمه Rich وجود دارد اشاره می کند و ستون F_No، عکس این قضیه می باشد.

    در نهایت تمامی کلمات در قالب جدول بالا بررسی می شوند.
    این عمل را بار اول خودمان انجام می دهیم.

    توجه: اسپم بودن یا نبودن هر ایمیل مورد نظر است و نه هر کلمه هر ایمیل به صورت جداگانه.

    توجه: هر لغتی که در متن یک ایمیل داشته باشیم، همان یک بار برای متنش حساب می شود و نه بیشتر.
    مثلا یک ایمیلی ۱۰۰ عدد کلمه Click دارد.
    در این حالت می گوییم کلمه Click در این ایمیل آمده است و به تعدادش اشاره نمی کنیم.

    اما چرا اینگونه عمل کردیم؟ چون طبیعت، هموار (Smooth) است.

    در ادامه ۱۰۰ کلمه ای (تعداد دلخواه) که بیشترین تفاضل را دارند، انتخاب کرده و برای یک ایمیلی که می خواهیم بررسی اش کنیم، می گوییم اگر درون این ایمیل، مثلاً بیشتر از ۲۰ کلمه مجزا از این ۱۰۰ کلمه وجود داشت، آن ایمیل، یک ایمیل اسپم است.

    پس به صورت خلاصه به شکل زیر عمل می کنیم:
    #text(dir: ltr)[
        + Collect a set of spam and real (not-spam) messages.
        + Count words in the message.
        + Select top #text(stylistic-set: 2)[100] distincitve (Highly frequent in spams) spam words
        // For a new message or stage???
        + For a new message if M contains more than #text(stylistic-set: 2)[20] distincitve words, It is spam.
    ]

    در نهایت برنامه ای به شکل زیر ساخته خواهد شد:

    #tool.custom_figure(
        image("images/ML/02_01.png"),
        caption: "یک برنامه یادگیری ماشین که یک ورودی و دو خروجی به شکل بالا دارد.",
        inset: 1em
    )

    به این نوع یادگیری ماشین، Classification می گوییم.
]

#tool.example()[
    مثالی در حوزه Classification به صورت زیر آمده است:
    ساخت یک برنامه یادگیری ماشین که Chest X-Ray را به عنوان ورودی بگیرد و بگوید ریه فرد، چقدر درگیر است.
    خروجی برنامه نیز یکی از موارد زیر است:
    #text(dir: ltr)[
        + None
        + Low
        + Mild
        + High
        + Severe
    ]
]

==== Regression
#tool.question()[
    پیش بینی کردن قیمت خانه
]

#tool.true_answer()[
    - گام اول: فرض کنیم قیمت خانه ها به شکل زیر است:

    #tool.custom_figure(caption: "قیمت خانه ها بر اساس مساحت آن ها", kind: table, inset: 1em)[
        #table(
            columns: 2,
            inset: 1em,
            stroke: black,
            align: center,
            "Area",
            "Price",
            [50 $m^2$],
            [100],
            [75 $m^2$],
            [105],
            [75 $m^2$],
            [150],
            [100 $m^2$],
            [220],
            [120 $m^2$],
            [240]
        )
    ]

    برای آن که درک بهتری از جدول بالا داشته باشیم به شکل زیر توجه کنید:

    #tool.custom_figure(
        image("images/ML/02_02.png", width: 70%),
        caption: "تلاش می کنیم معادله ای که تا جای ممکن تمامی نقاط نمودار را پوشش می دهد، پیدا کنیم.",
        inset: 1em
    )

    بر اساس اصل پیوسته بودن طبیعت مشاهده می کنیم که نقاط شکل بالا گویی حول محور آبی حرکت می کنند.

    - گام دوم:

    معادله خط مربوط به خط آبی رنگ را پیدا می کنیم.
    مثلا:
    
    $ "Price = 2" "Area" + epsilon $

    به این گونه مسائل که به دنبال یافتن معادله ای همچون
    
    $ y = f(x) $
    
    برای حل شان می گردیم؛ مسائل Regression می گویند.
]

#tool.list()[
    مسائل پایه ای یادگیری ماشین:
    #text(dir: ltr)[
        + Supervised learning
            + Classification
            + Regression
        + Unsupervised learning
            + Association learning
            + Clustering
            + Distribution learning (Density estimation)
        + Reinforcement learning
            + Reward / Punishment
    ]
]

=== Unsupervised learning
==== Association learning

#tool.question()[
    فروشنده یک مغازه می خواهد به مشتری ای که مثلاً ۴ کالا خریده است، کالای پنجمی را پیشنهاد داده و آن را بفروشد.
    چگونه به او پیشنهاد بدهد؟
]

#tool.true_answer()[
    + داده های گذشته رو بررسی می کنیم.
        مثلا:
        #tool.custom_figure(caption: "کالا های خریده شده توسط مشتری ها", kind: table, inset: 1em)[
            #table(
                columns: 2,
                inset: 1em,
                stroke: black,
                align: center,
                "مشتری ۱",
                "پنیر - [شیر] - [نان]",
                "مشتری ۲",
                "<رب> - تخم مرغ - <نان>",
                "مشتری ۳",
                "[شیر] - رب> - [<نان>]>",
                [#sym.dots.v],
                [#sym.dots.v],
                "مشتری N",
                [#sym.dots]
            )
        ]

    + کالا های با بیشترین تکرار را پیدا می کنیم.
        مثلا:
    
        $ F_1 = "رب - شیر - نان" $

    + کد الگوریتم را به صورت زیر می نویسیم (برای آموزش یا همان Training)):
        #tool.custom_figure(caption: "آموزش مدل برای یافتن کالا های با بیشترین تکرار", kind: raw, inset: 1em)[
            ```
            F_1 = {} F_2 = {}

            for each x in F_1 {
                for each y in F_1 {
                    if <x, y> is frequent {
                        F_2 = F_2 U {<x, y>}
                    }
                }
            }
            ```
        ]

    + در آخر برنامه پیشنهاد کالا را با استفاده از داده هایی که در مرحله قبل به دست آوردیم به صورت زیر می نویسیم و اجرا می کنیم:
        #tool.custom_figure(caption: "برنامه پیشنهاد کالا که از مدل آموزش داده شده، استفاده می کند.", kind: raw, inset: 1em)[
            ```
            for each customer c {
                for each pair <x, y> in F_2 {
                    if c buys x {
                        recommend y
                    }
                }
            }
            ```
        ]

    این مسأله نوعی مسأله در حوزه Association learning می باشد.
]

==== Clustering
#tool.question()[
    در ادامه مسأله قبلی، حالا می خواهیم بدانیم که چگونه مشتری هایی داریم؟ (Grouping customers)
]

#tool.true_answer()[
    بر اساس سبد خرید مشتری ها، آن ها را دسته بندی می کنیم.

    + به صورت زیر سبد ها را دو به دو مقایسه کرده و دسته بندی می کنیم.
        
        داریم:
        $ B_1 , B_2 $

        به کمک فرمول زیر، شباهت بین دو سبد $B_1$ و $B_2$ را به دست می آوریم (علامت قدر مطلق به اندازه مجموعه ها اشاره می کند):
        $ S = abs(B_1 sect B_2) / abs(B_1 union B_2) $
        
        برای نمونه بین مشتری ۱ و مشتری ۲ داریم:
        $ S = abs("نان") / abs("رب - تخم مرغ - پنیر - شیر - نان") = ۱ / ۵ $

        #text(number-width: "proportional")[یعنی سبد خرید مشتری ۱ و مشتری ۲ به میزان ۲۰٪ به یکدیگر شباهت دارند.]

    + به تعداد دلخواه مثلاً ۵ عدد گروه در نظر می گیریم و به صورت زیر عمل می کنیم:
    
        + #text(number-width: "proportional")[فرض کنید ۱۰۰ تا مشتری داریم.
            این مشتری ها را به شکل تصادفی در ۵ گروه ۲۰ تایی تقسیم بندی می کنیم.]
        
        + سپس یکی از مشتری ها را از یک گروهی انتخاب کرده و با همه گروه ها مقایسه می کنیم.
            در نهایت مشتری به گروهی که بیشترین شباهت را با آن دارد، منتقل می شود.
        
        + #text(number-width: "proportional")[اگر این کار را بر روی مشتری ها ادامه دهیم بعد از مدتی به همگرایی خواهیم رسید و ۵ گروه ۲۰ تایی خواهیم داشت که اعضای درون هر گروه به یکدیگر شباهت دارند.]

        اما این دسته بندی چه فایده ای دارد؟
        
        یک نمونه مثال از فایده آن این است که مشتری هایی که در گروه مشترک هستند را بررسی می کنیم چه کالا هایی را خریدند تا آن کالا ها را در یک راهرو کنار هم قرار دهیم.

        این مسئله نمونه ای از مسائل Clustering می باشد.
]

=== Reinforcement learning
==== Reward / Punishment
#tool.question()[
    می خواهیم نحوه بازی کردن شطرنج را آموزش دهیم.
]

#tool.true_answer()[
    فرض کنیم دو بازیکن به نام های بازیکن ۱ و ۲ داریم.
    بازیکن ۲ می خواهد شطرنج را به بازیکن ۱ یاد بدهد.

    + #text(number-width: "proportional")[ابتدا حرکاتی که هر مهره می تواند انجام دهد به بازیکن ۱ گفته می شود.]
    + بازیکن ها شروع به بازی کردن می کنند.
    + #text(number-width: "proportional")[به صورت زیر هر دو بازیکن حرکاتی را انجام می دهند و در نهایت بازیکن ۲ می برد.]
        #tool.custom_figure(caption: "حرکت های بازیکن های ۱ و ۲", kind: table, inset: 1em)[
            #table(
                columns: 2,
                inset: 1em,
                stroke: black,
                align: center,
                "بازیکن ۱",
                "بازیکن ۲",
                [$W_1$],
                [$B_1$],
                [$W_2$],
                [$B_2$],
                [#sym.dots.v],
                [#sym.dots.v],
                [$W_7$],
                [$B_7$]
            )
        ]
    + #text(number-width: "proportional")[وقتی که بازیکن ۱ می بازد، می فهمد مجموعه حرکاتی که انجام داده، بد بوده است و بابت باخت مجازات می شود.]
    + #text(number-width: "proportional")[بازیکن ۱ اینقدر حرکات شانسی مختلف را امتحان می کند تا می برد و بابت برد امتیاز می گیرد.]

    به این صورت بازیکن ۱ بازی شطرنج را یاد می گیرد.

    به این روش که ماشین می تواند از شکست ها (جریمه ها) و برد ها (جایزه ها) یاد بگیرد روش Reward / Punishment می گویند که زیر مجموعه ای از Reinforcement learning می باشد.
]

= جلسه سوم
== مسائل پایه ای یادگیری ماشین (ادامه)
=== Unsupervised learning
==== Distribution learning (Density estimation)
#tool.question()[
    یک فرد سیگاری داریم. این فرد چند سال دارد؟
]

#tool.true_answer()[
    داده ها را جمع آوری کرده و معمولاً به صورت فراوانی نسبی نشان شان می دهیم.

    از تعداد جمعیت ۱۰۰ نفر، سن شان پرسیده می شود و به جدول زیر می رسیم.
    
    #tool.custom_figure(caption: "فراوانی سیگاری بودن افراد در سنین مختلف", kind: table, inset: 1em)[
        #table(
            columns: 3,
            inset: 1em,
            stroke: black,
            align: center,
            "سن\n(Age)",
            "فراوانی\n(Frequency)",
            "فراوانی نسبی\n(Relative frequency)",
            "1",
            "0",
            "0",
            "5",
            "0",
            "0",
            "10",
            "5",
            "0.05",
            "15",
            "15",
            "0.15",
            "20",
            "16",
            "0.16",
            "25",
            "16",
            "0.16",
            "30",
            "16",
            "0.16",
            "50",
            "15",
            "0.15",
            "60",
            "10",
            "0.10",
            "80",
            "5",
            "0.05",
            "90",
            "2",
            "0.02",
            "100",
            "0",
            "0",
            "---",
            "مجموع",
            "---",
            "---",
            "100",
            "---",
        )
    ]

    حالا می خواهیم به این برسیم که مثلاً احتمال اینکه یک آدم ۴۰ ساله سیگاری باشد چقدر است.
    یعنی:
    $ P("Smoking" | "Age" = 40) = space ? $

    راه حل این است که می آییم می بینیم که ۳۰ ساله ها احتمال ۰/۱۶ و ۵۰ ساله ها احتمال ۰/۱۵ را دارند.
    از آن جایی که سن ۴۰ سال بین این دو احتمال است، میانگین شان را برای آن در نظر می گیریم.
    یعنی:
    $ P("Smoking" | "Age" = 40) = 0.155 $

    پس اگر Data ما به صورت زیر باشد:
    $ X = {x_1, x_2, dots, x_n} $

    آنگاه به
    $ P(x in X) $
    می گویند Distribution و به پیدا کردنش می گویند Distribution learning.
    به عبارت دیگر Distribution learning یعنی اینکه توزیع داده ها را به دست آوریم.
    $ P(x in X): "Distribution learning" $

    اما گاهی مقادیری که یک متغیر می تواند اختیار کند، خیلی زیاد است یا بی نهایت است.
    در اینگونه موارد، معمولاً در آمار به جای کاری که کردیم، برای Distribution از Probability density function استفاده می کنیم که به صورت خلاصه به آن PDF می گویند:

    $ P("Smoking" | x) = cases(0 &"if" space.quad x < 10 &|space space| space.quad x > 90, 0.01 x &"if" space.quad x >= 10 &amp amp space.quad x < 20, 0.16 &"if" space.quad x >= 20 &amp amp space.quad x < 50, 0.16 - 0.01 x space.quad &"if" space.quad x >= 50 space.quad &amp amp space.quad x < 90) $

    به این ترتیب هدف ما در Distribution learning، پیدا کردن یک تابع توزیع است.
]

#tool.question()[
    همان سؤال قبلی با فرض این که داده ها توزیع نرمال داشته باشند.
    یعنی سن افراد سیگاری به صورت نرمال توزیع شده باشد.
]

#tool.true_answer()[
    در اصل ML engineer از سوادش به این موضوع پی می برد که داده ها نرمال هستند.
    مثلاً مشاهده می کند که ۵ فرد سیگاری ۱۰ ساله داریم و بعدش ۱۵ فرد سیگاری ۱۵ ساله داریم و به همین ترتیب متوجه می شود که داده ها شکلی نرمال دارند.

    با ضرب نظیر به نظیر هر عضو ستون سن در ستون فراوانی، و سپس تقسیم کردن حاصل آن بر تعداد جمعیت که ۱۰۰ می باشد به میانگین زیر می رسیم:
    $ mu = "Average" = 34 $
    و احتمالاً دارای انحراف معیار زیر می باشد:
    $ "Standard deviation" = 5 $

    و بر این اساس به نمودار زیر می رسیم:
    #tool.custom_figure(
        image("images/ML/03_01.png", width: 56%),
        caption: "با توجه به میانگین و انحراف معیار جمعیت، به نمودار بالا می رسیم.",
        inset: 1em
    )
]

#tool.tip()[
    تفاوت روش Regression با Distribution learning: در Regression لزوماً متغیر خروجی مان یک متغیر احتمالاتی نیست.
    این دو روش از هم خیلی دور نیستند ولی به هر صورت تفاوت دارند.
]

== Classification
#tool.question()[
    می خواهیم یک ماشین مناسب خانواده بخریم (Family car detection).
    چه ماشینی مناسب خانواده است؟
]

#tool.true_answer()[
    دو نقش برای حل این مسأله داریم:
    + ML engineer: برنامه ای می سازد که بتواند ماشین مناسب برای خانواده را با توجه به قدرت موتور و قیمت آن، تشخیص دهد.
    + Domain expert: می گوید چه ماشینی مناسب خانواده است.
        با گفتن قدرت موتور و قیمت ماشین به او، به ما جواب خواهد داد.

    ML engineer داده های قدرت و قیمت ماشین ها را به Domain expert می دهد و از او سؤال می کند آیا با توجه به مقدار آن ها، ماشین مربوطه مناسب است یا خیر؟
    در جدول زیر اطلاعات ماشین ها و پاسخ او آمده است:
    #tool.custom_figure(caption: "مناسب بودن یا نبودن ماشین برای خانواده با توجه به قدرت موتور و قیمت ماشین", kind: table, inset: 1em)[
        #table(
            columns: 3,
            inset: 1em,
            stroke: black,
            align: center,
            [Engine power ($X_1$)],
            [Price ($X_2$)],
            [Family car ($Y$)],
            "10",
            "1k",
            "No",
            "20",
            "1.2k",
            "No",
            "45",
            "5k",
            "Yes",
            "60",
            "10k",
            "Yes",
            "120",
            "15k",
            "Yes",
            "140",
            "30k",
            "No",
            "30",
            "100k",
            "No",
            "20",
            "200k",
            "No"
        )
    ]

    در ادامه مراحل زیر را انجام می دهیم:
    + Plot data:
        از آن جایی که انسان با دیدن نمودار داده ها درک بهتری از آن ها پیدا می کند، تا دیدن جدول، نمودار جدول بالا را رسم می کنیم.
        #tool.custom_figure(
            image("images/ML/03_02.png"),
            caption: "نمودار جدول بالا. دایره های منفی بیانگر ماشین های نامناسب و دایره های مثبت بیانگر ماشین های مناسب خانواده می باشند.",
            inset: 1em
        )

    + Get an insight:
        #tool.custom_figure(
            image("images/ML/03_03.png"),
            caption: "با کمی نگاه به نموداری که رسم کردیم، به این دیدگاه می رسیم که ماشین های مناسب خانواده درون محدوده قرمز رنگ قرار می گیرند. گویی که توسط یک مستطیل (که با طول و عرض و مختصات نقطه پایین سمت چپش مشخص می شود) احاطه شده اند.",
            inset: 1em
        )
        ما به عنوان ML engineer تصمیم می گیریم که محدوده ماشین های مناسب خانواده در نمودار بالا را به کمک شکلی نمایش دهیم.
        برای مثال به کمک یک مستطیل موازی محور های مختصات این محدوده را مشخص می کنیم.
        یکی از دلایل انتخاب مستطیل به جای مثلاً بیضی، ساده بودن رسم و تعریف آن است.
        
    + Make hypothesis and select a model:
        مهم ترین گام ما این گام است که در آن باید یک فرضیه خوب بسازیم.

        برای این مسأله فرضیه ما این است: ماشین های مناسب خانواده درون یک مستطیل موازی محور های مختصات هستند.
        در این جا مستطیلی که تعریف کردیم، همان Model برنامه ما می باشد که دارای ۴ پارامتر است و به صورت زیر تعریف می شود:

        #align(center)[
            #text(dir: ltr)[
                Model\<Left, Bottom, Width, Height\>
            ]
        ]

    + Train the model:
        یعنی یافتن بهترین مقادیر برای پارامتر های مدل.

        در این مرحله باید مدل خود را آموزش دهیم.
        از آنجایی که مدل پیشنهادی ما یک مستطیل است، برای آن که برنامه ما بتواند مشخصات این مستطیل را یاد بگیرد الگوریتم زیر را می نویسیم (الگوریتم Training):
        #tool.custom_figure(caption: "الگوریتم Training مدل.", kind: raw, inset: 1em)[
            ```
            // X is the data items consisting from only the first 2 columns of the former table (An N x 2 matrix)
            // Y is the data items consisting from only the last column of the former table (An N x 1 matrix)
            // N is the number of table rows (Here N = 8)

            Input: X, Y, N
            left = Infinity, bottom = Infinity
            width = -Infinity, height = -Infinity

            for k = 1 to N {
                // Poisitive example
                if Y[k] = True {
                    if X[k, 1] < left {
                        left = X[k, 1]
                    }
                    if X[k, 2] < bottom {
                        bottom = X[k, 2]
                    }
                    if X[k, 1] - left > width {
                        width = X[k, 1] - left
                    }
                    if X[k, 2] - bottom > height {
                        height = X[k, 2] - bottom
                    }
                }
            }
            ```
        ]

        پس از اجرای الگوریتم و آموزش دادن برنامه، باید برنامه را تست کنیم.
        برای مثال اگر ماشینی با مشخصات زیر به برنامه بدهیم:
        
        #align(center)[
            #text(stylistic-set: 2)[Engine power: 50, Price: 12k]
        ]

        برنامه به ما جواب
        Yes
        می دهد چون داخل مستطیل می افتد.
        فرآیندی که توضیح دادیم فرآیند Prediction می باشد.

        الگوریتم Prediction برای این مسأله به صورت زیر می باشد (Class label prediction):
        #tool.custom_figure(caption: "الگوریتم Prediction بر اساس مدل آموزش داده شده.", kind: raw, inset: 1em)[
            ```
            // e ---> Engine power
            // p ---> Price
            // M ---> Model
            // M[1] ---> Left,  M[2] ---> Bottom
            // M[3] ---> Width, M[4] ---> Height
            function Prediction(e, p, M) {
                if e >= M[1] and
                e <= M[1] + M[3] and
                p >= M[2] and
                p <= M[2] + M[4] {
                    return "Yes"
                } else {
                    return "No"
                }
            }
            ```
        ]

    #tool.list()[
        عبارت های مهم در این درس:
        - Classification
        - Plot: رسم کردن
        - Insight: بینش
        - Hypothesis: فرضیه
        - Model
        - Parameter
        - Train
        - Algorithm
        - Feature: در این جا همان ستون های مربوط به X می باشد.
        - Training set: در این جا همان مجموعه داده های X و Y می باشد.
        - Prediction (Recognition)
        - Inductive bias: هر دانسته ای غیر از اطلاعاتی که صورت مسأله داده و آن را به مسأله اضافه می کنیم، می گویند.
            مثلاً اینکه مدل مان مستطیل باشد یا بیضی، یک Inductive bias است.
    ]
]

= جلسه چهارم
== Smoothness
#tool.simple_context()[
    هدف در یادگیری ماشین (با کمی سهل گیری، هوش مصنوعی) این هست که دنیا را یک موجودیت پیوسته ببینیم، مدلش کنیم و این مدل را برای پیش بینی داده هایی که نداریم، استفاده کنیم.
    در دنیا موجودات مشابه هم، کنار هم هستند.
]

#tool.example()[
    Object زیر را داریم:
    $ "Object" cases("Attribute 1", "Attribute 2", "Attribute 3", dots.v, "Attribute N") $
]

#tool.double_section()[
    #tool.question()[
        دو Object ای که از یک جنس یا جمعیت هستند، انتظار داریم Attribute هاشون مشابه باشد یا نه؟
    ]
][
    #tool.true_answer()[
        انتظار داریم مشابه باشند.
        #v(3.2em)
    ]
]

#tool.double_section()[
    #tool.tip()[
        کل صحبتی که در یادگیری ماشین (با کمی سهل گیری، هوش مصنوعی) می شود، بر مبنای فرض Continuity یا Smoothness می باشد.
        #v(1.6em)
    ]
][
    #tool.example()[
        انتظار نداریم دیروز که هوا آفتابی بوده و امروز هم آفتابی هست فردا ناگهانی برفی بشود.
        حالت طبیعی این است که به تدریج هوا ابری شود و باد های سرد بوزد و به مرور هوا برفی شود.
    ]
]

#tool.reminder()[
    در مثال خرید ماشین خانواده، وقتی داده های مرتبطش را بر روی نمودار رسم کردیم، حدس زدیم که مستطیلی را می توان پیدا کرد که درون آن ماشین های مناسب خانواده قرار می گیرند. به این مستطیل، مدل می گویند. که به شکل زیر تعریف می شود:

    #align(center)[
        #text(dir: ltr)[
            Model\<Axis aligned rectangle\> = Model\<Left, Bottom, Width, Height\>
        ]
    ]

    #tool.custom_figure(
        image("images/ML/04_01.png"),
        caption: "مثال خرید ماشین مناسب خانواده در جلسه سوم",
        inset: 1em
    )

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

    #tool.custom_figure(
        image("images/ML/04_02.png"),
        caption: "ابزار Learning که دو ورودی و یک خروجی به شکل بالا دارد.",
        inset: 1em
    )

    در مدل آموزش داده شده، پارامتر های آن مقدار دهی شده اند.
]

== مفهوم مخفی و فرضیه سازگار
#tool.example()[
    فرض کنیم در مثال ماشین خانواده، ماشین های مناسب واقعا توسط یک مستطیل مشخص می شوند (مستطیل بزرگتر شکل زیر).

    #tool.custom_figure(
        image("images/ML/04_03.png", width: 76%),
        caption: "مستطیل بزرگتر چیزی است که واقعا وجود دارد و مستطیل کوچک تر مدلی است که از یادگیری از روی مثال های داده شده به دست آمده است.",
        inset: 1em
    )

    فرض کنیم شروع به تست کردن برنامه می کنیم و پاسخ آن این است که ماشین مناسب خانواده نیست، در صورتی که در واقع مناسب است.
]

#tool.double_section()[
    #tool.definition()[
        Latent concept: به مستطیلی که (در مثال بالا مستطیل است) واقعا وجود دارد و اغلب از آن خبر نداریم، می گویند و آن را با C نمایش می دهیم.
    ]
][
    #tool.definition()[
        Consistent hypothesis: چیزی که مدل یاد گرفت، که با نمونه های مثبت مان سازگار است، می گویند.
        #v(1.6em)
    ]
]

== بررسی یک الگو
#tool.example(pause: true)[
    فرض کنیم مساحت مستطیل کوچک $S_2$ و مساحت مستطیل بزرگ $S_1$ باشد.
    همچنین فرض کنیم:
    $ S_1 = 1 $
    در نتیجه:
    $ S_2 < S_1 $

    حال فرض کنیم یک نفر یک ماشین خانواده مناسب (نمونه مثبت) پیدا کرده و به ما می دهد (یعنی از کل C انتخاب کرده است).
]

#tool.double_section()[
    #tool.question()[
        احتمال این که از $S_2$ انتخاب کند چقدر است؟
    ]
][
    #tool.true_answer()[
        $S_2$
        #v(1.7em)
    ]
]

#tool.double_section()[
    #tool.question()[
        احتمال این که بیرون از $S_2$ انتخاب کند چقدر است؟
    ]
][
    #tool.true_answer()[
        $S_1 - S_2$
        #v(1.7em)
    ]
]

#tool.example(continuation: true, pause: true)[
    اگر اسم نمونه مورد نظر را $x$ بگذاریم آن گاه:
    $ p(x in S_2) = S_2 $
    $ p(x in.not S_2) = S_1 - S_2 $

    پس احتمالی وجود دارد که نمونه جدید به بهتر شدن فرضیه ما کمک می کند.
    این اتفاق زمانی می افتد که نمونه جدید در ناحیه درون $S_1$ و بیرون از $S_2$ باشد.

    احتمال اینکه همه N عدد نمونه ما درون $S_2$ باشند به صورت زیر است:
    $ (S_2)^N $
    
    به این ترتیب احتمال اینکه نمونه اول ما درون $S_2$ باشد، به صورت زیر است:
    $ S_2 $

    فرض کنیم $S_2$ نصف $S_1$ است.
    به این ترتیب احتمال این که اولین نمونه داخل $S_2$ باشد، ۵۰٪ درصد است.

    به نمونه هایی که می گیریم می گویند:
    // در این درس فرض ما این است که نمونه هایمان به صورت زیر است:
    #align(center)[
        #text(dir: ltr)[
            Independently and Identically Distributed (IID)
        ]
    ]
]

#tool.definition()[
    IID Sample: نمونه هایی که مستقل از هم اند و توزیع یکسانی دارند (احتمال یکسانی دارند).

    یعنی اگر مثلا ترتیب نمونه ها را عوض کنیم، چیزی عوض نمی شود.
]

#tool.double_section()[
    #tool.example()[
        از یک بشکه آب برداریم آبش کم می شود اما از یک چشمه آب برداریم گویی آبی کم نمیشه.
        در این جا چشمه IID است ولی بشکه IID نیست.
        #v(4.8em)
    ]
][
    #tool.example()[
        تعدادی توپ با رنگ های مختلف داریم.
        وقتی توپ ها را بر می داریم و رنگشان را نگاه می کنیم.
        اگر:
        + توپ ها را سر جایشان برگردانیم: نمونه ها IID هستند.
        + توپ را نگه داریم (IID): نمونه ها IID نیستند.
    ]
]
#tool.example(continuation: true)[
    فرض کنیم $S_2 = 0.5$ و همه نمونه ها IID هستند.
    احتمال این که نمونه اول داخل $S_2$ باشد و کمکی به یادگیری و بهبود Hypothesis ما نکند، برابر زیر است:
    $ (0.5) $

    نمونه دوم:
    $ (0.5)(0.5) $

    نمونه سوم:
    $ (0.5)(0.5)(0.5) $

    نمونه N ام:
    $ (0.5)^N $

    اگر بخواهیم احتمال بد شانسی ما کمتر از ۰/۰۱ باشد، (یعنی به احتمال ۰/۹۹ خوش شانس باشیم):
    $ P_"بد شانسی" = (0.5)^N <= 0.01 $
    $ (0.5)^N <= 0.01 arrow N log 0.5 <= log 0.01 arrow N >= (log 0.01) / (log 0.5) arrow N >= 6.7 tilde.eq 7 $

    یعنی به ۷ نمونه نیاز داریم تا به احتمال ۰/۹۹ خوش شانس باشیم (مدل مان چیز جدید یاد بگیرد).

    در ادامه احتمال های بد شانسی مختلف به همراه تعداد نمونه لازم برای رسیدن به آن ها، آورده شده است:
    #tool.custom_figure(caption: [رابطه بین احتمال بد شانسی $S_2$ و تعداد نمونه ها], kind: table, inset: 1em)[
        #table(
            columns: 2,
            inset: 1em,
            stroke: black,
            align: center + horizon,
            [$S_2$ (بد شانسی)],
            "Samples\ncount",
            "0.01",
            "1",
            "0.1",
            "2",
            "0.5",
            "7",
            "0.9",
            "43",
            "0.99",
            "458"
        )
    ]

    با دقت به جدول بالا به این نتیجه می رسیم که $S_2$ زمانی کوچکتر است که تعداد نمونه ها کم تر است.
]

#tool.tip()[
    هر چقدر در فرآیند آموزش از نمونه های جدید بیش تری استفاده می کنیم، از خوش شانسی به سمت بد شانسی می رویم.
    یعنی مثلاً اگر احتمال بد شانسی ما ۰/۹۹ است، با توجه به جدول قبلی، حداقل باید ۴۵۸ نمونه اضافه کنیم تا مدل مان بهتر شود.
    به عبارت دیگر یادگیری در ابتدا خیلی سریع است و به مرور کند تر می شود.

    #tool.custom_figure(
        image("images/ML/04_04.png", width: 77%),
        caption: "اغلب نمودار های یادگیری به صورت بالا هستند. افت خطا در ابتدای آموزش که تعداد کمی نمونه دریافت می شود، زیاد است. اما از جایی به بعد نمونه های جدید خیلی کمکی نمی کنند.",
        inset: 1em
    )
]

#tool.tip()[
    یادگیری ماشین را نمی توان بدون استفاده از نمونه انجام داد.
]

#tool.tip()[
    حجم نمونه آموزشی برای یادگیری مناسب، مهم است. نیاز است تعداد نمونه آموزشی مان از حداقل خاصی بیشتر باشد تا بتوان با کیفیت مد نظرمان یادگیری انجام شود.
]

== خطا و انواع آن
#tool.example()[
    فرض کنید Concept واقعی به صورت زیر است اما الگوریتم یادگیری به جای آن که از نمونه های مثبت یاد بگیرد از نمونه های منفی یاد بگیرد.
    #tool.custom_figure(
        image("images/ML/04_05.png", width: 75%),
        caption: "در شکل بالا، مدل ما به صورت مستطیل چسبیده به نمونه های منفی تعریف می شود.",
        inset: 1em
    )

    تفاوتی که مدل بالا با مدل قبلی دارد، به جز اینکه از نمونه های منفی برای آموزش استفاده می کند، این است که h ما به صورت کامل درون C قرار ندارد.

    ابتدا خطایی برای h تعریف می کنیم.
]

#tool.definition()[
    خطا: تعداد تشخیص های غلط برای نمونه های تستی مدل.

    انواع خطا ها شامل موارد زیر است:
    + خطای مطلق (Absolute error): 
        این خطا در ریاضی کاربرد دارد و شامل مجموع همه خطا های موجود بر روی کل دامنه است.

    + خطای تجربی (Emprical error): تعداد خطا در مجموعه نمونه های کوچک و محدودی که داریم.
        شکل ریاضی این خطا به صورت زیر است:
        $ x, y: "Testing set" $
        $ E(h, x) = sum_(k = 1)^(abs(x)) 1(h(x^(<k>)) eq.not y^(<k>)) $
        در عبارت بالا $y$ برچسب تک تک $x$ ها است.
        مثلاً به صورت زیر:
        #tool.custom_figure(caption: "برچسب مرتبط با هر نمونه (هر نمونه فقط یک ویژگی x را دارد).", kind: table, inset: 1em)[
            #table(
                columns: 2,
                inset: 1em,
                stroke: black,
                align: center + horizon,
                [$x$],
                [$y$],
                [$x^(<1>)$],
                "Yes",
                [$x^(<2>)$],
                "No",
                [#sym.dots.v],
                [#sym.dots.v],
            )
        ]

        همچنین $h(x^(<k>)) eq.not y^(<k>)$ به معنای این است که Label ای که Hypothesis ما به $k$ امین نمونه آزمایش داده است، با Label واقعی مان متفاوت باشد.

    + خطای تجربی میانگین (Average emprical error):
        خطای تجربی تقسیم بر اندازه نمونه.
        این خطا برای مقایسه مدل ها به کار می رود چرا که مستقل از مجموعه Emprical شان است (بر خلاف Emprical error که قابل مقایسه نیست).
        شکل ریاضی این خطا به صورت زیر است:
        $ E_"Average" = 1 / (abs(x) + 1) sum_(k=1)^abs(x) 1(h(x^(<k>)) eq.not y^(<k>)) $
]

== انواع پاسخ های برنامه
#tool.definition()[
    انواع پاسخ هایی که برنامه ما می تواند تولید کند شامل موارد زیر است:
    + True Poisitive (TP)
    + True Negative (TN)
    + False Poisitive (FP)
    + False Negative / False Reject (FN / FR)
    که به صورت شهودی در شکل زیر آمده است:
    #tool.custom_figure(
        image("images/ML/04_06.png", width: 71%),
        caption: "انواع پاسخ های برنامه ما",
        inset: 1em
    )
]

== قاعده Maximum Entropy
#tool.tip()[
    تا اینجا دو مدل یاد گرفتیم.
    یک مدل بر پایه داده های مثبت به دست می آمد و مدل دیگر بر پایه داده های منفی.
    قاعده Maximum Entropy به ما می گوید مستطیلی (مدل ما در اینجا) را پیدا کنیم که دقیقا وسط دو مستطیل دیگر (دو مدل دیگر) باشد.
    #tool.custom_figure(
        image("images/ML/04_07.png"),
        caption: "مستطیل کوچک مدلی است که از نمونه داده های مثبت و مستطیل بزرگ مدلی است که از نمونه داده های منفی به دست آوردیم. مستطیلی که از قاعده Maximum Entropy به دست می آید، همان مستطیلی است که دقیقا وسط دو مستطیل دیگر قرار دارد.",
        inset: 1em
    )

    این قاعده در همه جا ما را به نتایج خوبی می رساند.
]

#tool.example()[
    فرض کنید یک مسأله ای به شکل زیر داریم. چه چیزی نمونه های مثبت و منفی را از هم جدا می کند؟ بی نهایت خط.
    اما طبق قاعده Maximum Entropy مرز وسط به دست می آید.
    #tool.custom_figure(
        image("images/ML/04_08.png", width: 67%),
        caption: "مرز بین دو گروه به وسیله خط وسطی مشخص شده است که از قاعده Maximum Entropy به دست می آید.",
        inset: 1em
    )
]

#tool.tip()[
    یک Classifier محدود به یک Model نیست.
]

== VC-Dimension
#tool.double_section()[
    #tool.question()[
        فرض کنید کلاً یک نمونه مثبت داریم.
        با چه چیزی جداسازی را انجام می دهیم؟
    ]
][
    #tool.true_answer()[
        هیچ چیز.
        چون همه چیز مثبت است.
        #v(1.6em)
    ]
]

#tool.double_section()[
    #tool.question()[
        فرض کنید کلاً ۲ نمونه مثبت داریم.
        با چه چیزی جداسازی را انجام می دهیم؟
    ]
][
    #tool.true_answer()[
        هیچ چیز.
        چون همه چیز مثبت است.
        #v(1.6em)
    ]
]

#tool.double_section()[
    #tool.question()[
        فرض کنید کلاً ۲ نمونه داریم که یکی مثبت و دیگری منفی است.
        با چه چیزی جداسازی را انجام می دهیم؟
    ]
][
    #tool.true_answer()[
        با چیز های زیادی از جمله مستطیل، دایره، مثلث و ... اما ساده ترین شکل ممکن برای آن، خط است.
    ]
]

#tool.double_section()[
    #tool.tip()[
        اولین قاعده در یادگیری ماشین این است که مسأله ای که می خواهیم حل کنیم با ساده ترین مدل ممکن حل کنیم.
    ]
][
    #tool.question()[
        فرض کنید کلاً ۳ نمونه داریم که یکی مثبت و دو مورد دیگر منفی است (و یا بر عکس).
        با چه چیزی جداسازی را انجام می دهیم؟
    ]
]

#tool.true_answer()[
    با یک خط می توان جدا سازی را انجام داد.
]

#tool.double_section()[
    #tool.question()[
        فرض کنید کلاً ۴ نمونه داریم که غیر واقع بر یک خط راست هستند که دو مورد آن ها مثبت و دو مورد دیگر منفی هستند (و یا بر عکس).
        با چه چیزی جداسازی را انجام می دهیم؟
    ]
][
    #tool.true_answer()[
        نمی توان ۴ نقطه ای را پیدا کرد که یک خط بتواند همه جور برچسب زنی هایش را جدا کند.
        #v(3.2em)
    ]
]

#tool.double_section()[
    #tool.definition()[
        VC-Dimension یک Model: حداکثر تعداد نمونه هایی که مدل همه نوع برچسب گذاری آن ها را به درستی تفکیک می کند.
    ]
][
    #tool.example()[
        VC-Dimension یک خط برابر است با ۳.
        چرا که اگر بیش از ۳ نقطه داشته باشیم احتمال این که خط اشتباه کند وجود دارد.
    ]
]

#tool.double_section()[
    #tool.example()[
        VC-Dimension دو خط برابر است با ۵.
        چرا که اگر بیش از ۵ نقطه داشته باشیم احتمال این که دو خط اشتباه کنند وجود دارد.
    ]
][
    #tool.tip()[
        در یادگیری ماشین خطا اجتناب ناپذیر است.
        #v(3.2em)
    ]
]

#tool.double_section()[
    #tool.question()[
        مثال هایی وجود دارند که با وجود این که ۱۰۰۰ نمونه داریم به راحتی از یک خط استفاده می کنیم. چرا؟
        #v(1.6em)
    ]
][
    #tool.true_answer()[
        بنا به اصل پیوستگی انتظار چینش های عجیب و غریب نداریم و جاهایی که خط نمی تواند جدا کند حالت های بسیار خاص و بسیار نادر هستند.
    ]
]

#tool.tip()[
    تعداد نمونه های آموزشی مورد نیاز برای این که مدل خوب یاد بگیرد به لگاریتم خطا ربط دارد:
    $ N space alpha space log ("error") $
    $N$ تعداد نمونه های آموزشی می باشد.
]

= جلسه پنجم
#tool.simple_context()[
    اگر با هر الگوریتم دلخواه h را یادگیری بکنیم، بر اساس این که Hypothesis ما چه مقدار از C را پوشش می دهد، می توان کیفیت مدل را بررسی کرد.
]

#tool.reminder()[
    #tool.custom_figure(
        image("images/ML/05_01.png"),
        caption: "یادآوری از جلسه قبل.",
        inset: 1em
    )
]

#tool.reminder()[
    #text(dir: ltr)[
        ML Elements:
        + Examples
        + Model
        + Training Algorithm
    ]
]

== S, G and Version Space
#tool.definition()[
    در جلسات قبل یک مدل از نمونه های مثبت (S در شکل زیر) و یک مدل از نمونه های منفی (G در تصویر زیر) ساختیم که در شکل زیر آمده اند:
    #tool.custom_figure(
        image("images/ML/05_02.png"),
        caption: [به مدل S، #box[Most specific hypothesis] و به مدل G، #box[Most general hypothesis] می گویند.],
        inset: 1em
    )
    S کوچکترین Hypothesis سازگار با نمونه های آموزشی و G بزرگترین Hypothesis سازگار با نمونه های آموزشی می باشد.
    در شکل بالا هر مستطیلی که بین S و G باشد، جزو مجموعه جواب های ما است.

]

#tool.double_section()[
    #tool.definition()[
        Version Space: به فضایی که از S شروع و به G ختم می شود، که همان مجموعه جواب های بین S و G است، می گوییم #box[Version Space] می گویند.
    ]
][
    #tool.definition()[
        مسائل خوش ریخت: مسائلی که دانسته های مسأله برای تعیین جواب دقیق کافی است.
        #v(1.6em)
    ]
]

#tool.double_section()[
    #tool.definition()[
        مسائل بد ریخت: مسائلی که دانسته های مسأله برای تعیین جواب دقیق کافی نیست.
        در این مسائل، تعداد معادله ها از تعداد مجهول ها کمتر است.
        #v(1.6em)
    ]
][
    #tool.tip()[
        یادگیری (ماشین) یک مسأله بد ریخت (ill-posed problem) می باشد.
        مثلاً در شکل پیشین بی نهایت مستطیل به عنوان جواب بین S و G وجود دارد و مسأله آن یک مسأله ill-posed می باشد.
    ]
]

#tool.tip()[
    نمونه های بیشتر در فرآیند یادگیری مسأله را به سمت well-posed بودن می برد.
    #v(1.6em)
]

== انتخاب از درون Version Space
#tool.question()[
    در شکل پیشین از S تا G کدام مستطیل را اتنخاب کنیم؟
    (می خواهیم یک مورد از درون Version Space را انتخاب کنیم).
]

#tool.true_answer(pause: true)[
    1. می توان وسط آن را انتخاب کرد که این روش بر مبنای فرض Max Margin می باشد.
]

#tool.example()[
    با توجه به شکل زیر، فرض کنید نیاز های خانواده ها برای ماشین تغییر کند. این باعث می شود که تعریف ماشین خانواده کمی دچار تفاوت شود.
    مثلاً از این به بعد ماشین های خانواده نیاز است فضایی برای قرار دادن ماهواره برای اینترنت ماهواره ای داشته باشند.

    #tool.custom_figure(
        image("images/ML/05_03.png"),
        caption: "قاعده Max Margin",
        inset: 1em
    )

    بنابراین برای آن که مدل مان به تغییرات کوچک حساس نشود، مستطیلی را انتخاب می کنیم که با هر دو مستطیل S و G، مرز زیادی داشته باشد.
]

#tool.true_answer(continuation: true)[
    2. اگر مسأله طوری است که در آن مثلاً بیشترین ماشین ممکن را باید در گردونه ماشین های خانواده قرار دهیم، آن گاه باید طوری عمل کنیم که h به G نزدیکتر شود.
    
    3. اگر مسأله طوری است که در آن مثلاً ماشین خانواده یک چیز مشخص و معینی است، آن گاه باید طوری عمل کنیم که ماشین هایی که تفاوت کوچکی با مشخصات تعریف شده دارند، در دسته ماشین خانواده قرار نگیرند.
        در این حالت سعی می شود h به S نزدیک شود.
]

#tool.simple_context()[
    بعضی وقت ها برای انتخاب یک مورد از Version Space راهنمایی هایی همچون بالا را نداریم.
    در این صورت از قاعده کلی زیر (که می توان به دو صورت آن را پیاده سازی کرد) استفاده می شود.
]

#tool.definition(pause: true)[
    قاعده کلی انتخاب یک مورد از Version Space: معمولاً اگر از تعدادی Domain Expert که IID هستند (از هم مستقل هستند و با احتمال یکسان به طور تصادفی انتخاب می شوند)، سؤال بپرسیم، آنگاه رأی اکثریت به واقعیت نزدیک تر است.

    به دو صورت زیر این قاعده را با توجه به مثال شکل پیشین پیاده سازی می کنیم:

    می خواهیم مستطیلی را به صورت تصادفی بین S و G انتخاب کنیم. چگونه این کار را انجام می دهیم؟
        ۴ نقطه تصادفی بین S و G را به شکل زیر انتخاب می کنیم:
        #tool.custom_figure(
            image("images/ML/05_04.png", width: 80%),
            caption: "مختصات ۴ نقطه درون ۴ بازه بالا که بین S و G هستند، به صورت تصادفی ساخته می شود.",
            inset: 1em
        )
        از آن جایی که مستطیل مورد نظر بین مستطیل S و G می باشد، با نمونه های آموزشی مان سازگار است.
        دقت شود که در مثال بالا S و G از نمونه ها و h بین این دو به صورت تصادفی ساخته می شود.
]

#tool.question()[
    در روش بالا، چند مستطیل تصادفی باید بسازیم؟
]

#tool.true_answer()[
    $ N >= 33 $
    یعنی حداقل ۳۳ عدد.
    به دلیل قضیه حد مرکزی این عدد انتخاب می شود.
    حداقل تعداد نمونه های لازم در نمونه برداری از توزیع نرمال برای آن که توزیع به دست آمده از نمونه ها توزیع درستی باشد، ۳۳ (در اصل ۳۲ ولی در اینجا همان ۳۳ را در نظر بگیرید) عدد است.

    بنابراین از میان S و G (که همان Version Space مان است) N عدد مستطیل به صورت تصادفی انتخاب می کنیم.

    (برای فهم آنکه چرا N باید حداقل ۳۳ باشد به Normal Distribution Estimation و Central Limit Theorem مطالعه شود.)
]

#tool.definition(continuation: true)[
    پس از انتخاب N مستطیل به صورت توضیح داده شده، الگوریتم Voting را اجرا می کنیم.
    به این صورت که وقتی نمونه جدیدی به ما داده شود، Label آن Label ای است که اکثریت این N مستطیل اعلام می کنند.
]

#tool.tip()[
    قاعده Max Margin در کنار خوبی ای که دارد، دو عیب زیر را دارد:
    + باید بتوانیم برای هر Classifier، #box[Margin] را حساب کرد.
        این در حالی است که برای خیلی از Classifier ها به راحتی نمی توان Margin را حساب کرد.
    + این روش همیشه به ما کمک نمی کند.
        به این صورت که بعضی وقت ها یک Class مهم تر از یک Class دیگر است و باید Margin را کمی به این طرف و آن طرف هول داد.
]

== تقلید در یادگیری ماشین
#tool.tip()[
    در یادگیری ماشین با پشت صحنه پدیده ها کاری نداریم.
    بلکه با نمایش بیرونی آن ها کار داریم.
]

#tool.tip()[
    در یادگیری ماشین در اغلب اوقات برای ما مهم نیست که فرضیه ای که درباره موضوع مورد نظر می سازیم چقدر درست و چقدر غلط است.
    بلکه این مهم است که آن فرضیه چقدر مشاهدات ما را خوب توضیح می دهد.
]

#tool.example()[
    در زمان قدیم این فرضیه وجود داشت که زمین صاف است چرا که با استفاده از این فرضیه می توانستند شب و روز را مدل کنند، تقویم بسازند و جهت یابی کنند.
    بعداً مردم متوجه شدند که این فرضیه اشتباه است اما چیزی که باعث شد این فرضیه تا مدت ها پابرجا بماند این بود که برای مردم آن زمان کار می کرد و نیازشان را برطرف می کرد.
]

#tool.definition()[
    Digital Twin: برنامه ای کامپیوتری است که تلاش می کند رفتار یک سیستم واقعی را تقلید کند.

    #tool.custom_figure(
        image("images/ML/05_05.png", width: 62%),
        caption: "Digital Twin سعی می کند رفتار Real System را تقلید کند.",
        inset: 1em
    )

    دقت شود که درون Real System و Digital Twin لزوماً مانند یکدیگر نیست اما ورودی و خروجی یکسانی دارند.

    یکی از کاربرد های Digital Twin زمانی است که Real System گران قیمتی داریم و نمی توانیم هر کاری را با آن انجام دهیم.
]

== PAC Learning
#tool.definition()[
    #tool.custom_figure(
        image("images/ML/05_06.png"),
        caption: "Probably Approximately Correct (PAC) Learning",
        inset: 1em
    )
    فرض کنید C همان مفهومی است که واقعا وجود دارد و مساحت آن ۱ است.
    ما می خواهیم h را بسازیم.

    طبق شکل بالا خطای h شامل ۴ قسمت بالا، پایین، چپ و راستی است که بیرون از h و درون C قرار دارند.
    خطای h را $epsilon$ در نظر می گیریم.
    فرض کنیم مساحت ناحیه خطای شکل بالا $epsilon$ است و مساحت ۴ ناحیه با هم برابر است هر چند که اندازه شان متفاوت است.
    به این ترتیب مساحت هر یک از آن ها $epsilon \/ 4$ می باشد.

    احتمال این که یکی از ۴ نوار بالا به درون h بیافتد به صورت زیر است:
    $ 1 - epsilon / 4 $
    اگر N نمونه جدید پشت سر هم انتخاب کنیم، احتمال آن که همه این N نمونه از یک نوار خاص به درون h بیافتند، به صورت زیر است: $ (1 - epsilon / 4)^N arrow "Because samples are IID" $

    اگر N نمونه جدید پشت سر هم انتخاب کنیم، احتمال آن که همه این N نمونه از ۴ نوار به درون h بیافتاند، به صورت زیر است: $ 4 (1 - epsilon / 4)^N $

    احتمال بد شانسی را $delta$ در نظر می گیریم.
    اگر بخواهیم احتمال بد شانسی از یک $delta$ ای کمتر باشد، از رابطه زیر استفاده می کنیم:
    $ 4 (1 - epsilon / 4)^N <= delta $
    $delta$ کمیتی است که خودمان انتخاب می کنیم.
    مثلاً می خواهیم احتمال بد شانسی کمتر از ۰/۰۱ باشد.

    در ادامه به رابطه های آخر شکل بالا می رسیم که رابطه نهایی آن شکل، در زیر آورده شده است:

    $ N >= (4 / epsilon) log(4 / delta) $

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

    به این تحلیل تئوریک، Probably Approximately Correct (PAC) Learning می گویند.

    $epsilon$: خطای نمونه

    $delta$: احتمال یادگیری مدل با استفاده از N نمونه آموزشی که خطای آن از $epsilon$ بیشتر باشد. $arrow.l$ احتمال بد شانسی
]

#tool.tip()[
    PAC Learning تکنیکی است برای تعیین حداقل تعداد نمونه های آموزشی برای آن که مدل خوب یاد گرفته شود و احتمال بد شانسی کم شود.
]

#tool.list()[
    در تکنیک PAC Learning دو مورد را مشخص می کنیم:
    + $epsilon$ (خطای قابل تحمل)
    + $delta$
    که در پاسخ، حداقل تعداد نمونه های آموزشی به دست می آید.
]

#tool.tip()[
    تحلیل هایی که در آن ها می خواهیم یک Boundry یا بازه را پیدا کنیم، اهمیت ندارند که دقیق باشند.
    این گونه تحلیل ها را تحلیل بد بینانه (Pessimistic) می گویند.
]

== مدل های یادگیری ماشین
#tool.double_section()[
    #tool.question()[
        چه مدلی بهتر است؟
        #v(3.6em)
    ]
][
    #tool.true_answer()[
        خبر بد:
        کسی نمی داند.

        خبر خوب:
        مجموعه ای از مدل های خوب برای مسائل عام شناسایی شدند.
    ]
]


#tool.tip()[
    مسأله ای که با یک مدل ساده تر حل می شود را با مدل پیچیده حل نمی کنند، چرا که:
    #tool.double_section()[
        + استفاده از آن ساده تر است.
        + Train کردن آن راحت تر است.
    ][
        3. توضیح دادن آن راحت تر است.
        + بهتر تعمیم می یابد.
    ]

    #tool.custom_figure(
        image("images/ML/05_07.png", width: 86%),
        caption: "دلایل استفاده از مدل ساده تر",
        inset: 1em
    )
]

#tool.list()[
    Classifier Models:
    + Basic Classifier: مدل هایی که با یک رابطه ریاضی یا یک ساختمان داده قابل توصیف اند.
        مانند:
        
        #text(dir: ltr)[Line, Polynomial, Decision Tree, Naive Bayes, Axis Aligned Rectangle, #sym.dots]
    + Ensemble Models (مدل های مرکب):
        مدل هایی هستند که چندین Basic Model درون خود دارند.
        مانند یک خط با یک مستطیل و یا مانند مثالی که مستطیل S و G را داشتیم و تعدادی مستطیل بین آن ها به طور تصادفی انتخاب کردیم و هنگام تولید Label از آن ها رأی گیری کردیم.
    + Neural Network & Deep Models: (فکر کنم یک جور هایی در هر دو گروه بالا می توانند قرار بگیرند)
]

=== Ensemble Models
#tool.example()[
    نمونه ای دیگر از یک Ensemble Model:

    می خواهیم دو گروه مثبت و منفی را از یکدیگر جدا کنیم که در شکل زیر آمده اند:
    #tool.custom_figure(
        image("images/ML/05_08.png", width: 50%),
        caption: "جدا سازی دو گروه به کمک یک Ensemble Model",
        inset: 1em
    )
    
    این کار در مراحل زیر انجام می گیرد:
    + جمع آوری نمونه ها #sym.arrow.l نمونه های مثبت و منفی
    + انتخاب مدل #sym.arrow.l خط
    + آموزش مدل #sym.arrow.l با کمک الگوریتم عمود منصف

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

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

= جلسه ششم
== Probabilistic Classifiers
#tool.tip()[
    در این طبقه بند ها ما اطلاعی نداریم که نمونه به کدام کلاس تعلق دارد اما سعی می کنیم بر اساس شواهدی آن را به کلاسی تخصیص دهیم.
]

#tool.double_section()[
    #tool.question()[
        اگر یک تاس ساده را بیاندازیم، احتمال آن که عدد ۳ بیاید چقدر است؟
    ]
][
    #tool.true_answer()[
        $ 1 / 6 $
        #v(0.3em)
    ]
]

#tool.double_section()[
    #tool.question()[
        اگر یک تاس ساده را بیاندازیم و بدانیم که عددی فرد آمده است، احتمال آن که مقدار آن ۳ باشد چقدر است؟
    ]
][
    #tool.true_answer()[
        $ 1 / 3 $
        #v(1.9em)
    ]
]

#tool.double_section()[
    #tool.tip()[
        در مواقعی دانسته هایی داریم که ما را در رسیدن به احتمال مورد نظر کمک می کنند و آن را کمتر یا بیشتر می کنند.
    ]
][
    #tool.definition()[
        Evidence (مشاهده): چیزی است که ذهنیت ما را به یک سمت می برد.
        #v(1.6em)
    ]
]

#tool.double_section()[
    #tool.question()[
        فردی وارد کلاس می شود.
        احتمال آن که اهل فرانسه باشد و احتمال آن که اهل ایران باشد چقدر است؟
        #v(3.2em)
    ]
][
    #tool.true_answer()[
        احتمال زیاد ایرانی است چرا که ذهن ما به سمت حقیقتی Bias شده و آن این است که احتمال دیدن شخصی فرانسوی در این جا خیلی خیلی کمتر از احتمال دیدن شخصی ایرانی است. 
    ]
]

#tool.tip()[
    بعضی اوقات بدون این که درباره Class یک نمونه اطلاعاتی داشته باشیم، ذهن ما سراغ دانش خاصی می رود.
]

=== Prior, Posterio and Marginal Probability
#tool.definition()[
    Prior Probability (احتمال پیشین): به اینکه بدون این که درباره موضوع مورد نظر Evidence خاصی داشته باشیم، ذهن ما به دلیل خاصی به یک جهت خاصی گرایش پیدا کرده است.

    به عبارتی دیگر احتمال Prior به احتمالی می گویند که بدون داشتن اطلاعاتی راجع به پیش آمد بیان می شود.
]

#tool.double_section()[
    #tool.definition()[
        Posterio Probability (احتمال پسین): احتمالی است که با داشتن اطلاعاتی راجع به پیش آمد بیان می شود.
        #v(1.6em)
    ]
][
    #tool.definition()[
        Marginal Probability (احتمال حاشیه ای): احتمال حاشیه ای به احتمال مشاهده یک مقدار خاص از یک متغیر، ادغام شده روی تمام مقادیر ممکن سایر متغیرها اشاره دارد.
    ]
]

#tool.double_section()[
    #tool.tip()[
        از Evidence به Probability می رسیم.
        #v(3.2em)
    ]
][
    #tool.example()[
        اگر بدانیم که بعد از انداختن تاس عددی که آمده فرد است، احتمال آمدن عدد ۳ بیشتر می شود.
    ]
]

#tool.definition()[
    در بسیاری از موارد 
    $p(x)$
    را داریم که احتمال رخ دادن متغیر $x$ می باشد.
    برای نمونه در مثال تاس بدون داشتن دانش قبلی به صورت زیر است:
    $ p(1) = 1 / 6 = p(2) = dots = p(6) $

    اما مواردی وجود دارند که اطلاع قبلی ای در مورد موضوع مورد نظر داریم.
    این موارد به صورت احتمال شرطی بیان می شوند.
    این گونه احتمالات شبیه زیر بیان می شوند:
    $ "Likelihood" arrow p("evidence" | "class") $
    مانند زیر که $x$ را به یک کلاس مشروط کردیم:
    #text(size: 1em)[
        $ p(underbrace(x, "مشاهده") | x in underbrace({1, 3, 5}, "گروه یا کلاس")) = 1 / 3 $
    ]
]

#tool.tip()[
    Likelihood معمولا با یک Probability Density Function یا همان PDF بیان می شود.
    #h(10.5em) $p(x | c): "pdf"$
]

#tool.example(pause: true)[
    در یک آزمایش پزشکی، تعداد گلبول های سفید در واحد خون تعدادی آدم شمرده می شود.
    اگر بدن درگیر مهاجمی شده باشد، تعداد گلبول های سفید افزایش می یابد.

    #tool.custom_figure(
        image("images/ML/06_01.png", width: 79%),
        caption: "تعداد گلبول های سفید در واحد خون و فراوانی افراد مرتبط با این تعداد گلبول سفید",
        inset: 1em
    )

    #tool.custom_figure(
        image("images/ML/06_02.png", width: 79%),
        caption: "تعداد گلبول های سفید در واحد خون و احتمال داشتن این تعداد از گلبول های سفید برای یک فرد با توجه به اینکه مریض است یا سالم است.",
        inset: 1em
    )

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

    پزشک با داشتن تعداد گلبول های سفید، می خواهد بداند احتمال بیمار بودن فرد چقدر است؟ یعنی مثلا:
    $ p("disease" | x = 15) $
]

=== Chain Rule of Probability
#tool.definition()[
    قاعده زنجیره احتمالات توأمان (Chain rule of probability):
    $ p(A, B) = p(A) times p(B | A) = p(B) times p(A | B) = p(B, A) $
    $ P(A, B, C) = p(A) times p(B | A) times p(C | A, B) $
    $ P(A, B, C, D) = p(A) times p(B | A) times p(C | A, B) times p(D | A, B, C) $
]

#tool.example(continuation: true)[
    #text(fill: red_color)[$C_1$] نمایانگر بیمار بودن و #text(fill: green_color)[$C_2$] نمایانگر سالم بودن است.

    $ p(x_1, C_1) = p(x) times p(C_1 | x) = p(C_1) times p(x | C_1) $

    همانطور که گفتیم پزشک می خواهد احتمال بیمار بودن فرد را بداند:
    #text(size: 1.25em)[
        $ overbrace(p(C_1 | x), "Posterio") = (overbrace(p(C_1), "Prior") times overbrace(p(x | C_1), "Likelihood")) / (p(x) =  underbrace(p(x | C_1) + p(x | C_2), "Marginal probability of x")) $
    ]
    $p(C_1)$ یعنی احتمال بیمار بودن یک آدم در یک جمعیت، بدون اینکه Evidence ای داشته باشیم.

    $p(x)$ یعنی احتمال اینکه تعداد گلبول های سفید در یک جمعیت، مقدار $x$ باشد، بدون اینکه Evidence ای داشته باشیم.

    همچنین چون فقط $C_1$ و $C_2$ هستند که فضا را افراز می کنند، $p(x)$ را در مخرج معادله بالا برابر با مقدار زیر قرار دادیم:
    $ p(x) = p(x | C_1) + p(x | C_2) $
    که به آن Marginal probability مربوط به $x$ می گویند.
]

#tool.question()[
    شخصی با WBC = 14 به پزشک مراجعه کرده است.
    آیا بیمار است؟
]

#tool.true_answer()[
    برای این که پزشک بیمار بودن فرد را تشخیص دهد، مقدار دو احتمال زیر را حساب کرده و مقدار هر کدام که بیشتر بود یعنی فرد در آن وضعیت (سالم یا بیمار) قرار دارد.
    $ p("بیمار" | "wbc" = 14) space.quad , space.quad p("سالم" | "wbc" = 14) $

    بنابراین فرد در صورت زیر بیمار است:
    $ "Type of a preson" == "بیمار" "iff" p("بیمار" | "wbc" = 14) > p("سالم" | "wbc" = 14) $
]

=== Bayesian Learning
#tool.definition()[
    Bayesian Learning:
    #text(size: 1.25em)[
        $
        x in C_1 "iff" p(C_1 | x) > p(C_2 | x) \
        = (p(C_1) times p(x | C_1)) / cancel(p(x)) > (p(C_2) times p(x | C_2)) / cancel(p(x)) \
        = p(C_1) times p(x | C_1) > p(C_2) times p(x | C_2)
        $
    ]
]

#tool.question()[
    مقدار $p(C_1)$ را از کجا می آوریم و چقدر است؟ 
]

#tool.true_answer()[
    از Domain Knowledge می آوریم.

    در مسائل Machine Learning همان اول روی Train Data معادله زیر را اعمال کرده و با این معادله مقدار $p(C_1)$ را حساب می کنیم:
    #text(size: 1.25em)[
        $ p(C_1) = n(C_1) / (n(C_1) + n(C_2) = N) $
    ]
]

=== به دست آوردن $p(x | C_1)$ و $p(x | C_2)$
#tool.question()[
مقدار $p(x | C_1)$ و $p(x | C_2)$ را چگونه به دست آوریم؟
]

#tool.true_answer()[
    این موارد نیز از روی Train Data، حساب می شوند.

    فرض کنید Train Data ای به شکل زیر داریم:
    #tool.custom_figure(caption: [Train Data ما دارای تعدادی m ویژگی و دو کلاس $C_1$ و $C_2$ است.], kind: table, inset: 1em)[
        $
        #stack(
            v(2.5em),
            $ "Number of rows" arrow.l N lr(\{, size: #20em) $,
        )
        #table(
            columns: 2,
            inset: 1em,
            stroke: black,
            align: center,
            $x_1 x_2 dots x_m$,
            $y$,
            line(),
            $C_1$,
            line(),
            $C_1$,
            $dots.v$,
            $dots.v$,
            line(),
            $C_1$,
            line(),
            $C_2$,
            line(),
            $C_2$,
            line(),
            $C_2$,
            line(),
            $C_2$
        )
        #stack(
            v(3em),
            $ lr(}, size: #9em) C_1 $,
            v(2em),
            $ lr(}, size: #9em) C_2 $,
        )
        $
    ]

    با استفاده از یک جدول احتمالاتی ساده $p(C_1)$ و $p(C_2)$ که در پاسخ سؤال قبلی فرمول آن آورده شد، به دست می آیند.

    $p(x | C_1)$ و $p(x | C_2)$ نیز به صورت یک Probability Distribution نوشته می شوند که معمولاً دو حالت دارد زیر را دارد:
    + Tabular: یعنی به صورت جدولی نوشته می شود.
        مانند جدول زیر:
        #tool.custom_figure(caption: "نمونه ای از نوشته شدن یک توزیع احتمالاتی به شکل جدول.", kind: table, inset: 1em)[
            #table(
                columns: 2,
                inset: 1em,
                stroke: black,
                align: center,
                $x$,
                $p(x)$,
                $1$,
                $0.1$,
                $2$,
                $0.002$,
                $dots.v$,
                $dots.v$,
                $100$,
                $0.0003$
            )
        ]
    + PDF: یک تابع ریاضی می نویسیم که $x$ را به احتمالش نگاشت می کند.
        مثلاً برای خیلی از پدیده هایی که با آن ها سر و کار داریم، یک تابع توزیع احتمال نرمال می نویسیم.
        فرمول تابع توزیع نرمال برای $C_1$ به صورت زیر است:
        #text(size: 1.5em)[
            $ p(x | C_1): "Normal"(underbrace(mu_1, "Mean"), underbrace(sigma_1, "Standard deviation")) arrow.curve.b $
        ]
        #text(size: 2em)[
            $ p(x | C_1) = 1 / (sqrt(2 pi sigma_1^2)) e^((-(x - mu_1)^2) / (2 sigma_1^2)) $
        ]
        #text(size: 1.5em)[
            $ mu_1 = (sum_(x in C_1)x) / (n(C_1)) $
            $ sigma_1 = sqrt((sum_(x in C_1)(x - mu_1)^2) / (N - 1)) $
        ]
]

#tool.tip()[
    برای توزیع های کوچک Tabular و برای توزیع های بزرگ PDF خوب است.
]

=== احتمال شرطی دو متغیره

#tool.question()[
    ۶ نمونه که هر یک، دو Feature دارند و در کل به دو کلاس تقسیم بندی می شوند، به شکل زیر داریم:
    #tool.custom_figure(
        image("images/ML/06_03.png", width: 46%),
        caption: "۶ نمونه داریم که به شکل بالا توزیع شده اند.",
        inset: 1em,
        refrence: <diagram1>
    )

    نمونه ای داریم که ویژگی های آن به صورت $x_1 = -1$ و $x_2 = 0$ است.
    این نمونه متعلق به کلاس $C_1$ است یا $C_2$؟
]

#tool.true_answer()[
    برای حل این مسأله هر دو احتمال زیر را حساب می کنیم:
    $ p(C_1 | < x_1 = -1, x_2 = 0 >) = space ? space.quarter , space.quarter p(C_2 | < x_1 = -1, x_2 = 0 >) = space ? $
    این مسأله را به کمک جدول حل می کنیم.
    ابتدا نمودار را به صورت جدول زیر در می آوریم:
    #tool.custom_figure(caption: [جدول مربوط به نمودار @diagram1], kind: table, inset: 1em)[
        #table(
            columns: 3,
            inset: 1em,
            stroke: black,
            align: center,
            $x_1$,
            $x_2$,
            $y$,
            $-1$,
            $0$,
            $C_1$,
            $-1$,
            $-1$,
            $C_1$,
            $0$,
            $-1$,
            $C_1$,
            $1$,
            $0$,
            $C_2$,
            $1$,
            $1$,
            $C_2$,
            $0$,
            $1$,
            $C_2$
        )
    ]

    سپس احتمالات شرطی (Posterio های) مربوط به $x_1$ را به صورت جدول زیر می نویسیم:
    #tool.custom_figure(caption: [احتمالات شرطی (Posterio های) مربوط به $x_1$], kind: table, inset: 1em)[
        #table(
            columns: 3,
            inset: 1em,
            stroke: black,
            align: center,
            $x_1$,
            $p(x_1 | C_1)$,
            $p(x_1 | C_2)$,
            $-1$,
            $ 2 / 3 $,
            $0$,
            $0$,
            $ 1 / 3 $,
            $ 1 / 3 $,
            $1$,
            $0$,
            $ 2 / 3 $,
        )
    ]

    برای $x_2$ نیز به همین صورت عمل می کنیم:
    #tool.custom_figure(caption: [احتمالات شرطی (Posterio های) مربوط به $x_2$], kind: table, inset: 1em)[
        #table(
            columns: 3,
            inset: 1em,
            stroke: black,
            align: center,
            $x_2$,
            $p(x_2 | C_1)$,
            $p(x_2 | C_2)$,
            $-1$,
            $ 2 / 3 $,
            $0$,
            $0$,
            $ 1 / 3 $,
            $ 1 / 3 $,
            $1$,
            $0$,
            $ 2 / 3 $,
        )
    ]

    همچنین خود Prior ها را نیز می نویسیم:
    $ p(C_1) = p(C_2) = 0.5 $

    فرض کنید برای تست از همان داده های Training استفاده می کنیم (در اینجا برای سادگی این کار را می کنیم و گرنه کار خوبی نیست).
    در ادامه جواب دو احتمال شرطی ای که در ابتدا آورده شدند را محاسبه می کنیم:
    $ p(C_1 | < x_1 = -1, x_2 = 0 >) = space ? space.quarter , space.quarter p(C_2 | < x_1 = -1, x_2 = 0 >) = space ? $

    به کمک قاعده بیز ساده (Naive Bayes Assumption) می توان احتمال های بالا را حساب کرد.
    این قاعده می گوید که فرض کنیم $x_1$ و $x_2$ از هم مستقل هستند.
    این قاعده برای احتمال های بالا به صورت زیر نوشته می شود:
    $ p(C_1 | < x_1 = -1, x_2 = 0 >) = \ p(C_1 | x_1 = -1) times p(C_1 | x_2 = 0) $

    از آن جایی که $p(x)$ مساوی است، به آن نیازی نداریم و مخرج کسر را حساب نمی کنیم.
    در ادامه به صورت زیر معادله بالا را حل می کنیم:
    $
    p(C_1 | < x_1 = -1, x_2 = 0 >) = \ p(C_1 | x_1 = -1) times p(C_1 | x_2 = 0) = \
    cancel(p(C_1)) times p(x_1 = -1 | C_1) times cancel(p(C_1)) times p(x_2 = 0 | C_1) = \ 2 / 3 times 1 / 3 = 2 / 9 arrow star star #text(dir: ltr)[Wins] star star
    $
    $
    p(C_2 | < x_1 = -1, x_2 = 0 >) = \ p(C_2 | x_1 = -1) times p(C_2 | x_2 = 0) = \
    cancel(p(C_2)) times p(x_1 = -1 | C_2) times cancel(p(C_2)) times p(x_2 = 0 | C_2) = \ 0 times 1 / 3 = 0
    $
]

=== ترتیب استفاده از Classifier ها
#tool.tip()[
    Naive Bayes طبقه بند خیلی ساده ای است.
    به همین دلیل به عنوان Baseline یا مبنای پایه برای محاسبات استفاده می شود.
    اگر Naive Bayes در حد ۶۰٪ یا ۷۰٪ خوب جواب داد، آن گاه سراغ روش های دیگر برای بهتر کردن مدل می رویم.

    باید بقیه روش هایی که بعد از Naive Bayes استفاده می کنیم از آن بهتر باشند به جز Random Assignment.
    یعنی عملکرد روش های مختلف و ترتیب به کار گیری آن ها (از چپ به راست) به شکل زیر است:
    #align(center)[
        Random Assignment < Naive Bayes < Other Methods
    ]

    روش Random Assignment به این صورت کار می کند که به صورت تصادفی به نمونه ها Label می زنیم.
    مثلاُ این روش در یک مسأله دو کلاسه دارای دقت ۵۰٪ است.
]

#tool.example()[
    مسأله ای درباره طبقه بندی زعفران داریم.
    زعفران ها در ۵ کلاس طبقه بندی می شوند:
    #grid(
        columns: (1fr, 1fr, 1fr, 1fr, 1fr),
        align: center,
        [1. عالی],
        [2. بسیار خوب],
        [3. خوب],
        [4. متوسط],
        [5. بد]
    )
    روش Random Assignment برای این مسأله دارای دقت ۲۰٪ است.
    یعنی احتمال این که کلاس نمونه ای درست تشخیص داده شود، ۲۰٪ است.
    در ادامه طبقه بند Naive Bayes می سازیم.
    اگر دقت Naive Bayes بالای ۲۰٪ شد، به سراغ حل مسأله با روش های یادگیری ماشین می رویم.
    چرا که تجربه نشان می دهد اگر Naive Bayes خیلی بهتر از Random Assignment کار نکرد، اول به Dataset مسأله مان باید شک کنیم و به این گمان بیافتیم که در یک جای مسأله اشتباهی کرده ایم.
]