🌐 Update translations via Co-op Translator

pull/853/head
leestott 2 days ago committed by GitHub
parent 6a683a369d
commit 443c121c29

@ -1,8 +1,8 @@
<!-- <!--
CO_OP_TRANSLATOR_METADATA: CO_OP_TRANSLATOR_METADATA:
{ {
"original_hash": "0e6380999b08813a492200ca2e3bbf11", "original_hash": "b79add6cc71cc7468fa23c9cf42f2327",
"translation_date": "2025-08-29T12:45:23+00:00", "translation_date": "2025-09-04T06:13:14+00:00",
"source_file": "README.md", "source_file": "README.md",
"language_code": "ar" "language_code": "ar"
} }
@ -31,9 +31,9 @@ CO_OP_TRANSLATOR_METADATA:
> 🌍 سافر حول العالم بينما نستكشف تعلم الآلة من خلال ثقافات العالم 🌍 > 🌍 سافر حول العالم بينما نستكشف تعلم الآلة من خلال ثقافات العالم 🌍
يسر دعاة السحابة في Microsoft تقديم منهج دراسي لمدة 12 أسبوعًا و26 درسًا حول **تعلم الآلة**. في هذا المنهج، ستتعلم ما يُطلق عليه أحيانًا **تعلم الآلة الكلاسيكي**، باستخدام مكتبة Scikit-learn بشكل أساسي وتجنب التعلم العميق، الذي يتم تغطيته في [منهج الذكاء الاصطناعي للمبتدئين](https://aka.ms/ai4beginners). قم بإقران هذه الدروس مع [منهج علم البيانات للمبتدئين](https://aka.ms/ds4beginners) أيضًا! يسر دعاة السحابة في Microsoft تقديم منهج دراسي لمدة 12 أسبوعًا و26 درسًا حول **تعلم الآلة**. في هذا المنهج، ستتعلم ما يُطلق عليه أحيانًا **تعلم الآلة الكلاسيكي**، باستخدام مكتبة Scikit-learn بشكل أساسي وتجنب التعلم العميق، الذي يتم تغطيته في [منهج الذكاء الاصطناعي للمبتدئين](https://aka.ms/ai4beginners). قم بدمج هذه الدروس مع [منهج علم البيانات للمبتدئين](https://aka.ms/ds4beginners) أيضًا!
سافر معنا حول العالم بينما نطبق هذه التقنيات الكلاسيكية على بيانات من مناطق مختلفة من العالم. يتضمن كل درس اختبارات قبل وبعد الدرس، تعليمات مكتوبة لإكمال الدرس، حل، مهمة، والمزيد. تسمح لك منهجيتنا القائمة على المشاريع بالتعلم أثناء البناء، وهي طريقة مثبتة لجعل المهارات الجديدة "تلتصق". سافر معنا حول العالم بينما نطبق هذه التقنيات الكلاسيكية على بيانات من مناطق مختلفة من العالم. يتضمن كل درس اختبارات قبل وبعد الدرس، تعليمات مكتوبة لإكمال الدرس، حل، مهمة، والمزيد. تسمح لك طريقة التدريس القائمة على المشاريع بالتعلم أثناء البناء، وهي طريقة مثبتة لتثبيت المهارات الجديدة.
**✍️ شكر جزيل لمؤلفينا** Jen Looper, Stephen Howell, Francesca Lazzeri, Tomomi Imura, Cassie Breviu, Dmitry Soshnikov, Chris Noring, Anirban Mukherjee, Ornella Altunyan, Ruth Yakubu و Amy Boyd **✍️ شكر جزيل لمؤلفينا** Jen Looper, Stephen Howell, Francesca Lazzeri, Tomomi Imura, Cassie Breviu, Dmitry Soshnikov, Chris Noring, Anirban Mukherjee, Ornella Altunyan, Ruth Yakubu و Amy Boyd
@ -49,7 +49,7 @@ CO_OP_TRANSLATOR_METADATA:
1. **قم بعمل Fork للمستودع**: انقر على زر "Fork" في الزاوية العلوية اليمنى من هذه الصفحة. 1. **قم بعمل Fork للمستودع**: انقر على زر "Fork" في الزاوية العلوية اليمنى من هذه الصفحة.
2. **قم باستنساخ المستودع**: `git clone https://github.com/microsoft/ML-For-Beginners.git` 2. **قم باستنساخ المستودع**: `git clone https://github.com/microsoft/ML-For-Beginners.git`
> [اعثر على جميع الموارد الإضافية لهذا الدورة في مجموعة Microsoft Learn الخاصة بنا](https://learn.microsoft.com/en-us/collections/qrqzamz1nn2wx3?WT.mc_id=academic-77952-bethanycheum) > [اعثر على جميع الموارد الإضافية لهذه الدورة في مجموعة Microsoft Learn الخاصة بنا](https://learn.microsoft.com/en-us/collections/qrqzamz1nn2wx3?WT.mc_id=academic-77952-bethanycheum)
**[الطلاب](https://aka.ms/student-page)**، لاستخدام هذا المنهج، قم بعمل Fork للمستودع بالكامل إلى حساب GitHub الخاص بك وأكمل التمارين بمفردك أو مع مجموعة: **[الطلاب](https://aka.ms/student-page)**، لاستخدام هذا المنهج، قم بعمل Fork للمستودع بالكامل إلى حساب GitHub الخاص بك وأكمل التمارين بمفردك أو مع مجموعة:
@ -59,9 +59,9 @@ CO_OP_TRANSLATOR_METADATA:
- قم بإجراء اختبار ما بعد المحاضرة. - قم بإجراء اختبار ما بعد المحاضرة.
- أكمل التحدي. - أكمل التحدي.
- أكمل المهمة. - أكمل المهمة.
- بعد إكمال مجموعة الدروس، قم بزيارة [لوحة المناقشة](https://github.com/microsoft/ML-For-Beginners/discussions) و"تعلم بصوت عالٍ" من خلال ملء نموذج PAT المناسب. PAT هو أداة تقييم تقدم وهي نموذج تقوم بملئه لتعزيز تعلمك. يمكنك أيضًا التفاعل مع نماذج PAT الأخرى حتى نتعلم معًا. - بعد إكمال مجموعة الدروس، قم بزيارة [لوحة المناقشة](https://github.com/microsoft/ML-For-Beginners/discussions) و"تعلم بصوت عالٍ" من خلال ملء نموذج PAT المناسب. PAT هو أداة تقييم تقدم وهي نموذج تقوم بملئه لتعزيز تعلمك. يمكنك أيضًا التفاعل مع PATs الآخرين حتى نتعلم معًا.
> لمزيد من الدراسة، نوصي باتباع هذه [وحدات ومسارات التعلم من Microsoft Learn](https://docs.microsoft.com/en-us/users/jenlooper-2911/collections/k7o7tg1gp306q4?WT.mc_id=academic-77952-leestott). > لمزيد من الدراسة، نوصي باتباع هذه [وحدات ومسارات التعلم من Microsoft](https://docs.microsoft.com/en-us/users/jenlooper-2911/collections/k7o7tg1gp306q4?WT.mc_id=academic-77952-leestott).
**المعلمون**، لقد قمنا [بتضمين بعض الاقتراحات](for-teachers.md) حول كيفية استخدام هذا المنهج. **المعلمون**، لقد قمنا [بتضمين بعض الاقتراحات](for-teachers.md) حول كيفية استخدام هذا المنهج.
@ -71,13 +71,13 @@ CO_OP_TRANSLATOR_METADATA:
بعض الدروس متوفرة كفيديوهات قصيرة. يمكنك العثور على جميع هذه الفيديوهات داخل الدروس، أو على [قائمة تشغيل تعلم الآلة للمبتدئين على قناة Microsoft Developer على YouTube](https://aka.ms/ml-beginners-videos) بالنقر على الصورة أدناه. بعض الدروس متوفرة كفيديوهات قصيرة. يمكنك العثور على جميع هذه الفيديوهات داخل الدروس، أو على [قائمة تشغيل تعلم الآلة للمبتدئين على قناة Microsoft Developer على YouTube](https://aka.ms/ml-beginners-videos) بالنقر على الصورة أدناه.
[![ML for beginners banner](../../translated_images/ml-for-beginners-video-banner.279f2a268d2130758668f4044f8c252d42f7c0a141c2cb56294c1ccc157cdd1c.ar.png)](https://aka.ms/ml-beginners-videos) [![ML for beginners banner](../../images/ml-for-beginners-video-banner.png)](https://aka.ms/ml-beginners-videos)
--- ---
## تعرف على الفريق ## تعرف على الفريق
[![Promo video](../../ml.gif)](https://youtu.be/Tj1XWrDSYJU "Promo video") [![Promo video](../../images/ml.gif)](https://youtu.be/Tj1XWrDSYJU)
**Gif بواسطة** [Mohit Jaisal](https://linkedin.com/in/mohitjaisal) **Gif بواسطة** [Mohit Jaisal](https://linkedin.com/in/mohitjaisal)
@ -85,18 +85,18 @@ CO_OP_TRANSLATOR_METADATA:
--- ---
## منهجية التعليم ## طريقة التدريس
لقد اخترنا مبدأين تعليميين أثناء بناء هذا المنهج: التأكد من أنه عملي **قائم على المشاريع** وأنه يتضمن **اختبارات متكررة**. بالإضافة إلى ذلك، يحتوي هذا المنهج على **موضوع مشترك** يمنحه التماسك. لقد اخترنا مبدأين تربويين أثناء بناء هذا المنهج: التأكد من أنه عملي **قائم على المشاريع** وأنه يتضمن **اختبارات متكررة**. بالإضافة إلى ذلك، يحتوي هذا المنهج على **موضوع مشترك** لإعطائه التماسك.
من خلال ضمان توافق المحتوى مع المشاريع، تصبح العملية أكثر جاذبية للطلاب ويتم تعزيز الاحتفاظ بالمفاهيم. بالإضافة إلى ذلك، يحدد الاختبار منخفض المخاطر قبل الفصل نية الطالب نحو تعلم موضوع معين، بينما يضمن الاختبار الثاني بعد الفصل تعزيز الاحتفاظ. تم تصميم هذا المنهج ليكون مرنًا وممتعًا ويمكن أخذه بالكامل أو جزئيًا. تبدأ المشاريع صغيرة وتصبح أكثر تعقيدًا بحلول نهاية الدورة التي تستغرق 12 أسبوعًا. يتضمن هذا المنهج أيضًا ملحقًا حول التطبيقات الواقعية لتعلم الآلة، والذي يمكن استخدامه كائتمان إضافي أو كأساس للنقاش. من خلال ضمان أن المحتوى يتماشى مع المشاريع، تصبح العملية أكثر جاذبية للطلاب ويتم تعزيز الاحتفاظ بالمفاهيم. بالإضافة إلى ذلك، يحدد الاختبار منخفض المخاطر قبل الفصل نية الطالب نحو تعلم موضوع معين، بينما يضمن الاختبار الثاني بعد الفصل تعزيز الاحتفاظ. تم تصميم هذا المنهج ليكون مرنًا وممتعًا ويمكن أخذه بالكامل أو جزئيًا. تبدأ المشاريع صغيرة وتصبح أكثر تعقيدًا بحلول نهاية الدورة التي تستغرق 12 أسبوعًا. يتضمن هذا المنهج أيضًا ملحقًا حول التطبيقات الواقعية لتعلم الآلة، والذي يمكن استخدامه كائتمان إضافي أو كأساس للنقاش.
> اعثر على [مدونة قواعد السلوك](CODE_OF_CONDUCT.md)، [المساهمة](CONTRIBUTING.md)، و[إرشادات الترجمة](TRANSLATIONS.md). نرحب بملاحظاتك البناءة! > اعثر على [مدونة قواعد السلوك](CODE_OF_CONDUCT.md)، [المساهمة](CONTRIBUTING.md)، و[إرشادات الترجمة](TRANSLATIONS.md). نرحب بملاحظاتك البناءة!
## يتضمن كل درس ## كل درس يتضمن
- رسم تخطيطي اختياري - رسم تخطيطي اختياري
- فيديو إضافي اختياري - فيديو تكميلي اختياري
- فيديو توضيحي (بعض الدروس فقط) - فيديو توضيحي (بعض الدروس فقط)
- اختبار تمهيدي قبل المحاضرة - اختبار تمهيدي قبل المحاضرة
- درس مكتوب - درس مكتوب
@ -107,7 +107,7 @@ CO_OP_TRANSLATOR_METADATA:
- مهمة - مهمة
- اختبار بعد المحاضرة - اختبار بعد المحاضرة
> **ملاحظة حول اللغات**: هذه الدروس مكتوبة بشكل أساسي بلغة Python، ولكن العديد منها متوفر أيضًا بلغة R. لإكمال درس بلغة R، انتقل إلى مجلد `/solution` وابحث عن دروس R. تتضمن امتداد .rmd الذي يمثل ملف **R Markdown** والذي يمكن تعريفه ببساطة على أنه تضمين لـ `كتل الكود` (بلغة R أو لغات أخرى) و`رأس YAML` (الذي يوجه كيفية تنسيق المخرجات مثل PDF) في مستند `Markdown`. وبالتالي، فإنه يعمل كإطار عمل تأليفي مثالي لعلم البيانات لأنه يسمح لك بدمج الكود الخاص بك، ومخرجاته، وأفكارك من خلال السماح لك بكتابتها في Markdown. علاوة على ذلك، يمكن عرض مستندات R Markdown بتنسيقات إخراج مثل PDF أو HTML أو Word. > **ملاحظة حول اللغات**: هذه الدروس مكتوبة بشكل أساسي بلغة Python، ولكن العديد منها متوفر أيضًا بلغة R. لإكمال درس بلغة R، انتقل إلى مجلد `/solution` وابحث عن دروس R. تتضمن امتداد .rmd الذي يمثل ملف **R Markdown** والذي يمكن تعريفه ببساطة على أنه تضمين لـ `كتل الكود` (بلغة R أو لغات أخرى) و`رأس YAML` (الذي يوجه كيفية تنسيق المخرجات مثل PDF) في `وثيقة Markdown`. وبالتالي، فإنه يعمل كإطار عمل تأليفي مثالي لعلم البيانات لأنه يسمح لك بدمج الكود الخاص بك، ومخرجاته، وأفكارك من خلال السماح لك بكتابتها في Markdown. علاوة على ذلك، يمكن عرض مستندات R Markdown بتنسيقات إخراج مثل PDF أو HTML أو Word.
> **ملاحظة حول الاختبارات**: جميع الاختبارات موجودة في [مجلد تطبيق الاختبار](../../quiz-app)، بإجمالي 52 اختبارًا يحتوي كل منها على ثلاثة أسئلة. يتم ربطها من داخل الدروس ولكن يمكن تشغيل تطبيق الاختبار محليًا؛ اتبع التعليمات في مجلد `quiz-app` لاستضافة التطبيق محليًا أو نشره على Azure. > **ملاحظة حول الاختبارات**: جميع الاختبارات موجودة في [مجلد تطبيق الاختبار](../../quiz-app)، بإجمالي 52 اختبارًا يحتوي كل منها على ثلاثة أسئلة. يتم ربطها من داخل الدروس ولكن يمكن تشغيل تطبيق الاختبار محليًا؛ اتبع التعليمات في مجلد `quiz-app` لاستضافة التطبيق محليًا أو نشره على Azure.
@ -117,11 +117,11 @@ CO_OP_TRANSLATOR_METADATA:
| 02 | تاريخ تعلم الآلة | [المقدمة](1-Introduction/README.md) | تعلم التاريخ الذي يقوم عليه هذا المجال | [الدرس](1-Introduction/2-history-of-ML/README.md) | جين وأيمي | | 02 | تاريخ تعلم الآلة | [المقدمة](1-Introduction/README.md) | تعلم التاريخ الذي يقوم عليه هذا المجال | [الدرس](1-Introduction/2-history-of-ML/README.md) | جين وأيمي |
| 03 | الإنصاف وتعلم الآلة | [المقدمة](1-Introduction/README.md) | ما هي القضايا الفلسفية المهمة حول الإنصاف التي يجب أن يأخذها الطلاب في الاعتبار عند بناء وتطبيق نماذج تعلم الآلة؟ | [الدرس](1-Introduction/3-fairness/README.md) | تومومي | | 03 | الإنصاف وتعلم الآلة | [المقدمة](1-Introduction/README.md) | ما هي القضايا الفلسفية المهمة حول الإنصاف التي يجب أن يأخذها الطلاب في الاعتبار عند بناء وتطبيق نماذج تعلم الآلة؟ | [الدرس](1-Introduction/3-fairness/README.md) | تومومي |
| 04 | تقنيات تعلم الآلة | [المقدمة](1-Introduction/README.md) | ما هي التقنيات التي يستخدمها الباحثون في تعلم الآلة لبناء نماذج تعلم الآلة؟ | [الدرس](1-Introduction/4-techniques-of-ML/README.md) | كريس وجين | | 04 | تقنيات تعلم الآلة | [المقدمة](1-Introduction/README.md) | ما هي التقنيات التي يستخدمها الباحثون في تعلم الآلة لبناء نماذج تعلم الآلة؟ | [الدرس](1-Introduction/4-techniques-of-ML/README.md) | كريس وجين |
| 05 | مقدمة في الانحدار | [Regression](2-Regression/README.md) | ابدأ باستخدام Python و Scikit-learn لنماذج الانحدار | | 05 | مقدمة في الانحدار | [Regression](2-Regression/README.md) | البدء باستخدام Python و Scikit-learn لنماذج الانحدار |
<ul><li>[Python](2-Regression/1-Tools/README.md)</li><li>[R](../../2-Regression/1-Tools/solution/R/lesson_1.html)</li></ul> | <ul><li>جين</li><li>إريك وانجاو</li></ul> | <ul><li>[Python](2-Regression/1-Tools/README.md)</li><li>[R](../../2-Regression/1-Tools/solution/R/lesson_1.html)</li></ul> | <ul><li>جين</li><li>إريك وانجاو</li></ul> |
| 06 | أسعار القرع في أمريكا الشمالية 🎃 | [Regression](2-Regression/README.md) | تصور وتنظيف البيانات استعدادًا لتعلم الآلة | <ul><li>[Python](2-Regression/2-Data/README.md)</li><li>[R](../../2-Regression/2-Data/solution/R/lesson_2.html)</li></ul> | <ul><li>جين</li><li>إريك وانجاو</li></ul> | | 06 | أسعار اليقطين في أمريكا الشمالية 🎃 | [Regression](2-Regression/README.md) | تصور وتنظيف البيانات استعدادًا لتعلم الآلة | <ul><li>[Python](2-Regression/2-Data/README.md)</li><li>[R](../../2-Regression/2-Data/solution/R/lesson_2.html)</li></ul> | <ul><li>جين</li><li>إريك وانجاو</li></ul> |
| 07 | أسعار القرع في أمريكا الشمالية 🎃 | [Regression](2-Regression/README.md) | بناء نماذج الانحدار الخطي والانحدار متعدد الحدود | <ul><li>[Python](2-Regression/3-Linear/README.md)</li><li>[R](../../2-Regression/3-Linear/solution/R/lesson_3.html)</li></ul> | <ul><li>جين وديمتري</li><li>إريك وانجاو</li></ul> | | 07 | أسعار اليقطين في أمريكا الشمالية 🎃 | [Regression](2-Regression/README.md) | بناء نماذج الانحدار الخطي والمتعدد | <ul><li>[Python](2-Regression/3-Linear/README.md)</li><li>[R](../../2-Regression/3-Linear/solution/R/lesson_3.html)</li></ul> | <ul><li>جين وديمتري</li><li>إريك وانجاو</li></ul> |
| 08 | أسعار القرع في أمريكا الشمالية 🎃 | [Regression](2-Regression/README.md) | بناء نموذج الانحدار اللوجستي | <ul><li>[Python](2-Regression/4-Logistic/README.md) </li><li>[R](../../2-Regression/4-Logistic/solution/R/lesson_4.html)</li></ul> | <ul><li>جين</li><li>إريك وانجاو</li></ul> | | 08 | أسعار اليقطين في أمريكا الشمالية 🎃 | [Regression](2-Regression/README.md) | بناء نموذج الانحدار اللوجستي | <ul><li>[Python](2-Regression/4-Logistic/README.md) </li><li>[R](../../2-Regression/4-Logistic/solution/R/lesson_4.html)</li></ul> | <ul><li>جين</li><li>إريك وانجاو</li></ul> |
| 09 | تطبيق ويب 🔌 | [Web App](3-Web-App/README.md) | بناء تطبيق ويب لاستخدام النموذج المدرب | [Python](3-Web-App/1-Web-App/README.md) | جين | | 09 | تطبيق ويب 🔌 | [Web App](3-Web-App/README.md) | بناء تطبيق ويب لاستخدام النموذج المدرب | [Python](3-Web-App/1-Web-App/README.md) | جين |
| 10 | مقدمة في التصنيف | [Classification](4-Classification/README.md) | تنظيف البيانات وتحضيرها وتصورها؛ مقدمة في التصنيف | <ul><li> [Python](4-Classification/1-Introduction/README.md) </li><li>[R](../../4-Classification/1-Introduction/solution/R/lesson_10.html) | <ul><li>جين وكاسي</li><li>إريك وانجاو</li></ul> | | 10 | مقدمة في التصنيف | [Classification](4-Classification/README.md) | تنظيف البيانات وتحضيرها وتصورها؛ مقدمة في التصنيف | <ul><li> [Python](4-Classification/1-Introduction/README.md) </li><li>[R](../../4-Classification/1-Introduction/solution/R/lesson_10.html) | <ul><li>جين وكاسي</li><li>إريك وانجاو</li></ul> |
| 11 | المأكولات الآسيوية والهندية اللذيذة 🍜 | [Classification](4-Classification/README.md) | مقدمة في المصنفات | <ul><li> [Python](4-Classification/2-Classifiers-1/README.md)</li><li>[R](../../4-Classification/2-Classifiers-1/solution/R/lesson_11.html) | <ul><li>جين وكاسي</li><li>إريك وانجاو</li></ul> | | 11 | المأكولات الآسيوية والهندية اللذيذة 🍜 | [Classification](4-Classification/README.md) | مقدمة في المصنفات | <ul><li> [Python](4-Classification/2-Classifiers-1/README.md)</li><li>[R](../../4-Classification/2-Classifiers-1/solution/R/lesson_11.html) | <ul><li>جين وكاسي</li><li>إريك وانجاو</li></ul> |
@ -130,31 +130,31 @@ CO_OP_TRANSLATOR_METADATA:
| 14 | مقدمة في التجميع | [Clustering](5-Clustering/README.md) | تنظيف البيانات وتحضيرها وتصورها؛ مقدمة في التجميع | <ul><li> [Python](5-Clustering/1-Visualize/README.md)</li><li>[R](../../5-Clustering/1-Visualize/solution/R/lesson_14.html) | <ul><li>جين</li><li>إريك وانجاو</li></ul> | | 14 | مقدمة في التجميع | [Clustering](5-Clustering/README.md) | تنظيف البيانات وتحضيرها وتصورها؛ مقدمة في التجميع | <ul><li> [Python](5-Clustering/1-Visualize/README.md)</li><li>[R](../../5-Clustering/1-Visualize/solution/R/lesson_14.html) | <ul><li>جين</li><li>إريك وانجاو</li></ul> |
| 15 | استكشاف الأذواق الموسيقية النيجيرية 🎧 | [Clustering](5-Clustering/README.md) | استكشاف طريقة التجميع باستخدام K-Means | <ul><li> [Python](5-Clustering/2-K-Means/README.md)</li><li>[R](../../5-Clustering/2-K-Means/solution/R/lesson_15.html) | <ul><li>جين</li><li>إريك وانجاو</li></ul> | | 15 | استكشاف الأذواق الموسيقية النيجيرية 🎧 | [Clustering](5-Clustering/README.md) | استكشاف طريقة التجميع باستخدام K-Means | <ul><li> [Python](5-Clustering/2-K-Means/README.md)</li><li>[R](../../5-Clustering/2-K-Means/solution/R/lesson_15.html) | <ul><li>جين</li><li>إريك وانجاو</li></ul> |
| 16 | مقدمة في معالجة اللغة الطبيعية ☕️ | [Natural language processing](6-NLP/README.md) | تعلم الأساسيات حول معالجة اللغة الطبيعية من خلال بناء روبوت بسيط | [Python](6-NLP/1-Introduction-to-NLP/README.md) | ستيفن | | 16 | مقدمة في معالجة اللغة الطبيعية ☕️ | [Natural language processing](6-NLP/README.md) | تعلم الأساسيات حول معالجة اللغة الطبيعية من خلال بناء روبوت بسيط | [Python](6-NLP/1-Introduction-to-NLP/README.md) | ستيفن |
| 17 | مهام معالجة اللغة الطبيعية الشائعة ☕️ | [Natural language processing](6-NLP/README.md) | تعميق معرفتك بمعالجة اللغة الطبيعية من خلال فهم المهام الشائعة المطلوبة عند التعامل مع هياكل اللغة | [Python](6-NLP/2-Tasks/README.md) | ستيفن | | 17 | مهام معالجة اللغة الطبيعية الشائعة ☕️ | [Natural language processing](6-NLP/README.md) | تعميق المعرفة بمعالجة اللغة الطبيعية من خلال فهم المهام الشائعة المطلوبة عند التعامل مع الهياكل اللغوية | [Python](6-NLP/2-Tasks/README.md) | ستيفن |
| 18 | الترجمة وتحليل المشاعر ♥️ | [Natural language processing](6-NLP/README.md) | الترجمة وتحليل المشاعر مع جين أوستن | [Python](6-NLP/3-Translation-Sentiment/README.md) | ستيفن | | 18 | الترجمة وتحليل المشاعر ♥️ | [Natural language processing](6-NLP/README.md) | الترجمة وتحليل المشاعر باستخدام أعمال جين أوستن | [Python](6-NLP/3-Translation-Sentiment/README.md) | ستيفن |
| 19 | الفنادق الرومانسية في أوروبا ♥️ | [Natural language processing](6-NLP/README.md) | تحليل المشاعر مع مراجعات الفنادق 1 | [Python](6-NLP/4-Hotel-Reviews-1/README.md) | ستيفن | | 19 | الفنادق الرومانسية في أوروبا ♥️ | [Natural language processing](6-NLP/README.md) | تحليل المشاعر باستخدام مراجعات الفنادق 1 | [Python](6-NLP/4-Hotel-Reviews-1/README.md) | ستيفن |
| 20 | الفنادق الرومانسية في أوروبا ♥️ | [Natural language processing](6-NLP/README.md) | تحليل المشاعر مع مراجعات الفنادق 2 | [Python](6-NLP/5-Hotel-Reviews-2/README.md) | ستيفن | | 20 | الفنادق الرومانسية في أوروبا ♥️ | [Natural language processing](6-NLP/README.md) | تحليل المشاعر باستخدام مراجعات الفنادق 2 | [Python](6-NLP/5-Hotel-Reviews-2/README.md) | ستيفن |
| 21 | مقدمة في التنبؤ بالسلاسل الزمنية | [Time series](7-TimeSeries/README.md) | مقدمة في التنبؤ بالسلاسل الزمنية | [Python](7-TimeSeries/1-Introduction/README.md) | فرانشيسكا | | 21 | مقدمة في التنبؤ بالسلاسل الزمنية | [Time series](7-TimeSeries/README.md) | مقدمة في التنبؤ بالسلاسل الزمنية | [Python](7-TimeSeries/1-Introduction/README.md) | فرانشيسكا |
| 22 | ⚡️ استخدام الطاقة في العالم ⚡️ - التنبؤ بالسلاسل الزمنية باستخدام ARIMA | [Time series](7-TimeSeries/README.md) | التنبؤ بالسلاسل الزمنية باستخدام ARIMA | [Python](7-TimeSeries/2-ARIMA/README.md) | فرانشيسكا | | 22 | ⚡️ استخدام الطاقة العالمي ⚡️ - التنبؤ بالسلاسل الزمنية باستخدام ARIMA | [Time series](7-TimeSeries/README.md) | التنبؤ بالسلاسل الزمنية باستخدام ARIMA | [Python](7-TimeSeries/2-ARIMA/README.md) | فرانشيسكا |
| 23 | ⚡️ استخدام الطاقة في العالم ⚡️ - التنبؤ بالسلاسل الزمنية باستخدام SVR | [Time series](7-TimeSeries/README.md) | التنبؤ بالسلاسل الزمنية باستخدام Support Vector Regressor | [Python](7-TimeSeries/3-SVR/README.md) | أنيربان | | 23 | ⚡️ استخدام الطاقة العالمي ⚡️ - التنبؤ بالسلاسل الزمنية باستخدام SVR | [Time series](7-TimeSeries/README.md) | التنبؤ بالسلاسل الزمنية باستخدام Support Vector Regressor | [Python](7-TimeSeries/3-SVR/README.md) | أنيربان |
| 24 | مقدمة في التعلم المعزز | [Reinforcement learning](8-Reinforcement/README.md) | مقدمة في التعلم المعزز باستخدام Q-Learning | [Python](8-Reinforcement/1-QLearning/README.md) | ديمتري | | 24 | مقدمة في التعلم المعزز | [Reinforcement learning](8-Reinforcement/README.md) | مقدمة في التعلم المعزز باستخدام Q-Learning | [Python](8-Reinforcement/1-QLearning/README.md) | ديمتري |
| 25 | ساعد بيتر في تجنب الذئب! 🐺 | [Reinforcement learning](8-Reinforcement/README.md) | Gym التعلم المعزز | [Python](8-Reinforcement/2-Gym/README.md) | ديمتري | | 25 | مساعدة بيتر لتجنب الذئب! 🐺 | [Reinforcement learning](8-Reinforcement/README.md) | التعلم المعزز باستخدام Gym | [Python](8-Reinforcement/2-Gym/README.md) | ديمتري |
| Postscript | سيناريوهات وتطبيقات تعلم الآلة في العالم الحقيقي | [ML in the Wild](9-Real-World/README.md) | تطبيقات مثيرة وكاشفة لتعلم الآلة الكلاسيكي | [Lesson](9-Real-World/1-Applications/README.md) | الفريق | | Postscript | سيناريوهات وتطبيقات تعلم الآلة في العالم الحقيقي | [ML in the Wild](9-Real-World/README.md) | تطبيقات مثيرة وكاشفة لتعلم الآلة الكلاسيكي | [Lesson](9-Real-World/1-Applications/README.md) | الفريق |
| Postscript | تصحيح النماذج في تعلم الآلة باستخدام لوحة معلومات RAI | [ML in the Wild](9-Real-World/README.md) | تصحيح النماذج في تعلم الآلة باستخدام مكونات لوحة معلومات الذكاء الاصطناعي المسؤول | [Lesson](9-Real-World/2-Debugging-ML-Models/README.md) | روث ياكوب | | Postscript | تصحيح نماذج تعلم الآلة باستخدام لوحة تحكم الذكاء الاصطناعي المسؤول | [ML in the Wild](9-Real-World/README.md) | تصحيح نماذج تعلم الآلة باستخدام مكونات لوحة تحكم الذكاء الاصطناعي المسؤول | [Lesson](9-Real-World/2-Debugging-ML-Models/README.md) | روث ياكوب |
> [اعثر على جميع الموارد الإضافية لهذه الدورة في مجموعة Microsoft Learn الخاصة بنا](https://learn.microsoft.com/en-us/collections/qrqzamz1nn2wx3?WT.mc_id=academic-77952-bethanycheum) > [ابحث عن جميع الموارد الإضافية لهذه الدورة في مجموعة Microsoft Learn الخاصة بنا](https://learn.microsoft.com/en-us/collections/qrqzamz1nn2wx3?WT.mc_id=academic-77952-bethanycheum)
## الوصول دون اتصال ## الوصول دون اتصال
يمكنك تشغيل هذا التوثيق دون اتصال باستخدام [Docsify](https://docsify.js.org/#/). قم بعمل Fork لهذا المستودع، [قم بتثبيت Docsify](https://docsify.js.org/#/quickstart) على جهازك المحلي، ثم في المجلد الجذري لهذا المستودع، اكتب `docsify serve`. سيتم تشغيل الموقع على المنفذ 3000 على localhost الخاص بك: `localhost:3000`. يمكنك تشغيل هذا التوثيق دون اتصال باستخدام [Docsify](https://docsify.js.org/#/). قم باستنساخ هذا المستودع، [تثبيت Docsify](https://docsify.js.org/#/quickstart) على جهازك المحلي، ثم في المجلد الجذري لهذا المستودع، اكتب `docsify serve`. سيتم تشغيل الموقع على المنفذ 3000 على جهازك المحلي: `localhost:3000`.
## ملفات PDF ## ملفات PDF
اعثر على ملف PDF للمناهج مع الروابط [هنا](https://microsoft.github.io/ML-For-Beginners/pdf/readme.pdf). ابحث عن ملف PDF للمناهج مع الروابط [هنا](https://microsoft.github.io/ML-For-Beginners/pdf/readme.pdf).
## 🎒 دورات أخرى ## 🎒 دورات أخرى
فريقنا يقدم دورات أخرى! تحقق من: فريقنا ينتج دورات أخرى! تحقق من:
- [الذكاء الاصطناعي التوليدي للمبتدئين](https://aka.ms/genai-beginners) - [الذكاء الاصطناعي التوليدي للمبتدئين](https://aka.ms/genai-beginners)
- [الذكاء الاصطناعي التوليدي للمبتدئين .NET](https://github.com/microsoft/Generative-AI-for-beginners-dotnet) - [الذكاء الاصطناعي التوليدي للمبتدئين .NET](https://github.com/microsoft/Generative-AI-for-beginners-dotnet)
@ -174,4 +174,4 @@ CO_OP_TRANSLATOR_METADATA:
--- ---
**إخلاء المسؤولية**: **إخلاء المسؤولية**:
تم ترجمة هذا المستند باستخدام خدمة الترجمة بالذكاء الاصطناعي [Co-op Translator](https://github.com/Azure/co-op-translator). بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو معلومات غير دقيقة. يجب اعتبار المستند الأصلي بلغته الأصلية المصدر الرسمي. للحصول على معلومات حاسمة، يُوصى بالاستعانة بترجمة بشرية احترافية. نحن غير مسؤولين عن أي سوء فهم أو تفسيرات خاطئة تنشأ عن استخدام هذه الترجمة. تمت ترجمة هذا المستند باستخدام خدمة الترجمة الآلية [Co-op Translator](https://github.com/Azure/co-op-translator). بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو معلومات غير دقيقة. يجب اعتبار المستند الأصلي بلغته الأصلية هو المصدر الموثوق. للحصول على معلومات حساسة أو هامة، يُوصى بالاستعانة بترجمة بشرية احترافية. نحن غير مسؤولين عن أي سوء فهم أو تفسيرات خاطئة تنشأ عن استخدام هذه الترجمة.

@ -0,0 +1,447 @@
{
"nbformat": 4,
"nbformat_minor": 2,
"metadata": {
"colab": {
"name": "lesson_1-R.ipynb",
"provenance": [],
"collapsed_sections": [],
"toc_visible": true
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "c18d3bd0bd8ae3878597e89dcd1fa5c1",
"translation_date": "2025-09-04T07:03:05+00:00",
"source_file": "2-Regression/1-Tools/solution/R/lesson_1-R.ipynb",
"language_code": "bg"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "YJUHCXqK57yz"
}
},
{
"cell_type": "markdown",
"source": [
"## Въведение в регресията - Урок 1\n",
"\n",
"#### Поставяне в перспектива\n",
"\n",
"✅ Съществуват много видове методи за регресия, и изборът на подходящия зависи от въпроса, на който искате да отговорите. Ако искате да предвидите вероятната височина на човек на определена възраст, бихте използвали `линейна регресия`, тъй като търсите **числова стойност**. Ако се интересувате дали даден тип кухня трябва да се счита за веганска или не, търсите **категорийно определение**, затова бихте използвали `логистична регресия`. Ще научите повече за логистичната регресия по-късно. Помислете за някои въпроси, които можете да зададете на данните, и кой от тези методи би бил по-подходящ.\n",
"\n",
"В тази секция ще работите с [малък набор от данни за диабет](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html). Представете си, че искате да тествате лечение за пациенти с диабет. Моделите за машинно обучение могат да ви помогнат да определите кои пациенти биха реагирали по-добре на лечението, въз основа на комбинации от променливи. Дори един много базов модел за регресия, когато е визуализиран, може да покаже информация за променливи, които биха ви помогнали да организирате теоретичните си клинични изпитания.\n",
"\n",
"И така, нека започнем с тази задача!\n",
"\n",
"<p >\n",
" <img src=\"../../images/encouRage.jpg\"\n",
" width=\"630\"/>\n",
" <figcaption>Илюстрация от @allison_horst</figcaption>\n",
"\n",
"<!--![Илюстрация от \\@allison_horst](../../../../../../2-Regression/1-Tools/images/encouRage.jpg)<br>Илюстрация от @allison_horst-->\n"
],
"metadata": {
"id": "LWNNzfqd6feZ"
}
},
{
"cell_type": "markdown",
"source": [
"## 1. Зареждане на нашия инструментариум\n",
"\n",
"За тази задача ще ни трябват следните пакети:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) е [колекция от R пакети](https://www.tidyverse.org/packages), създадена да направи анализа на данни по-бърз, лесен и забавен!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) е [рамка от пакети](https://www.tidymodels.org/packages/) за моделиране и машинно обучение.\n",
"\n",
"Можете да ги инсталирате със следната команда:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\"))`\n",
"\n",
"Скриптът по-долу проверява дали имате необходимите пакети за завършване на този модул и ги инсталира, ако някои липсват.\n"
],
"metadata": {
"id": "FIo2YhO26wI9"
}
},
{
"cell_type": "code",
"execution_count": 2,
"source": [
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n",
"pacman::p_load(tidyverse, tidymodels)"
],
"outputs": [
{
"output_type": "stream",
"name": "stderr",
"text": [
"Loading required package: pacman\n",
"\n"
]
}
],
"metadata": {
"id": "cIA9fz9v7Dss",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "2df7073b-86b2-4b32-cb86-0da605a0dc11"
}
},
{
"cell_type": "markdown",
"source": [
"Сега нека заредим тези страхотни пакети и да ги направим достъпни в текущата ни R сесия. (Това е само за илюстрация, `pacman::p_load()` вече го направи за вас)\n"
],
"metadata": {
"id": "gpO_P_6f9WUG"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# load the core Tidyverse packages\r\n",
"library(tidyverse)\r\n",
"\r\n",
"# load the core Tidymodels packages\r\n",
"library(tidymodels)\r\n"
],
"outputs": [],
"metadata": {
"id": "NLMycgG-9ezO"
}
},
{
"cell_type": "markdown",
"source": [
"## 2. Диабетният набор от данни\n",
"\n",
"В това упражнение ще демонстрираме уменията си за регресия, като правим прогнози върху набор от данни за диабет. [Диабетният набор от данни](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.rwrite1.txt) включва `442 проби` с данни за диабет, с 10 променливи за прогнозиране: `възраст`, `пол`, `индекс на телесна маса`, `средно кръвно налягане` и `шест измервания на кръвния серум`, както и променлива за резултат `y`: количествена мярка за прогресията на заболяването една година след началната точка.\n",
"\n",
"|Брой наблюдения|442|\n",
"|----------------------|:---|\n",
"|Брой предиктори|Първите 10 колони са числови предиктивни|\n",
"|Резултат/Цел|Колона 11 е количествена мярка за прогресията на заболяването една година след началната точка|\n",
"|Информация за предикторите|- възраст в години\n",
"||- пол\n",
"||- bmi индекс на телесна маса\n",
"||- bp средно кръвно налягане\n",
"||- s1 tc, общ серумен холестерол\n",
"||- s2 ldl, липопротеини с ниска плътност\n",
"||- s3 hdl, липопротеини с висока плътност\n",
"||- s4 tch, общ холестерол / HDL\n",
"||- s5 ltg, вероятно логаритъм на нивото на серумните триглицериди\n",
"||- s6 glu, ниво на кръвна захар|\n",
"\n",
"> 🎓 Запомнете, това е контролирано обучение и ни е необходима целева променлива 'y'.\n",
"\n",
"Преди да можете да манипулирате данни с R, трябва да импортирате данните в паметта на R или да изградите връзка към данните, която R може да използва за достъп до тях дистанционно.\n",
"\n",
"> Пакетът [readr](https://readr.tidyverse.org/), който е част от Tidyverse, предоставя бърз и удобен начин за четене на правоъгълни данни в R.\n",
"\n",
"Сега, нека заредим диабетния набор от данни, предоставен на този URL адрес: <https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html>\n",
"\n",
"Също така ще направим проверка на данните с помощта на `glimpse()` и ще покажем първите 5 реда с помощта на `slice()`.\n",
"\n",
"Преди да продължим, нека въведем нещо, което често ще срещате в R код 🥁🥁: операторът pipe `%>%`\n",
"\n",
"Операторът pipe (`%>%`) изпълнява операции в логическа последователност, като предава обект напред към функция или израз за извикване. Можете да мислите за оператора pipe като \"и след това\" във вашия код.\n"
],
"metadata": {
"id": "KM6iXLH996Cl"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Import the data set\r\n",
"diabetes <- read_table2(file = \"https://www4.stat.ncsu.edu/~boos/var.select/diabetes.rwrite1.txt\")\r\n",
"\r\n",
"\r\n",
"# Get a glimpse and dimensions of the data\r\n",
"glimpse(diabetes)\r\n",
"\r\n",
"\r\n",
"# Select the first 5 rows of the data\r\n",
"diabetes %>% \r\n",
" slice(1:5)"
],
"outputs": [],
"metadata": {
"id": "Z1geAMhM-bSP"
}
},
{
"cell_type": "markdown",
"source": [
"`glimpse()` ни показва, че тези данни съдържат 442 реда и 11 колони, като всички колони са от тип данни `double`.\n",
"\n",
"<br>\n",
"\n",
"> glimpse() и slice() са функции в [`dplyr`](https://dplyr.tidyverse.org/). Dplyr, част от Tidyverse, е граматика за манипулиране на данни, която предоставя последователен набор от действия, помагащи за решаването на най-често срещаните предизвикателства при обработката на данни.\n",
"\n",
"<br>\n",
"\n",
"Сега, след като разполагаме с данните, нека се фокусираме върху една характеристика (`bmi`), която ще използваме за тази задача. Това ще изисква да изберем желаните колони. Как можем да направим това?\n",
"\n",
"[`dplyr::select()`](https://dplyr.tidyverse.org/reference/select.html) ни позволява да *изберем* (и при нужда да преименуваме) колони в дадена таблица с данни.\n"
],
"metadata": {
"id": "UwjVT1Hz-c3Z"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Select predictor feature `bmi` and outcome `y`\r\n",
"diabetes_select <- diabetes %>% \r\n",
" select(c(bmi, y))\r\n",
"\r\n",
"# Print the first 5 rows\r\n",
"diabetes_select %>% \r\n",
" slice(1:10)"
],
"outputs": [],
"metadata": {
"id": "RDY1oAKI-m80"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Данни за обучение и тестване\n",
"\n",
"Обичайна практика в контролираното обучение е *разделянето* на данните на два подмножества: (обикновено по-голям) набор за обучение на модела и по-малък \"задържан\" набор, с който да се провери как се е представил моделът.\n",
"\n",
"Сега, когато имаме готови данни, можем да видим дали машината може да помогне да се определи логично разделение между числата в този набор от данни. Можем да използваме пакета [rsample](https://tidymodels.github.io/rsample/), който е част от рамката Tidymodels, за да създадем обект, който съдържа информация за *как* да се разделят данните, а след това още две функции от rsample, за да извлечем създадените набори за обучение и тестване:\n"
],
"metadata": {
"id": "SDk668xK-tc3"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"set.seed(2056)\r\n",
"# Split 67% of the data for training and the rest for tesing\r\n",
"diabetes_split <- diabetes_select %>% \r\n",
" initial_split(prop = 0.67)\r\n",
"\r\n",
"# Extract the resulting train and test sets\r\n",
"diabetes_train <- training(diabetes_split)\r\n",
"diabetes_test <- testing(diabetes_split)\r\n",
"\r\n",
"# Print the first 3 rows of the training set\r\n",
"diabetes_train %>% \r\n",
" slice(1:10)"
],
"outputs": [],
"metadata": {
"id": "EqtHx129-1h-"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. Обучение на модел за линейна регресия с Tidymodels\n",
"\n",
"Сега сме готови да обучим нашия модел!\n",
"\n",
"В Tidymodels моделите се задават с помощта на `parsnip()` чрез определяне на три концепции:\n",
"\n",
"- **Типът** на модела разграничава различни модели като линейна регресия, логистична регресия, модели с дървета за решения и други.\n",
"\n",
"- **Режимът** на модела включва често срещани опции като регресия и класификация; някои типове модели поддържат и двете, докато други имат само един режим.\n",
"\n",
"- **Енджинът** на модела е изчислителният инструмент, който ще се използва за настройка на модела. Често това са R пакети, като **`\"lm\"`** или **`\"ranger\"`**\n",
"\n",
"Тази информация за модела се съхранява в спецификация на модела, така че нека създадем такава!\n"
],
"metadata": {
"id": "sBOS-XhB-6v7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Build a linear model specification\r\n",
"lm_spec <- \r\n",
" # Type\r\n",
" linear_reg() %>% \r\n",
" # Engine\r\n",
" set_engine(\"lm\") %>% \r\n",
" # Mode\r\n",
" set_mode(\"regression\")\r\n",
"\r\n",
"\r\n",
"# Print the model specification\r\n",
"lm_spec"
],
"outputs": [],
"metadata": {
"id": "20OwEw20--t3"
}
},
{
"cell_type": "markdown",
"source": [
"След като моделът бъде *определен*, той може да бъде `оценен` или `обучен`, като се използва функцията [`fit()`](https://parsnip.tidymodels.org/reference/fit.html), обикновено с помощта на формула и някакви данни.\n",
"\n",
"`y ~ .` означава, че ще напаснем `y` като предсказваната стойност/цел, обяснена от всички предиктори/характеристики, т.е. `.` (в този случай имаме само един предиктор: `bmi`).\n"
],
"metadata": {
"id": "_oDHs89k_CJj"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Build a linear model specification\r\n",
"lm_spec <- linear_reg() %>% \r\n",
" set_engine(\"lm\") %>%\r\n",
" set_mode(\"regression\")\r\n",
"\r\n",
"\r\n",
"# Train a linear regression model\r\n",
"lm_mod <- lm_spec %>% \r\n",
" fit(y ~ ., data = diabetes_train)\r\n",
"\r\n",
"# Print the model\r\n",
"lm_mod"
],
"outputs": [],
"metadata": {
"id": "YlsHqd-q_GJQ"
}
},
{
"cell_type": "markdown",
"source": [
"От модела можем да видим коефициентите, научени по време на обучението. Те представляват коефициентите на линията на най-добро съответствие, която ни дава най-ниската обща грешка между действителната и прогнозната променлива.\n",
"<br>\n",
"\n",
"## 5. Направете прогнози върху тестовия набор\n",
"\n",
"Сега, след като сме обучили модел, можем да го използваме, за да прогнозираме прогресията на заболяването y за тестовия набор от данни, използвайки [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Това ще се използва за начертаване на линията между групите данни.\n"
],
"metadata": {
"id": "kGZ22RQj_Olu"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make predictions for the test set\r\n",
"predictions <- lm_mod %>% \r\n",
" predict(new_data = diabetes_test)\r\n",
"\r\n",
"# Print out some of the predictions\r\n",
"predictions %>% \r\n",
" slice(1:5)"
],
"outputs": [],
"metadata": {
"id": "nXHbY7M2_aao"
}
},
{
"cell_type": "markdown",
"source": [
"Ура! 💃🕺 Току-що обучихме модел и го използвахме за правене на прогнози!\n",
"\n",
"При правене на прогнози, конвенцията на tidymodels е винаги да се създава tibble/data frame с резултати и стандартизирани имена на колони. Това улеснява комбинирането на оригиналните данни и прогнозите в удобен формат за последващи операции като визуализация.\n",
"\n",
"`dplyr::bind_cols()` ефективно свързва множество data frame-ове по колони.\n"
],
"metadata": {
"id": "R_JstwUY_bIs"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Combine the predictions and the original test set\r\n",
"results <- diabetes_test %>% \r\n",
" bind_cols(predictions)\r\n",
"\r\n",
"\r\n",
"results %>% \r\n",
" slice(1:5)"
],
"outputs": [],
"metadata": {
"id": "RybsMJR7_iI8"
}
},
{
"cell_type": "markdown",
"source": [
"## 6. Визуализация на резултатите от модела\n",
"\n",
"Сега е време да видим това визуално 📈. Ще създадем разпръснат график на всички стойности на `y` и `bmi` от тестовия набор, след което ще използваме прогнозите, за да начертаем линия на най-подходящото място, между групите данни на модела.\n",
"\n",
"R има няколко системи за създаване на графики, но `ggplot2` е една от най-елегантните и най-гъвкавите. Това ви позволява да съставяте графики чрез **комбиниране на независими компоненти**.\n"
],
"metadata": {
"id": "XJbYbMZW_n_s"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Set a theme for the plot\r\n",
"theme_set(theme_light())\r\n",
"# Create a scatter plot\r\n",
"results %>% \r\n",
" ggplot(aes(x = bmi)) +\r\n",
" # Add a scatter plot\r\n",
" geom_point(aes(y = y), size = 1.6) +\r\n",
" # Add a line plot\r\n",
" geom_line(aes(y = .pred), color = \"blue\", size = 1.5)"
],
"outputs": [],
"metadata": {
"id": "R9tYp3VW_sTn"
}
},
{
"cell_type": "markdown",
"source": [
"✅ Помислете малко какво се случва тук. Една права линия минава през множество малки точки от данни, но какво точно прави тя? Можете ли да видите как бихте могли да използвате тази линия, за да предвидите къде нова, невиждана досега точка от данни би трябвало да се впише спрямо оста y на графиката? Опитайте се да опишете с думи практическото приложение на този модел.\n",
"\n",
"Поздравления, създадохте първия си модел за линейна регресия, направихте предсказание с него и го визуализирахте в графика!\n"
],
"metadata": {
"id": "zrPtHIxx_tNI"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,46 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3-final"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python3",
"display_name": "Python 3",
"language": "python"
},
"coopTranslator": {
"original_hash": "1b2ab303ac6c604a34c6ca7a49077fc7",
"translation_date": "2025-09-04T07:10:44+00:00",
"source_file": "2-Regression/2-Data/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,672 @@
{
"nbformat": 4,
"nbformat_minor": 2,
"metadata": {
"colab": {
"name": "lesson_2-R.ipynb",
"provenance": [],
"collapsed_sections": [],
"toc_visible": true
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "f3c335f9940cfd76528b3ef918b9b342",
"translation_date": "2025-09-04T07:13:06+00:00",
"source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb",
"language_code": "bg"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [
"# Създаване на регресионен модел: подготовка и визуализация на данни\n",
"\n",
"## **Линейна регресия за тикви - Урок 2**\n",
"#### Въведение\n",
"\n",
"Сега, когато разполагате с инструментите, необходими за изграждане на модели за машинно обучение с Tidymodels и Tidyverse, сте готови да започнете да задавате въпроси към вашите данни. Докато работите с данни и прилагате решения за машинно обучение, е изключително важно да разберете как да зададете правилния въпрос, за да отключите потенциала на вашия набор от данни.\n",
"\n",
"В този урок ще научите:\n",
"\n",
"- Как да подготвите данните си за изграждане на модел.\n",
"\n",
"- Как да използвате `ggplot2` за визуализация на данни.\n",
"\n",
"Въпросът, на който искате да получите отговор, ще определи какъв тип алгоритми за машинно обучение ще използвате. А качеството на отговора, който ще получите, ще зависи в голяма степен от естеството на вашите данни.\n",
"\n",
"Нека видим това чрез практическо упражнение.\n",
"\n",
"<p >\n",
" <img src=\"../../images/unruly_data.jpg\"\n",
" width=\"700\"/>\n",
" <figcaption>Илюстрация от @allison_horst</figcaption>\n",
"\n",
"\n",
"<!--![Илюстрация от \\@allison_horst](../../../../../../2-Regression/2-Data/images/unruly_data.jpg)<br>Илюстрация от \\@allison_horst-->\n"
],
"metadata": {
"id": "Pg5aexcOPqAZ"
}
},
{
"cell_type": "markdown",
"source": [
"## 1. Импортиране на данни за тикви и извикване на Tidyverse\n",
"\n",
"Ще ни трябват следните пакети, за да обработим този урок:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) е [колекция от R пакети](https://www.tidyverse.org/packages), създадена да направи науката за данни по-бърза, лесна и забавна!\n",
"\n",
"Можете да ги инсталирате със следната команда:\n",
"\n",
"`install.packages(c(\"tidyverse\"))`\n",
"\n",
"Скриптът по-долу проверява дали имате необходимите пакети за завършване на този модул и ги инсталира, ако някои липсват.\n"
],
"metadata": {
"id": "dc5WhyVdXAjR"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n",
"pacman::p_load(tidyverse)"
],
"outputs": [],
"metadata": {
"id": "GqPYUZgfXOBt"
}
},
{
"cell_type": "markdown",
"source": [
"Сега нека стартираме някои пакети и заредим [данните](https://github.com/microsoft/ML-For-Beginners/blob/main/2-Regression/data/US-pumpkins.csv), предоставени за този урок!\n"
],
"metadata": {
"id": "kvjDTPDSXRr2"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load the core Tidyverse packages\n",
"library(tidyverse)\n",
"\n",
"# Import the pumpkins data\n",
"pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\")\n",
"\n",
"\n",
"# Get a glimpse and dimensions of the data\n",
"glimpse(pumpkins)\n",
"\n",
"\n",
"# Print the first 50 rows of the data set\n",
"pumpkins %>% \n",
" slice_head(n =50)"
],
"outputs": [],
"metadata": {
"id": "VMri-t2zXqgD"
}
},
{
"cell_type": "markdown",
"source": [
"Един бърз `glimpse()` веднага показва, че има празни стойности и смесица от низове (`chr`) и числови данни (`dbl`). `Date` е от тип символен низ, а има и странна колона, наречена `Package`, където данните са смесица от `sacks`, `bins` и други стойности. Данните, всъщност, са малко хаотични 😤.\n",
"\n",
"Всъщност, не е много често да получите набор от данни, който е напълно готов за създаване на ML модел директно. Но не се притеснявайте, в този урок ще научите как да подготвите суров набор от данни, използвайки стандартни библиотеки на R 🧑‍🔧. Също така ще научите различни техники за визуализиране на данните.📈📊\n",
"<br>\n",
"\n",
"> Припомняне: Операторът за тръбопровод (`%>%`) изпълнява операции в логическа последователност, като предава обект напред към функция или израз. Можете да мислите за оператора за тръбопровод като за \"и след това\" във вашия код.\n"
],
"metadata": {
"id": "REWcIv9yX29v"
}
},
{
"cell_type": "markdown",
"source": [
"## 2. Проверка за липсващи данни\n",
"\n",
"Един от най-често срещаните проблеми, с които се сблъскват специалистите по данни, е непълните или липсващи данни. В R липсващите или неизвестни стойности се представят със специална стойност: `NA` (Not Available).\n",
"\n",
"Как можем да разберем дали дадена таблица с данни съдържа липсващи стойности? \n",
"<br>\n",
"- Един директен начин е да използваме базовата R функция `anyNA`, която връща логическите стойности `TRUE` или `FALSE`.\n"
],
"metadata": {
"id": "Zxfb3AM5YbUe"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" anyNA()"
],
"outputs": [],
"metadata": {
"id": "G--DQutAYltj"
}
},
{
"cell_type": "markdown",
"source": [
"Чудесно, изглежда, че липсват някои данни! Това е добро място за начало.\n",
"\n",
"- Друг начин би бил да използвате функцията `is.na()`, която показва кои отделни елементи в колоните липсват с логическа стойност `TRUE`.\n"
],
"metadata": {
"id": "mU-7-SB6YokF"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" is.na() %>% \n",
" head(n = 7)"
],
"outputs": [],
"metadata": {
"id": "W-DxDOR4YxSW"
}
},
{
"cell_type": "markdown",
"source": [
"Добре, свършихме работата, но с толкова голяма таблица като тази би било неефективно и практически невъзможно да се прегледат всички редове и колони индивидуално😴.\n",
"\n",
"- По-интуитивен начин би бил да се изчисли сумата на липсващите стойности за всяка колона:\n"
],
"metadata": {
"id": "xUWxipKYY0o7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" is.na() %>% \n",
" colSums()"
],
"outputs": [],
"metadata": {
"id": "ZRBWV6P9ZArL"
}
},
{
"cell_type": "markdown",
"source": [
"Много по-добре! Липсват данни, но може би това няма да е от значение за задачата. Нека видим какво ще покаже по-нататъшният анализ.\n",
"\n",
"> Освен страхотните пакети и функции, R разполага с много добра документация. Например, използвайте `help(colSums)` или `?colSums`, за да научите повече за функцията.\n"
],
"metadata": {
"id": "9gv-crB6ZD1Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Dplyr: Граматика на манипулиране на данни\n",
"\n",
"<p >\n",
" <img src=\"../../images/dplyr_wrangling.png\"\n",
" width=\"569\"/>\n",
" <figcaption>Илюстрация от @allison_horst</figcaption>\n",
"\n",
"\n",
"<!--![Илюстрация от \\@allison_horst](../../../../../../2-Regression/2-Data/images/dplyr_wrangling.png)<br/>Илюстрация от \\@allison_horst-->\n"
],
"metadata": {
"id": "o4jLY5-VZO2C"
}
},
{
"cell_type": "markdown",
"source": [
"[`dplyr`](https://dplyr.tidyverse.org/), пакет от Tidyverse, е граматика за манипулиране на данни, която предоставя последователен набор от глаголи, които ви помагат да решите най-често срещаните предизвикателства при обработката на данни. В този раздел ще разгледаме някои от глаголите на dplyr!\n",
"<br>\n"
],
"metadata": {
"id": "i5o33MQBZWWw"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::select()\n",
"\n",
"`select()` е функция в пакета `dplyr`, която ви помага да изберете колони, които да запазите или изключите.\n",
"\n",
"За да направите вашата таблица с данни по-лесна за работа, премахнете няколко от нейните колони, използвайки `select()`, като запазите само колоните, които са ви необходими.\n",
"\n",
"Например, в това упражнение нашият анализ ще включва колоните `Package`, `Low Price`, `High Price` и `Date`. Нека изберем тези колони.\n"
],
"metadata": {
"id": "x3VGMAGBZiUr"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Select desired columns\n",
"pumpkins <- pumpkins %>% \n",
" select(Package, `Low Price`, `High Price`, Date)\n",
"\n",
"\n",
"# Print data set\n",
"pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "F_FgxQnVZnM0"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::mutate()\n",
"\n",
"`mutate()` е функция в пакета `dplyr`, която ви помага да създавате или модифицирате колони, като запазвате съществуващите колони.\n",
"\n",
"Общата структура на `mutate` е:\n",
"\n",
"`data %>% mutate(new_column_name = what_it_contains)`\n",
"\n",
"Нека използваме `mutate` върху колоната `Date`, като извършим следните операции:\n",
"\n",
"1. Конвертирайте датите (в момента от тип символ) във формат за месец (това са американски дати, така че форматът е `MM/DD/YYYY`).\n",
"\n",
"2. Извлечете месеца от датите в нова колона.\n",
"\n",
"В R, пакетът [lubridate](https://lubridate.tidyverse.org/) улеснява работата с данни от тип дата и час. Затова нека използваме `dplyr::mutate()`, `lubridate::mdy()`, `lubridate::month()` и да видим как да постигнем горните цели. Можем да премахнем колоната `Date`, тъй като няма да ни е необходима за следващите операции.\n"
],
"metadata": {
"id": "2KKo0Ed9Z1VB"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load lubridate\n",
"library(lubridate)\n",
"\n",
"pumpkins <- pumpkins %>% \n",
" # Convert the Date column to a date object\n",
" mutate(Date = mdy(Date)) %>% \n",
" # Extract month from Date\n",
" mutate(Month = month(Date)) %>% \n",
" # Drop Date column\n",
" select(-Date)\n",
"\n",
"# View the first few rows\n",
"pumpkins %>% \n",
" slice_head(n = 7)"
],
"outputs": [],
"metadata": {
"id": "5joszIVSZ6xe"
}
},
{
"cell_type": "markdown",
"source": [
"Ура! 🤩\n",
"\n",
"Следващата стъпка е да създадем нова колона `Price`, която представлява средната цена на тиква. Сега, нека изчислим средната стойност на колоните `Low Price` и `High Price`, за да попълним новата колона Price.\n",
"<br>\n"
],
"metadata": {
"id": "nIgLjNMCZ-6Y"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Create a new column Price\n",
"pumpkins <- pumpkins %>% \n",
" mutate(Price = (`Low Price` + `High Price`)/2)\n",
"\n",
"# View the first few rows of the data\n",
"pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "Zo0BsqqtaJw2"
}
},
{
"cell_type": "markdown",
"source": [
"Дааа!💪\n",
"\n",
"„Но чакай малко!“, ще кажете, след като прегледате целия набор от данни с `View(pumpkins)`, „Тук има нещо странно!“🤔\n",
"\n",
"Ако погледнете колоната `Package`, тиквите се продават в много различни конфигурации. Някои се продават в мерки от `1 1/9 bushel`, други в мерки от `1/2 bushel`, някои на тиква, някои на килограм, а някои в големи кутии с различни ширини.\n",
"\n",
"Нека проверим това:\n"
],
"metadata": {
"id": "p77WZr-9aQAR"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Verify the distinct observations in Package column\n",
"pumpkins %>% \n",
" distinct(Package)"
],
"outputs": [],
"metadata": {
"id": "XISGfh0IaUy6"
}
},
{
"cell_type": "markdown",
"source": [
"Невероятно!👏\n",
"\n",
"Тиквите изглежда са много трудни за претегляне по последователен начин, затова нека ги филтрираме, като изберем само тиквите със стринга *bushel* в колоната `Package` и поставим това в новия датафрейм `new_pumpkins`.\n"
],
"metadata": {
"id": "7sMjiVujaZxY"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::filter() и stringr::str_detect()\n",
"\n",
"[`dplyr::filter()`](https://dplyr.tidyverse.org/reference/filter.html): създава подмножество от данни, съдържащо само **редове**, които отговарят на вашите условия, в този случай тикви със стринга *bushel* в колоната `Package`.\n",
"\n",
"[stringr::str_detect()](https://stringr.tidyverse.org/reference/str_detect.html): открива наличието или отсъствието на даден шаблон в стринг.\n",
"\n",
"Пакетът [`stringr`](https://github.com/tidyverse/stringr) предоставя лесни функции за често срещани операции със стрингове.\n"
],
"metadata": {
"id": "L8Qfcs92ageF"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Retain only pumpkins with \"bushel\"\n",
"new_pumpkins <- pumpkins %>% \n",
" filter(str_detect(Package, \"bushel\"))\n",
"\n",
"# Get the dimensions of the new data\n",
"dim(new_pumpkins)\n",
"\n",
"# View a few rows of the new data\n",
"new_pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "hy_SGYREampd"
}
},
{
"cell_type": "markdown",
"source": [
"Можете да видите, че сме стеснили избора до около 415 реда данни, съдържащи тикви на едро.🤩 \n",
"<br>\n"
],
"metadata": {
"id": "VrDwF031avlR"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::case_when()\n",
"\n",
"**Но чакайте! Има още нещо, което трябва да направите**\n",
"\n",
"Забелязахте ли, че количеството в бушел варира за всеки ред? Трябва да нормализирате цените, така че да показвате цената на бушел, а не на 1 1/9 или 1/2 бушел. Време е за малко математика, за да я стандартизирате.\n",
"\n",
"Ще използваме функцията [`case_when()`](https://dplyr.tidyverse.org/reference/case_when.html), за да *променим* колоната Price в зависимост от някои условия. `case_when` ви позволява да векторизирате множество изрази `if_else()`.\n"
],
"metadata": {
"id": "mLpw2jH4a0tx"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Convert the price if the Package contains fractional bushel values\n",
"new_pumpkins <- new_pumpkins %>% \n",
" mutate(Price = case_when(\n",
" str_detect(Package, \"1 1/9\") ~ Price/(1 + 1/9),\n",
" str_detect(Package, \"1/2\") ~ Price/(1/2),\n",
" TRUE ~ Price))\n",
"\n",
"# View the first few rows of the data\n",
"new_pumpkins %>% \n",
" slice_head(n = 30)"
],
"outputs": [],
"metadata": {
"id": "P68kLVQmbM6I"
}
},
{
"cell_type": "markdown",
"source": [
"Сега можем да анализираме цената на единица въз основа на измерването им в бушели. Цялото това изследване на бушели с тикви обаче показва колко `важно` е да `разберем естеството на данните си`!\n",
"\n",
"> ✅ Според [The Spruce Eats](https://www.thespruceeats.com/how-much-is-a-bushel-1389308), теглото на един бушел зависи от вида на продукцията, тъй като това е измерване на обем. \"Един бушел домати, например, трябва да тежи 56 паунда... Листата и зелените заемат повече пространство с по-малко тегло, така че един бушел спанак е само 20 паунда.\" Всичко това е доста сложно! Нека не се занимаваме с преобразуване от бушели в паунди, а вместо това да определим цената на бушел. Цялото това изследване на бушели с тикви обаче показва колко важно е да разберем естеството на данните си!\n",
">\n",
"> ✅ Забелязахте ли, че тиквите, продавани на половин бушел, са много скъпи? Можете ли да разберете защо? Подсказка: малките тикви са много по-скъпи от големите, вероятно защото има много повече от тях в един бушел, като се има предвид неизползваното пространство, което заема една голяма куха тиква за пай.\n"
],
"metadata": {
"id": "pS2GNPagbSdb"
}
},
{
"cell_type": "markdown",
"source": [
"Сега, накрая, заради чистото удоволствие от приключението 💁‍♀️, нека също преместим колоната Month на първа позиция, т.е. `преди` колоната `Package`.\n",
"\n",
"`dplyr::relocate()` се използва за промяна на позициите на колоните.\n"
],
"metadata": {
"id": "qql1SowfbdnP"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Create a new data frame new_pumpkins\n",
"new_pumpkins <- new_pumpkins %>% \n",
" relocate(Month, .before = Package)\n",
"\n",
"new_pumpkins %>% \n",
" slice_head(n = 7)"
],
"outputs": [],
"metadata": {
"id": "JJ1x6kw8bixF"
}
},
{
"cell_type": "markdown",
"source": [
"Браво!👌 Сега разполагате с чист и подреден набор от данни, върху който можете да изградите новия си регресионен модел! \n",
"<br>\n"
],
"metadata": {
"id": "y8TJ0Za_bn5Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. Визуализация на данни с ggplot2\n",
"\n",
"<p >\n",
" <img src=\"../../images/data-visualization.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Инфографика от Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"<!--![Инфографика от Dasani Madipalli](../../../../../../2-Regression/2-Data/images/data-visualization.png){width=\"600\"}-->\n",
"\n",
"Има една *мъдра* поговорка, която гласи:\n",
"\n",
"> \"Простият график е донесъл повече информация на ума на анализатора на данни, отколкото всяко друго устройство.\" --- Джон Туки\n",
"\n",
"Част от ролята на специалиста по данни е да демонстрира качеството и характера на данните, с които работи. За да направят това, те често създават интересни визуализации, или графики, диаграми и таблици, които показват различни аспекти на данните. По този начин те могат визуално да покажат връзки и пропуски, които иначе биха били трудни за откриване.\n",
"\n",
"Визуализациите също могат да помогнат при определянето на най-подходящата техника за машинно обучение за дадените данни. Например, разпръснат график, който изглежда следва линия, показва, че данните са добър кандидат за упражнение с линейна регресия.\n",
"\n",
"R предлага редица системи за създаване на графики, но [`ggplot2`](https://ggplot2.tidyverse.org/index.html) е една от най-елегантните и най-гъвкавите. `ggplot2` ви позволява да съставяте графики чрез **комбиниране на независими компоненти**.\n",
"\n",
"Нека започнем с прост разпръснат график за колоните Price и Month.\n",
"\n",
"В този случай ще започнем с [`ggplot()`](https://ggplot2.tidyverse.org/reference/ggplot.html), ще предоставим набор от данни и естетическо картографиране (с [`aes()`](https://ggplot2.tidyverse.org/reference/aes.html)), след което ще добавим слоеве (като [`geom_point()`](https://ggplot2.tidyverse.org/reference/geom_point.html)) за разпръснати графики.\n"
],
"metadata": {
"id": "mYSH6-EtbvNa"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Set a theme for the plots\n",
"theme_set(theme_light())\n",
"\n",
"# Create a scatter plot\n",
"p <- ggplot(data = new_pumpkins, aes(x = Price, y = Month))\n",
"p + geom_point()"
],
"outputs": [],
"metadata": {
"id": "g2YjnGeOcLo4"
}
},
{
"cell_type": "markdown",
"source": [
"Полезен ли е този график 🤷? Има ли нещо изненадващо в него?\n",
"\n",
"Не е особено полезен, тъй като единственото, което прави, е да показва вашите данни като разпръснати точки за даден месец. \n",
"<br>\n"
],
"metadata": {
"id": "Ml7SDCLQcPvE"
}
},
{
"cell_type": "markdown",
"source": [
"### **Как да го направим полезно?**\n",
"\n",
"За да покажем полезни данни в диаграмите, обикновено трябва да групираме данните по някакъв начин. Например, в нашия случай, намирането на средната цена на тиквите за всеки месец би предоставило повече информация за основните модели в нашите данни. Това ни води до още един бърз поглед към **dplyr**:\n",
"\n",
"#### `dplyr::group_by() %>% summarize()`\n",
"\n",
"Групирана агрегация в R може лесно да се изчисли с помощта на\n",
"\n",
"`dplyr::group_by() %>% summarize()`\n",
"\n",
"- `dplyr::group_by()` променя единицата на анализ от целия набор от данни към отделни групи, например по месеци.\n",
"\n",
"- `dplyr::summarize()` създава нова таблица с една колона за всяка променлива на групиране и една колона за всяка от статистиките, които сте посочили.\n",
"\n",
"Например, можем да използваме `dplyr::group_by() %>% summarize()`, за да групираме тиквите в групи въз основа на колоната **Month** и след това да намерим **средната цена** за всеки месец.\n"
],
"metadata": {
"id": "jMakvJZIcVkh"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Find the average price of pumpkins per month\r\n",
"new_pumpkins %>%\r\n",
" group_by(Month) %>% \r\n",
" summarise(mean_price = mean(Price))"
],
"outputs": [],
"metadata": {
"id": "6kVSUa2Bcilf"
}
},
{
"cell_type": "markdown",
"source": [
"Кратко!✨\n",
"\n",
"Категориални характеристики, като например месеци, се представят по-добре с помощта на стълбовидна диаграма 📊. Слоевете, отговорни за стълбовидните диаграми, са `geom_bar()` и `geom_col()`. Консултирайте се с `?geom_bar`, за да научите повече.\n",
"\n",
"Да създадем една!\n"
],
"metadata": {
"id": "Kds48GUBcj3W"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Find the average price of pumpkins per month then plot a bar chart\r\n",
"new_pumpkins %>%\r\n",
" group_by(Month) %>% \r\n",
" summarise(mean_price = mean(Price)) %>% \r\n",
" ggplot(aes(x = Month, y = mean_price)) +\r\n",
" geom_col(fill = \"midnightblue\", alpha = 0.7) +\r\n",
" ylab(\"Pumpkin Price\")"
],
"outputs": [],
"metadata": {
"id": "VNbU1S3BcrxO"
}
},
{
"cell_type": "markdown",
"source": [
"🤩🤩Това е по-полезна визуализация на данни! Изглежда, че най-високата цена за тикви се наблюдава през септември и октомври. Това отговаря ли на вашите очаквания? Защо или защо не?\n",
"\n",
"Поздравления за завършването на втория урок 👏! Подготвихте данните си за изграждане на модел, след което открихте повече прозрения чрез визуализации!\n"
],
"metadata": {
"id": "zDm0VOzzcuzR"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,128 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Цени на тиквите\n",
"\n",
"Заредете необходимите библиотеки и набора от данни. Преобразувайте данните в датафрейм, съдържащ подмножество от данните:\n",
"\n",
"- Включете само тикви, оценени на цена за бушел\n",
"- Преобразувайте датата в месец\n",
"- Изчислете цената като средна стойност между високата и ниската цена\n",
"- Преобразувайте цената, за да отразява количеството на ценообразуване за бушел\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from datetime import datetime\n",
"\n",
"pumpkins = pd.read_csv('../data/US-pumpkins.csv')\n",
"\n",
"pumpkins.head()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pumpkins = pumpkins[pumpkins['Package'].str.contains('bushel', case=True, regex=True)]\n",
"\n",
"columns_to_select = ['Package', 'Variety', 'City Name', 'Low Price', 'High Price', 'Date']\n",
"pumpkins = pumpkins.loc[:, columns_to_select]\n",
"\n",
"price = (pumpkins['Low Price'] + pumpkins['High Price']) / 2\n",
"\n",
"month = pd.DatetimeIndex(pumpkins['Date']).month\n",
"day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)\n",
"\n",
"new_pumpkins = pd.DataFrame(\n",
" {'Month': month, \n",
" 'DayOfYear' : day_of_year, \n",
" 'Variety': pumpkins['Variety'], \n",
" 'City': pumpkins['City Name'], \n",
" 'Package': pumpkins['Package'], \n",
" 'Low Price': pumpkins['Low Price'],\n",
" 'High Price': pumpkins['High Price'], \n",
" 'Price': price})\n",
"\n",
"new_pumpkins.loc[new_pumpkins['Package'].str.contains('1 1/9'), 'Price'] = price/1.1\n",
"new_pumpkins.loc[new_pumpkins['Package'].str.contains('1/2'), 'Price'] = price*2\n",
"\n",
"new_pumpkins.head()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Една основна точкова диаграма ни напомня, че имаме данни само за месеците от август до декември. Вероятно ни трябват повече данни, за да можем да правим изводи по линеен начин.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"plt.scatter('Month','Price',data=new_pumpkins)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"plt.scatter('DayOfYear','Price',data=new_pumpkins)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3-final"
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "b032d371c75279373507f003439a577e",
"translation_date": "2025-09-04T06:17:00+00:00",
"source_file": "2-Regression/3-Linear/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,269 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Видове тикви и цвят\n",
"\n",
"Заредете необходимите библиотеки и набор от данни. Преобразувайте данните в датафрейм, съдържащ подмножество от данните:\n",
"\n",
"Нека разгледаме връзката между цвета и вида.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>City Name</th>\n",
" <th>Type</th>\n",
" <th>Package</th>\n",
" <th>Variety</th>\n",
" <th>Sub Variety</th>\n",
" <th>Grade</th>\n",
" <th>Date</th>\n",
" <th>Low Price</th>\n",
" <th>High Price</th>\n",
" <th>Mostly Low</th>\n",
" <th>...</th>\n",
" <th>Unit of Sale</th>\n",
" <th>Quality</th>\n",
" <th>Condition</th>\n",
" <th>Appearance</th>\n",
" <th>Storage</th>\n",
" <th>Crop</th>\n",
" <th>Repack</th>\n",
" <th>Trans Mode</th>\n",
" <th>Unnamed: 24</th>\n",
" <th>Unnamed: 25</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>4/29/17</td>\n",
" <td>270.0</td>\n",
" <td>280.0</td>\n",
" <td>270.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>E</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>5/6/17</td>\n",
" <td>270.0</td>\n",
" <td>280.0</td>\n",
" <td>270.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>E</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>HOWDEN TYPE</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>9/24/16</td>\n",
" <td>160.0</td>\n",
" <td>160.0</td>\n",
" <td>160.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>N</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>HOWDEN TYPE</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>9/24/16</td>\n",
" <td>160.0</td>\n",
" <td>160.0</td>\n",
" <td>160.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>N</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>HOWDEN TYPE</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>11/5/16</td>\n",
" <td>90.0</td>\n",
" <td>100.0</td>\n",
" <td>90.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>N</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 26 columns</p>\n",
"</div>"
],
"text/plain": [
" City Name Type Package Variety Sub Variety Grade Date \\\n",
"0 BALTIMORE NaN 24 inch bins NaN NaN NaN 4/29/17 \n",
"1 BALTIMORE NaN 24 inch bins NaN NaN NaN 5/6/17 \n",
"2 BALTIMORE NaN 24 inch bins HOWDEN TYPE NaN NaN 9/24/16 \n",
"3 BALTIMORE NaN 24 inch bins HOWDEN TYPE NaN NaN 9/24/16 \n",
"4 BALTIMORE NaN 24 inch bins HOWDEN TYPE NaN NaN 11/5/16 \n",
"\n",
" Low Price High Price Mostly Low ... Unit of Sale Quality Condition \\\n",
"0 270.0 280.0 270.0 ... NaN NaN NaN \n",
"1 270.0 280.0 270.0 ... NaN NaN NaN \n",
"2 160.0 160.0 160.0 ... NaN NaN NaN \n",
"3 160.0 160.0 160.0 ... NaN NaN NaN \n",
"4 90.0 100.0 90.0 ... NaN NaN NaN \n",
"\n",
" Appearance Storage Crop Repack Trans Mode Unnamed: 24 Unnamed: 25 \n",
"0 NaN NaN NaN E NaN NaN NaN \n",
"1 NaN NaN NaN E NaN NaN NaN \n",
"2 NaN NaN NaN N NaN NaN NaN \n",
"3 NaN NaN NaN N NaN NaN NaN \n",
"4 NaN NaN NaN N NaN NaN NaN \n",
"\n",
"[5 rows x 26 columns]"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"full_pumpkins = pd.read_csv('../data/US-pumpkins.csv')\n",
"\n",
"full_pumpkins.head()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "dee08c2b49057b0de8b6752c4dbca368",
"translation_date": "2025-09-04T06:42:11+00:00",
"source_file": "2-Regression/4-Logistic/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

@ -0,0 +1,685 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Създаване на модел за логистична регресия - Урок 4\n",
"\n",
"![Инфографика за логистична срещу линейна регресия](../../../../../../2-Regression/4-Logistic/images/linear-vs-logistic.png)\n",
"\n",
"#### **[Тест преди лекцията](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n",
"\n",
"#### Въведение\n",
"\n",
"В този последен урок за регресия, една от основните *класически* техники в машинното обучение, ще разгледаме логистичната регресия. Тази техника се използва за откриване на модели, които предсказват бинарни категории. Това бонбон шоколад ли е или не? Това заболяване заразно ли е или не? Този клиент ще избере този продукт или не?\n",
"\n",
"В този урок ще научите:\n",
"\n",
"- Техники за логистична регресия\n",
"\n",
"✅ Задълбочете разбирането си за работа с този тип регресия в този [учебен модул](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n",
"\n",
"## Предпоставки\n",
"\n",
"След като работихме с данните за тиквите, вече сме достатъчно запознати с тях, за да осъзнаем, че има една бинарна категория, с която можем да работим: `Color`.\n",
"\n",
"Нека създадем модел за логистична регресия, за да предскажем, въз основа на някои променливи, *какъв цвят вероятно ще има дадена тиква* (оранжева 🎃 или бяла 👻).\n",
"\n",
"> Защо говорим за бинарна класификация в урок, посветен на регресия? Само за езиково удобство, тъй като логистичната регресия е [всъщност метод за класификация](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), макар и базиран на линейни принципи. Научете за други начини за класифициране на данни в следващата група уроци.\n",
"\n",
"За този урок ще са ни необходими следните пакети:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) е [колекция от R пакети](https://www.tidyverse.org/packages), създадена да направи науката за данни по-бърза, лесна и забавна!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) е рамка, представляваща [колекция от пакети](https://www.tidymodels.org/packages/) за моделиране и машинно обучение.\n",
"\n",
"- `janitor`: [janitor пакетът](https://github.com/sfirke/janitor) предоставя прости инструменти за изследване и почистване на \"мръсни\" данни.\n",
"\n",
"- `ggbeeswarm`: [ggbeeswarm пакетът](https://github.com/eclarke/ggbeeswarm) предлага методи за създаване на диаграми тип \"пчелно рояк\" с помощта на ggplot2.\n",
"\n",
"Можете да ги инсталирате със следната команда:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n",
"\n",
"Алтернативно, скриптът по-долу проверява дали имате необходимите пакети за завършване на този модул и ги инсталира, ако липсват.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\n",
"\n",
"pacman::p_load(tidyverse, tidymodels, janitor, ggbeeswarm)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **Определяне на въпроса**\n",
"\n",
"За нашите цели ще го изразим като бинарен: 'Бял' или 'Не бял'. В нашия набор от данни има и категория 'райе', но тя съдържа малко примери, затова няма да я използваме. Тя така или иначе изчезва, когато премахнем стойностите null от набора от данни.\n",
"\n",
"> 🎃 Забавен факт: понякога наричаме белите тикви 'призрачни' тикви. Те не са много лесни за издълбаване, затова не са толкова популярни, колкото оранжевите, но изглеждат страхотно! Така че можем да преформулираме въпроса си като: 'Призрачна' или 'Не призрачна'. 👻\n",
"\n",
"## **За логистичната регресия**\n",
"\n",
"Логистичната регресия се различава от линейната регресия, за която научихте преди, по няколко важни начина.\n",
"\n",
"#### **Бинарна класификация**\n",
"\n",
"Логистичната регресия не предлага същите функции като линейната регресия. Първата предлага прогноза за `бинарна категория` (\"оранжева или не оранжева\"), докато втората е способна да прогнозира `непрекъснати стойности`, например, въз основа на произхода на тиквата и времето на прибиране на реколтата, *колко ще се повиши цената ѝ*.\n",
"\n",
"![Инфографика от Dasani Madipalli](../../../../../../2-Regression/4-Logistic/images/pumpkin-classifier.png)\n",
"\n",
"### Други класификации\n",
"\n",
"Съществуват и други видове логистична регресия, включително мултиномна и ординална:\n",
"\n",
"- **Мултиномна**, която включва повече от една категория - \"Оранжева, Бяла и Райе\".\n",
"\n",
"- **Ординална**, която включва подредени категории, полезна ако искаме да подредим резултатите си логично, като например тикви, които са подредени по краен брой размери (мини, малък, среден, голям, XL, XXL).\n",
"\n",
"![Мултиномна срещу ординална регресия](../../../../../../2-Regression/4-Logistic/images/multinomial-vs-ordinal.png)\n",
"\n",
"#### **Променливите НЕ трябва да са корелирани**\n",
"\n",
"Помните ли как линейната регресия работеше по-добре с повече корелирани променливи? Логистичната регресия е обратното - променливите не трябва да са свързани. Това е подходящо за тези данни, които имат сравнително слаби корелации.\n",
"\n",
"#### **Нуждаете се от много чисти данни**\n",
"\n",
"Логистичната регресия ще даде по-точни резултати, ако използвате повече данни; нашият малък набор от данни не е оптимален за тази задача, така че имайте това предвид.\n",
"\n",
"✅ Помислете за типовете данни, които биха били подходящи за логистична регресия.\n",
"\n",
"## Упражнение - почистете данните\n",
"\n",
"Първо, почистете данните малко, като премахнете стойностите null и изберете само някои от колоните:\n",
"\n",
"1. Добавете следния код:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Load the core tidyverse packages\n",
"library(tidyverse)\n",
"\n",
"# Import the data and clean column names\n",
"pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\") %>% \n",
" clean_names()\n",
"\n",
"# Select desired columns\n",
"pumpkins_select <- pumpkins %>% \n",
" select(c(city_name, package, variety, origin, item_size, color)) \n",
"\n",
"# Drop rows containing missing values and encode color as factor (category)\n",
"pumpkins_select <- pumpkins_select %>% \n",
" drop_na() %>% \n",
" mutate(color = factor(color))\n",
"\n",
"# View the first few rows\n",
"pumpkins_select %>% \n",
" slice_head(n = 5)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Винаги можете да хвърлите поглед към новия си dataframe, като използвате функцията [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html), както е показано по-долу:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"pumpkins_select %>% \n",
" glimpse()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Нека потвърдим, че всъщност ще решаваме задача за бинарна класификация:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Subset distinct observations in outcome column\n",
"pumpkins_select %>% \n",
" distinct(color)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Визуализация - категориален график\n",
"Дотук вече сте заредили данните за тиквите отново и сте ги почистили, за да запазите набор от данни, съдържащ няколко променливи, включително Цвят. Нека визуализираме таблицата в тетрадката, използвайки библиотеката ggplot.\n",
"\n",
"Библиотеката ggplot предлага някои удобни начини за визуализация на вашите данни. Например, можете да сравните разпределенията на данните за всяка разновидност и цвят в категориален график.\n",
"\n",
"1. Създайте такъв график, като използвате функцията geombar, използвайки нашите данни за тиквите, и задайте цветово картографиране за всяка категория тикви (оранжеви или бели):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "python"
}
},
"outputs": [],
"source": [
"# Specify colors for each value of the hue variable\n",
"palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n",
"\n",
"# Create the bar plot\n",
"ggplot(pumpkins_select, aes(y = variety, fill = color)) +\n",
" geom_bar(position = \"dodge\") +\n",
" scale_fill_manual(values = palette) +\n",
" labs(y = \"Variety\", fill = \"Color\") +\n",
" theme_minimal()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Като наблюдавате данните, можете да видите как информацията за Цвят се свързва с Разновидност.\n",
"\n",
"✅ Като се има предвид този категориален график, какви интересни изследвания можете да си представите?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Предварителна обработка на данни: кодиране на признаци\n",
"\n",
"Нашият набор от данни за тикви съдържа текстови стойности за всички свои колони. Работата с категорийни данни е интуитивна за хората, но не и за машините. Алгоритмите за машинно обучение работят добре с числа. Затова кодиране е много важна стъпка в етапа на предварителна обработка на данни, тъй като ни позволява да преобразуваме категорийни данни в числови, без да губим информация. Добро кодиране води до изграждане на добър модел.\n",
"\n",
"За кодиране на признаци има два основни типа кодери:\n",
"\n",
"1. Ординален кодер: подходящ е за ординални променливи, които са категорийни променливи, при които данните следват логическа подредба, като колоната `item_size` в нашия набор от данни. Той създава съответствие, при което всяка категория се представя с число, което е редът на категорията в колоната.\n",
"\n",
"2. Категориен кодер: подходящ е за номинални променливи, които са категорийни променливи, при които данните не следват логическа подредба, като всички признаци, различни от `item_size` в нашия набор от данни. Това е кодиране тип \"едно-горещо\", което означава, че всяка категория се представя с двоична колона: кодираната променлива е равна на 1, ако тиквата принадлежи към съответния сорт, и 0 в противен случай.\n",
"\n",
"Tidymodels предоставя още един удобен пакет: [recipes](https://recipes.tidymodels.org/) - пакет за предварителна обработка на данни. Ще дефинираме `recipe`, който уточнява, че всички колони с предиктори трябва да бъдат кодирани в набор от цели числа, ще го `prep`, за да изчислим необходимите количества и статистики за всяка операция, и накрая ще го `bake`, за да приложим изчисленията към нови данни.\n",
"\n",
"> Обикновено recipes се използва като предварителен процесор за моделиране, където се определя какви стъпки трябва да бъдат приложени към набор от данни, за да бъде готов за моделиране. В този случай е **силно препоръчително** да използвате `workflow()` вместо ръчното изчисляване на recipe чрез prep и bake. Ще разгледаме всичко това след малко.\n",
">\n",
"> Засега обаче използваме recipes + prep + bake, за да уточним какви стъпки трябва да бъдат приложени към набор от данни, за да бъде готов за анализ на данни, и след това извличаме предварително обработените данни с приложените стъпки.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Preprocess and extract data to allow some data analysis\n",
"baked_pumpkins <- recipe(color ~ ., data = pumpkins_select) %>%\n",
" # Define ordering for item_size column\n",
" step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n",
" # Convert factors to numbers using the order defined above (Ordinal encoding)\n",
" step_integer(item_size, zero_based = F) %>%\n",
" # Encode all other predictors using one hot encoding\n",
" step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE) %>%\n",
" prep(data = pumpkin_select) %>%\n",
" bake(new_data = NULL)\n",
"\n",
"# Display the first few rows of preprocessed data\n",
"baked_pumpkins %>% \n",
" slice_head(n = 5)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"✅ Какви са предимствата от използването на ординален енкодер за колоната Item Size?\n",
"\n",
"### Анализ на връзките между променливите\n",
"\n",
"След като сме обработили данните си, можем да анализираме връзките между характеристиките и етикета, за да добием представа колко добре моделът ще може да предскаже етикета въз основа на характеристиките. Най-добрият начин за извършване на този вид анализ е чрез визуализация на данните. \n",
"Ще използваме отново функцията ggplot geom_boxplot_, за да визуализираме връзките между Item Size, Variety и Color в категориален график. За по-добра визуализация на данните ще използваме кодираната колона Item Size и некодираната колона Variety.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Define the color palette\n",
"palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n",
"\n",
"# We need the encoded Item Size column to use it as the x-axis values in the plot\n",
"pumpkins_select_plot<-pumpkins_select\n",
"pumpkins_select_plot$item_size <- baked_pumpkins$item_size\n",
"\n",
"# Create the grouped box plot\n",
"ggplot(pumpkins_select_plot, aes(x = `item_size`, y = color, fill = color)) +\n",
" geom_boxplot() +\n",
" facet_grid(variety ~ ., scales = \"free_x\") +\n",
" scale_fill_manual(values = palette) +\n",
" labs(x = \"Item Size\", y = \"\") +\n",
" theme_minimal() +\n",
" theme(strip.text = element_text(size = 12)) +\n",
" theme(axis.text.x = element_text(size = 10)) +\n",
" theme(axis.title.x = element_text(size = 12)) +\n",
" theme(axis.title.y = element_blank()) +\n",
" theme(legend.position = \"bottom\") +\n",
" guides(fill = guide_legend(title = \"Color\")) +\n",
" theme(panel.spacing = unit(0.5, \"lines\"))+\n",
" theme(strip.text.y = element_text(size = 4, hjust = 0)) \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Използване на swarm plot\n",
"\n",
"Тъй като Color е бинарна категория (Бяло или Не), тя изисква '[специализиран подход](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf) за визуализация'.\n",
"\n",
"Опитайте `swarm plot`, за да покажете разпределението на цвета спрямо item_size.\n",
"\n",
"Ще използваме [пакета ggbeeswarm](https://github.com/eclarke/ggbeeswarm), който предоставя методи за създаване на графики в стил beeswarm с ggplot2. Beeswarm графиките са начин за визуализиране на точки, които обикновено биха се припокривали, така че да се разположат една до друга вместо това.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Create beeswarm plots of color and item_size\n",
"baked_pumpkins %>% \n",
" mutate(color = factor(color)) %>% \n",
" ggplot(mapping = aes(x = color, y = item_size, color = color)) +\n",
" geom_quasirandom() +\n",
" scale_color_brewer(palette = \"Dark2\", direction = -1) +\n",
" theme(legend.position = \"none\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сега, когато имаме представа за връзката между бинарните категории на цвета и по-голямата група размери, нека разгледаме логистичната регресия, за да определим вероятния цвят на дадена тиква.\n",
"\n",
"## Създайте своя модел\n",
"\n",
"Изберете променливите, които искате да използвате във вашия класификационен модел, и разделете данните на тренировъчни и тестови набори. [rsample](https://rsample.tidymodels.org/), пакет в Tidymodels, предоставя инфраструктура за ефективно разделяне и повторно извадково тестване на данни:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Split data into 80% for training and 20% for testing\n",
"set.seed(2056)\n",
"pumpkins_split <- pumpkins_select %>% \n",
" initial_split(prop = 0.8)\n",
"\n",
"# Extract the data in each split\n",
"pumpkins_train <- training(pumpkins_split)\n",
"pumpkins_test <- testing(pumpkins_split)\n",
"\n",
"# Print out the first 5 rows of the training set\n",
"pumpkins_train %>% \n",
" slice_head(n = 5)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"🙌 Сега сме готови да обучим модел, като свържем тренировъчните характеристики с тренировъчния етикет (цвят).\n",
"\n",
"Ще започнем, като създадем рецепта, която определя стъпките за предварителна обработка, които трябва да се извършат върху нашите данни, за да ги подготвим за моделиране, например: кодиране на категориални променливи в набор от цели числа. Точно както `baked_pumpkins`, създаваме `pumpkins_recipe`, но не използваме `prep` и `bake`, тъй като това ще бъде включено в работен процес, който ще видите само след няколко стъпки.\n",
"\n",
"Има доста начини за задаване на модел за логистична регресия в Tidymodels. Вижте `?logistic_reg()`. Засега ще зададем модел за логистична регресия чрез стандартния двигател `stats::glm()`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Create a recipe that specifies preprocessing steps for modelling\n",
"pumpkins_recipe <- recipe(color ~ ., data = pumpkins_train) %>% \n",
" step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n",
" step_integer(item_size, zero_based = F) %>% \n",
" step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE)\n",
"\n",
"# Create a logistic model specification\n",
"log_reg <- logistic_reg() %>% \n",
" set_engine(\"glm\") %>% \n",
" set_mode(\"classification\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сега, когато имаме рецепта и спецификация на модела, трябва да намерим начин да ги обединим в един обект, който първо ще обработи данните (подготовка + изпичане зад кулисите), ще обучи модела върху предварително обработените данни и също така ще позволи потенциални дейности по последваща обработка.\n",
"\n",
"В Tidymodels този удобен обект се нарича [`workflow`](https://workflows.tidymodels.org/) и удобно съхранява вашите компоненти за моделиране.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Bundle modelling components in a workflow\n",
"log_reg_wf <- workflow() %>% \n",
" add_recipe(pumpkins_recipe) %>% \n",
" add_model(log_reg)\n",
"\n",
"# Print out the workflow\n",
"log_reg_wf\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"След като работният процес бъде *уточнен*, моделът може да бъде `обучен` с помощта на функцията [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html). Работният процес ще оцени рецептата и ще обработи данните преди обучението, така че няма да се налага да го правим ръчно с prep и bake.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Train the model\n",
"wf_fit <- log_reg_wf %>% \n",
" fit(data = pumpkins_train)\n",
"\n",
"# Print the trained workflow\n",
"wf_fit\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Моделът отпечатва коефициентите, научени по време на обучението.\n",
"\n",
"Сега, след като сме обучили модела с тренировъчните данни, можем да правим прогнози върху тестовите данни, използвайки [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Нека започнем, като използваме модела, за да предвидим етикетите за нашия тестов набор и вероятностите за всеки етикет. Когато вероятността е повече от 0.5, предсказаният клас е `WHITE`, в противен случай е `ORANGE`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Make predictions for color and corresponding probabilities\n",
"results <- pumpkins_test %>% select(color) %>% \n",
" bind_cols(wf_fit %>% \n",
" predict(new_data = pumpkins_test)) %>%\n",
" bind_cols(wf_fit %>%\n",
" predict(new_data = pumpkins_test, type = \"prob\"))\n",
"\n",
"# Compare predictions\n",
"results %>% \n",
" slice_head(n = 10)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Много добре! Това предоставя допълнителна информация за начина, по който работи логистичната регресия.\n",
"\n",
"### По-добро разбиране чрез матрица на объркване\n",
"\n",
"Сравняването на всяка прогноза с нейното съответстващо \"истинско\" реално значение не е много ефективен начин за определяне на точността на модела. За щастие, Tidymodels има още няколко трика в ръкава си: [`yardstick`](https://yardstick.tidymodels.org/) - пакет, използван за измерване на ефективността на моделите чрез метрики за производителност.\n",
"\n",
"Една метрика за производителност, свързана с проблемите на класификацията, е [`матрицата на объркване`](https://wikipedia.org/wiki/Confusion_matrix). Матрицата на объркване описва колко добре се представя моделът за класификация. Тя показва колко примери от всяка категория са правилно класифицирани от модела. В нашия случай, тя ще покаже колко оранжеви тикви са класифицирани като оранжеви и колко бели тикви са класифицирани като бели; матрицата на объркване също показва колко са класифицирани в **грешните** категории.\n",
"\n",
"Функцията [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) от yardstick изчислява тази кръстосана таблица на наблюдаваните и предсказаните категории.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Confusion matrix for prediction results\n",
"conf_mat(data = results, truth = color, estimate = .pred_class)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Нека интерпретираме матрицата на объркване. Нашият модел трябва да класифицира тиквите в две бинарни категории: категория `бяла` и категория `не-бяла`.\n",
"\n",
"- Ако вашият модел предскаже тиква като бяла и тя наистина принадлежи към категорията 'бяла', това наричаме `истински положителен` (true positive), показано с числото в горния ляв ъгъл.\n",
"\n",
"- Ако вашият модел предскаже тиква като не-бяла и тя наистина принадлежи към категорията 'бяла', това наричаме `фалшиво отрицателен` (false negative), показано с числото в долния ляв ъгъл.\n",
"\n",
"- Ако вашият модел предскаже тиква като бяла и тя наистина принадлежи към категорията 'не-бяла', това наричаме `фалшиво положителен` (false positive), показано с числото в горния десен ъгъл.\n",
"\n",
"- Ако вашият модел предскаже тиква като не-бяла и тя наистина принадлежи към категорията 'не-бяла', това наричаме `истински отрицателен` (true negative), показано с числото в долния десен ъгъл.\n",
"\n",
"| Истина |\n",
"|:-----:|\n",
"\n",
"| | | |\n",
"|---------------|--------|-------|\n",
"| **Предсказано** | БЯЛА | ОРАНЖЕВА |\n",
"| БЯЛА | TP | FP |\n",
"| ОРАНЖЕВА | FN | TN |\n",
"\n",
"Както може би се досещате, е за предпочитане да имаме по-голям брой истински положителни и истински отрицателни, както и по-малък брой фалшиво положителни и фалшиво отрицателни, което означава, че моделът се представя по-добре.\n",
"\n",
"Матрицата на объркване е полезна, защото води до други метрики, които могат да ни помогнат по-добре да оценим представянето на класификационния модел. Нека разгледаме някои от тях:\n",
"\n",
"🎓 Прецизност (Precision): `TP/(TP + FP)` дефинирана като пропорцията на предсказаните положителни, които наистина са положителни. Нарича се също [положителна предсказателна стойност](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n",
"\n",
"🎓 Чувствителност (Recall): `TP/(TP + FN)` дефинирана като пропорцията на положителните резултати спрямо броя на пробите, които наистина са положителни. Известна също като `чувствителност`.\n",
"\n",
"🎓 Специфичност (Specificity): `TN/(TN + FP)` дефинирана като пропорцията на отрицателните резултати спрямо броя на пробите, които наистина са отрицателни.\n",
"\n",
"🎓 Точност (Accuracy): `TP + TN/(TP + TN + FP + FN)` Процентът на етикетите, предсказани правилно за дадена проба.\n",
"\n",
"🎓 F Мярка (F Measure): Претеглена средна стойност на прецизността и чувствителността, като най-добрата стойност е 1, а най-лошата е 0.\n",
"\n",
"Нека изчислим тези метрики!\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Combine metric functions and calculate them all at once\n",
"eval_metrics <- metric_set(ppv, recall, spec, f_meas, accuracy)\n",
"eval_metrics(data = results, truth = color, estimate = .pred_class)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Визуализиране на ROC кривата на този модел\n",
"\n",
"Нека направим още една визуализация, за да видим така наречената [`ROC крива`](https://en.wikipedia.org/wiki/Receiver_operating_characteristic):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Make a roc_curve\n",
"results %>% \n",
" roc_curve(color, .pred_ORANGE) %>% \n",
" autoplot()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ROC кривите често се използват, за да се получи представа за резултатите на класификатор в контекста на истински спрямо фалшиви положителни стойности. ROC кривите обикновено показват `True Positive Rate`/Чувствителност на оста Y и `False Positive Rate`/1-Специфичност на оста X. Следователно, стръмността на кривата и пространството между средната линия и кривата са от значение: желаете крива, която бързо се изкачва нагоре и преминава над линията. В нашия случай има фалшиви положителни стойности в началото, след което линията се изкачва нагоре и преминава правилно.\n",
"\n",
"Накрая, нека използваме `yardstick::roc_auc()`, за да изчислим действителната площ под кривата (Area Under the Curve). Един от начините за интерпретиране на AUC е като вероятността моделът да класира случайно избран положителен пример по-високо от случайно избран отрицателен пример.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Calculate area under curve\n",
"results %>% \n",
" roc_auc(color, .pred_ORANGE)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Резултатът е около `0.975`. Като се има предвид, че AUC варира от 0 до 1, искате висок резултат, тъй като модел, който е 100% точен в своите прогнози, ще има AUC от 1; в този случай моделът е *доста добър*.\n",
"\n",
"В бъдещи уроци за класификации ще научите как да подобрите резултатите на вашия модел (например справяне с небалансирани данни в този случай).\n",
"\n",
"## 🚀Предизвикателство\n",
"\n",
"Има много повече за разглеждане относно логистичната регресия! Но най-добрият начин да научите е чрез експериментиране. Намерете набор от данни, който е подходящ за този тип анализ, и изградете модел с него. Какво научавате? съвет: опитайте [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) за интересни набори от данни.\n",
"\n",
"## Преглед и самостоятелно обучение\n",
"\n",
"Прочетете първите няколко страници от [тази статия от Станфорд](https://web.stanford.edu/~jurafsky/slp3/5.pdf) за някои практически приложения на логистичната регресия. Помислете за задачи, които са по-подходящи за единия или другия тип регресионни задачи, които сме изучавали до този момент. Какво би работило най-добре?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да било недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
],
"metadata": {
"anaconda-cloud": "",
"kernelspec": {
"display_name": "R",
"langauge": "R",
"name": "ir"
},
"language_info": {
"codemirror_mode": "r",
"file_extension": ".r",
"mimetype": "text/x-r-source",
"name": "R",
"pygments_lexer": "r",
"version": "3.4.1"
},
"coopTranslator": {
"original_hash": "feaf125f481a89c468fa115bf2aed580",
"translation_date": "2025-09-04T06:46:31+00:00",
"source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,267 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python37364bit8d3b438fb5fc4430a93ac2cb74d693a7",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "5fa2e8f4584c78250ca9729b46562ceb",
"translation_date": "2025-09-04T08:16:42+00:00",
"source_file": "3-Web-App/1-Web-App/solution/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" datetime city state country shape \\\n",
"0 10/10/1949 20:30 san marcos tx us cylinder \n",
"1 10/10/1949 21:00 lackland afb tx NaN light \n",
"2 10/10/1955 17:00 chester (uk/england) NaN gb circle \n",
"3 10/10/1956 21:00 edna tx us circle \n",
"4 10/10/1960 20:00 kaneohe hi us light \n",
"\n",
" duration (seconds) duration (hours/min) \\\n",
"0 2700.0 45 minutes \n",
"1 7200.0 1-2 hrs \n",
"2 20.0 20 seconds \n",
"3 20.0 1/2 hour \n",
"4 900.0 15 minutes \n",
"\n",
" comments date posted latitude \\\n",
"0 This event took place in early fall around 194... 4/27/2004 29.883056 \n",
"1 1949 Lackland AFB&#44 TX. Lights racing acros... 12/16/2005 29.384210 \n",
"2 Green/Orange circular disc over Chester&#44 En... 1/21/2008 53.200000 \n",
"3 My older brother and twin sister were leaving ... 1/17/2004 28.978333 \n",
"4 AS a Marine 1st Lt. flying an FJ4B fighter/att... 1/22/2004 21.418056 \n",
"\n",
" longitude \n",
"0 -97.941111 \n",
"1 -98.581082 \n",
"2 -2.916667 \n",
"3 -96.645833 \n",
"4 -157.803611 "
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>datetime</th>\n <th>city</th>\n <th>state</th>\n <th>country</th>\n <th>shape</th>\n <th>duration (seconds)</th>\n <th>duration (hours/min)</th>\n <th>comments</th>\n <th>date posted</th>\n <th>latitude</th>\n <th>longitude</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>10/10/1949 20:30</td>\n <td>san marcos</td>\n <td>tx</td>\n <td>us</td>\n <td>cylinder</td>\n <td>2700.0</td>\n <td>45 minutes</td>\n <td>This event took place in early fall around 194...</td>\n <td>4/27/2004</td>\n <td>29.883056</td>\n <td>-97.941111</td>\n </tr>\n <tr>\n <th>1</th>\n <td>10/10/1949 21:00</td>\n <td>lackland afb</td>\n <td>tx</td>\n <td>NaN</td>\n <td>light</td>\n <td>7200.0</td>\n <td>1-2 hrs</td>\n <td>1949 Lackland AFB&amp;#44 TX. Lights racing acros...</td>\n <td>12/16/2005</td>\n <td>29.384210</td>\n <td>-98.581082</td>\n </tr>\n <tr>\n <th>2</th>\n <td>10/10/1955 17:00</td>\n <td>chester (uk/england)</td>\n <td>NaN</td>\n <td>gb</td>\n <td>circle</td>\n <td>20.0</td>\n <td>20 seconds</td>\n <td>Green/Orange circular disc over Chester&amp;#44 En...</td>\n <td>1/21/2008</td>\n <td>53.200000</td>\n <td>-2.916667</td>\n </tr>\n <tr>\n <th>3</th>\n <td>10/10/1956 21:00</td>\n <td>edna</td>\n <td>tx</td>\n <td>us</td>\n <td>circle</td>\n <td>20.0</td>\n <td>1/2 hour</td>\n <td>My older brother and twin sister were leaving ...</td>\n <td>1/17/2004</td>\n <td>28.978333</td>\n <td>-96.645833</td>\n </tr>\n <tr>\n <th>4</th>\n <td>10/10/1960 20:00</td>\n <td>kaneohe</td>\n <td>hi</td>\n <td>us</td>\n <td>light</td>\n <td>900.0</td>\n <td>15 minutes</td>\n <td>AS a Marine 1st Lt. flying an FJ4B fighter/att...</td>\n <td>1/22/2004</td>\n <td>21.418056</td>\n <td>-157.803611</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {},
"execution_count": 23
}
],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"ufos = pd.read_csv('../data/ufos.csv')\n",
"ufos.head()\n"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"array(['us', nan, 'gb', 'ca', 'au', 'de'], dtype=object)"
]
},
"metadata": {},
"execution_count": 24
}
],
"source": [
"\n",
"ufos = pd.DataFrame({'Seconds': ufos['duration (seconds)'], 'Country': ufos['country'],'Latitude': ufos['latitude'],'Longitude': ufos['longitude']})\n",
"\n",
"ufos.Country.unique()\n",
"\n",
"# 0 au, 1 ca, 2 de, 3 gb, 4 us"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"<class 'pandas.core.frame.DataFrame'>\nInt64Index: 25863 entries, 2 to 80330\nData columns (total 4 columns):\n # Column Non-Null Count Dtype \n--- ------ -------------- ----- \n 0 Seconds 25863 non-null float64\n 1 Country 25863 non-null object \n 2 Latitude 25863 non-null float64\n 3 Longitude 25863 non-null float64\ndtypes: float64(3), object(1)\nmemory usage: 1010.3+ KB\n"
]
}
],
"source": [
"ufos.dropna(inplace=True)\n",
"\n",
"ufos = ufos[(ufos['Seconds'] >= 1) & (ufos['Seconds'] <= 60)]\n",
"\n",
"ufos.info()"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Seconds Country Latitude Longitude\n",
"2 20.0 3 53.200000 -2.916667\n",
"3 20.0 4 28.978333 -96.645833\n",
"14 30.0 4 35.823889 -80.253611\n",
"23 60.0 4 45.582778 -122.352222\n",
"24 3.0 3 51.783333 -0.783333"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Seconds</th>\n <th>Country</th>\n <th>Latitude</th>\n <th>Longitude</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>2</th>\n <td>20.0</td>\n <td>3</td>\n <td>53.200000</td>\n <td>-2.916667</td>\n </tr>\n <tr>\n <th>3</th>\n <td>20.0</td>\n <td>4</td>\n <td>28.978333</td>\n <td>-96.645833</td>\n </tr>\n <tr>\n <th>14</th>\n <td>30.0</td>\n <td>4</td>\n <td>35.823889</td>\n <td>-80.253611</td>\n </tr>\n <tr>\n <th>23</th>\n <td>60.0</td>\n <td>4</td>\n <td>45.582778</td>\n <td>-122.352222</td>\n </tr>\n <tr>\n <th>24</th>\n <td>3.0</td>\n <td>3</td>\n <td>51.783333</td>\n <td>-0.783333</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {},
"execution_count": 26
}
],
"source": [
"from sklearn.preprocessing import LabelEncoder\n",
"\n",
"ufos['Country'] = LabelEncoder().fit_transform(ufos['Country'])\n",
"\n",
"ufos.head()"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split\n",
"\n",
"Selected_features = ['Seconds','Latitude','Longitude']\n",
"\n",
"X = ufos[Selected_features]\n",
"y = ufos['Country']\n",
"\n",
"\n",
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)\n"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stderr",
"text": [
"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:432: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.\n",
" FutureWarning)\n",
"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:469: FutureWarning: Default multi_class will be changed to 'auto' in 0.22. Specify the multi_class option to silence this warning.\n",
" \"this warning.\", FutureWarning)\n",
" precision recall f1-score support\n",
"\n",
" 0 1.00 1.00 1.00 41\n",
" 1 1.00 0.02 0.05 250\n",
" 2 0.00 0.00 0.00 8\n",
" 3 0.94 1.00 0.97 131\n",
" 4 0.95 1.00 0.97 4743\n",
"\n",
" accuracy 0.95 5173\n",
" macro avg 0.78 0.60 0.60 5173\n",
"weighted avg 0.95 0.95 0.93 5173\n",
"\n",
"Predicted labels: [4 4 4 ... 3 4 4]\n",
"Accuracy: 0.9512855209742895\n",
"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sklearn/metrics/classification.py:1437: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.\n",
" 'precision', 'predicted', average, warn_for)\n"
]
}
],
"source": [
"from sklearn.model_selection import train_test_split\n",
"from sklearn.metrics import accuracy_score, classification_report \n",
"from sklearn.linear_model import LogisticRegression\n",
"model = LogisticRegression()\n",
"model.fit(X_train, y_train)\n",
"predictions = model.predict(X_test)\n",
"\n",
"print(classification_report(y_test, predictions))\n",
"print('Predicted labels: ', predictions)\n",
"print('Accuracy: ', accuracy_score(y_test, predictions))\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[3]\n"
]
}
],
"source": [
"import pickle\n",
"model_filename = 'ufo-model.pkl'\n",
"pickle.dump(model, open(model_filename,'wb'))\n",
"\n",
"model = pickle.load(open('ufo-model.pkl','rb'))\n",
"print(model.predict([[50,44,-12]]))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,39 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "d544ef384b7ba73757d830a72372a7f2",
"translation_date": "2025-09-04T08:44:08+00:00",
"source_file": "4-Classification/1-Introduction/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,727 @@
{
"nbformat": 4,
"nbformat_minor": 2,
"metadata": {
"colab": {
"name": "lesson_10-R.ipynb",
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "2621e24705e8100893c9bf84e0fc8aef",
"translation_date": "2025-09-04T08:49:23+00:00",
"source_file": "4-Classification/1-Introduction/solution/R/lesson_10-R.ipynb",
"language_code": "bg"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [
"# Създайте модел за класификация: Вкусни азиатски и индийски ястия\n"
],
"metadata": {
"id": "ItETB4tSFprR"
}
},
{
"cell_type": "markdown",
"source": [
"## Въведение в класификацията: Почистете, подгответе и визуализирайте данните си\n",
"\n",
"В тези четири урока ще разгледате основен аспект на класическото машинно обучение - *класификация*. Ще преминем през използването на различни алгоритми за класификация с набор от данни за всички невероятни кухни на Азия и Индия. Надявам се, че сте гладни!\n",
"\n",
"<p >\n",
" <img src=\"../../images/pinch.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Празнувайте паназиатските кухни в тези уроци! Изображение от Джен Лупър</figcaption>\n",
"\n",
"\n",
"<!--![Празнувайте паназиатските кухни в тези уроци! Изображение от Джен Лупър](../../../../../../4-Classification/1-Introduction/solution/R/images/pinch.png)-->\n",
"\n",
"Класификацията е форма на [контролирано обучение](https://wikipedia.org/wiki/Supervised_learning), която има много общо с техниките за регресия. При класификацията обучавате модел, за да предскаже към коя `категория` принадлежи даден елемент. Ако машинното обучение е свързано с предсказване на стойности или имена на неща чрез използване на набори от данни, тогава класификацията обикновено се разделя на две групи: *бинарна класификация* и *многокласова класификация*.\n",
"\n",
"Запомнете:\n",
"\n",
"- **Линейната регресия** ви помогна да предскажете връзките между променливите и да направите точни прогнози за това къде нова точка от данни би попаднала спрямо тази линия. Например, можете да предскажете числови стойности като *каква би била цената на тиква през септември спрямо декември*.\n",
"\n",
"- **Логистичната регресия** ви помогна да откриете \"бинарни категории\": при тази ценова точка, *оранжева ли е тиквата или не*?\n",
"\n",
"Класификацията използва различни алгоритми, за да определи други начини за определяне на етикета или класа на дадена точка от данни. Нека работим с тези данни за кухни, за да видим дали, наблюдавайки група от съставки, можем да определим произхода на кухнята.\n",
"\n",
"### [**Тест преди лекцията**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/19/)\n",
"\n",
"### **Въведение**\n",
"\n",
"Класификацията е една от основните дейности на изследователя в областта на машинното обучение и на специалиста по данни. От основна класификация на бинарна стойност (\"този имейл спам ли е или не?\") до сложна класификация на изображения и сегментация с помощта на компютърно зрение, винаги е полезно да можете да сортирате данни в класове и да задавате въпроси за тях.\n",
"\n",
"Ако трябва да опишем процеса по-научно, вашият метод за класификация създава предсказателен модел, който ви позволява да картографирате връзката между входните променливи и изходните променливи.\n",
"\n",
"<p >\n",
" <img src=\"../../images/binary-multiclass.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Бинарни срещу многокласови проблеми, които алгоритмите за класификация трябва да решат. Инфографика от Джен Лупър</figcaption>\n",
"\n",
"\n",
"\n",
"Преди да започнем процеса на почистване на данните, визуализирането им и подготовката им за нашите задачи по машинно обучение, нека научим малко за различните начини, по които машинното обучение може да се използва за класифициране на данни.\n",
"\n",
"Произлизаща от [статистиката](https://wikipedia.org/wiki/Statistical_classification), класификацията с помощта на класическо машинно обучение използва характеристики като `пушач`, `тегло` и `възраст`, за да определи *вероятността за развитие на дадено заболяване*. Като техника за контролирано обучение, подобна на упражненията за регресия, които извършихте по-рано, вашите данни са етикетирани, а алгоритмите за машинно обучение използват тези етикети, за да класифицират и предсказват класове (или 'характеристики') на набор от данни и да ги присвояват към група или резултат.\n",
"\n",
"✅ Отделете момент, за да си представите набор от данни за кухни. Какво би могъл да отговори един многокласов модел? Какво би могъл да отговори един бинарен модел? Ами ако искате да определите дали дадена кухня вероятно използва сминдух? Ами ако искате да видите дали, при наличието на торба с хранителни продукти, пълна със звезден анасон, артишок, карфиол и хрян, можете да създадете типично индийско ястие?\n",
"\n",
"### **Здравейте, 'класификатор'**\n",
"\n",
"Въпросът, който искаме да зададем на този набор от данни за кухни, всъщност е **многокласов въпрос**, тъй като имаме няколко потенциални национални кухни, с които да работим. Като се има предвид група от съставки, към кой от тези много класове ще се впишат данните?\n",
"\n",
"Tidymodels предлага няколко различни алгоритми за класифициране на данни, в зависимост от вида на проблема, който искате да решите. В следващите два урока ще научите за някои от тези алгоритми.\n",
"\n",
"#### **Предварителни изисквания**\n",
"\n",
"За този урок ще ни трябват следните пакети, за да почистим, подготвим и визуализираме данните си:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) е [колекция от пакети за R](https://www.tidyverse.org/packages), създадена да направи науката за данни по-бърза, лесна и забавна!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) е рамка, представляваща [колекция от пакети](https://www.tidymodels.org/packages/) за моделиране и машинно обучение.\n",
"\n",
"- `DataExplorer`: [DataExplorer](https://cran.r-project.org/web/packages/DataExplorer/vignettes/dataexplorer-intro.html) е пакет, предназначен да опрости и автоматизира процеса на изследване на данни и генериране на отчети.\n",
"\n",
"- `themis`: [themis](https://themis.tidymodels.org/) предоставя допълнителни стъпки за рецепти за работа с небалансирани данни.\n",
"\n",
"Можете да ги инсталирате със следната команда:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"DataExplorer\", \"here\"))`\n",
"\n",
"Алтернативно, скриптът по-долу проверява дали имате необходимите пакети за завършване на този модул и ги инсталира, ако липсват.\n"
],
"metadata": {
"id": "ri5bQxZ-Fz_0"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\r\n",
"\r\n",
"pacman::p_load(tidyverse, tidymodels, DataExplorer, themis, here)"
],
"outputs": [],
"metadata": {
"id": "KIPxa4elGAPI"
}
},
{
"cell_type": "markdown",
"source": [
"По-късно ще заредим тези страхотни пакети и ще ги направим достъпни в текущата R сесия. (Това е само за илюстрация, `pacman::p_load()` вече го направи за вас)\n"
],
"metadata": {
"id": "YkKAxOJvGD4C"
}
},
{
"cell_type": "markdown",
"source": [
"## Упражнение - почистете и балансирайте вашите данни\n",
"\n",
"Първата задача, преди да започнете този проект, е да почистите и **балансирате** вашите данни, за да постигнете по-добри резултати.\n",
"\n",
"Нека се запознаем с данните! 🕵️\n"
],
"metadata": {
"id": "PFkQDlk0GN5O"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Import data\r\n",
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/4-Classification/data/cuisines.csv\")\r\n",
"\r\n",
"# View the first 5 rows\r\n",
"df %>% \r\n",
" slice_head(n = 5)\r\n"
],
"outputs": [],
"metadata": {
"id": "Qccw7okxGT0S"
}
},
{
"cell_type": "markdown",
"source": [
"Интересно! От изгледа на нещата, първата колона е вид `id` колона. Нека получим малко повече информация за данните.\n"
],
"metadata": {
"id": "XrWnlgSrGVmR"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Basic information about the data\r\n",
"df %>%\r\n",
" introduce()\r\n",
"\r\n",
"# Visualize basic information above\r\n",
"df %>% \r\n",
" plot_intro(ggtheme = theme_light())"
],
"outputs": [],
"metadata": {
"id": "4UcGmxRxGieA"
}
},
{
"cell_type": "markdown",
"source": [
"От резултата веднага виждаме, че имаме `2448` реда и `385` колони и `0` липсващи стойности. Също така имаме 1 дискретна колона, *cuisine*.\n",
"\n",
"## Упражнение - запознаване с кухните\n",
"\n",
"Сега работата започва да става по-интересна. Нека открием разпределението на данните по кухни.\n"
],
"metadata": {
"id": "AaPubl__GmH5"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Count observations per cuisine\r\n",
"df %>% \r\n",
" count(cuisine) %>% \r\n",
" arrange(n)\r\n",
"\r\n",
"# Plot the distribution\r\n",
"theme_set(theme_light())\r\n",
"df %>% \r\n",
" count(cuisine) %>% \r\n",
" ggplot(mapping = aes(x = n, y = reorder(cuisine, -n))) +\r\n",
" geom_col(fill = \"midnightblue\", alpha = 0.7) +\r\n",
" ylab(\"cuisine\")"
],
"outputs": [],
"metadata": {
"id": "FRsBVy5eGrrv"
}
},
{
"cell_type": "markdown",
"source": [
"Има ограничен брой кухни, но разпределението на данните е неравномерно. Можете да го поправите! Преди това обаче, разгледайте малко повече.\n",
"\n",
"След това, нека разпределим всяка кухня в отделна tibble и да разберем колко данни са налични (редове, колони) за всяка кухня.\n",
"\n",
"> [tibble](https://tibble.tidyverse.org/) е модерен data frame.\n",
"\n",
"<p >\n",
" <img src=\"../../images/dplyr_filter.jpg\"\n",
" width=\"600\"/>\n",
" <figcaption>Илюстрация от @allison_horst</figcaption>\n"
],
"metadata": {
"id": "vVvyDb1kG2in"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Create individual tibble for the cuisines\r\n",
"thai_df <- df %>% \r\n",
" filter(cuisine == \"thai\")\r\n",
"japanese_df <- df %>% \r\n",
" filter(cuisine == \"japanese\")\r\n",
"chinese_df <- df %>% \r\n",
" filter(cuisine == \"chinese\")\r\n",
"indian_df <- df %>% \r\n",
" filter(cuisine == \"indian\")\r\n",
"korean_df <- df %>% \r\n",
" filter(cuisine == \"korean\")\r\n",
"\r\n",
"\r\n",
"# Find out how much data is available per cuisine\r\n",
"cat(\" thai df:\", dim(thai_df), \"\\n\",\r\n",
" \"japanese df:\", dim(japanese_df), \"\\n\",\r\n",
" \"chinese_df:\", dim(chinese_df), \"\\n\",\r\n",
" \"indian_df:\", dim(indian_df), \"\\n\",\r\n",
" \"korean_df:\", dim(korean_df))"
],
"outputs": [],
"metadata": {
"id": "0TvXUxD3G8Bk"
}
},
{
"cell_type": "markdown",
"source": [
"## **Упражнение - Откриване на основни съставки по кухня с помощта на dplyr**\n",
"\n",
"Сега можете да се задълбочите в данните и да разберете кои са типичните съставки за различните кухни. Трябва да премахнете повтарящи се данни, които създават объркване между кухните, така че нека разгледаме този проблем.\n",
"\n",
"Създайте функция `create_ingredient()` в R, която връща dataframe със съставки. Тази функция ще започне с премахване на ненужна колона и ще сортира съставките според тяхната честота.\n",
"\n",
"Основната структура на функция в R е:\n",
"\n",
"`myFunction <- function(arglist){`\n",
"\n",
"**`...`**\n",
"\n",
"**`return`**`(value)`\n",
"\n",
"`}`\n",
"\n",
"Едно добро въведение в R функциите можете да намерите [тук](https://skirmer.github.io/presentations/functions_with_r.html#1).\n",
"\n",
"Да се захващаме за работа! Ще използваме [глаголите на dplyr](https://dplyr.tidyverse.org/), които изучавахме в предишните уроци. Като обобщение:\n",
"\n",
"- `dplyr::select()`: помага ви да изберете кои **колони** да запазите или изключите.\n",
"\n",
"- `dplyr::pivot_longer()`: помага ви да \"удължите\" данните, увеличавайки броя на редовете и намалявайки броя на колоните.\n",
"\n",
"- `dplyr::group_by()` и `dplyr::summarise()`: помагат ви да намерите обобщени статистики за различни групи и да ги представите в удобна таблица.\n",
"\n",
"- `dplyr::filter()`: създава подмножество от данните, съдържащо само редовете, които отговарят на вашите условия.\n",
"\n",
"- `dplyr::mutate()`: помага ви да създавате или модифицирате колони.\n",
"\n",
"Разгледайте този [*арт*-пълен learnr урок](https://allisonhorst.shinyapps.io/dplyr-learnr/#section-welcome) от Алисън Хорст, който представя някои полезни функции за обработка на данни в dplyr *(част от Tidyverse)*.\n"
],
"metadata": {
"id": "K3RF5bSCHC76"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Creates a functions that returns the top ingredients by class\r\n",
"\r\n",
"create_ingredient <- function(df){\r\n",
" \r\n",
" # Drop the id column which is the first colum\r\n",
" ingredient_df = df %>% select(-1) %>% \r\n",
" # Transpose data to a long format\r\n",
" pivot_longer(!cuisine, names_to = \"ingredients\", values_to = \"count\") %>% \r\n",
" # Find the top most ingredients for a particular cuisine\r\n",
" group_by(ingredients) %>% \r\n",
" summarise(n_instances = sum(count)) %>% \r\n",
" filter(n_instances != 0) %>% \r\n",
" # Arrange by descending order\r\n",
" arrange(desc(n_instances)) %>% \r\n",
" mutate(ingredients = factor(ingredients) %>% fct_inorder())\r\n",
" \r\n",
" \r\n",
" return(ingredient_df)\r\n",
"} # End of function"
],
"outputs": [],
"metadata": {
"id": "uB_0JR82HTPa"
}
},
{
"cell_type": "markdown",
"source": [
"Сега можем да използваме функцията, за да получим представа за десетте най-популярни съставки според кухнята. Нека я изпробваме с `thai_df`.\n"
],
"metadata": {
"id": "h9794WF8HWmc"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Call create_ingredient and display popular ingredients\r\n",
"thai_ingredient_df <- create_ingredient(df = thai_df)\r\n",
"\r\n",
"thai_ingredient_df %>% \r\n",
" slice_head(n = 10)"
],
"outputs": [],
"metadata": {
"id": "agQ-1HrcHaEA"
}
},
{
"cell_type": "markdown",
"source": [
"В предишния раздел използвахме `geom_col()`, нека видим как можете да използвате и `geom_bar`, за да създавате стълбовидни диаграми. Използвайте `?geom_bar` за допълнително четене.\n"
],
"metadata": {
"id": "kHu9ffGjHdcX"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make a bar chart for popular thai cuisines\r\n",
"thai_ingredient_df %>% \r\n",
" slice_head(n = 10) %>% \r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"steelblue\") +\r\n",
" xlab(\"\") + ylab(\"\")"
],
"outputs": [],
"metadata": {
"id": "fb3Bx_3DHj6e"
}
},
{
"cell_type": "markdown",
"source": [
"Нека направим същото за японските данни\n"
],
"metadata": {
"id": "RHP_xgdkHnvM"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Get popular ingredients for Japanese cuisines and make bar chart\r\n",
"create_ingredient(df = japanese_df) %>% \r\n",
" slice_head(n = 10) %>%\r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"darkorange\", alpha = 0.8) +\r\n",
" xlab(\"\") + ylab(\"\")\r\n"
],
"outputs": [],
"metadata": {
"id": "019v8F0XHrRU"
}
},
{
"cell_type": "markdown",
"source": [
"Какво ще кажете за китайската кухня?\n"
],
"metadata": {
"id": "iIGM7vO8Hu3v"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Get popular ingredients for Chinese cuisines and make bar chart\r\n",
"create_ingredient(df = chinese_df) %>% \r\n",
" slice_head(n = 10) %>%\r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"cyan4\", alpha = 0.8) +\r\n",
" xlab(\"\") + ylab(\"\")"
],
"outputs": [],
"metadata": {
"id": "lHd9_gd2HyzU"
}
},
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "ir8qyQbNH1c7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Get popular ingredients for Indian cuisines and make bar chart\r\n",
"create_ingredient(df = indian_df) %>% \r\n",
" slice_head(n = 10) %>%\r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"#041E42FF\", alpha = 0.8) +\r\n",
" xlab(\"\") + ylab(\"\")"
],
"outputs": [],
"metadata": {
"id": "ApukQtKjH5FO"
}
},
{
"cell_type": "markdown",
"source": [
"Накрая начертайте корейските съставки.\n"
],
"metadata": {
"id": "qv30cwY1H-FM"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Get popular ingredients for Korean cuisines and make bar chart\r\n",
"create_ingredient(df = korean_df) %>% \r\n",
" slice_head(n = 10) %>%\r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"#852419FF\", alpha = 0.8) +\r\n",
" xlab(\"\") + ylab(\"\")"
],
"outputs": [],
"metadata": {
"id": "lumgk9cHIBie"
}
},
{
"cell_type": "markdown",
"source": [
"От визуализациите на данните можем сега да премахнем най-често срещаните съставки, които създават объркване между различните кухни, използвайки `dplyr::select()`.\n",
"\n",
"Всички обичат ориз, чесън и джинджифил!\n"
],
"metadata": {
"id": "iO4veMXuIEta"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Drop id column, rice, garlic and ginger from our original data set\r\n",
"df_select <- df %>% \r\n",
" select(-c(1, rice, garlic, ginger))\r\n",
"\r\n",
"# Display new data set\r\n",
"df_select %>% \r\n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "iHJPiG6rIUcK"
}
},
{
"cell_type": "markdown",
"source": [
"## Предварителна обработка на данни с рецепти 👩‍🍳👨‍🍳 - Работа с небалансирани данни ⚖️\n",
"\n",
"<p >\n",
" <img src=\"../../images/recipes.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Илюстрация от @allison_horst</figcaption>\n",
"\n",
"Тъй като този урок е за кухни, трябва да поставим `рецептите` в контекст.\n",
"\n",
"Tidymodels предоставя още един удобен пакет: `recipes` - пакет за предварителна обработка на данни.\n"
],
"metadata": {
"id": "kkFd-JxdIaL6"
}
},
{
"cell_type": "markdown",
"source": [
"Нека отново разгледаме разпределението на нашите кухни.\n"
],
"metadata": {
"id": "6l2ubtTPJAhY"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Distribution of cuisines\r\n",
"old_label_count <- df_select %>% \r\n",
" count(cuisine) %>% \r\n",
" arrange(desc(n))\r\n",
"\r\n",
"old_label_count"
],
"outputs": [],
"metadata": {
"id": "1e-E9cb7JDVi"
}
},
{
"cell_type": "markdown",
"source": [
"Както виждате, има доста неравномерно разпределение в броя на кухните. Корейските кухни са почти три пъти повече от тайландските. Небалансираните данни често имат отрицателно въздействие върху производителността на модела. Помислете за бинарна класификация. Ако по-голямата част от вашите данни принадлежат към един клас, моделът за машинно обучение ще предсказва този клас по-често, просто защото има повече данни за него. Балансирането на данните коригира всякакви изкривявания и помага за премахването на този дисбаланс. Много модели работят най-добре, когато броят на наблюденията е равен, и следователно имат затруднения с небалансирани данни.\n",
"\n",
"Има основно два начина за справяне с небалансирани набори от данни:\n",
"\n",
"- добавяне на наблюдения към малцинствения клас: `Over-sampling`, например чрез използване на алгоритъма SMOTE\n",
"\n",
"- премахване на наблюдения от мнозинствения клас: `Under-sampling`\n",
"\n",
"Нека сега демонстрираме как да се справим с небалансирани набори от данни, използвайки `recipe`. Рецептата може да се разглежда като план, който описва какви стъпки трябва да се приложат към набора от данни, за да бъде подготвен за анализ.\n"
],
"metadata": {
"id": "soAw6826JKx9"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load themis package for dealing with imbalanced data\r\n",
"library(themis)\r\n",
"\r\n",
"# Create a recipe for preprocessing data\r\n",
"cuisines_recipe <- recipe(cuisine ~ ., data = df_select) %>% \r\n",
" step_smote(cuisine)\r\n",
"\r\n",
"cuisines_recipe"
],
"outputs": [],
"metadata": {
"id": "HS41brUIJVJy"
}
},
{
"cell_type": "markdown",
"source": [
"Нека разгледаме стъпките за предварителна обработка.\n",
"\n",
"- Извикването на `recipe()` с формула указва на рецептата *ролите* на променливите, използвайки данните от `df_select` като референция. Например, колоната `cuisine` е определена с роля `outcome`, докато останалите колони са определени с роля `predictor`.\n",
"\n",
"- [`step_smote(cuisine)`](https://themis.tidymodels.org/reference/step_smote.html) създава *спецификация* на стъпка от рецептата, която синтетично генерира нови примери за малцинствената класа, използвайки най-близките съседи на тези случаи.\n",
"\n",
"Сега, ако искаме да видим предварително обработените данни, трябва да [**`prep()`**](https://recipes.tidymodels.org/reference/prep.html) и [**`bake()`**](https://recipes.tidymodels.org/reference/bake.html) нашата рецепта.\n",
"\n",
"`prep()`: изчислява необходимите параметри от тренировъчен набор, които по-късно могат да бъдат приложени към други набори от данни.\n",
"\n",
"`bake()`: взема предварително обработена рецепта и прилага операциите към всеки набор от данни.\n"
],
"metadata": {
"id": "Yb-7t7XcJaC8"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Prep and bake the recipe\r\n",
"preprocessed_df <- cuisines_recipe %>% \r\n",
" prep() %>% \r\n",
" bake(new_data = NULL) %>% \r\n",
" relocate(cuisine)\r\n",
"\r\n",
"# Display data\r\n",
"preprocessed_df %>% \r\n",
" slice_head(n = 5)\r\n",
"\r\n",
"# Quick summary stats\r\n",
"preprocessed_df %>% \r\n",
" introduce()"
],
"outputs": [],
"metadata": {
"id": "9QhSgdpxJl44"
}
},
{
"cell_type": "markdown",
"source": [
"Нека сега проверим разпределението на нашите кухни и да ги сравним с небалансираните данни.\n"
],
"metadata": {
"id": "dmidELh_LdV7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Distribution of cuisines\r\n",
"new_label_count <- preprocessed_df %>% \r\n",
" count(cuisine) %>% \r\n",
" arrange(desc(n))\r\n",
"\r\n",
"list(new_label_count = new_label_count,\r\n",
" old_label_count = old_label_count)"
],
"outputs": [],
"metadata": {
"id": "aSh23klBLwDz"
}
},
{
"cell_type": "markdown",
"source": [
"Ммм! Данните са чисти, балансирани и много вкусни 😋!\n",
"\n",
"> Обикновено рецептата се използва като предварителен процесор за моделиране, където се определя какви стъпки трябва да се приложат към набора от данни, за да бъде готов за моделиране. В този случай обикновено се използва `workflow()` (както вече видяхме в предишните уроци), вместо ръчно да се изчислява рецепта.\n",
">\n",
"> Затова обикновено не е необходимо да използвате **`prep()`** и **`bake()`** за рецепти, когато работите с tidymodels, но те са полезни функции, които можете да имате в арсенала си, за да потвърдите, че рецептите работят според очакванията ви, както е в нашия случай.\n",
">\n",
"> Когато използвате **`bake()`** върху предварително подготвена рецепта с **`new_data = NULL`**, получавате обратно данните, които сте предоставили при дефинирането на рецептата, но вече преминали през стъпките на предварителната обработка.\n",
"\n",
"Нека сега запазим копие на тези данни за използване в бъдещи уроци:\n"
],
"metadata": {
"id": "HEu80HZ8L7ae"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Save preprocessed data\r\n",
"write_csv(preprocessed_df, \"../../../data/cleaned_cuisines_R.csv\")"
],
"outputs": [],
"metadata": {
"id": "cBmCbIgrMOI6"
}
},
{
"cell_type": "markdown",
"source": [
"Този нов CSV файл вече може да бъде намерен в основната папка с данни.\n",
"\n",
"**🚀Предизвикателство**\n",
"\n",
"Тази учебна програма съдържа няколко интересни набора от данни. Разгледайте папките `data` и вижте дали някой от тях съдържа набори от данни, подходящи за бинарна или многокласова класификация? Какви въпроси бихте задали на този набор от данни?\n",
"\n",
"## [**Тест след лекцията**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/20/)\n",
"\n",
"## **Преглед и самостоятелно обучение**\n",
"\n",
"- Разгледайте [пакета themis](https://github.com/tidymodels/themis). Какви други техники можем да използваме за справяне с небалансирани данни?\n",
"\n",
"- Уебсайт с референции за Tidy models [тук](https://www.tidymodels.org/start/).\n",
"\n",
"- Х. Уикъм и Г. Гролемунд, [*R за анализ на данни: Визуализация, моделиране, трансформация, подреждане и импортиране на данни*](https://r4ds.had.co.nz/).\n",
"\n",
"#### БЛАГОДАРНОСТИ КЪМ:\n",
"\n",
"[`Алисън Хорст`](https://twitter.com/allison_horst/) за създаването на невероятните илюстрации, които правят R по-приветлив и ангажиращ. Намерете още илюстрации в нейния [галерия](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n",
"\n",
"[Каси Бревиу](https://www.twitter.com/cassieview) и [Джен Лупър](https://www.twitter.com/jenlooper) за създаването на оригиналната версия на този модул на Python ♥️\n",
"\n",
"<p >\n",
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
" width=\"600\"/>\n",
" <figcaption>Илюстрация от @allison_horst</figcaption>\n"
],
"metadata": {
"id": "WQs5621pMGwf"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,41 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "68829b06b4dcd512d3327849191f4d7f",
"translation_date": "2025-09-04T08:17:18+00:00",
"source_file": "4-Classification/2-Classifiers-1/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [
"# Създаване на модели за класификация\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,281 @@
{
"cells": [
{
"source": [
"# Създаване на модели за класификация\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Unnamed: 0 cuisine almond angelica anise anise_seed apple \\\n",
"0 0 indian 0 0 0 0 0 \n",
"1 1 indian 1 0 0 0 0 \n",
"2 2 indian 0 0 0 0 0 \n",
"3 3 indian 0 0 0 0 0 \n",
"4 4 indian 0 0 0 0 0 \n",
"\n",
" apple_brandy apricot armagnac ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 382 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Unnamed: 0</th>\n <th>cuisine</th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>indian</td>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 382 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 1
}
],
"source": [
"import pandas as pd\n",
"cuisines_df = pd.read_csv(\"../../data/cleaned_cuisines.csv\")\n",
"cuisines_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.model_selection import train_test_split, cross_val_score\n",
"from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report, precision_recall_curve\n",
"from sklearn.svm import SVC\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"0 indian\n",
"1 indian\n",
"2 indian\n",
"3 indian\n",
"4 indian\n",
"Name: cuisine, dtype: object"
]
},
"metadata": {},
"execution_count": 3
}
],
"source": [
"cuisines_label_df = cuisines_df['cuisine']\n",
"cuisines_label_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" almond angelica anise anise_seed apple apple_brandy apricot \\\n",
"0 0 0 0 0 0 0 0 \n",
"1 1 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 0 0 \n",
"\n",
" armagnac artemisia artichoke ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 380 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>artemisia</th>\n <th>artichoke</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 380 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 4
}
],
"source": [
"cuisines_feature_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1)\n",
"cuisines_feature_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(cuisines_feature_df, cuisines_label_df, test_size=0.3)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Accuracy is 0.8181818181818182\n"
]
}
],
"source": [
"lr = LogisticRegression(multi_class='ovr',solver='liblinear')\n",
"model = lr.fit(X_train, np.ravel(y_train))\n",
"\n",
"accuracy = model.score(X_test, y_test)\n",
"print (\"Accuracy is {}\".format(accuracy))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"ingredients: Index(['artemisia', 'black_pepper', 'mushroom', 'shiitake', 'soy_sauce',\n 'vegetable_oil'],\n dtype='object')\ncuisine: korean\n"
]
}
],
"source": [
"# test an item\n",
"print(f'ingredients: {X_test.iloc[50][X_test.iloc[50]!=0].keys()}')\n",
"print(f'cuisine: {y_test.iloc[50]}')"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" 0\n",
"korean 0.392231\n",
"chinese 0.372872\n",
"japanese 0.218825\n",
"thai 0.013427\n",
"indian 0.002645"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>0</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>korean</th>\n <td>0.392231</td>\n </tr>\n <tr>\n <th>chinese</th>\n <td>0.372872</td>\n </tr>\n <tr>\n <th>japanese</th>\n <td>0.218825</td>\n </tr>\n <tr>\n <th>thai</th>\n <td>0.013427</td>\n </tr>\n <tr>\n <th>indian</th>\n <td>0.002645</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {},
"execution_count": 8
}
],
"source": [
"#rehsape to 2d array and transpose\n",
"test= X_test.iloc[50].values.reshape(-1, 1).T\n",
"# predict with score\n",
"proba = model.predict_proba(test)\n",
"classes = model.classes_\n",
"# create df with classes and scores\n",
"resultdf = pd.DataFrame(data=proba, columns=classes)\n",
"\n",
"# create df to show results\n",
"topPrediction = resultdf.T.sort_values(by=[0], ascending = [False])\n",
"topPrediction.head()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" precision recall f1-score support\n\n chinese 0.75 0.73 0.74 223\n indian 0.93 0.88 0.90 255\n japanese 0.78 0.78 0.78 253\n korean 0.87 0.86 0.86 236\n thai 0.76 0.84 0.80 232\n\n accuracy 0.82 1199\n macro avg 0.82 0.82 0.82 1199\nweighted avg 0.82 0.82 0.82 1199\n\n"
]
}
],
"source": [
"y_pred = model.predict(X_test)\r\n",
"print(classification_report(y_test,y_pred))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "9408506dd864f2b6e334c62f80c0cfcc",
"translation_date": "2025-09-04T08:18:02+00:00",
"source_file": "4-Classification/2-Classifiers-1/solution/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

@ -0,0 +1,165 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Създаване на модел за класификация\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Unnamed: 0 cuisine almond angelica anise anise_seed apple \\\n",
"0 0 indian 0 0 0 0 0 \n",
"1 1 indian 1 0 0 0 0 \n",
"2 2 indian 0 0 0 0 0 \n",
"3 3 indian 0 0 0 0 0 \n",
"4 4 indian 0 0 0 0 0 \n",
"\n",
" apple_brandy apricot armagnac ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 382 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Unnamed: 0</th>\n <th>cuisine</th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>indian</td>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 382 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 9
}
],
"source": [
"import pandas as pd\n",
"cuisines_df = pd.read_csv(\"../data/cleaned_cuisines.csv\")\n",
"cuisines_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"0 indian\n",
"1 indian\n",
"2 indian\n",
"3 indian\n",
"4 indian\n",
"Name: cuisine, dtype: object"
]
},
"metadata": {},
"execution_count": 10
}
],
"source": [
"cuisines_label_df = cuisines_df['cuisine']\n",
"cuisines_label_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" almond angelica anise anise_seed apple apple_brandy apricot \\\n",
"0 0 0 0 0 0 0 0 \n",
"1 1 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 0 0 \n",
"\n",
" armagnac artemisia artichoke ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 380 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>artemisia</th>\n <th>artichoke</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 380 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 11
}
],
"source": [
"cuisines_feature_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1)\n",
"cuisines_feature_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "15a83277036572e0773229b5f21c1e12",
"translation_date": "2025-09-04T08:31:45+00:00",
"source_file": "4-Classification/3-Classifiers-2/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

@ -0,0 +1,650 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "lesson_12-R.ipynb",
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "fab50046ca413a38939d579f8432274f",
"translation_date": "2025-09-04T08:34:11+00:00",
"source_file": "4-Classification/3-Classifiers-2/solution/R/lesson_12-R.ipynb",
"language_code": "bg"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "jsFutf_ygqSx"
},
"source": [
"# Създайте модел за класификация: Вкусни азиатски и индийски ястия\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "HD54bEefgtNO"
},
"source": [
"## Класификатори за кухня 2\n",
"\n",
"В този втори урок за класификация ще разгледаме `повече начини` за класифициране на категорийни данни. Ще научим също за последствията от избора на един класификатор пред друг.\n",
"\n",
"### [**Тест преди лекцията**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/23/)\n",
"\n",
"### **Предварителни знания**\n",
"\n",
"Предполага се, че сте завършили предишните уроци, тъй като ще използваме някои концепции, които научихме преди.\n",
"\n",
"За този урок ще са ни необходими следните пакети:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) е [колекция от R пакети](https://www.tidyverse.org/packages), създадена да направи науката за данни по-бърза, лесна и забавна!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) е рамка, представляваща [колекция от пакети](https://www.tidymodels.org/packages/) за моделиране и машинно обучение.\n",
"\n",
"- `themis`: [themis пакетът](https://themis.tidymodels.org/) предоставя допълнителни стъпки за обработка на небалансирани данни.\n",
"\n",
"Можете да ги инсталирате със следната команда:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"kernlab\", \"themis\", \"ranger\", \"xgboost\", \"kknn\"))`\n",
"\n",
"Алтернативно, скриптът по-долу проверява дали имате необходимите пакети за завършване на този модул и ги инсталира, ако липсват.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "vZ57IuUxgyQt"
},
"source": [
"suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\n",
"\n",
"pacman::p_load(tidyverse, tidymodels, themis, kernlab, ranger, xgboost, kknn)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "z22M-pj4g07x"
},
"source": [
"## **1. Карта за класификация**\n",
"\n",
"В нашия [предишен урок](https://github.com/microsoft/ML-For-Beginners/tree/main/4-Classification/2-Classifiers-1) се опитахме да отговорим на въпроса: как да изберем между множество модели? До голяма степен това зависи от характеристиките на данните и типа проблем, който искаме да решим (например класификация или регресия).\n",
"\n",
"По-рано научихме за различните опции, които имате при класифициране на данни, използвайки помощния лист на Microsoft. Машинно обучителната рамка на Python, Scikit-learn, предлага подобен, но по-детайлен помощен лист, който може допълнително да помогне за стесняване на избора на оценители (друг термин за класификатори):\n",
"\n",
"<p >\n",
" <img src=\"../../images/map.png\"\n",
" width=\"700\"/>\n",
" <figcaption></figcaption>\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "u1i3xRIVg7vG"
},
"source": [
"> Съвет: [посетете тази карта онлайн](https://scikit-learn.org/stable/tutorial/machine_learning_map/) и кликнете по пътя, за да прочетете документацията.\n",
">\n",
"> [Референтният сайт на Tidymodels](https://www.tidymodels.org/find/parsnip/#models) също предоставя отлична документация за различните видове модели.\n",
"\n",
"### **Планът** 🗺️\n",
"\n",
"Тази карта е много полезна, когато имате ясна представа за вашите данни, тъй като можете да „вървите“ по нейните пътеки към решение:\n",
"\n",
"- Имаме \\>50 проби\n",
"\n",
"- Искаме да предвидим категория\n",
"\n",
"- Имаме етикетирани данни\n",
"\n",
"- Имаме по-малко от 100K проби\n",
"\n",
"- ✨ Можем да изберем Linear SVC\n",
"\n",
"- Ако това не работи, тъй като имаме числови данни\n",
"\n",
" - Можем да опитаме ✨ KNeighbors Classifier\n",
"\n",
" - Ако това не работи, опитайте ✨ SVC и ✨ Ensemble Classifiers\n",
"\n",
"Това е много полезен път за следване. Сега, нека се потопим в него, използвайки [tidymodels](https://www.tidymodels.org/) рамката за моделиране: последователна и гъвкава колекция от R пакети, разработени за насърчаване на добри статистически практики 😊.\n",
"\n",
"## 2. Разделяне на данните и справяне с небалансиран набор от данни.\n",
"\n",
"От предишните ни уроци научихме, че има набор от общи съставки в различните кухни. Също така, имаше доста неравномерно разпределение в броя на кухните.\n",
"\n",
"Ще се справим с това, като:\n",
"\n",
"- Премахнем най-често срещаните съставки, които създават объркване между различните кухни, използвайки `dplyr::select()`.\n",
"\n",
"- Използваме `recipe`, който предварително обработва данните, за да ги подготви за моделиране, като приложим алгоритъм за `over-sampling`.\n",
"\n",
"Вече разгледахме горното в предишния урок, така че това трябва да бъде лесно 🥳!\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "6tj_rN00hClA"
},
"source": [
"# Load the core Tidyverse and Tidymodels packages\n",
"library(tidyverse)\n",
"library(tidymodels)\n",
"\n",
"# Load the original cuisines data\n",
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/4-Classification/data/cuisines.csv\")\n",
"\n",
"# Drop id column, rice, garlic and ginger from our original data set\n",
"df_select <- df %>% \n",
" select(-c(1, rice, garlic, ginger)) %>%\n",
" # Encode cuisine column as categorical\n",
" mutate(cuisine = factor(cuisine))\n",
"\n",
"\n",
"# Create data split specification\n",
"set.seed(2056)\n",
"cuisines_split <- initial_split(data = df_select,\n",
" strata = cuisine,\n",
" prop = 0.7)\n",
"\n",
"# Extract the data in each split\n",
"cuisines_train <- training(cuisines_split)\n",
"cuisines_test <- testing(cuisines_split)\n",
"\n",
"# Display distribution of cuisines in the training set\n",
"cuisines_train %>% \n",
" count(cuisine) %>% \n",
" arrange(desc(n))"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "zFin5yw3hHb1"
},
"source": [
"### Работа с небалансирани данни\n",
"\n",
"Небалансираните данни често оказват негативно влияние върху представянето на модела. Много модели работят най-добре, когато броят на наблюденията е равен, и следователно имат затруднения с небалансирани данни.\n",
"\n",
"Има основно два начина за справяне с небалансирани набори от данни:\n",
"\n",
"- добавяне на наблюдения към малцинствения клас: `Over-sampling`, например чрез използване на алгоритъма SMOTE, който синтетично генерира нови примери за малцинствения клас, използвайки най-близките съседи на тези случаи.\n",
"\n",
"- премахване на наблюдения от мнозинствения клас: `Under-sampling`\n",
"\n",
"В предишния ни урок демонстрирахме как да се справим с небалансирани набори от данни, използвайки `recipe`. Рецептата може да се разглежда като план, който описва какви стъпки трябва да се приложат към набора от данни, за да бъде готов за анализ. В нашия случай искаме да постигнем равномерно разпределение в броя на нашите кухни за нашия `training set`. Нека започнем.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "cRzTnHolhLWd"
},
"source": [
"# Load themis package for dealing with imbalanced data\n",
"library(themis)\n",
"\n",
"# Create a recipe for preprocessing training data\n",
"cuisines_recipe <- recipe(cuisine ~ ., data = cuisines_train) %>%\n",
" step_smote(cuisine) \n",
"\n",
"# Print recipe\n",
"cuisines_recipe"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "KxOQ2ORhhO81"
},
"source": [
"Сега сме готови да обучаваме модели 👩‍💻👨‍💻!\n",
"\n",
"## 3. Отвъд моделите за мултиномиална регресия\n",
"\n",
"В предишния урок разгледахме модели за мултиномиална регресия. Нека изследваме някои по-гъвкави модели за класификация.\n",
"\n",
"### Поддържащи векторни машини (Support Vector Machines)\n",
"\n",
"В контекста на класификацията, `Поддържащите векторни машини` са техника за машинно обучение, която се опитва да намери *хиперплоскост*, която \"най-добре\" разделя класовете. Нека разгледаме един прост пример:\n",
"\n",
"<p >\n",
" <img src=\"../../images/svm.png\"\n",
" width=\"300\"/>\n",
" <figcaption>https://commons.wikimedia.org/w/index.php?curid=22877598</figcaption>\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "C4Wsd0vZhXYu"
},
"source": [
"H1~ не разделя класовете. H2~ ги разделя, но само с малък отстъп. H3~ ги разделя с максимален отстъп.\n",
"\n",
"#### Линеен класификатор с опорни вектори\n",
"\n",
"Клъстеризацията с опорни вектори (SVC) е част от семейството на машинно обучение с опорни вектори. При SVC хиперплоскостта се избира така, че да разделя `повечето` от тренировъчните наблюдения правилно, но `може да класифицира погрешно` някои наблюдения. Като се позволи на някои точки да бъдат от грешната страна, SVM става по-устойчив към аномалии и следователно по-добре обобщава нови данни. Параметърът, който регулира това нарушение, се нарича `cost` и има стойност по подразбиране 1 (вижте `help(\"svm_poly\")`).\n",
"\n",
"Нека създадем линеен SVC, като зададем `degree = 1` в полиномиален SVM модел.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "vJpp6nuChlBz"
},
"source": [
"# Make a linear SVC specification\n",
"svc_linear_spec <- svm_poly(degree = 1) %>% \n",
" set_engine(\"kernlab\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle specification and recipe into a worklow\n",
"svc_linear_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(svc_linear_spec)\n",
"\n",
"# Print out workflow\n",
"svc_linear_wf"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "rDs8cWNkhoqu"
},
"source": [
"Сега, след като сме обхванали стъпките за предварителна обработка и спецификацията на модела в *workflow*, можем да продължим с обучението на линейния SVC и да оценим резултатите по време на процеса. За метрики на производителността, нека създадем набор от метрики, който ще оцени: `accuracy`, `sensitivity`, `Positive Predicted Value` и `F Measure`.\n",
"\n",
"> `augment()` ще добави колона(и) за предсказания към дадените данни.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "81wiqcwuhrnq"
},
"source": [
"# Train a linear SVC model\n",
"svc_linear_fit <- svc_linear_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"# Create a metric set\n",
"eval_metrics <- metric_set(ppv, sens, accuracy, f_meas)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"svc_linear_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "0UFQvHf-huo3"
},
"source": [
"#### Поддържаща векторна машина\n",
"\n",
"Поддържащата векторна машина (SVM) е разширение на класификатора с поддържащи вектори, което позволява използването на нелинейна граница между класовете. По същество, SVM използва *трик с ядрото*, за да разшири пространството на характеристиките и да се адаптира към нелинейни връзки между класовете. Една популярна и изключително гъвкава ядрена функция, използвана от SVM, е *функцията с радиална база*. Нека видим как ще се представи върху нашите данни.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "-KX4S8mzhzmp"
},
"source": [
"set.seed(2056)\n",
"\n",
"# Make an RBF SVM specification\n",
"svm_rbf_spec <- svm_rbf() %>% \n",
" set_engine(\"kernlab\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle specification and recipe into a worklow\n",
"svm_rbf_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(svm_rbf_spec)\n",
"\n",
"\n",
"# Train an RBF model\n",
"svm_rbf_fit <- svm_rbf_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"svm_rbf_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "QBFSa7WSh4HQ"
},
"source": [
"Много по-добре 🤩!\n",
"\n",
"> ✅ Моля, вижте:\n",
">\n",
"> - [*Support Vector Machines*](https://bradleyboehmke.github.io/HOML/svm.html), Hands-on Machine Learning with R\n",
">\n",
"> - [*Support Vector Machines*](https://www.statlearning.com/), An Introduction to Statistical Learning with Applications in R\n",
">\n",
"> за допълнително четене.\n",
"\n",
"### Класификатори на най-близки съседи\n",
"\n",
"*K*-най-близки съседи (KNN) е алгоритъм, при който всяко наблюдение се предсказва въз основа на неговата *сходство* с други наблюдения.\n",
"\n",
"Нека приложим такъв към нашите данни.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "k4BxxBcdh9Ka"
},
"source": [
"# Make a KNN specification\n",
"knn_spec <- nearest_neighbor() %>% \n",
" set_engine(\"kknn\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle recipe and model specification into a workflow\n",
"knn_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(knn_spec)\n",
"\n",
"# Train a boosted tree model\n",
"knn_wf_fit <- knn_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"knn_wf_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "HaegQseriAcj"
},
"source": [
"Изглежда, че този модел не се представя толкова добре. Вероятно промяната на аргументите на модела (вижте `help(\"nearest_neighbor\")`) ще подобри производителността на модела. Не забравяйте да го изпробвате.\n",
"\n",
"> ✅ Моля, вижте:\n",
">\n",
"> - [Hands-on Machine Learning with R](https://bradleyboehmke.github.io/HOML/)\n",
">\n",
"> - [An Introduction to Statistical Learning with Applications in R](https://www.statlearning.com/)\n",
">\n",
"> за да научите повече за класификаторите *K*-най-близки съседи.\n",
"\n",
"### Ансамблови класификатори\n",
"\n",
"Ансамбловите алгоритми работят, като комбинират множество базови оценители, за да създадат оптимален модел, като използват:\n",
"\n",
"`bagging`: прилагане на *усредняваща функция* към колекция от базови модели\n",
"\n",
"`boosting`: изграждане на последователност от модели, които се надграждат един върху друг, за да подобрят предсказателната производителност.\n",
"\n",
"Нека започнем, като изпробваме модел Random Forest, който изгражда голяма колекция от дървета за вземане на решения и след това прилага усредняваща функция за създаване на по-добър цялостен модел.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "49DPoVs6iK1M"
},
"source": [
"# Make a random forest specification\n",
"rf_spec <- rand_forest() %>% \n",
" set_engine(\"ranger\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle recipe and model specification into a workflow\n",
"rf_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(rf_spec)\n",
"\n",
"# Train a random forest model\n",
"rf_wf_fit <- rf_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"rf_wf_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "RGVYwC_aiUWc"
},
"source": [
"Браво 👏!\n",
"\n",
"Нека също така да експериментираме с модел на Усилено Дърво.\n",
"\n",
"Усиленото Дърво определя ансамблов метод, който създава серия от последователни дървета за вземане на решения, като всяко дърво зависи от резултатите на предишните дървета в опит да намали грешката постепенно. То се фокусира върху теглата на неправилно класифицираните елементи и коригира модела за следващия класификатор, за да поправи грешките.\n",
"\n",
"Има различни начини за настройка на този модел (вижте `help(\"boost_tree\")`). В този пример ще настроим Усилени дървета чрез енджина `xgboost`.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Py1YWo-micWs"
},
"source": [
"# Make a boosted tree specification\n",
"boost_spec <- boost_tree(trees = 200) %>% \n",
" set_engine(\"xgboost\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle recipe and model specification into a workflow\n",
"boost_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(boost_spec)\n",
"\n",
"# Train a boosted tree model\n",
"boost_wf_fit <- boost_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"boost_wf_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "zNQnbuejigZM"
},
"source": [
"> ✅ Моля, вижте:\n",
"\n",
"> - [Machine Learning for Social Scientists](https://cimentadaj.github.io/ml_socsci/tree-based-methods.html#random-forests)\n",
">\n",
"> - [Hands-on Machine Learning with R](https://bradleyboehmke.github.io/HOML/)\n",
">\n",
"> - [An Introduction to Statistical Learning with Applications in R](https://www.statlearning.com/)\n",
">\n",
"> - <https://algotech.netlify.app/blog/xgboost/> - Разглежда модела AdaBoost, който е добра алтернатива на xgboost.\n",
">\n",
"> за да научите повече за ансамбловите класификатори.\n",
"\n",
"## 4. Допълнително - сравнение на множество модели\n",
"\n",
"В тази лаборатория сме създали доста модели 🙌. Може да стане досадно или обременително да създаваме множество работни потоци от различни набори от предварителни обработки и/или спецификации на модели и след това да изчисляваме метриките за производителност една по една.\n",
"\n",
"Нека видим дали можем да решим този проблем, като създадем функция, която прилага списък от работни потоци върху обучаващия набор и след това връща метриките за производителност, базирани на тестовия набор. Ще използваме `map()` и `map_dfr()` от пакета [purrr](https://purrr.tidyverse.org/), за да приложим функции към всеки елемент от списъка.\n",
"\n",
"> [`map()`](https://purrr.tidyverse.org/reference/map.html) функциите ви позволяват да замените много цикли for с код, който е по-кратък и по-лесен за четене. Най-доброто място за учене за [`map()`](https://purrr.tidyverse.org/reference/map.html) функциите е [главата за итерации](http://r4ds.had.co.nz/iteration.html) в R for Data Science.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Qzb7LyZnimd2"
},
"source": [
"set.seed(2056)\n",
"\n",
"# Create a metric set\n",
"eval_metrics <- metric_set(ppv, sens, accuracy, f_meas)\n",
"\n",
"# Define a function that returns performance metrics\n",
"compare_models <- function(workflow_list, train_set, test_set){\n",
" \n",
" suppressWarnings(\n",
" # Fit each model to the train_set\n",
" map(workflow_list, fit, data = train_set) %>% \n",
" # Make predictions on the test set\n",
" map_dfr(augment, new_data = test_set, .id = \"model\") %>%\n",
" # Select desired columns\n",
" select(model, cuisine, .pred_class) %>% \n",
" # Evaluate model performance\n",
" group_by(model) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class) %>% \n",
" ungroup()\n",
" )\n",
" \n",
"} # End of function"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "Fwa712sNisDA"
},
"source": []
},
{
"cell_type": "code",
"metadata": {
"id": "3i4VJOi2iu-a"
},
"source": [
"# Make a list of workflows\n",
"workflow_list <- list(\n",
" \"svc\" = svc_linear_wf,\n",
" \"svm\" = svm_rbf_wf,\n",
" \"knn\" = knn_wf,\n",
" \"random_forest\" = rf_wf,\n",
" \"xgboost\" = boost_wf)\n",
"\n",
"# Call the function\n",
"set.seed(2056)\n",
"perf_metrics <- compare_models(workflow_list = workflow_list, train_set = cuisines_train, test_set = cuisines_test)\n",
"\n",
"# Print out performance metrics\n",
"perf_metrics %>% \n",
" group_by(.metric) %>% \n",
" arrange(desc(.estimate)) %>% \n",
" slice_head(n=7)\n",
"\n",
"# Compare accuracy\n",
"perf_metrics %>% \n",
" filter(.metric == \"accuracy\") %>% \n",
" arrange(desc(.estimate))\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "KuWK_lEli4nW"
},
"source": [
"Пакетът [**workflowset**](https://workflowsets.tidymodels.org/) позволява на потребителите да създават и лесно да прилагат голям брой модели, но е основно предназначен за работа с техники за повторно извадково тестване като `кръстосана проверка`, подход, който все още не сме разгледали.\n",
"\n",
"## **🚀Предизвикателство**\n",
"\n",
"Всяка от тези техники има голям брой параметри, които можете да настройвате, например `cost` в SVMs, `neighbors` в KNN, `mtry` (Случайно избрани предиктори) в Random Forest.\n",
"\n",
"Проучете стандартните параметри на всяка от тях и помислете какво би означавало настройването на тези параметри за качеството на модела.\n",
"\n",
"За да научите повече за конкретен модел и неговите параметри, използвайте: `help(\"model\")`, например `help(\"rand_forest\")`.\n",
"\n",
"> На практика обикновено *оценяваме* *най-добрите стойности* за тези параметри, като обучаваме много модели върху `симулиран набор от данни` и измерваме колко добре се представят всички тези модели. Този процес се нарича **настройване**.\n",
"\n",
"### [**Тест след лекцията**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/24/)\n",
"\n",
"### **Преглед и самостоятелно обучение**\n",
"\n",
"В тези уроци има много терминология, затова отделете малко време, за да прегледате [този списък](https://docs.microsoft.com/dotnet/machine-learning/resources/glossary?WT.mc_id=academic-77952-leestott) с полезни термини!\n",
"\n",
"#### БЛАГОДАРНОСТИ КЪМ:\n",
"\n",
"[`Allison Horst`](https://twitter.com/allison_horst/) за създаването на невероятните илюстрации, които правят R по-приветлив и ангажиращ. Намерете повече илюстрации в нейния [галерия](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n",
"\n",
"[Cassie Breviu](https://www.twitter.com/cassieview) и [Jen Looper](https://www.twitter.com/jenlooper) за създаването на оригиналната версия на този модул на Python ♥️\n",
"\n",
"Приятно учене,\n",
"\n",
"[Eric](https://twitter.com/ericntay), Златен студентски посланик на Microsoft Learn.\n",
"\n",
"<p >\n",
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
" width=\"569\"/>\n",
" <figcaption>Илюстрация от @allison_horst</figcaption>\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,304 @@
{
"cells": [
{
"source": [
"# Създайте повече модели за класификация\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Unnamed: 0 cuisine almond angelica anise anise_seed apple \\\n",
"0 0 indian 0 0 0 0 0 \n",
"1 1 indian 1 0 0 0 0 \n",
"2 2 indian 0 0 0 0 0 \n",
"3 3 indian 0 0 0 0 0 \n",
"4 4 indian 0 0 0 0 0 \n",
"\n",
" apple_brandy apricot armagnac ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 382 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Unnamed: 0</th>\n <th>cuisine</th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>indian</td>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 382 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 1
}
],
"source": [
"import pandas as pd\n",
"cuisines_df = pd.read_csv(\"../../data/cleaned_cuisines.csv\")\n",
"cuisines_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"0 indian\n",
"1 indian\n",
"2 indian\n",
"3 indian\n",
"4 indian\n",
"Name: cuisine, dtype: object"
]
},
"metadata": {},
"execution_count": 2
}
],
"source": [
"cuisines_label_df = cuisines_df['cuisine']\n",
"cuisines_label_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" almond angelica anise anise_seed apple apple_brandy apricot \\\n",
"0 0 0 0 0 0 0 0 \n",
"1 1 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 0 0 \n",
"\n",
" armagnac artemisia artichoke ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 380 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>artemisia</th>\n <th>artichoke</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 380 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 3
}
],
"source": [
"cuisines_feature_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1)\n",
"cuisines_feature_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Опитайте различни класификатори\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.neighbors import KNeighborsClassifier\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.svm import SVC\n",
"from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier\n",
"from sklearn.model_selection import train_test_split, cross_val_score\n",
"from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report, precision_recall_curve\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(cuisines_feature_df, cuisines_label_df, test_size=0.3)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"\n",
"C = 10\n",
"# Create different classifiers.\n",
"classifiers = {\n",
" 'Linear SVC': SVC(kernel='linear', C=C, probability=True,random_state=0),\n",
" 'KNN classifier': KNeighborsClassifier(C),\n",
" 'SVC': SVC(),\n",
" 'RFST': RandomForestClassifier(n_estimators=100),\n",
" 'ADA': AdaBoostClassifier(n_estimators=100)\n",
" \n",
"}\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Accuracy (train) for Linear SVC: 76.4% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.64 0.66 0.65 242\n",
" indian 0.91 0.86 0.89 236\n",
" japanese 0.72 0.73 0.73 245\n",
" korean 0.83 0.75 0.79 234\n",
" thai 0.75 0.82 0.78 242\n",
"\n",
" accuracy 0.76 1199\n",
" macro avg 0.77 0.76 0.77 1199\n",
"weighted avg 0.77 0.76 0.77 1199\n",
"\n",
"Accuracy (train) for KNN classifier: 70.7% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.65 0.63 0.64 242\n",
" indian 0.84 0.81 0.82 236\n",
" japanese 0.60 0.81 0.69 245\n",
" korean 0.89 0.53 0.67 234\n",
" thai 0.69 0.75 0.72 242\n",
"\n",
" accuracy 0.71 1199\n",
" macro avg 0.73 0.71 0.71 1199\n",
"weighted avg 0.73 0.71 0.71 1199\n",
"\n",
"Accuracy (train) for SVC: 80.1% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.71 0.69 0.70 242\n",
" indian 0.92 0.92 0.92 236\n",
" japanese 0.77 0.78 0.77 245\n",
" korean 0.87 0.77 0.82 234\n",
" thai 0.75 0.86 0.80 242\n",
"\n",
" accuracy 0.80 1199\n",
" macro avg 0.80 0.80 0.80 1199\n",
"weighted avg 0.80 0.80 0.80 1199\n",
"\n",
"Accuracy (train) for RFST: 82.8% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.80 0.75 0.77 242\n",
" indian 0.90 0.91 0.90 236\n",
" japanese 0.82 0.78 0.80 245\n",
" korean 0.85 0.82 0.83 234\n",
" thai 0.78 0.89 0.83 242\n",
"\n",
" accuracy 0.83 1199\n",
" macro avg 0.83 0.83 0.83 1199\n",
"weighted avg 0.83 0.83 0.83 1199\n",
"\n",
"Accuracy (train) for ADA: 71.1% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.60 0.57 0.58 242\n",
" indian 0.87 0.84 0.86 236\n",
" japanese 0.71 0.60 0.65 245\n",
" korean 0.68 0.78 0.72 234\n",
" thai 0.70 0.78 0.74 242\n",
"\n",
" accuracy 0.71 1199\n",
" macro avg 0.71 0.71 0.71 1199\n",
"weighted avg 0.71 0.71 0.71 1199\n",
"\n"
]
}
],
"source": [
"n_classifiers = len(classifiers)\n",
"\n",
"for index, (name, classifier) in enumerate(classifiers.items()):\n",
" classifier.fit(X_train, np.ravel(y_train))\n",
"\n",
" y_pred = classifier.predict(X_test)\n",
" accuracy = accuracy_score(y_test, y_pred)\n",
" print(\"Accuracy (train) for %s: %0.1f%% \" % (name, accuracy * 100))\n",
" print(classification_report(y_test,y_pred))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "7ea2b714669c823a596d986ba2d5739f",
"translation_date": "2025-09-04T08:32:24+00:00",
"source_file": "4-Classification/3-Classifiers-2/solution/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

@ -0,0 +1,41 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "2f3e0d9e9ac5c301558fb8bf733ac0cb",
"translation_date": "2025-09-04T08:30:28+00:00",
"source_file": "4-Classification/4-Applied/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [
"# Създайте препоръчител за кухня\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,292 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"coopTranslator": {
"original_hash": "49325d6dd12a3628fc64fa7ccb1a80ff",
"translation_date": "2025-09-04T08:31:05+00:00",
"source_file": "4-Classification/4-Applied/solution/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [
"# Създайте препоръчител за кухня\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Requirement already satisfied: skl2onnx in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (1.8.0)\n",
"Requirement already satisfied: protobuf in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (3.8.0)\n",
"Requirement already satisfied: numpy>=1.15 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (1.19.2)\n",
"Requirement already satisfied: onnx>=1.2.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (1.9.0)\n",
"Requirement already satisfied: six in /Users/jenlooper/Library/Python/3.7/lib/python/site-packages (from skl2onnx) (1.12.0)\n",
"Requirement already satisfied: onnxconverter-common<1.9,>=1.6.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (1.8.1)\n",
"Requirement already satisfied: scikit-learn>=0.19 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (0.24.2)\n",
"Requirement already satisfied: scipy>=1.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (1.4.1)\n",
"Requirement already satisfied: setuptools in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from protobuf->skl2onnx) (45.1.0)\n",
"Requirement already satisfied: typing-extensions>=3.6.2.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from onnx>=1.2.1->skl2onnx) (3.10.0.0)\n",
"Requirement already satisfied: threadpoolctl>=2.0.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from scikit-learn>=0.19->skl2onnx) (2.1.0)\n",
"Requirement already satisfied: joblib>=0.11 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from scikit-learn>=0.19->skl2onnx) (0.16.0)\n",
"\u001b[33mWARNING: You are using pip version 20.2.3; however, version 21.1.2 is available.\n",
"You should consider upgrading via the '/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7 -m pip install --upgrade pip' command.\u001b[0m\n",
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"!pip install skl2onnx"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd \n"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Unnamed: 0 cuisine almond angelica anise anise_seed apple \\\n",
"0 0 indian 0 0 0 0 0 \n",
"1 1 indian 1 0 0 0 0 \n",
"2 2 indian 0 0 0 0 0 \n",
"3 3 indian 0 0 0 0 0 \n",
"4 4 indian 0 0 0 0 0 \n",
"\n",
" apple_brandy apricot armagnac ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 382 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Unnamed: 0</th>\n <th>cuisine</th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>indian</td>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 382 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 60
}
],
"source": [
"data = pd.read_csv('../../data/cleaned_cuisines.csv')\n",
"data.head()"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" almond angelica anise anise_seed apple apple_brandy apricot \\\n",
"0 0 0 0 0 0 0 0 \n",
"1 1 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 0 0 \n",
"\n",
" armagnac artemisia artichoke ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 380 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>artemisia</th>\n <th>artichoke</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 380 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 61
}
],
"source": [
"X = data.iloc[:,2:]\n",
"X.head()"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" cuisine\n",
"0 indian\n",
"1 indian\n",
"2 indian\n",
"3 indian\n",
"4 indian"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>cuisine</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>indian</td>\n </tr>\n <tr>\n <th>1</th>\n <td>indian</td>\n </tr>\n <tr>\n <th>2</th>\n <td>indian</td>\n </tr>\n <tr>\n <th>3</th>\n <td>indian</td>\n </tr>\n <tr>\n <th>4</th>\n <td>indian</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {},
"execution_count": 62
}
],
"source": [
"y = data[['cuisine']]\n",
"y.head()"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split\n",
"from sklearn.svm import SVC\n",
"from sklearn.model_selection import cross_val_score\n",
"from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3)"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"SVC(C=10, kernel='linear', probability=True, random_state=0)"
]
},
"metadata": {},
"execution_count": 65
}
],
"source": [
"model = SVC(kernel='linear', C=10, probability=True,random_state=0)\n",
"model.fit(X_train,y_train.values.ravel())\n"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [],
"source": [
"y_pred = model.predict(X_test)"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" precision recall f1-score support\n\n chinese 0.72 0.70 0.71 236\n indian 0.91 0.88 0.89 243\n japanese 0.80 0.75 0.77 240\n korean 0.80 0.81 0.81 230\n thai 0.76 0.85 0.80 250\n\n accuracy 0.80 1199\n macro avg 0.80 0.80 0.80 1199\nweighted avg 0.80 0.80 0.80 1199\n\n"
]
}
],
"source": [
"print(classification_report(y_test,y_pred))"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [],
"source": [
"from skl2onnx import convert_sklearn\n",
"from skl2onnx.common.data_types import FloatTensorType\n",
"\n",
"initial_type = [('float_input', FloatTensorType([None, 380]))]\n",
"options = {id(model): {'nocl': True, 'zipmap': False}}\n",
"onx = convert_sklearn(model, initial_types=initial_type, options=options)\n",
"with open(\"./model.onnx\", \"wb\") as f:\n",
" f.write(onx.SerializeToString())\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,50 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python383jvsc74a57bd0e134e05457d34029b6460cd73bbf1ed73f339b5b6d98c95be70b69eba114fe95",
"display_name": "Python 3.8.3 64-bit (conda)"
},
"coopTranslator": {
"original_hash": "40e0707e96b3e1899a912776006264f9",
"translation_date": "2025-09-04T07:41:53+00:00",
"source_file": "5-Clustering/1-Visualize/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,500 @@
{
"cells": [
{
"cell_type": "markdown",
"source": [
"## **Нигерийска музика, извлечена от Spotify - анализ**\n",
"\n",
"Клъстерирането е вид [Ненадзиравано обучение](https://wikipedia.org/wiki/Unsupervised_learning), което предполага, че даден набор от данни е без етикети или че входните данни не са свързани с предварително дефинирани изходи. То използва различни алгоритми, за да сортира неетикетирани данни и да предостави групировки според моделите, които открива в данните.\n",
"\n",
"[**Тест преди лекцията**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/27/)\n",
"\n",
"### **Въведение**\n",
"\n",
"[Клъстерирането](https://link.springer.com/referenceworkentry/10.1007%2F978-0-387-30164-8_124) е много полезно за изследване на данни. Нека видим дали може да помогне за откриване на тенденции и модели в начина, по който нигерийската аудитория консумира музика.\n",
"\n",
"> ✅ Отделете минута, за да помислите за приложенията на клъстерирането. В реалния живот клъстерирането се случва, когато имате купчина пране и трябва да сортирате дрехите на членовете на семейството си 🧦👕👖🩲. В науката за данни клъстерирането се случва, когато се опитвате да анализирате предпочитанията на потребителите или да определите характеристиките на който и да е набор от данни без етикети. Клъстерирането, по някакъв начин, помага да се внесе ред в хаоса, като например чекмедже за чорапи.\n",
"\n",
"В професионална среда клъстерирането може да се използва за определяне на неща като сегментация на пазара, например за установяване кои възрастови групи купуват какви продукти. Друго приложение би било откриването на аномалии, например за откриване на измами в набор от данни с транзакции с кредитни карти. Или може да използвате клъстериране, за да идентифицирате тумори в група медицински сканирания.\n",
"\n",
"✅ Помислете за момент как сте се сблъсквали с клъстериране „в дивата природа“, в банковия сектор, електронната търговия или бизнес среда.\n",
"\n",
"> 🎓 Интересно е, че анализът на клъстери произхожда от областите на антропологията и психологията през 1930-те години. Можете ли да си представите как е бил използван?\n",
"\n",
"Алтернативно, можете да го използвате за групиране на резултати от търсене - например по връзки за пазаруване, изображения или ревюта. Клъстерирането е полезно, когато имате голям набор от данни, който искате да намалите и върху който искате да извършите по-детайлен анализ, така че техниката може да се използва за изучаване на данни преди изграждането на други модели.\n",
"\n",
"✅ След като данните ви са организирани в клъстери, им присвоявате идентификатор на клъстер, и тази техника може да бъде полезна за запазване на поверителността на набора от данни; вместо това можете да се позовавате на точка от данни чрез идентификатора на клъстера, вместо чрез по-разкриващи идентифицируеми данни. Можете ли да се сетите за други причини, поради които бихте се позовали на идентификатор на клъстер, вместо на други елементи от клъстера, за да го идентифицирате?\n",
"\n",
"### Започване с клъстериране\n",
"\n",
"> 🎓 Как създаваме клъстери има много общо с начина, по който събираме точките от данни в групи. Нека разгледаме някои термини:\n",
">\n",
"> 🎓 ['Трансдуктивно' срещу 'индуктивно'](https://wikipedia.org/wiki/Transduction_(machine_learning))\n",
">\n",
"> Трансдуктивното заключение се извежда от наблюдавани тренировъчни случаи, които се свързват със специфични тестови случаи. Индуктивното заключение се извежда от тренировъчни случаи, които се свързват с общи правила, които след това се прилагат към тестови случаи.\n",
">\n",
"> Пример: Представете си, че имате набор от данни, който е само частично етикетиран. Някои неща са „плочи“, някои „CD-та“, а някои са празни. Вашата задача е да предоставите етикети за празните. Ако изберете индуктивен подход, бихте обучили модел, който търси „плочи“ и „CD-та“, и бихте приложили тези етикети към неетикетираните данни. Този подход ще има проблеми с класифицирането на неща, които всъщност са „касети“. Трансдуктивният подход, от друга страна, се справя с тези неизвестни данни по-ефективно, тъй като работи за групиране на подобни елементи заедно и след това прилага етикет към групата. В този случай клъстерите може да отразяват „кръгли музикални неща“ и „квадратни музикални неща“.\n",
">\n",
"> 🎓 ['Неплоска' срещу 'плоска' геометрия](https://datascience.stackexchange.com/questions/52260/terminology-flat-geometry-in-the-context-of-clustering)\n",
">\n",
"> Произхождаща от математическата терминология, неплоска срещу плоска геометрия се отнася до измерването на разстоянията между точки чрез „плоски“ ([Евклидови](https://wikipedia.org/wiki/Euclidean_geometry)) или „неплоски“ (неевклидови) геометрични методи.\n",
">\n",
"> „Плоска“ в този контекст се отнася до Евклидова геометрия (части от която се преподават като „планиметрия“), а неплоска се отнася до неевклидова геометрия. Какво общо има геометрията с машинното обучение? Е, като две области, които са вкоренени в математиката, трябва да има общ начин за измерване на разстоянията между точки в клъстери, и това може да се направи по „плосък“ или „неплосък“ начин, в зависимост от естеството на данните. [Евклидовите разстояния](https://wikipedia.org/wiki/Euclidean_distance) се измерват като дължината на отсечка между две точки. [Неевклидовите разстояния](https://wikipedia.org/wiki/Non-Euclidean_geometry) се измерват по крива. Ако вашите данни, визуализирани, изглежда не съществуват на равнина, може да се наложи да използвате специализиран алгоритъм, за да ги обработите.\n",
"\n",
"<p >\n",
" <img src=\"../../images/flat-nonflat.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Инфографика от Дасани Мадипали</figcaption>\n",
"\n",
"\n",
"\n",
"> 🎓 ['Разстояния'](https://web.stanford.edu/class/cs345a/slides/12-clustering.pdf)\n",
">\n",
"> Клъстерите се определят от тяхната матрица на разстояния, например разстоянията между точки. Това разстояние може да се измери по няколко начина. Евклидовите клъстери се определят от средната стойност на точките и съдържат „центроид“ или централна точка. Разстоянията се измерват спрямо този центроид. Неевклидовите разстояния се отнасят до „клъстроиди“, точката, която е най-близо до другите точки. Клъстроидите могат да бъдат дефинирани по различни начини.\n",
">\n",
"> 🎓 ['Ограничено'](https://wikipedia.org/wiki/Constrained_clustering)\n",
">\n",
"> [Ограниченото клъстериране](https://web.cs.ucdavis.edu/~davidson/Publications/ICDMTutorial.pdf) въвежда „полунадзиравано“ обучение в този ненадзираван метод. Връзките между точките се маркират като „не може да се свърже“ или „трябва да се свърже“, така че някои правила се налагат върху набора от данни.\n",
">\n",
"> Пример: Ако алгоритъмът е оставен свободен върху група неетикетирани или полуетикетирани данни, клъстерите, които произвежда, може да са с лошо качество. В горния пример клъстерите може да групират „кръгли музикални неща“, „квадратни музикални неща“, „триъгълни неща“ и „бисквити“. Ако се дадат някои ограничения или правила, които да се следват („елементът трябва да е направен от пластмаса“, „елементът трябва да може да произвежда музика“), това може да помогне за „ограничаване“ на алгоритъма да прави по-добри избори.\n",
">\n",
"> 🎓 'Плътност'\n",
">\n",
"> Данните, които са „шумни“, се считат за „плътни“. Разстоянията между точките във всеки от клъстерите може да се окажат, при разглеждане, повече или по-малко плътни, или „претъпкани“, и следователно тези данни трябва да бъдат анализирани с подходящия метод за клъстериране. [Тази статия](https://www.kdnuggets.com/2020/02/understanding-density-based-clustering.html) демонстрира разликата между използването на K-Means клъстериране и HDBSCAN алгоритми за изследване на шумен набор от данни с неравномерна плътност на клъстерите.\n",
"\n",
"Задълбочете разбирането си за техниките за клъстериране в този [учебен модул](https://docs.microsoft.com/learn/modules/train-evaluate-cluster-models?WT.mc_id=academic-77952-leestott)\n",
"\n",
"### **Алгоритми за клъстериране**\n",
"\n",
"Съществуват над 100 алгоритма за клъстериране, и тяхното използване зависи от естеството на данните. Нека обсъдим някои от основните:\n",
"\n",
"- **Йерархично клъстериране**. Ако даден обект се класифицира според близостта му до друг обект, а не до по-далечен, клъстерите се формират въз основа на разстоянието между членовете им. Йерархичното клъстериране се характеризира с многократно комбиниране на два клъстера.\n",
"\n",
"\n",
"<p >\n",
" <img src=\"../../images/hierarchical.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Инфографика от Дасани Мадипали</figcaption>\n",
"\n",
"\n",
"\n",
"- **Клъстериране чрез центроид**. Този популярен алгоритъм изисква избор на 'k', или броя на клъстерите, които да се формират, след което алгоритъмът определя централната точка на клъстера и събира данни около тази точка. [K-means клъстериране](https://wikipedia.org/wiki/K-means_clustering) е популярна версия на клъстериране чрез центроид, която разделя набор от данни на предварително дефинирани K групи. Центърът се определя от най-близката средна стойност, откъдето идва и името. Квадратното разстояние от клъстера се минимизира.\n",
"\n",
"<p >\n",
" <img src=\"../../images/centroid.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Инфографика от Дасани Мадипали</figcaption>\n",
"\n",
"\n",
"\n",
"- **Клъстериране, базирано на разпределение**. Основава се на статистическо моделиране, клъстерирането, базирано на разпределение, се фокусира върху определяне на вероятността дадена точка от данни да принадлежи към клъстер и я присвоява съответно. Методите на Гаусова смес принадлежат към този тип.\n",
"\n",
"- **Клъстериране, базирано на плътност**. Точките от данни се присвояват към клъстери въз основа на тяхната плътност или групиране около други точки. Точки от данни, които са далеч от групата, се считат за аутлайъри или шум. DBSCAN, Mean-shift и OPTICS принадлежат към този тип клъстериране.\n",
"\n",
"- **Клъстериране, базирано на мрежа**. За многомерни набори от данни се създава мрежа и данните се разделят между клетките на мрежата, като по този начин се създават клъстери.\n",
"\n",
"Най-добрият начин да научите за клъстерирането е да го опитате сами, така че това ще направите в това упражнение.\n",
"\n",
"Ще ни трябват някои пакети, за да завършим този модул. Можете да ги инсталирате с: `install.packages(c('tidyverse', 'tidymodels', 'DataExplorer', 'summarytools', 'plotly', 'paletteer', 'corrplot', 'patchwork'))`\n",
"\n",
"Алтернативно, скриптът по-долу проверява дали имате необходимите пакети за завършване на този модул и ги инсталира, ако липсват.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\r\n",
"\r\n",
"pacman::p_load('tidyverse', 'tidymodels', 'DataExplorer', 'summarytools', 'plotly', 'paletteer', 'corrplot', 'patchwork')\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"## Упражнение - клъстеризирайте вашите данни\n",
"\n",
"Клъстеризацията като техника е значително улеснена от правилната визуализация, така че нека започнем с визуализиране на нашите музикални данни. Това упражнение ще ни помогне да решим кой от методите за клъстеризация ще бъде най-ефективен за характера на тези данни.\n",
"\n",
"Да започнем директно с импортиране на данните.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load the core tidyverse and make it available in your current R session\r\n",
"library(tidyverse)\r\n",
"\r\n",
"# Import the data into a tibble\r\n",
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/5-Clustering/data/nigerian-songs.csv\")\r\n",
"\r\n",
"# View the first 5 rows of the data set\r\n",
"df %>% \r\n",
" slice_head(n = 5)\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Понякога може да искаме малко повече информация за нашите данни. Можем да разгледаме `данните` и `тяхната структура`, като използваме функцията [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html):\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Glimpse into the data set\r\n",
"df %>% \r\n",
" glimpse()\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Добра работа!💪\n",
"\n",
"Можем да забележим, че `glimpse()` ще ви покаже общия брой редове (наблюдения) и колони (променливи), след това първите няколко записи на всяка променлива в ред след името на променливата. Освен това, *типът данни* на променливата се показва веднага след името на променливата вътре в `< >`.\n",
"\n",
"`DataExplorer::introduce()` може да обобщи тази информация по ясен начин:\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Describe basic information for our data\r\n",
"df %>% \r\n",
" introduce()\r\n",
"\r\n",
"# A visual display of the same\r\n",
"df %>% \r\n",
" plot_intro()\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Страхотно! Току-що научихме, че нашите данни нямат липсващи стойности.\n",
"\n",
"Докато сме на тази тема, можем да разгледаме често срещаните статистики за централна тенденция (например [средна стойност](https://en.wikipedia.org/wiki/Arithmetic_mean) и [медиана](https://en.wikipedia.org/wiki/Median)) и мерки за разсейване (например [стандартно отклонение](https://en.wikipedia.org/wiki/Standard_deviation)) с помощта на `summarytools::descr()`.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Describe common statistics\r\n",
"df %>% \r\n",
" descr(stats = \"common\")\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Нека разгледаме общите стойности на данните. Имайте предвид, че популярността може да бъде `0`, което показва песни без класиране. Ще премахнем тези скоро.\n",
"\n",
"> 🤔 Ако работим с клъстеризация, неконтролиран метод, който не изисква етикетирани данни, защо показваме тези данни с етикети? Във фазата на изследване на данните те са полезни, но не са необходими за работата на алгоритмите за клъстеризация.\n",
"\n",
"### 1. Изследване на популярни жанрове\n",
"\n",
"Нека продължим и разберем кои са най-популярните жанрове 🎶, като преброим колко пъти се появяват.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Popular genres\r\n",
"top_genres <- df %>% \r\n",
" count(artist_top_genre, sort = TRUE) %>% \r\n",
"# Encode to categorical and reorder the according to count\r\n",
" mutate(artist_top_genre = factor(artist_top_genre) %>% fct_inorder())\r\n",
"\r\n",
"# Print the top genres\r\n",
"top_genres\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Това мина добре! Казват, че една снимка струва колкото хиляда реда от датафрейм (всъщност никой никога не го казва 😅). Но схващаш идеята, нали?\n",
"\n",
"Един от начините за визуализиране на категорийни данни (символни или факторни променливи) е чрез стълбовидни диаграми. Нека направим стълбовидна диаграма за топ 10 жанра:\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Change the default gray theme\r\n",
"theme_set(theme_light())\r\n",
"\r\n",
"# Visualize popular genres\r\n",
"top_genres %>%\r\n",
" slice(1:10) %>% \r\n",
" ggplot(mapping = aes(x = artist_top_genre, y = n,\r\n",
" fill = artist_top_genre)) +\r\n",
" geom_col(alpha = 0.8) +\r\n",
" paletteer::scale_fill_paletteer_d(\"rcartocolor::Vivid\") +\r\n",
" ggtitle(\"Top genres\") +\r\n",
" theme(plot.title = element_text(hjust = 0.5),\r\n",
" # Rotates the X markers (so we can read them)\r\n",
" axis.text.x = element_text(angle = 90))\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Сега е много по-лесно да се идентифицира, че имаме `липсващи` жанрове 🧐!\n",
"\n",
"> Добрата визуализация ще ви покаже неща, които не сте очаквали, или ще повдигне нови въпроси относно данните - Хадли Уикъм и Гарет Гролемунд, [R For Data Science](https://r4ds.had.co.nz/introduction.html)\n",
"\n",
"Забележете, когато водещият жанр е описан като `Липсващ`, това означава, че Spotify не го е класифицирал, така че нека го премахнем.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Visualize popular genres\r\n",
"top_genres %>%\r\n",
" filter(artist_top_genre != \"Missing\") %>% \r\n",
" slice(1:10) %>% \r\n",
" ggplot(mapping = aes(x = artist_top_genre, y = n,\r\n",
" fill = artist_top_genre)) +\r\n",
" geom_col(alpha = 0.8) +\r\n",
" paletteer::scale_fill_paletteer_d(\"rcartocolor::Vivid\") +\r\n",
" ggtitle(\"Top genres\") +\r\n",
" theme(plot.title = element_text(hjust = 0.5),\r\n",
" # Rotates the X markers (so we can read them)\r\n",
" axis.text.x = element_text(angle = 90))\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"От малкото изследване на данните научаваме, че трите водещи жанра доминират в този набор от данни. Нека се съсредоточим върху `afro dancehall`, `afropop` и `nigerian pop`, като допълнително филтрираме набора от данни, за да премахнем всичко с нулева стойност на популярност (което означава, че не е класифицирано с популярност в набора от данни и може да се счита за шум за нашите цели):\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"nigerian_songs <- df %>% \r\n",
" # Concentrate on top 3 genres\r\n",
" filter(artist_top_genre %in% c(\"afro dancehall\", \"afropop\",\"nigerian pop\")) %>% \r\n",
" # Remove unclassified observations\r\n",
" filter(popularity != 0)\r\n",
"\r\n",
"\r\n",
"\r\n",
"# Visualize popular genres\r\n",
"nigerian_songs %>%\r\n",
" count(artist_top_genre) %>%\r\n",
" ggplot(mapping = aes(x = artist_top_genre, y = n,\r\n",
" fill = artist_top_genre)) +\r\n",
" geom_col(alpha = 0.8) +\r\n",
" paletteer::scale_fill_paletteer_d(\"ggsci::category10_d3\") +\r\n",
" ggtitle(\"Top genres\") +\r\n",
" theme(plot.title = element_text(hjust = 0.5))\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Нека видим дали има очевидна линейна връзка между числовите променливи в нашия набор от данни. Тази връзка се количествено определя математически чрез [статистиката за корелация](https://en.wikipedia.org/wiki/Correlation).\n",
"\n",
"Статистиката за корелация е стойност между -1 и 1, която показва силата на връзката. Стойности над 0 показват *положителна* корелация (високите стойности на една променлива обикновено съвпадат с високите стойности на другата), докато стойности под 0 показват *отрицателна* корелация (високите стойности на една променлива обикновено съвпадат с ниските стойности на другата).\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Narrow down to numeric variables and fid correlation\r\n",
"corr_mat <- nigerian_songs %>% \r\n",
" select(where(is.numeric)) %>% \r\n",
" cor()\r\n",
"\r\n",
"# Visualize correlation matrix\r\n",
"corrplot(corr_mat, order = 'AOE', col = c('white', 'black'), bg = 'gold2') \r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Данните не са силно корелирани, освен между `energy` и `loudness`, което е логично, тъй като силната музика обикновено е доста енергична. `Popularity` има връзка с `release date`, което също е логично, тъй като по-новите песни вероятно са по-популярни. Дължината и енергията също изглежда имат корелация.\n",
"\n",
"Ще бъде интересно да видим какво може да направи алгоритъм за клъстеризация с тези данни!\n",
"\n",
"> 🎓 Имайте предвид, че корелацията не означава причинно-следствена връзка! Имаме доказателство за корелация, но нямаме доказателство за причинност. Един [забавен уебсайт](https://tylervigen.com/spurious-correlations) предлага визуализации, които подчертават този факт.\n",
"\n",
"### 2. Изследване на разпределението на данните\n",
"\n",
"Нека зададем някои по-фини въпроси. Дали жанровете се различават значително в тяхната възприемаема танцувалност, базирана на тяхната популярност? Нека разгледаме разпределението на данните за популярност и танцувалност на нашите топ три жанра по дадена x и y ос, използвайки [графики на плътност](https://www.khanacademy.org/math/ap-statistics/density-curves-normal-distribution-ap/density-curves/v/density-curves).\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Perform 2D kernel density estimation\r\n",
"density_estimate_2d <- nigerian_songs %>% \r\n",
" ggplot(mapping = aes(x = popularity, y = danceability, color = artist_top_genre)) +\r\n",
" geom_density_2d(bins = 5, size = 1) +\r\n",
" paletteer::scale_color_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n",
" xlim(-20, 80) +\r\n",
" ylim(0, 1.2)\r\n",
"\r\n",
"# Density plot based on the popularity\r\n",
"density_estimate_pop <- nigerian_songs %>% \r\n",
" ggplot(mapping = aes(x = popularity, fill = artist_top_genre, color = artist_top_genre)) +\r\n",
" geom_density(size = 1, alpha = 0.5) +\r\n",
" paletteer::scale_fill_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n",
" paletteer::scale_color_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n",
" theme(legend.position = \"none\")\r\n",
"\r\n",
"# Density plot based on the danceability\r\n",
"density_estimate_dance <- nigerian_songs %>% \r\n",
" ggplot(mapping = aes(x = danceability, fill = artist_top_genre, color = artist_top_genre)) +\r\n",
" geom_density(size = 1, alpha = 0.5) +\r\n",
" paletteer::scale_fill_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n",
" paletteer::scale_color_paletteer_d(\"RSkittleBrewer::wildberry\")\r\n",
"\r\n",
"\r\n",
"# Patch everything together\r\n",
"library(patchwork)\r\n",
"density_estimate_2d / (density_estimate_pop + density_estimate_dance)\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Виждаме, че има концентрични кръгове, които съвпадат, независимо от жанра. Възможно ли е нигерийските предпочитания да се сближават на определено ниво на танцувалност за този жанр?\n",
"\n",
"Като цяло, трите жанра се подреждат по отношение на популярност и танцувалност. Определянето на клъстери в тези слабо подредени данни ще бъде предизвикателство. Нека видим дали диаграма с разпръснати точки може да подкрепи това.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# A scatter plot of popularity and danceability\r\n",
"scatter_plot <- nigerian_songs %>% \r\n",
" ggplot(mapping = aes(x = popularity, y = danceability, color = artist_top_genre, shape = artist_top_genre)) +\r\n",
" geom_point(size = 2, alpha = 0.8) +\r\n",
" paletteer::scale_color_paletteer_d(\"futurevisions::mars\")\r\n",
"\r\n",
"# Add a touch of interactivity\r\n",
"ggplotly(scatter_plot)\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Скатерплот на същите оси показва подобен модел на сближаване.\n",
"\n",
"Като цяло, за клъстеризация можете да използвате скатерплотове, за да покажете групи от данни, така че овладяването на този тип визуализация е много полезно. В следващия урок ще използваме тези филтрирани данни и ще приложим k-means клъстеризация, за да открием групи в данните, които се припокриват по интересни начини.\n",
"\n",
"## **🚀 Предизвикателство**\n",
"\n",
"В подготовка за следващия урок, създайте диаграма за различните алгоритми за клъстеризация, които може да откриете и използвате в производствена среда. Какви видове проблеми се опитва да реши клъстеризацията?\n",
"\n",
"## [**Тест след лекцията**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/28/)\n",
"\n",
"## **Преглед и самостоятелно обучение**\n",
"\n",
"Преди да приложите алгоритми за клъстеризация, както научихме, е добра идея да разберете естеството на вашия набор от данни. Прочетете повече по темата [тук](https://www.kdnuggets.com/2019/10/right-clustering-algorithm.html)\n",
"\n",
"Задълбочете разбирането си за техники за клъстеризация:\n",
"\n",
"- [Обучение и оценка на модели за клъстеризация с Tidymodels и приятели](https://rpubs.com/eR_ic/clustering)\n",
"\n",
"- Брадли Бьомке и Брандън Грийнуел, [*Практическо машинно обучение с R*](https://bradleyboehmke.github.io/HOML/)*.*\n",
"\n",
"## **Задача**\n",
"\n",
"[Проучете други визуализации за клъстеризация](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/assignment.md)\n",
"\n",
"## БЛАГОДАРНОСТИ НА:\n",
"\n",
"[Джен Лупър](https://www.twitter.com/jenlooper) за създаването на оригиналната Python версия на този модул ♥️\n",
"\n",
"[`Дасани Мадипали`](https://twitter.com/dasani_decoded) за създаването на невероятните илюстрации, които правят концепциите за машинно обучение по-разбираеми и лесни за възприемане.\n",
"\n",
"Приятно учене,\n",
"\n",
"[Ерик](https://twitter.com/ericntay), Златен студентски посланик на Microsoft Learn.\n"
],
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
],
"metadata": {
"anaconda-cloud": "",
"kernelspec": {
"display_name": "R",
"language": "R",
"name": "ir"
},
"language_info": {
"codemirror_mode": "r",
"file_extension": ".r",
"mimetype": "text/x-r-source",
"name": "R",
"pygments_lexer": "r",
"version": "3.4.1"
},
"coopTranslator": {
"original_hash": "99c36449cad3708a435f6798cfa39972",
"translation_date": "2025-09-04T07:46:33+00:00",
"source_file": "5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,639 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"anaconda-cloud": "",
"kernelspec": {
"display_name": "R",
"language": "R",
"name": "ir"
},
"language_info": {
"codemirror_mode": "r",
"file_extension": ".r",
"mimetype": "text/x-r-source",
"name": "R",
"pygments_lexer": "r",
"version": "3.4.1"
},
"colab": {
"name": "lesson_14.ipynb",
"provenance": [],
"collapsed_sections": [],
"toc_visible": true
},
"coopTranslator": {
"original_hash": "ad65fb4aad0a156b42216e4929f490fc",
"translation_date": "2025-09-04T08:05:19+00:00",
"source_file": "5-Clustering/2-K-Means/solution/R/lesson_15-R.ipynb",
"language_code": "bg"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "GULATlQXLXyR"
},
"source": [
"## Изследване на клъстеризация с K-Means чрез R и принципите на Tidy данни.\n",
"\n",
"### [**Тест преди лекцията**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/29/)\n",
"\n",
"В този урок ще научите как да създавате клъстери, използвайки пакета Tidymodels и други пакети от екосистемата на R (ще ги наричаме приятели 🧑‍🤝‍🧑), както и набора от данни за нигерийска музика, който импортирахте по-рано. Ще разгледаме основите на K-Means за клъстеризация. Имайте предвид, че както научихте в предишния урок, има много начини за работа с клъстери и методът, който използвате, зависи от вашите данни. Ще опитаме K-Means, тъй като това е най-често използваната техника за клъстеризация. Да започваме!\n",
"\n",
"Термини, които ще научите:\n",
"\n",
"- Оценка на силуета\n",
"\n",
"- Метод на лакътя\n",
"\n",
"- Инерция\n",
"\n",
"- Вариация\n",
"\n",
"### **Въведение**\n",
"\n",
"[K-Means клъстеризация](https://wikipedia.org/wiki/K-means_clustering) е метод, произхождащ от областта на обработката на сигнали. Използва се за разделяне и групиране на данни в `k клъстери` въз основа на сходства в техните характеристики.\n",
"\n",
"Клъстерите могат да бъдат визуализирани като [диаграми на Вороной](https://wikipedia.org/wiki/Voronoi_diagram), които включват точка (или 'семе') и съответната й област.\n",
"\n",
"<p >\n",
" <img src=\"../../images/voronoi.png\"\n",
" width=\"500\"/>\n",
" <figcaption>Инфографика от Джен Лупър</figcaption>\n",
"\n",
"Стъпките на K-Means клъстеризацията са следните:\n",
"\n",
"1. Ученият по данни започва с определяне на желания брой клъстери, които да бъдат създадени.\n",
"\n",
"2. След това алгоритъмът случайно избира K наблюдения от набора от данни, които да служат като начални центрове за клъстерите (т.е. центроиди).\n",
"\n",
"3. След това всяко от останалите наблюдения се присвоява на най-близкия центроид.\n",
"\n",
"4. След това се изчислява новата средна стойност на всеки клъстер и центроидът се премества към тази средна стойност.\n",
"\n",
"5. Сега, когато центровете са преизчислени, всяко наблюдение отново се проверява, за да се види дали може да е по-близо до друг клъстер. Всички обекти се преразпределят отново, използвайки актуализираните средни стойности на клъстерите. Стъпките за преразпределение на клъстерите и актуализация на центроидите се повтарят итеративно, докато разпределението на клъстерите спре да се променя (т.е. когато се постигне конвергенция). Обикновено алгоритъмът приключва, когато всяка нова итерация води до незначително движение на центроидите и клъстерите стават статични.\n",
"\n",
"<div>\n",
"\n",
"> Имайте предвид, че поради случайността при избора на началните k наблюдения, използвани като стартови центроиди, можем да получим леко различни резултати всеки път, когато приложим процедурата. Поради тази причина повечето алгоритми използват няколко *случайни старта* и избират итерацията с най-нисък WCSS. Затова силно се препоръчва винаги да изпълнявате K-Means с няколко стойности на *nstart*, за да избегнете *нежелан локален оптимум.*\n",
"\n",
"</div>\n",
"\n",
"Тази кратка анимация, използваща [илюстрациите](https://github.com/allisonhorst/stats-illustrations) на Алисън Хорст, обяснява процеса на клъстеризация:\n",
"\n",
"<p >\n",
" <img src=\"../../images/kmeans.gif\"\n",
" width=\"550\"/>\n",
" <figcaption>Илюстрация от @allison_horst</figcaption>\n",
"\n",
"Един основен въпрос, който възниква при клъстеризацията, е следният: как да разберете на колко клъстери да разделите данните си? Един недостатък на използването на K-Means е фактът, че трябва да установите `k`, тоест броя на `центроидите`. За щастие, `методът на лакътя` помага да се оцени добра начална стойност за `k`. Ще го опитате след малко.\n",
"\n",
"### \n",
"\n",
"**Предварителни изисквания**\n",
"\n",
"Ще продължим точно оттам, където спряхме в [предишния урок](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb), където анализирахме набора от данни, направихме множество визуализации и филтрирахме набора от данни до интересуващите ни наблюдения. Уверете се, че сте го разгледали!\n",
"\n",
"Ще ни трябват някои пакети, за да завършим този модул. Можете да ги инсталирате със следната команда: `install.packages(c('tidyverse', 'tidymodels', 'cluster', 'summarytools', 'plotly', 'paletteer', 'factoextra', 'patchwork'))`\n",
"\n",
"Алтернативно, скриптът по-долу проверява дали имате необходимите пакети за завършване на този модул и ги инсталира за вас, ако някои липсват.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "ah_tBi58LXyi"
},
"source": [
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n",
"\n",
"pacman::p_load('tidyverse', 'tidymodels', 'cluster', 'summarytools', 'plotly', 'paletteer', 'factoextra', 'patchwork')\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "7e--UCUTLXym"
},
"source": [
"Нека запретнем ръкави!\n",
"\n",
"## 1. Танц с данните: Стеснете избора до трите най-популярни музикални жанра\n",
"\n",
"Това е обобщение на това, което направихме в предишния урок. Нека анализираме и обработим малко данни!\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Ycamx7GGLXyn"
},
"source": [
"# Load the core tidyverse and make it available in your current R session\n",
"library(tidyverse)\n",
"\n",
"# Import the data into a tibble\n",
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/5-Clustering/data/nigerian-songs.csv\", show_col_types = FALSE)\n",
"\n",
"# Narrow down to top 3 popular genres\n",
"nigerian_songs <- df %>% \n",
" # Concentrate on top 3 genres\n",
" filter(artist_top_genre %in% c(\"afro dancehall\", \"afropop\",\"nigerian pop\")) %>% \n",
" # Remove unclassified observations\n",
" filter(popularity != 0)\n",
"\n",
"\n",
"\n",
"# Visualize popular genres using bar plots\n",
"theme_set(theme_light())\n",
"nigerian_songs %>%\n",
" count(artist_top_genre) %>%\n",
" ggplot(mapping = aes(x = artist_top_genre, y = n,\n",
" fill = artist_top_genre)) +\n",
" geom_col(alpha = 0.8) +\n",
" paletteer::scale_fill_paletteer_d(\"ggsci::category10_d3\") +\n",
" ggtitle(\"Top genres\") +\n",
" theme(plot.title = element_text(hjust = 0.5))\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "b5h5zmkPLXyp"
},
"source": [
"🤩 Това мина добре!\n",
"\n",
"## 2. Още изследване на данните.\n",
"\n",
"Колко чисти са тези данни? Нека проверим за отклонения с помощта на box plot диаграми. Ще се съсредоточим върху числови колони с по-малко отклонения (въпреки че бихте могли да изчистите отклоненията). Box plot диаграмите могат да покажат диапазона на данните и ще помогнат да се изберат кои колони да се използват. Забележете, че box plot диаграмите не показват вариация, която е важен елемент за добри данни, подходящи за клъстеризация. Моля, вижте [тази дискусия](https://stats.stackexchange.com/questions/91536/deduce-variance-from-boxplot) за допълнителна информация.\n",
"\n",
"[Box plot диаграмите](https://en.wikipedia.org/wiki/Box_plot) се използват за графично представяне на разпределението на `числови` данни, така че нека започнем с *избор* на всички числови колони заедно с популярните музикални жанрове.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "HhNreJKLLXyq"
},
"source": [
"# Select top genre column and all other numeric columns\n",
"df_numeric <- nigerian_songs %>% \n",
" select(artist_top_genre, where(is.numeric)) \n",
"\n",
"# Display the data\n",
"df_numeric %>% \n",
" slice_head(n = 5)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "uYXrwJRaLXyq"
},
"source": [
"Вижте как помощникът за селекция `where` прави това лесно 💁? Разгледайте други подобни функции [тук](https://tidyselect.r-lib.org/).\n",
"\n",
"Тъй като ще създаваме кутии за разпределение (boxplot) за всяка числова характеристика и искаме да избегнем използването на цикли, нека преформатираме данните си в *по-дълъг* формат, който ще ни позволи да се възползваме от `facets` - подграфики, всяка от които показва един подмножество от данните.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "gd5bR3f8LXys"
},
"source": [
"# Pivot data from wide to long\n",
"df_numeric_long <- df_numeric %>% \n",
" pivot_longer(!artist_top_genre, names_to = \"feature_names\", values_to = \"values\") \n",
"\n",
"# Print out data\n",
"df_numeric_long %>% \n",
" slice_head(n = 15)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "-7tE1swnLXyv"
},
"source": [
"Много по-дълго! Сега е време за малко `ggplots`! И така, кой `geom` ще използваме?\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "r88bIsyuLXyy"
},
"source": [
"# Make a box plot\n",
"df_numeric_long %>% \n",
" ggplot(mapping = aes(x = feature_names, y = values, fill = feature_names)) +\n",
" geom_boxplot() +\n",
" facet_wrap(~ feature_names, ncol = 4, scales = \"free\") +\n",
" theme(legend.position = \"none\")\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "EYVyKIUELXyz"
},
"source": [
"Лесно-gg!\n",
"\n",
"Сега можем да видим, че тези данни са малко шумни: като наблюдаваме всяка колона чрез boxplot, можем да забележим аутлайъри. Бихте могли да прегледате набора от данни и да премахнете тези аутлайъри, но това би направило данните доста минимални.\n",
"\n",
"Засега нека изберем кои колони ще използваме за нашето упражнение по клъстеризация. Нека изберем числовите колони с подобни диапазони. Можем да кодираме `artist_top_genre` като числова стойност, но засега ще я пропуснем.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "-wkpINyZLXy0"
},
"source": [
"# Select variables with similar ranges\n",
"df_numeric_select <- df_numeric %>% \n",
" select(popularity, danceability, acousticness, loudness, energy) \n",
"\n",
"# Normalize data\n",
"# df_numeric_select <- scale(df_numeric_select)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "D7dLzgpqLXy1"
},
"source": [
"## 3. Изчисляване на k-means клъстериране в R\n",
"\n",
"Можем да изчислим k-means в R с вградената функция `kmeans`, вижте `help(\"kmeans()\")`. Функцията `kmeans()` приема дата фрейм с всички числови колони като основен аргумент.\n",
"\n",
"Първата стъпка при използването на k-means клъстериране е да се определи броят на клъстерите (k), които ще бъдат генерирани в крайното решение. Знаем, че има 3 музикални жанра, които сме извлекли от набора от данни, така че нека опитаме с 3:\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "uC4EQ5w7LXy5"
},
"source": [
"set.seed(2056)\n",
"# Kmeans clustering for 3 clusters\n",
"kclust <- kmeans(\n",
" df_numeric_select,\n",
" # Specify the number of clusters\n",
" centers = 3,\n",
" # How many random initial configurations\n",
" nstart = 25\n",
")\n",
"\n",
"# Display clustering object\n",
"kclust\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "hzfhscWrLXy-"
},
"source": [
"Обектът kmeans съдържа няколко части информация, които са добре обяснени в `help(\"kmeans()\")`. Засега нека се съсредоточим върху няколко от тях. Виждаме, че данните са групирани в 3 клъстера с размери 65, 110, 111. Резултатът също така съдържа центровете на клъстерите (средните стойности) за трите групи през петте променливи.\n",
"\n",
"Клъстеризиращият вектор представлява класификацията на клъстера за всяко наблюдение. Нека използваме функцията `augment`, за да добавим класификацията на клъстера към оригиналния набор от данни.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "0XwwpFGQLXy_"
},
"source": [
"# Add predicted cluster assignment to data set\n",
"augment(kclust, df_numeric_select) %>% \n",
" relocate(.cluster) %>% \n",
" slice_head(n = 10)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "NXIVXXACLXzA"
},
"source": [
"Перфектно, току-що разделихме нашия набор от данни на 3 групи. И така, колко добра е нашата кластеризация 🤷? Нека разгледаме `Silhouette score`.\n",
"\n",
"### **Silhouette score**\n",
"\n",
"[Silhouette анализът](https://en.wikipedia.org/wiki/Silhouette_(clustering)) може да се използва за изучаване на разстоянието на разделяне между получените клъстери. Тази оценка варира от -1 до 1, като ако оценката е близо до 1, клъстерът е плътен и добре отделен от другите клъстери. Стойност близо до 0 представлява припокриващи се клъстери с проби, които са много близо до границата на решение на съседните клъстери. [източник](https://dzone.com/articles/kmeans-silhouette-score-explained-with-python-exam).\n",
"\n",
"Методът за средна стойност на силуета изчислява средния силует на наблюденията за различни стойности на *k*. Висока средна стойност на силуета показва добра кластеризация.\n",
"\n",
"Функцията `silhouette` в пакета за клъстери се използва за изчисляване на средната ширина на силуета.\n",
"\n",
"> Силуетът може да бъде изчислен с всяка [метрика за разстояние](https://en.wikipedia.org/wiki/Distance \"Distance\"), като например [Евклидово разстояние](https://en.wikipedia.org/wiki/Euclidean_distance \"Euclidean distance\") или [Манхатънско разстояние](https://en.wikipedia.org/wiki/Manhattan_distance \"Manhattan distance\"), които обсъдихме в [предишния урок](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb).\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Jn0McL28LXzB"
},
"source": [
"# Load cluster package\n",
"library(cluster)\n",
"\n",
"# Compute average silhouette score\n",
"ss <- silhouette(kclust$cluster,\n",
" # Compute euclidean distance\n",
" dist = dist(df_numeric_select))\n",
"mean(ss[, 3])\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "QyQRn97nLXzC"
},
"source": [
"Нашият резултат е **0.549**, което е точно по средата. Това показва, че нашите данни не са особено подходящи за този тип клъстеризация. Нека видим дали можем да потвърдим това предположение визуално. Пакетът [factoextra](https://rpkgs.datanovia.com/factoextra/index.html) предоставя функции (`fviz_cluster()`) за визуализиране на клъстеризацията.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "7a6Km1_FLXzD"
},
"source": [
"library(factoextra)\n",
"\n",
"# Visualize clustering results\n",
"fviz_cluster(kclust, df_numeric_select)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "IBwCWt-0LXzD"
},
"source": [
"Покриването на клъстерите показва, че нашите данни не са особено подходящи за този тип клъстеризация, но нека продължим.\n",
"\n",
"## 4. Определяне на оптималния брой клъстери\n",
"\n",
"Основен въпрос, който често възниква при клъстеризация с K-Means, е следният - без известни етикети на класовете, как да разберем на колко клъстера да разделим данните си?\n",
"\n",
"Един от начините да разберем това е като използваме извадка от данните, за да `създадем серия от модели за клъстеризация` с увеличаващ се брой клъстери (например от 1 до 10) и оценим метрики за клъстеризация като **Silhouette score.**\n",
"\n",
"Нека определим оптималния брой клъстери, като изчислим алгоритъма за клъстеризация за различни стойности на *k* и оценим **Сумата на квадратите в рамките на клъстера** (WCSS). Общата сума на квадратите в рамките на клъстера (WCSS) измерва компактността на клъстеризацията и искаме тя да бъде възможно най-малка, като по-ниски стойности означават, че точките от данните са по-близо една до друга.\n",
"\n",
"Нека изследваме ефекта от различните избори на `k`, от 1 до 10, върху тази клъстеризация.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "hSeIiylDLXzE"
},
"source": [
"# Create a series of clustering models\n",
"kclusts <- tibble(k = 1:10) %>% \n",
" # Perform kmeans clustering for 1,2,3 ... ,10 clusters\n",
" mutate(model = map(k, ~ kmeans(df_numeric_select, centers = .x, nstart = 25)),\n",
" # Farm out clustering metrics eg WCSS\n",
" glanced = map(model, ~ glance(.x))) %>% \n",
" unnest(cols = glanced)\n",
" \n",
"\n",
"# View clustering rsulsts\n",
"kclusts\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "m7rS2U1eLXzE"
},
"source": [
"Сега, когато имаме общата сума на квадратите в рамките на клъстера (tot.withinss) за всеки алгоритъм за клъстеризация с център *k*, използваме [метода на лакътя](https://en.wikipedia.org/wiki/Elbow_method_(clustering)), за да намерим оптималния брой клъстери. Методът се състои в изчертаване на WCSS като функция от броя на клъстерите и избиране на [лакътя на кривата](https://en.wikipedia.org/wiki/Elbow_of_the_curve \"Лакът на кривата\") като броя на клъстерите, които да се използват.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "o_DjHGItLXzF"
},
"source": [
"set.seed(2056)\n",
"# Use elbow method to determine optimum number of clusters\n",
"kclusts %>% \n",
" ggplot(mapping = aes(x = k, y = tot.withinss)) +\n",
" geom_line(size = 1.2, alpha = 0.8, color = \"#FF7F0EFF\") +\n",
" geom_point(size = 2, color = \"#FF7F0EFF\")\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "pLYyt5XSLXzG"
},
"source": [
"Графиката показва значително намаление на WCSS (следователно по-голяма *стегнатост*), когато броят на клъстерите се увеличава от един на два, и допълнително забележимо намаление от два на три клъстера. След това намалението е по-слабо изразено, което води до `лакът` 💪 на графиката около три клъстера. Това е добър показател, че има две до три сравнително добре разделени клъстера от точки данни.\n",
"\n",
"Сега можем да продължим и да извлечем модела за клъстериране, където `k = 3`:\n",
"\n",
"> `pull()`: използва се за извличане на една колона\n",
">\n",
"> `pluck()`: използва се за индексиране на структури от данни като списъци\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "JP_JPKBILXzG"
},
"source": [
"# Extract k = 3 clustering\n",
"final_kmeans <- kclusts %>% \n",
" filter(k == 3) %>% \n",
" pull(model) %>% \n",
" pluck(1)\n",
"\n",
"\n",
"final_kmeans\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "l_PDTu8tLXzI"
},
"source": [
"Чудесно! Нека да визуализираме получените клъстери. Искате ли малко интерактивност с `plotly`?\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "dNcleFe-LXzJ"
},
"source": [
"# Add predicted cluster assignment to data set\n",
"results <- augment(final_kmeans, df_numeric_select) %>% \n",
" bind_cols(df_numeric %>% select(artist_top_genre)) \n",
"\n",
"# Plot cluster assignments\n",
"clust_plt <- results %>% \n",
" ggplot(mapping = aes(x = popularity, y = danceability, color = .cluster, shape = artist_top_genre)) +\n",
" geom_point(size = 2, alpha = 0.8) +\n",
" paletteer::scale_color_paletteer_d(\"ggthemes::Tableau_10\")\n",
"\n",
"ggplotly(clust_plt)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "6JUM_51VLXzK"
},
"source": [
"Може би бихме очаквали, че всеки клъстер (представен с различни цветове) ще има различни жанрове (представени с различни форми).\n",
"\n",
"Нека разгледаме точността на модела.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "HdIMUGq7LXzL"
},
"source": [
"# Assign genres to predefined integers\n",
"label_count <- results %>% \n",
" group_by(artist_top_genre) %>% \n",
" mutate(id = cur_group_id()) %>% \n",
" ungroup() %>% \n",
" summarise(correct_labels = sum(.cluster == id))\n",
"\n",
"\n",
"# Print results \n",
"cat(\"Result:\", label_count$correct_labels, \"out of\", nrow(results), \"samples were correctly labeled.\")\n",
"\n",
"cat(\"\\nAccuracy score:\", label_count$correct_labels/nrow(results))\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "C50wvaAOLXzM"
},
"source": [
"Точността на този модел не е лоша, но не е и отлична. Възможно е данните да не са подходящи за K-Means Clustering. Тези данни са твърде небалансирани, слабо корелирани и има прекалено голяма вариация между стойностите на колоните, за да се формират добри клъстери. Всъщност, клъстерите, които се формират, вероятно са силно повлияни или изкривени от трите жанрови категории, които дефинирахме по-горе.\n",
"\n",
"Въпреки това, процесът беше доста поучителен!\n",
"\n",
"В документацията на Scikit-learn можете да видите, че модел като този, с клъстери, които не са добре разграничени, има проблем с \"вариацията\":\n",
"\n",
"<p >\n",
" <img src=\"../../images/problems.png\"\n",
" width=\"500\"/>\n",
" <figcaption>Инфографика от Scikit-learn</figcaption>\n",
"\n",
"\n",
"\n",
"## **Вариация**\n",
"\n",
"Вариацията се определя като \"средната стойност на квадратите на разликите от средната стойност\" [източник](https://www.mathsisfun.com/data/standard-deviation.html). В контекста на този проблем с клъстерирането, това се отнася до данни, при които стойностите в набора от данни се отклоняват твърде много от средната стойност.\n",
"\n",
"✅ Това е чудесен момент да помислите за всички начини, по които можете да коригирате този проблем. Да промените данните малко повече? Да използвате различни колони? Да използвате различен алгоритъм? Подсказка: Опитайте [скалиране на данните](https://www.mygreatlearning.com/blog/learning-data-science-with-k-means-clustering/), за да ги нормализирате и да тествате други колони.\n",
"\n",
"> Опитайте този '[калкулатор за вариация](https://www.calculatorsoup.com/calculators/statistics/variance-calculator.php)', за да разберете концепцията малко по-добре.\n",
"\n",
"------------------------------------------------------------------------\n",
"\n",
"## **🚀Предизвикателство**\n",
"\n",
"Отделете време с този notebook, за да промените параметрите. Можете ли да подобрите точността на модела, като почистите данните повече (например премахнете аутлайъри)? Можете да използвате тегла, за да дадете повече тежест на определени проби от данни. Какво друго можете да направите, за да създадете по-добри клъстери?\n",
"\n",
"Подсказка: Опитайте да скалирате данните си. В notebook има коментиран код, който добавя стандартно скалиране, за да направи колоните с данни по-сходни по отношение на диапазона. Ще забележите, че докато оценката на силуета намалява, \"пречупването\" в графиката на лакътя се изглажда. Това е така, защото оставянето на данните без скалиране позволява данни с по-малка вариация да имат по-голяма тежест. Прочетете повече за този проблем [тук](https://stats.stackexchange.com/questions/21222/are-mean-normalization-and-feature-scaling-needed-for-k-means-clustering/21226#21226).\n",
"\n",
"## [**Тест след лекцията**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/30/)\n",
"\n",
"## **Преглед и самостоятелно обучение**\n",
"\n",
"- Разгледайте симулатор за K-Means [като този](https://user.ceng.metu.edu.tr/~akifakkus/courses/ceng574/k-means/). Можете да използвате този инструмент, за да визуализирате примерни точки от данни и да определите техните центроиди. Можете да редактирате случайността на данните, броя на клъстерите и броя на центроидите. Помага ли това да получите представа как данните могат да бъдат групирани?\n",
"\n",
"- Също така, разгледайте [този материал за K-Means](https://stanford.edu/~cpiech/cs221/handouts/kmeans.html) от Станфорд.\n",
"\n",
"Искате ли да приложите новопридобитите си умения за клъстериране към набори от данни, които са подходящи за K-Means клъстериране? Вижте:\n",
"\n",
"- [Обучение и оценка на модели за клъстериране](https://rpubs.com/eR_ic/clustering) с помощта на Tidymodels и приятели\n",
"\n",
"- [Анализ на клъстери с K-Means](https://uc-r.github.io/kmeans_clustering), UC Business Analytics R Programming Guide\n",
"\n",
"- [Клъстериране с K-Means и принципи на tidy данни](https://www.tidymodels.org/learn/statistics/k-means/)\n",
"\n",
"## **Задание**\n",
"\n",
"[Опитайте различни методи за клъстериране](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/2-K-Means/assignment.md)\n",
"\n",
"## БЛАГОДАРНОСТИ НА:\n",
"\n",
"[Jen Looper](https://www.twitter.com/jenlooper) за създаването на оригиналната Python версия на този модул ♥️\n",
"\n",
"[`Allison Horst`](https://twitter.com/allison_horst/) за създаването на невероятните илюстрации, които правят R по-приветлив и ангажиращ. Намерете повече илюстрации в нейния [галерия](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n",
"\n",
"Приятно учене,\n",
"\n",
"[Eric](https://twitter.com/ericntay), Златен студентски посланик на Microsoft Learn.\n",
"\n",
"<p >\n",
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
" width=\"500\"/>\n",
" <figcaption>Илюстрация от @allison_horst</figcaption>\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,100 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "27de2abc0235ebd22080fc8f1107454d",
"translation_date": "2025-09-04T09:29:46+00:00",
"source_file": "6-NLP/3-Translation-Sentiment/solution/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from textblob import TextBlob\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# You should download the book text, clean it, and import it here\n",
"with open(\"pride.txt\", encoding=\"utf8\") as f:\n",
" file_contents = f.read()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"book_pride = TextBlob(file_contents)\n",
"positive_sentiment_sentences = []\n",
"negative_sentiment_sentences = []"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for sentence in book_pride.sentences:\n",
" if sentence.sentiment.polarity == 1:\n",
" positive_sentiment_sentences.append(sentence)\n",
" if sentence.sentiment.polarity == -1:\n",
" negative_sentiment_sentences.append(sentence)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"The \" + str(len(positive_sentiment_sentences)) + \" most positive sentences:\")\n",
"for sentence in positive_sentiment_sentences:\n",
" print(\"+ \" + str(sentence.replace(\"\\n\", \"\").replace(\" \", \" \")))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"The \" + str(len(negative_sentiment_sentences)) + \" most negative sentences:\")\n",
"for sentence in negative_sentiment_sentences:\n",
" print(\"- \" + str(sentence.replace(\"\\n\", \"\").replace(\" \", \" \")))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Не носим отговорност за каквито и да било недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,174 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "2d05e7db439376aa824f4b387f8324ca",
"translation_date": "2025-09-04T09:29:17+00:00",
"source_file": "6-NLP/4-Hotel-Reviews-1/solution/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# EDA\n",
"import pandas as pd\n",
"import time"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_difference_review_avg(row):\n",
" return row[\"Average_Score\"] - row[\"Calc_Average_Score\"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Load the hotel reviews from CSV\n",
"print(\"Loading data file now, this could take a while depending on file size\")\n",
"start = time.time()\n",
"df = pd.read_csv('../../data/Hotel_Reviews.csv')\n",
"end = time.time()\n",
"print(\"Loading took \" + str(round(end - start, 2)) + \" seconds\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# What shape is the data (rows, columns)?\n",
"print(\"The shape of the data (rows, cols) is \" + str(df.shape))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# value_counts() creates a Series object that has index and values\n",
"# in this case, the country and the frequency they occur in reviewer nationality\n",
"nationality_freq = df[\"Reviewer_Nationality\"].value_counts()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# What reviewer nationality is the most common in the dataset?\n",
"print(\"The highest frequency reviewer nationality is \" + str(nationality_freq.index[0]).strip() + \" with \" + str(nationality_freq[0]) + \" reviews.\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# What is the top 10 most common nationalities and their frequencies?\n",
"print(\"The top 10 highest frequency reviewer nationalities are:\")\n",
"print(nationality_freq[0:10].to_string())\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# How many unique nationalities are there?\n",
"print(\"There are \" + str(nationality_freq.index.size) + \" unique nationalities in the dataset\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# What was the most frequently reviewed hotel for the top 10 nationalities - print the hotel and number of reviews\n",
"for nat in nationality_freq[:10].index:\n",
" # First, extract all the rows that match the criteria into a new dataframe\n",
" nat_df = df[df[\"Reviewer_Nationality\"] == nat] \n",
" # Now get the hotel freq\n",
" freq = nat_df[\"Hotel_Name\"].value_counts()\n",
" print(\"The most reviewed hotel for \" + str(nat).strip() + \" was \" + str(freq.index[0]) + \" with \" + str(freq[0]) + \" reviews.\") \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# How many reviews are there per hotel (frequency count of hotel) and do the results match the value in `Total_Number_of_Reviews`?\n",
"# First create a new dataframe based on the old one, removing the uneeded columns\n",
"hotel_freq_df = df.drop([\"Hotel_Address\", \"Additional_Number_of_Scoring\", \"Review_Date\", \"Average_Score\", \"Reviewer_Nationality\", \"Negative_Review\", \"Review_Total_Negative_Word_Counts\", \"Positive_Review\", \"Review_Total_Positive_Word_Counts\", \"Total_Number_of_Reviews_Reviewer_Has_Given\", \"Reviewer_Score\", \"Tags\", \"days_since_review\", \"lat\", \"lng\"], axis = 1)\n",
"# Group the rows by Hotel_Name, count them and put the result in a new column Total_Reviews_Found\n",
"hotel_freq_df['Total_Reviews_Found'] = hotel_freq_df.groupby('Hotel_Name').transform('count')\n",
"# Get rid of all the duplicated rows\n",
"hotel_freq_df = hotel_freq_df.drop_duplicates(subset = [\"Hotel_Name\"])\n",
"print()\n",
"print(hotel_freq_df.to_string())\n",
"print(str(hotel_freq_df.shape))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# While there is an `Average_Score` for each hotel according to the dataset, \n",
"# you can also calculate an average score (getting the average of all reviewer scores in the dataset for each hotel)\n",
"# Add a new column to your dataframe with the column header `Calc_Average_Score` that contains that calculated average. \n",
"df['Calc_Average_Score'] = round(df.groupby('Hotel_Name').Reviewer_Score.transform('mean'), 1)\n",
"# Add a new column with the difference between the two average scores\n",
"df[\"Average_Score_Difference\"] = df.apply(get_difference_review_avg, axis = 1)\n",
"# Create a df without all the duplicates of Hotel_Name (so only 1 row per hotel)\n",
"review_scores_df = df.drop_duplicates(subset = [\"Hotel_Name\"])\n",
"# Sort the dataframe to find the lowest and highest average score difference\n",
"review_scores_df = review_scores_df.sort_values(by=[\"Average_Score_Difference\"])\n",
"print(review_scores_df[[\"Average_Score_Difference\", \"Average_Score\", \"Calc_Average_Score\", \"Hotel_Name\"]])\n",
"# Do any hotels have the same (rounded to 1 decimal place) `Average_Score` and `Calc_Average_Score`?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,172 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 4,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"coopTranslator": {
"original_hash": "033cb89c85500224b3c63fd04f49b4aa",
"translation_date": "2025-09-04T09:30:17+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/solution/1-notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import time\n",
"import ast"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def replace_address(row):\n",
" if \"Netherlands\" in row[\"Hotel_Address\"]:\n",
" return \"Amsterdam, Netherlands\"\n",
" elif \"Barcelona\" in row[\"Hotel_Address\"]:\n",
" return \"Barcelona, Spain\"\n",
" elif \"United Kingdom\" in row[\"Hotel_Address\"]:\n",
" return \"London, United Kingdom\"\n",
" elif \"Milan\" in row[\"Hotel_Address\"]: \n",
" return \"Milan, Italy\"\n",
" elif \"France\" in row[\"Hotel_Address\"]:\n",
" return \"Paris, France\"\n",
" elif \"Vienna\" in row[\"Hotel_Address\"]:\n",
" return \"Vienna, Austria\" \n",
" else:\n",
" return row.Hotel_Address\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# Load the hotel reviews from CSV\n",
"start = time.time()\n",
"df = pd.read_csv('../../data/Hotel_Reviews.csv')\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# dropping columns we will not use:\n",
"df.drop([\"lat\", \"lng\"], axis = 1, inplace=True)\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# Replace all the addresses with a shortened, more useful form\n",
"df[\"Hotel_Address\"] = df.apply(replace_address, axis = 1)\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# Drop `Additional_Number_of_Scoring`\n",
"df.drop([\"Additional_Number_of_Scoring\"], axis = 1, inplace=True)\n",
"# Replace `Total_Number_of_Reviews` and `Average_Score` with our own calculated values\n",
"df.Total_Number_of_Reviews = df.groupby('Hotel_Name').transform('count')\n",
"df.Average_Score = round(df.groupby('Hotel_Name').Reviewer_Score.transform('mean'), 1)\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# Process the Tags into new columns\n",
"# The file Hotel_Reviews_Tags.py, identifies the most important tags\n",
"# Leisure trip, Couple, Solo traveler, Business trip, Group combined with Travelers with friends, \n",
"# Family with young children, Family with older children, With a pet\n",
"df[\"Leisure_trip\"] = df.Tags.apply(lambda tag: 1 if \"Leisure trip\" in tag else 0)\n",
"df[\"Couple\"] = df.Tags.apply(lambda tag: 1 if \"Couple\" in tag else 0)\n",
"df[\"Solo_traveler\"] = df.Tags.apply(lambda tag: 1 if \"Solo traveler\" in tag else 0)\n",
"df[\"Business_trip\"] = df.Tags.apply(lambda tag: 1 if \"Business trip\" in tag else 0)\n",
"df[\"Group\"] = df.Tags.apply(lambda tag: 1 if \"Group\" in tag or \"Travelers with friends\" in tag else 0)\n",
"df[\"Family_with_young_children\"] = df.Tags.apply(lambda tag: 1 if \"Family with young children\" in tag else 0)\n",
"df[\"Family_with_older_children\"] = df.Tags.apply(lambda tag: 1 if \"Family with older children\" in tag else 0)\n",
"df[\"With_a_pet\"] = df.Tags.apply(lambda tag: 1 if \"With a pet\" in tag else 0)\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# No longer need any of these columns\n",
"df.drop([\"Review_Date\", \"Review_Total_Negative_Word_Counts\", \"Review_Total_Positive_Word_Counts\", \"days_since_review\", \"Total_Number_of_Reviews_Reviewer_Has_Given\"], axis = 1, inplace=True)\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Saving results to Hotel_Reviews_Filtered.csv\n",
"Filtering took 23.74 seconds\n"
]
}
],
"source": [
"# Saving new data file with calculated columns\n",
"print(\"Saving results to Hotel_Reviews_Filtered.csv\")\n",
"df.to_csv(r'../../data/Hotel_Reviews_Filtered.csv', index = False)\n",
"end = time.time()\n",
"print(\"Filtering took \" + str(round(end - start, 2)) + \" seconds\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,137 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 4,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"coopTranslator": {
"original_hash": "341efc86325ec2a214f682f57a189dfd",
"translation_date": "2025-09-04T09:30:46+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/solution/2-notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# Load the hotel reviews from CSV (you can )\n",
"import pandas as pd \n",
"\n",
"df = pd.read_csv('../../data/Hotel_Reviews_Filtered.csv')\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# We want to find the most useful tags to keep\n",
"# Remove opening and closing brackets\n",
"df.Tags = df.Tags.str.strip(\"[']\")\n",
"# remove all quotes too\n",
"df.Tags = df.Tags.str.replace(\" ', '\", \",\", regex = False)\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# removing this to take advantage of the 'already a phrase' fact of the dataset \n",
"# Now split the strings into a list\n",
"tag_list_df = df.Tags.str.split(',', expand = True)\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# Remove leading and trailing spaces\n",
"df[\"Tag_1\"] = tag_list_df[0].str.strip()\n",
"df[\"Tag_2\"] = tag_list_df[1].str.strip()\n",
"df[\"Tag_3\"] = tag_list_df[2].str.strip()\n",
"df[\"Tag_4\"] = tag_list_df[3].str.strip()\n",
"df[\"Tag_5\"] = tag_list_df[4].str.strip()\n",
"df[\"Tag_6\"] = tag_list_df[5].str.strip()\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# Merge the 6 columns into one with melt\n",
"df_tags = df.melt(value_vars=[\"Tag_1\", \"Tag_2\", \"Tag_3\", \"Tag_4\", \"Tag_5\", \"Tag_6\"])\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"The shape of the tags with no filtering: (2514684, 2)\n",
" index count\n",
"0 Leisure trip 338423\n",
"1 Couple 205305\n",
"2 Solo traveler 89779\n",
"3 Business trip 68176\n",
"4 Group 51593\n",
"5 Family with young children 49318\n",
"6 Family with older children 21509\n",
"7 Travelers with friends 1610\n",
"8 With a pet 1078\n"
]
}
],
"source": [
"# Get the value counts\n",
"tag_vc = df_tags.value.value_counts()\n",
"# print(tag_vc)\n",
"print(\"The shape of the tags with no filtering:\", str(df_tags.shape))\n",
"# Drop rooms, suites, and length of stay, mobile device and anything with less count than a 1000\n",
"df_tags = df_tags[~df_tags.value.str.contains(\"Standard|room|Stayed|device|Beds|Suite|Studio|King|Superior|Double\", na=False, case=False)]\n",
"tag_vc = df_tags.value.value_counts().reset_index(name=\"count\").query(\"count > 1000\")\n",
"# Print the top 10 (there should only be 9 and we'll use these in the filtering section)\n",
"print(tag_vc[:10])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

@ -0,0 +1,260 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 4,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"coopTranslator": {
"original_hash": "705bf02633759f689abc37b19749a16d",
"translation_date": "2025-09-04T09:31:17+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/solution/3-notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stderr",
"text": [
"[nltk_data] Downloading package vader_lexicon to\n[nltk_data] /Users/jenlooper/nltk_data...\n"
]
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"True"
]
},
"metadata": {},
"execution_count": 9
}
],
"source": [
"import time\n",
"import pandas as pd\n",
"import nltk as nltk\n",
"from nltk.corpus import stopwords\n",
"from nltk.sentiment.vader import SentimentIntensityAnalyzer\n",
"nltk.download('vader_lexicon')\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"vader_sentiment = SentimentIntensityAnalyzer()\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# There are 3 possibilities of input for a review:\n",
"# It could be \"No Negative\", in which case, return 0\n",
"# It could be \"No Positive\", in which case, return 0\n",
"# It could be a review, in which case calculate the sentiment\n",
"def calc_sentiment(review): \n",
" if review == \"No Negative\" or review == \"No Positive\":\n",
" return 0\n",
" return vader_sentiment.polarity_scores(review)[\"compound\"] \n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"# Load the hotel reviews from CSV\n",
"df = pd.read_csv(\"../../data/Hotel_Reviews_Filtered.csv\")\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"# Remove stop words - can be slow for a lot of text!\n",
"# Ryan Han (ryanxjhan on Kaggle) has a great post measuring performance of different stop words removal approaches\n",
"# https://www.kaggle.com/ryanxjhan/fast-stop-words-removal # using the approach that Ryan recommends\n",
"start = time.time()\n",
"cache = set(stopwords.words(\"english\"))\n",
"def remove_stopwords(review):\n",
" text = \" \".join([word for word in review.split() if word not in cache])\n",
" return text\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"# Remove the stop words from both columns\n",
"df.Negative_Review = df.Negative_Review.apply(remove_stopwords) \n",
"df.Positive_Review = df.Positive_Review.apply(remove_stopwords)\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Removing stop words took 5.77 seconds\n"
]
}
],
"source": [
"end = time.time()\n",
"print(\"Removing stop words took \" + str(round(end - start, 2)) + \" seconds\")\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Calculating sentiment columns for both positive and negative reviews\n",
"Calculating sentiment took 201.07 seconds\n"
]
}
],
"source": [
"# Add a negative sentiment and positive sentiment column\n",
"print(\"Calculating sentiment columns for both positive and negative reviews\")\n",
"start = time.time()\n",
"df[\"Negative_Sentiment\"] = df.Negative_Review.apply(calc_sentiment)\n",
"df[\"Positive_Sentiment\"] = df.Positive_Review.apply(calc_sentiment)\n",
"end = time.time()\n",
"print(\"Calculating sentiment took \" + str(round(end - start, 2)) + \" seconds\")\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" Negative_Review Negative_Sentiment\n",
"186584 So bad experience memories I hotel The first n... -0.9920\n",
"129503 First charged twice room booked booking second... -0.9896\n",
"307286 The staff Had bad experience even booking Janu... -0.9889\n",
"452092 No WLAN room Incredibly rude restaurant staff ... -0.9884\n",
"201293 We usually traveling Paris 2 3 times year busi... -0.9873\n",
"... ... ...\n",
"26899 I would say however one night expensive even d... 0.9933\n",
"138365 Wifi terribly slow I speed test network upload... 0.9938\n",
"79215 I find anything hotel first I walked past hote... 0.9938\n",
"278506 The property great location There bakery next ... 0.9945\n",
"339189 Guys I like hotel I wish return next year Howe... 0.9948\n",
"\n",
"[515738 rows x 2 columns]\n",
" Positive_Review Positive_Sentiment\n",
"137893 Bathroom Shower We going stay twice hotel 2 ni... -0.9820\n",
"5839 I completely disappointed mad since reception ... -0.9780\n",
"64158 get everything extra internet parking breakfas... -0.9751\n",
"124178 I didnt like anythig Room small Asked upgrade ... -0.9721\n",
"489137 Very rude manager abusive staff reception Dirt... -0.9703\n",
"... ... ...\n",
"331570 Everything This recently renovated hotel class... 0.9984\n",
"322920 From moment stepped doors Guesthouse Hotel sta... 0.9985\n",
"293710 This place surprise expected good actually gre... 0.9985\n",
"417442 We celebrated wedding night Langham I commend ... 0.9985\n",
"132492 We arrived super cute boutique hotel area expl... 0.9987\n",
"\n",
"[515738 rows x 2 columns]\n"
]
}
],
"source": [
"df = df.sort_values(by=[\"Negative_Sentiment\"], ascending=True)\n",
"print(df[[\"Negative_Review\", \"Negative_Sentiment\"]])\n",
"df = df.sort_values(by=[\"Positive_Sentiment\"], ascending=True)\n",
"print(df[[\"Positive_Review\", \"Positive_Sentiment\"]])\n"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"# Reorder the columns (This is cosmetic, but to make it easier to explore the data later)\n",
"df = df.reindex([\"Hotel_Name\", \"Hotel_Address\", \"Total_Number_of_Reviews\", \"Average_Score\", \"Reviewer_Score\", \"Negative_Sentiment\", \"Positive_Sentiment\", \"Reviewer_Nationality\", \"Leisure_trip\", \"Couple\", \"Solo_traveler\", \"Business_trip\", \"Group\", \"Family_with_young_children\", \"Family_with_older_children\", \"With_a_pet\", \"Negative_Review\", \"Positive_Review\"], axis=1)\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Saving results to Hotel_Reviews_NLP.csv\n"
]
}
],
"source": [
"print(\"Saving results to Hotel_Reviews_NLP.csv\")\n",
"df.to_csv(r\"../../data/Hotel_Reviews_NLP.csv\", index = False)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,63 @@
{
"cells": [
{
"source": [
"# Подготовка на данни\n",
"\n",
"В този тетрадка ще демонстрираме как да:\n",
"\n",
"подготвим времеви редове за този модул \n",
"визуализираме данните \n",
"Данните в този пример са взети от състезанието за прогнозиране GEFCom2014. Те включват 3 години почасови стойности за електрическо натоварване и температура за периода между 2012 и 2014 година.\n",
"\n",
"1Tao Hong, Pierre Pinson, Shu Fan, Hamidreza Zareipour, Alberto Troccoli и Rob J. Hyndman, \"Probabilistic energy forecasting: Global Energy Forecasting Competition 2014 and beyond\", International Journal of Forecasting, том 32, бр. 3, стр. 896-913, юли-септември, 2016.\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
],
"metadata": {
"kernel_info": {
"name": "python3"
},
"kernelspec": {
"name": "python37364bit8d3b438fb5fc4430a93ac2cb74d693a7",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"nteract": {
"version": "nteract-front-end@1.0.0"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "5e2bbe594906dce3aaaa736d6dac6683",
"translation_date": "2025-09-04T07:33:21+00:00",
"source_file": "7-TimeSeries/1-Introduction/working/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,59 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "523ec472196307b3c4235337353c9ceb",
"translation_date": "2025-09-04T07:30:49+00:00",
"source_file": "7-TimeSeries/2-ARIMA/working/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [
"# Прогнозиране на времеви редове с ARIMA\n",
"\n",
"В този тетрадка ще демонстрираме как да:\n",
"- подготвим данни за времеви редове за обучение на ARIMA модел за прогнозиране\n",
"- приложим прост ARIMA модел за прогнозиране на следващите HORIZON стъпки напред (време *t+1* до *t+HORIZON*) във времевия ред\n",
"- оценим модела\n",
"\n",
"Данните в този пример са взети от състезанието за прогнозиране GEFCom2014. Те се състоят от 3 години почасови стойности на електрическо натоварване и температура между 2012 и 2014 година. Задачата е да се прогнозират бъдещи стойности на електрическото натоварване. В този пример ще покажем как да прогнозираме една стъпка напред, използвайки само исторически данни за натоварването.\n",
"\n",
"Tao Hong, Pierre Pinson, Shu Fan, Hamidreza Zareipour, Alberto Troccoli и Rob J. Hyndman, \"Probabilistic energy forecasting: Global Energy Forecasting Competition 2014 and beyond\", International Journal of Forecasting, vol.32, no.3, стр. 896-913, юли-септември, 2016.\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pip install statsmodels"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,705 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "fv9OoQsMFk5A"
},
"source": [
"# Прогнозиране на времеви редове с помощта на регресор с опорни вектори\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В този тефтер ще демонстрираме как да:\n",
"\n",
"- подготвим двумерни времеви редове за обучение на SVM регресионен модел\n",
"- реализираме SVR с помощта на RBF ядро\n",
"- оценим модела чрез графики и MAPE\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Импортиране на модули\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"sys.path.append('../../')"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "M687KNlQFp0-"
},
"outputs": [],
"source": [
"import os\n",
"import warnings\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"import datetime as dt\n",
"import math\n",
"\n",
"from sklearn.svm import SVR\n",
"from sklearn.preprocessing import MinMaxScaler\n",
"from common.utils import load_data, mape"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Cj-kfVdMGjWP"
},
"source": [
"## Подготовка на данни\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8fywSjC6GsRz"
},
"source": [
"### Зареди данни\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 363
},
"id": "aBDkEB11Fumg",
"outputId": "99cf7987-0509-4b73-8cc2-75d7da0d2740"
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>load</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2012-01-01 00:00:00</th>\n",
" <td>2698.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 01:00:00</th>\n",
" <td>2558.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 02:00:00</th>\n",
" <td>2444.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 03:00:00</th>\n",
" <td>2402.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 04:00:00</th>\n",
" <td>2403.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" load\n",
"2012-01-01 00:00:00 2698.0\n",
"2012-01-01 01:00:00 2558.0\n",
"2012-01-01 02:00:00 2444.0\n",
"2012-01-01 03:00:00 2402.0\n",
"2012-01-01 04:00:00 2403.0"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"energy = load_data('../../data')[['load']]\n",
"energy.head(5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "O0BWP13rGnh4"
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 486
},
"id": "hGaNPKu_Gidk",
"outputId": "7f89b326-9057-4f49-efbe-cb100ebdf76d"
},
"outputs": [],
"source": [
"energy.plot(y='load', subplots=True, figsize=(15, 8), fontsize=12)\n",
"plt.xlabel('timestamp', fontsize=12)\n",
"plt.ylabel('load', fontsize=12)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "IPuNor4eGwYY"
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ysvsNyONGt0Q"
},
"outputs": [],
"source": [
"train_start_dt = '2014-11-01 00:00:00'\n",
"test_start_dt = '2014-12-30 00:00:00'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 548
},
"id": "SsfdLoPyGy9w",
"outputId": "d6d6c25b-b1f4-47e5-91d1-707e043237d7"
},
"outputs": [],
"source": [
"energy[(energy.index < test_start_dt) & (energy.index >= train_start_dt)][['load']].rename(columns={'load':'train'}) \\\n",
" .join(energy[test_start_dt:][['load']].rename(columns={'load':'test'}), how='outer') \\\n",
" .plot(y=['train', 'test'], figsize=(15, 8), fontsize=12)\n",
"plt.xlabel('timestamp', fontsize=12)\n",
"plt.ylabel('load', fontsize=12)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XbFTqBw6G1Ch"
},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сега трябва да подготвите данните за обучение, като извършите филтриране и мащабиране на данните си.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "cYivRdQpHDj3",
"outputId": "a138f746-461c-4fd6-bfa6-0cee094c4aa1"
},
"outputs": [],
"source": [
"train = energy.copy()[(energy.index >= train_start_dt) & (energy.index < test_start_dt)][['load']]\n",
"test = energy.copy()[energy.index >= test_start_dt][['load']]\n",
"\n",
"print('Training data shape: ', train.shape)\n",
"print('Test data shape: ', test.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Мащабирайте данните, за да бъдат в диапазона (0, 1).\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 363
},
"id": "3DNntGQnZX8G",
"outputId": "210046bc-7a66-4ccd-d70d-aa4a7309949c"
},
"outputs": [],
"source": [
"scaler = MinMaxScaler()\n",
"train['load'] = scaler.fit_transform(train)\n",
"train.head(5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 206
},
"id": "26Yht-rzZexe",
"outputId": "20326077-a38a-4e78-cc5b-6fd7af95d301"
},
"outputs": [],
"source": [
"test['load'] = scaler.transform(test)\n",
"test.head(5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "x0n6jqxOQ41Z"
},
"source": [
"### Създаване на данни с времеви стъпки\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "fdmxTZtOQ8xs"
},
"source": [
"За нашия SVR преобразуваме входните данни във формата `[batch, timesteps]`. Затова променяме формата на съществуващите `train_data` и `test_data`, така че да има ново измерение, което се отнася до времевите стъпки. В нашия пример вземаме `timesteps = 5`. Така че входовете към модела са данните за първите 4 времеви стъпки, а изходът ще бъдат данните за 5-тата времева стъпка.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Rpju-Sc2HFm0"
},
"outputs": [],
"source": [
"# Converting to numpy arrays\n",
"\n",
"train_data = train.values\n",
"test_data = test.values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Selecting the timesteps\n",
"\n",
"timesteps=None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "O-JrsrsVJhUQ",
"outputId": "c90dbe71-bacc-4ec4-b452-f82fe5aefaef"
},
"outputs": [],
"source": [
"# Converting data to 2D tensor\n",
"\n",
"train_data_timesteps=None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "exJD8AI7KE4g",
"outputId": "ce90260c-f327-427d-80f2-77307b5a6318"
},
"outputs": [],
"source": [
"# Converting test data to 2D tensor\n",
"\n",
"test_data_timesteps=None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2u0R2sIsLuq5"
},
"outputs": [],
"source": [
"x_train, y_train = None\n",
"x_test, y_test = None\n",
"\n",
"print(x_train.shape, y_train.shape)\n",
"print(x_test.shape, y_test.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8wIPOtAGLZlh"
},
"source": [
"## Създаване на SVR модел\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "EhA403BEPEiD"
},
"outputs": [],
"source": [
"# Create model using RBF kernel\n",
"\n",
"model = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "GS0UA3csMbqp",
"outputId": "d86b6f05-5742-4c1d-c2db-c40510bd4f0d"
},
"outputs": [],
"source": [
"# Fit model on training data"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Rz_x8S3UrlcF"
},
"source": [
"### Направете прогноза на модела\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "XR0gnt3MnuYS",
"outputId": "157e40ab-9a23-4b66-a885-0d52a24b2364"
},
"outputs": [],
"source": [
"# Making predictions\n",
"\n",
"y_train_pred = None\n",
"y_test_pred = None"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_2epncg-SGzr"
},
"source": [
"## Анализиране на производителността на модела\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Scaling the predictions\n",
"\n",
"y_train_pred = scaler.inverse_transform(y_train_pred)\n",
"y_test_pred = scaler.inverse_transform(y_test_pred)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "xmm_YLXhq7gV",
"outputId": "18392f64-4029-49ac-c71a-a4e2411152a1"
},
"outputs": [],
"source": [
"# Scaling the original values\n",
"\n",
"y_train = scaler.inverse_transform(y_train)\n",
"y_test = scaler.inverse_transform(y_test)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "u3LBj93coHEi",
"outputId": "d4fd49e8-8c6e-4bb0-8ef9-ca0b26d725b4"
},
"outputs": [],
"source": [
"# Extract the timesteps for x-axis\n",
"\n",
"train_timestamps = None\n",
"test_timestamps = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(25,6))\n",
"# plot original output\n",
"# plot predicted output\n",
"plt.legend(['Actual','Predicted'])\n",
"plt.xlabel('Timestamp')\n",
"plt.title(\"Training data prediction\")\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "LnhzcnYtXHCm",
"outputId": "f5f0d711-f18b-4788-ad21-d4470ea2c02b"
},
"outputs": [],
"source": [
"print('MAPE for training data: ', mape(y_train_pred, y_train)*100, '%')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 225
},
"id": "53Q02FoqQH4V",
"outputId": "53e2d59b-5075-4765-ad9e-aed56c966583"
},
"outputs": [],
"source": [
"plt.figure(figsize=(10,3))\n",
"# plot original output\n",
"# plot predicted output\n",
"plt.legend(['Actual','Predicted'])\n",
"plt.xlabel('Timestamp')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "clOAUH-SXCJG",
"outputId": "a3aa85ff-126a-4a4a-cd9e-90b9cc465ef5"
},
"outputs": [],
"source": [
"print('MAPE for testing data: ', mape(y_test_pred, y_test)*100, '%')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "DHlKvVCId5ue"
},
"source": [
"## Прогноза за пълния набор от данни\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "cOFJ45vreO0N",
"outputId": "35628e33-ecf9-4966-8036-f7ea86db6f16"
},
"outputs": [],
"source": [
"# Extracting load values as numpy array\n",
"data = None\n",
"\n",
"# Scaling\n",
"data = None\n",
"\n",
"# Transforming to 2D tensor as per model input requirement\n",
"data_timesteps=None\n",
"\n",
"# Selecting inputs and outputs from data\n",
"X, Y = None, None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ESSAdQgwexIi"
},
"outputs": [],
"source": [
"# Make model predictions\n",
"\n",
"# Inverse scale and reshape\n",
"Y_pred = None\n",
"Y = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 328
},
"id": "M_qhihN0RVVX",
"outputId": "a89cb23e-1d35-437f-9d63-8b8907e12f80"
},
"outputs": [],
"source": [
"plt.figure(figsize=(30,8))\n",
"# plot original output\n",
"# plot predicted output\n",
"plt.legend(['Actual','Predicted'])\n",
"plt.xlabel('Timestamp')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "AcN7pMYXVGTK",
"outputId": "7e1c2161-47ce-496c-9d86-7ad9ae0df770"
},
"outputs": [],
"source": [
"print('MAPE: ', mape(Y_pred, Y)*100, '%')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\n"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"collapsed_sections": [],
"name": "Recurrent_Neural_Networks.ipynb",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.1"
},
"coopTranslator": {
"original_hash": "e86ce102239a14c44585623b9b924a74",
"translation_date": "2025-09-04T07:38:36+00:00",
"source_file": "7-TimeSeries/3-SVR/working/notebook.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

@ -0,0 +1,450 @@
{
"nbformat": 4,
"nbformat_minor": 2,
"metadata": {
"colab": {
"name": "lesson_1-R.ipynb",
"provenance": [],
"collapsed_sections": [],
"toc_visible": true
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "c18d3bd0bd8ae3878597e89dcd1fa5c1",
"translation_date": "2025-09-04T07:03:52+00:00",
"source_file": "2-Regression/1-Tools/solution/R/lesson_1-R.ipynb",
"language_code": "cs"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "YJUHCXqK57yz"
}
},
{
"cell_type": "markdown",
"source": [
"## Úvod do regrese - Lekce 1\n",
"\n",
"#### Uvedení do kontextu\n",
"\n",
"✅ Existuje mnoho typů regresních metod a výběr té správné závisí na tom, jakou odpověď hledáte. Pokud chcete předpovědět pravděpodobnou výšku osoby určitého věku, použijete `lineární regresi`, protože hledáte **číselnou hodnotu**. Pokud vás zajímá, zda by určitý typ kuchyně měl být považován za veganský nebo ne, hledáte **přiřazení kategorie**, a proto byste použili `logistickou regresi`. O logistické regresi se dozvíte více později. Zamyslete se nad některými otázkami, které byste mohli klást datům, a nad tím, která z těchto metod by byla vhodnější.\n",
"\n",
"V této části budete pracovat s [malou datovou sadou o cukrovce](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html). Představte si, že byste chtěli otestovat léčbu pro pacienty s cukrovkou. Modely strojového učení by vám mohly pomoci určit, kteří pacienti by na léčbu reagovali lépe, na základě kombinací proměnných. I velmi základní regresní model, pokud je vizualizován, by mohl ukázat informace o proměnných, které by vám pomohly uspořádat vaše teoretické klinické studie.\n",
"\n",
"Tak tedy, pojďme se pustit do tohoto úkolu!\n",
"\n",
"<p >\n",
" <img src=\"../../images/encouRage.jpg\"\n",
" width=\"630\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n",
"\n",
"<!--![Ilustrace od \\@allison_horst](../../../../../../2-Regression/1-Tools/images/encouRage.jpg)<br>Ilustrace od @allison_horst-->\n"
],
"metadata": {
"id": "LWNNzfqd6feZ"
}
},
{
"cell_type": "markdown",
"source": [
"## 1. Načtení našeho nástrojového setu\n",
"\n",
"Pro tento úkol budeme potřebovat následující balíčky:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) je [kolekce balíčků pro R](https://www.tidyverse.org/packages), která je navržena tak, aby byla práce s daty rychlejší, jednodušší a zábavnější!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) je [kolekce balíčků](https://www.tidymodels.org/packages/) určená pro modelování a strojové učení.\n",
"\n",
"Můžete je nainstalovat pomocí:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\"))`\n",
"\n",
"Níže uvedený skript zkontroluje, zda máte balíčky potřebné k dokončení tohoto modulu, a v případě, že některé chybí, je pro vás nainstaluje.\n"
],
"metadata": {
"id": "FIo2YhO26wI9"
}
},
{
"cell_type": "code",
"execution_count": 2,
"source": [
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n",
"pacman::p_load(tidyverse, tidymodels)"
],
"outputs": [
{
"output_type": "stream",
"name": "stderr",
"text": [
"Loading required package: pacman\n",
"\n"
]
}
],
"metadata": {
"id": "cIA9fz9v7Dss",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "2df7073b-86b2-4b32-cb86-0da605a0dc11"
}
},
{
"cell_type": "markdown",
"source": [
"Nyní načtěme tyto skvělé balíčky a zpřístupněme je v naší aktuální relaci R. (Toto je pouze pro ilustraci, `pacman::p_load()` to již udělal za vás)\n"
],
"metadata": {
"id": "gpO_P_6f9WUG"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# load the core Tidyverse packages\r\n",
"library(tidyverse)\r\n",
"\r\n",
"# load the core Tidymodels packages\r\n",
"library(tidymodels)\r\n"
],
"outputs": [],
"metadata": {
"id": "NLMycgG-9ezO"
}
},
{
"cell_type": "markdown",
"source": [
"## 2. Datová sada o cukrovce\n",
"\n",
"V tomto cvičení si procvičíme naše dovednosti v regresi tím, že budeme provádět predikce na datové sadě o cukrovce. [Datová sada o cukrovce](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.rwrite1.txt) obsahuje `442 vzorků` dat týkajících se cukrovky, s 10 prediktivními proměnnými, jako jsou `věk`, `pohlaví`, `index tělesné hmotnosti`, `průměrný krevní tlak` a `šest měření krevního séra`, a také výstupní proměnnou `y`: kvantitativní míru progrese onemocnění jeden rok po výchozím stavu.\n",
"\n",
"|Počet pozorování|442|\n",
"|----------------|:---|\n",
"|Počet prediktorů|Prvních 10 sloupců jsou číselné prediktivní proměnné|\n",
"|Výstup/Cíl|Sloupec 11 je kvantitativní míra progrese onemocnění jeden rok po výchozím stavu|\n",
"|Informace o prediktorech|- věk v letech\n",
"||- pohlaví\n",
"||- bmi index tělesné hmotnosti\n",
"||- bp průměrný krevní tlak\n",
"||- s1 tc, celkový cholesterol v séru\n",
"||- s2 ldl, lipoproteiny s nízkou hustotou\n",
"||- s3 hdl, lipoproteiny s vysokou hustotou\n",
"||- s4 tch, poměr celkového cholesterolu k HDL\n",
"||- s5 ltg, pravděpodobně logaritmus hladiny triglyceridů v séru\n",
"||- s6 glu, hladina cukru v krvi|\n",
"\n",
"\n",
"\n",
"\n",
"> 🎓 Pamatujte, že se jedná o učení s učitelem (supervised learning), a potřebujeme cílovou proměnnou 'y'.\n",
"\n",
"Než budete moci manipulovat s daty v R, musíte data načíst do paměti R nebo vytvořit připojení k datům, které R umožní přístup k datům vzdáleně.\n",
"\n",
"> Balíček [readr](https://readr.tidyverse.org/), který je součástí Tidyverse, poskytuje rychlý a uživatelsky přívětivý způsob, jak načíst obdélníková data do R.\n",
"\n",
"Nyní načtěme datovou sadu o cukrovce z tohoto zdrojového URL: <https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html>\n",
"\n",
"Také provedeme kontrolu našich dat pomocí funkce `glimpse()` a zobrazíme prvních 5 řádků pomocí funkce `slice()`.\n",
"\n",
"Než budeme pokračovat, představme si ještě něco, s čím se v kódu R často setkáte 🥁🥁: operátor pipe `%>%`\n",
"\n",
"Operátor pipe (`%>%`) provádí operace v logickém sledu tím, že předává objekt dál do funkce nebo výrazu. Můžete si operátor pipe představit jako výraz \"a pak\" ve vašem kódu.\n"
],
"metadata": {
"id": "KM6iXLH996Cl"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Import the data set\r\n",
"diabetes <- read_table2(file = \"https://www4.stat.ncsu.edu/~boos/var.select/diabetes.rwrite1.txt\")\r\n",
"\r\n",
"\r\n",
"# Get a glimpse and dimensions of the data\r\n",
"glimpse(diabetes)\r\n",
"\r\n",
"\r\n",
"# Select the first 5 rows of the data\r\n",
"diabetes %>% \r\n",
" slice(1:5)"
],
"outputs": [],
"metadata": {
"id": "Z1geAMhM-bSP"
}
},
{
"cell_type": "markdown",
"source": [
"`glimpse()` nám ukazuje, že tato data obsahují 442 řádků a 11 sloupců, přičemž všechny sloupce mají datový typ `double`.\n",
"\n",
"<br>\n",
"\n",
"> glimpse() a slice() jsou funkce v [`dplyr`](https://dplyr.tidyverse.org/). Dplyr, součást Tidyverse, je gramatika pro manipulaci s daty, která poskytuje konzistentní sadu sloves, jež vám pomohou vyřešit nejběžnější výzvy při práci s daty.\n",
"\n",
"<br>\n",
"\n",
"Teď, když máme data, zaměříme se na jednu vlastnost (`bmi`) jako cíl tohoto cvičení. To bude vyžadovat, abychom vybrali požadované sloupce. Jak to uděláme?\n",
"\n",
"[`dplyr::select()`](https://dplyr.tidyverse.org/reference/select.html) nám umožňuje *vybrat* (a případně přejmenovat) sloupce v datovém rámci.\n"
],
"metadata": {
"id": "UwjVT1Hz-c3Z"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Select predictor feature `bmi` and outcome `y`\r\n",
"diabetes_select <- diabetes %>% \r\n",
" select(c(bmi, y))\r\n",
"\r\n",
"# Print the first 5 rows\r\n",
"diabetes_select %>% \r\n",
" slice(1:10)"
],
"outputs": [],
"metadata": {
"id": "RDY1oAKI-m80"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Trénovací a testovací data\n",
"\n",
"V řízeném učení je běžnou praxí *rozdělit* data na dvě podmnožiny; (obvykle větší) sadu, která slouží k trénování modelu, a menší „záložní“ sadu, která slouží k ověření, jak si model vedl.\n",
"\n",
"Nyní, když máme data připravena, můžeme zjistit, zda nám stroj dokáže pomoci určit logické rozdělení čísel v tomto datasetu. Můžeme použít balíček [rsample](https://tidymodels.github.io/rsample/), který je součástí frameworku Tidymodels, k vytvoření objektu, který obsahuje informace o *tom*, jak data rozdělit, a poté dvě další funkce rsample k extrakci vytvořených trénovacích a testovacích sad:\n"
],
"metadata": {
"id": "SDk668xK-tc3"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"set.seed(2056)\r\n",
"# Split 67% of the data for training and the rest for tesing\r\n",
"diabetes_split <- diabetes_select %>% \r\n",
" initial_split(prop = 0.67)\r\n",
"\r\n",
"# Extract the resulting train and test sets\r\n",
"diabetes_train <- training(diabetes_split)\r\n",
"diabetes_test <- testing(diabetes_split)\r\n",
"\r\n",
"# Print the first 3 rows of the training set\r\n",
"diabetes_train %>% \r\n",
" slice(1:10)"
],
"outputs": [],
"metadata": {
"id": "EqtHx129-1h-"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. Trénování lineárního regresního modelu pomocí Tidymodels\n",
"\n",
"Teď jsme připraveni trénovat náš model!\n",
"\n",
"V Tidymodels specifikujete modely pomocí `parsnip()` tím, že určíte tři koncepty:\n",
"\n",
"- **Typ modelu** rozlišuje mezi modely, jako je lineární regrese, logistická regrese, modely rozhodovacích stromů a podobně.\n",
"\n",
"- **Režim modelu** zahrnuje běžné možnosti, jako je regrese a klasifikace; některé typy modelů podporují obě možnosti, zatímco jiné mají pouze jeden režim.\n",
"\n",
"- **Engine modelu** je výpočetní nástroj, který bude použit k nastavení modelu. Často se jedná o balíčky v R, jako například **`\"lm\"`** nebo **`\"ranger\"`**.\n",
"\n",
"Tyto informace o modelování jsou zachyceny ve specifikaci modelu, tak si jednu vytvořme!\n"
],
"metadata": {
"id": "sBOS-XhB-6v7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Build a linear model specification\r\n",
"lm_spec <- \r\n",
" # Type\r\n",
" linear_reg() %>% \r\n",
" # Engine\r\n",
" set_engine(\"lm\") %>% \r\n",
" # Mode\r\n",
" set_mode(\"regression\")\r\n",
"\r\n",
"\r\n",
"# Print the model specification\r\n",
"lm_spec"
],
"outputs": [],
"metadata": {
"id": "20OwEw20--t3"
}
},
{
"cell_type": "markdown",
"source": [
"Poté, co byl model *specifikován*, může být model `odhadnut` nebo `natrénován` pomocí funkce [`fit()`](https://parsnip.tidymodels.org/reference/fit.html), obvykle za použití vzorce a nějakých dat.\n",
"\n",
"`y ~ .` znamená, že budeme přizpůsobovat `y` jako předpovídanou hodnotu/cíl, vysvětlenou všemi prediktory/vlastnostmi, tj. `.` (v tomto případě máme pouze jeden prediktor: `bmi`).\n"
],
"metadata": {
"id": "_oDHs89k_CJj"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Build a linear model specification\r\n",
"lm_spec <- linear_reg() %>% \r\n",
" set_engine(\"lm\") %>%\r\n",
" set_mode(\"regression\")\r\n",
"\r\n",
"\r\n",
"# Train a linear regression model\r\n",
"lm_mod <- lm_spec %>% \r\n",
" fit(y ~ ., data = diabetes_train)\r\n",
"\r\n",
"# Print the model\r\n",
"lm_mod"
],
"outputs": [],
"metadata": {
"id": "YlsHqd-q_GJQ"
}
},
{
"cell_type": "markdown",
"source": [
"Z výstupu modelu můžeme vidět koeficienty naučené během trénování. Tyto koeficienty představují parametry přímky nejlepšího přizpůsobení, která nám poskytuje nejnižší celkovou chybu mezi skutečnou a předpovězenou proměnnou.\n",
"<br>\n",
"\n",
"## 5. Vytvoření předpovědí na testovací sadě\n",
"\n",
"Nyní, když jsme model natrénovali, můžeme jej použít k předpovědi vývoje onemocnění y pro testovací dataset pomocí [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). To bude použito k vykreslení čáry mezi skupinami dat.\n"
],
"metadata": {
"id": "kGZ22RQj_Olu"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make predictions for the test set\r\n",
"predictions <- lm_mod %>% \r\n",
" predict(new_data = diabetes_test)\r\n",
"\r\n",
"# Print out some of the predictions\r\n",
"predictions %>% \r\n",
" slice(1:5)"
],
"outputs": [],
"metadata": {
"id": "nXHbY7M2_aao"
}
},
{
"cell_type": "markdown",
"source": [
"Hurá! 💃🕺 Právě jsme natrénovali model a použili ho k vytvoření předpovědí!\n",
"\n",
"Při vytváření předpovědí je konvencí v tidymodels vždy vytvořit tibble/datový rámec s výsledky, který má standardizované názvy sloupců. To usnadňuje kombinaci původních dat a předpovědí do použitelného formátu pro následné operace, jako je například vytváření grafů.\n",
"\n",
"`dplyr::bind_cols()` efektivně spojuje více datových rámců podle sloupců.\n"
],
"metadata": {
"id": "R_JstwUY_bIs"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Combine the predictions and the original test set\r\n",
"results <- diabetes_test %>% \r\n",
" bind_cols(predictions)\r\n",
"\r\n",
"\r\n",
"results %>% \r\n",
" slice(1:5)"
],
"outputs": [],
"metadata": {
"id": "RybsMJR7_iI8"
}
},
{
"cell_type": "markdown",
"source": [
"## 6. Zobrazení výsledků modelování\n",
"\n",
"Teď je čas podívat se na to vizuálně 📈. Vytvoříme bodový graf všech hodnot `y` a `bmi` z testovací sady a poté použijeme predikce k nakreslení čáry na nejvhodnějším místě mezi skupinami dat modelu.\n",
"\n",
"R má několik systémů pro vytváření grafů, ale `ggplot2` je jedním z nejpůsobivějších a nejvšestrannějších. Umožňuje vám skládat grafy **kombinováním nezávislých komponent**.\n"
],
"metadata": {
"id": "XJbYbMZW_n_s"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Set a theme for the plot\r\n",
"theme_set(theme_light())\r\n",
"# Create a scatter plot\r\n",
"results %>% \r\n",
" ggplot(aes(x = bmi)) +\r\n",
" # Add a scatter plot\r\n",
" geom_point(aes(y = y), size = 1.6) +\r\n",
" # Add a line plot\r\n",
" geom_line(aes(y = .pred), color = \"blue\", size = 1.5)"
],
"outputs": [],
"metadata": {
"id": "R9tYp3VW_sTn"
}
},
{
"cell_type": "markdown",
"source": [
"✅ Zamyslete se nad tím, co se zde děje. Přímka prochází mnoha malými body dat, ale co přesně dělá? Vidíte, jak byste měli být schopni použít tuto přímku k předpovědi, kam by měl nový, neviděný datový bod zapadnout ve vztahu k ose y grafu? Zkuste slovy popsat praktické využití tohoto modelu.\n",
"\n",
"Gratulujeme, vytvořili jste svůj první model lineární regrese, provedli předpověď a zobrazili ji v grafu!\n"
],
"metadata": {
"id": "zrPtHIxx_tNI"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). Ačkoli se snažíme o přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace se doporučuje profesionální lidský překlad. Nenese odpovědnost za žádné nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,46 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3-final"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python3",
"display_name": "Python 3",
"language": "python"
},
"coopTranslator": {
"original_hash": "1b2ab303ac6c604a34c6ca7a49077fc7",
"translation_date": "2025-09-04T07:10:47+00:00",
"source_file": "2-Regression/2-Data/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,673 @@
{
"nbformat": 4,
"nbformat_minor": 2,
"metadata": {
"colab": {
"name": "lesson_2-R.ipynb",
"provenance": [],
"collapsed_sections": [],
"toc_visible": true
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "f3c335f9940cfd76528b3ef918b9b342",
"translation_date": "2025-09-04T07:14:33+00:00",
"source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb",
"language_code": "cs"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [
"# Vytvoření regresního modelu: příprava a vizualizace dat\n",
"\n",
"## **Lineární regrese pro dýně - Lekce 2**\n",
"#### Úvod\n",
"\n",
"Nyní, když máte k dispozici nástroje potřebné k zahájení budování modelů strojového učení pomocí Tidymodels a Tidyverse, jste připraveni začít klást otázky svým datům. Při práci s daty a aplikaci řešení strojového učení je velmi důležité vědět, jak položit správnou otázku, abyste mohli plně využít potenciál svého datasetu.\n",
"\n",
"V této lekci se naučíte:\n",
"\n",
"- Jak připravit data pro budování modelu.\n",
"\n",
"- Jak používat `ggplot2` pro vizualizaci dat.\n",
"\n",
"Otázka, na kterou potřebujete odpověď, určí, jaký typ algoritmů strojového učení budete používat. Kvalita odpovědi, kterou získáte, bude silně záviset na povaze vašich dat.\n",
"\n",
"Podívejme se na to prostřednictvím praktického cvičení.\n",
"\n",
"\n",
"<p >\n",
" <img src=\"../../images/unruly_data.jpg\"\n",
" width=\"700\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n",
"\n",
"\n",
"<!--![Ilustrace od \\@allison_horst](../../../../../../2-Regression/2-Data/images/unruly_data.jpg)<br>Ilustrace od \\@allison_horst-->\n"
],
"metadata": {
"id": "Pg5aexcOPqAZ"
}
},
{
"cell_type": "markdown",
"source": [
"## 1. Importování dat o dýních a přivolání Tidyverse\n",
"\n",
"Budeme potřebovat následující balíčky, abychom mohli rozdělit a zpracovat tuto lekci:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) je [sbírka balíčků pro R](https://www.tidyverse.org/packages), která je navržena tak, aby byla datová věda rychlejší, jednodušší a zábavnější!\n",
"\n",
"Můžete je nainstalovat pomocí:\n",
"\n",
"`install.packages(c(\"tidyverse\"))`\n",
"\n",
"Níže uvedený skript zkontroluje, zda máte balíčky potřebné k dokončení tohoto modulu, a v případě, že některé chybí, je pro vás nainstaluje.\n"
],
"metadata": {
"id": "dc5WhyVdXAjR"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n",
"pacman::p_load(tidyverse)"
],
"outputs": [],
"metadata": {
"id": "GqPYUZgfXOBt"
}
},
{
"cell_type": "markdown",
"source": [
"Nyní spusťme některé balíčky a načtěme [data](https://github.com/microsoft/ML-For-Beginners/blob/main/2-Regression/data/US-pumpkins.csv) poskytnutá pro tuto lekci!\n"
],
"metadata": {
"id": "kvjDTPDSXRr2"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load the core Tidyverse packages\n",
"library(tidyverse)\n",
"\n",
"# Import the pumpkins data\n",
"pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\")\n",
"\n",
"\n",
"# Get a glimpse and dimensions of the data\n",
"glimpse(pumpkins)\n",
"\n",
"\n",
"# Print the first 50 rows of the data set\n",
"pumpkins %>% \n",
" slice_head(n =50)"
],
"outputs": [],
"metadata": {
"id": "VMri-t2zXqgD"
}
},
{
"cell_type": "markdown",
"source": [
"Rychlý `glimpse()` okamžitě ukazuje, že jsou zde prázdné hodnoty a směs řetězců (`chr`) a číselných dat (`dbl`). `Date` je typu znakového řetězce a je tu také zvláštní sloupec nazvaný `Package`, kde jsou data směsí mezi `sacks`, `bins` a dalšími hodnotami. Data jsou vlastně trochu chaotická 😤.\n",
"\n",
"Ve skutečnosti není příliš běžné dostat dataset, který je zcela připravený k použití pro vytvoření ML modelu hned na první pokus. Ale nezoufejte, v této lekci se naučíte, jak připravit surový dataset pomocí standardních knihoven v R 🧑‍🔧. Také se naučíte různé techniky vizualizace dat.📈📊\n",
"<br>\n",
"\n",
"> Připomenutí: Operátor pipe (`%>%`) provádí operace v logickém sledu tím, že předává objekt dál do funkce nebo výrazu. Můžete si operátor pipe představit jako \"a potom\" ve vašem kódu.\n"
],
"metadata": {
"id": "REWcIv9yX29v"
}
},
{
"cell_type": "markdown",
"source": [
"## 2. Kontrola chybějících dat\n",
"\n",
"Jedním z nejčastějších problémů, se kterými se datoví vědci musí vypořádat, jsou neúplná nebo chybějící data. R reprezentuje chybějící nebo neznámé hodnoty pomocí speciálního sentinelového hodnoty: `NA` (Not Available).\n",
"\n",
"Jak tedy zjistíme, že datový rámec obsahuje chybějící hodnoty?\n",
"<br>\n",
"- Jedním z nejjednodušších způsobů je použití základní funkce R `anyNA`, která vrací logické objekty `TRUE` nebo `FALSE`.\n"
],
"metadata": {
"id": "Zxfb3AM5YbUe"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" anyNA()"
],
"outputs": [],
"metadata": {
"id": "G--DQutAYltj"
}
},
{
"cell_type": "markdown",
"source": [
"Skvělé, zdá se, že některá data chybí! To je dobré místo, kde začít.\n",
"\n",
"- Dalším způsobem by bylo použít funkci `is.na()`, která označuje, které jednotlivé prvky sloupce chybí pomocí logické hodnoty `TRUE`.\n"
],
"metadata": {
"id": "mU-7-SB6YokF"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" is.na() %>% \n",
" head(n = 7)"
],
"outputs": [],
"metadata": {
"id": "W-DxDOR4YxSW"
}
},
{
"cell_type": "markdown",
"source": [
"Dobře, hotovo, ale s tak velkým datovým rámcem, jako je tento, by bylo neefektivní a prakticky nemožné zkontrolovat všechny řádky a sloupce jednotlivě😴.\n",
"\n",
"- Intuitivnější způsob by byl spočítat součet chybějících hodnot pro každý sloupec:\n"
],
"metadata": {
"id": "xUWxipKYY0o7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" is.na() %>% \n",
" colSums()"
],
"outputs": [],
"metadata": {
"id": "ZRBWV6P9ZArL"
}
},
{
"cell_type": "markdown",
"source": [
"Mnohem lepší! Chybí některá data, ale možná to nebude mít vliv na daný úkol. Uvidíme, jaký další rozbor přinese.\n",
"\n",
"> Spolu s úžasnými balíčky a funkcemi má R velmi dobrou dokumentaci. Například použijte `help(colSums)` nebo `?colSums`, abyste se dozvěděli více o této funkci.\n"
],
"metadata": {
"id": "9gv-crB6ZD1Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Dplyr: Gramatika manipulace s daty\n",
"\n",
"<p >\n",
" <img src=\"../../images/dplyr_wrangling.png\"\n",
" width=\"569\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n",
"\n",
"\n",
"<!--![Ilustrace od \\@allison_horst](../../../../../../2-Regression/2-Data/images/dplyr_wrangling.png)<br/>Ilustrace od \\@allison_horst-->\n"
],
"metadata": {
"id": "o4jLY5-VZO2C"
}
},
{
"cell_type": "markdown",
"source": [
"[`dplyr`](https://dplyr.tidyverse.org/), balíček v Tidyverse, je gramatikou manipulace s daty, která poskytuje konzistentní sadu sloves, jež vám pomohou vyřešit nejběžnější výzvy při manipulaci s daty. V této části se podíváme na některá slovesa z dplyr! \n",
"<br>\n"
],
"metadata": {
"id": "i5o33MQBZWWw"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::select()\n",
"\n",
"`select()` je funkce z balíčku `dplyr`, která vám pomáhá vybrat sloupce, které chcete zachovat nebo vyloučit.\n",
"\n",
"Abyste si usnadnili práci s datovým rámcem, odstraňte několik jeho sloupců pomocí `select()` a ponechte pouze ty, které potřebujete.\n",
"\n",
"Například v tomto cvičení bude naše analýza zahrnovat sloupce `Package`, `Low Price`, `High Price` a `Date`. Pojďme tyto sloupce vybrat.\n"
],
"metadata": {
"id": "x3VGMAGBZiUr"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Select desired columns\n",
"pumpkins <- pumpkins %>% \n",
" select(Package, `Low Price`, `High Price`, Date)\n",
"\n",
"\n",
"# Print data set\n",
"pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "F_FgxQnVZnM0"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::mutate()\n",
"\n",
"`mutate()` je funkce z balíčku `dplyr`, která vám umožňuje vytvářet nebo upravovat sloupce, přičemž zachovává stávající sloupce.\n",
"\n",
"Obecná struktura funkce mutate je:\n",
"\n",
"`data %>% mutate(new_column_name = what_it_contains)`\n",
"\n",
"Pojďme si vyzkoušet `mutate` na sloupci `Date` provedením následujících operací:\n",
"\n",
"1. Převést data (aktuálně typu znak) na formát měsíce (jedná se o americká data, takže formát je `MM/DD/YYYY`).\n",
"\n",
"2. Extrahovat měsíc z dat do nového sloupce.\n",
"\n",
"V R balíček [lubridate](https://lubridate.tidyverse.org/) usnadňuje práci s daty a časy. Takže použijeme `dplyr::mutate()`, `lubridate::mdy()`, `lubridate::month()` a podíváme se, jak dosáhnout výše uvedených cílů. Sloupec Date můžeme vynechat, protože ho v dalších operacích nebudeme potřebovat.\n"
],
"metadata": {
"id": "2KKo0Ed9Z1VB"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load lubridate\n",
"library(lubridate)\n",
"\n",
"pumpkins <- pumpkins %>% \n",
" # Convert the Date column to a date object\n",
" mutate(Date = mdy(Date)) %>% \n",
" # Extract month from Date\n",
" mutate(Month = month(Date)) %>% \n",
" # Drop Date column\n",
" select(-Date)\n",
"\n",
"# View the first few rows\n",
"pumpkins %>% \n",
" slice_head(n = 7)"
],
"outputs": [],
"metadata": {
"id": "5joszIVSZ6xe"
}
},
{
"cell_type": "markdown",
"source": [
"Hurá! 🤩\n",
"\n",
"Nyní vytvořme nový sloupec `Price`, který bude představovat průměrnou cenu dýně. Vezmeme průměr hodnot ze sloupců `Low Price` a `High Price` a použijeme jej k naplnění nového sloupce Price.\n",
"<br>\n"
],
"metadata": {
"id": "nIgLjNMCZ-6Y"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Create a new column Price\n",
"pumpkins <- pumpkins %>% \n",
" mutate(Price = (`Low Price` + `High Price`)/2)\n",
"\n",
"# View the first few rows of the data\n",
"pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "Zo0BsqqtaJw2"
}
},
{
"cell_type": "markdown",
"source": [
"Yeees!💪\n",
"\n",
"„Ale počkejte!“, řeknete po rychlém prohlédnutí celého datového souboru pomocí `View(pumpkins)`, „Tady je něco zvláštního!“🤔\n",
"\n",
"Pokud se podíváte na sloupec `Package`, dýně se prodávají v mnoha různých konfiguracích. Některé se prodávají v mírách `1 1/9 bushel`, některé v mírách `1/2 bushel`, některé na kus, některé na váhu, a některé ve velkých krabicích s různými šířkami.\n",
"\n",
"Pojďme si to ověřit:\n"
],
"metadata": {
"id": "p77WZr-9aQAR"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Verify the distinct observations in Package column\n",
"pumpkins %>% \n",
" distinct(Package)"
],
"outputs": [],
"metadata": {
"id": "XISGfh0IaUy6"
}
},
{
"cell_type": "markdown",
"source": [
"Úžasné!👏\n",
"\n",
"Zdá se, že dýně je velmi těžké vážit konzistentně, takže je vyfiltrujeme tím, že vybereme pouze dýně, které obsahují řetězec *bushel* ve sloupci `Package`, a uložíme je do nového datového rámce `new_pumpkins`.\n"
],
"metadata": {
"id": "7sMjiVujaZxY"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::filter() a stringr::str_detect()\n",
"\n",
"[`dplyr::filter()`](https://dplyr.tidyverse.org/reference/filter.html): vytváří podmnožinu dat obsahující pouze **řádky**, které splňují vaše podmínky, v tomto případě dýně s řetězcem *bushel* ve sloupci `Package`.\n",
"\n",
"[stringr::str_detect()](https://stringr.tidyverse.org/reference/str_detect.html): zjišťuje přítomnost nebo nepřítomnost vzoru v řetězci.\n",
"\n",
"Balíček [`stringr`](https://github.com/tidyverse/stringr) poskytuje jednoduché funkce pro běžné operace s řetězci.\n"
],
"metadata": {
"id": "L8Qfcs92ageF"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Retain only pumpkins with \"bushel\"\n",
"new_pumpkins <- pumpkins %>% \n",
" filter(str_detect(Package, \"bushel\"))\n",
"\n",
"# Get the dimensions of the new data\n",
"dim(new_pumpkins)\n",
"\n",
"# View a few rows of the new data\n",
"new_pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "hy_SGYREampd"
}
},
{
"cell_type": "markdown",
"source": [
"Můžete vidět, že jsme zúžili výběr na přibližně 415 řádků dat obsahujících dýně po bušlech.🤩 \n",
"<br>\n"
],
"metadata": {
"id": "VrDwF031avlR"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::case_when()\n",
"\n",
"**Ale počkejte! Ještě je třeba něco udělat**\n",
"\n",
"Všimli jste si, že množství v bušlech se liší podle řádku? Je potřeba normalizovat ceny tak, aby ukazovaly cenu za bušel, a ne za 1 1/9 nebo 1/2 bušle. Je čas provést nějaké výpočty, abychom to standardizovali.\n",
"\n",
"Použijeme funkci [`case_when()`](https://dplyr.tidyverse.org/reference/case_when.html) k *úpravě* sloupce Price na základě určitých podmínek. `case_when` umožňuje vektorizovat více `if_else()` výroků.\n"
],
"metadata": {
"id": "mLpw2jH4a0tx"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Convert the price if the Package contains fractional bushel values\n",
"new_pumpkins <- new_pumpkins %>% \n",
" mutate(Price = case_when(\n",
" str_detect(Package, \"1 1/9\") ~ Price/(1 + 1/9),\n",
" str_detect(Package, \"1/2\") ~ Price/(1/2),\n",
" TRUE ~ Price))\n",
"\n",
"# View the first few rows of the data\n",
"new_pumpkins %>% \n",
" slice_head(n = 30)"
],
"outputs": [],
"metadata": {
"id": "P68kLVQmbM6I"
}
},
{
"cell_type": "markdown",
"source": [
"Nyní můžeme analyzovat cenu za jednotku na základě jejich měření v bušlech. Celá tato studie bušlů dýní však ukazuje, jak velmi `důležité` je `pochopit povahu vašich dat`!\n",
"\n",
"> ✅ Podle [The Spruce Eats](https://www.thespruceeats.com/how-much-is-a-bushel-1389308) závisí váha bušle na typu produktu, protože jde o objemové měření. \"Bušl rajčat by například měl vážit 56 liber... Listy a zelené rostliny zabírají více prostoru s menší váhou, takže bušl špenátu váží pouze 20 liber.\" Je to všechno docela složité! Nezabývejme se převodem bušlů na libry a místo toho stanovme cenu podle bušle. Celá tato studie bušlů dýní však ukazuje, jak velmi důležité je pochopit povahu vašich dat!\n",
">\n",
"> ✅ Všimli jste si, že dýně prodávané na půl bušle jsou velmi drahé? Dokážete zjistit proč? Nápověda: malé dýně jsou mnohem dražší než velké, pravděpodobně proto, že jich je mnohem více na bušl, vzhledem k nevyužitému prostoru, který zabírá jedna velká dutá dýně na koláč.\n"
],
"metadata": {
"id": "pS2GNPagbSdb"
}
},
{
"cell_type": "markdown",
"source": [
"Nyní nakonec, čistě pro dobrodružství 💁‍♀️, pojďme také přesunout sloupec Month na první pozici, tj. `před` sloupec `Package`.\n",
"\n",
"Funkce `dplyr::relocate()` se používá ke změně pozic sloupců.\n"
],
"metadata": {
"id": "qql1SowfbdnP"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Create a new data frame new_pumpkins\n",
"new_pumpkins <- new_pumpkins %>% \n",
" relocate(Month, .before = Package)\n",
"\n",
"new_pumpkins %>% \n",
" slice_head(n = 7)"
],
"outputs": [],
"metadata": {
"id": "JJ1x6kw8bixF"
}
},
{
"cell_type": "markdown",
"source": [
"Dobrá práce!👌 Nyní máte čistý a uspořádaný dataset, na kterém můžete postavit svůj nový regresní model! \n",
"<br>\n"
],
"metadata": {
"id": "y8TJ0Za_bn5Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. Vizualizace dat s ggplot2\n",
"\n",
"<p >\n",
" <img src=\"../../images/data-visualization.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Infografika od Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"<!--![Infografika od Dasani Madipalli](../../../../../../2-Regression/2-Data/images/data-visualization.png){width=\"600\"}-->\n",
"\n",
"Existuje *moudré* rčení, které říká:\n",
"\n",
"> \"Jednoduchý graf přinesl analytikovi více informací než jakékoli jiné zařízení.\" --- John Tukey\n",
"\n",
"Součástí role datového vědce je ukázat kvalitu a povahu dat, se kterými pracuje. K tomu často vytváří zajímavé vizualizace, nebo grafy, diagramy a tabulky, které zobrazují různé aspekty dat. Tímto způsobem mohou vizuálně ukázat vztahy a mezery, které by jinak bylo obtížné odhalit.\n",
"\n",
"Vizualizace také mohou pomoci určit, která technika strojového učení je pro daná data nejvhodnější. Například bodový graf, který se zdá sledovat přímku, naznačuje, že data jsou vhodným kandidátem pro úlohu lineární regrese.\n",
"\n",
"R nabízí několik systémů pro tvorbu grafů, ale [`ggplot2`](https://ggplot2.tidyverse.org/index.html) je jedním z nejelegantnějších a nejvšestrannějších. `ggplot2` vám umožňuje skládat grafy **kombinováním nezávislých komponent**.\n",
"\n",
"Začněme jednoduchým bodovým grafem pro sloupce Price a Month.\n",
"\n",
"V tomto případě začneme s [`ggplot()`](https://ggplot2.tidyverse.org/reference/ggplot.html), dodáme dataset a estetické mapování (pomocí [`aes()`](https://ggplot2.tidyverse.org/reference/aes.html)) a poté přidáme vrstvy (jako [`geom_point()`](https://ggplot2.tidyverse.org/reference/geom_point.html)) pro bodové grafy.\n"
],
"metadata": {
"id": "mYSH6-EtbvNa"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Set a theme for the plots\n",
"theme_set(theme_light())\n",
"\n",
"# Create a scatter plot\n",
"p <- ggplot(data = new_pumpkins, aes(x = Price, y = Month))\n",
"p + geom_point()"
],
"outputs": [],
"metadata": {
"id": "g2YjnGeOcLo4"
}
},
{
"cell_type": "markdown",
"source": [
"Je tento graf užitečný 🤷? Překvapilo vás na něm něco?\n",
"\n",
"Není příliš užitečný, protože pouze zobrazuje vaše data jako rozptyl bodů v daném měsíci. \n",
"<br>\n"
],
"metadata": {
"id": "Ml7SDCLQcPvE"
}
},
{
"cell_type": "markdown",
"source": [
"### **Jak to udělat užitečné?**\n",
"\n",
"Aby grafy zobrazovaly užitečná data, obvykle je potřeba data nějakým způsobem seskupit. Například v našem případě by nalezení průměrné ceny dýní za každý měsíc poskytlo více informací o základních vzorcích v našich datech. To nás přivádí k dalšímu rychlému přehledu **dplyr**:\n",
"\n",
"#### `dplyr::group_by() %>% summarize()`\n",
"\n",
"Seskupenou agregaci v R lze snadno vypočítat pomocí\n",
"\n",
"`dplyr::group_by() %>% summarize()`\n",
"\n",
"- `dplyr::group_by()` mění jednotku analýzy z celého datasetu na jednotlivé skupiny, například podle měsíců.\n",
"\n",
"- `dplyr::summarize()` vytváří nový datový rámec s jedním sloupcem pro každou seskupovací proměnnou a jedním sloupcem pro každou zadanou statistiku shrnutí.\n",
"\n",
"Například můžeme použít `dplyr::group_by() %>% summarize()` k seskupení dýní do skupin na základě sloupce **Month** a následně najít **průměrnou cenu** za každý měsíc.\n"
],
"metadata": {
"id": "jMakvJZIcVkh"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Find the average price of pumpkins per month\r\n",
"new_pumpkins %>%\r\n",
" group_by(Month) %>% \r\n",
" summarise(mean_price = mean(Price))"
],
"outputs": [],
"metadata": {
"id": "6kVSUa2Bcilf"
}
},
{
"cell_type": "markdown",
"source": [
"Stručně!✨\n",
"\n",
"Kategorie, jako jsou měsíce, se lépe zobrazují pomocí sloupcového grafu 📊. Vrstvy, které se používají pro sloupcové grafy, jsou `geom_bar()` a `geom_col()`. Podívejte se na `?geom_bar`, abyste zjistili více.\n",
"\n",
"Pojďme si jeden vytvořit!\n"
],
"metadata": {
"id": "Kds48GUBcj3W"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Find the average price of pumpkins per month then plot a bar chart\r\n",
"new_pumpkins %>%\r\n",
" group_by(Month) %>% \r\n",
" summarise(mean_price = mean(Price)) %>% \r\n",
" ggplot(aes(x = Month, y = mean_price)) +\r\n",
" geom_col(fill = \"midnightblue\", alpha = 0.7) +\r\n",
" ylab(\"Pumpkin Price\")"
],
"outputs": [],
"metadata": {
"id": "VNbU1S3BcrxO"
}
},
{
"cell_type": "markdown",
"source": [
"🤩🤩 Toto je užitečnější vizualizace dat! Zdá se, že naznačuje, že nejvyšší cena za dýně se vyskytuje v září a říjnu. Odpovídá to vašemu očekávání? Proč ano nebo proč ne?\n",
"\n",
"Gratulujeme k dokončení druhé lekce 👏! Připravili jste svá data pro tvorbu modelu a poté odhalili další poznatky pomocí vizualizací!\n"
],
"metadata": {
"id": "zDm0VOzzcuzR"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). Ačkoli se snažíme o přesnost, mějte na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádné nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,128 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Ceny dýní\n",
"\n",
"Načtěte potřebné knihovny a dataset. Převést data na dataframe obsahující podmnožinu dat:\n",
"\n",
"- Získat pouze dýně oceněné podle množství na bušl\n",
"- Převést datum na měsíc\n",
"- Vypočítat cenu jako průměr vysokých a nízkých cen\n",
"- Převést cenu tak, aby odrážela ocenění podle množství na bušl\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from datetime import datetime\n",
"\n",
"pumpkins = pd.read_csv('../data/US-pumpkins.csv')\n",
"\n",
"pumpkins.head()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pumpkins = pumpkins[pumpkins['Package'].str.contains('bushel', case=True, regex=True)]\n",
"\n",
"columns_to_select = ['Package', 'Variety', 'City Name', 'Low Price', 'High Price', 'Date']\n",
"pumpkins = pumpkins.loc[:, columns_to_select]\n",
"\n",
"price = (pumpkins['Low Price'] + pumpkins['High Price']) / 2\n",
"\n",
"month = pd.DatetimeIndex(pumpkins['Date']).month\n",
"day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)\n",
"\n",
"new_pumpkins = pd.DataFrame(\n",
" {'Month': month, \n",
" 'DayOfYear' : day_of_year, \n",
" 'Variety': pumpkins['Variety'], \n",
" 'City': pumpkins['City Name'], \n",
" 'Package': pumpkins['Package'], \n",
" 'Low Price': pumpkins['Low Price'],\n",
" 'High Price': pumpkins['High Price'], \n",
" 'Price': price})\n",
"\n",
"new_pumpkins.loc[new_pumpkins['Package'].str.contains('1 1/9'), 'Price'] = price/1.1\n",
"new_pumpkins.loc[new_pumpkins['Package'].str.contains('1/2'), 'Price'] = price*2\n",
"\n",
"new_pumpkins.head()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Základní bodový graf nám připomíná, že máme údaje pouze od srpna do prosince. Pravděpodobně potřebujeme více dat, abychom mohli vyvodit závěry lineárním způsobem.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"plt.scatter('Month','Price',data=new_pumpkins)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"plt.scatter('DayOfYear','Price',data=new_pumpkins)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3-final"
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "b032d371c75279373507f003439a577e",
"translation_date": "2025-09-04T06:17:07+00:00",
"source_file": "2-Regression/3-Linear/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,269 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Druhy dýní a barva\n",
"\n",
"Načtěte potřebné knihovny a dataset. Převést data na dataframe obsahující podmnožinu dat:\n",
"\n",
"Podívejme se na vztah mezi barvou a druhem\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>City Name</th>\n",
" <th>Type</th>\n",
" <th>Package</th>\n",
" <th>Variety</th>\n",
" <th>Sub Variety</th>\n",
" <th>Grade</th>\n",
" <th>Date</th>\n",
" <th>Low Price</th>\n",
" <th>High Price</th>\n",
" <th>Mostly Low</th>\n",
" <th>...</th>\n",
" <th>Unit of Sale</th>\n",
" <th>Quality</th>\n",
" <th>Condition</th>\n",
" <th>Appearance</th>\n",
" <th>Storage</th>\n",
" <th>Crop</th>\n",
" <th>Repack</th>\n",
" <th>Trans Mode</th>\n",
" <th>Unnamed: 24</th>\n",
" <th>Unnamed: 25</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>4/29/17</td>\n",
" <td>270.0</td>\n",
" <td>280.0</td>\n",
" <td>270.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>E</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>5/6/17</td>\n",
" <td>270.0</td>\n",
" <td>280.0</td>\n",
" <td>270.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>E</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>HOWDEN TYPE</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>9/24/16</td>\n",
" <td>160.0</td>\n",
" <td>160.0</td>\n",
" <td>160.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>N</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>HOWDEN TYPE</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>9/24/16</td>\n",
" <td>160.0</td>\n",
" <td>160.0</td>\n",
" <td>160.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>N</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>BALTIMORE</td>\n",
" <td>NaN</td>\n",
" <td>24 inch bins</td>\n",
" <td>HOWDEN TYPE</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>11/5/16</td>\n",
" <td>90.0</td>\n",
" <td>100.0</td>\n",
" <td>90.0</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>N</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 26 columns</p>\n",
"</div>"
],
"text/plain": [
" City Name Type Package Variety Sub Variety Grade Date \\\n",
"0 BALTIMORE NaN 24 inch bins NaN NaN NaN 4/29/17 \n",
"1 BALTIMORE NaN 24 inch bins NaN NaN NaN 5/6/17 \n",
"2 BALTIMORE NaN 24 inch bins HOWDEN TYPE NaN NaN 9/24/16 \n",
"3 BALTIMORE NaN 24 inch bins HOWDEN TYPE NaN NaN 9/24/16 \n",
"4 BALTIMORE NaN 24 inch bins HOWDEN TYPE NaN NaN 11/5/16 \n",
"\n",
" Low Price High Price Mostly Low ... Unit of Sale Quality Condition \\\n",
"0 270.0 280.0 270.0 ... NaN NaN NaN \n",
"1 270.0 280.0 270.0 ... NaN NaN NaN \n",
"2 160.0 160.0 160.0 ... NaN NaN NaN \n",
"3 160.0 160.0 160.0 ... NaN NaN NaN \n",
"4 90.0 100.0 90.0 ... NaN NaN NaN \n",
"\n",
" Appearance Storage Crop Repack Trans Mode Unnamed: 24 Unnamed: 25 \n",
"0 NaN NaN NaN E NaN NaN NaN \n",
"1 NaN NaN NaN E NaN NaN NaN \n",
"2 NaN NaN NaN N NaN NaN NaN \n",
"3 NaN NaN NaN N NaN NaN NaN \n",
"4 NaN NaN NaN N NaN NaN NaN \n",
"\n",
"[5 rows x 26 columns]"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"full_pumpkins = pd.read_csv('../data/US-pumpkins.csv')\n",
"\n",
"full_pumpkins.head()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby AI pro překlady [Co-op Translator](https://github.com/Azure/co-op-translator). Ačkoli se snažíme o přesnost, mějte prosím na paměti, že automatizované překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace se doporučuje profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "dee08c2b49057b0de8b6752c4dbca368",
"translation_date": "2025-09-04T06:42:16+00:00",
"source_file": "2-Regression/4-Logistic/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

@ -0,0 +1,686 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vytvoření modelu logistické regrese - Lekce 4\n",
"\n",
"![Infografika: Logistická vs. lineární regrese](../../../../../../2-Regression/4-Logistic/images/linear-vs-logistic.png)\n",
"\n",
"#### **[Kvíz před lekcí](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n",
"\n",
"#### Úvod\n",
"\n",
"V této závěrečné lekci o regresi, jednom ze základních *klasických* technik strojového učení, se podíváme na logistickou regresi. Tuto techniku byste použili k objevování vzorců pro predikci binárních kategorií. Je tato cukrovinka čokoláda, nebo ne? Je tato nemoc nakažlivá, nebo ne? Vybere si tento zákazník tento produkt, nebo ne?\n",
"\n",
"V této lekci se naučíte:\n",
"\n",
"- Techniky logistické regrese\n",
"\n",
"✅ Prohlubte své znalosti práce s tímto typem regrese v tomto [výukovém modulu](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n",
"\n",
"## Předpoklady\n",
"\n",
"Po práci s daty o dýních jsme nyní dostatečně obeznámeni s tím, že existuje jedna binární kategorie, se kterou můžeme pracovat: `Color`.\n",
"\n",
"Postavme model logistické regrese, který předpoví, na základě některých proměnných, *jakou barvu bude mít daná dýně* (oranžová 🎃 nebo bílá 👻).\n",
"\n",
"> Proč mluvíme o binární klasifikaci v lekci zaměřené na regresi? Pouze z jazykového pohodlí, protože logistická regrese je [ve skutečnosti klasifikační metoda](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), i když založená na lineární regresi. O dalších způsobech klasifikace dat se dozvíte v další skupině lekcí.\n",
"\n",
"Pro tuto lekci budeme potřebovat následující balíčky:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) je [kolekce balíčků pro R](https://www.tidyverse.org/packages), která usnadňuje, zrychluje a zpříjemňuje práci s datovou vědou!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) je rámec [kolekce balíčků](https://www.tidymodels.org/packages/) pro modelování a strojové učení.\n",
"\n",
"- `janitor`: [janitor balíček](https://github.com/sfirke/janitor) poskytuje jednoduché nástroje pro zkoumání a čištění špinavých dat.\n",
"\n",
"- `ggbeeswarm`: [ggbeeswarm balíček](https://github.com/eclarke/ggbeeswarm) nabízí metody pro vytváření grafů ve stylu \"beeswarm\" pomocí ggplot2.\n",
"\n",
"Můžete je nainstalovat pomocí:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n",
"\n",
"Alternativně níže uvedený skript zkontroluje, zda máte potřebné balíčky pro dokončení tohoto modulu, a v případě jejich absence je nainstaluje.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\n",
"\n",
"pacman::p_load(tidyverse, tidymodels, janitor, ggbeeswarm)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **Definujte otázku**\n",
"\n",
"Pro naše účely ji vyjádříme jako binární: 'Bílá' nebo 'Ne bílá'. V našem datasetu je také kategorie 'pruhovaná', ale má málo záznamů, takže ji nebudeme používat. Stejně zmizí, jakmile odstraníme nulové hodnoty z datasetu.\n",
"\n",
"> 🎃 Zajímavost: bílé dýně někdy nazýváme 'duchové' dýně. Nejsou příliš snadné na vyřezávání, takže nejsou tak populární jako oranžové, ale vypadají zajímavě! Mohli bychom tedy naši otázku přeformulovat na: 'Duch' nebo 'Ne duch'. 👻\n",
"\n",
"## **O logistické regresi**\n",
"\n",
"Logistická regrese se liší od lineární regrese, kterou jste se naučili dříve, v několika důležitých ohledech.\n",
"\n",
"#### **Binární klasifikace**\n",
"\n",
"Logistická regrese nenabízí stejné funkce jako lineární regrese. První z nich poskytuje předpověď o `binární kategorii` (\"oranžová nebo ne oranžová\"), zatímco druhá je schopna předpovídat `kontinuální hodnoty`, například na základě původu dýně a času sklizně, *o kolik se zvýší její cena*.\n",
"\n",
"![Infografika od Dasani Madipalli](../../../../../../2-Regression/4-Logistic/images/pumpkin-classifier.png)\n",
"\n",
"### Další klasifikace\n",
"\n",
"Existují i jiné typy logistické regrese, včetně multinomiální a ordinální:\n",
"\n",
"- **Multinomiální**, která zahrnuje více než jednu kategorii - \"Oranžová, Bílá a Pruhovaná\".\n",
"\n",
"- **Ordinální**, která zahrnuje uspořádané kategorie, užitečné, pokud bychom chtěli logicky uspořádat naše výsledky, například naše dýně, které jsou uspořádány podle konečného počtu velikostí (mini,sm,med,lg,xl,xxl).\n",
"\n",
"![Multinomiální vs ordinální regrese](../../../../../../2-Regression/4-Logistic/images/multinomial-vs-ordinal.png)\n",
"\n",
"#### **Proměnné NEMUSÍ být korelované**\n",
"\n",
"Pamatujete si, jak lineární regrese fungovala lépe s více korelovanými proměnnými? Logistická regrese je opakem - proměnné nemusí být v souladu. To funguje pro tato data, která mají poměrně slabé korelace.\n",
"\n",
"#### **Potřebujete hodně čistých dat**\n",
"\n",
"Logistická regrese poskytne přesnější výsledky, pokud použijete více dat; náš malý dataset není pro tento úkol optimální, takže na to pamatujte.\n",
"\n",
"✅ Zamyslete se nad typy dat, které by se dobře hodily pro logistickou regresi.\n",
"\n",
"## Cvičení - úprava dat\n",
"\n",
"Nejprve data trochu vyčistěte, odstraňte nulové hodnoty a vyberte pouze některé sloupce:\n",
"\n",
"1. Přidejte následující kód:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Load the core tidyverse packages\n",
"library(tidyverse)\n",
"\n",
"# Import the data and clean column names\n",
"pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\") %>% \n",
" clean_names()\n",
"\n",
"# Select desired columns\n",
"pumpkins_select <- pumpkins %>% \n",
" select(c(city_name, package, variety, origin, item_size, color)) \n",
"\n",
"# Drop rows containing missing values and encode color as factor (category)\n",
"pumpkins_select <- pumpkins_select %>% \n",
" drop_na() %>% \n",
" mutate(color = factor(color))\n",
"\n",
"# View the first few rows\n",
"pumpkins_select %>% \n",
" slice_head(n = 5)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Vždy se můžete podívat na svůj nový dataframe pomocí funkce [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html), jak je uvedeno níže:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"pumpkins_select %>% \n",
" glimpse()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pojďme si potvrdit, že se skutečně budeme zabývat problémem binární klasifikace:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Subset distinct observations in outcome column\n",
"pumpkins_select %>% \n",
" distinct(color)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Vizualizace - kategorický graf\n",
"Nyní jste znovu načetli data o dýních a vyčistili je tak, aby obsahovala dataset s několika proměnnými, včetně barvy. Pojďme vizualizovat dataframe v notebooku pomocí knihovny ggplot.\n",
"\n",
"Knihovna ggplot nabízí několik skvělých způsobů, jak vizualizovat vaše data. Například můžete porovnat rozložení dat pro každou odrůdu a barvu v kategorickém grafu.\n",
"\n",
"1. Vytvořte takový graf pomocí funkce geombar, použijte naše data o dýních a specifikujte barevné mapování pro každou kategorii dýní (oranžová nebo bílá):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "python"
}
},
"outputs": [],
"source": [
"# Specify colors for each value of the hue variable\n",
"palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n",
"\n",
"# Create the bar plot\n",
"ggplot(pumpkins_select, aes(y = variety, fill = color)) +\n",
" geom_bar(position = \"dodge\") +\n",
" scale_fill_manual(values = palette) +\n",
" labs(y = \"Variety\", fill = \"Color\") +\n",
" theme_minimal()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pozorováním dat můžete vidět, jak se údaje o barvě vztahují k odrůdě.\n",
"\n",
"✅ Na základě tohoto kategorického grafu, jaké zajímavé průzkumy si dokážete představit?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Předzpracování dat: kódování atributů\n",
"\n",
"Náš dataset dýní obsahuje textové hodnoty ve všech svých sloupcích. Práce s kategoriálními daty je pro lidi intuitivní, ale pro stroje nikoliv. Algoritmy strojového učení pracují dobře s čísly. Proto je kódování velmi důležitým krokem ve fázi předzpracování dat, protože nám umožňuje převést kategoriální data na numerická, aniž bychom ztratili jakékoliv informace. Dobré kódování vede k vytvoření kvalitního modelu.\n",
"\n",
"Pro kódování atributů existují dva hlavní typy kódovačů:\n",
"\n",
"1. Ordinalní kódovač: hodí se pro ordinalní proměnné, což jsou kategoriální proměnné, jejichž data mají logické pořadí, jako například sloupec `item_size` v našem datasetu. Vytváří mapování, kde každá kategorie je reprezentována číslem, které odpovídá pořadí kategorie ve sloupci.\n",
"\n",
"2. Kategoriální kódovač: hodí se pro nominální proměnné, což jsou kategoriální proměnné, jejichž data nemají logické pořadí, jako všechny atributy kromě `item_size` v našem datasetu. Jedná se o one-hot kódování, což znamená, že každá kategorie je reprezentována binárním sloupcem: kódovaná proměnná je rovna 1, pokud dýně patří do dané Variety, a 0 v opačném případě.\n",
"\n",
"Tidymodels poskytuje další šikovný balíček: [recipes](https://recipes.tidymodels.org/) - balíček pro předzpracování dat. Definujeme `recipe`, který specifikuje, že všechny sloupce prediktorů by měly být kódovány na sadu celých čísel, `prep` pro odhad potřebných množství a statistik potřebných pro jakékoliv operace, a nakonec `bake` pro aplikaci výpočtů na nová data.\n",
"\n",
"> Obvykle se recipes používá jako předzpracovatel pro modelování, kde definuje, jaké kroky by měly být aplikovány na dataset, aby byl připraven pro modelování. V takovém případě je **vysoce doporučeno**, abyste použili `workflow()` místo ručního odhadu recipe pomocí prep a bake. Vše si ukážeme za chvíli.\n",
">\n",
"> Prozatím však používáme recipes + prep + bake k tomu, abychom specifikovali, jaké kroky by měly být aplikovány na dataset, aby byl připraven pro analýzu dat, a následně extrahovali předzpracovaná data s aplikovanými kroky.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Preprocess and extract data to allow some data analysis\n",
"baked_pumpkins <- recipe(color ~ ., data = pumpkins_select) %>%\n",
" # Define ordering for item_size column\n",
" step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n",
" # Convert factors to numbers using the order defined above (Ordinal encoding)\n",
" step_integer(item_size, zero_based = F) %>%\n",
" # Encode all other predictors using one hot encoding\n",
" step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE) %>%\n",
" prep(data = pumpkin_select) %>%\n",
" bake(new_data = NULL)\n",
"\n",
"# Display the first few rows of preprocessed data\n",
"baked_pumpkins %>% \n",
" slice_head(n = 5)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"✅ Jaké jsou výhody použití ordinálního enkodéru pro sloupec Item Size?\n",
"\n",
"### Analýza vztahů mezi proměnnými\n",
"\n",
"Nyní, když jsme předzpracovali naše data, můžeme analyzovat vztahy mezi vlastnostmi a štítkem, abychom získali představu o tom, jak dobře bude model schopen předpovědět štítek na základě vlastností. Nejlepší způsob, jak provést tento typ analýzy, je vizualizace dat. \n",
"Opět použijeme funkci ggplot geom_boxplot_, abychom zobrazili vztahy mezi Item Size, Variety a Color v kategorickém grafu. Pro lepší vizualizaci dat použijeme zakódovaný sloupec Item Size a nekódovaný sloupec Variety.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Define the color palette\n",
"palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n",
"\n",
"# We need the encoded Item Size column to use it as the x-axis values in the plot\n",
"pumpkins_select_plot<-pumpkins_select\n",
"pumpkins_select_plot$item_size <- baked_pumpkins$item_size\n",
"\n",
"# Create the grouped box plot\n",
"ggplot(pumpkins_select_plot, aes(x = `item_size`, y = color, fill = color)) +\n",
" geom_boxplot() +\n",
" facet_grid(variety ~ ., scales = \"free_x\") +\n",
" scale_fill_manual(values = palette) +\n",
" labs(x = \"Item Size\", y = \"\") +\n",
" theme_minimal() +\n",
" theme(strip.text = element_text(size = 12)) +\n",
" theme(axis.text.x = element_text(size = 10)) +\n",
" theme(axis.title.x = element_text(size = 12)) +\n",
" theme(axis.title.y = element_blank()) +\n",
" theme(legend.position = \"bottom\") +\n",
" guides(fill = guide_legend(title = \"Color\")) +\n",
" theme(panel.spacing = unit(0.5, \"lines\"))+\n",
" theme(strip.text.y = element_text(size = 4, hjust = 0)) \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Použijte swarm plot\n",
"\n",
"Protože Barva je binární kategorie (Bílá nebo Ne), vyžaduje '[specializovaný přístup](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf) k vizualizaci'.\n",
"\n",
"Vyzkoušejte `swarm plot`, abyste zobrazili rozložení barvy vzhledem k velikosti položky.\n",
"\n",
"Použijeme balíček [ggbeeswarm](https://github.com/eclarke/ggbeeswarm), který poskytuje metody pro vytváření grafů ve stylu beeswarm pomocí ggplot2. Beeswarm grafy jsou způsobem vykreslování bodů, které by se za normálních okolností překrývaly, tak, aby se zobrazily vedle sebe.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Create beeswarm plots of color and item_size\n",
"baked_pumpkins %>% \n",
" mutate(color = factor(color)) %>% \n",
" ggplot(mapping = aes(x = color, y = item_size, color = color)) +\n",
" geom_quasirandom() +\n",
" scale_color_brewer(palette = \"Dark2\", direction = -1) +\n",
" theme(legend.position = \"none\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Nyní, když máme představu o vztahu mezi binárními kategoriemi barvy a širší skupinou velikostí, pojďme prozkoumat logistickou regresi, abychom určili pravděpodobnou barvu dané dýně.\n",
"\n",
"## Vytvořte svůj model\n",
"\n",
"Vyberte proměnné, které chcete použít ve svém klasifikačním modelu, a rozdělte data na trénovací a testovací sady. [rsample](https://rsample.tidymodels.org/), balíček v Tidymodels, poskytuje infrastrukturu pro efektivní rozdělování dat a resampling:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Split data into 80% for training and 20% for testing\n",
"set.seed(2056)\n",
"pumpkins_split <- pumpkins_select %>% \n",
" initial_split(prop = 0.8)\n",
"\n",
"# Extract the data in each split\n",
"pumpkins_train <- training(pumpkins_split)\n",
"pumpkins_test <- testing(pumpkins_split)\n",
"\n",
"# Print out the first 5 rows of the training set\n",
"pumpkins_train %>% \n",
" slice_head(n = 5)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"🙌 Nyní jsme připraveni trénovat model tím, že přizpůsobíme tréninkové vlastnosti tréninkovému štítku (barvě).\n",
"\n",
"Začneme vytvořením receptu, který určuje kroky předzpracování, jež by měly být provedeny na našich datech, aby byla připravena pro modelování, tj. kódování kategoriálních proměnných do sady celých čísel. Stejně jako `baked_pumpkins` vytvoříme `pumpkins_recipe`, ale nebudeme používat `prep` a `bake`, protože to bude zahrnuto do pracovního postupu, který uvidíte za pár kroků.\n",
"\n",
"Existuje poměrně mnoho způsobů, jak specifikovat logistický regresní model v Tidymodels. Podívejte se na `?logistic_reg()`. Prozatím specifikujeme logistický regresní model pomocí výchozího enginu `stats::glm()`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Create a recipe that specifies preprocessing steps for modelling\n",
"pumpkins_recipe <- recipe(color ~ ., data = pumpkins_train) %>% \n",
" step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n",
" step_integer(item_size, zero_based = F) %>% \n",
" step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE)\n",
"\n",
"# Create a logistic model specification\n",
"log_reg <- logistic_reg() %>% \n",
" set_engine(\"glm\") %>% \n",
" set_mode(\"classification\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Nyní, když máme recept a specifikaci modelu, musíme najít způsob, jak je spojit dohromady do objektu, který nejprve předzpracuje data (příprava + pečení na pozadí), přizpůsobí model na předzpracovaná data a také umožní případné aktivity po zpracování.\n",
"\n",
"V Tidymodels se tento praktický objekt nazývá [`workflow`](https://workflows.tidymodels.org/) a pohodlně uchovává vaše modelovací komponenty.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Bundle modelling components in a workflow\n",
"log_reg_wf <- workflow() %>% \n",
" add_recipe(pumpkins_recipe) %>% \n",
" add_model(log_reg)\n",
"\n",
"# Print out the workflow\n",
"log_reg_wf\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Poté, co byl pracovní postup *definován*, může být model `natrénován` pomocí funkce [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html). Pracovní postup odhadne recept a předzpracuje data před tréninkem, takže to nebudeme muset dělat ručně pomocí funkcí prep a bake.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Train the model\n",
"wf_fit <- log_reg_wf %>% \n",
" fit(data = pumpkins_train)\n",
"\n",
"# Print the trained workflow\n",
"wf_fit\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Model vytiskne koeficienty naučené během trénování.\n",
"\n",
"Nyní, když jsme model natrénovali pomocí trénovacích dat, můžeme provádět predikce na testovacích datech pomocí [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Začněme tím, že použijeme model k predikci štítků pro naši testovací sadu a pravděpodobností pro každý štítek. Pokud je pravděpodobnost vyšší než 0,5, predikovaná třída je `WHITE`, jinak `ORANGE`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Make predictions for color and corresponding probabilities\n",
"results <- pumpkins_test %>% select(color) %>% \n",
" bind_cols(wf_fit %>% \n",
" predict(new_data = pumpkins_test)) %>%\n",
" bind_cols(wf_fit %>%\n",
" predict(new_data = pumpkins_test, type = \"prob\"))\n",
"\n",
"# Compare predictions\n",
"results %>% \n",
" slice_head(n = 10)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Velmi pěkné! To poskytuje další vhledy do toho, jak funguje logistická regrese.\n",
"\n",
"### Lepší pochopení pomocí matice záměn\n",
"\n",
"Porovnávání každé předpovědi s odpovídající „skutečnou hodnotou“ není příliš efektivní způsob, jak zjistit, jak dobře model předpovídá. Naštěstí má Tidymodels ještě několik triků v rukávu: [`yardstick`](https://yardstick.tidymodels.org/) - balíček používaný k měření účinnosti modelů pomocí metrik výkonu.\n",
"\n",
"Jednou z metrik výkonu spojených s klasifikačními problémy je [`matice záměn`](https://wikipedia.org/wiki/Confusion_matrix). Matice záměn popisuje, jak dobře klasifikační model funguje. Matice záměn zaznamenává, kolik příkladů v každé třídě bylo modelem správně klasifikováno. V našem případě vám ukáže, kolik oranžových dýní bylo klasifikováno jako oranžové a kolik bílých dýní bylo klasifikováno jako bílé; matice záměn také ukazuje, kolik bylo klasifikováno do **nesprávných** kategorií.\n",
"\n",
"Funkce [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) z yardsticku vypočítává tuto křížovou tabulku pozorovaných a předpovězených tříd.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Confusion matrix for prediction results\n",
"conf_mat(data = results, truth = color, estimate = .pred_class)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pojďme si vysvětlit matici záměn. Náš model má za úkol klasifikovat dýně do dvou binárních kategorií, kategorie `bílá` a kategorie `ne-bílá`.\n",
"\n",
"- Pokud váš model předpoví dýni jako bílou a ve skutečnosti patří do kategorie 'bílá', nazýváme to `pravý pozitivní`, což je znázorněno číslem v levém horním rohu.\n",
"\n",
"- Pokud váš model předpoví dýni jako ne-bílou a ve skutečnosti patří do kategorie 'bílá', nazýváme to `falešný negativní`, což je znázorněno číslem v levém dolním rohu.\n",
"\n",
"- Pokud váš model předpoví dýni jako bílou a ve skutečnosti patří do kategorie 'ne-bílá', nazýváme to `falešný pozitivní`, což je znázorněno číslem v pravém horním rohu.\n",
"\n",
"- Pokud váš model předpoví dýni jako ne-bílou a ve skutečnosti patří do kategorie 'ne-bílá', nazýváme to `pravý negativní`, což je znázorněno číslem v pravém dolním rohu.\n",
"\n",
"| Skutečnost |\n",
"|:----------:|\n",
"\n",
"\n",
"| | | |\n",
"|---------------|--------|-------|\n",
"| **Předpověď** | BÍLÁ | ORANŽOVÁ |\n",
"| BÍLÁ | TP | FP |\n",
"| ORANŽOVÁ | FN | TN |\n",
"\n",
"Jak jste možná uhodli, je žádoucí mít větší počet pravých pozitivních a pravých negativních a nižší počet falešných pozitivních a falešných negativních, což naznačuje, že model funguje lépe.\n",
"\n",
"Matice záměn je užitečná, protože z ní vycházejí další metriky, které nám mohou pomoci lépe vyhodnotit výkon klasifikačního modelu. Pojďme si je projít:\n",
"\n",
"🎓 Přesnost: `TP/(TP + FP)` definovaná jako podíl předpovězených pozitivních, které jsou skutečně pozitivní. Také se nazývá [pozitivní prediktivní hodnota](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n",
"\n",
"🎓 Záchyt: `TP/(TP + FN)` definovaný jako podíl pozitivních výsledků z počtu vzorků, které byly skutečně pozitivní. Také známý jako `citlivost`.\n",
"\n",
"🎓 Specifičnost: `TN/(TN + FP)` definovaná jako podíl negativních výsledků z počtu vzorků, které byly skutečně negativní.\n",
"\n",
"🎓 Přesnost modelu: `TP + TN/(TP + TN + FP + FN)` Procento štítků správně předpovězených pro vzorek.\n",
"\n",
"🎓 F míra: Vážený průměr přesnosti a záchytu, přičemž nejlepší hodnota je 1 a nejhorší je 0.\n",
"\n",
"Pojďme tyto metriky vypočítat!\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Combine metric functions and calculate them all at once\n",
"eval_metrics <- metric_set(ppv, recall, spec, f_meas, accuracy)\n",
"eval_metrics(data = results, truth = color, estimate = .pred_class)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vizualizace ROC křivky tohoto modelu\n",
"\n",
"Provedeme ještě jednu vizualizaci, abychom si prohlédli tzv. [`ROC křivku`](https://en.wikipedia.org/wiki/Receiver_operating_characteristic):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Make a roc_curve\n",
"results %>% \n",
" roc_curve(color, .pred_ORANGE) %>% \n",
" autoplot()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ROC křivky se často používají k zobrazení výstupu klasifikátoru z hlediska jeho skutečných vs. falešných pozitivních výsledků. ROC křivky obvykle zobrazují `True Positive Rate`/citlivost na ose Y a `False Positive Rate`/1-specificitu na ose X. Strmost křivky a prostor mezi středovou čarou a křivkou jsou důležité: chcete křivku, která rychle stoupá a překračuje čáru. V našem případě se na začátku objevují falešné pozitivní výsledky, poté čára správně stoupá a překračuje.\n",
"\n",
"Nakonec použijme `yardstick::roc_auc()` k výpočtu skutečné plochy pod křivkou. Jedním ze způsobů interpretace AUC je pravděpodobnost, že model zařadí náhodný pozitivní příklad výše než náhodný negativní příklad.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Calculate area under curve\n",
"results %>% \n",
" roc_auc(color, .pred_ORANGE)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Výsledek je přibližně `0.975`. Vzhledem k tomu, že AUC se pohybuje v rozmezí od 0 do 1, chcete dosáhnout vysokého skóre, protože model, který je ve svých předpovědích 100% přesný, bude mít AUC rovno 1; v tomto případě je model *docela dobrý*.\n",
"\n",
"V budoucích lekcích o klasifikacích se naučíte, jak zlepšit skóre svého modelu (například jak se vypořádat s nevyváženými daty v tomto případě).\n",
"\n",
"## 🚀Výzva\n",
"\n",
"Logistická regrese nabízí mnohem více k prozkoumání! Nejlepší způsob, jak se učit, je experimentovat. Najděte dataset, který se hodí k tomuto typu analýzy, a vytvořte s ním model. Co jste se naučili? tip: zkuste [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) pro zajímavé datové sady.\n",
"\n",
"## Přehled & Samostudium\n",
"\n",
"Přečtěte si první několik stran [tohoto článku ze Stanfordu](https://web.stanford.edu/~jurafsky/slp3/5.pdf) o praktickém využití logistické regrese. Zamyslete se nad úkoly, které jsou lépe vhodné pro jeden nebo druhý typ regresních úkolů, které jsme dosud studovali. Co by fungovalo nejlépe?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace se doporučuje profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
],
"metadata": {
"anaconda-cloud": "",
"kernelspec": {
"display_name": "R",
"langauge": "R",
"name": "ir"
},
"language_info": {
"codemirror_mode": "r",
"file_extension": ".r",
"mimetype": "text/x-r-source",
"name": "R",
"pygments_lexer": "r",
"version": "3.4.1"
},
"coopTranslator": {
"original_hash": "feaf125f481a89c468fa115bf2aed580",
"translation_date": "2025-09-04T06:48:07+00:00",
"source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,267 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python37364bit8d3b438fb5fc4430a93ac2cb74d693a7",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "5fa2e8f4584c78250ca9729b46562ceb",
"translation_date": "2025-09-04T08:16:46+00:00",
"source_file": "3-Web-App/1-Web-App/solution/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" datetime city state country shape \\\n",
"0 10/10/1949 20:30 san marcos tx us cylinder \n",
"1 10/10/1949 21:00 lackland afb tx NaN light \n",
"2 10/10/1955 17:00 chester (uk/england) NaN gb circle \n",
"3 10/10/1956 21:00 edna tx us circle \n",
"4 10/10/1960 20:00 kaneohe hi us light \n",
"\n",
" duration (seconds) duration (hours/min) \\\n",
"0 2700.0 45 minutes \n",
"1 7200.0 1-2 hrs \n",
"2 20.0 20 seconds \n",
"3 20.0 1/2 hour \n",
"4 900.0 15 minutes \n",
"\n",
" comments date posted latitude \\\n",
"0 This event took place in early fall around 194... 4/27/2004 29.883056 \n",
"1 1949 Lackland AFB&#44 TX. Lights racing acros... 12/16/2005 29.384210 \n",
"2 Green/Orange circular disc over Chester&#44 En... 1/21/2008 53.200000 \n",
"3 My older brother and twin sister were leaving ... 1/17/2004 28.978333 \n",
"4 AS a Marine 1st Lt. flying an FJ4B fighter/att... 1/22/2004 21.418056 \n",
"\n",
" longitude \n",
"0 -97.941111 \n",
"1 -98.581082 \n",
"2 -2.916667 \n",
"3 -96.645833 \n",
"4 -157.803611 "
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>datetime</th>\n <th>city</th>\n <th>state</th>\n <th>country</th>\n <th>shape</th>\n <th>duration (seconds)</th>\n <th>duration (hours/min)</th>\n <th>comments</th>\n <th>date posted</th>\n <th>latitude</th>\n <th>longitude</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>10/10/1949 20:30</td>\n <td>san marcos</td>\n <td>tx</td>\n <td>us</td>\n <td>cylinder</td>\n <td>2700.0</td>\n <td>45 minutes</td>\n <td>This event took place in early fall around 194...</td>\n <td>4/27/2004</td>\n <td>29.883056</td>\n <td>-97.941111</td>\n </tr>\n <tr>\n <th>1</th>\n <td>10/10/1949 21:00</td>\n <td>lackland afb</td>\n <td>tx</td>\n <td>NaN</td>\n <td>light</td>\n <td>7200.0</td>\n <td>1-2 hrs</td>\n <td>1949 Lackland AFB&amp;#44 TX. Lights racing acros...</td>\n <td>12/16/2005</td>\n <td>29.384210</td>\n <td>-98.581082</td>\n </tr>\n <tr>\n <th>2</th>\n <td>10/10/1955 17:00</td>\n <td>chester (uk/england)</td>\n <td>NaN</td>\n <td>gb</td>\n <td>circle</td>\n <td>20.0</td>\n <td>20 seconds</td>\n <td>Green/Orange circular disc over Chester&amp;#44 En...</td>\n <td>1/21/2008</td>\n <td>53.200000</td>\n <td>-2.916667</td>\n </tr>\n <tr>\n <th>3</th>\n <td>10/10/1956 21:00</td>\n <td>edna</td>\n <td>tx</td>\n <td>us</td>\n <td>circle</td>\n <td>20.0</td>\n <td>1/2 hour</td>\n <td>My older brother and twin sister were leaving ...</td>\n <td>1/17/2004</td>\n <td>28.978333</td>\n <td>-96.645833</td>\n </tr>\n <tr>\n <th>4</th>\n <td>10/10/1960 20:00</td>\n <td>kaneohe</td>\n <td>hi</td>\n <td>us</td>\n <td>light</td>\n <td>900.0</td>\n <td>15 minutes</td>\n <td>AS a Marine 1st Lt. flying an FJ4B fighter/att...</td>\n <td>1/22/2004</td>\n <td>21.418056</td>\n <td>-157.803611</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {},
"execution_count": 23
}
],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"ufos = pd.read_csv('../data/ufos.csv')\n",
"ufos.head()\n"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"array(['us', nan, 'gb', 'ca', 'au', 'de'], dtype=object)"
]
},
"metadata": {},
"execution_count": 24
}
],
"source": [
"\n",
"ufos = pd.DataFrame({'Seconds': ufos['duration (seconds)'], 'Country': ufos['country'],'Latitude': ufos['latitude'],'Longitude': ufos['longitude']})\n",
"\n",
"ufos.Country.unique()\n",
"\n",
"# 0 au, 1 ca, 2 de, 3 gb, 4 us"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"<class 'pandas.core.frame.DataFrame'>\nInt64Index: 25863 entries, 2 to 80330\nData columns (total 4 columns):\n # Column Non-Null Count Dtype \n--- ------ -------------- ----- \n 0 Seconds 25863 non-null float64\n 1 Country 25863 non-null object \n 2 Latitude 25863 non-null float64\n 3 Longitude 25863 non-null float64\ndtypes: float64(3), object(1)\nmemory usage: 1010.3+ KB\n"
]
}
],
"source": [
"ufos.dropna(inplace=True)\n",
"\n",
"ufos = ufos[(ufos['Seconds'] >= 1) & (ufos['Seconds'] <= 60)]\n",
"\n",
"ufos.info()"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Seconds Country Latitude Longitude\n",
"2 20.0 3 53.200000 -2.916667\n",
"3 20.0 4 28.978333 -96.645833\n",
"14 30.0 4 35.823889 -80.253611\n",
"23 60.0 4 45.582778 -122.352222\n",
"24 3.0 3 51.783333 -0.783333"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Seconds</th>\n <th>Country</th>\n <th>Latitude</th>\n <th>Longitude</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>2</th>\n <td>20.0</td>\n <td>3</td>\n <td>53.200000</td>\n <td>-2.916667</td>\n </tr>\n <tr>\n <th>3</th>\n <td>20.0</td>\n <td>4</td>\n <td>28.978333</td>\n <td>-96.645833</td>\n </tr>\n <tr>\n <th>14</th>\n <td>30.0</td>\n <td>4</td>\n <td>35.823889</td>\n <td>-80.253611</td>\n </tr>\n <tr>\n <th>23</th>\n <td>60.0</td>\n <td>4</td>\n <td>45.582778</td>\n <td>-122.352222</td>\n </tr>\n <tr>\n <th>24</th>\n <td>3.0</td>\n <td>3</td>\n <td>51.783333</td>\n <td>-0.783333</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {},
"execution_count": 26
}
],
"source": [
"from sklearn.preprocessing import LabelEncoder\n",
"\n",
"ufos['Country'] = LabelEncoder().fit_transform(ufos['Country'])\n",
"\n",
"ufos.head()"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split\n",
"\n",
"Selected_features = ['Seconds','Latitude','Longitude']\n",
"\n",
"X = ufos[Selected_features]\n",
"y = ufos['Country']\n",
"\n",
"\n",
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)\n"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stderr",
"text": [
"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:432: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.\n",
" FutureWarning)\n",
"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:469: FutureWarning: Default multi_class will be changed to 'auto' in 0.22. Specify the multi_class option to silence this warning.\n",
" \"this warning.\", FutureWarning)\n",
" precision recall f1-score support\n",
"\n",
" 0 1.00 1.00 1.00 41\n",
" 1 1.00 0.02 0.05 250\n",
" 2 0.00 0.00 0.00 8\n",
" 3 0.94 1.00 0.97 131\n",
" 4 0.95 1.00 0.97 4743\n",
"\n",
" accuracy 0.95 5173\n",
" macro avg 0.78 0.60 0.60 5173\n",
"weighted avg 0.95 0.95 0.93 5173\n",
"\n",
"Predicted labels: [4 4 4 ... 3 4 4]\n",
"Accuracy: 0.9512855209742895\n",
"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sklearn/metrics/classification.py:1437: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.\n",
" 'precision', 'predicted', average, warn_for)\n"
]
}
],
"source": [
"from sklearn.model_selection import train_test_split\n",
"from sklearn.metrics import accuracy_score, classification_report \n",
"from sklearn.linear_model import LogisticRegression\n",
"model = LogisticRegression()\n",
"model.fit(X_train, y_train)\n",
"predictions = model.predict(X_test)\n",
"\n",
"print(classification_report(y_test, predictions))\n",
"print('Predicted labels: ', predictions)\n",
"print('Accuracy: ', accuracy_score(y_test, predictions))\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[3]\n"
]
}
],
"source": [
"import pickle\n",
"model_filename = 'ufo-model.pkl'\n",
"pickle.dump(model, open(model_filename,'wb'))\n",
"\n",
"model = pickle.load(open('ufo-model.pkl','rb'))\n",
"print(model.predict([[50,44,-12]]))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Upozornění**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace se doporučuje profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,39 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "d544ef384b7ba73757d830a72372a7f2",
"translation_date": "2025-09-04T08:44:11+00:00",
"source_file": "4-Classification/1-Introduction/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,727 @@
{
"nbformat": 4,
"nbformat_minor": 2,
"metadata": {
"colab": {
"name": "lesson_10-R.ipynb",
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "2621e24705e8100893c9bf84e0fc8aef",
"translation_date": "2025-09-04T08:50:44+00:00",
"source_file": "4-Classification/1-Introduction/solution/R/lesson_10-R.ipynb",
"language_code": "cs"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [
"# Vytvořte klasifikační model: Lahodné asijské a indické kuchyně\n"
],
"metadata": {
"id": "ItETB4tSFprR"
}
},
{
"cell_type": "markdown",
"source": [
"## Úvod do klasifikace: Čištění, příprava a vizualizace dat\n",
"\n",
"V těchto čtyřech lekcích se zaměříme na základní téma klasického strojového učení - *klasifikaci*. Projdeme si použití různých klasifikačních algoritmů na datasetu o všech skvělých kuchyních Asie a Indie. Doufáme, že máte hlad!\n",
"\n",
"<p >\n",
" <img src=\"../../images/pinch.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Oslavte panasijské kuchyně v těchto lekcích! Obrázek od Jen Looper</figcaption>\n",
"\n",
"\n",
"<!--![Oslavte panasijské kuchyně v těchto lekcích! Obrázek od Jen Looper](../../../../../../4-Classification/1-Introduction/solution/R/images/pinch.png)-->\n",
"\n",
"Klasifikace je forma [učeného učení](https://wikipedia.org/wiki/Supervised_learning), která má mnoho společného s regresními technikami. Při klasifikaci trénujete model, aby předpověděl, do které `kategorie` daná položka patří. Pokud je strojové učení o předpovídání hodnot nebo názvů věcí pomocí datasetů, pak klasifikace obecně spadá do dvou skupin: *binární klasifikace* a *vícetřídová klasifikace*.\n",
"\n",
"Pamatujte:\n",
"\n",
"- **Lineární regrese** vám pomohla předpovědět vztahy mezi proměnnými a provádět přesné předpovědi, kam nový datový bod spadne ve vztahu k této linii. Například jste mohli předpovědět číselné hodnoty, jako *jaká bude cena dýně v září oproti prosinci*.\n",
"\n",
"- **Logistická regrese** vám pomohla objevit \"binární kategorie\": při této cenové hladině, *je tato dýně oranžová nebo neoranžová*?\n",
"\n",
"Klasifikace využívá různé algoritmy k určení dalších způsobů, jak určit štítek nebo třídu datového bodu. Pojďme pracovat s těmito daty o kuchyních a zjistit, zda můžeme na základě skupiny ingrediencí určit původní kuchyni.\n",
"\n",
"### [**Kvíz před lekcí**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/19/)\n",
"\n",
"### **Úvod**\n",
"\n",
"Klasifikace je jednou ze základních činností výzkumníka strojového učení a datového vědce. Od základní klasifikace binární hodnoty (\"je tento e-mail spam nebo ne?\") až po složitou klasifikaci a segmentaci obrázků pomocí počítačového vidění, je vždy užitečné být schopen třídit data do tříd a klást jim otázky.\n",
"\n",
"Řečeno vědecky, vaše klasifikační metoda vytváří prediktivní model, který vám umožňuje mapovat vztah mezi vstupními proměnnými a výstupními proměnnými.\n",
"\n",
"<p >\n",
" <img src=\"../../images/binary-multiclass.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Binární vs. vícetřídové problémy, které klasifikační algoritmy řeší. Infografika od Jen Looper</figcaption>\n",
"\n",
"\n",
"\n",
"Než začneme s procesem čištění našich dat, jejich vizualizací a přípravou na úkoly strojového učení, pojďme se trochu seznámit s různými způsoby, jak lze strojové učení využít ke klasifikaci dat.\n",
"\n",
"Odvozeno ze [statistiky](https://wikipedia.org/wiki/Statistical_classification), klasifikace pomocí klasického strojového učení využívá vlastnosti, jako jsou `kuřák`, `váha` a `věk`, k určení *pravděpodobnosti vývoje X nemoci*. Jako technika učeného učení podobná regresním cvičením, která jste prováděli dříve, jsou vaše data označena a algoritmy strojového učení používají tyto štítky k klasifikaci a předpovědi tříd (nebo 'vlastností') datasetu a jejich přiřazení ke skupině nebo výsledku.\n",
"\n",
"✅ Udělejte si chvíli a představte si dataset o kuchyních. Na co by mohl odpovědět vícetřídový model? Na co by mohl odpovědět binární model? Co kdybyste chtěli určit, zda daná kuchyně pravděpodobně používá pískavici? Co kdybyste chtěli zjistit, zda byste mohli z tašky s potravinami plné badyánu, artyčoků, květáku a křenu vytvořit typické indické jídlo?\n",
"\n",
"### **Ahoj 'klasifikátore'**\n",
"\n",
"Otázka, kterou chceme položit tomuto datasetu o kuchyních, je vlastně **vícetřídová otázka**, protože máme několik potenciálních národních kuchyní, se kterými můžeme pracovat. Na základě dávky ingrediencí, do které z těchto mnoha tříd budou data spadat?\n",
"\n",
"Tidymodels nabízí několik různých algoritmů pro klasifikaci dat, v závislosti na typu problému, který chcete řešit. V následujících dvou lekcích se naučíte o několika z těchto algoritmů.\n",
"\n",
"#### **Předpoklady**\n",
"\n",
"Pro tuto lekci budeme potřebovat následující balíčky pro čištění, přípravu a vizualizaci našich dat:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) je [kolekce balíčků pro R](https://www.tidyverse.org/packages), která dělá datovou vědu rychlejší, jednodušší a zábavnější!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) je [rámec balíčků](https://www.tidymodels.org/packages/) pro modelování a strojové učení.\n",
"\n",
"- `DataExplorer`: [balíček DataExplorer](https://cran.r-project.org/web/packages/DataExplorer/vignettes/dataexplorer-intro.html) je určen k zjednodušení a automatizaci procesu EDA a generování reportů.\n",
"\n",
"- `themis`: [balíček themis](https://themis.tidymodels.org/) poskytuje další kroky pro práci s nevyváženými daty.\n",
"\n",
"Můžete je nainstalovat pomocí:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"DataExplorer\", \"here\"))`\n",
"\n",
"Alternativně, skript níže zkontroluje, zda máte balíčky potřebné k dokončení tohoto modulu, a nainstaluje je za vás, pokud chybí.\n"
],
"metadata": {
"id": "ri5bQxZ-Fz_0"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\r\n",
"\r\n",
"pacman::p_load(tidyverse, tidymodels, DataExplorer, themis, here)"
],
"outputs": [],
"metadata": {
"id": "KIPxa4elGAPI"
}
},
{
"cell_type": "markdown",
"source": [
"Později načteme tyto skvělé balíčky a zpřístupníme je v naší aktuální relaci R. (Toto je pouze pro ilustraci, `pacman::p_load()` to již za vás udělal)\n"
],
"metadata": {
"id": "YkKAxOJvGD4C"
}
},
{
"cell_type": "markdown",
"source": [
"## Cvičení - vyčistěte a vyvažte svá data\n",
"\n",
"Prvním úkolem, než začnete s tímto projektem, je vyčistit a **vyvážit** svá data, abyste dosáhli lepších výsledků.\n",
"\n",
"Seznamme se s daty! 🕵️\n"
],
"metadata": {
"id": "PFkQDlk0GN5O"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Import data\r\n",
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/4-Classification/data/cuisines.csv\")\r\n",
"\r\n",
"# View the first 5 rows\r\n",
"df %>% \r\n",
" slice_head(n = 5)\r\n"
],
"outputs": [],
"metadata": {
"id": "Qccw7okxGT0S"
}
},
{
"cell_type": "markdown",
"source": [
"Zajímavé! Podle všeho je první sloupec jakýsi sloupec `id`. Zjistíme si trochu více informací o těchto datech.\n"
],
"metadata": {
"id": "XrWnlgSrGVmR"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Basic information about the data\r\n",
"df %>%\r\n",
" introduce()\r\n",
"\r\n",
"# Visualize basic information above\r\n",
"df %>% \r\n",
" plot_intro(ggtheme = theme_light())"
],
"outputs": [],
"metadata": {
"id": "4UcGmxRxGieA"
}
},
{
"cell_type": "markdown",
"source": [
"Z výstupu můžeme okamžitě vidět, že máme `2448` řádků a `385` sloupců a `0` chybějících hodnot. Máme také 1 diskrétní sloupec, *cuisine*.\n",
"\n",
"## Cvičení - poznávání kuchyní\n",
"\n",
"Teď začíná práce být zajímavější. Pojďme objevit rozložení dat podle jednotlivých kuchyní.\n"
],
"metadata": {
"id": "AaPubl__GmH5"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Count observations per cuisine\r\n",
"df %>% \r\n",
" count(cuisine) %>% \r\n",
" arrange(n)\r\n",
"\r\n",
"# Plot the distribution\r\n",
"theme_set(theme_light())\r\n",
"df %>% \r\n",
" count(cuisine) %>% \r\n",
" ggplot(mapping = aes(x = n, y = reorder(cuisine, -n))) +\r\n",
" geom_col(fill = \"midnightblue\", alpha = 0.7) +\r\n",
" ylab(\"cuisine\")"
],
"outputs": [],
"metadata": {
"id": "FRsBVy5eGrrv"
}
},
{
"cell_type": "markdown",
"source": [
"Existuje konečný počet kuchyní, ale rozložení dat je nerovnoměrné. To můžete napravit! Než tak učiníte, prozkoumejte to trochu více.\n",
"\n",
"Dále přiřaďme každou kuchyni do jejího vlastního tibble a zjistěme, kolik dat je k dispozici (řádky, sloupce) pro jednotlivé kuchyně.\n",
"\n",
"> [Tibble](https://tibble.tidyverse.org/) je moderní datový rámec.\n",
"\n",
"<p >\n",
" <img src=\"../../images/dplyr_filter.jpg\"\n",
" width=\"600\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n"
],
"metadata": {
"id": "vVvyDb1kG2in"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Create individual tibble for the cuisines\r\n",
"thai_df <- df %>% \r\n",
" filter(cuisine == \"thai\")\r\n",
"japanese_df <- df %>% \r\n",
" filter(cuisine == \"japanese\")\r\n",
"chinese_df <- df %>% \r\n",
" filter(cuisine == \"chinese\")\r\n",
"indian_df <- df %>% \r\n",
" filter(cuisine == \"indian\")\r\n",
"korean_df <- df %>% \r\n",
" filter(cuisine == \"korean\")\r\n",
"\r\n",
"\r\n",
"# Find out how much data is available per cuisine\r\n",
"cat(\" thai df:\", dim(thai_df), \"\\n\",\r\n",
" \"japanese df:\", dim(japanese_df), \"\\n\",\r\n",
" \"chinese_df:\", dim(chinese_df), \"\\n\",\r\n",
" \"indian_df:\", dim(indian_df), \"\\n\",\r\n",
" \"korean_df:\", dim(korean_df))"
],
"outputs": [],
"metadata": {
"id": "0TvXUxD3G8Bk"
}
},
{
"cell_type": "markdown",
"source": [
"## **Cvičení - Objevování nejlepších ingrediencí podle kuchyně pomocí dplyr**\n",
"\n",
"Nyní se můžete ponořit hlouběji do dat a zjistit, jaké jsou typické ingredience pro jednotlivé kuchyně. Měli byste odstranit opakující se data, která vytvářejí zmatek mezi kuchyněmi, takže se podíváme na tento problém.\n",
"\n",
"Vytvořte funkci `create_ingredient()` v R, která vrátí dataframe s ingrediencemi. Tato funkce začne odstraněním nepotřebného sloupce a seřadí ingredience podle jejich počtu.\n",
"\n",
"Základní struktura funkce v R vypadá takto:\n",
"\n",
"`myFunction <- function(arglist){`\n",
"\n",
"**`...`**\n",
"\n",
"**`return`**`(value)`\n",
"\n",
"`}`\n",
"\n",
"Přehledný úvod do funkcí v R najdete [zde](https://skirmer.github.io/presentations/functions_with_r.html#1).\n",
"\n",
"Pojďme na to! Využijeme [dplyr sloves](https://dplyr.tidyverse.org/), které jsme se učili v předchozích lekcích. Pro připomenutí:\n",
"\n",
"- `dplyr::select()`: pomáhá vám vybrat, které **sloupce** chcete ponechat nebo vyloučit.\n",
"\n",
"- `dplyr::pivot_longer()`: pomáhá \"prodloužit\" data, zvýšit počet řádků a snížit počet sloupců.\n",
"\n",
"- `dplyr::group_by()` a `dplyr::summarise()`: pomáhá najít souhrnné statistiky pro různé skupiny a uspořádat je do přehledné tabulky.\n",
"\n",
"- `dplyr::filter()`: vytváří podmnožinu dat obsahující pouze řádky, které splňují vaše podmínky.\n",
"\n",
"- `dplyr::mutate()`: pomáhá vytvořit nebo upravit sloupce.\n",
"\n",
"Podívejte se na tento [*uměním* naplněný learnr tutoriál](https://allisonhorst.shinyapps.io/dplyr-learnr/#section-welcome) od Allison Horst, který představuje některé užitečné funkce pro zpracování dat v dplyr *(součást Tidyverse)*.\n"
],
"metadata": {
"id": "K3RF5bSCHC76"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Creates a functions that returns the top ingredients by class\r\n",
"\r\n",
"create_ingredient <- function(df){\r\n",
" \r\n",
" # Drop the id column which is the first colum\r\n",
" ingredient_df = df %>% select(-1) %>% \r\n",
" # Transpose data to a long format\r\n",
" pivot_longer(!cuisine, names_to = \"ingredients\", values_to = \"count\") %>% \r\n",
" # Find the top most ingredients for a particular cuisine\r\n",
" group_by(ingredients) %>% \r\n",
" summarise(n_instances = sum(count)) %>% \r\n",
" filter(n_instances != 0) %>% \r\n",
" # Arrange by descending order\r\n",
" arrange(desc(n_instances)) %>% \r\n",
" mutate(ingredients = factor(ingredients) %>% fct_inorder())\r\n",
" \r\n",
" \r\n",
" return(ingredient_df)\r\n",
"} # End of function"
],
"outputs": [],
"metadata": {
"id": "uB_0JR82HTPa"
}
},
{
"cell_type": "markdown",
"source": [
"Nyní můžeme použít funkci, abychom získali představu o deseti nejoblíbenějších ingrediencích podle kuchyně. Pojďme si to vyzkoušet s `thai_df`.\n"
],
"metadata": {
"id": "h9794WF8HWmc"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Call create_ingredient and display popular ingredients\r\n",
"thai_ingredient_df <- create_ingredient(df = thai_df)\r\n",
"\r\n",
"thai_ingredient_df %>% \r\n",
" slice_head(n = 10)"
],
"outputs": [],
"metadata": {
"id": "agQ-1HrcHaEA"
}
},
{
"cell_type": "markdown",
"source": [
"V předchozí části jsme použili `geom_col()`, podívejme se, jak můžete použít také `geom_bar` k vytvoření sloupcových grafů. Použijte `?geom_bar` pro další čtení.\n"
],
"metadata": {
"id": "kHu9ffGjHdcX"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make a bar chart for popular thai cuisines\r\n",
"thai_ingredient_df %>% \r\n",
" slice_head(n = 10) %>% \r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"steelblue\") +\r\n",
" xlab(\"\") + ylab(\"\")"
],
"outputs": [],
"metadata": {
"id": "fb3Bx_3DHj6e"
}
},
{
"cell_type": "markdown",
"source": [
"Pojďme udělat totéž pro japonská data\n"
],
"metadata": {
"id": "RHP_xgdkHnvM"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Get popular ingredients for Japanese cuisines and make bar chart\r\n",
"create_ingredient(df = japanese_df) %>% \r\n",
" slice_head(n = 10) %>%\r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"darkorange\", alpha = 0.8) +\r\n",
" xlab(\"\") + ylab(\"\")\r\n"
],
"outputs": [],
"metadata": {
"id": "019v8F0XHrRU"
}
},
{
"cell_type": "markdown",
"source": [
"Co třeba čínská kuchyně?\n"
],
"metadata": {
"id": "iIGM7vO8Hu3v"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Get popular ingredients for Chinese cuisines and make bar chart\r\n",
"create_ingredient(df = chinese_df) %>% \r\n",
" slice_head(n = 10) %>%\r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"cyan4\", alpha = 0.8) +\r\n",
" xlab(\"\") + ylab(\"\")"
],
"outputs": [],
"metadata": {
"id": "lHd9_gd2HyzU"
}
},
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "ir8qyQbNH1c7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Get popular ingredients for Indian cuisines and make bar chart\r\n",
"create_ingredient(df = indian_df) %>% \r\n",
" slice_head(n = 10) %>%\r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"#041E42FF\", alpha = 0.8) +\r\n",
" xlab(\"\") + ylab(\"\")"
],
"outputs": [],
"metadata": {
"id": "ApukQtKjH5FO"
}
},
{
"cell_type": "markdown",
"source": [
"Nakonec vykreslete korejské ingredience.\n"
],
"metadata": {
"id": "qv30cwY1H-FM"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Get popular ingredients for Korean cuisines and make bar chart\r\n",
"create_ingredient(df = korean_df) %>% \r\n",
" slice_head(n = 10) %>%\r\n",
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
" geom_bar(stat = \"identity\", width = 0.5, fill = \"#852419FF\", alpha = 0.8) +\r\n",
" xlab(\"\") + ylab(\"\")"
],
"outputs": [],
"metadata": {
"id": "lumgk9cHIBie"
}
},
{
"cell_type": "markdown",
"source": [
"Z datových vizualizací nyní můžeme vyřadit nejběžnější ingredience, které způsobují záměnu mezi různými kuchyněmi, pomocí `dplyr::select()`.\n",
"\n",
"Každý miluje rýži, česnek a zázvor!\n"
],
"metadata": {
"id": "iO4veMXuIEta"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Drop id column, rice, garlic and ginger from our original data set\r\n",
"df_select <- df %>% \r\n",
" select(-c(1, rice, garlic, ginger))\r\n",
"\r\n",
"# Display new data set\r\n",
"df_select %>% \r\n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "iHJPiG6rIUcK"
}
},
{
"cell_type": "markdown",
"source": [
"## Předzpracování dat pomocí receptů 👩‍🍳👨‍🍳 - Práce s nevyváženými daty ⚖️\n",
"\n",
"<p >\n",
" <img src=\"../../images/recipes.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n",
"\n",
"Vzhledem k tomu, že tato lekce je o kuchyních, musíme dát `recepty` do kontextu.\n",
"\n",
"Tidymodels nabízí další šikovný balíček: `recipes` - balíček pro předzpracování dat.\n"
],
"metadata": {
"id": "kkFd-JxdIaL6"
}
},
{
"cell_type": "markdown",
"source": [
"Pojďme se znovu podívat na rozložení našich kuchyní.\n"
],
"metadata": {
"id": "6l2ubtTPJAhY"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Distribution of cuisines\r\n",
"old_label_count <- df_select %>% \r\n",
" count(cuisine) %>% \r\n",
" arrange(desc(n))\r\n",
"\r\n",
"old_label_count"
],
"outputs": [],
"metadata": {
"id": "1e-E9cb7JDVi"
}
},
{
"cell_type": "markdown",
"source": [
"Jak vidíte, počet kuchyní je značně nerovnoměrně rozložen. Korejské kuchyně jsou téměř třikrát početnější než thajské kuchyně. Nevyvážená data často negativně ovlivňují výkon modelu. Představte si binární klasifikaci. Pokud většina vašich dat patří do jedné třídy, model strojového učení bude tuto třídu předpovídat častěji, jednoduše proto, že pro ni má více dat. Vyvážení dat odstraňuje jakoukoli nerovnováhu v datech. Mnoho modelů dosahuje nejlepšího výkonu, když je počet pozorování stejný, a proto mají tendenci mít problémy s nevyváženými daty.\n",
"\n",
"Existují dvě hlavní metody, jak pracovat s nevyváženými datovými sadami:\n",
"\n",
"- přidání pozorování do minoritní třídy: `Over-sampling`, například použití algoritmu SMOTE\n",
"\n",
"- odstranění pozorování z majoritní třídy: `Under-sampling`\n",
"\n",
"Nyní si ukážeme, jak pracovat s nevyváženými datovými sadami pomocí `receptu`. Recept si můžete představit jako plán, který popisuje, jaké kroky by měly být aplikovány na datovou sadu, aby byla připravena pro analýzu dat.\n"
],
"metadata": {
"id": "soAw6826JKx9"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load themis package for dealing with imbalanced data\r\n",
"library(themis)\r\n",
"\r\n",
"# Create a recipe for preprocessing data\r\n",
"cuisines_recipe <- recipe(cuisine ~ ., data = df_select) %>% \r\n",
" step_smote(cuisine)\r\n",
"\r\n",
"cuisines_recipe"
],
"outputs": [],
"metadata": {
"id": "HS41brUIJVJy"
}
},
{
"cell_type": "markdown",
"source": [
"Pojďme si rozebrat kroky předzpracování.\n",
"\n",
"- Volání `recipe()` s formulí říká receptu *role* proměnných pomocí dat `df_select` jako referenčního bodu. Například sloupec `cuisine` byl přiřazen roli `outcome`, zatímco ostatní sloupce byly přiřazeny roli `predictor`.\n",
"\n",
"- [`step_smote(cuisine)`](https://themis.tidymodels.org/reference/step_smote.html) vytváří *specifikaci* kroku receptu, který synteticky generuje nové příklady minoritní třídy pomocí nejbližších sousedů těchto případů.\n",
"\n",
"Pokud bychom nyní chtěli vidět předzpracovaná data, museli bychom [**`prep()`**](https://recipes.tidymodels.org/reference/prep.html) a [**`bake()`**](https://recipes.tidymodels.org/reference/bake.html) náš recept.\n",
"\n",
"`prep()`: odhaduje potřebné parametry z trénovací sady, které mohou být později aplikovány na jiné datové sady.\n",
"\n",
"`bake()`: vezme připravený recept a aplikuje operace na jakoukoli datovou sadu.\n"
],
"metadata": {
"id": "Yb-7t7XcJaC8"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Prep and bake the recipe\r\n",
"preprocessed_df <- cuisines_recipe %>% \r\n",
" prep() %>% \r\n",
" bake(new_data = NULL) %>% \r\n",
" relocate(cuisine)\r\n",
"\r\n",
"# Display data\r\n",
"preprocessed_df %>% \r\n",
" slice_head(n = 5)\r\n",
"\r\n",
"# Quick summary stats\r\n",
"preprocessed_df %>% \r\n",
" introduce()"
],
"outputs": [],
"metadata": {
"id": "9QhSgdpxJl44"
}
},
{
"cell_type": "markdown",
"source": [
"Pojďme nyní zkontrolovat rozložení našich kuchyní a porovnat je s nevyváženými daty.\n"
],
"metadata": {
"id": "dmidELh_LdV7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Distribution of cuisines\r\n",
"new_label_count <- preprocessed_df %>% \r\n",
" count(cuisine) %>% \r\n",
" arrange(desc(n))\r\n",
"\r\n",
"list(new_label_count = new_label_count,\r\n",
" old_label_count = old_label_count)"
],
"outputs": [],
"metadata": {
"id": "aSh23klBLwDz"
}
},
{
"cell_type": "markdown",
"source": [
"Mňam! Data jsou pěkně čistá, vyvážená a velmi chutná 😋!\n",
"\n",
"> Obvykle se recept používá jako předzpracovatel pro modelování, kde definuje, jaké kroky by měly být aplikovány na datovou sadu, aby byla připravena pro modelování. V takovém případě se obvykle používá `workflow()` (jak jsme již viděli v našich předchozích lekcích) místo ručního odhadu receptu.\n",
">\n",
"> Proto obvykle nemusíte používat **`prep()`** a **`bake()`** recepty, když používáte tidymodels, ale jsou to užitečné funkce, které můžete mít ve své sadě nástrojů pro ověření, že recepty fungují podle vašich očekávání, jako v našem případě.\n",
">\n",
"> Když použijete **`bake()`** na připravený recept s **`new_data = NULL`**, získáte zpět data, která jste poskytli při definování receptu, ale prošla kroky předzpracování.\n",
"\n",
"Teď si uložíme kopii těchto dat pro použití v budoucích lekcích:\n"
],
"metadata": {
"id": "HEu80HZ8L7ae"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Save preprocessed data\r\n",
"write_csv(preprocessed_df, \"../../../data/cleaned_cuisines_R.csv\")"
],
"outputs": [],
"metadata": {
"id": "cBmCbIgrMOI6"
}
},
{
"cell_type": "markdown",
"source": [
"Tento nový CSV soubor nyní najdete v kořenové složce dat.\n",
"\n",
"**🚀Výzva**\n",
"\n",
"Tento kurz obsahuje několik zajímavých datových sad. Projděte složky `data` a zjistěte, zda některé obsahují datové sady vhodné pro binární nebo vícetřídní klasifikaci. Jaké otázky byste si k této datové sadě položili?\n",
"\n",
"## [**Kvíz po přednášce**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/20/)\n",
"\n",
"## **Opakování & Samostudium**\n",
"\n",
"- Podívejte se na [balíček themis](https://github.com/tidymodels/themis). Jaké další techniky bychom mohli použít k řešení problémů s nevyváženými daty?\n",
"\n",
"- Referenční web [Tidy models](https://www.tidymodels.org/start/).\n",
"\n",
"- H. Wickham a G. Grolemund, [*R for Data Science: Visualize, Model, Transform, Tidy, and Import Data*](https://r4ds.had.co.nz/).\n",
"\n",
"#### DĚKUJEME:\n",
"\n",
"[`Allison Horst`](https://twitter.com/allison_horst/) za vytvoření úžasných ilustrací, které činí R přívětivějším a poutavějším. Další ilustrace najdete v její [galerii](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n",
"\n",
"[Cassie Breviu](https://www.twitter.com/cassieview) a [Jen Looper](https://www.twitter.com/jenlooper) za vytvoření původní verze tohoto modulu v Pythonu ♥️\n",
"\n",
"<p >\n",
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
" width=\"600\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n"
],
"metadata": {
"id": "WQs5621pMGwf"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Upozornění**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,41 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "68829b06b4dcd512d3327849191f4d7f",
"translation_date": "2025-09-04T08:17:22+00:00",
"source_file": "4-Classification/2-Classifiers-1/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [
"Vytváření klasifikačních modelů\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Za autoritativní zdroj by měl být považován původní dokument v jeho původním jazyce. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,281 @@
{
"cells": [
{
"source": [
"# Vytváření klasifikačních modelů\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Unnamed: 0 cuisine almond angelica anise anise_seed apple \\\n",
"0 0 indian 0 0 0 0 0 \n",
"1 1 indian 1 0 0 0 0 \n",
"2 2 indian 0 0 0 0 0 \n",
"3 3 indian 0 0 0 0 0 \n",
"4 4 indian 0 0 0 0 0 \n",
"\n",
" apple_brandy apricot armagnac ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 382 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Unnamed: 0</th>\n <th>cuisine</th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>indian</td>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 382 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 1
}
],
"source": [
"import pandas as pd\n",
"cuisines_df = pd.read_csv(\"../../data/cleaned_cuisines.csv\")\n",
"cuisines_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.model_selection import train_test_split, cross_val_score\n",
"from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report, precision_recall_curve\n",
"from sklearn.svm import SVC\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"0 indian\n",
"1 indian\n",
"2 indian\n",
"3 indian\n",
"4 indian\n",
"Name: cuisine, dtype: object"
]
},
"metadata": {},
"execution_count": 3
}
],
"source": [
"cuisines_label_df = cuisines_df['cuisine']\n",
"cuisines_label_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" almond angelica anise anise_seed apple apple_brandy apricot \\\n",
"0 0 0 0 0 0 0 0 \n",
"1 1 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 0 0 \n",
"\n",
" armagnac artemisia artichoke ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 380 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>artemisia</th>\n <th>artichoke</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 380 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 4
}
],
"source": [
"cuisines_feature_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1)\n",
"cuisines_feature_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(cuisines_feature_df, cuisines_label_df, test_size=0.3)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Accuracy is 0.8181818181818182\n"
]
}
],
"source": [
"lr = LogisticRegression(multi_class='ovr',solver='liblinear')\n",
"model = lr.fit(X_train, np.ravel(y_train))\n",
"\n",
"accuracy = model.score(X_test, y_test)\n",
"print (\"Accuracy is {}\".format(accuracy))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"ingredients: Index(['artemisia', 'black_pepper', 'mushroom', 'shiitake', 'soy_sauce',\n 'vegetable_oil'],\n dtype='object')\ncuisine: korean\n"
]
}
],
"source": [
"# test an item\n",
"print(f'ingredients: {X_test.iloc[50][X_test.iloc[50]!=0].keys()}')\n",
"print(f'cuisine: {y_test.iloc[50]}')"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" 0\n",
"korean 0.392231\n",
"chinese 0.372872\n",
"japanese 0.218825\n",
"thai 0.013427\n",
"indian 0.002645"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>0</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>korean</th>\n <td>0.392231</td>\n </tr>\n <tr>\n <th>chinese</th>\n <td>0.372872</td>\n </tr>\n <tr>\n <th>japanese</th>\n <td>0.218825</td>\n </tr>\n <tr>\n <th>thai</th>\n <td>0.013427</td>\n </tr>\n <tr>\n <th>indian</th>\n <td>0.002645</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {},
"execution_count": 8
}
],
"source": [
"#rehsape to 2d array and transpose\n",
"test= X_test.iloc[50].values.reshape(-1, 1).T\n",
"# predict with score\n",
"proba = model.predict_proba(test)\n",
"classes = model.classes_\n",
"# create df with classes and scores\n",
"resultdf = pd.DataFrame(data=proba, columns=classes)\n",
"\n",
"# create df to show results\n",
"topPrediction = resultdf.T.sort_values(by=[0], ascending = [False])\n",
"topPrediction.head()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" precision recall f1-score support\n\n chinese 0.75 0.73 0.74 223\n indian 0.93 0.88 0.90 255\n japanese 0.78 0.78 0.78 253\n korean 0.87 0.86 0.86 236\n thai 0.76 0.84 0.80 232\n\n accuracy 0.82 1199\n macro avg 0.82 0.82 0.82 1199\nweighted avg 0.82 0.82 0.82 1199\n\n"
]
}
],
"source": [
"y_pred = model.predict(X_test)\r\n",
"print(classification_report(y_test,y_pred))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "9408506dd864f2b6e334c62f80c0cfcc",
"translation_date": "2025-09-04T08:18:06+00:00",
"source_file": "4-Classification/2-Classifiers-1/solution/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

@ -0,0 +1,163 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Unnamed: 0 cuisine almond angelica anise anise_seed apple \\\n",
"0 0 indian 0 0 0 0 0 \n",
"1 1 indian 1 0 0 0 0 \n",
"2 2 indian 0 0 0 0 0 \n",
"3 3 indian 0 0 0 0 0 \n",
"4 4 indian 0 0 0 0 0 \n",
"\n",
" apple_brandy apricot armagnac ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 382 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Unnamed: 0</th>\n <th>cuisine</th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>indian</td>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 382 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 9
}
],
"source": [
"import pandas as pd\n",
"cuisines_df = pd.read_csv(\"../data/cleaned_cuisines.csv\")\n",
"cuisines_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"0 indian\n",
"1 indian\n",
"2 indian\n",
"3 indian\n",
"4 indian\n",
"Name: cuisine, dtype: object"
]
},
"metadata": {},
"execution_count": 10
}
],
"source": [
"cuisines_label_df = cuisines_df['cuisine']\n",
"cuisines_label_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" almond angelica anise anise_seed apple apple_brandy apricot \\\n",
"0 0 0 0 0 0 0 0 \n",
"1 1 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 0 0 \n",
"\n",
" armagnac artemisia artichoke ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 380 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>artemisia</th>\n <th>artichoke</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 380 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 11
}
],
"source": [
"cuisines_feature_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1)\n",
"cuisines_feature_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "15a83277036572e0773229b5f21c1e12",
"translation_date": "2025-09-04T08:31:48+00:00",
"source_file": "4-Classification/3-Classifiers-2/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

@ -0,0 +1,650 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "lesson_12-R.ipynb",
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "fab50046ca413a38939d579f8432274f",
"translation_date": "2025-09-04T08:35:13+00:00",
"source_file": "4-Classification/3-Classifiers-2/solution/R/lesson_12-R.ipynb",
"language_code": "cs"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "jsFutf_ygqSx"
},
"source": [
"# Vytvořte klasifikační model: Lahodné asijské a indické kuchyně\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "HD54bEefgtNO"
},
"source": [
"## Klasifikátory kuchyní 2\n",
"\n",
"V této druhé lekci o klasifikaci se podíváme na `další způsoby`, jak klasifikovat kategorická data. Také se zaměříme na důsledky výběru jednoho klasifikátoru oproti jinému.\n",
"\n",
"### [**Kvíz před lekcí**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/23/)\n",
"\n",
"### **Předpoklady**\n",
"\n",
"Předpokládáme, že jste dokončili předchozí lekce, protože budeme navazovat na některé koncepty, které jsme se již naučili.\n",
"\n",
"Pro tuto lekci budeme potřebovat následující balíčky:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) je [kolekce balíčků pro R](https://www.tidyverse.org/packages), která usnadňuje, zrychluje a zpříjemňuje práci s datovou vědou!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) je rámec [kolekce balíčků](https://www.tidymodels.org/packages/) pro modelování a strojové učení.\n",
"\n",
"- `themis`: [balíček themis](https://themis.tidymodels.org/) poskytuje další kroky pro recepty, které řeší problém nevyvážených dat.\n",
"\n",
"Můžete je nainstalovat pomocí:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"kernlab\", \"themis\", \"ranger\", \"xgboost\", \"kknn\"))`\n",
"\n",
"Alternativně níže uvedený skript zkontroluje, zda máte balíčky potřebné k dokončení tohoto modulu, a v případě, že chybí, je nainstaluje.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "vZ57IuUxgyQt"
},
"source": [
"suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\n",
"\n",
"pacman::p_load(tidyverse, tidymodels, themis, kernlab, ranger, xgboost, kknn)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "z22M-pj4g07x"
},
"source": [
"## **1. Mapa klasifikace**\n",
"\n",
"V naší [předchozí lekci](https://github.com/microsoft/ML-For-Beginners/tree/main/4-Classification/2-Classifiers-1) jsme se snažili odpovědět na otázku: jak si vybrat mezi více modely? Do značné míry to závisí na charakteristikách dat a typu problému, který chceme řešit (například klasifikace nebo regrese?).\n",
"\n",
"Dříve jsme se seznámili s různými možnostmi, které máte při klasifikaci dat, pomocí přehledové tabulky od Microsoftu. Pythonův framework pro strojové učení, Scikit-learn, nabízí podobnou, ale podrobnější přehledovou tabulku, která vám může dále pomoci zúžit výběr odhadovačů (jiný termín pro klasifikátory):\n",
"\n",
"<p >\n",
" <img src=\"../../images/map.png\"\n",
" width=\"700\"/>\n",
" <figcaption></figcaption>\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "u1i3xRIVg7vG"
},
"source": [
"> Tip: [navštivte tuto mapu online](https://scikit-learn.org/stable/tutorial/machine_learning_map/) a klikněte na cestu, abyste si přečetli dokumentaci.\n",
">\n",
"> [Referenční stránka Tidymodels](https://www.tidymodels.org/find/parsnip/#models) také poskytuje vynikající dokumentaci o různých typech modelů.\n",
"\n",
"### **Plán** 🗺️\n",
"\n",
"Tato mapa je velmi užitečná, jakmile máte jasnou představu o svých datech, protože se můžete „procházet“ po jejích cestách k rozhodnutí:\n",
"\n",
"- Máme více než 50 vzorků\n",
"\n",
"- Chceme předpovědět kategorii\n",
"\n",
"- Máme označená data\n",
"\n",
"- Máme méně než 100 tisíc vzorků\n",
"\n",
"- ✨ Můžeme zvolit Linear SVC\n",
"\n",
"- Pokud to nefunguje, protože máme číselná data\n",
"\n",
" - Můžeme zkusit ✨ KNeighbors Classifier\n",
"\n",
" - Pokud to nefunguje, zkusíme ✨ SVC a ✨ Ensemble Classifiers\n",
"\n",
"Toto je velmi užitečná cesta, kterou se můžeme řídit. Teď se do toho pustíme pomocí [tidymodels](https://www.tidymodels.org/) frameworku pro modelování: konzistentní a flexibilní kolekce balíčků v R, vyvinutá pro podporu dobré statistické praxe 😊.\n",
"\n",
"## 2. Rozdělení dat a práce s nevyváženým datovým souborem.\n",
"\n",
"Z našich předchozích lekcí jsme se naučili, že existuje sada společných ingrediencí napříč našimi kuchyněmi. Také jsme zjistili, že rozložení počtu kuchyní bylo dost nerovnoměrné.\n",
"\n",
"S tím se vypořádáme takto:\n",
"\n",
"- Odstraníme nejběžnější ingredience, které vytvářejí zmatek mezi odlišnými kuchyněmi, pomocí `dplyr::select()`.\n",
"\n",
"- Použijeme `recipe`, který předzpracuje data, aby byla připravena pro modelování, aplikací algoritmu `over-sampling`.\n",
"\n",
"Toto jsme již probírali v předchozí lekci, takže to bude hračka 🥳!\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "6tj_rN00hClA"
},
"source": [
"# Load the core Tidyverse and Tidymodels packages\n",
"library(tidyverse)\n",
"library(tidymodels)\n",
"\n",
"# Load the original cuisines data\n",
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/4-Classification/data/cuisines.csv\")\n",
"\n",
"# Drop id column, rice, garlic and ginger from our original data set\n",
"df_select <- df %>% \n",
" select(-c(1, rice, garlic, ginger)) %>%\n",
" # Encode cuisine column as categorical\n",
" mutate(cuisine = factor(cuisine))\n",
"\n",
"\n",
"# Create data split specification\n",
"set.seed(2056)\n",
"cuisines_split <- initial_split(data = df_select,\n",
" strata = cuisine,\n",
" prop = 0.7)\n",
"\n",
"# Extract the data in each split\n",
"cuisines_train <- training(cuisines_split)\n",
"cuisines_test <- testing(cuisines_split)\n",
"\n",
"# Display distribution of cuisines in the training set\n",
"cuisines_train %>% \n",
" count(cuisine) %>% \n",
" arrange(desc(n))"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "zFin5yw3hHb1"
},
"source": [
"### Práce s nevyváženými daty\n",
"\n",
"Nevyvážená data často negativně ovlivňují výkon modelu. Mnoho modelů dosahuje nejlepších výsledků, když je počet pozorování vyrovnaný, a proto mají tendenci mít problémy s nevyváženými daty.\n",
"\n",
"Existují dvě hlavní metody, jak pracovat s nevyváženými datovými sadami:\n",
"\n",
"- přidání pozorování do menšinové třídy: `Over-sampling`, například použitím algoritmu SMOTE, který synteticky generuje nové příklady menšinové třídy na základě nejbližších sousedů těchto případů.\n",
"\n",
"- odstranění pozorování z většinové třídy: `Under-sampling`\n",
"\n",
"V naší předchozí lekci jsme ukázali, jak pracovat s nevyváženými datovými sadami pomocí `receptu`. Recept si můžeme představit jako plán, který popisuje, jaké kroky by měly být aplikovány na datovou sadu, aby byla připravena pro analýzu dat. V našem případě chceme dosáhnout rovnoměrného rozložení počtu našich kuchyní v `trénovací sadě`. Pojďme se do toho pustit.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "cRzTnHolhLWd"
},
"source": [
"# Load themis package for dealing with imbalanced data\n",
"library(themis)\n",
"\n",
"# Create a recipe for preprocessing training data\n",
"cuisines_recipe <- recipe(cuisine ~ ., data = cuisines_train) %>%\n",
" step_smote(cuisine) \n",
"\n",
"# Print recipe\n",
"cuisines_recipe"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "KxOQ2ORhhO81"
},
"source": [
"Teď jsme připraveni trénovat modely 👩‍💻👨‍💻!\n",
"\n",
"## 3. Nad rámec multinomiálních regresních modelů\n",
"\n",
"V naší předchozí lekci jsme se zabývali multinomiálními regresními modely. Pojďme prozkoumat některé flexibilnější modely pro klasifikaci.\n",
"\n",
"### Support Vector Machines\n",
"\n",
"V kontextu klasifikace je `Support Vector Machines` technika strojového učení, která se snaží najít *hyperrovinu*, která \"nejlépe\" odděluje třídy. Podívejme se na jednoduchý příklad:\n",
"\n",
"<p >\n",
" <img src=\"../../images/svm.png\"\n",
" width=\"300\"/>\n",
" <figcaption>https://commons.wikimedia.org/w/index.php?curid=22877598</figcaption>\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "C4Wsd0vZhXYu"
},
"source": [
"H1~ nerozděluje třídy. H2~ je rozděluje, ale pouze s malým okrajem. H3~ je rozděluje s maximálním okrajem.\n",
"\n",
"#### Lineární klasifikátor podpůrných vektorů\n",
"\n",
"Shlukování pomocí podpůrných vektorů (SVC) je součástí rodiny technik strojového učení založených na podpůrných vektorech. V SVC je hyperrovina zvolena tak, aby správně oddělila `většinu` tréninkových pozorování, ale `může nesprávně klasifikovat` několik pozorování. Tím, že umožníme některým bodům být na nesprávné straně, se SVM stává odolnějším vůči odlehlým hodnotám, což vede k lepší generalizaci na nová data. Parametr, který reguluje toto porušení, se nazývá `cost` a má výchozí hodnotu 1 (viz `help(\"svm_poly\")`).\n",
"\n",
"Vytvořme lineární SVC nastavením `degree = 1` v polynomiálním modelu SVM.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "vJpp6nuChlBz"
},
"source": [
"# Make a linear SVC specification\n",
"svc_linear_spec <- svm_poly(degree = 1) %>% \n",
" set_engine(\"kernlab\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle specification and recipe into a worklow\n",
"svc_linear_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(svc_linear_spec)\n",
"\n",
"# Print out workflow\n",
"svc_linear_wf"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "rDs8cWNkhoqu"
},
"source": [
"Nyní, když jsme zachytili kroky předzpracování a specifikaci modelu do *workflow*, můžeme pokračovat s trénováním lineárního SVC a zároveň vyhodnocovat výsledky. Pro metriky výkonu vytvořme sadu metrik, která bude hodnotit: `přesnost`, `citlivost`, `Pozitivní prediktivní hodnotu` a `F míru`.\n",
"\n",
"> `augment()` přidá sloupec/sloupce s predikcemi do daných dat.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "81wiqcwuhrnq"
},
"source": [
"# Train a linear SVC model\n",
"svc_linear_fit <- svc_linear_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"# Create a metric set\n",
"eval_metrics <- metric_set(ppv, sens, accuracy, f_meas)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"svc_linear_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "0UFQvHf-huo3"
},
"source": [
"#### Support Vector Machine\n",
"\n",
"Support Vector Machine (SVM) je rozšířením support vector classifier, které umožňuje zohlednit nelineární hranici mezi třídami. V podstatě SVM využívají *kernel trick* k rozšíření prostoru příznaků, aby se přizpůsobily nelineárním vztahům mezi třídami. Jednou z populárních a velmi flexibilních kernel funkcí používaných v SVM je *Radial basis function.* Podívejme se, jak si povede na našich datech.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "-KX4S8mzhzmp"
},
"source": [
"set.seed(2056)\n",
"\n",
"# Make an RBF SVM specification\n",
"svm_rbf_spec <- svm_rbf() %>% \n",
" set_engine(\"kernlab\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle specification and recipe into a worklow\n",
"svm_rbf_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(svm_rbf_spec)\n",
"\n",
"\n",
"# Train an RBF model\n",
"svm_rbf_fit <- svm_rbf_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"svm_rbf_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "QBFSa7WSh4HQ"
},
"source": [
"Mnohem lepší 🤩!\n",
"\n",
"> ✅ Podívejte se:\n",
">\n",
"> - [*Support Vector Machines*](https://bradleyboehmke.github.io/HOML/svm.html), Hands-on Machine Learning with R\n",
">\n",
"> - [*Support Vector Machines*](https://www.statlearning.com/), An Introduction to Statistical Learning with Applications in R\n",
">\n",
"> pro další čtení.\n",
"\n",
"### Klasifikátory nejbližšího souseda\n",
"\n",
"*K*-nejbližší soused (KNN) je algoritmus, ve kterém je každé pozorování předpovězeno na základě jeho *podobnosti* s ostatními pozorováními.\n",
"\n",
"Pojďme ho aplikovat na naše data.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "k4BxxBcdh9Ka"
},
"source": [
"# Make a KNN specification\n",
"knn_spec <- nearest_neighbor() %>% \n",
" set_engine(\"kknn\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle recipe and model specification into a workflow\n",
"knn_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(knn_spec)\n",
"\n",
"# Train a boosted tree model\n",
"knn_wf_fit <- knn_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"knn_wf_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "HaegQseriAcj"
},
"source": [
"Zdá se, že tento model nefunguje příliš dobře. Pravděpodobně změna parametrů modelu (viz `help(\"nearest_neighbor\")`) zlepší jeho výkon. Určitě to vyzkoušejte.\n",
"\n",
"> ✅ Podívejte se:\n",
">\n",
"> - [Hands-on Machine Learning with R](https://bradleyboehmke.github.io/HOML/)\n",
">\n",
"> - [An Introduction to Statistical Learning with Applications in R](https://www.statlearning.com/)\n",
">\n",
"> pro více informací o klasifikátorech *K*-Nearest Neighbors.\n",
"\n",
"### Ensemble klasifikátory\n",
"\n",
"Ensemble algoritmy fungují tak, že kombinují více základních odhadů, aby vytvořily optimální model buď:\n",
"\n",
"`bagging`: použitím *průměrovací funkce* na kolekci základních modelů\n",
"\n",
"`boosting`: vytvořením sekvence modelů, které na sebe navazují a zlepšují prediktivní výkon.\n",
"\n",
"Začněme tím, že vyzkoušíme model Random Forest, který vytváří velkou kolekci rozhodovacích stromů a poté aplikuje průměrovací funkci pro vytvoření lepšího celkového modelu.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "49DPoVs6iK1M"
},
"source": [
"# Make a random forest specification\n",
"rf_spec <- rand_forest() %>% \n",
" set_engine(\"ranger\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle recipe and model specification into a workflow\n",
"rf_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(rf_spec)\n",
"\n",
"# Train a random forest model\n",
"rf_wf_fit <- rf_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"rf_wf_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "RGVYwC_aiUWc"
},
"source": [
"Dobrá práce 👏!\n",
"\n",
"Pojďme také experimentovat s modelem Boosted Tree.\n",
"\n",
"Boosted Tree definuje ensemble metodu, která vytváří sérii sekvenčních rozhodovacích stromů, kde každý strom závisí na výsledcích předchozích stromů ve snaze postupně snižovat chybu. Zaměřuje se na váhy nesprávně klasifikovaných položek a upravuje přizpůsobení pro další klasifikátor, aby chybu napravil.\n",
"\n",
"Existují různé způsoby, jak tento model přizpůsobit (viz `help(\"boost_tree\")`). V tomto příkladu budeme přizpůsobovat Boosted trees pomocí enginu `xgboost`.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Py1YWo-micWs"
},
"source": [
"# Make a boosted tree specification\n",
"boost_spec <- boost_tree(trees = 200) %>% \n",
" set_engine(\"xgboost\") %>% \n",
" set_mode(\"classification\")\n",
"\n",
"# Bundle recipe and model specification into a workflow\n",
"boost_wf <- workflow() %>% \n",
" add_recipe(cuisines_recipe) %>% \n",
" add_model(boost_spec)\n",
"\n",
"# Train a boosted tree model\n",
"boost_wf_fit <- boost_wf %>% \n",
" fit(data = cuisines_train)\n",
"\n",
"\n",
"# Make predictions and Evaluate model performance\n",
"boost_wf_fit %>% \n",
" augment(new_data = cuisines_test) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "zNQnbuejigZM"
},
"source": [
"> ✅ Podívejte se:\n",
">\n",
"> - [Machine Learning for Social Scientists](https://cimentadaj.github.io/ml_socsci/tree-based-methods.html#random-forests)\n",
">\n",
"> - [Hands-on Machine Learning with R](https://bradleyboehmke.github.io/HOML/)\n",
">\n",
"> - [An Introduction to Statistical Learning with Applications in R](https://www.statlearning.com/)\n",
">\n",
"> - <https://algotech.netlify.app/blog/xgboost/> - Zkoumá model AdaBoost, který je dobrou alternativou k xgboost.\n",
">\n",
"> pro více informací o Ensemble klasifikátorech.\n",
"\n",
"## 4. Extra - porovnání více modelů\n",
"\n",
"V tomto cvičení jsme vytvořili poměrně velké množství modelů 🙌. Může být únavné nebo zdlouhavé vytvářet mnoho workflowů z různých sad předzpracování a/nebo specifikací modelů a poté jeden po druhém počítat metriky výkonu.\n",
"\n",
"Podívejme se, zda to můžeme vyřešit vytvořením funkce, která aplikuje seznam workflowů na trénovací sadu a poté vrátí metriky výkonu na základě testovací sady. Použijeme `map()` a `map_dfr()` z balíčku [purrr](https://purrr.tidyverse.org/) k aplikaci funkcí na každý prvek seznamu.\n",
"\n",
"> Funkce [`map()`](https://purrr.tidyverse.org/reference/map.html) vám umožňují nahradit mnoho for smyček kódem, který je stručnější a snadněji čitelný. Nejlepší místo, kde se naučit o funkcích [`map()`](https://purrr.tidyverse.org/reference/map.html), je [kapitola o iteraci](http://r4ds.had.co.nz/iteration.html) v R for data science.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Qzb7LyZnimd2"
},
"source": [
"set.seed(2056)\n",
"\n",
"# Create a metric set\n",
"eval_metrics <- metric_set(ppv, sens, accuracy, f_meas)\n",
"\n",
"# Define a function that returns performance metrics\n",
"compare_models <- function(workflow_list, train_set, test_set){\n",
" \n",
" suppressWarnings(\n",
" # Fit each model to the train_set\n",
" map(workflow_list, fit, data = train_set) %>% \n",
" # Make predictions on the test set\n",
" map_dfr(augment, new_data = test_set, .id = \"model\") %>%\n",
" # Select desired columns\n",
" select(model, cuisine, .pred_class) %>% \n",
" # Evaluate model performance\n",
" group_by(model) %>% \n",
" eval_metrics(truth = cuisine, estimate = .pred_class) %>% \n",
" ungroup()\n",
" )\n",
" \n",
"} # End of function"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "Fwa712sNisDA"
},
"source": []
},
{
"cell_type": "code",
"metadata": {
"id": "3i4VJOi2iu-a"
},
"source": [
"# Make a list of workflows\n",
"workflow_list <- list(\n",
" \"svc\" = svc_linear_wf,\n",
" \"svm\" = svm_rbf_wf,\n",
" \"knn\" = knn_wf,\n",
" \"random_forest\" = rf_wf,\n",
" \"xgboost\" = boost_wf)\n",
"\n",
"# Call the function\n",
"set.seed(2056)\n",
"perf_metrics <- compare_models(workflow_list = workflow_list, train_set = cuisines_train, test_set = cuisines_test)\n",
"\n",
"# Print out performance metrics\n",
"perf_metrics %>% \n",
" group_by(.metric) %>% \n",
" arrange(desc(.estimate)) %>% \n",
" slice_head(n=7)\n",
"\n",
"# Compare accuracy\n",
"perf_metrics %>% \n",
" filter(.metric == \"accuracy\") %>% \n",
" arrange(desc(.estimate))\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "KuWK_lEli4nW"
},
"source": [
"[**workflowset**](https://workflowsets.tidymodels.org/) balíček umožňuje uživatelům vytvářet a snadno aplikovat velké množství modelů, ale je primárně navržen pro práci s technikami resamplingu, jako je `cross-validation`, přístup, který teprve budeme probírat.\n",
"\n",
"## **🚀Výzva**\n",
"\n",
"Každá z těchto technik má velké množství parametrů, které můžete upravovat, například `cost` u SVM, `neighbors` u KNN, `mtry` (náhodně vybraní prediktory) u Random Forest.\n",
"\n",
"Prozkoumejte výchozí parametry každého z nich a zamyslete se nad tím, co by úprava těchto parametrů znamenala pro kvalitu modelu.\n",
"\n",
"Chcete-li zjistit více o konkrétním modelu a jeho parametrech, použijte: `help(\"model\")`, například `help(\"rand_forest\")`.\n",
"\n",
"> V praxi obvykle *odhadujeme* *nejlepší hodnoty* těchto parametrů tím, že trénujeme mnoho modelů na `simulovaném datovém souboru` a měříme, jak dobře všechny tyto modely fungují. Tento proces se nazývá **ladění**.\n",
"\n",
"### [**Kvíz po přednášce**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/24/)\n",
"\n",
"### **Přehled & Samostudium**\n",
"\n",
"V těchto lekcích je hodně odborných termínů, takže si udělejte chvíli na přezkoumání [tohoto seznamu](https://docs.microsoft.com/dotnet/machine-learning/resources/glossary?WT.mc_id=academic-77952-leestott) užitečné terminologie!\n",
"\n",
"#### DĚKUJEME:\n",
"\n",
"[`Allison Horst`](https://twitter.com/allison_horst/) za vytvoření úžasných ilustrací, které činí R přívětivějším a poutavějším. Další ilustrace najdete v její [galerii](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n",
"\n",
"[Cassie Breviu](https://www.twitter.com/cassieview) a [Jen Looper](https://www.twitter.com/jenlooper) za vytvoření původní verze tohoto modulu v Pythonu ♥️\n",
"\n",
"Šťastné učení,\n",
"\n",
"[Eric](https://twitter.com/ericntay), Zlatý ambasador Microsoft Learn Student.\n",
"\n",
"<p >\n",
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
" width=\"569\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Upozornění**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,302 @@
{
"cells": [
{
"source": [],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Unnamed: 0 cuisine almond angelica anise anise_seed apple \\\n",
"0 0 indian 0 0 0 0 0 \n",
"1 1 indian 1 0 0 0 0 \n",
"2 2 indian 0 0 0 0 0 \n",
"3 3 indian 0 0 0 0 0 \n",
"4 4 indian 0 0 0 0 0 \n",
"\n",
" apple_brandy apricot armagnac ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 382 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Unnamed: 0</th>\n <th>cuisine</th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>indian</td>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 382 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 1
}
],
"source": [
"import pandas as pd\n",
"cuisines_df = pd.read_csv(\"../../data/cleaned_cuisines.csv\")\n",
"cuisines_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"0 indian\n",
"1 indian\n",
"2 indian\n",
"3 indian\n",
"4 indian\n",
"Name: cuisine, dtype: object"
]
},
"metadata": {},
"execution_count": 2
}
],
"source": [
"cuisines_label_df = cuisines_df['cuisine']\n",
"cuisines_label_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" almond angelica anise anise_seed apple apple_brandy apricot \\\n",
"0 0 0 0 0 0 0 0 \n",
"1 1 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 0 0 \n",
"\n",
" armagnac artemisia artichoke ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 380 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>artemisia</th>\n <th>artichoke</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 380 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 3
}
],
"source": [
"cuisines_feature_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1)\n",
"cuisines_feature_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Vyzkoušejte různé klasifikátory\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.neighbors import KNeighborsClassifier\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.svm import SVC\n",
"from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier\n",
"from sklearn.model_selection import train_test_split, cross_val_score\n",
"from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report, precision_recall_curve\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(cuisines_feature_df, cuisines_label_df, test_size=0.3)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"\n",
"C = 10\n",
"# Create different classifiers.\n",
"classifiers = {\n",
" 'Linear SVC': SVC(kernel='linear', C=C, probability=True,random_state=0),\n",
" 'KNN classifier': KNeighborsClassifier(C),\n",
" 'SVC': SVC(),\n",
" 'RFST': RandomForestClassifier(n_estimators=100),\n",
" 'ADA': AdaBoostClassifier(n_estimators=100)\n",
" \n",
"}\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Accuracy (train) for Linear SVC: 76.4% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.64 0.66 0.65 242\n",
" indian 0.91 0.86 0.89 236\n",
" japanese 0.72 0.73 0.73 245\n",
" korean 0.83 0.75 0.79 234\n",
" thai 0.75 0.82 0.78 242\n",
"\n",
" accuracy 0.76 1199\n",
" macro avg 0.77 0.76 0.77 1199\n",
"weighted avg 0.77 0.76 0.77 1199\n",
"\n",
"Accuracy (train) for KNN classifier: 70.7% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.65 0.63 0.64 242\n",
" indian 0.84 0.81 0.82 236\n",
" japanese 0.60 0.81 0.69 245\n",
" korean 0.89 0.53 0.67 234\n",
" thai 0.69 0.75 0.72 242\n",
"\n",
" accuracy 0.71 1199\n",
" macro avg 0.73 0.71 0.71 1199\n",
"weighted avg 0.73 0.71 0.71 1199\n",
"\n",
"Accuracy (train) for SVC: 80.1% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.71 0.69 0.70 242\n",
" indian 0.92 0.92 0.92 236\n",
" japanese 0.77 0.78 0.77 245\n",
" korean 0.87 0.77 0.82 234\n",
" thai 0.75 0.86 0.80 242\n",
"\n",
" accuracy 0.80 1199\n",
" macro avg 0.80 0.80 0.80 1199\n",
"weighted avg 0.80 0.80 0.80 1199\n",
"\n",
"Accuracy (train) for RFST: 82.8% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.80 0.75 0.77 242\n",
" indian 0.90 0.91 0.90 236\n",
" japanese 0.82 0.78 0.80 245\n",
" korean 0.85 0.82 0.83 234\n",
" thai 0.78 0.89 0.83 242\n",
"\n",
" accuracy 0.83 1199\n",
" macro avg 0.83 0.83 0.83 1199\n",
"weighted avg 0.83 0.83 0.83 1199\n",
"\n",
"Accuracy (train) for ADA: 71.1% \n",
" precision recall f1-score support\n",
"\n",
" chinese 0.60 0.57 0.58 242\n",
" indian 0.87 0.84 0.86 236\n",
" japanese 0.71 0.60 0.65 245\n",
" korean 0.68 0.78 0.72 234\n",
" thai 0.70 0.78 0.74 242\n",
"\n",
" accuracy 0.71 1199\n",
" macro avg 0.71 0.71 0.71 1199\n",
"weighted avg 0.71 0.71 0.71 1199\n",
"\n"
]
}
],
"source": [
"n_classifiers = len(classifiers)\n",
"\n",
"for index, (name, classifier) in enumerate(classifiers.items()):\n",
" classifier.fit(X_train, np.ravel(y_train))\n",
"\n",
" y_pred = classifier.predict(X_test)\n",
" accuracy = accuracy_score(y_test, y_pred)\n",
" print(\"Accuracy (train) for %s: %0.1f%% \" % (name, accuracy * 100))\n",
" print(classification_report(y_test,y_pred))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "7ea2b714669c823a596d986ba2d5739f",
"translation_date": "2025-09-04T08:32:29+00:00",
"source_file": "4-Classification/3-Classifiers-2/solution/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

@ -0,0 +1,39 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "2f3e0d9e9ac5c301558fb8bf733ac0cb",
"translation_date": "2025-09-04T08:30:32+00:00",
"source_file": "4-Classification/4-Applied/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o přesnost, mějte na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace se doporučuje profesionální lidský překlad. Neodpovídáme za žádné nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,290 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"coopTranslator": {
"original_hash": "49325d6dd12a3628fc64fa7ccb1a80ff",
"translation_date": "2025-09-04T08:31:08+00:00",
"source_file": "4-Classification/4-Applied/solution/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Requirement already satisfied: skl2onnx in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (1.8.0)\n",
"Requirement already satisfied: protobuf in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (3.8.0)\n",
"Requirement already satisfied: numpy>=1.15 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (1.19.2)\n",
"Requirement already satisfied: onnx>=1.2.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (1.9.0)\n",
"Requirement already satisfied: six in /Users/jenlooper/Library/Python/3.7/lib/python/site-packages (from skl2onnx) (1.12.0)\n",
"Requirement already satisfied: onnxconverter-common<1.9,>=1.6.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (1.8.1)\n",
"Requirement already satisfied: scikit-learn>=0.19 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (0.24.2)\n",
"Requirement already satisfied: scipy>=1.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from skl2onnx) (1.4.1)\n",
"Requirement already satisfied: setuptools in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from protobuf->skl2onnx) (45.1.0)\n",
"Requirement already satisfied: typing-extensions>=3.6.2.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from onnx>=1.2.1->skl2onnx) (3.10.0.0)\n",
"Requirement already satisfied: threadpoolctl>=2.0.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from scikit-learn>=0.19->skl2onnx) (2.1.0)\n",
"Requirement already satisfied: joblib>=0.11 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from scikit-learn>=0.19->skl2onnx) (0.16.0)\n",
"\u001b[33mWARNING: You are using pip version 20.2.3; however, version 21.1.2 is available.\n",
"You should consider upgrading via the '/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7 -m pip install --upgrade pip' command.\u001b[0m\n",
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"!pip install skl2onnx"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd \n"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" Unnamed: 0 cuisine almond angelica anise anise_seed apple \\\n",
"0 0 indian 0 0 0 0 0 \n",
"1 1 indian 1 0 0 0 0 \n",
"2 2 indian 0 0 0 0 0 \n",
"3 3 indian 0 0 0 0 0 \n",
"4 4 indian 0 0 0 0 0 \n",
"\n",
" apple_brandy apricot armagnac ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 382 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Unnamed: 0</th>\n <th>cuisine</th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>indian</td>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4</td>\n <td>indian</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 382 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 60
}
],
"source": [
"data = pd.read_csv('../../data/cleaned_cuisines.csv')\n",
"data.head()"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" almond angelica anise anise_seed apple apple_brandy apricot \\\n",
"0 0 0 0 0 0 0 0 \n",
"1 1 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 0 0 \n",
"\n",
" armagnac artemisia artichoke ... whiskey white_bread white_wine \\\n",
"0 0 0 0 ... 0 0 0 \n",
"1 0 0 0 ... 0 0 0 \n",
"2 0 0 0 ... 0 0 0 \n",
"3 0 0 0 ... 0 0 0 \n",
"4 0 0 0 ... 0 0 0 \n",
"\n",
" whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n",
"0 0 0 0 0 0 0 0 \n",
"1 0 0 0 0 0 0 0 \n",
"2 0 0 0 0 0 0 0 \n",
"3 0 0 0 0 0 0 0 \n",
"4 0 0 0 0 0 1 0 \n",
"\n",
"[5 rows x 380 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>almond</th>\n <th>angelica</th>\n <th>anise</th>\n <th>anise_seed</th>\n <th>apple</th>\n <th>apple_brandy</th>\n <th>apricot</th>\n <th>armagnac</th>\n <th>artemisia</th>\n <th>artichoke</th>\n <th>...</th>\n <th>whiskey</th>\n <th>white_bread</th>\n <th>white_wine</th>\n <th>whole_grain_wheat_flour</th>\n <th>wine</th>\n <th>wood</th>\n <th>yam</th>\n <th>yeast</th>\n <th>yogurt</th>\n <th>zucchini</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>...</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>0</td>\n <td>1</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n<p>5 rows × 380 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 61
}
],
"source": [
"X = data.iloc[:,2:]\n",
"X.head()"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" cuisine\n",
"0 indian\n",
"1 indian\n",
"2 indian\n",
"3 indian\n",
"4 indian"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>cuisine</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>indian</td>\n </tr>\n <tr>\n <th>1</th>\n <td>indian</td>\n </tr>\n <tr>\n <th>2</th>\n <td>indian</td>\n </tr>\n <tr>\n <th>3</th>\n <td>indian</td>\n </tr>\n <tr>\n <th>4</th>\n <td>indian</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {},
"execution_count": 62
}
],
"source": [
"y = data[['cuisine']]\n",
"y.head()"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split\n",
"from sklearn.svm import SVC\n",
"from sklearn.model_selection import cross_val_score\n",
"from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3)"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"SVC(C=10, kernel='linear', probability=True, random_state=0)"
]
},
"metadata": {},
"execution_count": 65
}
],
"source": [
"model = SVC(kernel='linear', C=10, probability=True,random_state=0)\n",
"model.fit(X_train,y_train.values.ravel())\n"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [],
"source": [
"y_pred = model.predict(X_test)"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" precision recall f1-score support\n\n chinese 0.72 0.70 0.71 236\n indian 0.91 0.88 0.89 243\n japanese 0.80 0.75 0.77 240\n korean 0.80 0.81 0.81 230\n thai 0.76 0.85 0.80 250\n\n accuracy 0.80 1199\n macro avg 0.80 0.80 0.80 1199\nweighted avg 0.80 0.80 0.80 1199\n\n"
]
}
],
"source": [
"print(classification_report(y_test,y_pred))"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [],
"source": [
"from skl2onnx import convert_sklearn\n",
"from skl2onnx.common.data_types import FloatTensorType\n",
"\n",
"initial_type = [('float_input', FloatTensorType([None, 380]))]\n",
"options = {id(model): {'nocl': True, 'zipmap': False}}\n",
"onx = convert_sklearn(model, initial_types=initial_type, options=options)\n",
"with open(\"./model.onnx\", \"wb\") as f:\n",
" f.write(onx.SerializeToString())\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,50 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python383jvsc74a57bd0e134e05457d34029b6460cd73bbf1ed73f339b5b6d98c95be70b69eba114fe95",
"display_name": "Python 3.8.3 64-bit (conda)"
},
"coopTranslator": {
"original_hash": "40e0707e96b3e1899a912776006264f9",
"translation_date": "2025-09-04T07:41:57+00:00",
"source_file": "5-Clustering/1-Visualize/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Upozornění**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,500 @@
{
"cells": [
{
"cell_type": "markdown",
"source": [
"## **Nigerijská hudba získaná ze Spotify - analýza**\n",
"\n",
"Clustering je typ [neřízeného učení](https://wikipedia.org/wiki/Unsupervised_learning), který předpokládá, že dataset není označený nebo že jeho vstupy nejsou spárovány s předem definovanými výstupy. Používá různé algoritmy k třídění neoznačených dat a poskytuje skupiny podle vzorců, které v datech rozpozná.\n",
"\n",
"[**Kvíz před přednáškou**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/27/)\n",
"\n",
"### **Úvod**\n",
"\n",
"[Clustering](https://link.springer.com/referenceworkentry/10.1007%2F978-0-387-30164-8_124) je velmi užitečný pro průzkum dat. Podívejme se, zda nám může pomoci objevit trendy a vzorce ve způsobu, jakým nigerijské publikum konzumuje hudbu.\n",
"\n",
"> ✅ Udělejte si chvíli na zamyšlení nad využitím clusteringu. V reálném životě clustering probíhá například tehdy, když máte hromadu prádla a potřebujete roztřídit oblečení jednotlivých členů rodiny 🧦👕👖🩲. V datové vědě clustering probíhá při analýze preferencí uživatelů nebo při určování charakteristik jakéhokoli neoznačeného datasetu. Clustering tak trochu pomáhá dát chaosu smysl, jako třeba šuplíku na ponožky.\n",
"\n",
"V profesionálním prostředí může být clustering použit například k určení segmentace trhu, k zjištění, jaké věkové skupiny kupují jaké produkty. Dalším využitím může být detekce anomálií, například odhalování podvodů v datasetu transakcí kreditních karet. Nebo můžete clustering použít k určení nádorů v dávce lékařských skenů.\n",
"\n",
"✅ Zamyslete se chvíli nad tím, jak jste se mohli setkat s clusteringem „v divočině“, například v bankovnictví, e-commerce nebo obchodním prostředí.\n",
"\n",
"> 🎓 Zajímavé je, že analýza clusterů vznikla v oborech antropologie a psychologie ve 30. letech 20. století. Dokážete si představit, jak mohla být použita?\n",
"\n",
"Alternativně ji můžete použít ke skupinování výsledků vyhledávání například podle nákupních odkazů, obrázků nebo recenzí. Clustering je užitečný, když máte velký dataset, který chcete zmenšit a na kterém chcete provést podrobnější analýzu, takže tato technika může být použita k poznání dat před vytvořením dalších modelů.\n",
"\n",
"✅ Jakmile jsou vaše data organizována do clusterů, přiřadíte jim ID clusteru, což může být užitečné při zachování soukromí datasetu; místo odkazování na konkrétní data můžete použít ID clusteru. Dokážete si představit další důvody, proč byste odkazovali na ID clusteru místo na jiné prvky clusteru?\n",
"\n",
"### Začínáme s clusteringem\n",
"\n",
"> 🎓 Jak vytváříme clustery, hodně závisí na tom, jak shromažďujeme datové body do skupin. Pojďme si rozebrat některé pojmy:\n",
">\n",
"> 🎓 ['Transduktivní' vs. 'induktivní'](https://wikipedia.org/wiki/Transduction_(machine_learning))\n",
">\n",
"> Transduktivní inference je odvozena z pozorovaných tréninkových případů, které se mapují na konkrétní testovací případy. Induktivní inference je odvozena z tréninkových případů, které se mapují na obecná pravidla, která jsou teprve poté aplikována na testovací případy.\n",
">\n",
"> Příklad: Představte si, že máte dataset, který je pouze částečně označený. Některé věci jsou „desky“, některé „CD“ a některé jsou prázdné. Vaším úkolem je poskytnout štítky pro prázdné položky. Pokud zvolíte induktivní přístup, vytrénujete model hledající „desky“ a „CD“ a aplikujete tyto štítky na neoznačená data. Tento přístup bude mít problém klasifikovat věci, které jsou ve skutečnosti „kazety“. Transduktivní přístup naopak zvládá tato neznámá data efektivněji, protože pracuje na seskupení podobných položek dohromady a poté aplikuje štítek na skupinu. V tomto případě mohou clustery odrážet „kulaté hudební věci“ a „čtvercové hudební věci“.\n",
">\n",
"> 🎓 ['Neplochá' vs. 'plochá' geometrie](https://datascience.stackexchange.com/questions/52260/terminology-flat-geometry-in-the-context-of-clustering)\n",
">\n",
"> Odvozeno z matematické terminologie, neplochá vs. plochá geometrie se týká měření vzdáleností mezi body buď „plochými“ ([Euklidovskými](https://wikipedia.org/wiki/Euclidean_geometry)) nebo „neplochými“ (ne-Euklidovskými) geometrickými metodami.\n",
">\n",
"> „Plochá“ v tomto kontextu odkazuje na Euklidovskou geometrii (části z ní se učí jako „rovinná“ geometrie) a neplochá odkazuje na ne-Euklidovskou geometrii. Co má geometrie společného s machine learningem? Jako dvě oblasti, které jsou zakořeněné v matematice, musí existovat společný způsob měření vzdáleností mezi body v clusterech, a to může být provedeno „plochým“ nebo „neplochým“ způsobem, v závislosti na povaze dat. [Euklidovské vzdálenosti](https://wikipedia.org/wiki/Euclidean_distance) se měří jako délka úsečky mezi dvěma body. [Ne-Euklidovské vzdálenosti](https://wikipedia.org/wiki/Non-Euclidean_geometry) se měří podél křivky. Pokud vaše data, vizualizovaná, nevypadají, že existují na rovině, možná budete potřebovat použít specializovaný algoritmus k jejich zpracování.\n",
"\n",
"<p >\n",
" <img src=\"../../images/flat-nonflat.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Infografika od Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"\n",
"> 🎓 ['Vzdálenosti'](https://web.stanford.edu/class/cs345a/slides/12-clustering.pdf)\n",
">\n",
"> Clustery jsou definovány svou maticí vzdáleností, tj. vzdálenostmi mezi body. Tato vzdálenost může být měřena několika způsoby. Euklidovské clustery jsou definovány průměrem hodnot bodů a obsahují „centroid“ neboli středový bod. Vzdálenosti jsou tedy měřeny podle vzdálenosti k tomuto centroidu. Ne-Euklidovské vzdálenosti odkazují na „clustroidy“, bod nejbližší ostatním bodům. Clustroidy mohou být definovány různými způsoby.\n",
">\n",
"> 🎓 ['Omezený'](https://wikipedia.org/wiki/Constrained_clustering)\n",
">\n",
"> [Omezený clustering](https://web.cs.ucdavis.edu/~davidson/Publications/ICDMTutorial.pdf) zavádí „polořízené“ učení do této neřízené metody. Vztahy mezi body jsou označeny jako „nelze propojit“ nebo „musí být propojeno“, takže na dataset jsou vynucena určitá pravidla.\n",
">\n",
"> Příklad: Pokud je algoritmus volně spuštěn na dávce neoznačených nebo polo-označených dat, clustery, které vytvoří, mohou být nekvalitní. V příkladu výše mohou clustery seskupovat „kulaté hudební věci“, „čtvercové hudební věci“, „trojúhelníkové věci“ a „sušenky“. Pokud jsou algoritmu dány určité omezení nebo pravidla („položka musí být vyrobena z plastu“, „položka musí být schopna produkovat hudbu“), může to pomoci „omezit“ algoritmus, aby dělal lepší volby.\n",
">\n",
"> 🎓 'Hustota'\n",
">\n",
"> Data, která jsou „šumová“, jsou považována za „hustá“. Vzdálenosti mezi body v každém z jeho clusterů mohou být při zkoumání více či méně husté, nebo „přeplněné“, a proto je třeba tato data analyzovat pomocí vhodné metody clusteringu. [Tento článek](https://www.kdnuggets.com/2020/02/understanding-density-based-clustering.html) ukazuje rozdíl mezi použitím K-Means clusteringu a HDBSCAN algoritmů při zkoumání šumového datasetu s nerovnoměrnou hustotou clusterů.\n",
"\n",
"Prohlubte své znalosti technik clusteringu v tomto [výukovém modulu](https://docs.microsoft.com/learn/modules/train-evaluate-cluster-models?WT.mc_id=academic-77952-leestott)\n",
"\n",
"### **Algoritmy clusteringu**\n",
"\n",
"Existuje více než 100 algoritmů clusteringu a jejich použití závisí na povaze dat. Pojďme si probrat některé hlavní:\n",
"\n",
"- **Hierarchický clustering**. Pokud je objekt klasifikován podle své blízkosti k jinému objektu, spíše než k vzdálenějšímu, clustery se tvoří na základě vzdálenosti jejich členů k ostatním objektům. Hierarchický clustering se vyznačuje opakovaným kombinováním dvou clusterů.\n",
"\n",
"\n",
"<p >\n",
" <img src=\"../../images/hierarchical.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Infografika od Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"\n",
"- **Centroid clustering**. Tento populární algoritmus vyžaduje volbu „k“, tedy počet clusterů, které se mají vytvořit, po čemž algoritmus určí středový bod clusteru a shromáždí data kolem tohoto bodu. [K-means clustering](https://wikipedia.org/wiki/K-means_clustering) je populární verze centroid clusteringu, která rozděluje dataset do předem definovaných K skupin. Střed je určen podle nejbližšího průměru, odtud název. Čtvercová vzdálenost od clusteru je minimalizována.\n",
"\n",
"<p >\n",
" <img src=\"../../images/centroid.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Infografika od Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"\n",
"- **Clustering založený na distribuci**. Založený na statistickém modelování, clustering založený na distribuci se zaměřuje na určení pravděpodobnosti, že datový bod patří do clusteru, a jeho následné přiřazení. Metody Gaussovské směsi patří do tohoto typu.\n",
"\n",
"- **Clustering založený na hustotě**. Datové body jsou přiřazeny do clusterů na základě jejich hustoty, tedy jejich seskupení kolem sebe. Datové body vzdálené od skupiny jsou považovány za odlehlé body nebo šum. DBSCAN, Mean-shift a OPTICS patří do tohoto typu clusteringu.\n",
"\n",
"- **Clustering založený na mřížce**. Pro vícerozměrné datasety je vytvořena mřížka a data jsou rozdělena mezi buňky mřížky, čímž se vytvářejí clustery.\n",
"\n",
"Nejlepší způsob, jak se naučit clustering, je vyzkoušet si ho sami, což uděláte v tomto cvičení.\n",
"\n",
"Budeme potřebovat některé balíčky, abychom mohli dokončit tento modul. Můžete je nainstalovat pomocí: `install.packages(c('tidyverse', 'tidymodels', 'DataExplorer', 'summarytools', 'plotly', 'paletteer', 'corrplot', 'patchwork'))`\n",
"\n",
"Alternativně níže uvedený skript zkontroluje, zda máte balíčky potřebné k dokončení tohoto modulu, a nainstaluje je za vás, pokud některé chybí.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\r\n",
"\r\n",
"pacman::p_load('tidyverse', 'tidymodels', 'DataExplorer', 'summarytools', 'plotly', 'paletteer', 'corrplot', 'patchwork')\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"## Cvičení - seskupte svá data\n",
"\n",
"Shlukování jako technika je výrazně usnadněno správnou vizualizací, takže začněme vizualizací našich hudebních dat. Toto cvičení nám pomůže rozhodnout, kterou z metod shlukování bychom měli nejefektivněji použít pro povahu těchto dat.\n",
"\n",
"Pojďme rovnou na věc a naimportujme data.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load the core tidyverse and make it available in your current R session\r\n",
"library(tidyverse)\r\n",
"\r\n",
"# Import the data into a tibble\r\n",
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/5-Clustering/data/nigerian-songs.csv\")\r\n",
"\r\n",
"# View the first 5 rows of the data set\r\n",
"df %>% \r\n",
" slice_head(n = 5)\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Někdy můžeme chtít získat trochu více informací o našich datech. Můžeme se podívat na `data` a `jejich strukturu` pomocí funkce [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html):\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Glimpse into the data set\r\n",
"df %>% \r\n",
" glimpse()\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Dobrá práce!💪\n",
"\n",
"Můžeme si všimnout, že `glimpse()` vám poskytne celkový počet řádků (pozorování) a sloupců (proměnných), poté několik prvních hodnot každé proměnné v řádku za názvem proměnné. Navíc je *datový typ* proměnné uveden ihned za názvem proměnné uvnitř `< >`.\n",
"\n",
"`DataExplorer::introduce()` dokáže tyto informace přehledně shrnout:\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Describe basic information for our data\r\n",
"df %>% \r\n",
" introduce()\r\n",
"\r\n",
"# A visual display of the same\r\n",
"df %>% \r\n",
" plot_intro()\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Skvělé! Právě jsme zjistili, že naše data nemají žádné chybějící hodnoty.\n",
"\n",
"Když už jsme u toho, můžeme prozkoumat běžné statistiky centrální tendence (např. [průměr](https://en.wikipedia.org/wiki/Arithmetic_mean) a [medián](https://en.wikipedia.org/wiki/Median)) a míry rozptylu (např. [směrodatná odchylka](https://en.wikipedia.org/wiki/Standard_deviation)) pomocí `summarytools::descr()`.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Describe common statistics\r\n",
"df %>% \r\n",
" descr(stats = \"common\")\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Podívejme se na obecné hodnoty dat. Všimněte si, že popularita může být `0`, což ukazuje písně, které nemají žádné hodnocení. Tyto hodnoty brzy odstraníme.\n",
"\n",
"> 🤔 Pokud pracujeme s klastrováním, nesupervizovanou metodou, která nevyžaduje označená data, proč ukazujeme tato data s označeními? Ve fázi průzkumu dat jsou užitečná, ale pro fungování klastrovacích algoritmů nejsou nezbytná.\n",
"\n",
"### 1. Prozkoumejte oblíbené žánry\n",
"\n",
"Pojďme zjistit nejpopulárnější žánry 🎶 tím, že spočítáme, kolikrát se objevují.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Popular genres\r\n",
"top_genres <- df %>% \r\n",
" count(artist_top_genre, sort = TRUE) %>% \r\n",
"# Encode to categorical and reorder the according to count\r\n",
" mutate(artist_top_genre = factor(artist_top_genre) %>% fct_inorder())\r\n",
"\r\n",
"# Print the top genres\r\n",
"top_genres\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"To šlo dobře! Říká se, že obrázek má hodnotu tisíce řádků datového rámce (i když to vlastně nikdo nikdy neříká 😅). Ale chápete, co tím myslím, že?\n",
"\n",
"Jedním ze způsobů, jak vizualizovat kategorická data (znakové nebo faktorové proměnné), je použití sloupcových grafů. Pojďme vytvořit sloupcový graf pro 10 nejlepších žánrů:\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Change the default gray theme\r\n",
"theme_set(theme_light())\r\n",
"\r\n",
"# Visualize popular genres\r\n",
"top_genres %>%\r\n",
" slice(1:10) %>% \r\n",
" ggplot(mapping = aes(x = artist_top_genre, y = n,\r\n",
" fill = artist_top_genre)) +\r\n",
" geom_col(alpha = 0.8) +\r\n",
" paletteer::scale_fill_paletteer_d(\"rcartocolor::Vivid\") +\r\n",
" ggtitle(\"Top genres\") +\r\n",
" theme(plot.title = element_text(hjust = 0.5),\r\n",
" # Rotates the X markers (so we can read them)\r\n",
" axis.text.x = element_text(angle = 90))\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Teď je mnohem snazší zjistit, že máme `chybějící` žánry 🧐!\n",
"\n",
"> Dobrá vizualizace vám ukáže věci, které jste nečekali, nebo vyvolá nové otázky ohledně dat - Hadley Wickham a Garrett Grolemund, [R For Data Science](https://r4ds.had.co.nz/introduction.html)\n",
"\n",
"Poznámka: Když je hlavní žánr označen jako `Chybějící`, znamená to, že ho Spotify nezařadilo, takže se ho zbavme.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Visualize popular genres\r\n",
"top_genres %>%\r\n",
" filter(artist_top_genre != \"Missing\") %>% \r\n",
" slice(1:10) %>% \r\n",
" ggplot(mapping = aes(x = artist_top_genre, y = n,\r\n",
" fill = artist_top_genre)) +\r\n",
" geom_col(alpha = 0.8) +\r\n",
" paletteer::scale_fill_paletteer_d(\"rcartocolor::Vivid\") +\r\n",
" ggtitle(\"Top genres\") +\r\n",
" theme(plot.title = element_text(hjust = 0.5),\r\n",
" # Rotates the X markers (so we can read them)\r\n",
" axis.text.x = element_text(angle = 90))\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Z malého průzkumu dat se dozvídáme, že tři nejvýznamnější žánry dominují tomuto datasetu. Zaměřme se na `afro dancehall`, `afropop` a `nigerian pop`, a navíc dataset zfiltrujme tak, aby odstranil vše s hodnotou popularity 0 (což znamená, že nebylo v datasetu klasifikováno s popularitou a pro naše účely to lze považovat za šum):\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"nigerian_songs <- df %>% \r\n",
" # Concentrate on top 3 genres\r\n",
" filter(artist_top_genre %in% c(\"afro dancehall\", \"afropop\",\"nigerian pop\")) %>% \r\n",
" # Remove unclassified observations\r\n",
" filter(popularity != 0)\r\n",
"\r\n",
"\r\n",
"\r\n",
"# Visualize popular genres\r\n",
"nigerian_songs %>%\r\n",
" count(artist_top_genre) %>%\r\n",
" ggplot(mapping = aes(x = artist_top_genre, y = n,\r\n",
" fill = artist_top_genre)) +\r\n",
" geom_col(alpha = 0.8) +\r\n",
" paletteer::scale_fill_paletteer_d(\"ggsci::category10_d3\") +\r\n",
" ggtitle(\"Top genres\") +\r\n",
" theme(plot.title = element_text(hjust = 0.5))\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Podívejme se, zda existuje nějaký zjevný lineární vztah mezi číselnými proměnnými v našem datovém souboru. Tento vztah je matematicky kvantifikován pomocí [korelačního koeficientu](https://en.wikipedia.org/wiki/Correlation).\n",
"\n",
"Korelační koeficient je hodnota mezi -1 a 1, která udává sílu vztahu. Hodnoty nad 0 označují *pozitivní* korelaci (vysoké hodnoty jedné proměnné mají tendenci se shodovat s vysokými hodnotami druhé), zatímco hodnoty pod 0 označují *negativní* korelaci (vysoké hodnoty jedné proměnné mají tendenci se shodovat s nízkými hodnotami druhé).\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Narrow down to numeric variables and fid correlation\r\n",
"corr_mat <- nigerian_songs %>% \r\n",
" select(where(is.numeric)) %>% \r\n",
" cor()\r\n",
"\r\n",
"# Visualize correlation matrix\r\n",
"corrplot(corr_mat, order = 'AOE', col = c('white', 'black'), bg = 'gold2') \r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Data nejsou silně korelovaná, kromě vztahu mezi `energy` a `loudness`, což dává smysl, protože hlasitá hudba bývá obvykle dost energická. `Popularity` má souvislost s `release date`, což také dává smysl, protože novější skladby jsou pravděpodobně populárnější. Zdá se, že délka a energie mají také určitou korelaci.\n",
"\n",
"Bude zajímavé zjistit, co si s těmito daty poradí algoritmus pro shlukování!\n",
"\n",
"> 🎓 Pamatujte, že korelace neznamená kauzalitu! Máme důkaz o korelaci, ale žádný důkaz o kauzalitě. [Zábavná webová stránka](https://tylervigen.com/spurious-correlations) obsahuje vizualizace, které tento bod zdůrazňují.\n",
"\n",
"### 2. Prozkoumejte rozložení dat\n",
"\n",
"Položme si několik jemnějších otázek. Jsou žánry výrazně odlišné v jejich vnímání tanečnosti na základě jejich popularity? Prozkoumejme rozložení dat našich tří nejlepších žánrů z hlediska popularity a tanečnosti podél dané osy x a y pomocí [hustotních grafů](https://www.khanacademy.org/math/ap-statistics/density-curves-normal-distribution-ap/density-curves/v/density-curves).\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Perform 2D kernel density estimation\r\n",
"density_estimate_2d <- nigerian_songs %>% \r\n",
" ggplot(mapping = aes(x = popularity, y = danceability, color = artist_top_genre)) +\r\n",
" geom_density_2d(bins = 5, size = 1) +\r\n",
" paletteer::scale_color_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n",
" xlim(-20, 80) +\r\n",
" ylim(0, 1.2)\r\n",
"\r\n",
"# Density plot based on the popularity\r\n",
"density_estimate_pop <- nigerian_songs %>% \r\n",
" ggplot(mapping = aes(x = popularity, fill = artist_top_genre, color = artist_top_genre)) +\r\n",
" geom_density(size = 1, alpha = 0.5) +\r\n",
" paletteer::scale_fill_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n",
" paletteer::scale_color_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n",
" theme(legend.position = \"none\")\r\n",
"\r\n",
"# Density plot based on the danceability\r\n",
"density_estimate_dance <- nigerian_songs %>% \r\n",
" ggplot(mapping = aes(x = danceability, fill = artist_top_genre, color = artist_top_genre)) +\r\n",
" geom_density(size = 1, alpha = 0.5) +\r\n",
" paletteer::scale_fill_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n",
" paletteer::scale_color_paletteer_d(\"RSkittleBrewer::wildberry\")\r\n",
"\r\n",
"\r\n",
"# Patch everything together\r\n",
"library(patchwork)\r\n",
"density_estimate_2d / (density_estimate_pop + density_estimate_dance)\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Vidíme, že existují soustředné kruhy, které se shodují, bez ohledu na žánr. Mohlo by to znamenat, že nigerijské preference se sbíhají na určité úrovni tanečnosti pro tento žánr?\n",
"\n",
"Obecně se tyto tři žánry shodují, pokud jde o jejich popularitu a tanečnost. Určení shluků v těchto volně sladěných datech bude výzvou. Podívejme se, zda by to mohl podpořit bodový graf.\n"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# A scatter plot of popularity and danceability\r\n",
"scatter_plot <- nigerian_songs %>% \r\n",
" ggplot(mapping = aes(x = popularity, y = danceability, color = artist_top_genre, shape = artist_top_genre)) +\r\n",
" geom_point(size = 2, alpha = 0.8) +\r\n",
" paletteer::scale_color_paletteer_d(\"futurevisions::mars\")\r\n",
"\r\n",
"# Add a touch of interactivity\r\n",
"ggplotly(scatter_plot)\r\n"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"Rozptylový graf stejných os ukazuje podobný vzorec konvergence.\n",
"\n",
"Obecně platí, že pro shlukování můžete použít rozptylové grafy k zobrazení shluků dat, takže zvládnutí tohoto typu vizualizace je velmi užitečné. V příští lekci vezmeme tato filtrovaná data a použijeme k-means shlukování k objevení skupin v těchto datech, které se zajímavým způsobem překrývají.\n",
"\n",
"## **🚀 Výzva**\n",
"\n",
"V rámci přípravy na příští lekci vytvořte graf o různých algoritmech pro shlukování, které můžete objevit a použít v produkčním prostředí. Jaké typy problémů se snaží shlukování řešit?\n",
"\n",
"## [**Kvíz po přednášce**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/28/)\n",
"\n",
"## **Přehled & Samostudium**\n",
"\n",
"Než začnete aplikovat algoritmy pro shlukování, jak jsme se naučili, je dobré pochopit povahu vašeho datasetu. Přečtěte si více na toto téma [zde](https://www.kdnuggets.com/2019/10/right-clustering-algorithm.html)\n",
"\n",
"Prohlubte své znalosti technik shlukování:\n",
"\n",
"- [Trénování a hodnocení modelů shlukování pomocí Tidymodels a dalších nástrojů](https://rpubs.com/eR_ic/clustering)\n",
"\n",
"- Bradley Boehmke & Brandon Greenwell, [*Hands-On Machine Learning with R*](https://bradleyboehmke.github.io/HOML/)*.*\n",
"\n",
"## **Úkol**\n",
"\n",
"[Prozkoumejte další vizualizace pro shlukování](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/assignment.md)\n",
"\n",
"## DĚKUJEME:\n",
"\n",
"[Jen Looper](https://www.twitter.com/jenlooper) za vytvoření původní verze tohoto modulu v Pythonu ♥️\n",
"\n",
"[`Dasani Madipalli`](https://twitter.com/dasani_decoded) za vytvoření úžasných ilustrací, které usnadňují pochopení konceptů strojového učení.\n",
"\n",
"Šťastné učení,\n",
"\n",
"[Eric](https://twitter.com/ericntay), Gold Microsoft Learn Student Ambassador.\n"
],
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
],
"metadata": {
"anaconda-cloud": "",
"kernelspec": {
"display_name": "R",
"language": "R",
"name": "ir"
},
"language_info": {
"codemirror_mode": "r",
"file_extension": ".r",
"mimetype": "text/x-r-source",
"name": "R",
"pygments_lexer": "r",
"version": "3.4.1"
},
"coopTranslator": {
"original_hash": "99c36449cad3708a435f6798cfa39972",
"translation_date": "2025-09-04T07:48:17+00:00",
"source_file": "5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,640 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"anaconda-cloud": "",
"kernelspec": {
"display_name": "R",
"language": "R",
"name": "ir"
},
"language_info": {
"codemirror_mode": "r",
"file_extension": ".r",
"mimetype": "text/x-r-source",
"name": "R",
"pygments_lexer": "r",
"version": "3.4.1"
},
"colab": {
"name": "lesson_14.ipynb",
"provenance": [],
"collapsed_sections": [],
"toc_visible": true
},
"coopTranslator": {
"original_hash": "ad65fb4aad0a156b42216e4929f490fc",
"translation_date": "2025-09-04T08:06:44+00:00",
"source_file": "5-Clustering/2-K-Means/solution/R/lesson_15-R.ipynb",
"language_code": "cs"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "GULATlQXLXyR"
},
"source": [
"## Prozkoumejte shlukování metodou K-Means pomocí R a principů tidy dat.\n",
"\n",
"### [**Kvíz před lekcí**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/29/)\n",
"\n",
"V této lekci se naučíte, jak vytvářet shluky pomocí balíčku Tidymodels a dalších balíčků z ekosystému R (říkejme jim přátelé 🧑‍🤝‍🧑) a nigerijského hudebního datasetu, který jste si dříve importovali. Probereme základy metody K-Means pro shlukování. Mějte na paměti, že jak jste se naučili v předchozí lekci, existuje mnoho způsobů, jak pracovat se shluky, a metoda, kterou použijete, závisí na vašich datech. Vyzkoušíme metodu K-Means, protože je to nejběžnější technika shlukování. Pojďme začít!\n",
"\n",
"Pojmy, o kterých se dozvíte:\n",
"\n",
"- Silhouette skóre\n",
"\n",
"- Metoda lokte\n",
"\n",
"- Inerční moment\n",
"\n",
"- Variance\n",
"\n",
"### **Úvod**\n",
"\n",
"[Shlukování metodou K-Means](https://wikipedia.org/wiki/K-means_clustering) je metoda pocházející z oblasti zpracování signálů. Používá se k rozdělení a seskupení dat do `k shluků` na základě podobností jejich vlastností.\n",
"\n",
"Shluky lze vizualizovat jako [Voronoiovy diagramy](https://wikipedia.org/wiki/Voronoi_diagram), které zahrnují bod (nebo „semínko“) a jeho odpovídající oblast.\n",
"\n",
"<p >\n",
" <img src=\"../../images/voronoi.png\"\n",
" width=\"500\"/>\n",
" <figcaption>Infografika od Jen Looper</figcaption>\n",
"\n",
"\n",
"Shlukování metodou K-Means zahrnuje následující kroky:\n",
"\n",
"1. Datový vědec nejprve určí požadovaný počet shluků, které mají být vytvořeny.\n",
"\n",
"2. Algoritmus poté náhodně vybere K pozorování z datové sady, která budou sloužit jako počáteční středy shluků (tj. centroidy).\n",
"\n",
"3. Každé z ostatních pozorování je následně přiřazeno k nejbližšímu centroidu.\n",
"\n",
"4. Poté se vypočítá nový průměr každého shluku a centroid se přesune na tento průměr.\n",
"\n",
"5. Jakmile jsou středy přepočítány, každé pozorování se znovu zkontroluje, zda by nemohlo být blíže jinému shluku. Všechna pozorování jsou znovu přiřazena pomocí aktualizovaných průměrů shluků. Kroky přiřazení shluků a aktualizace centroidů se iterativně opakují, dokud se přiřazení shluků nepřestane měnit (tj. dokud není dosaženo konvergence). Algoritmus obvykle končí, když každá nová iterace vede k zanedbatelnému pohybu centroidů a shluky se stanou statickými.\n",
"\n",
"<div>\n",
"\n",
"> Všimněte si, že kvůli náhodnosti počátečních k pozorování použitých jako výchozí centroidy můžeme pokaždé, když aplikujeme tento postup, získat mírně odlišné výsledky. Z tohoto důvodu většina algoritmů používá několik *náhodných startů* a vybírá iteraci s nejnižší hodnotou WCSS. Proto se důrazně doporučuje vždy spouštět metodu K-Means s několika hodnotami *nstart*, aby se předešlo *nežádoucímu lokálnímu optimu.*\n",
"\n",
"</div>\n",
"\n",
"Tato krátká animace využívající [ilustrace](https://github.com/allisonhorst/stats-illustrations) od Allison Horst vysvětluje proces shlukování:\n",
"\n",
"<p >\n",
" <img src=\"../../images/kmeans.gif\"\n",
" width=\"550\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n",
"\n",
"\n",
"\n",
"Základní otázka, která při shlukování vyvstává, zní: jak zjistíte, na kolik shluků máte svá data rozdělit? Jednou z nevýhod metody K-Means je skutečnost, že musíte určit `k`, tedy počet `centroidů`. Naštěstí vám `metoda lokte` pomůže odhadnout dobrý výchozí počet `k`. Za chvíli si to vyzkoušíte.\n",
"\n",
"### \n",
"\n",
"**Předpoklady**\n",
"\n",
"Navážeme přesně tam, kde jsme skončili v [předchozí lekci](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb), kde jsme analyzovali datovou sadu, vytvořili spoustu vizualizací a filtrovali datovou sadu na pozorování, která nás zajímají. Určitě si ji projděte!\n",
"\n",
"Budeme potřebovat několik balíčků, abychom mohli začít s tímto modulem. Můžete si je nainstalovat pomocí: `install.packages(c('tidyverse', 'tidymodels', 'cluster', 'summarytools', 'plotly', 'paletteer', 'factoextra', 'patchwork'))`\n",
"\n",
"Alternativně níže uvedený skript zkontroluje, zda máte balíčky potřebné k dokončení tohoto modulu, a v případě, že některé chybí, je pro vás nainstaluje.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "ah_tBi58LXyi"
},
"source": [
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n",
"\n",
"pacman::p_load('tidyverse', 'tidymodels', 'cluster', 'summarytools', 'plotly', 'paletteer', 'factoextra', 'patchwork')\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "7e--UCUTLXym"
},
"source": [
"Pojďme rovnou na věc!\n",
"\n",
"## 1. Tanec s daty: Zúžení na 3 nejoblíbenější hudební žánry\n",
"\n",
"Toto je rekapitulace toho, co jsme dělali v předchozí lekci. Pojďme si trochu pohrát s daty!\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Ycamx7GGLXyn"
},
"source": [
"# Load the core tidyverse and make it available in your current R session\n",
"library(tidyverse)\n",
"\n",
"# Import the data into a tibble\n",
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/5-Clustering/data/nigerian-songs.csv\", show_col_types = FALSE)\n",
"\n",
"# Narrow down to top 3 popular genres\n",
"nigerian_songs <- df %>% \n",
" # Concentrate on top 3 genres\n",
" filter(artist_top_genre %in% c(\"afro dancehall\", \"afropop\",\"nigerian pop\")) %>% \n",
" # Remove unclassified observations\n",
" filter(popularity != 0)\n",
"\n",
"\n",
"\n",
"# Visualize popular genres using bar plots\n",
"theme_set(theme_light())\n",
"nigerian_songs %>%\n",
" count(artist_top_genre) %>%\n",
" ggplot(mapping = aes(x = artist_top_genre, y = n,\n",
" fill = artist_top_genre)) +\n",
" geom_col(alpha = 0.8) +\n",
" paletteer::scale_fill_paletteer_d(\"ggsci::category10_d3\") +\n",
" ggtitle(\"Top genres\") +\n",
" theme(plot.title = element_text(hjust = 0.5))\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "b5h5zmkPLXyp"
},
"source": [
"🤩 To šlo dobře!\n",
"\n",
"## 2. Další průzkum dat.\n",
"\n",
"Jak čistá jsou tato data? Podívejme se na odlehlé hodnoty pomocí krabicových grafů. Zaměříme se na číselné sloupce s menším počtem odlehlých hodnot (i když byste mohli odlehlé hodnoty odstranit). Krabicové grafy mohou ukázat rozsah dat a pomohou vybrat, které sloupce použít. Všimněte si, že krabicové grafy neukazují rozptyl, což je důležitý prvek pro dobře seskupitelná data. Další informace naleznete v [této diskusi](https://stats.stackexchange.com/questions/91536/deduce-variance-from-boxplot).\n",
"\n",
"[Krabicové grafy](https://en.wikipedia.org/wiki/Box_plot) se používají k grafickému znázornění rozložení `číselných` dat, takže začněme *výběrem* všech číselných sloupců spolu s oblíbenými hudebními žánry.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "HhNreJKLLXyq"
},
"source": [
"# Select top genre column and all other numeric columns\n",
"df_numeric <- nigerian_songs %>% \n",
" select(artist_top_genre, where(is.numeric)) \n",
"\n",
"# Display the data\n",
"df_numeric %>% \n",
" slice_head(n = 5)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "uYXrwJRaLXyq"
},
"source": [
"Podívejte se, jak výběrový pomocník `where` usnadňuje tento proces 💁? Prozkoumejte další podobné funkce [zde](https://tidyselect.r-lib.org/).\n",
"\n",
"Protože budeme vytvářet krabicové grafy pro každou číselnou vlastnost a chceme se vyhnout použití smyček, přeformátujeme naše data do *delšího* formátu, který nám umožní využít `facets` - podgrafy, z nichž každý zobrazuje jednu podmnožinu dat.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "gd5bR3f8LXys"
},
"source": [
"# Pivot data from wide to long\n",
"df_numeric_long <- df_numeric %>% \n",
" pivot_longer(!artist_top_genre, names_to = \"feature_names\", values_to = \"values\") \n",
"\n",
"# Print out data\n",
"df_numeric_long %>% \n",
" slice_head(n = 15)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "-7tE1swnLXyv"
},
"source": [
"Mnohem delší! Teď je čas na nějaké `ggplots`! Tak jaký `geom` použijeme?\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "r88bIsyuLXyy"
},
"source": [
"# Make a box plot\n",
"df_numeric_long %>% \n",
" ggplot(mapping = aes(x = feature_names, y = values, fill = feature_names)) +\n",
" geom_boxplot() +\n",
" facet_wrap(~ feature_names, ncol = 4, scales = \"free\") +\n",
" theme(legend.position = \"none\")\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "EYVyKIUELXyz"
},
"source": [
"Teď můžeme vidět, že tato data jsou trochu hlučná: při pohledu na jednotlivé sloupce jako boxploty můžete vidět odlehlé hodnoty. Mohli byste projít dataset a tyto odlehlé hodnoty odstranit, ale to by data značně zredukovalo.\n",
"\n",
"Prozatím si vybereme, které sloupce použijeme pro náš cvičný úkol shlukování. Vybereme číselné sloupce s podobnými rozsahy. Mohli bychom zakódovat `artist_top_genre` jako číselné hodnoty, ale prozatím ho vynecháme.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "-wkpINyZLXy0"
},
"source": [
"# Select variables with similar ranges\n",
"df_numeric_select <- df_numeric %>% \n",
" select(popularity, danceability, acousticness, loudness, energy) \n",
"\n",
"# Normalize data\n",
"# df_numeric_select <- scale(df_numeric_select)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "D7dLzgpqLXy1"
},
"source": [
"## 3. Výpočet k-means shlukování v R\n",
"\n",
"K-means můžeme vypočítat v R pomocí vestavěné funkce `kmeans`, viz `help(\"kmeans()\")`. Funkce `kmeans()` přijímá datový rámec, který obsahuje pouze číselné sloupce, jako svůj hlavní argument.\n",
"\n",
"Prvním krokem při použití k-means shlukování je specifikace počtu shluků (k), které budou vytvořeny ve finálním řešení. Víme, že máme 3 hudební žánry, které jsme vyčlenili z datasetu, takže zkusme 3:\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "uC4EQ5w7LXy5"
},
"source": [
"set.seed(2056)\n",
"# Kmeans clustering for 3 clusters\n",
"kclust <- kmeans(\n",
" df_numeric_select,\n",
" # Specify the number of clusters\n",
" centers = 3,\n",
" # How many random initial configurations\n",
" nstart = 25\n",
")\n",
"\n",
"# Display clustering object\n",
"kclust\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "hzfhscWrLXy-"
},
"source": [
"Objekt kmeans obsahuje několik informací, které jsou dobře vysvětleny v `help(\"kmeans()\")`. Prozatím se zaměříme na několik z nich. Vidíme, že data byla rozdělena do 3 klastrů o velikostech 65, 110, 111. Výstup také obsahuje středové body (průměry) pro 3 skupiny napříč 5 proměnnými.\n",
"\n",
"Vektor klastrů představuje přiřazení klastru pro každé pozorování. Použijme funkci `augment`, abychom přidali přiřazení klastru do původního datového souboru.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "0XwwpFGQLXy_"
},
"source": [
"# Add predicted cluster assignment to data set\n",
"augment(kclust, df_numeric_select) %>% \n",
" relocate(.cluster) %>% \n",
" slice_head(n = 10)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "NXIVXXACLXzA"
},
"source": [
"Perfektní, právě jsme rozdělili náš datový soubor do 3 skupin. Takže, jak dobré je naše shlukování 🤷? Podívejme se na `Silhouette skóre`.\n",
"\n",
"### **Silhouette skóre**\n",
"\n",
"[Silhouette analýza](https://en.wikipedia.org/wiki/Silhouette_(clustering)) může být použita ke studiu vzdálenosti mezi výslednými shluky. Toto skóre se pohybuje od -1 do 1, a pokud je skóre blízko 1, shluk je hustý a dobře oddělený od ostatních shluků. Hodnota blízko 0 představuje překrývající se shluky se vzorky velmi blízko rozhodovací hranice sousedních shluků. [zdroj](https://dzone.com/articles/kmeans-silhouette-score-explained-with-python-exam).\n",
"\n",
"Metoda průměrného silhouette skóre počítá průměrné silhouette skóre pozorování pro různé hodnoty *k*. Vysoké průměrné silhouette skóre naznačuje dobré shlukování.\n",
"\n",
"Funkce `silhouette` v balíčku cluster slouží k výpočtu průměrné šířky silhouette.\n",
"\n",
"> Silhouette lze vypočítat pomocí jakékoli [vzdálenostní](https://en.wikipedia.org/wiki/Distance \"Distance\") metriky, jako je [Euklidovská vzdálenost](https://en.wikipedia.org/wiki/Euclidean_distance \"Euclidean distance\") nebo [Manhattanská vzdálenost](https://en.wikipedia.org/wiki/Manhattan_distance \"Manhattan distance\"), které jsme probírali v [předchozí lekci](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb).\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Jn0McL28LXzB"
},
"source": [
"# Load cluster package\n",
"library(cluster)\n",
"\n",
"# Compute average silhouette score\n",
"ss <- silhouette(kclust$cluster,\n",
" # Compute euclidean distance\n",
" dist = dist(df_numeric_select))\n",
"mean(ss[, 3])\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "QyQRn97nLXzC"
},
"source": [
"Náš skóre je **.549**, tedy přesně uprostřed. To naznačuje, že naše data nejsou obzvlášť vhodná pro tento typ shlukování. Podívejme se, zda můžeme tento předpoklad vizuálně potvrdit. Balíček [factoextra](https://rpkgs.datanovia.com/factoextra/index.html) poskytuje funkce (`fviz_cluster()`) pro vizualizaci shlukování.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "7a6Km1_FLXzD"
},
"source": [
"library(factoextra)\n",
"\n",
"# Visualize clustering results\n",
"fviz_cluster(kclust, df_numeric_select)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "IBwCWt-0LXzD"
},
"source": [
"Překrývání v klastrech naznačuje, že naše data nejsou příliš vhodná pro tento typ klastrování, ale pojďme pokračovat.\n",
"\n",
"## 4. Určení optimálního počtu klastrů\n",
"\n",
"Základní otázka, která často vyvstává při klastrování metodou K-Means, je tato: bez známých třídních štítků, jak zjistíte, na kolik klastrů rozdělit svá data?\n",
"\n",
"Jedním ze způsobů, jak to zjistit, je použít vzorek dat k `vytvoření série modelů klastrování` s postupně se zvyšujícím počtem klastrů (např. od 1 do 10) a vyhodnotit metriky klastrování, jako je **Silhouette skóre.**\n",
"\n",
"Určeme optimální počet klastrů výpočtem algoritmu klastrování pro různé hodnoty *k* a vyhodnocením **součtu čtverců uvnitř klastrů** (WCSS). Celkový součet čtverců uvnitř klastrů (WCSS) měří kompaktnost klastrování a chceme, aby byl co nejmenší, přičemž nižší hodnoty znamenají, že datové body jsou blíže u sebe.\n",
"\n",
"Prozkoumejme vliv různých voleb hodnoty `k`, od 1 do 10, na toto klastrování.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "hSeIiylDLXzE"
},
"source": [
"# Create a series of clustering models\n",
"kclusts <- tibble(k = 1:10) %>% \n",
" # Perform kmeans clustering for 1,2,3 ... ,10 clusters\n",
" mutate(model = map(k, ~ kmeans(df_numeric_select, centers = .x, nstart = 25)),\n",
" # Farm out clustering metrics eg WCSS\n",
" glanced = map(model, ~ glance(.x))) %>% \n",
" unnest(cols = glanced)\n",
" \n",
"\n",
"# View clustering rsulsts\n",
"kclusts\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "m7rS2U1eLXzE"
},
"source": [
"Nyní, když máme celkový součet čtverců uvnitř klastrů (tot.withinss) pro každý algoritmus shlukování s centrem *k*, použijeme [metodu lokte](https://en.wikipedia.org/wiki/Elbow_method_(clustering)) k nalezení optimálního počtu klastrů. Tato metoda spočívá v zakreslení WCSS jako funkce počtu klastrů a výběru [lokte křivky](https://en.wikipedia.org/wiki/Elbow_of_the_curve \"Elbow of the curve\") jako počtu klastrů, které použijeme.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "o_DjHGItLXzF"
},
"source": [
"set.seed(2056)\n",
"# Use elbow method to determine optimum number of clusters\n",
"kclusts %>% \n",
" ggplot(mapping = aes(x = k, y = tot.withinss)) +\n",
" geom_line(size = 1.2, alpha = 0.8, color = \"#FF7F0EFF\") +\n",
" geom_point(size = 2, color = \"#FF7F0EFF\")\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "pLYyt5XSLXzG"
},
"source": [
"Graf ukazuje výrazné snížení WCSS (tedy větší *soudržnost*), když se počet klastrů zvýší z jednoho na dva, a další znatelné snížení při přechodu ze dvou na tři klastry. Poté je snížení méně výrazné, což vede k vytvoření `lokte` 💪 na grafu přibližně u tří klastrů. To je dobrý náznak, že existují dva až tři poměrně dobře oddělené klastry datových bodů.\n",
"\n",
"Nyní můžeme přistoupit k extrakci modelu klastrování, kde `k = 3`:\n",
"\n",
"> `pull()`: používá se k extrakci jednoho sloupce\n",
">\n",
"> `pluck()`: používá se k indexování datových struktur, jako jsou seznamy\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "JP_JPKBILXzG"
},
"source": [
"# Extract k = 3 clustering\n",
"final_kmeans <- kclusts %>% \n",
" filter(k == 3) %>% \n",
" pull(model) %>% \n",
" pluck(1)\n",
"\n",
"\n",
"final_kmeans\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "l_PDTu8tLXzI"
},
"source": [
"Skvělé! Pojďme si vizualizovat získané clustery. Máte chuť na trochu interaktivity s použitím `plotly`?\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "dNcleFe-LXzJ"
},
"source": [
"# Add predicted cluster assignment to data set\n",
"results <- augment(final_kmeans, df_numeric_select) %>% \n",
" bind_cols(df_numeric %>% select(artist_top_genre)) \n",
"\n",
"# Plot cluster assignments\n",
"clust_plt <- results %>% \n",
" ggplot(mapping = aes(x = popularity, y = danceability, color = .cluster, shape = artist_top_genre)) +\n",
" geom_point(size = 2, alpha = 0.8) +\n",
" paletteer::scale_color_paletteer_d(\"ggthemes::Tableau_10\")\n",
"\n",
"ggplotly(clust_plt)\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "6JUM_51VLXzK"
},
"source": [
"Možná bychom očekávali, že každý klastr (reprezentovaný různými barvami) bude mít odlišné žánry (reprezentované různými tvary).\n",
"\n",
"Podívejme se na přesnost modelu.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "HdIMUGq7LXzL"
},
"source": [
"# Assign genres to predefined integers\n",
"label_count <- results %>% \n",
" group_by(artist_top_genre) %>% \n",
" mutate(id = cur_group_id()) %>% \n",
" ungroup() %>% \n",
" summarise(correct_labels = sum(.cluster == id))\n",
"\n",
"\n",
"# Print results \n",
"cat(\"Result:\", label_count$correct_labels, \"out of\", nrow(results), \"samples were correctly labeled.\")\n",
"\n",
"cat(\"\\nAccuracy score:\", label_count$correct_labels/nrow(results))\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "C50wvaAOLXzM"
},
"source": [
"Přesnost tohoto modelu není špatná, ale ani skvělá. Může to být způsobeno tím, že data nejsou vhodná pro K-Means Clustering. Tato data jsou příliš nevyvážená, málo korelovaná a mezi hodnotami sloupců je příliš velká variabilita, což ztěžuje jejich seskupování. Ve skutečnosti jsou vytvořené clustery pravděpodobně silně ovlivněny nebo zkresleny třemi kategoriemi žánrů, které jsme výše definovali.\n",
"\n",
"Nicméně, i tak to byl skvělý proces učení!\n",
"\n",
"V dokumentaci Scikit-learn můžete vidět, že model jako tento, s clustery, které nejsou příliš dobře vymezené, má problém s „variabilitou“:\n",
"\n",
"<p >\n",
" <img src=\"../../images/problems.png\"\n",
" width=\"500\"/>\n",
" <figcaption>Infografika ze Scikit-learn</figcaption>\n",
"\n",
"\n",
"\n",
"## **Variabilita**\n",
"\n",
"Variabilita je definována jako „průměr čtverců odchylek od průměru“ [zdroj](https://www.mathsisfun.com/data/standard-deviation.html). V kontextu tohoto problému seskupování to znamená, že hodnoty v našem datasetu mají tendenci se od průměru odchylovat až příliš.\n",
"\n",
"✅ Toto je skvělý moment k zamyšlení nad všemi způsoby, jak tento problém vyřešit. Můžete data ještě více upravit? Použít jiné sloupce? Nebo jiný algoritmus? Tip: Zkuste [škálovat svá data](https://www.mygreatlearning.com/blog/learning-data-science-with-k-means-clustering/), abyste je normalizovali, a otestujte jiné sloupce.\n",
"\n",
"> Vyzkoušejte tento '[kalkulátor variability](https://www.calculatorsoup.com/calculators/statistics/variance-calculator.php)', abyste lépe pochopili tento koncept.\n",
"\n",
"------------------------------------------------------------------------\n",
"\n",
"## **🚀Výzva**\n",
"\n",
"Stravte nějaký čas s tímto notebookem a upravujte parametry. Dokážete zlepšit přesnost modelu tím, že data více vyčistíte (například odstraněním odlehlých hodnot)? Můžete použít váhy, abyste některým vzorkům dat přidali větší důležitost. Co dalšího můžete udělat, abyste vytvořili lepší clustery?\n",
"\n",
"Tip: Zkuste škálovat svá data. V notebooku je zakomentovaný kód, který přidává standardní škálování, aby se hodnoty sloupců více podobaly z hlediska rozsahu. Zjistíte, že i když skóre siluety klesne, „zlom“ v grafu lokte se vyhladí. To je proto, že ponechání dat neškálovaných umožňuje, aby data s menší variabilitou měla větší váhu. Přečtěte si o tomto problému více [zde](https://stats.stackexchange.com/questions/21222/are-mean-normalization-and-feature-scaling-needed-for-k-means-clustering/21226#21226).\n",
"\n",
"## [**Kvíz po přednášce**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/30/)\n",
"\n",
"## **Opakování a samostudium**\n",
"\n",
"- Podívejte se na simulátor K-Means [například tento](https://user.ceng.metu.edu.tr/~akifakkus/courses/ceng574/k-means/). Tento nástroj můžete použít k vizualizaci vzorků datových bodů a určení jejich centroidů. Můžete upravit náhodnost dat, počet clusterů a počet centroidů. Pomáhá vám to získat představu o tom, jak lze data seskupit?\n",
"\n",
"- Podívejte se také na [tento materiál o K-Means](https://stanford.edu/~cpiech/cs221/handouts/kmeans.html) ze Stanfordu.\n",
"\n",
"Chcete si vyzkoušet své nově nabyté dovednosti v seskupování na datasetech, které se dobře hodí pro K-Means clustering? Podívejte se na:\n",
"\n",
"- [Trénování a hodnocení modelů seskupování](https://rpubs.com/eR_ic/clustering) pomocí Tidymodels a dalších nástrojů\n",
"\n",
"- [Analýza clusterů pomocí K-means](https://uc-r.github.io/kmeans_clustering), UC Business Analytics R Programming Guide\n",
"\n",
"- [K-means clustering s principy tidy dat](https://www.tidymodels.org/learn/statistics/k-means/)\n",
"\n",
"## **Úkol**\n",
"\n",
"[Vyzkoušejte různé metody seskupování](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/2-K-Means/assignment.md)\n",
"\n",
"## PODĚKOVÁNÍ:\n",
"\n",
"[Jen Looper](https://www.twitter.com/jenlooper) za vytvoření původní verze tohoto modulu v Pythonu ♥️\n",
"\n",
"[`Allison Horst`](https://twitter.com/allison_horst/) za vytvoření úžasných ilustrací, které dělají R přívětivějším a poutavějším. Další ilustrace najdete v její [galerii](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n",
"\n",
"Přejeme příjemné učení,\n",
"\n",
"[Eric](https://twitter.com/ericntay), Gold Microsoft Learn Student Ambassador.\n",
"\n",
"<p >\n",
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
" width=\"500\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). Přestože se snažíme o přesnost, mějte na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádné nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,100 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "27de2abc0235ebd22080fc8f1107454d",
"translation_date": "2025-09-04T09:29:49+00:00",
"source_file": "6-NLP/3-Translation-Sentiment/solution/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from textblob import TextBlob\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# You should download the book text, clean it, and import it here\n",
"with open(\"pride.txt\", encoding=\"utf8\") as f:\n",
" file_contents = f.read()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"book_pride = TextBlob(file_contents)\n",
"positive_sentiment_sentences = []\n",
"negative_sentiment_sentences = []"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for sentence in book_pride.sentences:\n",
" if sentence.sentiment.polarity == 1:\n",
" positive_sentiment_sentences.append(sentence)\n",
" if sentence.sentiment.polarity == -1:\n",
" negative_sentiment_sentences.append(sentence)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"The \" + str(len(positive_sentiment_sentences)) + \" most positive sentences:\")\n",
"for sentence in positive_sentiment_sentences:\n",
" print(\"+ \" + str(sentence.replace(\"\\n\", \"\").replace(\" \", \" \")))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"The \" + str(len(negative_sentiment_sentences)) + \" most negative sentences:\")\n",
"for sentence in negative_sentiment_sentences:\n",
" print(\"- \" + str(sentence.replace(\"\\n\", \"\").replace(\" \", \" \")))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,174 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "2d05e7db439376aa824f4b387f8324ca",
"translation_date": "2025-09-04T09:29:20+00:00",
"source_file": "6-NLP/4-Hotel-Reviews-1/solution/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# EDA\n",
"import pandas as pd\n",
"import time"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_difference_review_avg(row):\n",
" return row[\"Average_Score\"] - row[\"Calc_Average_Score\"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Load the hotel reviews from CSV\n",
"print(\"Loading data file now, this could take a while depending on file size\")\n",
"start = time.time()\n",
"df = pd.read_csv('../../data/Hotel_Reviews.csv')\n",
"end = time.time()\n",
"print(\"Loading took \" + str(round(end - start, 2)) + \" seconds\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# What shape is the data (rows, columns)?\n",
"print(\"The shape of the data (rows, cols) is \" + str(df.shape))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# value_counts() creates a Series object that has index and values\n",
"# in this case, the country and the frequency they occur in reviewer nationality\n",
"nationality_freq = df[\"Reviewer_Nationality\"].value_counts()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# What reviewer nationality is the most common in the dataset?\n",
"print(\"The highest frequency reviewer nationality is \" + str(nationality_freq.index[0]).strip() + \" with \" + str(nationality_freq[0]) + \" reviews.\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# What is the top 10 most common nationalities and their frequencies?\n",
"print(\"The top 10 highest frequency reviewer nationalities are:\")\n",
"print(nationality_freq[0:10].to_string())\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# How many unique nationalities are there?\n",
"print(\"There are \" + str(nationality_freq.index.size) + \" unique nationalities in the dataset\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# What was the most frequently reviewed hotel for the top 10 nationalities - print the hotel and number of reviews\n",
"for nat in nationality_freq[:10].index:\n",
" # First, extract all the rows that match the criteria into a new dataframe\n",
" nat_df = df[df[\"Reviewer_Nationality\"] == nat] \n",
" # Now get the hotel freq\n",
" freq = nat_df[\"Hotel_Name\"].value_counts()\n",
" print(\"The most reviewed hotel for \" + str(nat).strip() + \" was \" + str(freq.index[0]) + \" with \" + str(freq[0]) + \" reviews.\") \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# How many reviews are there per hotel (frequency count of hotel) and do the results match the value in `Total_Number_of_Reviews`?\n",
"# First create a new dataframe based on the old one, removing the uneeded columns\n",
"hotel_freq_df = df.drop([\"Hotel_Address\", \"Additional_Number_of_Scoring\", \"Review_Date\", \"Average_Score\", \"Reviewer_Nationality\", \"Negative_Review\", \"Review_Total_Negative_Word_Counts\", \"Positive_Review\", \"Review_Total_Positive_Word_Counts\", \"Total_Number_of_Reviews_Reviewer_Has_Given\", \"Reviewer_Score\", \"Tags\", \"days_since_review\", \"lat\", \"lng\"], axis = 1)\n",
"# Group the rows by Hotel_Name, count them and put the result in a new column Total_Reviews_Found\n",
"hotel_freq_df['Total_Reviews_Found'] = hotel_freq_df.groupby('Hotel_Name').transform('count')\n",
"# Get rid of all the duplicated rows\n",
"hotel_freq_df = hotel_freq_df.drop_duplicates(subset = [\"Hotel_Name\"])\n",
"print()\n",
"print(hotel_freq_df.to_string())\n",
"print(str(hotel_freq_df.shape))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# While there is an `Average_Score` for each hotel according to the dataset, \n",
"# you can also calculate an average score (getting the average of all reviewer scores in the dataset for each hotel)\n",
"# Add a new column to your dataframe with the column header `Calc_Average_Score` that contains that calculated average. \n",
"df['Calc_Average_Score'] = round(df.groupby('Hotel_Name').Reviewer_Score.transform('mean'), 1)\n",
"# Add a new column with the difference between the two average scores\n",
"df[\"Average_Score_Difference\"] = df.apply(get_difference_review_avg, axis = 1)\n",
"# Create a df without all the duplicates of Hotel_Name (so only 1 row per hotel)\n",
"review_scores_df = df.drop_duplicates(subset = [\"Hotel_Name\"])\n",
"# Sort the dataframe to find the lowest and highest average score difference\n",
"review_scores_df = review_scores_df.sort_values(by=[\"Average_Score_Difference\"])\n",
"print(review_scores_df[[\"Average_Score_Difference\", \"Average_Score\", \"Calc_Average_Score\", \"Hotel_Name\"]])\n",
"# Do any hotels have the same (rounded to 1 decimal place) `Average_Score` and `Calc_Average_Score`?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Upozornění**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,172 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 4,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"coopTranslator": {
"original_hash": "033cb89c85500224b3c63fd04f49b4aa",
"translation_date": "2025-09-04T09:30:20+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/solution/1-notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import time\n",
"import ast"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def replace_address(row):\n",
" if \"Netherlands\" in row[\"Hotel_Address\"]:\n",
" return \"Amsterdam, Netherlands\"\n",
" elif \"Barcelona\" in row[\"Hotel_Address\"]:\n",
" return \"Barcelona, Spain\"\n",
" elif \"United Kingdom\" in row[\"Hotel_Address\"]:\n",
" return \"London, United Kingdom\"\n",
" elif \"Milan\" in row[\"Hotel_Address\"]: \n",
" return \"Milan, Italy\"\n",
" elif \"France\" in row[\"Hotel_Address\"]:\n",
" return \"Paris, France\"\n",
" elif \"Vienna\" in row[\"Hotel_Address\"]:\n",
" return \"Vienna, Austria\" \n",
" else:\n",
" return row.Hotel_Address\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# Load the hotel reviews from CSV\n",
"start = time.time()\n",
"df = pd.read_csv('../../data/Hotel_Reviews.csv')\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# dropping columns we will not use:\n",
"df.drop([\"lat\", \"lng\"], axis = 1, inplace=True)\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# Replace all the addresses with a shortened, more useful form\n",
"df[\"Hotel_Address\"] = df.apply(replace_address, axis = 1)\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# Drop `Additional_Number_of_Scoring`\n",
"df.drop([\"Additional_Number_of_Scoring\"], axis = 1, inplace=True)\n",
"# Replace `Total_Number_of_Reviews` and `Average_Score` with our own calculated values\n",
"df.Total_Number_of_Reviews = df.groupby('Hotel_Name').transform('count')\n",
"df.Average_Score = round(df.groupby('Hotel_Name').Reviewer_Score.transform('mean'), 1)\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# Process the Tags into new columns\n",
"# The file Hotel_Reviews_Tags.py, identifies the most important tags\n",
"# Leisure trip, Couple, Solo traveler, Business trip, Group combined with Travelers with friends, \n",
"# Family with young children, Family with older children, With a pet\n",
"df[\"Leisure_trip\"] = df.Tags.apply(lambda tag: 1 if \"Leisure trip\" in tag else 0)\n",
"df[\"Couple\"] = df.Tags.apply(lambda tag: 1 if \"Couple\" in tag else 0)\n",
"df[\"Solo_traveler\"] = df.Tags.apply(lambda tag: 1 if \"Solo traveler\" in tag else 0)\n",
"df[\"Business_trip\"] = df.Tags.apply(lambda tag: 1 if \"Business trip\" in tag else 0)\n",
"df[\"Group\"] = df.Tags.apply(lambda tag: 1 if \"Group\" in tag or \"Travelers with friends\" in tag else 0)\n",
"df[\"Family_with_young_children\"] = df.Tags.apply(lambda tag: 1 if \"Family with young children\" in tag else 0)\n",
"df[\"Family_with_older_children\"] = df.Tags.apply(lambda tag: 1 if \"Family with older children\" in tag else 0)\n",
"df[\"With_a_pet\"] = df.Tags.apply(lambda tag: 1 if \"With a pet\" in tag else 0)\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# No longer need any of these columns\n",
"df.drop([\"Review_Date\", \"Review_Total_Negative_Word_Counts\", \"Review_Total_Positive_Word_Counts\", \"days_since_review\", \"Total_Number_of_Reviews_Reviewer_Has_Given\"], axis = 1, inplace=True)\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Saving results to Hotel_Reviews_Filtered.csv\n",
"Filtering took 23.74 seconds\n"
]
}
],
"source": [
"# Saving new data file with calculated columns\n",
"print(\"Saving results to Hotel_Reviews_Filtered.csv\")\n",
"df.to_csv(r'../../data/Hotel_Reviews_Filtered.csv', index = False)\n",
"end = time.time()\n",
"print(\"Filtering took \" + str(round(end - start, 2)) + \" seconds\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). Ačkoli se snažíme o přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,137 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 4,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"coopTranslator": {
"original_hash": "341efc86325ec2a214f682f57a189dfd",
"translation_date": "2025-09-04T09:30:49+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/solution/2-notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# Load the hotel reviews from CSV (you can )\n",
"import pandas as pd \n",
"\n",
"df = pd.read_csv('../../data/Hotel_Reviews_Filtered.csv')\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# We want to find the most useful tags to keep\n",
"# Remove opening and closing brackets\n",
"df.Tags = df.Tags.str.strip(\"[']\")\n",
"# remove all quotes too\n",
"df.Tags = df.Tags.str.replace(\" ', '\", \",\", regex = False)\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# removing this to take advantage of the 'already a phrase' fact of the dataset \n",
"# Now split the strings into a list\n",
"tag_list_df = df.Tags.str.split(',', expand = True)\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# Remove leading and trailing spaces\n",
"df[\"Tag_1\"] = tag_list_df[0].str.strip()\n",
"df[\"Tag_2\"] = tag_list_df[1].str.strip()\n",
"df[\"Tag_3\"] = tag_list_df[2].str.strip()\n",
"df[\"Tag_4\"] = tag_list_df[3].str.strip()\n",
"df[\"Tag_5\"] = tag_list_df[4].str.strip()\n",
"df[\"Tag_6\"] = tag_list_df[5].str.strip()\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# Merge the 6 columns into one with melt\n",
"df_tags = df.melt(value_vars=[\"Tag_1\", \"Tag_2\", \"Tag_3\", \"Tag_4\", \"Tag_5\", \"Tag_6\"])\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"The shape of the tags with no filtering: (2514684, 2)\n",
" index count\n",
"0 Leisure trip 338423\n",
"1 Couple 205305\n",
"2 Solo traveler 89779\n",
"3 Business trip 68176\n",
"4 Group 51593\n",
"5 Family with young children 49318\n",
"6 Family with older children 21509\n",
"7 Travelers with friends 1610\n",
"8 With a pet 1078\n"
]
}
],
"source": [
"# Get the value counts\n",
"tag_vc = df_tags.value.value_counts()\n",
"# print(tag_vc)\n",
"print(\"The shape of the tags with no filtering:\", str(df_tags.shape))\n",
"# Drop rooms, suites, and length of stay, mobile device and anything with less count than a 1000\n",
"df_tags = df_tags[~df_tags.value.str.contains(\"Standard|room|Stayed|device|Beds|Suite|Studio|King|Superior|Double\", na=False, case=False)]\n",
"tag_vc = df_tags.value.value_counts().reset_index(name=\"count\").query(\"count > 1000\")\n",
"# Print the top 10 (there should only be 9 and we'll use these in the filtering section)\n",
"print(tag_vc[:10])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

@ -0,0 +1,260 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"orig_nbformat": 4,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
},
"coopTranslator": {
"original_hash": "705bf02633759f689abc37b19749a16d",
"translation_date": "2025-09-04T09:31:20+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/solution/3-notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stderr",
"text": [
"[nltk_data] Downloading package vader_lexicon to\n[nltk_data] /Users/jenlooper/nltk_data...\n"
]
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"True"
]
},
"metadata": {},
"execution_count": 9
}
],
"source": [
"import time\n",
"import pandas as pd\n",
"import nltk as nltk\n",
"from nltk.corpus import stopwords\n",
"from nltk.sentiment.vader import SentimentIntensityAnalyzer\n",
"nltk.download('vader_lexicon')\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"vader_sentiment = SentimentIntensityAnalyzer()\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# There are 3 possibilities of input for a review:\n",
"# It could be \"No Negative\", in which case, return 0\n",
"# It could be \"No Positive\", in which case, return 0\n",
"# It could be a review, in which case calculate the sentiment\n",
"def calc_sentiment(review): \n",
" if review == \"No Negative\" or review == \"No Positive\":\n",
" return 0\n",
" return vader_sentiment.polarity_scores(review)[\"compound\"] \n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"# Load the hotel reviews from CSV\n",
"df = pd.read_csv(\"../../data/Hotel_Reviews_Filtered.csv\")\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"# Remove stop words - can be slow for a lot of text!\n",
"# Ryan Han (ryanxjhan on Kaggle) has a great post measuring performance of different stop words removal approaches\n",
"# https://www.kaggle.com/ryanxjhan/fast-stop-words-removal # using the approach that Ryan recommends\n",
"start = time.time()\n",
"cache = set(stopwords.words(\"english\"))\n",
"def remove_stopwords(review):\n",
" text = \" \".join([word for word in review.split() if word not in cache])\n",
" return text\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"# Remove the stop words from both columns\n",
"df.Negative_Review = df.Negative_Review.apply(remove_stopwords) \n",
"df.Positive_Review = df.Positive_Review.apply(remove_stopwords)\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Removing stop words took 5.77 seconds\n"
]
}
],
"source": [
"end = time.time()\n",
"print(\"Removing stop words took \" + str(round(end - start, 2)) + \" seconds\")\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Calculating sentiment columns for both positive and negative reviews\n",
"Calculating sentiment took 201.07 seconds\n"
]
}
],
"source": [
"# Add a negative sentiment and positive sentiment column\n",
"print(\"Calculating sentiment columns for both positive and negative reviews\")\n",
"start = time.time()\n",
"df[\"Negative_Sentiment\"] = df.Negative_Review.apply(calc_sentiment)\n",
"df[\"Positive_Sentiment\"] = df.Positive_Review.apply(calc_sentiment)\n",
"end = time.time()\n",
"print(\"Calculating sentiment took \" + str(round(end - start, 2)) + \" seconds\")\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" Negative_Review Negative_Sentiment\n",
"186584 So bad experience memories I hotel The first n... -0.9920\n",
"129503 First charged twice room booked booking second... -0.9896\n",
"307286 The staff Had bad experience even booking Janu... -0.9889\n",
"452092 No WLAN room Incredibly rude restaurant staff ... -0.9884\n",
"201293 We usually traveling Paris 2 3 times year busi... -0.9873\n",
"... ... ...\n",
"26899 I would say however one night expensive even d... 0.9933\n",
"138365 Wifi terribly slow I speed test network upload... 0.9938\n",
"79215 I find anything hotel first I walked past hote... 0.9938\n",
"278506 The property great location There bakery next ... 0.9945\n",
"339189 Guys I like hotel I wish return next year Howe... 0.9948\n",
"\n",
"[515738 rows x 2 columns]\n",
" Positive_Review Positive_Sentiment\n",
"137893 Bathroom Shower We going stay twice hotel 2 ni... -0.9820\n",
"5839 I completely disappointed mad since reception ... -0.9780\n",
"64158 get everything extra internet parking breakfas... -0.9751\n",
"124178 I didnt like anythig Room small Asked upgrade ... -0.9721\n",
"489137 Very rude manager abusive staff reception Dirt... -0.9703\n",
"... ... ...\n",
"331570 Everything This recently renovated hotel class... 0.9984\n",
"322920 From moment stepped doors Guesthouse Hotel sta... 0.9985\n",
"293710 This place surprise expected good actually gre... 0.9985\n",
"417442 We celebrated wedding night Langham I commend ... 0.9985\n",
"132492 We arrived super cute boutique hotel area expl... 0.9987\n",
"\n",
"[515738 rows x 2 columns]\n"
]
}
],
"source": [
"df = df.sort_values(by=[\"Negative_Sentiment\"], ascending=True)\n",
"print(df[[\"Negative_Review\", \"Negative_Sentiment\"]])\n",
"df = df.sort_values(by=[\"Positive_Sentiment\"], ascending=True)\n",
"print(df[[\"Positive_Review\", \"Positive_Sentiment\"]])\n"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"# Reorder the columns (This is cosmetic, but to make it easier to explore the data later)\n",
"df = df.reindex([\"Hotel_Name\", \"Hotel_Address\", \"Total_Number_of_Reviews\", \"Average_Score\", \"Reviewer_Score\", \"Negative_Sentiment\", \"Positive_Sentiment\", \"Reviewer_Nationality\", \"Leisure_trip\", \"Couple\", \"Solo_traveler\", \"Business_trip\", \"Group\", \"Family_with_young_children\", \"Family_with_older_children\", \"With_a_pet\", \"Negative_Review\", \"Positive_Review\"], axis=1)\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Saving results to Hotel_Reviews_NLP.csv\n"
]
}
],
"source": [
"print(\"Saving results to Hotel_Reviews_NLP.csv\")\n",
"df.to_csv(r\"../../data/Hotel_Reviews_NLP.csv\", index = False)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Upozornění**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Za závazný zdroj by měl být považován originální dokument v jeho původním jazyce. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,63 @@
{
"cells": [
{
"source": [
"# Nastavení dat\n",
"\n",
"V tomto notebooku ukážeme, jak:\n",
"\n",
"nastavit časová řadová data pro tento modul\n",
"vizualizovat data\n",
"Data v tomto příkladu pocházejí ze soutěže GEFCom2014 v oblasti prognózování1. Obsahují 3 roky hodinových hodnot spotřeby elektřiny a teploty mezi lety 2012 a 2014.\n",
"\n",
"1Tao Hong, Pierre Pinson, Shu Fan, Hamidreza Zareipour, Alberto Troccoli a Rob J. Hyndman, \"Probabilistic energy forecasting: Global Energy Forecasting Competition 2014 and beyond\", International Journal of Forecasting, sv.32, č.3, str. 896-913, červenec-září, 2016.\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
],
"metadata": {
"kernel_info": {
"name": "python3"
},
"kernelspec": {
"name": "python37364bit8d3b438fb5fc4430a93ac2cb74d693a7",
"display_name": "Python 3.7.0 64-bit ('3.7')"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"nteract": {
"version": "nteract-front-end@1.0.0"
},
"metadata": {
"interpreter": {
"hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d"
}
},
"coopTranslator": {
"original_hash": "5e2bbe594906dce3aaaa736d6dac6683",
"translation_date": "2025-09-04T07:33:27+00:00",
"source_file": "7-TimeSeries/1-Introduction/working/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,50 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": 3
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "523ec472196307b3c4235337353c9ceb",
"translation_date": "2025-09-04T07:30:54+00:00",
"source_file": "7-TimeSeries/2-ARIMA/working/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [
"Tao Hong, Pierre Pinson, Shu Fan, Hamidreza Zareipour, Alberto Troccoli a Rob J. Hyndman, \"Probabilistické energetické předpovědi: Globální soutěž v energetickém předpovídání 2014 a dále\", International Journal of Forecasting, sv.32, č.3, str. 896-913, červenec-září, 2016.\n"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pip install statsmodels"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,699 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "fv9OoQsMFk5A"
},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"V tomto zápisníku si ukážeme, jak:\n",
"\n",
"- připravit 2D časové řady pro trénování modelu SVM regresoru\n",
"- implementovat SVR s RBF jádrem\n",
"- vyhodnotit model pomocí grafů a MAPE\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Importování modulů\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"sys.path.append('../../')"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "M687KNlQFp0-"
},
"outputs": [],
"source": [
"import os\n",
"import warnings\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"import datetime as dt\n",
"import math\n",
"\n",
"from sklearn.svm import SVR\n",
"from sklearn.preprocessing import MinMaxScaler\n",
"from common.utils import load_data, mape"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Cj-kfVdMGjWP"
},
"source": [
"## Příprava dat\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8fywSjC6GsRz"
},
"source": [
"### Načíst data\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 363
},
"id": "aBDkEB11Fumg",
"outputId": "99cf7987-0509-4b73-8cc2-75d7da0d2740"
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>load</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2012-01-01 00:00:00</th>\n",
" <td>2698.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 01:00:00</th>\n",
" <td>2558.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 02:00:00</th>\n",
" <td>2444.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 03:00:00</th>\n",
" <td>2402.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 04:00:00</th>\n",
" <td>2403.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" load\n",
"2012-01-01 00:00:00 2698.0\n",
"2012-01-01 01:00:00 2558.0\n",
"2012-01-01 02:00:00 2444.0\n",
"2012-01-01 03:00:00 2402.0\n",
"2012-01-01 04:00:00 2403.0"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"energy = load_data('../../data')[['load']]\n",
"energy.head(5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "O0BWP13rGnh4"
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 486
},
"id": "hGaNPKu_Gidk",
"outputId": "7f89b326-9057-4f49-efbe-cb100ebdf76d"
},
"outputs": [],
"source": [
"energy.plot(y='load', subplots=True, figsize=(15, 8), fontsize=12)\n",
"plt.xlabel('timestamp', fontsize=12)\n",
"plt.ylabel('load', fontsize=12)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "IPuNor4eGwYY"
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ysvsNyONGt0Q"
},
"outputs": [],
"source": [
"train_start_dt = '2014-11-01 00:00:00'\n",
"test_start_dt = '2014-12-30 00:00:00'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 548
},
"id": "SsfdLoPyGy9w",
"outputId": "d6d6c25b-b1f4-47e5-91d1-707e043237d7"
},
"outputs": [],
"source": [
"energy[(energy.index < test_start_dt) & (energy.index >= train_start_dt)][['load']].rename(columns={'load':'train'}) \\\n",
" .join(energy[test_start_dt:][['load']].rename(columns={'load':'test'}), how='outer') \\\n",
" .plot(y=['train', 'test'], figsize=(15, 8), fontsize=12)\n",
"plt.xlabel('timestamp', fontsize=12)\n",
"plt.ylabel('load', fontsize=12)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XbFTqBw6G1Ch"
},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Nyní je potřeba připravit data pro trénink provedením filtrování a škálování vašich dat.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "cYivRdQpHDj3",
"outputId": "a138f746-461c-4fd6-bfa6-0cee094c4aa1"
},
"outputs": [],
"source": [
"train = energy.copy()[(energy.index >= train_start_dt) & (energy.index < test_start_dt)][['load']]\n",
"test = energy.copy()[energy.index >= test_start_dt][['load']]\n",
"\n",
"print('Training data shape: ', train.shape)\n",
"print('Test data shape: ', test.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Škálujte data tak, aby byla v rozsahu (0, 1).\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 363
},
"id": "3DNntGQnZX8G",
"outputId": "210046bc-7a66-4ccd-d70d-aa4a7309949c"
},
"outputs": [],
"source": [
"scaler = MinMaxScaler()\n",
"train['load'] = scaler.fit_transform(train)\n",
"train.head(5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 206
},
"id": "26Yht-rzZexe",
"outputId": "20326077-a38a-4e78-cc5b-6fd7af95d301"
},
"outputs": [],
"source": [
"test['load'] = scaler.transform(test)\n",
"test.head(5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "x0n6jqxOQ41Z"
},
"source": [
"### Vytváření dat s časovými kroky\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "fdmxTZtOQ8xs"
},
"source": [
"Pro náš SVR transformujeme vstupní data do formy `[batch, timesteps]`. Proto přetváříme existující `train_data` a `test_data` tak, aby existovala nová dimenze, která odkazuje na časové kroky. V našem příkladu bereme `timesteps = 5`. Vstupy do modelu jsou tedy data pro první 4 časové kroky a výstupem budou data pro 5. časový krok.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Rpju-Sc2HFm0"
},
"outputs": [],
"source": [
"# Converting to numpy arrays\n",
"\n",
"train_data = train.values\n",
"test_data = test.values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Selecting the timesteps\n",
"\n",
"timesteps=None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "O-JrsrsVJhUQ",
"outputId": "c90dbe71-bacc-4ec4-b452-f82fe5aefaef"
},
"outputs": [],
"source": [
"# Converting data to 2D tensor\n",
"\n",
"train_data_timesteps=None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "exJD8AI7KE4g",
"outputId": "ce90260c-f327-427d-80f2-77307b5a6318"
},
"outputs": [],
"source": [
"# Converting test data to 2D tensor\n",
"\n",
"test_data_timesteps=None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2u0R2sIsLuq5"
},
"outputs": [],
"source": [
"x_train, y_train = None\n",
"x_test, y_test = None\n",
"\n",
"print(x_train.shape, y_train.shape)\n",
"print(x_test.shape, y_test.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8wIPOtAGLZlh"
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "EhA403BEPEiD"
},
"outputs": [],
"source": [
"# Create model using RBF kernel\n",
"\n",
"model = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "GS0UA3csMbqp",
"outputId": "d86b6f05-5742-4c1d-c2db-c40510bd4f0d"
},
"outputs": [],
"source": [
"# Fit model on training data"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Rz_x8S3UrlcF"
},
"source": [
"### Proveďte predikci modelu\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "XR0gnt3MnuYS",
"outputId": "157e40ab-9a23-4b66-a885-0d52a24b2364"
},
"outputs": [],
"source": [
"# Making predictions\n",
"\n",
"y_train_pred = None\n",
"y_test_pred = None"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_2epncg-SGzr"
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Scaling the predictions\n",
"\n",
"y_train_pred = scaler.inverse_transform(y_train_pred)\n",
"y_test_pred = scaler.inverse_transform(y_test_pred)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "xmm_YLXhq7gV",
"outputId": "18392f64-4029-49ac-c71a-a4e2411152a1"
},
"outputs": [],
"source": [
"# Scaling the original values\n",
"\n",
"y_train = scaler.inverse_transform(y_train)\n",
"y_test = scaler.inverse_transform(y_test)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "u3LBj93coHEi",
"outputId": "d4fd49e8-8c6e-4bb0-8ef9-ca0b26d725b4"
},
"outputs": [],
"source": [
"# Extract the timesteps for x-axis\n",
"\n",
"train_timestamps = None\n",
"test_timestamps = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(25,6))\n",
"# plot original output\n",
"# plot predicted output\n",
"plt.legend(['Actual','Predicted'])\n",
"plt.xlabel('Timestamp')\n",
"plt.title(\"Training data prediction\")\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "LnhzcnYtXHCm",
"outputId": "f5f0d711-f18b-4788-ad21-d4470ea2c02b"
},
"outputs": [],
"source": [
"print('MAPE for training data: ', mape(y_train_pred, y_train)*100, '%')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 225
},
"id": "53Q02FoqQH4V",
"outputId": "53e2d59b-5075-4765-ad9e-aed56c966583"
},
"outputs": [],
"source": [
"plt.figure(figsize=(10,3))\n",
"# plot original output\n",
"# plot predicted output\n",
"plt.legend(['Actual','Predicted'])\n",
"plt.xlabel('Timestamp')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "clOAUH-SXCJG",
"outputId": "a3aa85ff-126a-4a4a-cd9e-90b9cc465ef5"
},
"outputs": [],
"source": [
"print('MAPE for testing data: ', mape(y_test_pred, y_test)*100, '%')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "DHlKvVCId5ue"
},
"source": [
"## Predikce úplné datové sady\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "cOFJ45vreO0N",
"outputId": "35628e33-ecf9-4966-8036-f7ea86db6f16"
},
"outputs": [],
"source": [
"# Extracting load values as numpy array\n",
"data = None\n",
"\n",
"# Scaling\n",
"data = None\n",
"\n",
"# Transforming to 2D tensor as per model input requirement\n",
"data_timesteps=None\n",
"\n",
"# Selecting inputs and outputs from data\n",
"X, Y = None, None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ESSAdQgwexIi"
},
"outputs": [],
"source": [
"# Make model predictions\n",
"\n",
"# Inverse scale and reshape\n",
"Y_pred = None\n",
"Y = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 328
},
"id": "M_qhihN0RVVX",
"outputId": "a89cb23e-1d35-437f-9d63-8b8907e12f80"
},
"outputs": [],
"source": [
"plt.figure(figsize=(30,8))\n",
"# plot original output\n",
"# plot predicted output\n",
"plt.legend(['Actual','Predicted'])\n",
"plt.xlabel('Timestamp')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "AcN7pMYXVGTK",
"outputId": "7e1c2161-47ce-496c-9d86-7ad9ae0df770"
},
"outputs": [],
"source": [
"print('MAPE: ', mape(Y_pred, Y)*100, '%')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Za autoritativní zdroj by měl být považován původní dokument v jeho původním jazyce. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu.\n"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"collapsed_sections": [],
"name": "Recurrent_Neural_Networks.ipynb",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.1"
},
"coopTranslator": {
"original_hash": "e86ce102239a14c44585623b9b924a74",
"translation_date": "2025-09-04T07:38:57+00:00",
"source_file": "7-TimeSeries/3-SVR/working/notebook.ipynb",
"language_code": "cs"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save