chore(i18n): sync translations with latest source changes (chunk 5/6, 259 changes)

pull/918/head
localizeflow[bot] 2 weeks ago
parent a137af942c
commit a8b0709227

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": [
"在這份筆記中,我們將示範如何:\n",
"\n",
"- 準備二維時間序列數據以訓練 SVM 回歸模型\n",
"- 使用 RBF 核心實現 SVR\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": []
},
{
"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": []
},
{
"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本文件已使用人工智能翻譯服務 [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-03T20:01:15+00:00",
"source_file": "7-TimeSeries/3-SVR/working/notebook.ipynb",
"language_code": "hk"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

@ -0,0 +1,28 @@
# 時間序列預測簡介
什麼是時間序列預測?它是通過分析過去的趨勢來預測未來事件。
## 地區主題:全球電力使用 ✨
在這兩節課中,你將學習時間序列預測,一個相對較少人熟悉但在工業和商業應用等領域非常有價值的機器學習領域。雖然神經網絡可以用來提升這些模型的效用,但我們將在經典機器學習的背景下研究它們,因為這些模型能夠根據過去的表現來預測未來。
我們的地區重點是全球的電力使用,這是一個有趣的數據集,可以用來學習如何根據過去的負載模式來預測未來的電力需求。你可以看到這種預測在商業環境中是多麼有幫助。
![電網](../../../translated_images/zh-HK/electric-grid.0c21d5214db09ffa.webp)
照片由 [Peddi Sai hrithik](https://unsplash.com/@shutter_log?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 在拉賈斯坦邦的道路上拍攝的電塔,來自 [Unsplash](https://unsplash.com/s/photos/electric-india?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
## 課程
1. [時間序列預測簡介](1-Introduction/README.md)
2. [建立 ARIMA 時間序列模型](2-ARIMA/README.md)
3. [建立支持向量回歸器進行時間序列預測](3-SVR/README.md)
## 致謝
"時間序列預測簡介" 由 [Francesca Lazzeri](https://twitter.com/frlazzeri) 和 [Jen Looper](https://twitter.com/jenlooper) ⚡️ 撰寫。這些筆記本最初出現在 [Azure "Deep Learning For Time Series" repo](https://github.com/Azure/DeepLearningForTimeSeriesForecasting),由 Francesca Lazzeri 原創撰寫。SVR 課程由 [Anirban Mukherjee](https://github.com/AnirbanMukherjeeXD) 撰寫。
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,請注意自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,205 @@
# 簡介:強化學習與 Q-Learning
![機器學習中強化學習的摘要示意圖](../../../../sketchnotes/ml-reinforcement.png)
> 示意圖由 [Tomomi Imura](https://www.twitter.com/girlie_mac) 提供
強化學習涉及三個重要概念代理agent、一些狀態states以及每個狀態的一組行動actions。通過在指定狀態下執行某個行動代理會獲得一個獎勵。想像一下電腦遊戲《超級瑪利歐》。你是瑪利歐處於遊戲關卡中站在懸崖邊上。你的上方有一枚硬幣。你作為瑪利歐處於遊戲關卡中的特定位置……這就是你的狀態。向右移動一步行動會讓你掉下懸崖這會給你一個低的數值分數。然而按下跳躍按鈕可以讓你得分並保持存活。這是一個正面的結果應該給你一個正的數值分數。
通過使用強化學習和模擬器(遊戲),你可以學習如何玩遊戲以最大化獎勵,即保持存活並盡可能多地得分。
[![強化學習簡介](https://img.youtube.com/vi/lDq_en8RNOo/0.jpg)](https://www.youtube.com/watch?v=lDq_en8RNOo)
> 🎥 點擊上方圖片觀看 Dmitry 討論強化學習
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
## 前置條件與設置
在本課程中,我們將使用 Python 實驗一些代碼。你應該能夠在你的電腦或雲端環境中運行本課程的 Jupyter Notebook 代碼。
你可以打開[課程筆記本](https://github.com/microsoft/ML-For-Beginners/blob/main/8-Reinforcement/1-QLearning/notebook.ipynb),並按照課程步驟進行。
> **注意:** 如果你從雲端打開此代碼,你還需要下載 [`rlboard.py`](https://github.com/microsoft/ML-For-Beginners/blob/main/8-Reinforcement/1-QLearning/rlboard.py) 文件,該文件在筆記本代碼中使用。將其添加到與筆記本相同的目錄中。
## 簡介
在本課程中,我們將探索 **[彼得與狼](https://en.wikipedia.org/wiki/Peter_and_the_Wolf)** 的世界,靈感來自俄羅斯作曲家 [Sergei Prokofiev](https://en.wikipedia.org/wiki/Sergei_Prokofiev) 的音樂童話。我們將使用 **強化學習** 讓彼得探索他的環境,收集美味的蘋果並避免遇到狼。
**強化學習**RL是一種學習技術通過多次實驗讓我們學習代理在某個**環境**中的最佳行為。代理在這個環境中應該有某些**目標**,由**獎勵函數**定義。
## 環境
為了簡化,我們將彼得的世界視為一個大小為 `width` x `height` 的方形棋盤,如下所示:
![彼得的環境](../../../../8-Reinforcement/1-QLearning/images/environment.png)
棋盤中的每個格子可以是:
* **地面**,彼得和其他生物可以在上面行走。
* **水域**,顯然不能行走。
* **樹木**或**草地**,可以休息的地方。
* **蘋果**,彼得希望找到以餵飽自己。
* **狼**,危險且應該避免。
有一個單獨的 Python 模塊 [`rlboard.py`](https://github.com/microsoft/ML-For-Beginners/blob/main/8-Reinforcement/1-QLearning/rlboard.py),包含與此環境交互的代碼。由於這些代碼對理解概念並不重要,我們將導入該模塊並使用它創建示例棋盤(代碼塊 1
```python
from rlboard import *
width, height = 8,8
m = Board(width,height)
m.randomize(seed=13)
m.plot()
```
此代碼應該打印出類似上圖的環境。
## 行動與策略
在我們的例子中,彼得的目標是找到蘋果,同時避免狼和其他障礙物。為此,他可以在棋盤上四處走動,直到找到蘋果。
因此,在任何位置,他可以選擇以下行動之一:向上、向下、向左和向右。
我們將這些行動定義為一個字典,並將它們映射到相應的坐標變化。例如,向右移動(`R`)對應於坐標對 `(1,0)`。(代碼塊 2
```python
actions = { "U" : (0,-1), "D" : (0,1), "L" : (-1,0), "R" : (1,0) }
action_idx = { a : i for i,a in enumerate(actions.keys()) }
```
總結一下,此場景的策略和目標如下:
- **策略**:代理(彼得)的策略由所謂的**策略函數**policy定義。策略函數在任何給定狀態下返回行動。在我們的例子中問題的狀態由棋盤表示包括玩家的當前位置。
- **目標**:強化學習的目標是最終學習一個良好的策略,能夠高效地解決問題。然而,作為基準,我們先考慮最簡單的策略,稱為**隨機行走**。
## 隨機行走
首先,我們通過實現隨機行走策略來解決問題。在隨機行走中,我們將從允許的行動中隨機選擇下一步,直到到達蘋果(代碼塊 3
1. 使用以下代碼實現隨機行走:
```python
def random_policy(m):
return random.choice(list(actions))
def walk(m,policy,start_position=None):
n = 0 # number of steps
# set initial position
if start_position:
m.human = start_position
else:
m.random_start()
while True:
if m.at() == Board.Cell.apple:
return n # success!
if m.at() in [Board.Cell.wolf, Board.Cell.water]:
return -1 # eaten by wolf or drowned
while True:
a = actions[policy(m)]
new_pos = m.move_pos(m.human,a)
if m.is_valid(new_pos) and m.at(new_pos)!=Board.Cell.water:
m.move(a) # do the actual move
break
n+=1
walk(m,random_policy)
```
`walk` 函數的調用應返回相應路徑的長度,該長度可能因每次運行而異。
1. 多次運行行走實驗例如100 次),並打印結果統計數據(代碼塊 4
```python
def print_statistics(policy):
s,w,n = 0,0,0
for _ in range(100):
z = walk(m,policy)
if z<0:
w+=1
else:
s += z
n += 1
print(f"Average path length = {s/n}, eaten by wolf: {w} times")
print_statistics(random_policy)
```
注意,路徑的平均長度約為 30-40 步,這相當多,考慮到到最近蘋果的平均距離約為 5-6 步。
你還可以看到彼得在隨機行走中的移動情況:
![彼得的隨機行走](../../../../8-Reinforcement/1-QLearning/images/random_walk.gif)
## 獎勵函數
為了讓我們的策略更智能,我們需要了解哪些移動比其他移動“更好”。為此,我們需要定義我們的目標。
目標可以通過**獎勵函數**來定義,該函數會為每個狀態返回一些分數值。數值越高,獎勵函數越好。(代碼塊 5
```python
move_reward = -0.1
goal_reward = 10
end_reward = -10
def reward(m,pos=None):
pos = pos or m.human
if not m.is_valid(pos):
return end_reward
x = m.at(pos)
if x==Board.Cell.water or x == Board.Cell.wolf:
return end_reward
if x==Board.Cell.apple:
return goal_reward
return move_reward
```
獎勵函數的一個有趣之處在於,大多數情況下,*只有在遊戲結束時才會給予實質性獎勵*。這意味著我們的算法應該以某種方式記住導致正面獎勵的“好”步驟,並增加它們的重要性。同樣,所有導致不良結果的移動應該被抑制。
## Q-Learning
我們將討論的算法稱為 **Q-Learning**。在此算法中,策略由一個函數(或數據結構)定義,稱為 **Q-Table**。它記錄了在給定狀態下每個行動的“好壞程度”。
之所以稱為 Q-Table是因為將其表示為表格或多維數組通常很方便。由於我們的棋盤尺寸為 `width` x `height`,我們可以使用形狀為 `width` x `height` x `len(actions)` 的 numpy 數組來表示 Q-Table代碼塊 6
```python
Q = np.ones((width,height,len(actions)),dtype=np.float)*1.0/len(actions)
```
注意,我們將 Q-Table 的所有值初始化為相等值,在我們的例子中為 0.25。這對應於“隨機行走”策略,因為每個狀態中的所有移動都是同樣好的。我們可以將 Q-Table 傳遞給 `plot` 函數,以便在棋盤上可視化該表:`m.plot(Q)`。
![彼得的環境](../../../../8-Reinforcement/1-QLearning/images/env_init.png)
在每個格子的中心有一個“箭頭”,指示移動的首選方向。由於所有方向都是相等的,因此顯示為一個點。
現在我們需要運行模擬,探索環境,並學習 Q-Table 值的更好分佈,這將使我們能夠更快地找到蘋果的路徑。
## Q-Learning 的核心:貝爾曼方程
一旦我們開始移動,每個行動都會有相應的獎勵,即我們理論上可以根據最高的即時獎勵選擇下一個行動。然而,在大多數狀態下,移動並不能實現我們到達蘋果的目標,因此我們無法立即決定哪個方向更好。
> 記住,重要的不是即時結果,而是最終結果,即我們在模擬結束時獲得的結果。
為了考慮這種延遲獎勵,我們需要使用 **[動態規劃](https://en.wikipedia.org/wiki/Dynamic_programming)** 的原則,這使我們能夠以遞歸方式思考問題。
假設我們現在處於狀態 *s*,並希望移動到下一個狀態 *s'*。通過這樣做,我們將獲得由獎勵函數定義的即時獎勵 *r(s,a)*,加上一些未來的獎勵。如果我們假設 Q-Table 正確反映了每個行動的“吸引力”,那麼在狀態 *s'* 我們將選擇對應於 *Q(s',a')* 最大值的行動 *a*。因此,我們在狀態 *s* 能夠獲得的最佳未來獎勵將由 `max` 定義。
學習過程可以總結如下:
- **平均路徑長度增加**。我們觀察到,起初平均路徑長度會增加。這可能是因為當我們對環境一無所知時,很容易陷入不良狀態,例如水或狼。隨著我們學到更多並開始利用這些知識,我們可以探索更久的環境,但仍然不太清楚蘋果的位置。
- **隨著學習的深入,路徑長度減少**。當我們學到足夠多時,代理更容易達成目標,路徑長度開始減少。然而,我們仍然保持探索的開放性,因此經常偏離最佳路徑,探索新的選項,導致路徑比最佳路徑更長。
- **路徑長度突然增加**。我們在圖表中還觀察到某些時候路徑長度突然增加。這表明過程的隨機性並且我們可能在某些時候通過覆寫新的值來“破壞”Q-Table的係數。理想情況下這應該通過降低學習率來最小化例如在訓練的後期我們僅以小幅度調整Q-Table的值
總體而言,重要的是要記住,學習過程的成功和質量在很大程度上取決於參數,例如學習率、學習率衰減和折扣因子。這些通常被稱為**超參數**,以區分於**參數**後者是在訓練過程中優化的例如Q-Table的係數。尋找最佳超參數值的過程被稱為**超參數優化**,這是一個值得單獨討論的主題。
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 作業
[更真實的世界](assignment.md)
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,32 @@
# 一個更真實的世界
在我們的情境中Peter 幾乎可以不感到疲倦或飢餓地四處移動。在一個更真實的世界中,他需要時不時坐下休息,並且需要進食。讓我們通過實現以下規則,使這個世界更加真實:
1. 每次從一個地方移動到另一個地方Peter 會失去**能量**並增加一些**疲勞**。
2. Peter 可以通過吃蘋果來獲得更多能量。
3. Peter 可以通過在樹下或草地上休息來消除疲勞(即走到有樹或草的棋盤位置 - 綠色區域)。
4. Peter 需要找到並擊殺狼。
5. 為了擊殺狼Peter 需要達到一定的能量和疲勞水平,否則他會輸掉戰鬥。
## 指引
使用原始的 [notebook.ipynb](notebook.ipynb) 筆記本作為解決方案的起點。
根據遊戲規則修改上述的獎勵函數,運行強化學習算法以學習贏得遊戲的最佳策略,並比較隨機行走與您的算法在贏得和輸掉遊戲次數上的結果。
> **Note**: 在您的新世界中,狀態更加複雜,除了人類的位置之外,還包括疲勞和能量水平。您可以選擇將狀態表示為一個元組 (Board, energy, fatigue),或者為狀態定義一個類(您可能還希望從 `Board` 派生),甚至修改原始的 `Board` 類,位於 [rlboard.py](../../../../8-Reinforcement/1-QLearning/rlboard.py)。
在您的解決方案中,請保留負責隨機行走策略的代碼,並在最後比較您的算法與隨機行走的結果。
> **Note**: 您可能需要調整超參數以使其正常工作,尤其是訓練的迭代次數。由於遊戲的成功(擊敗狼)是一個罕見事件,您可以預期需要更長的訓練時間。
## 評分標準
| 評分標準 | 優秀 | 合格 | 需要改進 |
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| | 提供了一個筆記本其中定義了新世界規則、Q-Learning 算法以及一些文字解釋。Q-Learning 能夠顯著改善與隨機行走相比的結果。 | 提供了筆記本,實現了 Q-Learning 並改善了與隨機行走相比的結果,但改善不顯著;或者筆記本文檔不完整,代碼結構不佳。 | 嘗試重新定義世界規則,但 Q-Learning 算法無法正常工作,或者獎勵函數未完全定義。 |
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

File diff suppressed because one or more lines are too long

@ -0,0 +1,6 @@
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,6 @@
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,請注意自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

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,324 @@
## 前置條件
在本課中,我們將使用名為 **OpenAI Gym** 的庫來模擬不同的 **環境**。你可以在本地運行本課的代碼(例如使用 Visual Studio Code此時模擬將在新窗口中打開。如果在線運行代碼可能需要對代碼進行一些調整具體請參考 [這裡](https://towardsdatascience.com/rendering-openai-gym-envs-on-binder-and-google-colab-536f99391cc7)。
## OpenAI Gym
在上一課中,遊戲的規則和狀態是由我們自己定義的 `Board` 類提供的。在這裡,我們將使用一個特殊的 **模擬環境**,它將模擬平衡杆的物理行為。最受歡迎的用於訓練強化學習算法的模擬環境之一叫做 [Gym](https://gym.openai.com/),由 [OpenAI](https://openai.com/) 維護。通過使用這個 Gym我們可以創建不同的 **環境**,從平衡杆模擬到 Atari 遊戲。
> **注意**:你可以在 [這裡](https://gym.openai.com/envs/#classic_control) 查看 OpenAI Gym 提供的其他環境。
首先,讓我們安裝 Gym 並導入所需的庫(代碼塊 1
```python
import sys
!{sys.executable} -m pip install gym
import gym
import matplotlib.pyplot as plt
import numpy as np
import random
```
## 練習 - 初始化平衡杆環境
要處理平衡杆問題,我們需要初始化相應的環境。每個環境都與以下內容相關聯:
- **觀察空間**:定義我們從環境中接收到的信息結構。對於平衡杆問題,我們接收到杆的位置、速度以及其他一些值。
- **動作空間**:定義可能的動作。在我們的例子中,動作空間是離散的,由兩個動作組成——**左** 和 **右**。(代碼塊 2
1. 要初始化,輸入以下代碼:
```python
env = gym.make("CartPole-v1")
print(env.action_space)
print(env.observation_space)
print(env.action_space.sample())
```
要了解環境如何運作,讓我們運行一個短模擬,持續 100 步。在每一步中,我們提供一個動作——在此模擬中,我們只是隨機選擇 `action_space` 中的一個動作。
1. 運行以下代碼並查看結果。
✅ 請記住,最好在本地 Python 安裝中運行此代碼!(代碼塊 3
```python
env.reset()
for i in range(100):
env.render()
env.step(env.action_space.sample())
env.close()
```
你應該會看到類似於以下圖片的效果:
![未平衡的平衡杆](../../../../8-Reinforcement/2-Gym/images/cartpole-nobalance.gif)
1. 在模擬過程中,我們需要獲取觀察值以決定如何行動。事實上,`step` 函數返回當前的觀察值、獎勵函數以及一個 `done` 標誌,指示是否應繼續模擬:(代碼塊 4
```python
env.reset()
done = False
while not done:
env.render()
obs, rew, done, info = env.step(env.action_space.sample())
print(f"{obs} -> {rew}")
env.close()
```
你會在筆記本輸出中看到類似以下的結果:
```text
[ 0.03403272 -0.24301182 0.02669811 0.2895829 ] -> 1.0
[ 0.02917248 -0.04828055 0.03248977 0.00543839] -> 1.0
[ 0.02820687 0.14636075 0.03259854 -0.27681916] -> 1.0
[ 0.03113408 0.34100283 0.02706215 -0.55904489] -> 1.0
[ 0.03795414 0.53573468 0.01588125 -0.84308041] -> 1.0
...
[ 0.17299878 0.15868546 -0.20754175 -0.55975453] -> 1.0
[ 0.17617249 0.35602306 -0.21873684 -0.90998894] -> 1.0
```
在模擬的每一步中返回的觀察向量包含以下值:
- 小車的位置
- 小車的速度
- 杆的角度
- 杆的旋轉速率
1. 獲取這些數值的最小值和最大值:(代碼塊 5
```python
print(env.observation_space.low)
print(env.observation_space.high)
```
你可能還會注意到,在每次模擬步驟中,獎勵值始終為 1。這是因為我們的目標是盡可能長時間保持杆在合理的垂直位置。
✅ 事實上,如果我們能在 100 次連續試驗中平均獲得 195 的獎勵值,則平衡杆模擬被認為已解決。
## 狀態離散化
在 Q-Learning 中,我們需要構建 Q-表,定義在每個狀態下應採取的行動。為了做到這一點,我們需要狀態是 **離散的**,更準確地說,它應包含有限數量的離散值。因此,我們需要以某種方式 **離散化** 我們的觀察值,將它們映射到有限的狀態集合。
有幾種方法可以做到這一點:
- **分割成區間**:如果我們知道某個值的範圍,我們可以將該範圍分割成若干 **區間**,然後用該值所屬的區間編號替代原值。這可以使用 numpy 的 [`digitize`](https://numpy.org/doc/stable/reference/generated/numpy.digitize.html) 方法來完成。在這種情況下,我們將精確知道狀態的大小,因為它將取決於我們為離散化選擇的區間數量。
✅ 我們可以使用線性插值將值映射到某個有限範圍(例如,從 -20 到 20然後通過四捨五入將數字轉換為整數。這種方法對狀態大小的控制稍弱特別是當我們不知道輸入值的確切範圍時。例如在我們的例子中4 個值中的 2 個沒有上下界,這可能導致無限的狀態數量。
在我們的例子中,我們將採用第二種方法。正如你稍後可能注意到的,儘管某些值沒有明確的上下界,但它們很少超出某些有限範圍,因此具有極端值的狀態將非常罕見。
1. 以下是將模型的觀察值轉換為 4 個整數值元組的函數:(代碼塊 6
```python
def discretize(x):
return tuple((x/np.array([0.25, 0.25, 0.01, 0.1])).astype(np.int))
```
1. 我們還可以探索另一種使用區間的離散化方法:(代碼塊 7
```python
def create_bins(i,num):
return np.arange(num+1)*(i[1]-i[0])/num+i[0]
print("Sample bins for interval (-5,5) with 10 bins\n",create_bins((-5,5),10))
ints = [(-5,5),(-2,2),(-0.5,0.5),(-2,2)] # intervals of values for each parameter
nbins = [20,20,10,10] # number of bins for each parameter
bins = [create_bins(ints[i],nbins[i]) for i in range(4)]
def discretize_bins(x):
return tuple(np.digitize(x[i],bins[i]) for i in range(4))
```
1. 現在讓我們運行一個短模擬並觀察這些離散化的環境值。可以嘗試使用 `discretize``discretize_bins`,看看是否有差異。
`discretize_bins` 返回的是區間編號,從 0 開始。因此,對於接近 0 的輸入值它返回的是區間中間的編號10。在 `discretize`我們並未關注輸出值的範圍允許它們為負因此狀態值未偏移0 對應於 0。代碼塊 8
```python
env.reset()
done = False
while not done:
#env.render()
obs, rew, done, info = env.step(env.action_space.sample())
#print(discretize_bins(obs))
print(discretize(obs))
env.close()
```
✅ 如果你想查看環境的執行效果,可以取消註釋以 `env.render` 開頭的行。否則,你可以在後台執行,這樣速度更快。在我們的 Q-Learning 過程中,我們將使用這種“隱形”執行。
## Q-表結構
在上一課中,狀態是一個簡單的數字對,範圍從 0 到 8因此用形狀為 8x8x2 的 numpy 張量表示 Q-表非常方便。如果我們使用區間離散化,狀態向量的大小也是已知的,因此我們可以使用相同的方法,將狀態表示為形狀為 20x20x10x10x2 的數組(其中 2 是動作空間的維度,前幾個維度對應於我們為觀察空間中每個參數選擇的區間數量)。
然而,有時觀察空間的精確維度是未知的。在使用 `discretize` 函數的情況下,我們可能無法確定狀態是否保持在某些限制範圍內,因為某些原始值是無界的。因此,我們將使用稍微不同的方法,通過字典來表示 Q-表。
1. 使用 *(state, action)* 作為字典鍵,值則對應於 Q-表的條目值。(代碼塊 9
```python
Q = {}
actions = (0,1)
def qvalues(state):
return [Q.get((state,a),0) for a in actions]
```
在這裡,我們還定義了一個函數 `qvalues()`,它返回給定狀態對應於所有可能動作的 Q-表值列表。如果 Q-表中沒有該條目,我們將返回默認值 0。
## 開始 Q-Learning
現在我們準備教 Peter 如何保持平衡了!
1. 首先,設置一些超參數:(代碼塊 10
```python
# hyperparameters
alpha = 0.3
gamma = 0.9
epsilon = 0.90
```
其中,`alpha` 是 **學習率**,定義了我們在每一步中應調整 Q-表當前值的程度。在上一課中,我們從 1 開始,然後在訓練過程中將 `alpha` 降低到較低的值。在本例中,為了簡化,我們將保持其不變,你可以稍後嘗試調整 `alpha` 值。
`gamma`**折扣因子**,顯示了我們應優先考慮未來獎勵而非當前獎勵的程度。
`epsilon`**探索/利用因子**,決定了我們應偏向探索還是利用。在我們的算法中,我們將在 `epsilon` 百分比的情況下根據 Q-表值選擇下一個動作,而在剩餘情況下執行隨機動作。這將允許我們探索以前未見過的搜索空間區域。
✅ 就平衡而言,選擇隨機動作(探索)就像是隨機地向錯誤方向推了一下,杆需要學會如何從這些“錯誤”中恢復平衡。
### 改進算法
我們還可以對上一課的算法進行兩項改進:
- **計算平均累積獎勵**:在多次模擬中計算平均累積獎勵。我們將每 5000 次迭代打印一次進度,並將累積獎勵平均分配到這段時間內。這意味著如果我們獲得超過 195 分,我們可以認為問題已解決,並且質量甚至高於要求。
- **計算最大平均累積結果**`Qmax`,並存儲對應於該結果的 Q-表值。當你運行訓練時,你會注意到有時平均累積結果開始下降,我們希望保留訓練過程中觀察到的最佳模型所對應的 Q-表值。
1. 在每次模擬中收集所有累積獎勵到 `rewards` 向量中,以便進一步繪圖。(代碼塊 11
```python
def probs(v,eps=1e-4):
v = v-v.min()+eps
v = v/v.sum()
return v
Qmax = 0
cum_rewards = []
rewards = []
for epoch in range(100000):
obs = env.reset()
done = False
cum_reward=0
# == do the simulation ==
while not done:
s = discretize(obs)
if random.random()<epsilon:
# exploitation - chose the action according to Q-Table probabilities
v = probs(np.array(qvalues(s)))
a = random.choices(actions,weights=v)[0]
else:
# exploration - randomly chose the action
a = np.random.randint(env.action_space.n)
obs, rew, done, info = env.step(a)
cum_reward+=rew
ns = discretize(obs)
Q[(s,a)] = (1 - alpha) * Q.get((s,a),0) + alpha * (rew + gamma * max(qvalues(ns)))
cum_rewards.append(cum_reward)
rewards.append(cum_reward)
# == Periodically print results and calculate average reward ==
if epoch%5000==0:
print(f"{epoch}: {np.average(cum_rewards)}, alpha={alpha}, epsilon={epsilon}")
if np.average(cum_rewards) > Qmax:
Qmax = np.average(cum_rewards)
Qbest = Q
cum_rewards=[]
```
你可能會注意到以下結果:
- **接近目標**:我們非常接近實現目標,即在 100 次以上的連續模擬中獲得 195 的累積獎勵,或者我們可能已經達到了目標!即使我們獲得較小的數值,我們仍然不知道,因為我們平均了 5000 次運行,而正式標準只需要 100 次運行。
- **獎勵開始下降**:有時獎勵開始下降,這意味著我們可能用更糟糕的值覆蓋了 Q-表中已學到的值。
這一觀察在繪製訓練進度時更為明顯。
## 繪製訓練進度
在訓練過程中,我們將每次迭代的累積獎勵值收集到 `rewards` 向量中。以下是將其與迭代次數繪製的結果:
```python
plt.plot(rewards)
```
![原始進度](../../../../8-Reinforcement/2-Gym/images/train_progress_raw.png)
從這個圖表中,我們無法得出任何結論,因為由於隨機訓練過程的特性,訓練會話的長度差異很大。為了讓這個圖表更有意義,我們可以計算一系列實驗的 **移動平均值**,例如 100。這可以方便地使用 `np.convolve` 完成:(代碼塊 12
```python
def running_average(x,window):
return np.convolve(x,np.ones(window)/window,mode='valid')
plt.plot(running_average(rewards,100))
```
![訓練進度](../../../../8-Reinforcement/2-Gym/images/train_progress_runav.png)
## 調整超參數
為了使學習更加穩定,我們可以在訓練過程中調整一些超參數。特別是:
- **對學習率 `alpha`**:我們可以從接近 1 的值開始,然後逐漸降低該參數。隨著時間的推移,我們將在 Q-表中獲得良好的概率值,因此我們應該稍微調整它們,而不是完全用新值覆蓋。
- **增加 `epsilon`**:我們可能希望慢慢增加 `epsilon`,以便減少探索並增加利用。可能更合理的是從較低的 `epsilon` 值開始,然後逐漸增加到接近 1。
> **任務 1**:嘗試調整超參數的值,看看能否獲得更高的累積回報。你能達到超過 195 嗎?
> **任務 2**:為了正式解決這個問題,你需要在連續 100 次運行中獲得平均 195 的回報。在訓練過程中測量這一點,並確保你已經正式解決了這個問題!
## 查看結果的實際效果
觀察訓練後的模型行為會很有趣。我們來運行模擬,並按照訓練時相同的行動選擇策略進行操作,根據 Q-Table 中的概率分佈進行採樣:(代碼塊 13
```python
obs = env.reset()
done = False
while not done:
s = discretize(obs)
env.render()
v = probs(np.array(qvalues(s)))
a = random.choices(actions,weights=v)[0]
obs,_,done,_ = env.step(a)
env.close()
```
你應該會看到類似這樣的畫面:
![a balancing cartpole](../../../../8-Reinforcement/2-Gym/images/cartpole-balance.gif)
---
## 🚀挑戰
> **任務 3**:在這裡,我們使用的是 Q-Table 的最終版本,但這可能不是表現最好的版本。記得我們已經將表現最好的 Q-Table 存儲在 `Qbest` 變數中!嘗試將 `Qbest` 複製到 `Q` 中,並使用最佳表現的 Q-Table 來運行相同的例子,看看是否能發現差異。
> **任務 4**:在這裡,我們並不是每一步都選擇最佳行動,而是根據相應的概率分佈進行採樣。是否更合理每次都選擇 Q-Table 值最高的最佳行動?這可以通過使用 `np.argmax` 函數來找到對應於最高 Q-Table 值的行動編號。實現這種策略,看看是否能改善平衡效果。
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 作業
[訓練一輛山地車](assignment.md)
## 總結
我們現在已經學會如何通過提供定義遊戲期望狀態的回報函數,並讓代理智能地探索搜索空間,來訓練代理以獲得良好的結果。我們成功地將 Q-Learning 演算法應用於離散和連續環境中的情況,但行動是離散的。
同樣重要的是研究行動狀態也是連續的情況,以及觀察空間更加複雜的情況,例如來自 Atari 遊戲畫面的圖像。在這些問題中,我們通常需要使用更強大的機器學習技術,例如神經網絡,來獲得良好的結果。這些更高階的主題將是我們即將推出的進階 AI 課程的內容。
---
**免責聲明**
此文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議使用專業的人類翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,48 @@
# 訓練山地車
[OpenAI Gym](http://gym.openai.com) 的設計使得所有環境都提供相同的 API —— 即相同的方法 `reset`、`step` 和 `render`,以及相同的 **動作空間** 和 **觀察空間** 抽象。因此,應該可以用最少的代碼更改將相同的強化學習算法適配到不同的環境中。
## 山地車環境
[山地車環境](https://gym.openai.com/envs/MountainCar-v0/) 包含一輛被困在山谷中的車:
目標是通過以下其中一個動作,在每一步中讓車輛成功逃出山谷並捕獲旗幟:
| 值 | 意義 |
|------|------------------|
| 0 | 向左加速 |
| 1 | 不加速 |
| 2 | 向右加速 |
然而,這個問題的主要難點在於車輛的引擎不夠強大,無法一次性爬上山頂。因此,唯一成功的方法是來回駕駛以積累動量。
觀察空間僅包含兩個值:
| 編號 | 觀察項目 | 最小值 | 最大值 |
|------|------------------|--------|--------|
| 0 | 車輛位置 | -1.2 | 0.6 |
| 1 | 車輛速度 | -0.07 | 0.07 |
山地車的獎勵系統相當棘手:
* 如果代理到達山頂的旗幟位置(位置 = 0.5),則獲得 0 的獎勵。
* 如果代理的位置小於 0.5,則獲得 -1 的獎勵。
當車輛位置超過 0.5 或劇集長度超過 200 時,劇集終止。
## 指引
將我們的強化學習算法適配到山地車問題中。從現有的 [notebook.ipynb](notebook.ipynb) 代碼開始,替換新的環境,修改狀態離散化函數,並嘗試以最少的代碼修改使現有算法進行訓練。通過調整超參數來優化結果。
> **注意**: 可能需要調整超參數以使算法收斂。
## 評分標準
| 標準 | 優秀表現 | 合格表現 | 需要改進 |
|----------|------------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
| | 成功從 CartPole 示例中適配 Q-Learning 算法,並以最少的代碼修改解決捕獲旗幟的問題,且能在 200 步內完成。 | 從網絡上採用新的 Q-Learning 算法,但有良好的文檔記錄;或採用現有算法但未達到預期結果。 | 未能成功採用任何算法但在解決方案上有重大進展例如實現狀態離散化、Q-Table 數據結構等)。 |
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,請注意自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

File diff suppressed because one or more lines are too long

@ -0,0 +1,6 @@
---
**免責聲明**
此文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,6 @@
---
**免責聲明**
此文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原文文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

File diff suppressed because one or more lines are too long

@ -0,0 +1,58 @@
# 強化學習簡介
強化學習RL被視為機器學習的基本範式之一與監督學習和非監督學習並列。RL 的核心在於決策:做出正確的決定,或者至少從決策中學習。
想像一下你有一個模擬環境例如股票市場。如果你施加某項規定會發生什麼事它會帶來正面還是負面的影響如果發生負面影響你需要接受這種_負面強化_從中學習並改變方向。如果結果是正面的你需要基於這種_正面強化_進一步發展。
![彼得與狼](../../../translated_images/zh-HK/peter.779730f9ba3a8a8d.webp)
> 彼得和他的朋友需要逃離飢餓的狼!圖片來源:[Jen Looper](https://twitter.com/jenlooper)
## 地區主題:彼得與狼(俄羅斯)
[彼得與狼](https://en.wikipedia.org/wiki/Peter_and_the_Wolf)是一部由俄羅斯作曲家[謝爾蓋·普羅科菲耶夫](https://en.wikipedia.org/wiki/Sergei_Prokofiev)創作的音樂童話故事。故事講述了年輕的先鋒彼得勇敢地走出家門,前往森林空地追逐狼。在本節中,我們將訓練機器學習算法來幫助彼得:
- **探索**周邊地區並建立最佳導航地圖
- **學習**如何使用滑板並保持平衡,以便更快地移動。
[![彼得與狼](https://img.youtube.com/vi/Fmi5zHg4QSM/0.jpg)](https://www.youtube.com/watch?v=Fmi5zHg4QSM)
> 🎥 點擊上方圖片收聽普羅科菲耶夫的《彼得與狼》
## 強化學習
在之前的章節中,你已經看到兩個機器學習問題的例子:
- **監督學習**,我們擁有建議問題解決方案的數據集。[分類](../4-Classification/README.md)和[回歸](../2-Regression/README.md)是監督學習任務。
- **非監督學習**,我們沒有標記的訓練數據。非監督學習的主要例子是[聚類](../5-Clustering/README.md)。
在本節中,我們將介紹一種不需要標記訓練數據的新型學習問題。有幾種類型的此類問題:
- **[半監督學習](https://wikipedia.org/wiki/Semi-supervised_learning)**,我們擁有大量未標記的數據,可以用來預訓練模型。
- **[強化學習](https://wikipedia.org/wiki/Reinforcement_learning)**,代理通過在某些模擬環境中進行實驗來學習如何行為。
### 示例 - 電腦遊戲
假設你想教電腦玩遊戲,例如象棋或[超級瑪利奧](https://wikipedia.org/wiki/Super_Mario)。為了讓電腦玩遊戲,我們需要它在每個遊戲狀態下預測應該採取的行動。雖然這看起來像是一個分類問題,但實際上並不是——因為我們沒有包含狀態和相應行動的數據集。雖然我們可能擁有一些數據,例如現有的象棋比賽或玩家玩超級瑪利奧的錄像,但這些數據可能不足以涵蓋足夠多的可能狀態。
與其尋找現有的遊戲數據,**強化學習**RL的核心理念是讓電腦玩很多次並觀察結果。因此要應用強化學習我們需要兩樣東西
- **一個環境**和**一個模擬器**,允許我們多次玩遊戲。這個模擬器會定義所有的遊戲規則以及可能的狀態和行動。
- **一個獎勵函數**,告訴我們在每次行動或遊戲中表現得如何。
強化學習與其他類型的機器學習的主要區別在於RL 通常直到遊戲結束才知道自己是贏還是輸。因此,我們無法判斷某個單獨的行動是否是好的——我們只有在遊戲結束時才會收到獎勵。我們的目標是設計算法,讓我們能夠在不確定的條件下訓練模型。我們將學習一種名為**Q-learning**的 RL 算法。
## 課程
1. [強化學習與 Q-Learning 簡介](1-QLearning/README.md)
2. [使用 gym 模擬環境](2-Gym/README.md)
## 致謝
《強化學習簡介》由[德米特里·索什尼科夫](http://soshnikov.com)用♥️撰寫。
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,150 @@
# 後記:機器學習在現實世界中的應用
![機器學習在現實世界中的應用摘要](../../../../sketchnotes/ml-realworld.png)
> Sketchnote 由 [Tomomi Imura](https://www.twitter.com/girlie_mac) 創作
在這個課程中,你已經學習了許多準備數據進行訓練以及建立機器學習模型的方法。你建立了一系列經典的回歸、聚類、分類、自然語言處理和時間序列模型。恭喜你!現在,你可能會想知道這些模型的實際用途是什麼……它們在現實世界中的應用是什麼?
雖然深度學習通常是人工智能AI在業界中吸引大量關注的原因但經典的機器學習模型仍然有其價值。事實上你可能今天就已經在使用其中一些應用在這節課中你將探索八個不同的行業和專業領域如何使用這些模型來使其應用更加高效、可靠、智能並為用戶創造更多價值。
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
## 💰 金融
金融領域提供了許多機器學習的應用機會。這個領域中的許多問題都可以通過機器學習建模和解決。
### 信用卡欺詐檢測
我們在課程中學習了 [k-means 聚類](../../5-Clustering/2-K-Means/README.md),但它如何用於解決信用卡欺詐相關的問題呢?
k-means 聚類在一種稱為**異常檢測**的信用卡欺詐檢測技術中非常有用。異常值或數據集中的偏差可以告訴我們信用卡是否在正常使用,或者是否有不尋常的情況發生。根據以下鏈接的論文所示,你可以使用 k-means 聚類算法對信用卡數據進行分類,並根據每筆交易的異常程度將其分配到不同的群組。然後,你可以評估最具風險的群組以區分欺詐交易和合法交易。
[參考資料](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.680.1195&rep=rep1&type=pdf)
### 財富管理
在財富管理中,個人或公司代表客戶處理投資。他們的工作是長期維持和增長財富,因此選擇表現良好的投資至關重要。
評估特定投資表現的一種方法是通過統計回歸。[線性回歸](../../2-Regression/1-Tools/README.md) 是理解基金相對於某個基準表現的有價值工具。我們還可以推斷回歸結果是否具有統計顯著性,或者它們對客戶投資的影響程度。你甚至可以進一步擴展分析,使用多元回歸來考慮額外的風險因素。以下鏈接的論文展示了如何使用回歸評估特定基金的表現。
[參考資料](http://www.brightwoodventures.com/evaluating-fund-performance-using-regression/)
## 🎓 教育
教育領域也是機器學習可以應用的一個非常有趣的領域。有許多有趣的問題需要解決,例如檢測考試或文章中的作弊行為,或者管理糾正過程中的偏見(無意或有意)。
### 預測學生行為
[Coursera](https://coursera.com),一家在線開放課程提供商,有一個很棒的技術博客,討論了許多工程決策。在這個案例研究中,他們繪製了一條回歸線,試圖探索低 NPS淨推薦值評分與課程保留或退課之間的相關性。
[參考資料](https://medium.com/coursera-engineering/controlled-regression-quantifying-the-impact-of-course-quality-on-learner-retention-31f956bd592a)
### 減少偏見
[Grammarly](https://grammarly.com),一個檢查拼寫和語法錯誤的寫作助手,在其產品中使用了複雜的[自然語言處理系統](../../6-NLP/README.md)。他們在技術博客中發表了一個有趣的案例研究,討論了如何處理機器學習中的性別偏見,這也是你在我們的[公平性入門課程](../../1-Introduction/3-fairness/README.md)中學到的內容。
[參考資料](https://www.grammarly.com/blog/engineering/mitigating-gender-bias-in-autocorrect/)
## 👜 零售
零售業可以從機器學習中受益匪淺,從創造更好的客戶旅程到以最佳方式管理庫存。
### 個性化客戶旅程
在 Wayfair一家銷售家具等家居用品的公司幫助客戶找到符合其品味和需求的產品至關重要。在這篇文章中該公司的工程師描述了他們如何使用機器學習和自然語言處理來「為客戶提供合適的結果」。值得注意的是他們的查詢意圖引擎使用了實體提取、分類器訓練、資產和意見提取以及客戶評論的情感標記。這是 NLP 在在線零售中的經典應用案例。
[參考資料](https://www.aboutwayfair.com/tech-innovation/how-we-use-machine-learning-and-natural-language-processing-to-empower-search)
### 庫存管理
像 [StitchFix](https://stitchfix.com) 這樣創新且靈活的公司,一家向消費者寄送服裝的盒子服務公司,依賴機器學習進行推薦和庫存管理。他們的造型團隊與商品團隊合作,事實上:「我們的一位數據科學家使用遺傳算法並將其應用於服裝,預測出今天不存在但可能成功的服裝。我們將其提供給商品團隊,現在他們可以將其作為工具使用。」
[參考資料](https://www.zdnet.com/article/how-stitch-fix-uses-machine-learning-to-master-the-science-of-styling/)
## 🏥 醫療保健
醫療保健領域可以利用機器學習來優化研究任務以及物流問題,例如患者再入院管理或阻止疾病傳播。
### 臨床試驗管理
臨床試驗中的毒性是製藥公司的一個主要關注點。多少毒性是可以容忍的?在這項研究中,分析各種臨床試驗方法導致了一種新的方法,用於預測臨床試驗結果的概率。具體而言,他們使用隨機森林生成了一個[分類器](../../4-Classification/README.md),能夠區分不同的藥物群組。
[參考資料](https://www.sciencedirect.com/science/article/pii/S2451945616302914)
### 醫院再入院管理
醫院護理成本高昂,尤其是當患者需要再次入院時。這篇論文討論了一家公司如何使用機器學習通過[聚類](../../5-Clustering/README.md)算法來預測再入院的可能性。這些群組幫助分析師「發現可能有共同原因的再入院群組」。
[參考資料](https://healthmanagement.org/c/healthmanagement/issuearticle/hospital-readmissions-and-machine-learning)
### 疾病管理
最近的疫情突顯了機器學習在阻止疾病傳播方面的作用。在這篇文章中,你會看到 ARIMA、邏輯曲線、線性回歸和 SARIMA 的使用。「這項工作試圖計算病毒的傳播速度,並預測死亡、康復和確診病例,以便我們能更好地準備和應對。」
[參考資料](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7979218/)
## 🌲 生態與綠色科技
自然和生態由許多敏感的系統組成,動物與自然之間的相互作用尤為重要。準確測量這些系統並在出現問題時採取適當行動(例如森林火災或動物數量下降)非常重要。
### 森林管理
你在之前的課程中學習了[強化學習](../../8-Reinforcement/README.md)。它在預測自然模式時非常有用。特別是它可以用於追蹤生態問題例如森林火災和入侵物種的擴散。在加拿大一組研究人員使用強化學習從衛星圖像中建立森林火災動態模型。使用創新的「空間擴散過程SSP他們將森林火災視為「景觀中任何單元格的代理」。火災在任何時間點可以採取的行動包括向北、南、東、西擴散或不擴散。
這種方法顛覆了通常的強化學習設置因為對應的馬爾可夫決策過程MDP的動態是一個已知函數用於即時火災擴散。閱讀以下鏈接了解該研究小組使用的經典算法。
[參考資料](https://www.frontiersin.org/articles/10.3389/fict.2018.00006/full)
### 動物運動感測
雖然深度學習在視覺追蹤動物運動方面引發了革命(你可以在這裡建立自己的[北極熊追蹤器](https://docs.microsoft.com/learn/modules/build-ml-model-with-azure-stream-analytics/?WT.mc_id=academic-77952-leestott)),但經典機器學習在這項任務中仍有一席之地。
用於追蹤農場動物運動的感測器和物聯網使用了這類視覺處理,但更基本的機器學習技術對數據預處理非常有用。例如,在這篇論文中,使用各種分類器算法監測和分析羊的姿勢。你可能會認出第 335 頁上的 ROC 曲線。
[參考資料](https://druckhaus-hofmann.de/gallery/31-wj-feb-2020.pdf)
### ⚡️ 能源管理
在我們的[時間序列預測](../../7-TimeSeries/README.md)課程中,我們提到了智能停車計劃如何根據供需理解為城鎮創造收入。這篇文章詳細討論了聚類、回歸和時間序列預測如何結合起來,幫助基於智能電表預測愛爾蘭未來的能源使用。
[參考資料](https://www-cdn.knime.com/sites/default/files/inline-images/knime_bigdata_energy_timeseries_whitepaper.pdf)
## 💼 保險
保險行業是另一個使用機器學習構建和優化可行財務和精算模型的領域。
### 波動性管理
MetLife一家人壽保險提供商公開了他們如何分析和減少財務模型中的波動性。在這篇文章中你會看到二元和序數分類的可視化以及預測的可視化。
[參考資料](https://investments.metlife.com/content/dam/metlifecom/us/investments/insights/research-topics/macro-strategy/pdf/MetLifeInvestmentManagement_MachineLearnedRanking_070920.pdf)
## 🎨 藝術、文化與文學
在藝術領域,例如新聞業,有許多有趣的問題需要解決。檢測假新聞是一個巨大的挑戰,因為它已被證明能影響人們的觀點,甚至顛覆民主。博物館也可以利用機器學習,從發現文物之間的聯繫到資源規劃。
### 假新聞檢測
在當今媒體中,檢測假新聞已成為一場貓捉老鼠的遊戲。在這篇文章中,研究人員建議可以測試並部署最佳模型的系統,結合了我們學過的多種機器學習技術:「該系統基於自然語言處理從數據中提取特徵,然後使用這些特徵訓練機器學習分類器,例如 Naive Bayes、支持向量機SVM、隨機森林RF、隨機梯度下降SGD和邏輯回歸LR。」
[參考資料](https://www.irjet.net/archives/V7/i6/IRJET-V7I6688.pdf)
這篇文章展示了如何結合不同的機器學習領域來產生有趣的結果,幫助阻止假新聞的傳播和造成的實際損害;在這個案例中,動機是關於 COVID 治療的謠言引發的暴力事件。
### 博物館機器學習
博物館正處於人工智能革命的前沿,隨著技術的進步,編目和數字化收藏以及發現文物之間的聯繫變得更加容易。像 [In Codice Ratio](https://www.sciencedirect.com/science/article/abs/pii/S0306457321001035#:~:text=1.,studies%20over%20large%20historical%20sources.) 這樣的項目正在幫助解開像梵蒂岡檔案館這樣難以接觸的收藏的謎團。但博物館的商業方面也受益於機器學習模型。
例如,芝加哥藝術博物館建立了模型來預測觀眾的興趣以及他們何時會參加展覽。目標是每次用戶參觀博物館時都能創造個性化和最佳化的訪客體驗。「在 2017 財年,該模型在 1% 的準確度內預測了參觀人數和門票收入,芝加哥藝術博物館高級副總裁 Andrew Simnick 說。」
[參考資料](https://www.chicagobusiness.com/article/20180518/ISSUE01/180519840/art-institute-of-chicago-uses-data-to-make-exhibit-choices)
## 🏷 行銷
### 客戶分群
最有效的行銷策略根據不同的群組以不同方式針對客戶。在這篇文章中,討論了聚類算法的用途以支持差異化行銷。差異化行銷幫助公司提高品牌認知度、接觸更多客戶並賺取更多收入。
[參考資料](https://ai.inqline.com/machine-learning-for-marketing-customer-segmentation/)
## 🚀 挑戰
找出另一個受益於本課程中所學技術的行業,並探索它如何使用機器學習。
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
Wayfair 的數據科學團隊有幾段有趣的影片,講解他們如何在公司內使用機器學習。值得[看看](https://www.youtube.com/channel/UCe2PjkQXqOuwkW1gw6Ameuw/videos)
## 作業
[機器學習尋寶遊戲](assignment.md)
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要資訊,建議使用專業的人類翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,18 @@
# 機器學習尋寶遊戲
## 指引
在這節課中,你學到了許多使用傳統機器學習解決的真實案例。雖然深度學習、新技術和人工智能工具的應用,以及神經網絡的使用,已經加快了這些領域工具的開發速度,但使用本課程中的技術進行的傳統機器學習仍然具有重要價值。
在這項作業中,假設你正在參加一個黑客松活動。利用你在課程中學到的知識,提出一個使用傳統機器學習解決本課中討論的某個領域問題的方案。製作一個演示文稿,討論你將如何實現你的想法。如果你能收集樣本數據並建立一個機器學習模型來支持你的概念,還能獲得額外加分!
## 評分標準
| 評分標準 | 卓越表現 | 合格表現 | 需要改進 |
| -------- | ---------------------------------------------------------------- | --------------------------------------------- | --------------------- |
| | 提交了一份PowerPoint演示文稿 - 建立模型可獲額外加分 | 提交了一份基礎且缺乏創意的演示文稿 | 工作未完成 |
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,174 @@
# 後記使用負責任AI儀表板元件進行機器學習模型調試
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
## 簡介
機器學習已深刻影響我們的日常生活。AI正逐漸滲透到一些對個人及社會至關重要的系統中例如醫療保健、金融、教育和就業。例如系統和模型參與了日常決策任務如醫療診斷或欺詐檢測。因此AI的進步及其加速採用也伴隨著不斷演變的社會期望和日益增長的監管要求。我們經常看到AI系統未能達到期望的領域它們暴露出新的挑戰而政府也開始對AI解決方案進行監管。因此分析這些模型以提供公平、可靠、包容、透明和負責任的結果對每個人都至關重要。
在本課程中我們將探討一些實用工具用於評估模型是否存在負責任AI的問題。傳統的機器學習調試技術通常基於定量計算例如整體準確率或平均錯誤損失。想像一下如果您用於構建這些模型的數據缺乏某些人口統計信息例如種族、性別、政治觀點、宗教或者這些人口統計信息的比例不均衡會發生什麼情況如果模型的輸出被解釋為偏向某些人口統計信息又會如何這可能導致對敏感特徵群體的過度或不足代表從而引發模型的公平性、包容性或可靠性問題。另一個因素是機器學習模型通常被視為黑盒子這使得理解和解釋模型的預測驅動因素變得困難。當數據科學家和AI開發者缺乏足夠的工具來調試和評估模型的公平性或可信度時這些都是他們面臨的挑戰。
在本課程中,您將學習如何使用以下方法調試您的模型:
- **錯誤分析**:識別模型在數據分佈中錯誤率較高的地方。
- **模型概覽**:對不同數據群體進行比較分析,以發現模型性能指標中的差異。
- **數據分析**:調查數據是否存在過度或不足代表,可能導致模型偏向某些數據群體。
- **特徵重要性**:了解哪些特徵在全局或局部層面上驅動模型的預測。
## 前置條件
作為前置條件,請先查看[開發者的負責任AI工具](https://www.microsoft.com/ai/ai-lab-responsible-ai-dashboard)
> ![負責任AI工具的GIF](../../../../9-Real-World/2-Debugging-ML-Models/images/rai-overview.gif)
## 錯誤分析
用於衡量準確性的傳統模型性能指標通常基於正確與錯誤預測的計算。例如判斷一個模型89%的準確率和0.001的錯誤損失可以被認為是良好的性能。然而錯誤通常並非均勻分佈於您的基礎數據集中。您可能獲得89%的模型準確率但發現模型在某些數據區域的錯誤率高達42%。某些數據群體的這些失敗模式可能導致公平性或可靠性問題。了解模型表現良好或不佳的區域至關重要。模型中錯誤率較高的數據區域可能是重要的數據群體。
![分析和調試模型錯誤](../../../../9-Real-World/2-Debugging-ML-Models/images/ea-error-distribution.png)
RAI儀表板上的錯誤分析元件通過樹狀可視化展示模型失敗在各群體中的分佈情況。這有助於識別數據集中錯誤率較高的特徵或區域。通過查看模型大部分錯誤的來源您可以開始調查根本原因。您還可以創建數據群體進行分析。這些數據群體有助於調試過程確定為什麼模型在某一群體表現良好而在另一群體中出現錯誤。
![錯誤分析](../../../../9-Real-World/2-Debugging-ML-Models/images/ea-error-cohort.png)
樹狀圖上的可視化指示器有助於更快地定位問題區域。例如,樹節點的紅色陰影越深,錯誤率越高。
熱圖是另一種可視化功能,用於通過一個或兩個特徵調查錯誤率,以找出模型錯誤的貢獻者,無論是整個數據集還是群體。
![錯誤分析熱圖](../../../../9-Real-World/2-Debugging-ML-Models/images/ea-heatmap.png)
使用錯誤分析時,您可以:
* 深入了解模型失敗如何分佈於數據集以及多個輸入和特徵維度。
* 分解整體性能指標,並自動發現錯誤群體,以指導您的針對性緩解措施。
## 模型概覽
評估機器學習模型的性能需要全面了解其行為。這可以通過查看多個指標例如錯誤率、準確率、召回率、精確度或平均絕對誤差MAE來實現以發現性能指標中的差異。一個性能指標可能看起來很好但另一個指標可能暴露出不準確。此外比較整個數據集或群體中的指標差異有助於揭示模型表現良好或不佳的地方。這在查看模型在敏感特徵例如患者的種族、性別或年齡與非敏感特徵中的表現時尤為重要以揭示模型可能存在的潛在不公平。例如發現模型在包含敏感特徵的群體中錯誤率更高可以揭示模型可能存在的潛在不公平。
RAI儀表板的模型概覽元件不僅有助於分析數據群體中的性能指標還使用戶能夠比較模型在不同群體中的行為。
![數據集群體 - RAI儀表板中的模型概覽](../../../../9-Real-World/2-Debugging-ML-Models/images/model-overview-dataset-cohorts.png)
該元件的基於特徵的分析功能允許用戶縮小特定特徵中的數據子群體,以更細緻地識別異常。例如,儀表板具有內置智能,可以自動為用戶選擇的特徵生成群體(例如*"time_in_hospital < 3"**"time_in_hospital >= 7"*)。這使得用戶能夠從更大的數據群體中隔離特定特徵,以查看它是否是模型錯誤結果的關鍵影響因素。
![特徵群體 - RAI儀表板中的模型概覽](../../../../9-Real-World/2-Debugging-ML-Models/images/model-overview-feature-cohorts.png)
模型概覽元件支持兩類差異指標:
**模型性能差異**:這些指標計算所選性能指標在數據子群體之間的差異(差距)。以下是一些示例:
* 準確率差異
* 錯誤率差異
* 精確度差異
* 召回率差異
* 平均絕對誤差MAE差異
**選擇率差異**此指標包含子群體之間選擇率有利預測的差異。例如貸款批准率的差異。選擇率指的是每個類別中被分類為1的數據點比例在二元分類中或預測值的分佈在回歸中
## 數據分析
> "如果你對數據施加足夠的壓力,它會承認任何事情" - Ronald Coase
這句話聽起來極端但事實上數據確實可以被操縱以支持任何結論。有時這種操縱可能是無意的。作為人類我們都有偏見並且往往難以有意識地知道何時在數據中引入了偏見。保證AI和機器學習的公平性仍然是一個複雜的挑戰。
數據是傳統模型性能指標的一個巨大盲點。您可能擁有高準確率但這並不總是反映出數據集中可能存在的潛在數據偏見。例如如果一家公司高管職位的員工數據集中有27%的女性和73%的男性基於此數據訓練的招聘AI模型可能會主要針對男性群體進行高級職位的招聘。數據中的這種不平衡使模型的預測偏向於某一性別這揭示了AI模型中的公平性問題即性別偏見。
RAI儀表板上的數據分析元件有助於識別數據集中過度和不足代表的區域。它幫助用戶診斷由於數據不平衡或缺乏特定數據群體代表性而引入的錯誤和公平性問題的根本原因。這使得用戶能夠根據預測和實際結果、錯誤群體以及特定特徵來可視化數據集。有時發現一個代表性不足的數據群體也可能揭示模型未能很好地學習因此錯誤率較高。擁有一個數據偏見的模型不僅是一個公平性問題還表明模型不具包容性或可靠性。
![RAI儀表板上的數據分析元件](../../../../9-Real-World/2-Debugging-ML-Models/images/dataanalysis-cover.png)
使用數據分析時,您可以:
* 通過選擇不同的篩選器探索數據集統計,將數據切分為不同的維度(也稱為群體)。
* 了解數據集在不同群體和特徵群體中的分佈。
* 確定您在公平性、錯誤分析和因果關係(來自其他儀表板元件)方面的發現是否是由數據集分佈引起的。
* 決定在哪些區域收集更多數據,以減少由代表性問題、標籤噪音、特徵噪音、標籤偏見等因素引起的錯誤。
## 模型可解釋性
機器學習模型往往是黑盒子。理解哪些關鍵數據特徵驅動模型的預測可能是一項挑戰。提供模型做出某一預測的透明性非常重要。例如如果AI系統預測某位糖尿病患者有可能在30天內再次入院它應該能夠提供支持其預測的數據。提供支持數據指標可以幫助醫生或醫院做出明智的決策。此外能夠解釋模型為個別患者做出某一預測的原因有助於符合健康法規的問責要求。當您使用機器學習模型影響人們的生活時了解和解釋模型行為的驅動因素至關重要。模型的可解釋性和可解釋性有助於回答以下場景中的問題
* 模型調試:為什麼我的模型會犯這個錯誤?我如何改進我的模型?
* 人類與AI合作我如何理解並信任模型的決策
* 法規合規性:我的模型是否符合法律要求?
RAI儀表板的特徵重要性元件幫助您調試並全面了解模型如何進行預測。它也是機器學習專業人士和決策者解釋和展示影響模型行為的特徵證據的有用工具以符合法規要求。接下來用戶可以探索全局和局部解釋驗證哪些特徵驅動模型的預測。全局解釋列出影響模型整體預測的主要特徵。局部解釋顯示哪些特徵導致模型對個別案例的預測。評估局部解釋的能力在調試或審核特定案例時也很有幫助以更好地理解和解釋模型為什麼做出準確或不準確的預測。
![RAI儀表板的特徵重要性元件](../../../../9-Real-World/2-Debugging-ML-Models/images/9-feature-importance.png)
* 全局解釋:例如,哪些特徵影響糖尿病患者住院再入院模型的整體行為?
* 局部解釋例如為什麼一位60歲以上且有過住院史的糖尿病患者被預測為會或不會在30天內再次入院
在調試模型性能的過程中,特徵重要性顯示特徵在不同群體中的影響程度。它有助於在比較特徵對模型錯誤預測的影響程度時揭示異常。特徵重要性元件可以顯示特徵中的哪些值對模型結果產生了正面或負面影響。例如,如果模型做出了一個不準確的預測,該元件使您能夠深入調查並確定哪些特徵或特徵值驅動了預測。這種細節不僅有助於調試,還在審計情況下提供透明性和問責性。最後,該元件可以幫助您識別公平性問題。例如,如果某些敏感特徵(如種族或性別)在驅動模型預測中具有高度影響力,這可能表明模型存在種族或性別偏見。
![特徵重要性](../../../../9-Real-World/2-Debugging-ML-Models/images/9-features-influence.png)
使用可解釋性時,您可以:
* 通過了解哪些特徵對預測最重要判斷您的AI系統的預測是否值得信任。
* 通過首先理解模型並確定模型是否使用健康特徵或僅僅是錯誤相關性,來進行模型調試。
* 通過了解模型是否基於敏感特徵或與敏感特徵高度相關的特徵進行預測,揭示潛在的不公平來源。
* 通過生成局部解釋來展示模型的結果,建立用戶對模型決策的信任。
* 完成AI系統的法規審計以驗證模型並監控模型決策對人類的影響。
## 結論
所有RAI儀表板元件都是幫助您構建對社會危害更少且更值得信賴的機器學習模型的實用工具。它有助於防止對人權的威脅避免歧視或排除某些群體的生活機會以及減少身體或心理傷害的風險。它還通過生成局部解釋來展示模型的結果幫助建立對模型決策的信任。一些潛在的危害可以分類為
- **分配**,例如某一性別或種族被偏袒。
- **服務質量**,如果您僅針對一個特定場景訓練數據,但現實情況更為複雜,則會導致服務性能不佳。
- **刻板印象**,將某一群體與預先分配的屬性聯繫起來。
- **貶低**,不公平地批評和標籤某事或某人。
- **過度或不足的代表性**。這個概念指的是某些群體在某些職業中未被看見,而任何持續推動這種情況的服務或功能都可能造成傷害。
### Azure RAI 儀表板
[Azure RAI 儀表板](https://learn.microsoft.com/en-us/azure/machine-learning/concept-responsible-ai-dashboard?WT.mc_id=aiml-90525-ruyakubu) 是基於由領先的學術機構和組織(包括 Microsoft開發的開源工具構建的旨在幫助數據科學家和 AI 開發者更好地理解模型行為,發現並減輕 AI 模型中的不良問題。
- 透過查看 RAI 儀表板的[文件](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-responsible-ai-dashboard?WT.mc_id=aiml-90525-ruyakubu),了解如何使用不同的組件。
- 查看一些 RAI 儀表板的[範例筆記本](https://github.com/Azure/RAI-vNext-Preview/tree/main/examples/notebooks),以便在 Azure 機器學習中調試更負責任的 AI 場景。
---
## 🚀 挑戰
為了防止統計或數據偏差從一開始就被引入,我們應該:
- 確保參與系統工作的團隊擁有多元化的背景和觀點
- 投資於反映社會多樣性的數據集
- 開發更好的方法來檢測和修正偏差
思考在模型構建和使用中不公平的真實場景。我們還應該考慮什麼?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
在本課中,你已學習了一些將負責任 AI 融入機器學習的實用工具。
觀看這個工作坊以更深入了解相關主題:
- 負責任 AI 儀表板:由 Besmira Nushi 和 Mehrnoosh Sameki 主講,實現 RAI 的一站式解決方案
[![負責任 AI 儀表板:實現 RAI 的一站式解決方案](https://img.youtube.com/vi/f1oaDNl3djg/0.jpg)](https://www.youtube.com/watch?v=f1oaDNl3djg "負責任 AI 儀表板:實現 RAI 的一站式解決方案")
> 🎥 點擊上方圖片觀看影片:由 Besmira Nushi 和 Mehrnoosh Sameki 主講的負責任 AI 儀表板工作坊
參考以下材料以了解更多關於負責任 AI 的資訊,以及如何構建更值得信賴的模型:
- Microsoft 的 RAI 儀表板工具,用於調試 ML 模型:[負責任 AI 工具資源](https://aka.ms/rai-dashboard)
- 探索負責任 AI 工具包:[Github](https://github.com/microsoft/responsible-ai-toolbox)
- Microsoft 的 RAI 資源中心:[負責任 AI 資源 Microsoft AI](https://www.microsoft.com/ai/responsible-ai-resources?activetab=pivot1%3aprimaryr4)
- Microsoft 的 FATE 研究小組:[FATEAI 中的公平性、問責性、透明性和倫理 - Microsoft Research](https://www.microsoft.com/research/theme/fate/)
## 作業
[探索 RAI 儀表板](assignment.md)
---
**免責聲明**
此文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,16 @@
# 探索負責任人工智能 (RAI) 儀表板
## 指引
在這節課中,你學習了關於 RAI 儀表板的內容。RAI 儀表板是一套基於「開源」工具的組件,幫助數據科學家進行錯誤分析、數據探索、公平性評估、模型可解釋性、反事實/假設情境評估以及人工智能系統的因果分析。作為這次作業的一部分,請探索一些 RAI 儀表板的示例[筆記本](https://github.com/Azure/RAI-vNext-Preview/tree/main/examples/notebooks),並在報告或演示中分享你的發現。
## 評分標準
| 評分標準 | 優秀 | 合格 | 需要改進 |
| -------- | --------- | -------- | ----------------- |
| | 提交了一份報告或 PowerPoint 演示,詳細討論了 RAI 儀表板的組件、運行的筆記本以及從中得出的結論 | 提交了一份報告,但未包含結論 | 未提交報告 |
---
**免責聲明**
此文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原文文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -0,0 +1,23 @@
# 後記:經典機器學習的實際應用
在本課程的這部分,你將了解一些經典機器學習在現實世界中的應用。我們在網絡上搜集了白皮書和文章,介紹使用這些策略的應用,儘量避免涉及神經網絡、深度學習和人工智能。了解機器學習如何應用於商業系統、生態應用、金融、藝術與文化等領域。
![chess](../../../translated_images/zh-HK/chess.e704a268781bdad8.webp)
> 照片由 <a href="https://unsplash.com/@childeye?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Alexis Fauvet</a> 提供,來源於 <a href="https://unsplash.com/s/photos/artificial-intelligence?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
## 課程
1. [機器學習的實際應用](1-Applications/README.md)
2. [使用負責任的人工智能儀表板組件進行機器學習模型調試](2-Debugging-ML-Models/README.md)
## 致謝
「機器學習的實際應用」由一個團隊撰寫,包括 [Jen Looper](https://twitter.com/jenlooper) 和 [Ornella Altunyan](https://twitter.com/ornelladotcom)。
「使用負責任的人工智能儀表板組件進行機器學習模型調試」由 [Ruth Yakubu](https://twitter.com/ruthieyakubu) 撰寫。
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,336 @@
# AGENTS.md
## 項目概述
這是 **機器學習初學者課程**一個為期12週、共26課的完整課程涵蓋使用 Python主要使用 Scikit-learn和 R 的經典機器學習概念。本倉庫設計為自學資源,包含實踐項目、測驗和作業。每節課通過來自世界各地不同文化和地區的真實數據探索機器學習概念。
主要內容:
- **教育內容**26節課涵蓋機器學習入門、回歸、分類、聚類、自然語言處理NLP、時間序列和強化學習
- **測驗應用**:基於 Vue.js 的測驗應用,提供課前和課後評估
- **多語言支持**:通過 GitHub Actions 自動翻譯至40多種語言
- **雙語支持**:課程提供 PythonJupyter notebooks和 RR Markdown 文件)版本
- **項目式學習**:每個主題都包含實踐項目和作業
## 倉庫結構
```
ML-For-Beginners/
├── 1-Introduction/ # ML basics, history, fairness, techniques
├── 2-Regression/ # Regression models with Python/R
├── 3-Web-App/ # Flask web app for ML model deployment
├── 4-Classification/ # Classification algorithms
├── 5-Clustering/ # Clustering techniques
├── 6-NLP/ # Natural Language Processing
├── 7-TimeSeries/ # Time series forecasting
├── 8-Reinforcement/ # Reinforcement learning
├── 9-Real-World/ # Real-world ML applications
├── quiz-app/ # Vue.js quiz application
├── translations/ # Auto-generated translations
└── sketchnotes/ # Visual learning aids
```
每個課程文件夾通常包含:
- `README.md` - 主要課程內容
- `notebook.ipynb` - Python Jupyter notebook
- `solution/` - 解決方案代碼Python 和 R 版本)
- `assignment.md` - 練習題
- `images/` - 視覺資源
## 設置命令
### Python 課程
大多數課程使用 Jupyter notebooks。安裝所需依賴項
```bash
# Install Python 3.8+ if not already installed
python --version
# Install Jupyter
pip install jupyter
# Install common ML libraries
pip install scikit-learn pandas numpy matplotlib seaborn
# For specific lessons, check lesson-specific requirements
# Example: Web App lesson
pip install flask
```
### R 課程
R 課程位於 `solution/R/` 文件夾中,格式為 `.rmd``.ipynb` 文件:
```bash
# Install R and required packages
# In R console:
install.packages(c("tidyverse", "tidymodels", "caret"))
```
### 測驗應用
測驗應用是一個位於 `quiz-app/` 目錄中的 Vue.js 應用:
```bash
cd quiz-app
npm install
```
### 文檔網站
本地運行文檔:
```bash
# Install Docsify
npm install -g docsify-cli
# Serve from repository root
docsify serve
# Access at http://localhost:3000
```
## 開發工作流程
### 使用課程筆記本
1. 進入課程目錄(例如 `2-Regression/1-Tools/`
2. 打開 Jupyter notebook
```bash
jupyter notebook notebook.ipynb
```
3. 完成課程內容和練習
4. 如有需要,可查看 `solution/` 文件夾中的解決方案
### Python 開發
- 課程使用標準的 Python 數據科學庫
- 使用 Jupyter notebooks 進行交互式學習
- 每節課的 `solution/` 文件夾中提供解決方案代碼
### R 開發
- R 課程以 `.rmd` 格式R Markdown提供
- 解決方案位於 `solution/R/` 子目錄中
- 使用 RStudio 或帶有 R kernel 的 Jupyter 運行 R notebooks
### 測驗應用開發
```bash
cd quiz-app
# Start development server
npm run serve
# Access at http://localhost:8080
# Build for production
npm run build
# Lint and fix files
npm run lint
```
## 測試說明
### 測驗應用測試
```bash
cd quiz-app
# Lint code
npm run lint
# Build to verify no errors
npm run build
```
**注意**:這主要是一個教育課程倉庫,課程內容沒有自動化測試。驗證通過以下方式完成:
- 完成課程練習
- 成功運行 notebook 的所有單元格
- 將輸出與解決方案中的預期結果進行比對
## 代碼風格指南
### Python 代碼
- 遵循 PEP 8 風格指南
- 使用清晰、描述性的變量名稱
- 為複雜操作添加註釋
- Jupyter notebooks 應包含解釋概念的 markdown 單元格
### JavaScript/Vue.js測驗應用
- 遵循 Vue.js 風格指南
- ESLint 配置位於 `quiz-app/package.json`
- 運行 `npm run lint` 檢查並自動修復問題
### 文檔
- Markdown 文件應清晰且結構良好
- 在圍欄代碼塊中包含代碼示例
- 使用相對鏈接進行內部引用
- 遵循現有的格式約定
## 構建和部署
### 測驗應用部署
測驗應用可以部署到 Azure 靜態 Web 應用:
1. **先決條件**
- Azure 帳戶
- GitHub 倉庫(已經 fork
2. **部署到 Azure**
- 創建 Azure 靜態 Web 應用資源
- 連接到 GitHub 倉庫
- 設置應用位置:`/quiz-app`
- 設置輸出位置:`dist`
- Azure 自動創建 GitHub Actions 工作流
3. **GitHub Actions 工作流**
- 工作流文件創建於 `.github/workflows/azure-static-web-apps-*.yml`
- 推送到主分支時自動構建和部署
### 文檔 PDF
從文檔生成 PDF
```bash
npm install
npm run convert
```
## 翻譯工作流程
**重要**:翻譯通過 GitHub Actions 使用 Co-op Translator 自動完成。
- 當更改推送到 `main` 分支時,翻譯會自動生成
- **請勿手動翻譯內容** - 系統會處理
- 工作流定義於 `.github/workflows/co-op-translator.yml`
- 使用 Azure AI/OpenAI 服務進行翻譯
- 支持40多種語言
## 貢獻指南
### 對內容貢獻者的要求
1. **Fork 倉庫**並創建功能分支
2. **修改課程內容**以添加或更新課程
3. **不要修改翻譯文件** - 它們是自動生成的
4. **測試代碼** - 確保所有 notebook 單元格成功運行
5. **驗證鏈接和圖片**是否正常工作
6. **提交拉取請求**並提供清晰的描述
### 拉取請求指南
- **標題格式**`[部分] 簡要描述更改`
- 示例:`[回歸] 修正第5課中的拼寫錯誤`
- 示例:`[測驗應用] 更新依賴項`
- **提交前**
- 確保所有 notebook 單元格無錯誤執行
- 如果修改了測驗應用,運行 `npm run lint`
- 驗證 markdown 格式
- 測試任何新的代碼示例
- **拉取請求必須包含**
- 更改描述
- 更改原因
- 如果有 UI 更改,提供截圖
- **行為準則**:遵循 [Microsoft 開源行為準則](CODE_OF_CONDUCT.md)
- **CLA**:您需要簽署貢獻者許可協議
## 課程結構
每節課遵循一致的模式:
1. **課前測驗** - 測試基礎知識
2. **課程內容** - 書面指導和解釋
3. **代碼演示** - notebook 中的實踐示例
4. **知識檢查** - 驗證理解
5. **挑戰** - 獨立應用概念
6. **作業** - 延伸練習
7. **課後測驗** - 評估學習成果
## 常用命令參考
```bash
# Python/Jupyter
jupyter notebook # Start Jupyter server
jupyter notebook notebook.ipynb # Open specific notebook
pip install -r requirements.txt # Install dependencies (where available)
# Quiz App
cd quiz-app
npm install # Install dependencies
npm run serve # Development server
npm run build # Production build
npm run lint # Lint and fix
# Documentation
docsify serve # Serve documentation locally
npm run convert # Generate PDF
# Git workflow
git checkout -b feature/my-change # Create feature branch
git add . # Stage changes
git commit -m "Description" # Commit changes
git push origin feature/my-change # Push to remote
```
## 附加資源
- **Microsoft Learn 集合**[機器學習初學者模塊](https://learn.microsoft.com/en-us/collections/qrqzamz1nn2wx3?WT.mc_id=academic-77952-bethanycheum)
- **測驗應用**[在線測驗](https://ff-quizzes.netlify.app/en/ml/)
- **討論板**[GitHub Discussions](https://github.com/microsoft/ML-For-Beginners/discussions)
- **視頻教程**[YouTube 播放列表](https://aka.ms/ml-beginners-videos)
## 核心技術
- **Python**機器學習課程的主要語言Scikit-learn, Pandas, NumPy, Matplotlib
- **R**:使用 tidyverse, tidymodels, caret 的替代實現
- **Jupyter**Python 課程的交互式筆記本
- **R Markdown**R 課程的文檔格式
- **Vue.js 3**:測驗應用框架
- **Flask**:機器學習模型部署的 Web 應用框架
- **Docsify**:文檔網站生成器
- **GitHub Actions**CI/CD 和自動翻譯
## 安全考量
- **代碼中不包含秘密信息**:切勿提交 API 密鑰或憑據
- **依賴項**:保持 npm 和 pip 包更新
- **用戶輸入**Flask Web 應用示例包含基本輸入驗證
- **敏感數據**:示例數據集是公開且無敏感信息的
## 故障排除
### Jupyter Notebooks
- **內核問題**如果單元格掛起重啟內核Kernel → Restart
- **導入錯誤**:確保使用 pip 安裝了所有所需包
- **路徑問題**:從 notebook 所在目錄運行
### 測驗應用
- **npm install 失敗**:清除 npm 緩存:`npm cache clean --force`
- **端口衝突**:更改端口:`npm run serve -- --port 8081`
- **構建錯誤**:刪除 `node_modules` 並重新安裝:`rm -rf node_modules && npm install`
### R 課程
- **未找到包**:使用以下命令安裝:`install.packages("package-name")`
- **RMarkdown 渲染**:確保已安裝 rmarkdown 包
- **內核問題**:可能需要為 Jupyter 安裝 IRkernel
## 項目特定注意事項
- 這主要是一個 **學習課程**,而非生產代碼
- 重點在於通過實踐理解 **機器學習概念**
- 代碼示例以 **清晰性優先於優化** 為原則
- 大多數課程是 **自包含的**,可獨立完成
- **提供解決方案**,但學習者應先嘗試完成練習
- 倉庫使用 **Docsify** 生成 Web 文檔,無需構建步驟
- **手繪筆記** 提供概念的視覺摘要
- **多語言支持** 使內容全球可訪問
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,14 @@
# Microsoft 開源行為準則
此項目已採用 [Microsoft 開源行為準則](https://opensource.microsoft.com/codeofconduct/)。
資源:
- [Microsoft 開源行為準則](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft 行為準則常見問題](https://opensource.microsoft.com/codeofconduct/faq/)
- 如有疑問或擔憂,請聯絡 [opencode@microsoft.com](mailto:opencode@microsoft.com)
---
**免責聲明**
此文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業的人類翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -0,0 +1,15 @@
# 貢獻
此項目歡迎各種貢獻和建議。大多數貢獻需要您同意一份貢獻者許可協議 (CLA),聲明您有權利並確實授予我們使用您貢獻的權利。詳情請訪問 https://cla.microsoft.com。
> 重要提示:在翻譯此存儲庫中的文本時,請確保不要使用機器翻譯。我們將通過社群驗證翻譯,因此請僅在您精通的語言中自願進行翻譯。
當您提交一個 pull request 時CLA 機器人會自動判斷您是否需要提供 CLA並適當地為 PR 添加標籤或評論。只需按照機器人提供的指示操作即可。您只需在所有使用我們 CLA 的存儲庫中執行一次此操作。
此項目採用了 [Microsoft 開源行為準則](https://opensource.microsoft.com/codeofconduct/)。
如需更多資訊,請參閱 [行為準則常見問題](https://opensource.microsoft.com/codeofconduct/faq/) 或聯絡 [opencode@microsoft.com](mailto:opencode@microsoft.com) 提出任何其他問題或意見。
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

File diff suppressed because it is too large Load Diff

@ -0,0 +1,222 @@
[![GitHub license](https://img.shields.io/github/license/microsoft/ML-For-Beginners.svg)](https://github.com/microsoft/ML-For-Beginners/blob/master/LICENSE)
[![GitHub contributors](https://img.shields.io/github/contributors/microsoft/ML-For-Beginners.svg)](https://GitHub.com/microsoft/ML-For-Beginners/graphs/contributors/)
[![GitHub issues](https://img.shields.io/github/issues/microsoft/ML-For-Beginners.svg)](https://GitHub.com/microsoft/ML-For-Beginners/issues/)
[![GitHub pull-requests](https://img.shields.io/github/issues-pr/microsoft/ML-For-Beginners.svg)](https://GitHub.com/microsoft/ML-For-Beginners/pulls/)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![GitHub watchers](https://img.shields.io/github/watchers/microsoft/ML-For-Beginners.svg?style=social&label=Watch)](https://GitHub.com/microsoft/ML-For-Beginners/watchers/)
[![GitHub forks](https://img.shields.io/github/forks/microsoft/ML-For-Beginners.svg?style=social&label=Fork)](https://GitHub.com/microsoft/ML-For-Beginners/network/)
[![GitHub stars](https://img.shields.io/github/stars/microsoft/ML-For-Beginners.svg?style=social&label=Star)](https://GitHub.com/microsoft/ML-For-Beginners/stargazers/)
### 🌐 多語言支援
#### 透過 GitHub Action 支援(自動且隨時更新)
<!-- CO-OP TRANSLATOR LANGUAGES TABLE START -->
[Arabic](../ar/README.md) | [Bengali](../bn/README.md) | [Bulgarian](../bg/README.md) | [Burmese (Myanmar)](../my/README.md) | [Chinese (Simplified)](../zh-CN/README.md) | [Chinese (Traditional, Hong Kong)](./README.md) | [Chinese (Traditional, Macau)](../zh-MO/README.md) | [Chinese (Traditional, Taiwan)](../zh-TW/README.md) | [Croatian](../hr/README.md) | [Czech](../cs/README.md) | [Danish](../da/README.md) | [Dutch](../nl/README.md) | [Estonian](../et/README.md) | [Finnish](../fi/README.md) | [French](../fr/README.md) | [German](../de/README.md) | [Greek](../el/README.md) | [Hebrew](../he/README.md) | [Hindi](../hi/README.md) | [Hungarian](../hu/README.md) | [Indonesian](../id/README.md) | [Italian](../it/README.md) | [Japanese](../ja/README.md) | [Kannada](../kn/README.md) | [Korean](../ko/README.md) | [Lithuanian](../lt/README.md) | [Malay](../ms/README.md) | [Malayalam](../ml/README.md) | [Marathi](../mr/README.md) | [Nepali](../ne/README.md) | [Nigerian Pidgin](../pcm/README.md) | [Norwegian](../no/README.md) | [Persian (Farsi)](../fa/README.md) | [Polish](../pl/README.md) | [Portuguese (Brazil)](../pt-BR/README.md) | [Portuguese (Portugal)](../pt-PT/README.md) | [Punjabi (Gurmukhi)](../pa/README.md) | [Romanian](../ro/README.md) | [Russian](../ru/README.md) | [Serbian (Cyrillic)](../sr/README.md) | [Slovak](../sk/README.md) | [Slovenian](../sl/README.md) | [Spanish](../es/README.md) | [Swahili](../sw/README.md) | [Swedish](../sv/README.md) | [Tagalog (Filipino)](../tl/README.md) | [Tamil](../ta/README.md) | [Telugu](../te/README.md) | [Thai](../th/README.md) | [Turkish](../tr/README.md) | [Ukrainian](../uk/README.md) | [Urdu](../ur/README.md) | [Vietnamese](../vi/README.md)
> **想要本地化克隆?**
> 本倉庫包含50多種語言的翻譯這大幅增加了下載大小。若想在不下載翻譯的情況下克隆請使用稀疏檢出
> ```bash
> git clone --filter=blob:none --sparse https://github.com/microsoft/ML-For-Beginners.git
> cd ML-For-Beginners
> git sparse-checkout set --no-cone '/*' '!translations' '!translated_images'
> ```
> 這樣能讓你以更快的速度獲得完成課程所需的所有內容。
<!-- CO-OP TRANSLATOR LANGUAGES TABLE END -->
#### 加入我們的社群
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
我們正在舉辦 Discord AI 學習系列了解更多並於2025年9月18日至30日期間加入我們詳情請見 [Learn with AI Series](https://aka.ms/learnwithai/discord)。你將獲得使用 GitHub Copilot 進行資料科學的技巧與秘訣。
![Learn with AI series](../../translated_images/zh-HK/3.9b58fd8d6c373c20.webp)
# 面向初學者的機器學習課程
> 🌍 隨我們以世界文化探索機器學習之旅 🌍
微軟的雲端倡導者很高興提供一套為期12週、共26課的 **機器學習** 課程。在此課程中,你將學習所謂的 **經典機器學習**,主要使用 Scikit-learn 庫,並避免深度學習部分,深度學習課程可參考我們的[AI 初學者課程](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
**🎨 也感謝插畫師** Tomomi Imura、Dasani Madipalli 和 Jen Looper
**🙏 特別感謝 🙏 微軟學生大使撰稿人、審查及內容貢獻者**,尤其是 Rishit Dagli、Muhammad Sakib Khan Inan、Rohan Raj、Alexandru Petrescu、Abhishek Jaiswal、Nawrin Tabassum、Ioan Samuila 和 Snigdha Agarwal
**🤩 額外感謝微軟學生大使 Eric Wanjau、Jasleen Sondhi 和 Vidushi Gupta 負責我們的 R 課程!**
# 開始使用
請依序執行下列步驟:
1. **Fork 倉庫**點選本頁右上角的「Fork」按鈕。
2. **Clone 倉庫**`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)
> 🔧 **需要協助?** 請查看我們的[故障排除指南](TROUBLESHOOTING.md),解決安裝、設定和執行課程時的常見問題。
**[學生](https://aka.ms/student-page)**,使用此課程前,請將整個倉庫 fork 至自己的 GitHub 帳號,並自行或與團隊完成練習:
- 從課前小測驗開始。
- 閱讀課程內容,完成活動,並在每個知識檢查處暫停和反思。
- 嘗試自行創建專案,理解課程內容,而非直接運行解答程式碼;但每個專案導向課程中 `/solution` 資料夾提供了完整解答程式碼。
- 進行課後小測驗。
- 完成挑戰。
- 完成作業。
- 完成一組課程後,請造訪[討論板](https://github.com/microsoft/ML-For-Beginners/discussions),透過填寫合適的 PAT 評分表來「大聲說學習」。PAT 即進度評量工具,是幫助你深化學習的評分表。你也可以回應他人的 PAT一起學習成長。
> 進一步學習,我們建議參考這些 [Microsoft Learn](https://docs.microsoft.com/en-us/users/jenlooper-2911/collections/k7o7tg1gp306q4?WT.mc_id=academic-77952-leestott) 模組和學習路徑。
**老師們**,我們也準備了一些[使用本課程的建議](for-teachers.md)。
---
## 影片導覽
部分課程提供短形式影片。你可以在課程中內嵌找到它們,或在 [Microsoft Developer YouTube 頻道的 ML for Beginners 播放列表](https://aka.ms/ml-beginners-videos)觀看,點擊下方圖片進入。
[![ML for beginners banner](../../translated_images/zh-HK/ml-for-beginners-video-banner.63f694a100034bc6.webp)](https://aka.ms/ml-beginners-videos)
---
## 團隊介紹
[![Promo video](../../images/ml.gif)](https://youtu.be/Tj1XWrDSYJU)
**動圖製作者** [Mohit Jaisal](https://linkedin.com/in/mohitjaisal)
> 🎥 點擊上方圖片,觀看關於本專案及其團隊的影片!
---
## 教學理念
打造本課程時,我們秉持兩大教學原則:確保為動手實作的**專案導向**,並加入**頻繁的小測驗**。此外,本課程圍繞一致的**主題**,提供課程整體性與連貫感。
透過內容與專案緊密結合使學習過程更加吸引人且概念記憶更深刻。課前的低壓小測驗幫助學員設定學習目標課後測驗則加強記憶。此課程設計彈性且有趣可全程完成或部分選讀。專案由淺入深於12週結束時達到較高複雜度。本課程並附有關於機器學習實際應用的後記可作為加分作業或討論基礎。
> 請閱讀我們的[行為守則](CODE_OF_CONDUCT.md)、[貢獻指南](CONTRIBUTING.md)、[翻譯指南](TRANSLATIONS.md)以及[故障排除](TROUBLESHOOTING.md)。期待你的建設性回饋!
## 每堂課程包含
- 選擇性手繪筆記
- 選擇性補充影片
- 影片導覽(部分課程)
- [課前暖身小測驗](https://ff-quizzes.netlify.app/en/ml/)
- 書面課程說明
- 專案導向課程,逐步指導專案建構
- 知識檢查
- 挑戰任務
- 補充閱讀
- 作業
- [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
> **關於語言的說明**:課程主要以 Python 撰寫,且多數課程也有 R 版本。欲完成 R 課程,請至 `/solution` 資料夾尋找 R 課程,檔案副檔名為 .rmd代表 **R Markdown** 文件,簡單說就是將 `程式碼區塊`R 或其他語言)與 `YAML 標頭`(控制輸出格式如 PDF嵌入 `Markdown 文件`。R Markdown 是一種理想的資料科學撰寫框架讓你結合程式碼、輸出結果與筆記文字。此外R Markdown 可輸出成 PDF、HTML 或 Word 等格式。
> **有關小測驗的說明**:所有小測驗均包含在[Quiz App folder](../../quiz-app)中總共52個小測驗每個小測驗有三條問題。它們在課程內有連結但該小測驗應用程式可以於本地運行請遵循 `quiz-app` 資料夾中的說明來本地託管或部署到 Azure。
| Lesson Number | Topic | Lesson Grouping | Learning Objectives | Linked Lesson | Author |
| :-----------: | :------------------------------------------------------------: | :-------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------: |
| 01 | 機器學習簡介 | [Introduction](1-Introduction/README.md) | 學習機器學習背後的基本概念 | [Lesson](1-Introduction/1-intro-to-ML/README.md) | Muhammad |
| 02 | 機器學習的歷史 | [Introduction](1-Introduction/README.md) | 了解該領域背後的歷史 | [Lesson](1-Introduction/2-history-of-ML/README.md) | Jen and Amy |
| 03 | 公平性與機器學習 | [Introduction](1-Introduction/README.md) | 在建立及應用機器學習模型時,學生應考慮哪些重要的公平性哲學議題? | [Lesson](1-Introduction/3-fairness/README.md) | Tomomi |
| 04 | 機器學習技術 | [Introduction](1-Introduction/README.md) | 機器學習研究人員使用哪些技術來建構機器學習模型? | [Lesson](1-Introduction/4-techniques-of-ML/README.md) | Chris and Jen |
| 05 | 回歸簡介 | [Regression](2-Regression/README.md) | 開始使用 Python 及 Scikit-learn 進行回歸模型 | [Python](2-Regression/1-Tools/README.md) • [R](../../2-Regression/1-Tools/solution/R/lesson_1.html) | Jen • Eric Wanjau |
| 06 | 北美南瓜價格 🎃 | [Regression](2-Regression/README.md) | 視覺化及清理資料為機器學習做準備 | [Python](2-Regression/2-Data/README.md) • [R](../../2-Regression/2-Data/solution/R/lesson_2.html) | Jen • Eric Wanjau |
| 07 | 北美南瓜價格 🎃 | [Regression](2-Regression/README.md) | 建構線性及多項式回歸模型 | [Python](2-Regression/3-Linear/README.md) • [R](../../2-Regression/3-Linear/solution/R/lesson_3.html) | Jen and Dmitry • Eric Wanjau |
| 08 | 北美南瓜價格 🎃 | [Regression](2-Regression/README.md) | 建立邏輯回歸模型 | [Python](2-Regression/4-Logistic/README.md) • [R](../../2-Regression/4-Logistic/solution/R/lesson_4.html) | Jen • Eric Wanjau |
| 09 | 網頁應用程式 🔌 | [Web App](3-Web-App/README.md) | 建立一個網頁應用程式使用你訓練的模型 | [Python](3-Web-App/1-Web-App/README.md) | Jen |
| 10 | 分類簡介 | [Classification](4-Classification/README.md) | 清理、準備及視覺化你的資料;分類簡介 | [Python](4-Classification/1-Introduction/README.md) • [R](../../4-Classification/1-Introduction/solution/R/lesson_10.html) | Jen and Cassie • Eric Wanjau |
| 11 | 美味的亞洲及印度美食 🍜 | [Classification](4-Classification/README.md) | 分類器介紹 | [Python](4-Classification/2-Classifiers-1/README.md) • [R](../../4-Classification/2-Classifiers-1/solution/R/lesson_11.html) | Jen and Cassie • Eric Wanjau |
| 12 | 美味的亞洲及印度美食 🍜 | [Classification](4-Classification/README.md) | 更多分類器 | [Python](4-Classification/3-Classifiers-2/README.md) • [R](../../4-Classification/3-Classifiers-2/solution/R/lesson_12.html) | Jen and Cassie • Eric Wanjau |
| 13 | 美味的亞洲及印度美食 🍜 | [Classification](4-Classification/README.md) | 使用你的模型建構推薦網頁應用程式 | [Python](4-Classification/4-Applied/README.md) | Jen |
| 14 | 叢集簡介 | [Clustering](5-Clustering/README.md) | 清理、準備及視覺化你的資料;叢集介紹 | [Python](5-Clustering/1-Visualize/README.md) • [R](../../5-Clustering/1-Visualize/solution/R/lesson_14.html) | Jen • Eric Wanjau |
| 15 | 探索尼日利亞音樂口味 🎧 | [Clustering](5-Clustering/README.md) | 探索 K-平均值叢集方法 | [Python](5-Clustering/2-K-Means/README.md) • [R](../../5-Clustering/2-K-Means/solution/R/lesson_15.html) | Jen • Eric Wanjau |
| 16 | 自然語言處理入門 ☕️ | [Natural language processing](6-NLP/README.md) | 透過建造一個簡單機械人學習 NLP 基礎 | [Python](6-NLP/1-Introduction-to-NLP/README.md) | Stephen |
| 17 | 常見的 NLP 任務 ☕️ | [Natural language processing](6-NLP/README.md) | 深化你的 NLP 知識,理解處理語言結構所需的常用任務 | [Python](6-NLP/2-Tasks/README.md) | Stephen |
| 18 | 翻譯及情感分析 ♥️ | [Natural language processing](6-NLP/README.md) | 使用珍·奧斯汀進行翻譯及情感分析 | [Python](6-NLP/3-Translation-Sentiment/README.md) | Stephen |
| 19 | 歐洲浪漫酒店 ♥️ | [Natural language processing](6-NLP/README.md) | 使用酒店評論一的情感分析 | [Python](6-NLP/4-Hotel-Reviews-1/README.md) | Stephen |
| 20 | 歐洲浪漫酒店 ♥️ | [Natural language processing](6-NLP/README.md) | 使用酒店評論二的情感分析 | [Python](6-NLP/5-Hotel-Reviews-2/README.md) | Stephen |
| 21 | 時間序列預測入門 | [Time series](7-TimeSeries/README.md) | 時間序列預測介紹 | [Python](7-TimeSeries/1-Introduction/README.md) | Francesca |
| 22 | ⚡️ 世界電力使用 ⚡️ - 使用 ARIMA 進行時間序列預測 | [Time series](7-TimeSeries/README.md) | 使用 ARIMA 進行時間序列預測 | [Python](7-TimeSeries/2-ARIMA/README.md) | Francesca |
| 23 | ⚡️ 世界電力使用 ⚡️ - 使用 SVR 進行時間序列預測 | [Time series](7-TimeSeries/README.md) | 使用支持向量回歸(SVR)進行時間序列預測 | [Python](7-TimeSeries/3-SVR/README.md) | Anirban |
| 24 | 強化學習入門 | [Reinforcement learning](8-Reinforcement/README.md) | 使用 Q-Learning 介紹強化學習 | [Python](8-Reinforcement/1-QLearning/README.md) | Dmitry |
| 25 | 幫彼得避開狼群!🐺 | [Reinforcement learning](8-Reinforcement/README.md) | 強化學習 Gym | [Python](8-Reinforcement/2-Gym/README.md) | Dmitry |
| Postscript | 真實世界的機器學習場景和應用 | [ML in the Wild](9-Real-World/README.md) | 傳統機器學習有趣且富啟發性的真實世界應用 | [Lesson](9-Real-World/1-Applications/README.md) | Team |
| Postscript | 使用 RAI dashboard 進行機器學習模型除錯 | [ML in the Wild](9-Real-World/README.md) | 使用 Responsible AI dashboard 組件進行機器學習模型除錯 | [Lesson](9-Real-World/2-Debugging-ML-Models/README.md) | Ruth Yakubu |
> [在我們的 Microsoft Learn 集合中找到本課程的所有額外資源](https://learn.microsoft.com/en-us/collections/qrqzamz1nn2wx3?WT.mc_id=academic-77952-bethanycheum)
## 離線存取
你可以使用 [Docsify](https://docsify.js.org/#/) 離線運行本文件。請 fork 此 repo並在本地機器上[安裝 Docsify](https://docsify.js.org/#/quickstart),然後在此 repo 的根目錄中,輸入 `docsify serve`。網站將在本地端口3000上提供服務`localhost:3000`。
## PDF 檔案
請在此處找到帶有連結的課程綱要 PDF[here](https://microsoft.github.io/ML-For-Beginners/pdf/readme.pdf)。
## 🎒 其他課程
我們團隊還製作了其他課程!敬請查看:
<!-- CO-OP TRANSLATOR OTHER COURSES START -->
### LangChain
[![LangChain4j for Beginners](https://img.shields.io/badge/LangChain4j%20for%20Beginners-22C55E?style=for-the-badge&&labelColor=E5E7EB&color=0553D6)](https://aka.ms/langchain4j-for-beginners)
[![LangChain.js for Beginners](https://img.shields.io/badge/LangChain.js%20for%20Beginners-22C55E?style=for-the-badge&labelColor=E5E7EB&color=0553D6)](https://aka.ms/langchainjs-for-beginners?WT.mc_id=m365-94501-dwahlin)
---
### Azure / Edge / MCP / Agents
[![AZD for Beginners](https://img.shields.io/badge/AZD%20for%20Beginners-0078D4?style=for-the-badge&labelColor=E5E7EB&color=0078D4)](https://github.com/microsoft/AZD-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Edge AI for Beginners](https://img.shields.io/badge/Edge%20AI%20for%20Beginners-00B8E4?style=for-the-badge&labelColor=E5E7EB&color=00B8E4)](https://github.com/microsoft/edgeai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![MCP for Beginners](https://img.shields.io/badge/MCP%20for%20Beginners-009688?style=for-the-badge&labelColor=E5E7EB&color=009688)](https://github.com/microsoft/mcp-for-beginners?WT.mc_id=academic-105485-koreyst)
[![AI Agents for Beginners](https://img.shields.io/badge/AI%20Agents%20for%20Beginners-00C49A?style=for-the-badge&labelColor=E5E7EB&color=00C49A)](https://github.com/microsoft/ai-agents-for-beginners?WT.mc_id=academic-105485-koreyst)
---
### Generative AI Series
[![Generative AI for Beginners](https://img.shields.io/badge/Generative%20AI%20for%20Beginners-8B5CF6?style=for-the-badge&labelColor=E5E7EB&color=8B5CF6)](https://github.com/microsoft/generative-ai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Generative AI (.NET)](https://img.shields.io/badge/Generative%20AI%20(.NET)-9333EA?style=for-the-badge&labelColor=E5E7EB&color=9333EA)](https://github.com/microsoft/Generative-AI-for-beginners-dotnet?WT.mc_id=academic-105485-koreyst)
[![Generative AI (Java)](https://img.shields.io/badge/Generative%20AI%20(Java)-C084FC?style=for-the-badge&labelColor=E5E7EB&color=C084FC)](https://github.com/microsoft/generative-ai-for-beginners-java?WT.mc_id=academic-105485-koreyst)
[![Generative AI (JavaScript)](https://img.shields.io/badge/Generative%20AI%20(JavaScript)-E879F9?style=for-the-badge&labelColor=E5E7EB&color=E879F9)](https://github.com/microsoft/generative-ai-with-javascript?WT.mc_id=academic-105485-koreyst)
---
### 核心學習
[![ML for Beginners](https://img.shields.io/badge/ML%20for%20Beginners-22C55E?style=for-the-badge&labelColor=E5E7EB&color=22C55E)](https://aka.ms/ml-beginners?WT.mc_id=academic-105485-koreyst)
[![Data Science for Beginners](https://img.shields.io/badge/Data%20Science%20for%20Beginners-84CC16?style=for-the-badge&labelColor=E5E7EB&color=84CC16)](https://aka.ms/datascience-beginners?WT.mc_id=academic-105485-koreyst)
[![AI for Beginners](https://img.shields.io/badge/AI%20for%20Beginners-A3E635?style=for-the-badge&labelColor=E5E7EB&color=A3E635)](https://aka.ms/ai-beginners?WT.mc_id=academic-105485-koreyst)
[![Cybersecurity for Beginners](https://img.shields.io/badge/Cybersecurity%20for%20Beginners-F97316?style=for-the-badge&labelColor=E5E7EB&color=F97316)](https://github.com/microsoft/Security-101?WT.mc_id=academic-96948-sayoung)
[![Web Dev for Beginners](https://img.shields.io/badge/Web%20Dev%20for%20Beginners-EC4899?style=for-the-badge&labelColor=E5E7EB&color=EC4899)](https://aka.ms/webdev-beginners?WT.mc_id=academic-105485-koreyst)
[![IoT for Beginners](https://img.shields.io/badge/IoT%20for%20Beginners-14B8A6?style=for-the-badge&labelColor=E5E7EB&color=14B8A6)](https://aka.ms/iot-beginners?WT.mc_id=academic-105485-koreyst)
[![XR Development for Beginners](https://img.shields.io/badge/XR%20Development%20for%20Beginners-38BDF8?style=for-the-badge&labelColor=E5E7EB&color=38BDF8)](https://github.com/microsoft/xr-development-for-beginners?WT.mc_id=academic-105485-koreyst)
---
### Copilot 系列
[![Copilot for AI Paired Programming](https://img.shields.io/badge/Copilot%20for%20AI%20Paired%20Programming-FACC15?style=for-the-badge&labelColor=E5E7EB&color=FACC15)](https://aka.ms/GitHubCopilotAI?WT.mc_id=academic-105485-koreyst)
[![Copilot for C#/.NET](https://img.shields.io/badge/Copilot%20for%20C%23/.NET-FBBF24?style=for-the-badge&labelColor=E5E7EB&color=FBBF24)](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers?WT.mc_id=academic-105485-koreyst)
[![Copilot Adventure](https://img.shields.io/badge/Copilot%20Adventure-FDE68A?style=for-the-badge&labelColor=E5E7EB&color=FDE68A)](https://github.com/microsoft/CopilotAdventures?WT.mc_id=academic-105485-koreyst)
<!-- CO-OP TRANSLATOR OTHER COURSES END -->
## 尋求協助
如果你遇到困難或在建立 AI 應用程式時有任何問題,歡迎加入 MCP 學習者及經驗豐富的開發者討論社群。這是一個支持性強的社區,歡迎提問並自由分享知識。
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
如果你有產品回饋或在開發時遇到錯誤,請造訪:
[![Microsoft Foundry Developer Forum](https://img.shields.io/badge/GitHub-Microsoft_Foundry_Developer_Forum-blue?style=for-the-badge&logo=github&color=000000&logoColor=fff)](https://aka.ms/foundry/forum)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**免責聲明**
本文件由人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於準確性,但請注意自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要資訊,建議採用專業人工翻譯。我們不對因使用此翻譯而引起的任何誤解或誤釋負責。
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -0,0 +1,42 @@
## 安全性
Microsoft 非常重視我們軟件產品和服務的安全性,包括所有透過我們的 GitHub 組織管理的原始碼庫,這些組織包括 [Microsoft](https://github.com/Microsoft)、[Azure](https://github.com/Azure)、[DotNet](https://github.com/dotnet)、[AspNet](https://github.com/aspnet)、[Xamarin](https://github.com/xamarin) 和 [我們的 GitHub 組織](https://opensource.microsoft.com/)。
如果您認為在任何 Microsoft 擁有的原始碼庫中發現了符合 [Microsoft 對安全漏洞的定義](https://docs.microsoft.com/previous-versions/tn-archive/cc751383(v=technet.10)?WT.mc_id=academic-77952-leestott) 的安全漏洞,請按照以下描述向我們報告。
## 報告安全問題
**請勿透過公開的 GitHub 問題報告安全漏洞。**
相反,請透過 Microsoft Security Response Center (MSRC) 報告安全漏洞:[https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report)。
如果您希望在不登入的情況下提交報告,請發送電子郵件至 [secure@microsoft.com](mailto:secure@microsoft.com)。如果可能,請使用我們的 PGP 密鑰加密您的訊息;您可以從 [Microsoft Security Response Center PGP Key 頁面](https://www.microsoft.com/en-us/msrc/pgp-key-msrc) 下載密鑰。
您應該在 24 小時內收到回覆。如果因某些原因未收到回覆,請透過電子郵件跟進,以確保我們收到您的原始訊息。更多資訊可參考 [microsoft.com/msrc](https://www.microsoft.com/msrc)。
請提供以下所需資訊(盡可能提供完整),以幫助我們更好地理解問題的性質和範圍:
* 問題類型例如緩衝區溢出、SQL 注入、跨站腳本攻擊等)
* 與問題表現相關的原始碼文件的完整路徑
* 受影響原始碼的位置(標籤/分支/提交或直接 URL
* 重現問題所需的任何特殊配置
* 重現問題的逐步指示
* 概念驗證或漏洞利用代碼(如果可能)
* 問題的影響,包括攻擊者可能如何利用該問題
這些資訊將幫助我們更快速地處理您的報告。
如果您是為漏洞賞金計劃報告,提供更完整的報告可能有助於獲得更高的賞金獎勵。請訪問我們的 [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) 頁面,了解更多有關我們現行計劃的詳情。
## 優先語言
我們希望所有的溝通都使用英文。
## 政策
Microsoft 遵循 [協調漏洞披露](https://www.microsoft.com/en-us/msrc/cvd) 的原則。
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要資訊,建議使用專業的人類翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,20 @@
# 支援
## 如何提交問題及尋求協助
在提交問題之前,請先查看我們的 [故障排除指南](TROUBLESHOOTING.md),以尋找有關安裝、設置及運行課程的常見問題解決方案。
此項目使用 GitHub Issues 來追蹤錯誤及功能請求。在提交新問題之前,請先搜索現有問題以避免重複。若需提交新問題,請將您的錯誤或功能請求作為新 Issue 提交。
若需協助或對使用此項目有任何疑問,您亦可:
- 查看 [故障排除指南](TROUBLESHOOTING.md)
- 參與我們的 [Discord 討論 #ml-for-beginners 頻道](https://aka.ms/foundry/discord)
- 提交問題
## 微軟支援政策
對此存儲庫的支援僅限於上述列出的資源。
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,601 @@
# 疑難排解指南
本指南旨在幫助您解決使用《機器學習初學者》課程時常見的問題。如果您在此未找到解決方案,請查看我們的 [Discord 討論區](https://aka.ms/foundry/discord) 或 [提交問題](https://github.com/microsoft/ML-For-Beginners/issues)。
## 目錄
- [安裝問題](../..)
- [Jupyter Notebook 問題](../..)
- [Python 套件問題](../..)
- [R 環境問題](../..)
- [測驗應用程式問題](../..)
- [數據和文件路徑問題](../..)
- [常見錯誤訊息](../..)
- [性能問題](../..)
- [環境與配置](../..)
---
## 安裝問題
### Python 安裝
**問題**`python: command not found`
**解決方案**
1. 從 [python.org](https://www.python.org/downloads/) 安裝 Python 3.8 或更高版本
2. 驗證安裝:`python --version` 或 `python3 --version`
3. 在 macOS/Linux 上,可能需要使用 `python3` 而非 `python`
**問題**:多個 Python 版本導致衝突
**解決方案**
```bash
# Use virtual environments to isolate projects
python -m venv ml-env
# Activate virtual environment
# On Windows:
ml-env\Scripts\activate
# On macOS/Linux:
source ml-env/bin/activate
```
### Jupyter 安裝
**問題**`jupyter: command not found`
**解決方案**
```bash
# Install Jupyter
pip install jupyter
# Or with pip3
pip3 install jupyter
# Verify installation
jupyter --version
```
**問題**Jupyter 無法在瀏覽器中啟動
**解決方案**
```bash
# Try specifying the browser
jupyter notebook --browser=chrome
# Or copy the URL with token from terminal and paste in browser manually
# Look for: http://localhost:8888/?token=...
```
### R 安裝
**問題**R 套件無法安裝
**解決方案**
```r
# Ensure you have the latest R version
# Install packages with dependencies
install.packages(c("tidyverse", "tidymodels", "caret"), dependencies = TRUE)
# If compilation fails, try installing binary versions
install.packages("package-name", type = "binary")
```
**問題**IRkernel 無法在 Jupyter 中使用
**解決方案**
```r
# In R console
install.packages('IRkernel')
IRkernel::installspec(user = TRUE)
```
---
## Jupyter Notebook 問題
### 核心問題
**問題**:核心不斷崩潰或重啟
**解決方案**
1. 重啟核心:`Kernel → Restart`
2. 清除輸出並重啟:`Kernel → Restart & Clear Output`
3. 檢查記憶體問題(請參閱 [性能問題](../..)
4. 嘗試逐個執行單元以識別有問題的代碼
**問題**:選擇了錯誤的 Python 核心
**解決方案**
1. 檢查當前核心:`Kernel → Change Kernel`
2. 選擇正確的 Python 版本
3. 如果核心缺失,請創建它:
```bash
python -m ipykernel install --user --name=ml-env
```
**問題**:核心無法啟動
**解決方案**
```bash
# Reinstall ipykernel
pip uninstall ipykernel
pip install ipykernel
# Register the kernel again
python -m ipykernel install --user
```
### Notebook 單元問題
**問題**:單元正在執行但未顯示輸出
**解決方案**
1. 檢查單元是否仍在執行(查看 `[*]` 指示器)
2. 重啟核心並執行所有單元:`Kernel → Restart & Run All`
3. 檢查瀏覽器控制台是否有 JavaScript 錯誤(按 F12
**問題**:無法執行單元 - 點擊「執行」無反應
**解決方案**
1. 檢查 Jupyter 伺服器是否仍在終端中運行
2. 刷新瀏覽器頁面
3. 關閉並重新打開 Notebook
4. 重啟 Jupyter 伺服器
---
## Python 套件問題
### 匯入錯誤
**問題**`ModuleNotFoundError: No module named 'sklearn'`
**解決方案**
```bash
pip install scikit-learn
# Common ML packages for this course
pip install scikit-learn pandas numpy matplotlib seaborn
```
**問題**`ImportError: cannot import name 'X' from 'sklearn'`
**解決方案**
```bash
# Update scikit-learn to latest version
pip install --upgrade scikit-learn
# Check version
python -c "import sklearn; print(sklearn.__version__)"
```
### 版本衝突
**問題**:套件版本不兼容錯誤
**解決方案**
```bash
# Create a new virtual environment
python -m venv fresh-env
source fresh-env/bin/activate # or fresh-env\Scripts\activate on Windows
# Install packages fresh
pip install jupyter scikit-learn pandas numpy matplotlib seaborn
# If specific version needed
pip install scikit-learn==1.3.0
```
**問題**`pip install` 因權限錯誤而失敗
**解決方案**
```bash
# Install for current user only
pip install --user package-name
# Or use virtual environment (recommended)
python -m venv venv
source venv/bin/activate
pip install package-name
```
### 數據加載問題
**問題**:加載 CSV 文件時出現 `FileNotFoundError`
**解決方案**
```python
import os
# Check current working directory
print(os.getcwd())
# Use relative paths from notebook location
df = pd.read_csv('../../data/filename.csv')
# Or use absolute paths
df = pd.read_csv('/full/path/to/data/filename.csv')
```
---
## R 環境問題
### 套件安裝
**問題**:套件安裝因編譯錯誤而失敗
**解決方案**
```r
# Install binary version (Windows/macOS)
install.packages("package-name", type = "binary")
# Update R to latest version if packages require it
# Check R version
R.version.string
# Install system dependencies (Linux)
# For Ubuntu/Debian, in terminal:
# sudo apt-get install r-base-dev
```
**問題**`tidyverse` 無法安裝
**解決方案**
```r
# Install dependencies first
install.packages(c("rlang", "vctrs", "pillar"))
# Then install tidyverse
install.packages("tidyverse")
# Or install components individually
install.packages(c("dplyr", "ggplot2", "tidyr", "readr"))
```
### RMarkdown 問題
**問題**RMarkdown 無法渲染
**解決方案**
```r
# Install/update rmarkdown
install.packages("rmarkdown")
# Install pandoc if needed
install.packages("pandoc")
# For PDF output, install tinytex
install.packages("tinytex")
tinytex::install_tinytex()
```
---
## 測驗應用程式問題
### 構建與安裝
**問題**`npm install` 失敗
**解決方案**
```bash
# Clear npm cache
npm cache clean --force
# Remove node_modules and package-lock.json
rm -rf node_modules package-lock.json
# Reinstall
npm install
# If still fails, try with legacy peer deps
npm install --legacy-peer-deps
```
**問題**8080 端口已被佔用
**解決方案**
```bash
# Use different port
npm run serve -- --port 8081
# Or find and kill process using port 8080
# On Linux/macOS:
lsof -ti:8080 | xargs kill -9
# On Windows:
netstat -ano | findstr :8080
taskkill /PID <PID> /F
```
### 構建錯誤
**問題**`npm run build` 失敗
**解決方案**
```bash
# Check Node.js version (should be 14+)
node --version
# Update Node.js if needed
# Then clean install
rm -rf node_modules package-lock.json
npm install
npm run build
```
**問題**Linting 錯誤阻止構建
**解決方案**
```bash
# Fix auto-fixable issues
npm run lint -- --fix
# Or temporarily disable linting in build
# (not recommended for production)
```
---
## 數據和文件路徑問題
### 路徑問題
**問題**:運行 Notebook 時找不到數據文件
**解決方案**
1. **始終從 Notebook 所在目錄運行**
```bash
cd /path/to/lesson/folder
jupyter notebook
```
2. **檢查代碼中的相對路徑**
```python
# Correct path from notebook location
df = pd.read_csv('../data/filename.csv')
# Not from your terminal location
```
3. **必要時使用絕對路徑**
```python
import os
base_path = os.path.dirname(os.path.abspath(__file__))
data_path = os.path.join(base_path, 'data', 'filename.csv')
```
### 缺少數據文件
**問題**:數據集文件丟失
**解決方案**
1. 檢查數據是否應包含在倉庫中 - 大多數數據集已包含
2. 某些課程可能需要下載數據 - 查看課程 README
3. 確保已拉取最新更改:
```bash
git pull origin main
```
---
## 常見錯誤訊息
### 記憶體錯誤
**錯誤**`MemoryError` 或核心在處理數據時崩潰
**解決方案**
```python
# Load data in chunks
for chunk in pd.read_csv('large_file.csv', chunksize=10000):
process(chunk)
# Or read only needed columns
df = pd.read_csv('file.csv', usecols=['col1', 'col2'])
# Free memory when done
del large_dataframe
import gc
gc.collect()
```
### 收斂警告
**警告**`ConvergenceWarning: Maximum number of iterations reached`
**解決方案**
```python
from sklearn.linear_model import LogisticRegression
# Increase max iterations
model = LogisticRegression(max_iter=1000)
# Or scale your features first
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
```
### 繪圖問題
**問題**Jupyter 中未顯示繪圖
**解決方案**
```python
# Enable inline plotting
%matplotlib inline
# Import pyplot
import matplotlib.pyplot as plt
# Show plot explicitly
plt.plot(data)
plt.show()
```
**問題**Seaborn 繪圖顯示異常或報錯
**解決方案**
```python
import warnings
warnings.filterwarnings('ignore', category=UserWarning)
# Update to compatible version
# pip install --upgrade seaborn matplotlib
```
### Unicode/編碼錯誤
**問題**:讀取文件時出現 `UnicodeDecodeError`
**解決方案**
```python
# Specify encoding explicitly
df = pd.read_csv('file.csv', encoding='utf-8')
# Or try different encoding
df = pd.read_csv('file.csv', encoding='latin-1')
# For errors='ignore' to skip problematic characters
df = pd.read_csv('file.csv', encoding='utf-8', errors='ignore')
```
---
## 性能問題
### Notebook 執行緩慢
**問題**Notebook 運行速度非常慢
**解決方案**
1. **重啟核心以釋放記憶體**`Kernel → Restart`
2. **關閉未使用的 Notebook** 以釋放資源
3. **使用較小的數據樣本進行測試**
```python
# Work with subset during development
df_sample = df.sample(n=1000)
```
4. **分析代碼性能** 以找到瓶頸:
```python
%time operation() # Time single operation
%timeit operation() # Time with multiple runs
```
### 高記憶體使用率
**問題**:系統記憶體不足
**解決方案**
```python
# Check memory usage
df.info(memory_usage='deep')
# Optimize data types
df['column'] = df['column'].astype('int32') # Instead of int64
# Drop unnecessary columns
df = df[['col1', 'col2']] # Keep only needed columns
# Process in batches
for batch in np.array_split(df, 10):
process(batch)
```
---
## 環境與配置
### 虛擬環境問題
**問題**:虛擬環境無法激活
**解決方案**
```bash
# Windows
python -m venv venv
venv\Scripts\activate.bat
# macOS/Linux
python3 -m venv venv
source venv/bin/activate
# Check if activated (should show venv name in prompt)
which python # Should point to venv python
```
**問題**:套件已安裝但在 Notebook 中找不到
**解決方案**
```bash
# Ensure notebook uses the correct kernel
# Install ipykernel in your venv
pip install ipykernel
python -m ipykernel install --user --name=ml-env --display-name="Python (ml-env)"
# In Jupyter: Kernel → Change Kernel → Python (ml-env)
```
### Git 問題
**問題**:無法拉取最新更改 - 合併衝突
**解決方案**
```bash
# Stash your changes
git stash
# Pull latest
git pull origin main
# Reapply your changes
git stash pop
# If conflicts, resolve manually or:
git checkout --theirs path/to/file # Take remote version
git checkout --ours path/to/file # Keep your version
```
### VS Code 集成
**問題**Jupyter Notebook 無法在 VS Code 中打開
**解決方案**
1. 在 VS Code 中安裝 Python 擴展
2. 安裝 Jupyter 擴展
3. 選擇正確的 Python 解釋器:`Ctrl+Shift+P` → "Python: Select Interpreter"
4. 重啟 VS Code
---
## 其他資源
- **Discord 討論區**[在 #ml-for-beginners 頻道提問並分享解決方案](https://aka.ms/foundry/discord)
- **Microsoft Learn**[機器學習初學者模組](https://learn.microsoft.com/en-us/collections/qrqzamz1nn2wx3?WT.mc_id=academic-77952-bethanycheum)
- **視頻教程**[YouTube 播放列表](https://aka.ms/ml-beginners-videos)
- **問題追蹤器**[報告錯誤](https://github.com/microsoft/ML-For-Beginners/issues)
---
## 仍有問題?
如果您已嘗試上述解決方案但仍遇到問題:
1. **搜索現有問題**[GitHub Issues](https://github.com/microsoft/ML-For-Beginners/issues)
2. **查看 Discord 討論**[Discord Discussions](https://aka.ms/foundry/discord)
3. **提交新問題**:請包括以下內容:
- 您的操作系統及版本
- Python/R 版本
- 錯誤訊息(完整回溯)
- 重現問題的步驟
- 您已嘗試的解決方法
我們隨時為您提供幫助!🚀
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,48 @@
- 簡介
- [機器學習簡介](../1-Introduction/1-intro-to-ML/README.md)
- [機器學習的歷史](../1-Introduction/2-history-of-ML/README.md)
- [機器學習與公平性](../1-Introduction/3-fairness/README.md)
- [機器學習的技術](../1-Introduction/4-techniques-of-ML/README.md)
- 回歸分析
- [實用工具](../2-Regression/1-Tools/README.md)
- [數據](../2-Regression/2-Data/README.md)
- [線性回歸](../2-Regression/3-Linear/README.md)
- [邏輯回歸](../2-Regression/4-Logistic/README.md)
- 建立網頁應用程式
- [網頁應用程式](../3-Web-App/1-Web-App/README.md)
- 分類
- [分類簡介](../4-Classification/1-Introduction/README.md)
- [分類器 1](../4-Classification/2-Classifiers-1/README.md)
- [分類器 2](../4-Classification/3-Classifiers-2/README.md)
- [應用機器學習](../4-Classification/4-Applied/README.md)
- 聚類
- [數據可視化](../5-Clustering/1-Visualize/README.md)
- [K-Means](../5-Clustering/2-K-Means/README.md)
- 自然語言處理 (NLP)
- [自然語言處理簡介](../6-NLP/1-Introduction-to-NLP/README.md)
- [自然語言處理任務](../6-NLP/2-Tasks/README.md)
- [翻譯與情感分析](../6-NLP/3-Translation-Sentiment/README.md)
- [酒店評論 1](../6-NLP/4-Hotel-Reviews-1/README.md)
- [酒店評論 2](../6-NLP/5-Hotel-Reviews-2/README.md)
- 時間序列預測
- [時間序列預測簡介](../7-TimeSeries/1-Introduction/README.md)
- [ARIMA](../7-TimeSeries/2-ARIMA/README.md)
- [SVR](../7-TimeSeries/3-SVR/README.md)
- 強化學習
- [Q-Learning](../8-Reinforcement/1-QLearning/README.md)
- [Gym](../8-Reinforcement/2-Gym/README.md)
- 真實世界的機器學習
- [應用](../9-Real-World/1-Applications/README.md)
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,28 @@
## 給教育工作者
想在課堂上使用這套課程嗎?請隨意使用!
事實上,你可以直接在 GitHub 上使用它,透過 GitHub Classroom 來進行。
要做到這一點,請先 fork 此 repo。你需要為每一課建立一個 repo因此需要將每個文件夾提取到一個獨立的 repo。這樣[GitHub Classroom](https://classroom.github.com/classrooms) 就可以分別處理每一課。
這些[完整指引](https://github.blog/2020-03-18-set-up-your-digital-classroom-with-github-classroom/)可以幫助你了解如何設置你的課堂。
## 按原樣使用此 repo
如果你希望直接使用目前的 repo而不使用 GitHub Classroom也可以這樣做。你需要與學生溝通告訴他們一起學習哪一課。
在網上教學形式(例如 Zoom、Teams 或其他平台)中,你可以為測驗設置分組討論室,並指導學生準備學習。然後邀請學生參加測驗,並在指定時間以 "issues" 的形式提交答案。如果你希望學生公開合作完成作業,也可以採用相同的方式。
如果你更喜歡較私密的形式,可以要求學生逐課 fork 此課程到他們自己的 GitHub 私人 repo並授予你訪問權限。然後他們可以私下完成測驗和作業並通過 classroom repo 的 issues 提交給你。
在網上課堂中有很多方法可以使這套課程運作起來。請告訴我們哪種方式最適合你!
## 請分享你的想法!
我們希望這套課程能夠滿足你和學生的需求。請提供[反饋](https://forms.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR2humCsRZhxNuI79cm6n0hRUQzRVVU9VVlU5UlFLWTRLWlkyQUxORTg5WS4u)。
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為具權威性的來源。對於重要信息,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,118 @@
# 測驗
這些測驗是機器學習課程https://aka.ms/ml-beginners的課前和課後測驗。
## 專案設置
```
npm install
```
### 編譯並熱加載以進行開發
```
npm run serve
```
### 編譯並壓縮以進行生產環境使用
```
npm run build
```
### 檢查並修復文件
```
npm run lint
```
### 自定義配置
請參閱[配置參考](https://cli.vuejs.org/config/)。
致謝感謝這個測驗應用程式的原始版本https://github.com/arpan45/simple-quiz-vue
## 部署到 Azure
以下是幫助你開始的逐步指南:
1. Fork 一個 GitHub 儲存庫
確保你的靜態網站應用程式代碼在你的 GitHub 儲存庫中。Fork 此儲存庫。
2. 建立 Azure 靜態網站應用程式
- 建立並[註冊 Azure 帳戶](http://azure.microsoft.com)
- 前往 [Azure 入口網站](https://portal.azure.com)
- 點擊「建立資源」然後搜尋「Static Web App」。
- 點擊「建立」。
3. 配置靜態網站應用程式
- 基本設定:
- 訂閱:選擇你的 Azure 訂閱。
- 資源群組:建立一個新的資源群組或使用現有的資源群組。
- 名稱:為你的靜態網站應用程式提供一個名稱。
- 區域:選擇最接近你的使用者的區域。
- #### 部署詳情:
- 原始碼來源選擇「GitHub」。
- GitHub 帳戶:授權 Azure 訪問你的 GitHub 帳戶。
- 組織:選擇你的 GitHub 組織。
- 儲存庫:選擇包含靜態網站應用程式的儲存庫。
- 分支:選擇你想要部署的分支。
- #### 構建詳情:
- 構建預設值:選擇你的應用程式所使用的框架(例如 React、Angular、Vue 等)。
- 應用程式位置:指定包含應用程式代碼的文件夾(例如,如果在根目錄,則為 /)。
- API 位置:如果有 API請指定其位置可選
- 輸出位置:指定構建輸出生成的文件夾(例如 build 或 dist
4. 檢查並建立
檢查你的設置然後點擊「建立」。Azure 會設置必要的資源,並在你的儲存庫中建立一個 GitHub Actions 工作流程。
5. GitHub Actions 工作流程
Azure 會自動在你的儲存庫中建立一個 GitHub Actions 工作流程文件(.github/workflows/azure-static-web-apps-<name>.yml。這個工作流程將處理構建和部署過程。
6. 監控部署
前往你的 GitHub 儲存庫中的「Actions」標籤。
你應該會看到一個工作流程正在運行。這個工作流程會構建並部署你的靜態網站應用程式到 Azure。
當工作流程完成後,你的應用程式將在提供的 Azure URL 上線。
### 範例工作流程文件
以下是一個 GitHub Actions 工作流程文件的範例:
name: Azure Static Web Apps CI/CD
```
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main
jobs:
build_and_deploy_job:
runs-on: ubuntu-latest
name: Build and Deploy Job
steps:
- uses: actions/checkout@v2
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: "upload"
app_location: "/quiz-app" # App source code path
api_location: ""API source code path optional
output_location: "dist" #Built app content directory - optional
```
### 其他資源
- [Azure 靜態網站應用程式文件](https://learn.microsoft.com/azure/static-web-apps/getting-started)
- [GitHub Actions 文件](https://docs.github.com/actions/use-cases-and-examples/deploying/deploying-to-azure-static-web-app)
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,190 @@
Attribution-ShareAlike 4.0 國際版
=======================================================================
創用CC公司Creative Commons並非律師事務所亦不提供法律服務或法律建議。分發創用CC公共授權並不構成律師與客戶或其他關係。創用CC以「現狀」提供其授權及相關資訊。創用CC對其授權、根據授權條款和條件授權的任何材料或相關資訊不作任何保證。創用CC在法律允許的最大範圍內對因使用其授權而導致的損害不承擔任何責任。
使用創用CC公共授權
創用CC公共授權提供了一套標準條款和條件創作者及其他權利持有人可用以分享受版權及以下公共授權中指定的某些其他權利保護的原創作品及其他材料。以下考量僅供參考並非詳盡無遺亦不構成授權的一部分。
授權者的考量我們的公共授權旨在供那些有權授予公眾使用受版權及某些其他權利限制的材料的人使用。我們的授權是不可撤銷的。授權者在應用授權前應仔細閱讀並理解授權的條款和條件。授權者亦應在應用授權前確保擁有所有必要的權利以便公眾能如預期般重用材料。授權者應清楚標示任何不受授權約束的材料包括其他創用CC授權的材料或根據版權的例外或限制使用的材料。更多授權者考量
wiki.creativecommons.org/Considerations_for_licensors
公眾的考量:通過使用我們的公共授權,授權者授予公眾根據指定的條款和條件使用授權材料的許可。如果因任何原因不需要授權者的許可,例如因適用的版權例外或限制,則該使用不受授權約束。我們的授權僅授予授權者有權授予的版權及某些其他權利的許可。使用授權材料可能仍因其他原因受到限制,包括其他人對材料擁有版權或其他權利。授權者可能提出特殊要求,例如要求標示或描述所有更改。雖然我們的授權並不要求這樣做,但在合理的情況下,建議尊重這些要求。更多公眾考量:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
創用CC Attribution-ShareAlike 4.0 國際公共授權
通過行使以下定義的授權權利您接受並同意受創用CC Attribution-ShareAlike 4.0 國際公共授權(「公共授權」)的條款和條件約束。在公共授權可被解釋為合同的範圍內,您因接受這些條款和條件而獲得授權權利,授權者因根據這些條款和條件提供授權材料而獲得利益。
第1節——定義。
a. 改編材料指受版權及類似權利保護的材料,該材料基於授權材料進行翻譯、改變、編排、轉化或以其他方式修改,並需要授權者持有的版權及類似權利的許可。就本公共授權而言,若授權材料為音樂作品、表演或聲音錄製,則改編材料始終指授權材料與動態影像同步的情況。
b. 改編者授權指您根據本公共授權的條款和條件,應用於您對改編材料的版權及類似權利的授權。
c. BY-SA 兼容授權指創用CC列出的授權詳見creativecommons.org/compatiblelicenses並由創用CC批准為基本等同於本公共授權的授權。
d. 版權及類似權利指版權及/或與版權密切相關的類似權利包括但不限於表演、廣播、聲音錄製及特殊數據庫權利不論權利如何標籤或分類。就本公共授權而言第2節(b)(1)-(2)中指定的權利不屬於版權及類似權利。
e. 有效技術措施指在未獲得適當授權的情況下根據1996年12月20日通過的WIPO版權條約第11條及/或類似國際協議,無法被規避的措施。
f. 例外和限制指公平使用、公平處理及/或任何其他適用於您使用授權材料的版權及類似權利的例外或限制。
g. 授權元素指創用CC公共授權名稱中列出的授權屬性。本公共授權的授權元素為署名及相同方式共享。
h. 授權材料指授權者應用本公共授權的藝術或文學作品、數據庫或其他材料。
i. 授權權利指根據本公共授權的條款和條件授予您的權利,僅限於適用於您使用授權材料的所有版權及類似權利,且授權者有權授予。
j. 授權者指根據本公共授權授予權利的個人或實體。
k. 分享指以任何需要授權權利許可的方式或過程向公眾提供材料,例如複製、公開展示、公開表演、分發、傳播、通信或進口,以及以公眾可在其選擇的時間和地點訪問材料的方式向公眾提供材料。
l. 特殊數據庫權利指歐洲議會和理事會於1996年3月11日通過的96/9/EC指令中關於數據庫法律保護的權利以及其他在世界範圍內基本等同的權利。
m. 您指根據本公共授權行使授權權利的個人或實體。「您的」具有相應含義。
第2節——範圍。
a. 授權授予。
1. 根據本公共授權的條款和條件,授權者特此授予您全球範圍內免版稅、不可再授權、非排他性、不可撤銷的授權,行使授權材料的授權權利以:
a. 複製及分享授權材料,無論是全部還是部分;以及
b. 創作、複製及分享改編材料。
2. 例外和限制。為避免疑義,若例外和限制適用於您的使用,本公共授權不適用,您無需遵守其條款和條件。
3. 期限。本公共授權的期限在第6節(a)中指定。
4. 媒體和格式;允許技術修改。授權者授權您在所有已知或未來創建的媒體和格式中行使授權權利,並進行必要的技術修改。授權者放棄及/或同意不主張任何禁止您進行必要技術修改的權利或權威包括為繞過有效技術措施而進行的技術修改。就本公共授權而言僅進行本第2節(a)(4)授權的修改永遠不會產生改編材料。
5. 下游接收者。
a. 授權者的提供——授權材料。授權材料的每位接收者自動獲得授權者的提供,根據本公共授權的條款和條件行使授權權利。
b. 授權者的額外提供——改編材料。您提供的改編材料的每位接收者自動獲得授權者的提供,根據您應用的改編者授權的條件行使改編材料的授權權利。
c. 無下游限制。您不得對授權材料提供或施加任何額外或不同的條款和條件,或應用任何有效技術措施,若此舉限制了授權材料接收者行使授權權利。
6. 無認可。本公共授權中的任何內容均不構成或可被解釋為授權您主張或暗示您或您的使用授權材料與授權者或其他指定接收署名者有關聯、受到支持、認可或授予官方地位。
b. 其他權利。
1. 道德權利,例如完整性權利,不在本公共授權範圍內,亦不包括公眾形象、隱私及/或其他類似人格權利;然而,在可能的範圍內,授權者放棄及/或同意不主張授權者持有的任何此類權利,以有限的範圍允許您行使授權權利,但不超出此範圍。
2. 專利及商標權不在本公共授權範圍內。
3. 在可能的範圍內,授權者放棄任何直接或通過收費機構根據任何自願或可放棄的法定或強制授權計劃向您收取版稅的權利。在所有其他情況下,授權者明確保留收取此類版稅的權利。
第3節——授權條件。
您行使授權權利明確受以下條件約束。
a. 署名。
1. 如果您分享授權材料(包括修改後的形式),您必須:
a. 保留授權者隨授權材料提供的以下內容:
i. 授權材料創作者及任何其他指定接收署名者的身份,以授權者要求的任何合理方式(包括使用筆名,如有指定);
ii. 版權聲明;
iii. 提及本公共授權的通知;
iv. 提及免責聲明的通知;
v. 在合理可行的範圍內提供授權材料的URI或超鏈接
b. 表明您是否修改了授權材料,並保留任何先前修改的指示;以及
c. 表明授權材料是根據本公共授權授權的並包括本公共授權的文本或URI或超鏈接。
2. 您可根據您分享授權材料的媒介、方式及上下文以任何合理方式滿足第3節(a)(1)中的條件。例如提供包含所需信息的資源的URI或超鏈接可能是合理的。
3. 如果授權者要求您必須在合理可行的範圍內移除第3節(a)(1)(A)中要求的任何信息。
b. 相同方式共享。
除第3節(a)中的條件外,如果您分享您創作的改編材料,以下條件亦適用。
1. 您應用的改編者授權必須是具有相同授權元素的創用CC授權本版本或更高版本或BY-SA兼容授權。
2. 您必須包括您應用的改編者授權的文本或URI或超鏈接。您可根據您分享改編材料的媒介、方式及上下文以任何合理方式滿足此條件。
3. 您不得對改編材料提供或施加任何額外或不同的條款和條件,或應用任何有效技術措施,若此舉限制了根據您應用的改編者授權授予的權利。
第4節——特殊數據庫權利。
若授權權利包括適用於您使用授權材料的特殊數據庫權利:
a. 為避免疑義第2節(a)(1)授予您提取、重用、複製及分享數據庫內容全部或實質部分的權利;
b. 如果您將數據庫內容全部或實質部分納入您擁有特殊數據庫權利的數據庫中:
權利,然後您擁有原創資料庫權利的資料庫(但不包括其個別內容)屬於改編材料,
包括為了第 3(b) 節的目的;以及
c. 如果您分享資料庫的全部或大部分內容,您必須遵守第 3(a) 節中的條件。
為免生疑,本第 4 節是補充而非取代您在本公共許可下的義務,當授權權利包括其他版權及類似權利時。
第 5 節——保證免責聲明及責任限制。
a. 除非授權方另有單獨承諾,在可能的範圍內,授權方以「現狀」及「可用」的方式提供授權材料,並且不對授權材料作出任何形式的陳述或保證,包括明示、默示、法定或其他保證。這包括但不限於所有權保證、適銷性、特定用途的適用性、非侵權、隱性或其他缺陷的不存在、準確性或錯誤的存在或不存在(無論是否已知或可發現)。如果保證免責聲明在全部或部分範圍內不被允許,則此免責聲明可能不適用於您。
b. 在可能的範圍內,授權方在任何法律理論(包括但不限於疏忽)或其他情況下,均不對您因使用本公共許可或授權材料而導致的任何直接、特殊、間接、附帶、後果性、懲罰性、示範性或其他損失、成本、費用或損害承擔責任,即使授權方已被告知可能發生此類損失、成本、費用或損害。如果責任限制在全部或部分範圍內不被允許,則此限制可能不適用於您。
c. 上述保證免責聲明及責任限制應以最接近絕對免責及放棄所有責任的方式解釋,在可能的範圍內。
第 6 節——期限及終止。
a. 本公共許可適用於授權版權及類似權利的期限。然而,如果您未能遵守本公共許可,則您在本公共許可下的權利將自動終止。
b. 如果您的使用授權材料的權利根據第 6(a) 節終止,則可恢復:
1. 自您發現違規之日起 30 天內糾正違規行為的日期起自動恢復;或
2. 經授權方明確恢復。
為免生疑,本第 6(b) 節不影響授權方因您違反本公共許可而尋求補救的任何權利。
c. 為免生疑,授權方亦可隨時根據其他條款或條件提供授權材料或停止分發授權材料;然而,這不會終止本公共許可。
d. 第 1 節、第 5 節、第 6 節、第 7 節及第 8 節在本公共許可終止後仍然有效。
第 7 節——其他條款及條件。
a. 除非授權方明確同意,授權方不受您傳達的任何額外或不同條款或條件的約束。
b. 關於授權材料的任何安排、理解或協議未在此處陳述的,均與本公共許可的條款及條件分開且獨立。
第 8 節——解釋。
a. 為免生疑,本公共許可不會且不應被解釋為減少、限制、約束或施加條件於任何在未經本公共許可授權的情況下合法使用授權材料的行為。
b. 在可能的範圍內,如果本公共許可的任何條款被認為不可執行,則應自動調整至最低必要範圍以使其可執行。如果該條款無法調整,則應從本公共許可中刪除,而不影響其餘條款及條件的可執行性。
c. 除非授權方明確同意,否則本公共許可的任何條款或條件均不會被放棄,且任何未遵守的行為均不會被視為已同意。
d. 本公共許可中的任何內容均不構成或可被解釋為限制或放棄授權方或您所享有的任何特權及豁免,包括免於任何司法管轄或權限的法律程序。
=======================================================================
Creative Commons 並非其公共許可的當事方。然而Creative Commons 可選擇將其公共許可應用於其發布的材料在這些情況下將被視為“授權方”。Creative Commons 公共許可的文本已根據 CC0 公共領域奉獻被奉獻至公共領域。除非為了表明材料是根據 Creative Commons 公共許可共享或根據 Creative Commons 政策(發布於 creativecommons.org/policies允許的其他用途Creative Commons 不授權使用“Creative Commons”商標或任何其他 Creative Commons 的商標或標誌,除非事先書面同意,包括但不限於任何未經授權修改其公共許可或任何其他安排、理解或協議有關授權材料的使用。為免生疑,本段不構成本公共許可的一部分。
Creative Commons 可通過 creativecommons.org 聯繫。
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,12 @@
所有課程的手繪筆記可以在這裡下載。
🖨 如需高解析度列印TIFF版本可在 [這個倉庫](https://github.com/girliemac/a-picture-is-worth-a-1000-words/tree/main/ml/tiff) 中找到。
🎨 製作人:[Tomomi Imura](https://github.com/girliemac)Twitter: [@girlie_mac](https://twitter.com/girlie_mac)
[![CC BY-SA 4.0](https://img.shields.io/badge/License-CC%20BY--SA%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-sa/4.0/)
---
**免責聲明**
本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。

@ -0,0 +1,596 @@
{
"1-Introduction/1-intro-to-ML/README.md": {
"original_hash": "69389392fa6346e0dfa30f664b7b6fec",
"translation_date": "2025-09-06T09:14:48+00:00",
"source_file": "1-Introduction/1-intro-to-ML/README.md",
"language_code": "zh-MO"
},
"1-Introduction/1-intro-to-ML/assignment.md": {
"original_hash": "4c4698044bb8af52cfb6388a4ee0e53b",
"translation_date": "2025-08-29T21:30:30+00:00",
"source_file": "1-Introduction/1-intro-to-ML/assignment.md",
"language_code": "zh-MO"
},
"1-Introduction/2-history-of-ML/README.md": {
"original_hash": "6a05fec147e734c3e6bfa54505648e2b",
"translation_date": "2025-09-06T09:15:13+00:00",
"source_file": "1-Introduction/2-history-of-ML/README.md",
"language_code": "zh-MO"
},
"1-Introduction/2-history-of-ML/assignment.md": {
"original_hash": "eb6e4d5afd1b21a57d2b9e6d0aac3969",
"translation_date": "2025-08-29T21:33:57+00:00",
"source_file": "1-Introduction/2-history-of-ML/assignment.md",
"language_code": "zh-MO"
},
"1-Introduction/3-fairness/README.md": {
"original_hash": "9a6b702d1437c0467e3c5c28d763dac2",
"translation_date": "2025-09-06T09:13:33+00:00",
"source_file": "1-Introduction/3-fairness/README.md",
"language_code": "zh-MO"
},
"1-Introduction/3-fairness/assignment.md": {
"original_hash": "dbda60e7b1fe5f18974e7858eff0004e",
"translation_date": "2025-08-29T21:24:09+00:00",
"source_file": "1-Introduction/3-fairness/assignment.md",
"language_code": "zh-MO"
},
"1-Introduction/4-techniques-of-ML/README.md": {
"original_hash": "9d91f3af3758fdd4569fb410575995ef",
"translation_date": "2025-09-06T09:14:17+00:00",
"source_file": "1-Introduction/4-techniques-of-ML/README.md",
"language_code": "zh-MO"
},
"1-Introduction/4-techniques-of-ML/assignment.md": {
"original_hash": "70d65aeddc06170bc1aed5b27805f930",
"translation_date": "2025-08-29T21:27:28+00:00",
"source_file": "1-Introduction/4-techniques-of-ML/assignment.md",
"language_code": "zh-MO"
},
"1-Introduction/README.md": {
"original_hash": "cf8ecc83f28e5b98051d2179eca08e08",
"translation_date": "2025-08-29T21:19:25+00:00",
"source_file": "1-Introduction/README.md",
"language_code": "zh-MO"
},
"2-Regression/1-Tools/README.md": {
"original_hash": "fa81d226c71d5af7a2cade31c1c92b88",
"translation_date": "2025-09-06T09:08:07+00:00",
"source_file": "2-Regression/1-Tools/README.md",
"language_code": "zh-MO"
},
"2-Regression/1-Tools/assignment.md": {
"original_hash": "74a5cf83e4ebc302afbcbc4f418afd0a",
"translation_date": "2025-08-29T20:33:23+00:00",
"source_file": "2-Regression/1-Tools/assignment.md",
"language_code": "zh-MO"
},
"2-Regression/1-Tools/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T20:33:51+00:00",
"source_file": "2-Regression/1-Tools/solution/Julia/README.md",
"language_code": "zh-MO"
},
"2-Regression/2-Data/README.md": {
"original_hash": "7c077988328ebfe33b24d07945f16eca",
"translation_date": "2025-09-06T09:08:43+00:00",
"source_file": "2-Regression/2-Data/README.md",
"language_code": "zh-MO"
},
"2-Regression/2-Data/assignment.md": {
"original_hash": "4485a1ed4dd1b5647365e3d87456515d",
"translation_date": "2025-08-29T20:37:25+00:00",
"source_file": "2-Regression/2-Data/assignment.md",
"language_code": "zh-MO"
},
"2-Regression/2-Data/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T20:37:57+00:00",
"source_file": "2-Regression/2-Data/solution/Julia/README.md",
"language_code": "zh-MO"
},
"2-Regression/3-Linear/README.md": {
"original_hash": "40e64f004f3cb50aa1d8661672d3cd92",
"translation_date": "2025-09-06T09:05:38+00:00",
"source_file": "2-Regression/3-Linear/README.md",
"language_code": "zh-MO"
},
"2-Regression/3-Linear/assignment.md": {
"original_hash": "cc471fa89c293bc735dd3a9a0fb79b1b",
"translation_date": "2025-08-29T20:19:36+00:00",
"source_file": "2-Regression/3-Linear/assignment.md",
"language_code": "zh-MO"
},
"2-Regression/3-Linear/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T20:20:02+00:00",
"source_file": "2-Regression/3-Linear/solution/Julia/README.md",
"language_code": "zh-MO"
},
"2-Regression/4-Logistic/README.md": {
"original_hash": "abf86d845c84330bce205a46b382ec88",
"translation_date": "2025-09-06T09:07:21+00:00",
"source_file": "2-Regression/4-Logistic/README.md",
"language_code": "zh-MO"
},
"2-Regression/4-Logistic/assignment.md": {
"original_hash": "8af40209a41494068c1f42b14c0b450d",
"translation_date": "2025-08-29T20:28:43+00:00",
"source_file": "2-Regression/4-Logistic/assignment.md",
"language_code": "zh-MO"
},
"2-Regression/4-Logistic/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T20:29:10+00:00",
"source_file": "2-Regression/4-Logistic/solution/Julia/README.md",
"language_code": "zh-MO"
},
"2-Regression/README.md": {
"original_hash": "508582278dbb8edd2a8a80ac96ef416c",
"translation_date": "2025-08-29T20:13:15+00:00",
"source_file": "2-Regression/README.md",
"language_code": "zh-MO"
},
"3-Web-App/1-Web-App/README.md": {
"original_hash": "e0b75f73e4a90d45181dc5581fe2ef5c",
"translation_date": "2025-09-06T09:15:43+00:00",
"source_file": "3-Web-App/1-Web-App/README.md",
"language_code": "zh-MO"
},
"3-Web-App/1-Web-App/assignment.md": {
"original_hash": "a8e8ae10be335cbc745b75ee552317ff",
"translation_date": "2025-08-29T21:38:04+00:00",
"source_file": "3-Web-App/1-Web-App/assignment.md",
"language_code": "zh-MO"
},
"3-Web-App/README.md": {
"original_hash": "9836ff53cfef716ddfd70e06c5f43436",
"translation_date": "2025-08-29T21:34:33+00:00",
"source_file": "3-Web-App/README.md",
"language_code": "zh-MO"
},
"4-Classification/1-Introduction/README.md": {
"original_hash": "aaf391d922bd6de5efba871d514c6d47",
"translation_date": "2025-09-06T09:17:41+00:00",
"source_file": "4-Classification/1-Introduction/README.md",
"language_code": "zh-MO"
},
"4-Classification/1-Introduction/assignment.md": {
"original_hash": "b2a01912beb24cfb0007f83594dba801",
"translation_date": "2025-08-29T21:53:57+00:00",
"source_file": "4-Classification/1-Introduction/assignment.md",
"language_code": "zh-MO"
},
"4-Classification/1-Introduction/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T21:54:26+00:00",
"source_file": "4-Classification/1-Introduction/solution/Julia/README.md",
"language_code": "zh-MO"
},
"4-Classification/2-Classifiers-1/README.md": {
"original_hash": "1a6e9e46b34a2e559fbbfc1f95397c7b",
"translation_date": "2025-09-06T09:16:12+00:00",
"source_file": "4-Classification/2-Classifiers-1/README.md",
"language_code": "zh-MO"
},
"4-Classification/2-Classifiers-1/assignment.md": {
"original_hash": "de6025f96841498b0577e9d1aee18d1f",
"translation_date": "2025-08-29T21:44:27+00:00",
"source_file": "4-Classification/2-Classifiers-1/assignment.md",
"language_code": "zh-MO"
},
"4-Classification/2-Classifiers-1/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T21:44:52+00:00",
"source_file": "4-Classification/2-Classifiers-1/solution/Julia/README.md",
"language_code": "zh-MO"
},
"4-Classification/3-Classifiers-2/README.md": {
"original_hash": "49047911108adc49d605cddfb455749c",
"translation_date": "2025-09-06T09:17:21+00:00",
"source_file": "4-Classification/3-Classifiers-2/README.md",
"language_code": "zh-MO"
},
"4-Classification/3-Classifiers-2/assignment.md": {
"original_hash": "58dfdaf79fb73f7d34b22bdbacf57329",
"translation_date": "2025-08-29T21:50:22+00:00",
"source_file": "4-Classification/3-Classifiers-2/assignment.md",
"language_code": "zh-MO"
},
"4-Classification/3-Classifiers-2/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T21:50:48+00:00",
"source_file": "4-Classification/3-Classifiers-2/solution/Julia/README.md",
"language_code": "zh-MO"
},
"4-Classification/4-Applied/README.md": {
"original_hash": "61bdec27ed2da8b098cd9065405d9bb0",
"translation_date": "2025-09-06T09:16:55+00:00",
"source_file": "4-Classification/4-Applied/README.md",
"language_code": "zh-MO"
},
"4-Classification/4-Applied/assignment.md": {
"original_hash": "799ed651e2af0a7cad17c6268db11578",
"translation_date": "2025-08-29T21:47:55+00:00",
"source_file": "4-Classification/4-Applied/assignment.md",
"language_code": "zh-MO"
},
"4-Classification/README.md": {
"original_hash": "74e809ffd1e613a1058bbc3e9600859e",
"translation_date": "2025-08-29T21:39:54+00:00",
"source_file": "4-Classification/README.md",
"language_code": "zh-MO"
},
"5-Clustering/1-Visualize/README.md": {
"original_hash": "730225ea274c9174fe688b21d421539d",
"translation_date": "2025-09-06T09:10:48+00:00",
"source_file": "5-Clustering/1-Visualize/README.md",
"language_code": "zh-MO"
},
"5-Clustering/1-Visualize/assignment.md": {
"original_hash": "589fa015a5e7d9e67bd629f7d47b53de",
"translation_date": "2025-08-29T21:04:26+00:00",
"source_file": "5-Clustering/1-Visualize/assignment.md",
"language_code": "zh-MO"
},
"5-Clustering/1-Visualize/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T21:04:53+00:00",
"source_file": "5-Clustering/1-Visualize/solution/Julia/README.md",
"language_code": "zh-MO"
},
"5-Clustering/2-K-Means/README.md": {
"original_hash": "7cdd17338d9bbd7e2171c2cd462eb081",
"translation_date": "2025-09-06T09:11:48+00:00",
"source_file": "5-Clustering/2-K-Means/README.md",
"language_code": "zh-MO"
},
"5-Clustering/2-K-Means/assignment.md": {
"original_hash": "b8e17eff34ad1680eba2a5d3cf9ffc41",
"translation_date": "2025-08-29T21:07:32+00:00",
"source_file": "5-Clustering/2-K-Means/assignment.md",
"language_code": "zh-MO"
},
"5-Clustering/2-K-Means/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T21:07:57+00:00",
"source_file": "5-Clustering/2-K-Means/solution/Julia/README.md",
"language_code": "zh-MO"
},
"5-Clustering/README.md": {
"original_hash": "b28a3a4911584062772c537b653ebbc7",
"translation_date": "2025-08-29T20:52:23+00:00",
"source_file": "5-Clustering/README.md",
"language_code": "zh-MO"
},
"6-NLP/1-Introduction-to-NLP/README.md": {
"original_hash": "1c2ec40cf55c98a028a359c27ef7e45a",
"translation_date": "2025-09-06T09:21:34+00:00",
"source_file": "6-NLP/1-Introduction-to-NLP/README.md",
"language_code": "zh-MO"
},
"6-NLP/1-Introduction-to-NLP/assignment.md": {
"original_hash": "1d7583e8046dacbb0c056d5ba0a71b16",
"translation_date": "2025-08-29T22:33:15+00:00",
"source_file": "6-NLP/1-Introduction-to-NLP/assignment.md",
"language_code": "zh-MO"
},
"6-NLP/2-Tasks/README.md": {
"original_hash": "5f3cb462e3122e1afe7ab0050ccf2bd3",
"translation_date": "2025-09-06T09:20:02+00:00",
"source_file": "6-NLP/2-Tasks/README.md",
"language_code": "zh-MO"
},
"6-NLP/2-Tasks/assignment.md": {
"original_hash": "2efc4c2aba5ed06c780c05539c492ae3",
"translation_date": "2025-08-29T22:21:28+00:00",
"source_file": "6-NLP/2-Tasks/assignment.md",
"language_code": "zh-MO"
},
"6-NLP/3-Translation-Sentiment/README.md": {
"original_hash": "be03c8182982b87ced155e4e9d1438e8",
"translation_date": "2025-09-06T09:22:02+00:00",
"source_file": "6-NLP/3-Translation-Sentiment/README.md",
"language_code": "zh-MO"
},
"6-NLP/3-Translation-Sentiment/assignment.md": {
"original_hash": "9d2a734deb904caff310d1a999c6bd7a",
"translation_date": "2025-08-29T22:38:19+00:00",
"source_file": "6-NLP/3-Translation-Sentiment/assignment.md",
"language_code": "zh-MO"
},
"6-NLP/3-Translation-Sentiment/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T22:39:04+00:00",
"source_file": "6-NLP/3-Translation-Sentiment/solution/Julia/README.md",
"language_code": "zh-MO"
},
"6-NLP/3-Translation-Sentiment/solution/R/README.md": {
"original_hash": "81db6ff2cf6e62fbe2340b094bb9509e",
"translation_date": "2025-08-29T22:38:48+00:00",
"source_file": "6-NLP/3-Translation-Sentiment/solution/R/README.md",
"language_code": "zh-MO"
},
"6-NLP/4-Hotel-Reviews-1/README.md": {
"original_hash": "8d32dadeda93c6fb5c43619854882ab1",
"translation_date": "2025-09-06T09:20:34+00:00",
"source_file": "6-NLP/4-Hotel-Reviews-1/README.md",
"language_code": "zh-MO"
},
"6-NLP/4-Hotel-Reviews-1/assignment.md": {
"original_hash": "bf39bceb833cd628f224941dca8041df",
"translation_date": "2025-08-29T22:28:59+00:00",
"source_file": "6-NLP/4-Hotel-Reviews-1/assignment.md",
"language_code": "zh-MO"
},
"6-NLP/4-Hotel-Reviews-1/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T22:29:38+00:00",
"source_file": "6-NLP/4-Hotel-Reviews-1/solution/Julia/README.md",
"language_code": "zh-MO"
},
"6-NLP/4-Hotel-Reviews-1/solution/R/README.md": {
"original_hash": "81db6ff2cf6e62fbe2340b094bb9509e",
"translation_date": "2025-08-29T22:29:21+00:00",
"source_file": "6-NLP/4-Hotel-Reviews-1/solution/R/README.md",
"language_code": "zh-MO"
},
"6-NLP/5-Hotel-Reviews-2/README.md": {
"original_hash": "2c742993fe95d5bcbb2846eda3d442a1",
"translation_date": "2025-09-06T09:22:39+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/README.md",
"language_code": "zh-MO"
},
"6-NLP/5-Hotel-Reviews-2/assignment.md": {
"original_hash": "daf144daa552da6a7d442aff6f3e77d8",
"translation_date": "2025-08-29T22:43:40+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/assignment.md",
"language_code": "zh-MO"
},
"6-NLP/5-Hotel-Reviews-2/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T22:44:21+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/solution/Julia/README.md",
"language_code": "zh-MO"
},
"6-NLP/5-Hotel-Reviews-2/solution/R/README.md": {
"original_hash": "81db6ff2cf6e62fbe2340b094bb9509e",
"translation_date": "2025-08-29T22:44:06+00:00",
"source_file": "6-NLP/5-Hotel-Reviews-2/solution/R/README.md",
"language_code": "zh-MO"
},
"6-NLP/README.md": {
"original_hash": "1eb379dc2d0c9940b320732d16083778",
"translation_date": "2025-08-29T22:17:45+00:00",
"source_file": "6-NLP/README.md",
"language_code": "zh-MO"
},
"6-NLP/data/README.md": {
"original_hash": "ee0670655c89e4719319764afb113624",
"translation_date": "2025-08-29T22:29:56+00:00",
"source_file": "6-NLP/data/README.md",
"language_code": "zh-MO"
},
"7-TimeSeries/1-Introduction/README.md": {
"original_hash": "662b509c39eee205687726636d0a8455",
"translation_date": "2025-09-06T09:09:48+00:00",
"source_file": "7-TimeSeries/1-Introduction/README.md",
"language_code": "zh-MO"
},
"7-TimeSeries/1-Introduction/assignment.md": {
"original_hash": "d1781b0b92568ea1d119d0a198b576b4",
"translation_date": "2025-08-29T20:47:58+00:00",
"source_file": "7-TimeSeries/1-Introduction/assignment.md",
"language_code": "zh-MO"
},
"7-TimeSeries/1-Introduction/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T20:48:42+00:00",
"source_file": "7-TimeSeries/1-Introduction/solution/Julia/README.md",
"language_code": "zh-MO"
},
"7-TimeSeries/1-Introduction/solution/R/README.md": {
"original_hash": "81db6ff2cf6e62fbe2340b094bb9509e",
"translation_date": "2025-08-29T20:48:25+00:00",
"source_file": "7-TimeSeries/1-Introduction/solution/R/README.md",
"language_code": "zh-MO"
},
"7-TimeSeries/2-ARIMA/README.md": {
"original_hash": "917dbf890db71a322f306050cb284749",
"translation_date": "2025-09-06T09:09:11+00:00",
"source_file": "7-TimeSeries/2-ARIMA/README.md",
"language_code": "zh-MO"
},
"7-TimeSeries/2-ARIMA/assignment.md": {
"original_hash": "1c814013e10866dfd92cdb32caaae3ac",
"translation_date": "2025-08-29T20:43:05+00:00",
"source_file": "7-TimeSeries/2-ARIMA/assignment.md",
"language_code": "zh-MO"
},
"7-TimeSeries/2-ARIMA/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T20:43:54+00:00",
"source_file": "7-TimeSeries/2-ARIMA/solution/Julia/README.md",
"language_code": "zh-MO"
},
"7-TimeSeries/2-ARIMA/solution/R/README.md": {
"original_hash": "81db6ff2cf6e62fbe2340b094bb9509e",
"translation_date": "2025-08-29T20:43:31+00:00",
"source_file": "7-TimeSeries/2-ARIMA/solution/R/README.md",
"language_code": "zh-MO"
},
"7-TimeSeries/3-SVR/README.md": {
"original_hash": "482bccabe1df958496ea71a3667995cd",
"translation_date": "2025-09-06T09:10:20+00:00",
"source_file": "7-TimeSeries/3-SVR/README.md",
"language_code": "zh-MO"
},
"7-TimeSeries/3-SVR/assignment.md": {
"original_hash": "94aa2fc6154252ae30a3f3740299707a",
"translation_date": "2025-08-29T20:51:36+00:00",
"source_file": "7-TimeSeries/3-SVR/assignment.md",
"language_code": "zh-MO"
},
"7-TimeSeries/README.md": {
"original_hash": "61342603bad8acadbc6b2e4e3aab3f66",
"translation_date": "2025-08-29T20:38:26+00:00",
"source_file": "7-TimeSeries/README.md",
"language_code": "zh-MO"
},
"8-Reinforcement/1-QLearning/README.md": {
"original_hash": "911efd5e595089000cb3c16fce1beab8",
"translation_date": "2025-09-06T09:18:41+00:00",
"source_file": "8-Reinforcement/1-QLearning/README.md",
"language_code": "zh-MO"
},
"8-Reinforcement/1-QLearning/assignment.md": {
"original_hash": "68394b2102d3503882e5e914bd0ff5c1",
"translation_date": "2025-08-29T22:10:31+00:00",
"source_file": "8-Reinforcement/1-QLearning/assignment.md",
"language_code": "zh-MO"
},
"8-Reinforcement/1-QLearning/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T22:11:47+00:00",
"source_file": "8-Reinforcement/1-QLearning/solution/Julia/README.md",
"language_code": "zh-MO"
},
"8-Reinforcement/1-QLearning/solution/R/README.md": {
"original_hash": "81db6ff2cf6e62fbe2340b094bb9509e",
"translation_date": "2025-08-29T22:11:31+00:00",
"source_file": "8-Reinforcement/1-QLearning/solution/R/README.md",
"language_code": "zh-MO"
},
"8-Reinforcement/2-Gym/README.md": {
"original_hash": "107d5bb29da8a562e7ae72262d251a75",
"translation_date": "2025-09-06T09:19:17+00:00",
"source_file": "8-Reinforcement/2-Gym/README.md",
"language_code": "zh-MO"
},
"8-Reinforcement/2-Gym/assignment.md": {
"original_hash": "1f2b7441745eb52e25745423b247016b",
"translation_date": "2025-08-29T22:16:19+00:00",
"source_file": "8-Reinforcement/2-Gym/assignment.md",
"language_code": "zh-MO"
},
"8-Reinforcement/2-Gym/solution/Julia/README.md": {
"original_hash": "a39c15d63f3b2795ee2284a82b986b93",
"translation_date": "2025-08-29T22:17:16+00:00",
"source_file": "8-Reinforcement/2-Gym/solution/Julia/README.md",
"language_code": "zh-MO"
},
"8-Reinforcement/2-Gym/solution/R/README.md": {
"original_hash": "81db6ff2cf6e62fbe2340b094bb9509e",
"translation_date": "2025-08-29T22:16:59+00:00",
"source_file": "8-Reinforcement/2-Gym/solution/R/README.md",
"language_code": "zh-MO"
},
"8-Reinforcement/README.md": {
"original_hash": "20ca019012b1725de956681d036d8b18",
"translation_date": "2025-08-29T22:02:15+00:00",
"source_file": "8-Reinforcement/README.md",
"language_code": "zh-MO"
},
"9-Real-World/1-Applications/README.md": {
"original_hash": "83320d6b6994909e35d830cebf214039",
"translation_date": "2025-09-06T09:12:11+00:00",
"source_file": "9-Real-World/1-Applications/README.md",
"language_code": "zh-MO"
},
"9-Real-World/1-Applications/assignment.md": {
"original_hash": "fdebfcd0a3f12c9e2b436ded1aa79885",
"translation_date": "2025-08-29T21:14:01+00:00",
"source_file": "9-Real-World/1-Applications/assignment.md",
"language_code": "zh-MO"
},
"9-Real-World/2-Debugging-ML-Models/README.md": {
"original_hash": "df2b538e8fbb3e91cf0419ae2f858675",
"translation_date": "2025-09-06T09:12:53+00:00",
"source_file": "9-Real-World/2-Debugging-ML-Models/README.md",
"language_code": "zh-MO"
},
"9-Real-World/2-Debugging-ML-Models/assignment.md": {
"original_hash": "91c6a180ef08e20cc15acfd2d6d6e164",
"translation_date": "2025-08-29T21:18:47+00:00",
"source_file": "9-Real-World/2-Debugging-ML-Models/assignment.md",
"language_code": "zh-MO"
},
"9-Real-World/README.md": {
"original_hash": "5e069a0ac02a9606a69946c2b3c574a9",
"translation_date": "2025-08-29T21:09:20+00:00",
"source_file": "9-Real-World/README.md",
"language_code": "zh-MO"
},
"AGENTS.md": {
"original_hash": "93fdaa0fd38836e50c4793e2f2f25e8b",
"translation_date": "2025-10-03T11:00:25+00:00",
"source_file": "AGENTS.md",
"language_code": "zh-MO"
},
"CODE_OF_CONDUCT.md": {
"original_hash": "c06b12caf3c901eb3156e3dd5b0aea56",
"translation_date": "2025-08-29T20:12:29+00:00",
"source_file": "CODE_OF_CONDUCT.md",
"language_code": "zh-MO"
},
"CONTRIBUTING.md": {
"original_hash": "977ec5266dfd78ad1ce2bd8d46fccbda",
"translation_date": "2025-08-29T20:10:10+00:00",
"source_file": "CONTRIBUTING.md",
"language_code": "zh-MO"
},
"README.md": {
"original_hash": "da2ceed62f16a0820259556e3a873c95",
"translation_date": "2026-01-29T17:48:12+00:00",
"source_file": "README.md",
"language_code": "zh-MO"
},
"SECURITY.md": {
"original_hash": "5e1b8da31aae9cca3d53ad243fa3365a",
"translation_date": "2025-08-29T20:10:55+00:00",
"source_file": "SECURITY.md",
"language_code": "zh-MO"
},
"SUPPORT.md": {
"original_hash": "09623d7343ff1c26ff4f198c1b2d3176",
"translation_date": "2025-10-03T11:43:22+00:00",
"source_file": "SUPPORT.md",
"language_code": "zh-MO"
},
"TROUBLESHOOTING.md": {
"original_hash": "134d8759f0e2ab886e9aa4f62362c201",
"translation_date": "2025-10-03T12:38:42+00:00",
"source_file": "TROUBLESHOOTING.md",
"language_code": "zh-MO"
},
"docs/_sidebar.md": {
"original_hash": "68dd06c685f6ce840e0acfa313352e7c",
"translation_date": "2025-08-29T21:08:30+00:00",
"source_file": "docs/_sidebar.md",
"language_code": "zh-MO"
},
"for-teachers.md": {
"original_hash": "b37de02054fa6c0438ede6fabe1fdfb8",
"translation_date": "2025-08-29T20:11:50+00:00",
"source_file": "for-teachers.md",
"language_code": "zh-MO"
},
"quiz-app/README.md": {
"original_hash": "6d130dffca5db70d7e615f926cb1ad4c",
"translation_date": "2025-08-29T21:38:53+00:00",
"source_file": "quiz-app/README.md",
"language_code": "zh-MO"
},
"sketchnotes/LICENSE.md": {
"original_hash": "fba3b94d88bfb9b81369b869a1e9a20f",
"translation_date": "2025-08-29T21:58:38+00:00",
"source_file": "sketchnotes/LICENSE.md",
"language_code": "zh-MO"
},
"sketchnotes/README.md": {
"original_hash": "a88d5918c1b9da69a40d917a0840c497",
"translation_date": "2025-08-29T21:54:50+00:00",
"source_file": "sketchnotes/README.md",
"language_code": "zh-MO"
}
}

@ -0,0 +1,150 @@
# 機器學習簡介
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
---
[![初學者的機器學習 - 機器學習入門](https://img.youtube.com/vi/6mSx_KJxcHI/0.jpg)](https://youtu.be/6mSx_KJxcHI "初學者的機器學習 - 機器學習入門")
> 🎥 點擊上方圖片觀看本課程的簡短介紹影片。
歡迎來到這門針對初學者的經典機器學習課程!無論您是完全新手,還是有經驗的機器學習從業者希望重新學習某些領域,我們都很高興您加入我們!我們希望為您的機器學習研究創造一個友好的起點,並樂於評估、回應和採納您的[反饋](https://github.com/microsoft/ML-For-Beginners/discussions)。
[![機器學習簡介](https://img.youtube.com/vi/h0e2HAPTGF4/0.jpg)](https://youtu.be/h0e2HAPTGF4 "機器學習簡介")
> 🎥 點擊上方圖片觀看影片:麻省理工學院的 John Guttag 介紹機器學習
---
## 機器學習入門
在開始學習本課程之前,您需要先準備好您的電腦以便在本地運行筆記本。
- **使用這些影片配置您的電腦**。通過以下連結學習[如何安裝 Python](https://youtu.be/CXZYvNRIAKM)以及[設置文本編輯器](https://youtu.be/EU8eayHWoZg)進行開發。
- **學習 Python**。建議您對[Python](https://docs.microsoft.com/learn/paths/python-language/?WT.mc_id=academic-77952-leestott)有基本的了解,這是一種對數據科學家非常有用的編程語言,我們在本課程中會使用它。
- **學習 Node.js 和 JavaScript**。我們在本課程中偶爾會使用 JavaScript 來構建網頁應用,因此您需要安裝 [node](https://nodejs.org) 和 [npm](https://www.npmjs.com/),以及[Visual Studio Code](https://code.visualstudio.com/)以進行 Python 和 JavaScript 的開發。
- **創建 GitHub 帳戶**。既然您在 [GitHub](https://github.com) 找到了我們,您可能已經有帳戶了,但如果沒有,請創建一個帳戶,然後 fork 本課程以供自己使用。(也可以給我們一顆星星 😊)
- **探索 Scikit-learn**。熟悉 [Scikit-learn](https://scikit-learn.org/stable/user_guide.html),這是一組我們在課程中引用的機器學習庫。
---
## 什麼是機器學習?
「機器學習」這個詞是當今最流行且最常用的術語之一。如果您對科技有一定的了解,無論您從事哪個領域,都有很大的可能性至少聽過一次這個詞。然而,機器學習的運作機制對大多數人來說仍然是一個謎。對於機器學習初學者來說,這個主題有時可能會讓人感到不知所措。因此,了解機器學習的真正含義並通過實際例子逐步學習是非常重要的。
---
## 熱潮曲線
![機器學習熱潮曲線](../../../../1-Introduction/1-intro-to-ML/images/hype.png)
> Google 趨勢顯示了「機器學習」這個詞最近的熱潮曲線
---
## 神秘的宇宙
我們生活在一個充滿迷人謎團的宇宙中。像史蒂芬·霍金、阿爾伯特·愛因斯坦等偉大的科學家,將一生奉獻於尋找有意義的信息,以揭示我們周圍世界的奧秘。這是人類學習的本質:一個孩子隨著成長逐年學習新事物,揭示他們世界的結構。
---
## 孩子的大腦
孩子的大腦和感官感知周圍環境的事實,並逐漸學習生活中隱藏的模式,幫助孩子制定邏輯規則以識別已學習的模式。人類大腦的學習過程使人類成為世界上最複雜的生物。通過不斷發現隱藏的模式並在這些模式上進行創新,我們能夠在一生中不斷改進自己。這種學習能力和進化能力與一個名為[大腦可塑性](https://www.simplypsychology.org/brain-plasticity.html)的概念有關。表面上,我們可以將人類大腦的學習過程與機器學習的概念進行一些激勵性的類比。
---
## 人類大腦
[人類大腦](https://www.livescience.com/29365-human-brain.html)從現實世界中感知事物處理感知到的信息做出理性決策並根據情況執行某些行動。這就是我們所說的智能行為。當我們將智能行為過程的模擬編程到機器上時這就被稱為人工智能AI
---
## 一些術語
雖然這些術語可能會混淆但機器學習ML是人工智能的一個重要子集。**機器學習專注於使用專門的算法從感知到的數據中發掘有意義的信息並找到隱藏的模式,以支持理性決策過程**。
---
## AI、ML、深度學習
![AI、ML、深度學習、數據科學](../../../../1-Introduction/1-intro-to-ML/images/ai-ml-ds.png)
> 一張展示 AI、ML、深度學習和數據科學之間關係的圖表。由 [Jen Looper](https://twitter.com/jenlooper) 製作,靈感來自[這張圖表](https://softwareengineering.stackexchange.com/questions/366996/distinction-between-ai-ml-neural-networks-deep-learning-and-data-mining)
---
## 涵蓋的概念
在本課程中,我們將只涵蓋機器學習的核心概念,這是初學者必須了解的。我們主要使用 Scikit-learn 來教授所謂的「經典機器學習」,這是一個許多學生用來學習基礎知識的優秀庫。要理解人工智能或深度學習的更廣泛概念,扎實的機器學習基礎知識是不可或缺的,因此我們希望在此提供這些知識。
---
## 在本課程中您將學到:
- 機器學習的核心概念
- 機器學習的歷史
- 機器學習與公平性
- 回歸機器學習技術
- 分類機器學習技術
- 聚類機器學習技術
- 自然語言處理機器學習技術
- 時間序列預測機器學習技術
- 強化學習
- 機器學習的實際應用
---
## 我們不會涵蓋的內容
- 深度學習
- 神經網絡
- 人工智能
為了提供更好的學習體驗,我們將避免涉及神經網絡的複雜性、「深度學習」——使用神經網絡構建多層模型——以及人工智能,這些內容我們會在其他課程中討論。我們還將提供即將推出的數據科學課程,專注於這個更大領域的相關方面。
---
## 為什麼要學習機器學習?
從系統的角度來看,機器學習被定義為創建能夠從數據中學習隱藏模式以幫助做出智能決策的自動化系統。
這種動機在某種程度上受到人類大腦如何根據外界感知的數據學習某些事物的啟發。
✅ 想一想,為什麼企業會選擇使用機器學習策略,而不是創建基於硬編碼規則的引擎?
---
## 機器學習的應用
機器學習的應用如今幾乎無處不在,就像我們社會中流動的數據一樣普遍,這些數據由智能手機、連接設備和其他系統生成。考慮到最先進的機器學習算法的巨大潛力,研究人員一直在探索它們解決多維度和多學科現實問題的能力,並取得了非常積極的成果。
---
## 機器學習的應用例子
**機器學習有許多用途**
- 從患者的病史或報告中預測疾病的可能性。
- 利用天氣數據預測天氣事件。
- 理解文本的情感。
- 檢測假新聞以阻止宣傳的傳播。
金融、經濟、地球科學、太空探索、生物醫學工程、認知科學,甚至人文領域都已經採用機器學習來解決其領域中繁重的數據處理問題。
---
## 結論
機器學習通過從現實世界或生成的數據中發現有意義的洞察來自動化模式發現的過程。它已經在商業、健康和金融應用等領域證明了自己的巨大價值。
在不久的將來,了解機器學習的基礎知識將成為任何領域人員的必備技能,因為它的廣泛採用。
---
# 🚀 挑戰
使用紙筆或像 [Excalidraw](https://excalidraw.com/) 這樣的在線應用程序,繪製您對 AI、ML、深度學習和數據科學之間差異的理解。添加一些這些技術擅長解決的問題的想法。
# [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
---
# 回顧與自學
要了解更多關於如何在雲端中使用機器學習算法,請參考這個[學習路徑](https://docs.microsoft.com/learn/paths/create-no-code-predictive-models-azure-machine-learning/?WT.mc_id=academic-77952-leestott)。
參加一個關於機器學習基礎的[學習路徑](https://docs.microsoft.com/learn/modules/introduction-to-machine-learning/?WT.mc_id=academic-77952-leestott)。
---
# 作業
[開始學習](assignment.md)
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,14 @@
# 開始運行
## 說明
在這個非評分的作業中,你需要複習 Python 並設置你的環境,使其能夠運行筆記本。
請參考這個 [Python 學習路徑](https://docs.microsoft.com/learn/paths/python-language/?WT.mc_id=academic-77952-leestott),然後通過以下入門視頻來設置你的系統:
https://www.youtube.com/playlist?list=PLlrxD0HtieHhS8VzuMCfQD4uJ9yne1mE6
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,155 @@
# 機器學習的歷史
![機器學習歷史摘要的手繪筆記](../../../../sketchnotes/ml-history.png)
> 手繪筆記由 [Tomomi Imura](https://www.twitter.com/girlie_mac) 提供
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
---
[![機器學習入門 - 機器學習的歷史](https://img.youtube.com/vi/N6wxM4wZ7V0/0.jpg)](https://youtu.be/N6wxM4wZ7V0 "機器學習入門 - 機器學習的歷史")
> 🎥 點擊上方圖片觀看本課程的短片。
在本課程中,我們將回顧機器學習和人工智慧歷史上的重要里程碑。
人工智慧AI作為一個領域的歷史與機器學習的歷史密切相關因為支撐機器學習的演算法和計算進步促進了人工智慧的發展。值得注意的是雖然這些領域作為獨立的研究方向在1950年代開始成形但重要的[演算法、統計、數學、計算和技術發現](https://wikipedia.org/wiki/Timeline_of_machine_learning)早在此之前就已出現並與這個時期重疊。事實上,人們已經思考這些問題[數百年](https://wikipedia.org/wiki/History_of_artificial_intelligence):本文探討了「思考機器」概念的歷史性智力基礎。
---
## 重要發現
- 1763年、1812年 [貝葉斯定理](https://wikipedia.org/wiki/Bayes%27_theorem)及其前身。此定理及其應用是推論的基礎,描述了基於先驗知識事件發生的概率。
- 1805年 [最小平方理論](https://wikipedia.org/wiki/Least_squares) 由法國數學家Adrien-Marie Legendre提出。此理論您將在回歸單元中學習有助於數據擬合。
- 1913年 [馬可夫鏈](https://wikipedia.org/wiki/Markov_chain)以俄羅斯數學家Andrey Markov命名用於描述基於前一狀態的一系列可能事件。
- 1957年 [感知器](https://wikipedia.org/wiki/Perceptron) 是一種由美國心理學家Frank Rosenblatt發明的線性分類器為深度學習的進步奠定了基礎。
---
- 1967年 [最近鄰演算法](https://wikipedia.org/wiki/Nearest_neighbor) 最初設計用於路徑規劃。在機器學習中,它被用於模式檢測。
- 1970年 [反向傳播](https://wikipedia.org/wiki/Backpropagation) 用於訓練[前饋神經網絡](https://wikipedia.org/wiki/Feedforward_neural_network)。
- 1982年 [循環神經網絡](https://wikipedia.org/wiki/Recurrent_neural_network) 是從前饋神經網絡衍生出的人工神經網絡,用於創建時間圖。
✅ 做一些研究。還有哪些日期在機器學習和人工智慧的歷史中具有重要意義?
---
## 1950年思考的機器
艾倫·圖靈Alan Turing一位真正非凡的人物被[公眾在2019年](https://wikipedia.org/wiki/Icons:_The_Greatest_Person_of_the_20th_Century)評選為20世紀最偉大的科學家他被認為幫助奠定了「能思考的機器」概念的基礎。他面對反對者並努力尋求這一概念的實證部分原因是創造了[圖靈測試](https://www.bbc.com/news/technology-18475646),您將在自然語言處理課程中進一步探索。
---
## 1956年達特茅斯夏季研究計劃
「達特茅斯夏季人工智慧研究計劃是人工智慧作為一個領域的奠基事件」,並且在這裡首次提出了「人工智慧」這一術語([來源](https://250.dartmouth.edu/highlights/artificial-intelligence-ai-coined-dartmouth))。
> 學習的每一個方面或智慧的任何其他特徵都可以原則上如此精確地描述,以至於可以製造出模擬它的機器。
---
領導研究的數學教授John McCarthy希望「基於這樣的猜想進行研究即學習的每一個方面或智慧的任何其他特徵都可以原則上如此精確地描述以至於可以製造出模擬它的機器。」參與者包括另一位該領域的傑出人物Marvin Minsky。
該研討會被認為促進並激發了多項討論,包括「符號方法的興起、專注於有限領域的系統(早期專家系統)以及演繹系統與歸納系統的對比。」([來源](https://wikipedia.org/wiki/Dartmouth_workshop))。
---
## 1956年 - 1974年「黃金時代」
從1950年代到70年代中期人們對人工智慧能解決許多問題的希望充滿樂觀。1967年Marvin Minsky自信地表示「在一代人之內……創造『人工智慧』的問題將基本上得到解決。」Minsky, Marvin (1967), Computation: Finite and Infinite Machines, Englewood Cliffs, N.J.: Prentice-Hall
自然語言處理研究蓬勃發展,搜索技術得到了改進並變得更強大,「微世界」的概念被創造出來,簡單的任務可以通過簡單的語言指令完成。
---
研究得到了政府機構的充分資助,計算和演算法取得了進展,智能機器的原型被建造出來。其中一些機器包括:
* [Shakey機器人](https://wikipedia.org/wiki/Shakey_the_robot),它能夠智能地移動並決定如何執行任務。
![Shakey一個智能機器人](../../../../1-Introduction/2-history-of-ML/images/shakey.jpg)
> 1972年的Shakey
---
* Eliza一個早期的「聊天機器人」能與人交談並充當一個原始的「治療師」。您將在自然語言處理課程中學習更多關於Eliza的內容。
![Eliza一個機器人](../../../../1-Introduction/2-history-of-ML/images/eliza.png)
> Eliza的版本一個聊天機器人
---
* 「積木世界」是一個微世界的例子,積木可以堆疊和排序,並且可以進行教導機器做出決策的實驗。使用像[SHRDLU](https://wikipedia.org/wiki/SHRDLU)這樣的庫進行的研究推動了語言處理的進步。
[![積木世界與SHRDLU](https://img.youtube.com/vi/QAJz4YKUwqw/0.jpg)](https://www.youtube.com/watch?v=QAJz4YKUwqw "積木世界與SHRDLU")
> 🎥 點擊上方圖片觀看影片積木世界與SHRDLU
---
## 1974年 - 1980年「人工智慧寒冬」
到1970年代中期製造「智能機器」的複雜性被低估了而其承諾在當時的計算能力下被過度吹捧。資金枯竭對該領域的信心減弱。一些影響信心的問題包括
---
- **限制**。計算能力過於有限。
- **組合爆炸**。隨著對計算機要求的增加,需要訓練的參數數量呈指數增長,而計算能力和性能並未同步發展。
- **數據匱乏**。數據的匱乏阻礙了測試、開發和改進演算法的過程。
- **我們是否在問正確的問題?**。研究者開始質疑他們所提出的問題:
- 圖靈測試因「中文房間理論」等觀點受到質疑,該理論認為「編程數字計算機可能使其看似理解語言,但無法產生真正的理解。」([來源](https://plato.stanford.edu/entries/chinese-room/)
- 將像「治療師」ELIZA這樣的人工智慧引入社會的倫理問題受到挑戰。
---
同時,各種人工智慧的學派開始形成。「[凌亂派與整潔派](https://wikipedia.org/wiki/Neats_and_scruffies)」的二分法被建立。_凌亂派_實驗室花費數小時調整程式以達到預期結果。_整潔派_實驗室「專注於邏輯和正式問題解決」。ELIZA和SHRDLU是著名的_凌亂派_系統。在1980年代隨著需求的出現要求使機器學習系統可重現_整潔派_方法逐漸占據主導地位因為其結果更具解釋性。
---
## 1980年代 專家系統
隨著該領域的發展其對商業的益處變得更加明顯1980年代「專家系統」的普及也隨之而來。「專家系統是最早真正成功的人工智慧AI軟體形式之一。」[來源](https://wikipedia.org/wiki/Expert_system)
這類系統實際上是_混合型_部分由定義業務需求的規則引擎組成部分由利用規則系統推導新事實的推理引擎組成。
這一時期也看到對神經網絡的關注逐漸增加。
---
## 1987年 - 1993年人工智慧「寒潮」
專家系統硬體的專業化程度過高,導致其不幸地變得過於專業化。個人電腦的興起也與這些大型、專業化、集中化的系統形成競爭。計算的民主化已經開始,最終為現代大數據的爆炸鋪平了道路。
---
## 1993年 - 2011年
這一時期為機器學習和人工智慧解決早期因數據和計算能力不足而引發的問題開啟了新篇章。數據量開始迅速增加並變得更廣泛可用無論是好是壞尤其是在2007年左右智能手機的出現之後。計算能力呈指數增長演算法也隨之演進。該領域開始成熟過去自由奔放的日子逐漸凝聚成一個真正的學科。
---
## 現在
如今機器學習和人工智慧幾乎觸及我們生活的每一部分。這個時代需要仔細理解這些演算法對人類生活的風險和潛在影響。正如微軟的Brad Smith所說「信息技術提出了涉及基本人權保護的問題例如隱私和言論自由。這些問題加重了創造這些產品的科技公司的責任。在我們看來這些問題也呼籲政府進行深思熟慮的監管以及制定關於可接受使用的規範。」[來源](https://www.technologyreview.com/2019/12/18/102365/the-future-of-ais-impact-on-society/)
---
未來會如何仍有待觀察,但理解這些計算機系統及其運行的軟體和演算法至關重要。我們希望這份課程能幫助您更好地理解,從而讓您自己做出判斷。
[![深度學習的歷史](https://img.youtube.com/vi/mTtDfKgLm54/0.jpg)](https://www.youtube.com/watch?v=mTtDfKgLm54 "深度學習的歷史")
> 🎥 點擊上方圖片觀看影片Yann LeCun在此講座中討論深度學習的歷史
---
## 🚀挑戰
深入研究這些歷史時刻中的一個,了解背後的人物。這些人物非常有趣,沒有任何科學發現是在文化真空中誕生的。您發現了什麼?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
---
## 回顧與自學
以下是一些可以觀看和收聽的內容:
[這個播客中Amy Boyd討論了人工智慧的演變](http://runasradio.com/Shows/Show/739)
[![Amy Boyd講述人工智慧的歷史](https://img.youtube.com/vi/EJt3_bFYKss/0.jpg)](https://www.youtube.com/watch?v=EJt3_bFYKss "Amy Boyd講述人工智慧的歷史")
---
## 作業
[創建一個時間線](assignment.md)
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,16 @@
# 建立時間軸
## 指導說明
使用[這個倉庫](https://github.com/Digital-Humanities-Toolkit/timeline-builder),建立一個關於算法、數學、統計、人工智慧或機器學習歷史某一方面的時間軸,或者結合這些主題。你可以專注於一個人、一個想法,或者一段長時間的思想發展。請務必加入多媒體元素。
## 評分標準
| 評分標準 | 優秀 | 合格 | 需要改進 |
| -------- | ----------------------------------------------- | -------------------------------------- | ---------------------------------------------------------------- |
| | 提供了一個作為 GitHub 頁面部署的完整時間軸 | 程式碼不完整且未部署 | 時間軸不完整,研究不充分且未部署 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,161 @@
# 使用負責任的人工智慧建構機器學習解決方案
![機器學習中負責任人工智慧的摘要草圖](../../../../sketchnotes/ml-fairness.png)
> 草圖由 [Tomomi Imura](https://www.twitter.com/girlie_mac) 提供
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
## 簡介
在這門課程中,您將開始探索機器學習如何影響我們的日常生活。即使是現在,系統和模型已經參與了日常的決策任務,例如醫療診斷、貸款審批或欺詐檢測。因此,確保這些模型能夠提供值得信賴的結果是非常重要的。就像任何軟體應用程式一樣,人工智慧系統可能無法達到預期或產生不理想的結果。因此,理解並解釋人工智慧模型的行為是至關重要的。
想像一下,當您用來構建這些模型的數據缺乏某些人口統計數據(例如種族、性別、政治觀點、宗教)或過度代表某些人口統計數據時會發生什麼情況?如果模型的輸出被解讀為偏袒某些群體,又會有什麼後果?此外,當模型產生不良結果並對人們造成傷害時,該怎麼辦?誰應該對人工智慧系統的行為負責?這些是我們在這門課程中將探討的一些問題。
在這節課中,您將:
- 提高對機器學習中公平性及相關傷害的重要性的認識。
- 熟悉探索異常值和不尋常情境以確保可靠性和安全性的實踐。
- 理解設計包容性系統以賦能每個人的必要性。
- 探討保護數據和人員隱私與安全的重要性。
- 認識到採用透明化方法解釋人工智慧模型行為的必要性。
- 意識到責任感對於建立對人工智慧系統的信任至關重要。
## 先修條件
作為先修條件,請完成「負責任人工智慧原則」學習路徑,並觀看以下主題的影片:
通過此 [學習路徑](https://docs.microsoft.com/learn/modules/responsible-ai-principles/?WT.mc_id=academic-77952-leestott) 了解更多關於負責任人工智慧的內容。
[![微軟的負責任人工智慧方法](https://img.youtube.com/vi/dnC8-uUZXSc/0.jpg)](https://youtu.be/dnC8-uUZXSc "微軟的負責任人工智慧方法")
> 🎥 點擊上方圖片觀看影片:微軟的負責任人工智慧方法
## 公平性
人工智慧系統應該公平對待每個人,避免對相似群體的人產生不同的影響。例如,當人工智慧系統提供醫療建議、貸款申請或就業建議時,應該對具有相似症狀、財務狀況或專業資格的人給出相同的建議。我們每個人都帶有一些繼承的偏見,這些偏見會影響我們的決策和行動。這些偏見可能會反映在我們用來訓練人工智慧系統的數據中,有時甚至是無意間發生的。我們往往很難有意識地察覺到自己在數據中引入了偏見。
**「不公平」** 包括對某些群體(例如基於種族、性別、年齡或殘疾狀況定義的群體)造成的負面影響或「傷害」。主要與公平性相關的傷害可以分類為:
- **分配不公**:例如,偏袒某一性別或種族。
- **服務質量**:如果您僅針對特定情境訓練數據,而現實情況更為複雜,則會導致服務表現不佳。例如,一款無法感應深色皮膚的洗手液分配器。[參考資料](https://gizmodo.com/why-cant-this-soap-dispenser-identify-dark-skin-1797931773)
- **貶低**:不公平地批評或標籤某事或某人。例如,一項圖像標籤技術曾將深色皮膚的人的照片錯誤標籤為猩猩。
- **過度或不足代表**:某些群體在某些職業中未被看到,而任何繼續推動這種情況的服務或功能都在助長傷害。
- **刻板印象**:將某一群體與預設的屬性聯繫起來。例如,英語與土耳其語之間的語言翻譯系統可能因性別相關的刻板印象而出現不準確。
![翻譯成土耳其語](../../../../1-Introduction/3-fairness/images/gender-bias-translate-en-tr.png)
> 翻譯成土耳其語
![翻譯回英語](../../../../1-Introduction/3-fairness/images/gender-bias-translate-tr-en.png)
> 翻譯回英語
在設計和測試人工智慧系統時,我們需要確保人工智慧是公平的,並且未被編程為做出偏見或歧視性的決策,這些決策是人類也被禁止做出的。保證人工智慧和機器學習的公平性仍然是一個複雜的社會技術挑戰。
### 可靠性與安全性
為了建立信任,人工智慧系統需要在正常和意外情況下保持可靠、安全和一致。我們需要了解人工智慧系統在各種情境下的行為,特別是當它們面對異常情況時。在構建人工智慧解決方案時,需要大量關注如何處理人工智慧可能遇到的各種情況。例如,自駕車需要將人們的安全放在首位。因此,驅動汽車的人工智慧需要考慮所有可能的情境,例如夜晚、雷暴或暴風雪、孩子橫穿馬路、寵物、道路施工等。人工智慧系統能否可靠、安全地處理廣泛的情況,反映了數據科學家或人工智慧開發者在設計或測試系統時的考量程度。
> [🎥 點擊這裡觀看影片:](https://www.microsoft.com/videoplayer/embed/RE4vvIl)
### 包容性
人工智慧系統應該被設計為能夠吸引並賦能每個人。在設計和實施人工智慧系統時數據科學家和人工智慧開發者需要識別並解決系統中可能無意間排除某些人的潛在障礙。例如全球有10億人有殘疾。隨著人工智慧的進步他們可以更輕鬆地獲取廣泛的信息和機會。通過解決這些障礙可以創造創新機會開發出能為所有人提供更好體驗的人工智慧產品。
> [🎥 點擊這裡觀看影片:人工智慧中的包容性](https://www.microsoft.com/videoplayer/embed/RE4vl9v)
### 安全性與隱私
人工智慧系統應該是安全的,並尊重人們的隱私。如果系統威脅到人們的隱私、信息或生命安全,人們對其的信任就會減少。在訓練機器學習模型時,我們依賴數據來產生最佳結果。在此過程中,必須考慮數據的來源和完整性。例如,數據是用戶提交的還是公開可用的?接下來,在處理數據時,開發能夠保護機密信息並抵禦攻擊的人工智慧系統至關重要。隨著人工智慧的普及,保護隱私和確保重要的個人和商業信息的安全變得越來越重要且複雜。隱私和數據安全問題對人工智慧尤為重要,因為數據的可用性對於人工智慧系統做出準確且知情的預測和決策至關重要。
> [🎥 點擊這裡觀看影片:人工智慧中的安全性](https://www.microsoft.com/videoplayer/embed/RE4voJF)
- 作為一個行業我們在隱私和安全性方面取得了顯著進展這在很大程度上得益於《通用數據保護條例》GDPR等法規。
- 然而,對於人工智慧系統,我們必須承認在需要更多個人數據以使系統更加個性化和有效與隱私之間的緊張關係。
- 就像互聯網誕生時連接的計算機一樣,我們也看到了與人工智慧相關的安全問題數量的急劇增加。
- 同時,我們也看到人工智慧被用於改善安全性。例如,大多數現代防病毒掃描器今天都由人工智慧啟發的啟發式方法驅動。
- 我們需要確保我們的數據科學流程與最新的隱私和安全實踐和諧融合。
### 透明性
人工智慧系統應該是可理解的。透明性的一個關鍵部分是解釋人工智慧系統及其組件的行為。提高對人工智慧系統的理解需要利益相關者了解它們如何以及為什麼運作,以便識別潛在的性能問題、安全和隱私問題、偏見、排他性實踐或意外結果。我們還認為,使用人工智慧系統的人應該誠實並坦率地說明何時、為什麼以及如何選擇部署它們,以及它們使用的系統的局限性。例如,如果一家銀行使用人工智慧系統來支持其消費者貸款決策,則需要檢查結果並了解哪些數據影響了系統的建議。隨著政府開始對各行業的人工智慧進行監管,數據科學家和組織必須解釋人工智慧系統是否符合監管要求,特別是在出現不良結果時。
> [🎥 點擊這裡觀看影片:人工智慧中的透明性](https://www.microsoft.com/videoplayer/embed/RE4voJF)
- 由於人工智慧系統非常複雜,很難理解它們的工作原理並解釋結果。
- 這種缺乏理解影響了這些系統的管理、運營和文檔化方式。
- 更重要的是,這種缺乏理解影響了基於這些系統產生的結果所做的決策。
### 責任
設計和部署人工智慧系統的人必須對其系統的運作方式負責。責任的必要性在面部識別等敏感技術中尤為重要。最近,對面部識別技術的需求不斷增長,特別是來自執法機構的需求,他們看到了該技術在尋找失蹤兒童等用途中的潛力。然而,這些技術可能會被政府用來威脅其公民的基本自由,例如,通過對特定個體進行持續監控。因此,數據科學家和組織需要對其人工智慧系統對個人或社會的影響負責。
[![人工智慧研究者警告面部識別可能導致大規模監控](../../../../1-Introduction/3-fairness/images/accountability.png)](https://www.youtube.com/watch?v=Wldt8P5V6D0 "微軟的負責任人工智慧方法")
> 🎥 點擊上方圖片觀看影片:面部識別可能導致大規模監控的警告
最終,作為第一代將人工智慧引入社會的人,我們這一代面臨的最大問題之一是如何確保計算機始終對人類負責,以及如何確保設計計算機的人對其他人負責。
## 影響評估
在訓練機器學習模型之前,進行影響評估以了解人工智慧系統的目的、預期用途、部署地點以及與系統互動的對象是非常重要的。這些評估對於評審者或測試者來說非常有幫助,因為它們可以知道在識別潛在風險和預期後果時需要考慮哪些因素。
進行影響評估時的重點領域包括:
* **對個人的不利影響**:了解任何限制或要求、不支持的用途或任何已知限制對系統性能的影響至關重要,以確保系統不會以可能對個人造成傷害的方式使用。
* **數據需求**:了解系統如何以及在哪裡使用數據,使評審者能夠探索需要注意的任何數據需求(例如 GDPR 或 HIPPA 數據法規)。此外,檢查數據的來源或數量是否足夠用於訓練。
* **影響摘要**:收集使用系統可能產生的潛在傷害清單。在機器學習生命周期中,檢查是否已緩解或解決識別出的問題。
* **適用於六大核心原則的目標**:評估每個原則的目標是否達成,以及是否存在任何差距。
## 使用負責任人工智慧進行調試
與調試軟體應用程式類似,調試人工智慧系統是識別和解決系統問題的必要過程。許多因素可能導致模型未按預期或負責任地運行。大多數傳統的模型性能指標是模型性能的定量匯總,這不足以分析模型如何違反負責任人工智慧原則。此外,機器學習模型是一個黑箱,難以理解其結果的驅動因素或在出錯時提供解釋。在本課程的後續部分,我們將學習如何使用負責任人工智慧儀表板來幫助調試人工智慧系統。該儀表板為數據科學家和人工智慧開發者提供了一個全面的工具,用於執行以下操作:
* **錯誤分析**:識別模型的錯誤分佈,這可能影響系統的公平性或可靠性。
* **模型概覽**:發現模型在數據群體中的性能差異。
* **數據分析**:了解數據分佈並識別數據中可能導致公平性、包容性和可靠性問題的潛在偏見。
* **模型可解釋性**:了解影響或影響模型預測的因素。這有助於解釋模型的行為,這對於透明性和責任感至關重要。
## 🚀 挑戰
為了防止傷害的產生,我們應該:
- 確保參與系統工作的團隊成員具有多樣化的背景和觀點。
- 投資於反映社會多樣性的數據集。
- 在機器學習生命周期中開發更好的方法來檢測和糾正負責任人工智慧問題。
思考一些現實生活中的情境,模型的不可信性在模型構建和使用中顯而易見。我們還應該考慮什麼?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
在本課中,您已經學習了機器學習中公平性和不公平性概念的一些基礎知識。
觀看這場工作坊,深入了解相關主題:
- 追求負責任的人工智慧:將原則付諸實踐,由 Besmira Nushi、Mehrnoosh Sameki 和 Amit Sharma 主講
[![負責任的人工智慧工具箱:建立負責任人工智慧的開源框架](https://img.youtube.com/vi/tGgJCrA-MZU/0.jpg)](https://www.youtube.com/watch?v=tGgJCrA-MZU "RAI Toolbox: 建立負責任人工智慧的開源框架")
> 🎥 點擊上方圖片觀看影片RAI Toolbox: 建立負責任人工智慧的開源框架,由 Besmira Nushi、Mehrnoosh Sameki 和 Amit Sharma 主講
此外,閱讀以下資源:
- 微軟的負責任人工智慧資源中心:[負責任人工智慧資源 Microsoft AI](https://www.microsoft.com/ai/responsible-ai-resources?activetab=pivot1%3aprimaryr4)
- 微軟的 FATE 研究小組:[FATE: 公平性、問責性、透明性與人工智慧倫理 - Microsoft Research](https://www.microsoft.com/research/theme/fate/)
RAI 工具箱:
- [負責任人工智慧工具箱 GitHub 儲存庫](https://github.com/microsoft/responsible-ai-toolbox)
了解 Azure 機器學習工具如何確保公平性:
- [Azure 機器學習](https://docs.microsoft.com/azure/machine-learning/concept-fairness-ml?WT.mc_id=academic-77952-leestott)
## 作業
[探索 RAI 工具箱](assignment.md)
---
**免責聲明**
本文件使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對於因使用此翻譯而產生的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,16 @@
# 探索負責任人工智慧工具箱
## 說明
在本課程中,您學習了負責任人工智慧工具箱,這是一個「開源、社群驅動的專案,旨在幫助資料科學家分析和改進人工智慧系統。」在這次作業中,請探索 RAI 工具箱的一個[筆記本](https://github.com/microsoft/responsible-ai-toolbox/blob/main/notebooks/responsibleaidashboard/getting-started.ipynb),並在報告或簡報中分享您的發現。
## 評分標準
| 評分標準 | 卓越 | 合格 | 需要改進 |
| -------- | ----- | ----- | -------- |
| | 提交一份報告或簡報,討論 Fairlearn 的系統、執行的筆記本,以及從執行中得出的結論 | 提交一份報告,但未包含結論 | 未提交報告 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -0,0 +1,123 @@
# 機器學習技術
建立、使用和維護機器學習模型及其所需數據的過程,與許多其他開發工作流程有很大的不同。在本課程中,我們將揭開這個過程的神秘面紗,並概述您需要了解的主要技術。您將:
- 理解機器學習背後的高層次流程。
- 探索基本概念,例如「模型」、「預測」和「訓練數據」。
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
[![機器學習入門 - 機器學習技術](https://img.youtube.com/vi/4NGM0U2ZSHU/0.jpg)](https://youtu.be/4NGM0U2ZSHU "機器學習入門 - 機器學習技術")
> 🎥 點擊上方圖片觀看本課程的短視頻。
## 簡介
從高層次來看創建機器學習ML流程的技術包括以下幾個步驟
1. **確定問題**。大多數機器學習流程始於提出一個無法通過簡單的條件程序或基於規則的引擎回答的問題。這些問題通常圍繞基於數據集合的預測。
2. **收集和準備數據**。為了回答您的問題,您需要數據。數據的質量以及有時候數量將決定您能多好地回答最初的問題。可視化數據是此階段的重要方面。此階段還包括將數據分為訓練組和測試組以建立模型。
3. **選擇訓練方法**。根據您的問題和數據的性質,您需要選擇如何訓練模型以最好地反映您的數據並進行準確的預測。這是機器學習流程中需要特定專業知識且通常需要大量實驗的部分。
4. **訓練模型**。使用您的訓練數據,您將使用各種算法訓練模型以識別數據中的模式。模型可能利用內部權重,這些權重可以調整以優化某些數據部分,從而建立更好的模型。
5. **評估模型**。使用從收集的數據集中從未見過的測試數據來檢查模型的性能。
6. **參數調整**。根據模型的性能,您可以使用不同的參數或變量重新進行過程,這些參數或變量控制用於訓練模型的算法行為。
7. **預測**。使用新的輸入測試模型的準確性。
## 提出問題
電腦特別擅長發現數據中的隱藏模式。這種能力對於研究人員來說非常有用,尤其是當他們面臨無法輕易通過條件規則引擎回答的問題時。例如,針對精算任務,數據科學家可能能夠手工製作規則來分析吸煙者與非吸煙者的死亡率。
然而,當涉及到許多其他變量時,機器學習模型可能更有效地根據過去的健康歷史預測未來的死亡率。一個更愉快的例子可能是根據包括緯度、經度、氣候變化、靠近海洋、噴流模式等數據,為某地四月的天氣進行預測。
✅ 這份[幻燈片](https://www2.cisl.ucar.edu/sites/default/files/2021-10/0900%20June%2024%20Haupt_0.pdf)提供了使用機器學習進行天氣分析的歷史視角。
## 建模前的任務
在開始建立模型之前,您需要完成幾項任務。為了測試您的問題並根據模型的預測形成假設,您需要識別並配置幾個元素。
### 數據
為了能夠有一定的確定性回答您的問題,您需要足夠數量且類型正確的數據。在這個階段,您需要完成以下兩件事:
- **收集數據**。記住上一課中關於數據分析公平性的內容,謹慎收集您的數據。注意數據的來源、可能存在的固有偏差,並記錄其來源。
- **準備數據**。數據準備過程包括多個步驟。如果數據來自不同來源,您可能需要整理並標準化它。您可以通過各種方法提高數據的質量和數量,例如將字符串轉換為數字(如我們在[聚類](../../5-Clustering/1-Visualize/README.md)中所做的)。您可能還會基於原始數據生成新數據(如我們在[分類](../../4-Classification/1-Introduction/README.md)中所做的)。您可以清理和編輯數據(如我們在[Web App](../../3-Web-App/README.md)課程之前所做的)。最後,根據您的訓練技術,您可能還需要隨機化並打亂數據。
✅ 在收集和處理數據後,花點時間檢查其形狀是否能幫助您解決預期問題。可能數據在您的任務中表現不佳,正如我們在[聚類](../../5-Clustering/1-Visualize/README.md)課程中所發現的!
### 特徵和目標
[特徵](https://www.datasciencecentral.com/profiles/blogs/an-introduction-to-variable-and-feature-selection)是數據的一個可測量屬性。在許多數據集中,它通常以列標題的形式表達,例如「日期」、「大小」或「顏色」。特徵變量通常在代碼中表示為`X`,代表用於訓練模型的輸入變量。
目標是您試圖預測的事物。目標通常在代碼中表示為`y`,代表您試圖從數據中回答的問題:在十二月,哪種**顏色**的南瓜最便宜?在舊金山,哪些街區的房地產**價格**最好?有時目標也被稱為標籤屬性。
### 選擇特徵變量
🎓 **特徵選擇與特徵提取** 如何在建立模型時選擇變量?您可能需要通過特徵選擇或特徵提取的過程來選擇最合適的變量以構建性能最佳的模型。然而,它們並不完全相同:「特徵提取通過原始特徵的函數創建新特徵,而特徵選擇返回特徵的子集。」([來源](https://wikipedia.org/wiki/Feature_selection)
### 可視化數據
數據科學家工具包中的一個重要方面是使用一些優秀的庫如Seaborn或MatPlotLib來可視化數據的能力。以可視化方式表示數據可能幫助您發現可以利用的隱藏相關性。您的可視化還可能幫助您發現偏差或數據不平衡如我們在[分類](../../4-Classification/2-Classifiers-1/README.md)中所發現的)。
### 分割數據集
在訓練之前,您需要將數據集分為兩個或更多不等大小的部分,這些部分仍然能很好地代表數據。
- **訓練**。數據集的這部分用於訓練模型。這部分通常佔原始數據集的大部分。
- **測試**。測試數據集是獨立的數據組,通常從原始數據中獲得,用於確認已建立模型的性能。
- **驗證**。驗證集是一個較小的獨立數據組,用於調整模型的超參數或架構以改進模型。根據數據的大小和您提出的問題,您可能不需要建立這第三部分(如我們在[時間序列預測](../../7-TimeSeries/1-Introduction/README.md)中所提到的)。
## 建立模型
使用您的訓練數據,您的目標是使用各種算法建立模型,或數據的統計表示,並對其進行**訓練**。訓練模型使其接觸數據,並讓其對發現的模式進行假設、驗證並接受或拒絕。
### 決定訓練方法
根據您的問題和數據的性質,您將選擇一種訓練方法。瀏覽[Scikit-learn的文檔](https://scikit-learn.org/stable/user_guide.html)——我們在本課程中使用它——您可以探索多種訓練模型的方法。根據您的經驗,您可能需要嘗試幾種不同的方法以建立最佳模型。您可能會經歷一個過程,數據科學家通過向模型提供未見過的數據來評估其性能,檢查準確性、偏差和其他質量下降問題,並選擇最適合當前任務的訓練方法。
### 訓練模型
有了訓練數據,您就可以「擬合」它來創建模型。您會注意到,在許多機器學習庫中,您會看到代碼`model.fit`——此時您將特徵變量作為值數組(通常是`X`)以及目標變量(通常是`y`)傳入。
### 評估模型
一旦訓練過程完成對於大型模型可能需要多次迭代或「epoch」您將能夠使用測試數據評估模型的質量以衡量其性能。這些數據是原始數據的一部分模型之前未曾分析過。您可以打印出關於模型質量的指標表。
🎓 **模型擬合**
在機器學習的背景下,模型擬合指的是模型的底層函數在分析其不熟悉的數據時的準確性。
🎓 **欠擬合**和**過擬合**是常見問題,會降低模型的質量,因為模型要麼擬合得不夠好,要麼擬合得太好。這會導致模型的預測要麼過於貼合,要麼過於偏離其訓練數據。過擬合模型因為過於熟悉數據的細節和噪音而對訓練數據預測得過於準確。欠擬合模型則不夠準確,既無法準確分析其訓練數據,也無法準確分析其未見過的數據。
![過擬合模型](../../../../1-Introduction/4-techniques-of-ML/images/overfitting.png)
> 信息圖由 [Jen Looper](https://twitter.com/jenlooper) 提供
## 參數調整
完成初步訓練後,觀察模型的質量,並考慮通過調整其「超參數」來改進它。閱讀更多相關內容[在文檔中](https://docs.microsoft.com/en-us/azure/machine-learning/how-to-tune-hyperparameters?WT.mc_id=academic-77952-leestott)。
## 預測
這是您可以使用全新數據測試模型準確性的時刻。在「應用」機器學習設置中,當您構建網頁資產以在生產環境中使用模型時,此過程可能涉及收集用戶輸入(例如按下按鈕)以設置變量並將其發送到模型進行推斷或評估。
在這些課程中,您將學習如何使用這些步驟來準備、建立、測試、評估和預測——這些都是數據科學家的手勢,隨著您的進步,您將成為「全棧」機器學習工程師。
---
## 🚀挑戰
繪製一個反映機器學習實踐者步驟的流程圖。您認為自己目前處於哪個步驟?您預測在哪些方面會遇到困難?哪些看起來比較容易?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
在線搜索數據科學家討論其日常工作的訪談。這裡有一個[例子](https://www.youtube.com/watch?v=Z3IjgbbCEfs)。
## 作業
[訪問一位數據科學家](assignment.md)
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -0,0 +1,16 @@
# 訪談一位數據科學家
## 指導說明
在你的公司、用戶群組或者你的朋友或同學之中找一位專業從事數據科學工作的人進行訪談。撰寫一篇簡短的文章500字描述他們的日常工作內容。他們是專業領域的專家還是負責「全方位」的工作
## 評分標準
| 評分標準 | 優秀 | 合格 | 需要改進 |
| -------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | --------------------- |
| | 提交一篇符合字數要求,並正確引用來源的文章,格式為 .doc 文件 | 文章引用不完整或字數少於要求 | 未提交文章 |
---
**免責聲明**
此文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對於因使用此翻譯而產生的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,28 @@
# 機器學習簡介
在本課程中,您將了解機器學習領域的基本概念、它的定義,以及它的歷史和研究人員使用的技術。讓我們一起探索這個機器學習的新世界吧!
![globe](../../../translated_images/zh-MO/globe.59f26379ceb40428.webp)
> 照片由 <a href="https://unsplash.com/@bill_oxford?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Bill Oxford</a> 提供,來自 <a href="https://unsplash.com/s/photos/globe?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
### 課程
1. [機器學習簡介](1-intro-to-ML/README.md)
1. [機器學習與人工智慧的歷史](2-history-of-ML/README.md)
1. [公平性與機器學習](3-fairness/README.md)
1. [機器學習的技術](4-techniques-of-ML/README.md)
### 致謝
「機器學習簡介」由 [Muhammad Sakib Khan Inan](https://twitter.com/Sakibinan)、[Ornella Altunyan](https://twitter.com/ornelladotcom) 和 [Jen Looper](https://twitter.com/jenlooper) 等團隊成員傾心撰寫。
「機器學習的歷史」由 [Jen Looper](https://twitter.com/jenlooper) 和 [Amy Boyd](https://twitter.com/AmyKateNicho) 傾心撰寫。
「公平性與機器學習」由 [Tomomi Imura](https://twitter.com/girliemac) 傾心撰寫。
「機器學習的技術」由 [Jen Looper](https://twitter.com/jenlooper) 和 [Chris Noring](https://twitter.com/softchris) 傾心撰寫。
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -0,0 +1,230 @@
# 使用 Python 和 Scikit-learn 建立回歸模型
![回歸模型的概述手繪筆記](../../../../sketchnotes/ml-regression.png)
> 手繪筆記由 [Tomomi Imura](https://www.twitter.com/girlie_mac) 提供
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
> ### [本課程也提供 R 版本!](../../../../2-Regression/1-Tools/solution/R/lesson_1.html)
## 簡介
在這四節課中,您將學習如何建立回歸模型。我們很快會討論這些模型的用途。但在開始之前,請確保您已準備好合適的工具來進行這個過程!
在本課程中,您將學到:
- 配置您的電腦以進行本地機器學習任務。
- 使用 Jupyter 筆記本。
- 安裝並使用 Scikit-learn。
- 通過實際操作探索線性回歸。
## 安裝與配置
[![機器學習入門 - 配置工具以建立機器學習模型](https://img.youtube.com/vi/-DfeD2k2Kj0/0.jpg)](https://youtu.be/-DfeD2k2Kj0 "機器學習入門 - 配置工具以建立機器學習模型")
> 🎥 點擊上方圖片觀看短片,了解如何配置您的電腦以進行機器學習。
1. **安裝 Python**。確保您的電腦已安裝 [Python](https://www.python.org/downloads/)。Python 是進行許多數據科學和機器學習任務的主要工具。大多數電腦系統已預裝 Python。也有一些 [Python 編碼包](https://code.visualstudio.com/learn/educators/installers?WT.mc_id=academic-77952-leestott) 可供使用,能簡化部分用戶的設置過程。
不過,某些 Python 的使用情境可能需要特定版本的軟件,因此建議使用 [虛擬環境](https://docs.python.org/3/library/venv.html)。
2. **安裝 Visual Studio Code**。確保您的電腦已安裝 Visual Studio Code。按照這些指示進行 [安裝 Visual Studio Code](https://code.visualstudio.com/) 的基本設置。在本課程中,您將在 Visual Studio Code 中使用 Python因此可以先熟悉如何 [配置 Visual Studio Code](https://docs.microsoft.com/learn/modules/python-install-vscode?WT.mc_id=academic-77952-leestott) 以進行 Python 開發。
> 透過這些 [學習模組](https://docs.microsoft.com/users/jenlooper-2911/collections/mp1pagggd5qrq7?WT.mc_id=academic-77952-leestott) 熟悉 Python。
>
> [![使用 Visual Studio Code 配置 Python](https://img.youtube.com/vi/yyQM70vi7V8/0.jpg)](https://youtu.be/yyQM70vi7V8 "使用 Visual Studio Code 配置 Python")
>
> 🎥 點擊上方圖片觀看短片:在 VS Code 中使用 Python。
3. **安裝 Scikit-learn**,按照 [這些指示](https://scikit-learn.org/stable/install.html) 進行安裝。由於需要使用 Python 3建議使用虛擬環境。如果您是在 M1 Mac 上安裝此庫,請參考上述頁面中的特殊指示。
4. **安裝 Jupyter Notebook**。您需要 [安裝 Jupyter 套件](https://pypi.org/project/jupyter/)。
## 您的機器學習開發環境
您將使用 **筆記本** 來開發 Python 程式碼並建立機器學習模型。這種文件格式是數據科學家常用的工具,其文件擴展名為 `.ipynb`
筆記本是一種互動式環境,允許開發者撰寫程式碼並添加註解或文件,這對於實驗性或研究導向的項目非常有幫助。
[![機器學習入門 - 配置 Jupyter 筆記本以開始建立回歸模型](https://img.youtube.com/vi/7E-jC8FLA2E/0.jpg)](https://youtu.be/7E-jC8FLA2E "機器學習入門 - 配置 Jupyter 筆記本以開始建立回歸模型")
> 🎥 點擊上方圖片觀看短片,了解如何進行此操作。
### 練習 - 使用筆記本
在此文件夾中,您會找到文件 _notebook.ipynb_
1. 在 Visual Studio Code 中打開 _notebook.ipynb_
Jupyter 伺服器將啟動,並使用 Python 3+。您會看到筆記本中的一些區塊可以 `執行`,這些是程式碼片段。您可以通過選擇播放按鈕圖標來執行程式碼區塊。
2. 選擇 `md` 圖標並添加一些 Markdown輸入以下文字 **# 歡迎來到您的筆記本**。
接下來,添加一些 Python 程式碼。
3. 在程式碼區塊中輸入 **print('hello notebook')**
4. 選擇箭頭以執行程式碼。
您應該會看到以下輸出:
```output
hello notebook
```
![在 VS Code 中打開的筆記本](../../../../2-Regression/1-Tools/images/notebook.jpg)
您可以在程式碼中穿插註解,以自我記錄筆記本。
✅ 思考一下,網頁開發者的工作環境與數據科學家的工作環境有何不同。
## 使用 Scikit-learn 入門
現在 Python 已在您的本地環境中設置完成,並且您已熟悉 Jupyter 筆記本,接下來讓我們熟悉 Scikit-learn發音為 `sci`,像 `science`。Scikit-learn 提供了 [廣泛的 API](https://scikit-learn.org/stable/modules/classes.html#api-ref),幫助您執行機器學習任務。
根據其 [官方網站](https://scikit-learn.org/stable/getting_started.html) 的描述,"Scikit-learn 是一個開源的機器學習庫,支持監督式和非監督式學習。它還提供了多種工具,用於模型擬合、數據預處理、模型選擇和評估,以及許多其他實用功能。"
在本課程中,您將使用 Scikit-learn 和其他工具來建立機器學習模型以執行我們所稱的「傳統機器學習」任務。我們刻意避開了神經網絡和深度學習這些內容將在即將推出的「AI 入門」課程中更詳細地介紹。
Scikit-learn 使建立模型並評估其使用變得簡單。它主要專注於使用數值數據,並包含幾個現成的數據集供學習使用。它還包括一些預建模型供學生嘗試。讓我們探索如何加載預打包數據並使用內建估算器進行第一次機器學習模型的建立。
## 練習 - 您的第一個 Scikit-learn 筆記本
> 本教程靈感來自 Scikit-learn 網站上的 [線性回歸範例](https://scikit-learn.org/stable/auto_examples/linear_model/plot_ols.html#sphx-glr-auto-examples-linear-model-plot-ols-py)。
[![機器學習入門 - 您的第一個 Python 線性回歸項目](https://img.youtube.com/vi/2xkXL5EUpS0/0.jpg)](https://youtu.be/2xkXL5EUpS0 "機器學習入門 - 您的第一個 Python 線性回歸項目")
> 🎥 點擊上方圖片觀看短片,了解如何進行此練習。
在與本課程相關的 _notebook.ipynb_ 文件中,按下「垃圾桶」圖標清除所有單元格。
在本節中,您將使用 Scikit-learn 中內建的關於糖尿病的小型數據集進行學習。假設您想測試一種糖尿病患者的治療方法。機器學習模型可能幫助您根據變數的組合,判斷哪些患者對治療的反應更好。即使是非常基本的回歸模型,當可視化時,也可能顯示出有助於組織理論臨床試驗的變數信息。
✅ 回歸方法有很多種類型,選擇哪一種取決於您想要回答的問題。如果您想預測某個年齡的人的可能身高,您會使用線性回歸,因為您尋求的是一個 **數值**。如果您想判斷某種菜餚是否應被視為素食,您尋求的是一個 **類別分配**,因此您會使用邏輯回歸。稍後您將學習更多關於邏輯回歸的內容。思考一下您可以向數據提出哪些問題,以及哪種方法更適合。
讓我們開始這項任務。
### 導入庫
在此任務中,我們將導入一些庫:
- **matplotlib**。這是一個有用的 [繪圖工具](https://matplotlib.org/),我們將使用它來創建折線圖。
- **numpy**。 [numpy](https://numpy.org/doc/stable/user/whatisnumpy.html) 是一個處理 Python 數值數據的有用庫。
- **sklearn**。這是 [Scikit-learn](https://scikit-learn.org/stable/user_guide.html) 庫。
導入一些庫以幫助完成任務。
1. 輸入以下程式碼以添加導入:
```python
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model, model_selection
```
上述程式碼中,您導入了 `matplotlib``numpy`,並從 `sklearn` 中導入了 `datasets`、`linear_model` 和 `model_selection`。`model_selection` 用於將數據分割為訓練集和測試集。
### 糖尿病數據集
內建的 [糖尿病數據集](https://scikit-learn.org/stable/datasets/toy_dataset.html#diabetes-dataset) 包含 442 個關於糖尿病的數據樣本,具有 10 個特徵變數,其中一些包括:
- age年齡以年為單位
- bmi身體質量指數
- bp平均血壓
- s1 tcT 細胞(一種白血球)
✅ 此數據集包含「性別」作為研究糖尿病的重要特徵變數。許多醫學數據集都包含這種二元分類。思考一下,這類分類可能如何排除某些群體的治療。
現在,載入 X 和 y 數據。
> 🎓 記住,這是監督式學習,我們需要一個名為 'y' 的目標。
在新的程式碼單元格中,通過調用 `load_diabetes()` 載入糖尿病數據集。輸入 `return_X_y=True` 表示 `X` 將是數據矩陣,而 `y` 將是回歸目標。
1. 添加一些 print 命令以顯示數據矩陣的形狀及其第一個元素:
```python
X, y = datasets.load_diabetes(return_X_y=True)
print(X.shape)
print(X[0])
```
您得到的響應是一個元組。您正在將元組的前兩個值分別分配給 `X``y`。了解更多 [關於元組](https://wikipedia.org/wiki/Tuple)。
您可以看到此數據包含 442 個項目,形狀為 10 個元素的數組:
```text
(442, 10)
[ 0.03807591 0.05068012 0.06169621 0.02187235 -0.0442235 -0.03482076
-0.04340085 -0.00259226 0.01990842 -0.01764613]
```
✅ 思考一下數據與回歸目標之間的關係。線性回歸預測特徵 X 和目標變數 y 之間的關係。您能在文檔中找到糖尿病數據集的 [目標](https://scikit-learn.org/stable/datasets/toy_dataset.html#diabetes-dataset) 嗎?此數據集展示了什麼?
2. 接下來,選擇此數據集的一部分進行繪圖,選擇數據集的第三列。您可以使用 `:` 運算符選擇所有行然後使用索引2選擇第三列。您還可以使用 `reshape(n_rows, n_columns)` 將數據重塑為 2D 數組——這是繪圖所需的格式。如果其中一個參數為 -1則對應的維度會自動計算。
```python
X = X[:, 2]
X = X.reshape((-1,1))
```
✅ 隨時打印數據以檢查其形狀。
3. 現在您已準備好繪製數據可以看看機器是否能幫助確定數據集中數字的邏輯分割。為此您需要將數據X和目標y分割為測試集和訓練集。Scikit-learn 提供了一種簡單的方法,您可以在給定點分割測試數據。
```python
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.33)
```
4. 現在您可以訓練模型了!載入線性回歸模型,並使用 `model.fit()` 訓練您的 X 和 y 訓練集:
```python
model = linear_model.LinearRegression()
model.fit(X_train, y_train)
```
`model.fit()` 是一個您會在許多機器學習庫(如 TensorFlow中看到的函數。
5. 然後,使用測試數據創建預測,使用函數 `predict()`。這將用於繪製數據組之間的分割線。
```python
y_pred = model.predict(X_test)
```
6. 現在是時候在圖中顯示數據了。Matplotlib 是完成此任務的非常有用的工具。創建所有 X 和 y 測試數據的散點圖,並使用預測在最合適的位置繪製一條線,分割模型的數據組。
```python
plt.scatter(X_test, y_test, color='black')
plt.plot(X_test, y_pred, color='blue', linewidth=3)
plt.xlabel('Scaled BMIs')
plt.ylabel('Disease Progression')
plt.title('A Graph Plot Showing Diabetes Progression Against BMI')
plt.show()
```
![顯示糖尿病數據點的散點圖](../../../../2-Regression/1-Tools/images/scatterplot.png)
✅ 想一想這裡發生了什麼。一條直線穿過許多小數據點,但它究竟在做什麼?你能否看出如何利用這條直線來預測一個新的、未見過的數據點應該如何與圖表的 y 軸關係匹配?試著用語言描述這個模型的實際用途。
恭喜你,完成了第一個線性回歸模型,用它進行了預測,並在圖表中展示了結果!
---
## 🚀挑戰
繪製此數據集中不同的變量。提示:編輯這一行:`X = X[:,2]`。根據此數據集的目標,你能發現糖尿病作為一種疾病的進展情況嗎?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
在本教程中,你使用了簡單線性回歸,而不是單變量或多變量線性回歸。閱讀一些關於這些方法差異的資料,或者觀看[這段影片](https://www.coursera.org/lecture/quantifying-relationships-regression-models/linear-vs-nonlinear-categorical-variables-ai2Ef)。
深入了解回歸的概念,並思考可以用這種技術回答哪些問題。參加這個[教程](https://docs.microsoft.com/learn/modules/train-evaluate-regression-models?WT.mc_id=academic-77952-leestott),加深你的理解。
## 作業
[不同的數據集](assignment.md)
---
**免責聲明**
本文件使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而產生的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,18 @@
# 使用 Scikit-learn 進行回歸分析
## 說明
查看 Scikit-learn 中的 [Linnerud 數據集](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_linnerud.html#sklearn.datasets.load_linnerud)。這個數據集包含多個[目標](https://scikit-learn.org/stable/datasets/toy_dataset.html#linnerrud-dataset):「它由三個運動(數據)和三個生理(目標)變量組成,這些數據是從健身俱樂部的二十名中年男性收集的。」
請用自己的話描述如何建立一個回歸模型,繪製腰圍與完成仰臥起坐次數之間的關係。同樣,請對此數據集中的其他數據點進行相同的操作。
## 評分標準
| 評分項目 | 優秀 | 合格 | 需要改進 |
| ------------------------------ | --------------------------------- | ----------------------------- | -------------------------- |
| 提交描述性段落 | 提交了一段撰寫良好的段落 | 提交了幾句簡短的描述 | 未提交任何描述 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,6 @@
---
**免責聲明**
本文件已使用 AI 翻譯服務 [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-08-29T23:09:02+00:00",
"source_file": "2-Regression/1-Tools/solution/R/lesson_1-R.ipynb",
"language_code": "mo"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "YJUHCXqK57yz"
}
},
{
"cell_type": "markdown",
"source": [
"## 回歸分析入門 - 第一課\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](../../../../../../translated_images/zh-MO/encouRage.e75d5fe0367fb913.webp)<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()` 對數據進行基本檢查,並使用 `slice()` 顯示前 5 行。\n",
"\n",
"在繼續之前,讓我們介紹一個您在 R 代碼中經常會遇到的東西 🥁🥁:管道運算符 `%>%`\n",
"\n",
"管道運算符 (`%>%`) 通過將一個對象向前傳遞到函數或調用表達式中,按邏輯順序執行操作。您可以將管道運算符理解為在代碼中表示 \"然後\" 的意思。\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",
"現在我們已經訓練了一個模型,可以使用 [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html) 來對測試數據集中的疾病進展 y 進行預測。這將用於繪製數據組之間的分界線。\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/資料框結果。這樣可以輕鬆地將原始數據和預測結果結合成一個可用的格式,方便後續操作,例如繪圖。\n",
"\n",
"`dplyr::bind_cols()` 可以高效地將多個資料框按欄位結合起來。\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,217 @@
# 使用 Scikit-learn 建立回歸模型:準備並視覺化數據
![數據視覺化資訊圖表](../../../../2-Regression/2-Data/images/data-visualization.png)
資訊圖表由 [Dasani Madipalli](https://twitter.com/dasani_decoded) 製作
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
> ### [本課程也提供 R 版本!](../../../../2-Regression/2-Data/solution/R/lesson_2.html)
## 簡介
現在您已經準備好使用 Scikit-learn 開始建立機器學習模型,您可以開始向數據提出問題了。在處理數據並應用機器學習解決方案時,了解如何提出正確的問題以充分發揮數據的潛力是非常重要的。
在本課程中,您將學到:
- 如何為模型建立準備數據。
- 如何使用 Matplotlib 進行數據視覺化。
## 向數據提出正確的問題
您需要回答的問題將決定您使用哪種類型的機器學習算法。而您得到答案的質量將在很大程度上取決於數據的性質。
看看本課程提供的[數據](https://github.com/microsoft/ML-For-Beginners/blob/main/2-Regression/data/US-pumpkins.csv)。您可以在 VS Code 中打開這個 .csv 文件。快速瀏覽後,您會發現其中有空白值,並且混合了字符串和數字數據。此外,還有一個名為 "Package" 的奇怪列,其中的數據混合了 "sacks"、"bins" 和其他值。事實上,這些數據有些混亂。
[![機器學習初學者 - 如何分析和清理數據集](https://img.youtube.com/vi/5qGjczWTrDQ/0.jpg)](https://youtu.be/5qGjczWTrDQ "機器學習初學者 - 如何分析和清理數據集")
> 🎥 點擊上方圖片觀看一段短片,了解如何準備本課程的數據。
事實上,很少能直接獲得完全準備好的數據集來建立機器學習模型。在本課程中,您將學習如何使用標準 Python 庫準備原始數據集。您還將學習各種視覺化數據的技術。
## 案例研究:'南瓜市場'
在此文件夾中,您會在根目錄的 `data` 文件夾中找到一個名為 [US-pumpkins.csv](https://github.com/microsoft/ML-For-Beginners/blob/main/2-Regression/data/US-pumpkins.csv) 的 .csv 文件,其中包含 1757 行有關南瓜市場的數據,按城市分組。這是從美國農業部發布的[特殊作物終端市場標準報告](https://www.marketnews.usda.gov/mnp/fv-report-config-step1?type=termPrice)中提取的原始數據。
### 準備數據
這些數據屬於公共領域。它可以從 USDA 網站下載按城市分成多個文件。為了避免過多的文件我們已將所有城市數據合併到一個電子表格中因此我們已經對數據進行了一些_準備_。接下來讓我們仔細看看這些數據。
### 南瓜數據 - 初步結論
您對這些數據有什麼看法?您可能已經注意到其中混合了字符串、數字、空白值和一些奇怪的值,這些都需要進一步理解。
使用回歸技術,您可以向這些數據提出什麼問題?例如:"預測某個月份出售的南瓜價格"。再次查看數據,您需要進行一些更改以創建適合此任務的數據結構。
## 練習 - 分析南瓜數據
讓我們使用 [Pandas](https://pandas.pydata.org/)(名稱代表 `Python Data Analysis`),這是一個非常有用的工具,用於整理數據,來分析和準備這些南瓜數據。
### 首先,檢查是否有缺失日期
您需要首先檢查是否有缺失日期:
1. 將日期轉換為月份格式(這些是美國日期,格式為 `MM/DD/YYYY`)。
2. 提取月份到新列。
在 Visual Studio Code 中打開 _notebook.ipynb_ 文件,並將電子表格導入到新的 Pandas dataframe 中。
1. 使用 `head()` 函數查看前五行。
```python
import pandas as pd
pumpkins = pd.read_csv('../data/US-pumpkins.csv')
pumpkins.head()
```
✅ 您會使用什麼函數來查看最後五行?
1. 檢查當前 dataframe 中是否有缺失數據:
```python
pumpkins.isnull().sum()
```
有缺失數據,但可能對當前任務影響不大。
1. 為了使 dataframe 更易於操作,使用 `loc` 函數選擇您需要的列。`loc` 函數從原始 dataframe 中提取一組行(作為第一個參數)和列(作為第二個參數)。以下表達式中的 `:` 表示 "所有行"。
```python
columns_to_select = ['Package', 'Low Price', 'High Price', 'Date']
pumpkins = pumpkins.loc[:, columns_to_select]
```
### 其次,確定南瓜的平均價格
思考如何確定某個月份南瓜的平均價格。您會選擇哪些列來完成此任務?提示:您需要 3 列。
解決方案:取 `Low Price``High Price` 列的平均值來填充新的 Price 列,並將 Date 列轉換為僅顯示月份。幸運的是,根據上述檢查,日期和價格沒有缺失數據。
1. 要計算平均值,添加以下代碼:
```python
price = (pumpkins['Low Price'] + pumpkins['High Price']) / 2
month = pd.DatetimeIndex(pumpkins['Date']).month
```
✅ 隨時使用 `print(month)` 打印任何您想檢查的數據。
2. 現在,將轉換後的數據複製到新的 Pandas dataframe 中:
```python
new_pumpkins = pd.DataFrame({'Month': month, 'Package': pumpkins['Package'], 'Low Price': pumpkins['Low Price'],'High Price': pumpkins['High Price'], 'Price': price})
```
打印出您的 dataframe您將看到一個乾淨整潔的數據集您可以基於此建立新的回歸模型。
### 等等!這裡有些奇怪的地方
如果您查看 `Package` 列,南瓜以多種不同的配置出售。有些以 "1 1/9 bushel" 測量,有些以 "1/2 bushel" 測量,有些按南瓜個數出售,有些按磅出售,還有些以不同寬度的大箱出售。
> 南瓜似乎很難一致地稱重
深入研究原始數據,發現 `Unit of Sale` 為 "EACH" 或 "PER BIN" 的項目,其 `Package` 類型也為每英寸、每箱或 "each"。南瓜似乎很難一致地稱重,因此讓我們通過選擇 `Package` 列中包含 "bushel" 字符串的南瓜來進行篩選。
1. 在文件頂部的初始 .csv 導入下添加篩選器:
```python
pumpkins = pumpkins[pumpkins['Package'].str.contains('bushel', case=True, regex=True)]
```
如果您現在打印數據,您會看到只有大約 415 行數據包含以 bushel 為單位的南瓜。
### 等等!還有一件事需要做
您是否注意到每行的 bushel 數量不同?您需要標準化定價,以顯示每 bushel 的價格,因此需要進行一些數學運算來標準化。
1. 在創建 new_pumpkins dataframe 的代碼塊後添加以下行:
```python
new_pumpkins.loc[new_pumpkins['Package'].str.contains('1 1/9'), 'Price'] = price/(1 + 1/9)
new_pumpkins.loc[new_pumpkins['Package'].str.contains('1/2'), 'Price'] = price/(1/2)
```
✅ 根據 [The Spruce Eats](https://www.thespruceeats.com/how-much-is-a-bushel-1389308)bushel 的重量取決於農產品的類型,因為它是一種體積測量。"例如,一 bushel 的番茄應該重 56 磅... 葉子和綠色蔬菜佔用更多空間但重量較輕,因此一 bushel 的菠菜僅重 20 磅。" 這一切都相當複雜!我們不需要進行 bushel 到磅的轉換,而是直接按 bushel 定價。然而,所有這些對南瓜 bushel 的研究表明,了解數據的性質是多麼重要!
現在,您可以根據 bushel 測量分析每單位的定價。如果您再次打印數據,您可以看到它已被標準化。
✅ 您是否注意到按半 bushel 出售的南瓜非常昂貴?您能找出原因嗎?提示:小南瓜比大南瓜更昂貴,可能是因為每 bushel 中有更多的小南瓜,而大南瓜的空心部分佔用了更多空間。
## 視覺化策略
數據科學家的部分職責是展示他們正在處理的數據的質量和性質。為此,他們通常會創建有趣的視覺化,例如圖表、折線圖和柱狀圖,展示數據的不同方面。通過這種方式,他們能夠直觀地展示數據中難以察覺的關係和差距。
[![機器學習初學者 - 如何使用 Matplotlib 視覺化數據](https://img.youtube.com/vi/SbUkxH6IJo0/0.jpg)](https://youtu.be/SbUkxH6IJo0 "機器學習初學者 - 如何使用 Matplotlib 視覺化數據")
> 🎥 點擊上方圖片觀看一段短片,了解如何視覺化本課程的數據。
視覺化還可以幫助確定最適合數據的機器學習技術。例如,似乎遵循一條線的散點圖表明該數據非常適合線性回歸練習。
一個在 Jupyter notebook 中效果良好的數據視覺化庫是 [Matplotlib](https://matplotlib.org/)(您在上一課中也見過)。
> 在[這些教程](https://docs.microsoft.com/learn/modules/explore-analyze-data-with-python?WT.mc_id=academic-77952-leestott)中獲得更多數據視覺化的經驗。
## 練習 - 嘗試使用 Matplotlib
嘗試創建一些基本圖表來顯示您剛剛創建的新 dataframe。基本折線圖會顯示什麼
1. 在文件頂部的 Pandas 導入下導入 Matplotlib
```python
import matplotlib.pyplot as plt
```
1. 重新運行整個 notebook 以刷新。
1. 在 notebook 底部添加一個單元格,將數據繪製為框圖:
```python
price = new_pumpkins.Price
month = new_pumpkins.Month
plt.scatter(price, month)
plt.show()
```
![顯示價格與月份關係的散點圖](../../../../2-Regression/2-Data/images/scatterplot.png)
這是一個有用的圖表嗎?有什麼讓您感到驚訝嗎?
它並不是特別有用,因為它僅僅顯示了某個月份的數據分佈。
### 使其更有用
要使圖表顯示有用的數據,通常需要以某種方式對數據進行分組。讓我們嘗試創建一個圖表,其中 y 軸顯示月份,數據展示數據的分佈。
1. 添加一個單元格以創建分組柱狀圖:
```python
new_pumpkins.groupby(['Month'])['Price'].mean().plot(kind='bar')
plt.ylabel("Pumpkin Price")
```
![顯示價格與月份關係的柱狀圖](../../../../2-Regression/2-Data/images/barchart.png)
這是一個更有用的數據視覺化!它似乎表明南瓜的最高價格出現在九月和十月。這符合您的預期嗎?為什麼?
---
## 🚀挑戰
探索 Matplotlib 提供的不同類型的視覺化。哪些類型最適合回歸問題?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
看看數據視覺化的多種方式。列出可用的各種庫,並記錄哪些庫最適合特定類型的任務,例如 2D 視覺化與 3D 視覺化。您發現了什麼?
## 作業
[探索視覺化](assignment.md)
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,14 @@
# 探索視覺化
有許多不同的庫可用於數據視覺化。在本課程中,使用南瓜數據在範例筆記本中創建一些視覺化,並使用 matplotlib 和 seaborn。哪些庫更容易使用
## 評分標準
| 標準 | 卓越 | 合格 | 需要改進 |
| -------- | --------- | -------- | ----------------- |
| | 提交了一個包含兩個探索/視覺化的筆記本 | 提交了一個包含一個探索/視覺化的筆記本 | 未提交筆記本 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -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-08-29T23:10:38+00:00",
"source_file": "2-Regression/2-Data/notebook.ipynb",
"language_code": "mo"
}
},
"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,6 @@
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,671 @@
{
"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-08-29T23:14:57+00:00",
"source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb",
"language_code": "mo"
}
},
"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 提供](../../../../../../translated_images/zh-MO/unruly_data.0eedc7ced92d2d91.webp)<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",
"事實上,很少能直接獲得一個完全準備好用來建立機器學習模型的資料集。但別擔心,在這節課中,你將學習如何使用標準的 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 提供](../../../../../../translated_images/zh-MO/dplyr_wrangling.f5f99c64fd4580f1.webp)<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",
"讓我們使用 `Date` 欄位來試試 `mutate`,進行以下操作:\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"
],
"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 蒲式耳` 為單位,有些是以 `1/2 蒲式耳` 為單位,有些是按南瓜數量出售,有些是按重量(每磅)出售,還有一些是裝在寬度各異的大箱子裡。\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",
"南瓜的重量似乎很難保持一致,所以我們來篩選一下,只選擇在 `Package` 欄位中包含 *bushel* 字串的南瓜,並將其放入一個新的資料框 `new_pumpkins` 中。\n",
"<br>\n"
],
"metadata": {
"id": "7sMjiVujaZxY"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::filter() 和 stringr::str_detect()\n",
"\n",
"[`dplyr::filter()`](https://dplyr.tidyverse.org/reference/filter.html):建立一個資料的子集,只包含符合條件的**列**,在此例中,是指在 `Package` 欄位中包含 *bushel* 字串的南瓜。\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": [
"現在,最後為了冒險的樂趣 💁‍♀️,我們將「月份」欄位移到第一個位置,也就是在「套件」欄位之前。\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 提供](../../../../../../translated_images/zh-MO/data-visualization.54e56dded7c1a804.webp){width=\"600\"}-->\n",
"\n",
"有一句*智慧*的名言是這樣說的:\n",
"\n",
"> 「簡單的圖表比任何其他工具都能為數據分析師帶來更多的信息。」 --- John Tukey\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"
],
"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,373 @@
# 使用 Scikit-learn 建立回歸模型:四種回歸方法
![線性回歸與多項式回歸資訊圖表](../../../../2-Regression/3-Linear/images/linear-polynomial.png)
> 資訊圖表由 [Dasani Madipalli](https://twitter.com/dasani_decoded) 製作
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
> ### [本課程也提供 R 版本!](../../../../2-Regression/3-Linear/solution/R/lesson_3.html)
### 簡介
到目前為止,您已經透過南瓜價格數據集的樣本數據了解了什麼是回歸分析,並使用 Matplotlib 進行了可視化。
現在,您準備深入了解機器學習中的回歸分析。雖然可視化可以幫助您理解數據,但機器學習的真正力量來自於 _訓練模型_。模型基於歷史數據進行訓練,能夠自動捕捉數據之間的依賴關係,並幫助您預測模型未曾見過的新數據的結果。
在本課程中您將學習更多關於兩種回歸方法_基本線性回歸_ 和 _多項式回歸_,以及這些技術背後的一些數學原理。這些模型將幫助我們根據不同的輸入數據預測南瓜的價格。
[![初學者的機器學習 - 理解線性回歸](https://img.youtube.com/vi/CRxFT8oTDMg/0.jpg)](https://youtu.be/CRxFT8oTDMg "初學者的機器學習 - 理解線性回歸")
> 🎥 點擊上方圖片觀看線性回歸的簡短視頻概述。
> 在整個課程中,我們假設學生的數學知識有限,並努力使內容對來自其他領域的學生更易理解,因此請留意筆記、🧮 數學提示、圖表以及其他學習工具以幫助理解。
### 先決條件
到目前為止,您應該已熟悉我們正在分析的南瓜數據的結構。您可以在本課程的 _notebook.ipynb_ 文件中找到預加載和預清理的數據。在該文件中,南瓜的價格以每蒲式耳的形式顯示在新的數據框中。請確保您可以在 Visual Studio Code 的內核中運行這些筆記本。
### 準備工作
提醒一下,您正在加載這些數據以便提出問題。
- 什麼時候是購買南瓜的最佳時機?
- 我可以預期一箱迷你南瓜的價格是多少?
- 我應該選擇半蒲式耳籃子還是 1 1/9 蒲式耳箱來購買?
讓我們繼續深入挖掘這些數據。
在上一課中,您創建了一個 Pandas 數據框,並用原始數據集的一部分填充它,將價格標準化為每蒲式耳。然而,通過這樣做,您只能收集到大約 400 個數據點,而且僅限於秋季月份。
查看本課程附帶的筆記本中預加載的數據。數據已預加載,並繪製了初始散點圖以顯示月份數據。也許通過進一步清理數據,我們可以更詳細地了解數據的性質。
## 線性回歸線
正如您在第一課中所學,線性回歸的目標是能夠繪製一條線以:
- **顯示變數關係**。展示變數之間的關係
- **進行預測**。準確預測新數據點在該線上的位置
通常使用 **最小平方回歸** 來繪製這種類型的線。'最小平方' 的意思是回歸線周圍的所有數據點的距離平方後相加。理想情況下,最終的總和應該盡可能小,因為我們希望誤差數量低,也就是 `最小平方`
我們這樣做是因為我們希望建模一條距離所有數據點累積距離最小的線。我們在相加之前對項進行平方,因為我們關注的是其大小而不是方向。
> **🧮 數學展示**
>
> 這條線,稱為 _最佳擬合線_,可以用 [一個方程](https://en.wikipedia.org/wiki/Simple_linear_regression) 表示:
>
> ```
> Y = a + bX
> ```
>
> `X` 是 '解釋變數'`Y` 是 '依賴變數'。線的斜率是 `b`,而 `a` 是 y 截距,指的是當 `X = 0``Y` 的值。
>
>![計算斜率](../../../../2-Regression/3-Linear/images/slope.png)
>
> 首先,計算斜率 `b`。資訊圖表由 [Jen Looper](https://twitter.com/jenlooper) 製作
>
> 換句話說,參考我們南瓜數據的原始問題:"根據月份預測每蒲式耳南瓜的價格"`X` 代表價格,`Y` 代表銷售月份。
>
>![完成方程](../../../../2-Regression/3-Linear/images/calculation.png)
>
> 計算 Y 的值。如果您支付大約 $4那一定是四月資訊圖表由 [Jen Looper](https://twitter.com/jenlooper) 製作
>
> 計算這條線的數學必須展示線的斜率,這也取決於截距,即當 `X = 0``Y` 的位置。
>
> 您可以在 [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html) 網站上觀察這些值的計算方法。也可以訪問 [最小平方計算器](https://www.mathsisfun.com/data/least-squares-calculator.html) 來查看數字值如何影響線。
## 相關性
另一個需要理解的術語是 **相關係數**,即給定 X 和 Y 變數之間的相關性。使用散點圖,您可以快速可視化該係數。數據點整齊排列成一條線的圖表具有高相關性,而數據點在 X 和 Y 之間隨意分佈的圖表則具有低相關性。
一個好的線性回歸模型應該是使用最小平方回歸方法和回歸線,並且具有高(接近 1 而非 0的相關係數。
✅ 運行本課程附帶的筆記本,查看月份與價格的散點圖。根據您的視覺解讀,南瓜銷售的月份與價格之間的數據是否具有高或低相關性?如果您使用更精細的測量方式(例如 *一年中的天數*,即自年初以來的天數),結果是否會有所改變?
在下面的代碼中,我們假設已清理數據,並獲得了一個名為 `new_pumpkins` 的數據框,類似於以下內容:
ID | Month | DayOfYear | Variety | City | Package | Low Price | High Price | Price
---|-------|-----------|---------|------|---------|-----------|------------|-------
70 | 9 | 267 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 15.0 | 15.0 | 13.636364
71 | 9 | 267 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 18.0 | 18.0 | 16.363636
72 | 10 | 274 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 18.0 | 18.0 | 16.363636
73 | 10 | 274 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 17.0 | 17.0 | 15.454545
74 | 10 | 281 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 15.0 | 15.0 | 13.636364
> 清理數據的代碼可在 [`notebook.ipynb`](../../../../2-Regression/3-Linear/notebook.ipynb) 中找到。我們執行了與上一課相同的清理步驟,並使用以下表達式計算了 `DayOfYear` 列:
```python
day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)
```
現在您已了解線性回歸背後的數學原理,讓我們建立一個回歸模型,看看是否可以預測哪種南瓜包裝的價格最划算。想要為節日南瓜園購買南瓜的人可能需要這些信息來優化南瓜包裝的購買。
## 尋找相關性
[![初學者的機器學習 - 尋找相關性:線性回歸的關鍵](https://img.youtube.com/vi/uoRq-lW2eQo/0.jpg)](https://youtu.be/uoRq-lW2eQo "初學者的機器學習 - 尋找相關性:線性回歸的關鍵")
> 🎥 點擊上方圖片觀看相關性的簡短視頻概述。
從上一課中,您可能已經看到不同月份的平均價格如下所示:
<img alt="按月份的平均價格" src="../../../../translated_images/zh-MO/barchart.a833ea9194346d76.webp" width="50%"/>
這表明應該存在某種相關性,我們可以嘗試訓練線性回歸模型來預測 `Month``Price``DayOfYear``Price` 之間的關係。以下是顯示後者關係的散點圖:
<img alt="價格與一年中的天數的散點圖" src="../../../../translated_images/zh-MO/scatter-dayofyear.bc171c189c9fd553.webp" width="50%" />
讓我們使用 `corr` 函數檢查是否存在相關性:
```python
print(new_pumpkins['Month'].corr(new_pumpkins['Price']))
print(new_pumpkins['DayOfYear'].corr(new_pumpkins['Price']))
```
看起來相關性很小,`Month` 為 -0.15`DayOfYear` 為 -0.17,但可能存在另一個重要的關係。看起來不同的南瓜品種對價格的影響更大。為了確認這一假設,讓我們用不同的顏色繪製每個南瓜品種。通過向 `scatter` 繪圖函數傳遞 `ax` 參數,我們可以將所有點繪製在同一圖上:
```python
ax=None
colors = ['red','blue','green','yellow']
for i,var in enumerate(new_pumpkins['Variety'].unique()):
df = new_pumpkins[new_pumpkins['Variety']==var]
ax = df.plot.scatter('DayOfYear','Price',ax=ax,c=colors[i],label=var)
```
<img alt="價格與一年中的天數的散點圖" src="../../../../translated_images/zh-MO/scatter-dayofyear-color.65790faefbb9d54f.webp" width="50%" />
我們的調查表明,品種對整體價格的影響比實際銷售日期更大。我們可以通過柱狀圖看到這一點:
```python
new_pumpkins.groupby('Variety')['Price'].mean().plot(kind='bar')
```
<img alt="價格與品種的柱狀圖" src="../../../../translated_images/zh-MO/price-by-variety.744a2f9925d9bcb4.webp" width="50%" />
讓我們暫時只關注一種南瓜品種——'pie type',看看日期對價格的影響:
```python
pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE']
pie_pumpkins.plot.scatter('DayOfYear','Price')
```
<img alt="價格與一年中的天數的散點圖" src="../../../../translated_images/zh-MO/pie-pumpkins-scatter.d14f9804a53f927e.webp" width="50%" />
如果我們現在使用 `corr` 函數計算 `Price``DayOfYear` 之間的相關性,我們會得到類似 `-0.27` 的結果——這意味著訓練一個預測模型是有意義的。
> 在訓練線性回歸模型之前,確保數據清理是很重要的。線性回歸對缺失值的處理效果不佳,因此清理掉所有空單元格是有意義的:
```python
pie_pumpkins.dropna(inplace=True)
pie_pumpkins.info()
```
另一種方法是用相應列的平均值填充這些空值。
## 簡單線性回歸
[![初學者的機器學習 - 使用 Scikit-learn 進行線性和多項式回歸](https://img.youtube.com/vi/e4c_UP2fSjg/0.jpg)](https://youtu.be/e4c_UP2fSjg "初學者的機器學習 - 使用 Scikit-learn 進行線性和多項式回歸")
> 🎥 點擊上方圖片觀看線性和多項式回歸的簡短視頻概述。
為了訓練我們的線性回歸模型,我們將使用 **Scikit-learn** 庫。
```python
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
```
首先,我們將輸入值(特徵)和預期輸出(標籤)分離到不同的 numpy 陣列中:
```python
X = pie_pumpkins['DayOfYear'].to_numpy().reshape(-1,1)
y = pie_pumpkins['Price']
```
> 請注意,我們需要對輸入數據進行 `reshape`,以便線性回歸包正確理解它。線性回歸需要一個 2D 陣列作為輸入,其中陣列的每一行對應於輸入特徵的向量。在我們的情況下,由於我們只有一個輸入——我們需要一個形狀為 N×1 的陣列,其中 N 是數據集的大小。
接著,我們需要將數據分為訓練集和測試集,以便在訓練後驗證模型:
```python
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
```
最後,訓練實際的線性回歸模型只需要兩行代碼。我們定義 `LinearRegression` 對象,並使用 `fit` 方法將其擬合到數據中:
```python
lin_reg = LinearRegression()
lin_reg.fit(X_train,y_train)
```
`LinearRegression` 對象在 `fit` 後包含所有回歸係數,可以通過 `.coef_` 屬性訪問。在我們的情況下,只有一個係數,應該大約是 `-0.017`。這意味著價格似乎隨時間略有下降,但幅度不大,每天大約下降 2 美分。我們還可以通過 `lin_reg.intercept_` 訪問回歸線與 Y 軸的交點——在我們的情況下,大約是 `21`,表示年初的價格。
為了查看模型的準確性我們可以在測試數據集上預測價格然後測量預測值與預期值的接近程度。這可以通過均方誤差MSE指標來完成MSE 是所有預期值與預測值之間平方差的平均值。
```python
pred = lin_reg.predict(X_test)
mse = np.sqrt(mean_squared_error(y_test,pred))
print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)')
```
我們的錯誤似乎集中在兩個點上,大約是 17%。表現不太理想。另一個衡量模型品質的指標是 **決定係數**,可以通過以下方式獲得:
```python
score = lin_reg.score(X_train,y_train)
print('Model determination: ', score)
```
如果值為 0表示模型未考慮輸入數據並且表現為*最差的線性預測器*,即僅僅是結果的平均值。值為 1 則表示我們可以完美地預測所有期望的輸出。在我們的情況下,決定係數約為 0.06,這相當低。
我們還可以繪製測試數據與回歸線的圖表,以更好地了解回歸在我們的案例中的表現:
```python
plt.scatter(X_test,y_test)
plt.plot(X_test,pred)
```
<img alt="線性回歸" src="../../../../translated_images/zh-MO/linear-results.f7c3552c85b0ed1c.webp" width="50%" />
## 多項式回歸
另一種線性回歸是多項式回歸。有時候,變量之間存在線性關係,例如南瓜的體積越大,價格越高;但有時候這些關係無法用平面或直線來表示。
✅ 這裡有一些[更多例子](https://online.stat.psu.edu/stat501/lesson/9/9.8),展示了可以使用多項式回歸的數據。
再看看日期與價格之間的關係。這個散點圖看起來是否一定要用直線來分析?價格難道不會波動嗎?在這種情況下,你可以嘗試使用多項式回歸。
✅ 多項式是可能包含一個或多個變量和係數的數學表達式。
多項式回歸會創建一條曲線,以更好地擬合非線性數據。在我們的案例中,如果我們在輸入數據中加入平方的 `DayOfYear` 變量,我們應該能用一條拋物線來擬合數據,該拋物線在一年中的某個點會有一個最低值。
Scikit-learn 提供了一個方便的 [pipeline API](https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.make_pipeline.html?highlight=pipeline#sklearn.pipeline.make_pipeline),可以將不同的數據處理步驟結合在一起。**Pipeline** 是一個由**估算器**組成的鏈。在我們的案例中,我們將創建一個 pipeline首先向模型添加多項式特徵然後訓練回歸
```python
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())
pipeline.fit(X_train,y_train)
```
使用 `PolynomialFeatures(2)` 表示我們將包含所有二次多項式特徵。在我們的案例中,這僅意味著 `DayOfYear`<sup>2</sup>,但如果有兩個輸入變量 X 和 Y這將添加 X<sup>2</sup>、XY 和 Y<sup>2</sup>。如果需要,我們也可以使用更高次的多項式。
Pipeline 的使用方式與原始的 `LinearRegression` 對象相同,例如我們可以 `fit` pipeline然後使用 `predict` 獲得預測結果。以下是顯示測試數據和近似曲線的圖表:
<img alt="多項式回歸" src="../../../../translated_images/zh-MO/poly-results.ee587348f0f1f60b.webp" width="50%" />
使用多項式回歸,我們可以獲得稍低的 MSE 和稍高的決定係數,但提升並不顯著。我們需要考慮其他特徵!
> 你可以看到南瓜價格的最低點大約出現在萬聖節附近。你能解釋這個現象嗎?
🎃 恭喜!你剛剛創建了一個可以幫助預測南瓜派價格的模型。你可能可以對所有南瓜類型重複相同的過程,但這樣會很繁瑣。接下來,我們將學習如何在模型中考慮南瓜品種!
## 類別特徵
在理想情況下,我們希望能夠使用同一個模型來預測不同南瓜品種的價格。然而,`Variety` 列與 `Month` 等列有所不同,因為它包含非數值型的值。這類列被稱為**類別型**。
[![初學者的機器學習 - 使用線性回歸進行類別特徵預測](https://img.youtube.com/vi/DYGliioIAE0/0.jpg)](https://youtu.be/DYGliioIAE0 "初學者的機器學習 - 使用線性回歸進行類別特徵預測")
> 🎥 點擊上方圖片觀看有關使用類別特徵的簡短視頻概述。
以下是品種與平均價格的關係:
<img alt="按品種劃分的平均價格" src="../../../../translated_images/zh-MO/price-by-variety.744a2f9925d9bcb4.webp" width="50%" />
為了考慮品種,我們首先需要將其轉換為數值形式,或者**編碼**。有幾種方法可以做到:
* 簡單的**數值編碼**會建立一個不同品種的表,然後用表中的索引替換品種名稱。這對線性回歸來說不是最好的方法,因為線性回歸會將索引的實際數值加到結果中,並乘以某個係數。在我們的案例中,索引號與價格之間的關係顯然是非線性的,即使我們確保索引按某種特定方式排序。
* **獨熱編碼**會用 4 個不同的列替換 `Variety` 列,每個列對應一個品種。如果某行屬於某品種,該列的值為 `1`,否則為 `0`。這意味著線性回歸中會有四個係數,每個南瓜品種都有一個,負責該品種的“起始價格”(或“附加價格”)。
以下代碼展示了如何對品種進行獨熱編碼:
```python
pd.get_dummies(new_pumpkins['Variety'])
```
ID | FAIRYTALE | MINIATURE | MIXED HEIRLOOM VARIETIES | PIE TYPE
----|-----------|-----------|--------------------------|----------
70 | 0 | 0 | 0 | 1
71 | 0 | 0 | 0 | 1
... | ... | ... | ... | ...
1738 | 0 | 1 | 0 | 0
1739 | 0 | 1 | 0 | 0
1740 | 0 | 1 | 0 | 0
1741 | 0 | 1 | 0 | 0
1742 | 0 | 1 | 0 | 0
要使用獨熱編碼的品種作為輸入訓練線性回歸,我們只需要正確初始化 `X``y` 數據:
```python
X = pd.get_dummies(new_pumpkins['Variety'])
y = new_pumpkins['Price']
```
其餘代碼與我們之前用於訓練線性回歸的代碼相同。如果你嘗試一下,你會發現均方誤差差不多,但我們的決定係數大幅提高(約 77%)。為了獲得更準確的預測,我們可以考慮更多的類別特徵,以及數值特徵,例如 `Month``DayOfYear`。要獲得一個大的特徵數組,我們可以使用 `join`
```python
X = pd.get_dummies(new_pumpkins['Variety']) \
.join(new_pumpkins['Month']) \
.join(pd.get_dummies(new_pumpkins['City'])) \
.join(pd.get_dummies(new_pumpkins['Package']))
y = new_pumpkins['Price']
```
在這裡,我們還考慮了 `City``Package` 類型,這使得 MSE 降至 2.8410%),決定係數提高到 0.94
## 整合所有內容
為了創建最佳模型,我們可以使用上述示例中的結合數據(獨熱編碼的類別特徵 + 數值特徵)以及多項式回歸。以下是完整代碼供你參考:
```python
# set up training data
X = pd.get_dummies(new_pumpkins['Variety']) \
.join(new_pumpkins['Month']) \
.join(pd.get_dummies(new_pumpkins['City'])) \
.join(pd.get_dummies(new_pumpkins['Package']))
y = new_pumpkins['Price']
# make train-test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
# setup and train the pipeline
pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())
pipeline.fit(X_train,y_train)
# predict results for test data
pred = pipeline.predict(X_test)
# calculate MSE and determination
mse = np.sqrt(mean_squared_error(y_test,pred))
print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)')
score = pipeline.score(X_train,y_train)
print('Model determination: ', score)
```
這應該能讓我們的決定係數達到接近 97%MSE=2.23(約 8% 的預測誤差)。
| 模型 | MSE | 決定係數 |
|-------|-----|---------------|
| `DayOfYear` 線性 | 2.77 (17.2%) | 0.07 |
| `DayOfYear` 多項式 | 2.73 (17.0%) | 0.08 |
| `Variety` 線性 | 5.24 (19.7%) | 0.77 |
| 所有特徵線性 | 2.84 (10.5%) | 0.94 |
| 所有特徵多項式 | 2.23 (8.25%) | 0.97 |
🏆 做得好!你在一節課中創建了四個回歸模型,並將模型品質提升到 97%。在回歸的最後一部分中,你將學習如何使用邏輯回歸來確定類別。
---
## 🚀挑戰
在此筆記本中測試幾個不同的變量,看看相關性如何影響模型準確性。
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
在本課中,我們學習了線性回歸。還有其他重要的回歸類型。閱讀有關逐步回歸、嶺回歸、套索回歸和彈性網技術的資料。一門很好的課程是 [斯坦福統計學習課程](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning)。
## 作業
[建立模型](assignment.md)
---
**免責聲明**
本文件使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對於因使用此翻譯而產生的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,16 @@
# 建立回歸模型
## 說明
在本課程中,您已學習如何使用線性回歸和多項式回歸來建立模型。利用這些知識,尋找一個數據集或使用 Scikit-learn 的內建數據集來建立一個全新的模型。在您的筆記本中解釋您選擇該技術的原因,並展示模型的準確性。如果模型不準確,請解釋原因。
## 評分標準
| 評分標準 | 卓越表現 | 合格表現 | 需要改進 |
| -------- | ----------------------------------------------------------- | -------------------------- | ------------------------------- |
| | 提供完整的筆記本並附有詳細記錄的解決方案 | 解決方案不完整 | 解決方案有缺陷或存在錯誤 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -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-08-29T22:45:22+00:00",
"source_file": "2-Regression/3-Linear/notebook.ipynb",
"language_code": "mo"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

@ -0,0 +1,6 @@
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

File diff suppressed because one or more lines are too long

@ -0,0 +1,409 @@
# 使用邏輯迴歸預測分類
![邏輯迴歸與線性迴歸資訊圖表](../../../../2-Regression/4-Logistic/images/linear-vs-logistic.png)
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
> ### [本課程也提供 R 版本!](../../../../2-Regression/4-Logistic/solution/R/lesson_4.html)
## 簡介
在這堂關於迴歸的最後一課中,我們將探討邏輯迴歸,這是基本的 _經典_ 機器學習技術之一。你可以使用這種技術來發現模式並預測二元分類。例如:這顆糖果是巧克力嗎?這種疾病是否具有傳染性?這位顧客是否會選擇這個產品?
在本課程中,你將學到:
- 一個新的資料視覺化庫
- 邏輯迴歸的技術
✅ 在這個 [學習模組](https://docs.microsoft.com/learn/modules/train-evaluate-classification-models?WT.mc_id=academic-77952-leestott) 中深入了解如何使用這種類型的迴歸。
## 前置條件
在使用南瓜數據後,我們已經足夠熟悉它,並意識到有一個二元分類可以使用:`Color`。
讓我們建立一個邏輯迴歸模型,根據一些變數來預測 _某個南瓜可能的顏色_(橙色 🎃 或白色 👻)。
> 為什麼我們在迴歸課程中討論二元分類?僅僅是語言上的方便,因為邏輯迴歸實際上是 [一種分類方法](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression),儘管它是基於線性的。在下一組課程中了解其他分類數據的方法。
## 定義問題
對於我們的目的,我們將其表述為二元分類:'白色' 或 '非白色'。我們的數據集中還有一個 '條紋' 類別,但它的樣本數量很少,因此我們不會使用它。事實上,當我們從數據集中移除空值時,它就消失了。
> 🎃 有趣的事實:我們有時會稱白色南瓜為 '幽靈南瓜'。它們不容易雕刻,因此不像橙色南瓜那麼受歡迎,但它們看起來很酷!所以我們也可以將問題重新表述為:'幽靈' 或 '非幽靈'。👻
## 關於邏輯迴歸
邏輯迴歸與之前學到的線性迴歸在幾個重要方面有所不同。
[![初學者的機器學習 - 理解邏輯迴歸](https://img.youtube.com/vi/KpeCT6nEpBY/0.jpg)](https://youtu.be/KpeCT6nEpBY "初學者的機器學習 - 理解邏輯迴歸")
> 🎥 點擊上方圖片觀看邏輯迴歸的簡短視頻概述。
### 二元分類
邏輯迴歸不提供與線性迴歸相同的功能。前者提供關於二元分類("白色或非白色"的預測而後者能夠預測連續值例如根據南瓜的產地和收穫時間_價格將上漲多少_。
![南瓜分類模型](../../../../2-Regression/4-Logistic/images/pumpkin-classifier.png)
> 資訊圖表由 [Dasani Madipalli](https://twitter.com/dasani_decoded) 提供
### 其他分類
邏輯迴歸還有其他類型,包括多項式和序列:
- **多項式**:涉及多個類別,例如 "橙色、白色和條紋"。
- **序列**:涉及有序的類別,適合我們希望按邏輯順序排列結果,例如南瓜按有限數量的大小排序(迷你、小、中、大、特大、超大)。
![多項式與序列迴歸](../../../../2-Regression/4-Logistic/images/multinomial-vs-ordinal.png)
### 變數不需要相關
還記得線性迴歸在變數相關性更高時效果更好嗎?邏輯迴歸則相反——變數不需要相關性。這適用於我們的數據,因為它的相關性較弱。
### 需要大量乾淨的數據
邏輯迴歸在使用更多數據時會提供更準確的結果;我們的小型數據集並不適合這項任務,因此請記住這一點。
[![初學者的機器學習 - 邏輯迴歸的數據分析與準備](https://img.youtube.com/vi/B2X4H9vcXTs/0.jpg)](https://youtu.be/B2X4H9vcXTs "初學者的機器學習 - 邏輯迴歸的數據分析與準備")
✅ 思考哪些類型的數據適合邏輯迴歸。
## 練習 - 整理數據
首先,稍微清理一下數據,刪除空值並選擇部分列:
1. 添加以下程式碼:
```python
columns_to_select = ['City Name','Package','Variety', 'Origin','Item Size', 'Color']
pumpkins = full_pumpkins.loc[:, columns_to_select]
pumpkins.dropna(inplace=True)
```
你可以隨時查看新的數據框:
```python
pumpkins.info
```
### 視覺化 - 類別圖
到目前為止,你已經在 [起始筆記本](../../../../2-Regression/4-Logistic/notebook.ipynb) 中載入了南瓜數據,並清理了它以保留包含一些變數(包括 `Color`)的數據集。讓我們使用不同的庫 [Seaborn](https://seaborn.pydata.org/index.html) 在筆記本中視覺化數據框。Seaborn 是基於我們之前使用的 Matplotlib。
Seaborn 提供了一些很棒的方式來視覺化數據。例如,你可以在類別圖中比較每個 `Variety``Color` 的數據分佈。
1. 使用 `catplot` 函數創建這樣的圖,使用南瓜數據 `pumpkins`,並為每個南瓜類別(橙色或白色)指定顏色映射:
```python
import seaborn as sns
palette = {
'ORANGE': 'orange',
'WHITE': 'wheat',
}
sns.catplot(
data=pumpkins, y="Variety", hue="Color", kind="count",
palette=palette,
)
```
![一組視覺化數據的網格](../../../../2-Regression/4-Logistic/images/pumpkins_catplot_1.png)
通過觀察數據,你可以看到 `Color` 數據與 `Variety` 的關係。
✅ 根據這個類別圖,你能想到哪些有趣的探索?
### 數據預處理:特徵和標籤編碼
我們的南瓜數據集包含所有列的字串值。對人類來說,處理類別數據是直觀的,但對機器來說並非如此。機器學習算法更適合處理數字。因此,編碼是數據預處理階段非常重要的一步,因為它使我們能夠將類別數據轉換為數字數據,而不丟失任何信息。良好的編碼有助於建立良好的模型。
對於特徵編碼,有兩種主要的編碼器:
1. 序列編碼器:適合序列變數,即類別變數,其數據遵循邏輯順序,例如數據集中的 `Item Size` 列。它創建一個映射,使每個類別由一個數字表示,該數字是列中類別的順序。
```python
from sklearn.preprocessing import OrdinalEncoder
item_size_categories = [['sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo']]
ordinal_features = ['Item Size']
ordinal_encoder = OrdinalEncoder(categories=item_size_categories)
```
2. 類別編碼器:適合名義變數,即類別變數,其數據不遵循邏輯順序,例如數據集中除 `Item Size` 以外的所有特徵。它是一種獨熱編碼,意味著每個類別由一個二元列表示:如果南瓜屬於該 `Variety`,則編碼變數等於 1否則為 0。
```python
from sklearn.preprocessing import OneHotEncoder
categorical_features = ['City Name', 'Package', 'Variety', 'Origin']
categorical_encoder = OneHotEncoder(sparse_output=False)
```
接著,使用 `ColumnTransformer` 將多個編碼器合併為一個步驟,並應用於適當的列。
```python
from sklearn.compose import ColumnTransformer
ct = ColumnTransformer(transformers=[
('ord', ordinal_encoder, ordinal_features),
('cat', categorical_encoder, categorical_features)
])
ct.set_output(transform='pandas')
encoded_features = ct.fit_transform(pumpkins)
```
另一方面,對於標籤編碼,我們使用 scikit-learn 的 `LabelEncoder` 類,這是一個工具類,用於將標籤標準化,使其僅包含 0 到 n_classes-1此處為 0 和 1之間的值。
```python
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
encoded_label = label_encoder.fit_transform(pumpkins['Color'])
```
一旦我們編碼了特徵和標籤,就可以將它們合併到新的數據框 `encoded_pumpkins` 中。
```python
encoded_pumpkins = encoded_features.assign(Color=encoded_label)
```
✅ 使用序列編碼器處理 `Item Size` 列有哪些優勢?
### 分析變數之間的關係
現在我們已經對數據進行了預處理,可以分析特徵和標籤之間的關係,以了解模型在給定特徵的情況下預測標籤的能力。
進行這類分析的最佳方式是繪製數據。我們將再次使用 Seaborn 的 `catplot` 函數,視覺化 `Item Size`、`Variety` 和 `Color` 之間的關係。為了更好地繪製數據,我們將使用編碼後的 `Item Size` 列和未編碼的 `Variety` 列。
```python
palette = {
'ORANGE': 'orange',
'WHITE': 'wheat',
}
pumpkins['Item Size'] = encoded_pumpkins['ord__Item Size']
g = sns.catplot(
data=pumpkins,
x="Item Size", y="Color", row='Variety',
kind="box", orient="h",
sharex=False, margin_titles=True,
height=1.8, aspect=4, palette=palette,
)
g.set(xlabel="Item Size", ylabel="").set(xlim=(0,6))
g.set_titles(row_template="{row_name}")
```
![視覺化數據的類別圖](../../../../2-Regression/4-Logistic/images/pumpkins_catplot_2.png)
### 使用 swarm plot
由於 `Color` 是二元分類(白色或非白色),它需要一種 [專門的視覺化方法](https://seaborn.pydata.org/tutorial/categorical.html?highlight=bar)。還有其他方法可以視覺化此分類與其他變數的關係。
你可以使用 Seaborn 圖表並排視覺化變數。
1. 嘗試使用 'swarm' 圖來顯示值的分佈:
```python
palette = {
0: 'orange',
1: 'wheat'
}
sns.swarmplot(x="Color", y="ord__Item Size", data=encoded_pumpkins, palette=palette)
```
![視覺化數據的 swarm 圖](../../../../2-Regression/4-Logistic/images/swarm_2.png)
**注意**:上述程式碼可能會產生警告,因為 Seaborn 無法在 swarm 圖中表示如此多的數據點。一種可能的解決方案是使用 'size' 參數減小標記的大小,但請注意這會影響圖表的可讀性。
> **🧮 數學解析**
>
> 邏輯迴歸依賴於 '最大似然' 的概念,使用 [S 型函數](https://wikipedia.org/wiki/Sigmoid_function)。在圖表上S 型函數看起來像一個 'S' 形。它將一個值映射到 0 和 1 之間的某個位置。其曲線也被稱為 '邏輯曲線'。公式如下:
>
> ![邏輯函數](../../../../2-Regression/4-Logistic/images/sigmoid.png)
>
> 其中 S 型函數的中點位於 x 的 0 點L 是曲線的最大值k 是曲線的陡度。如果函數的結果大於 0.5,該標籤將被分配為二元選擇中的 '1' 類別;否則,將被分配為 '0' 類別。
## 建立模型
在 Scikit-learn 中建立二元分類模型的過程相當簡單。
[![初學者的機器學習 - 使用邏輯迴歸進行數據分類](https://img.youtube.com/vi/MmZS2otPrQ8/0.jpg)](https://youtu.be/MmZS2otPrQ8 "初學者的機器學習 - 使用邏輯迴歸進行數據分類")
> 🎥 點擊上方圖片觀看建立線性迴歸模型的簡短視頻概述。
1. 選擇你想在分類模型中使用的變數,並使用 `train_test_split()` 分割訓練集和測試集:
```python
from sklearn.model_selection import train_test_split
X = encoded_pumpkins[encoded_pumpkins.columns.difference(['Color'])]
y = encoded_pumpkins['Color']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
```
2. 現在你可以通過使用訓練數據調用 `fit()` 來訓練模型,並打印出結果:
```python
from sklearn.metrics import f1_score, classification_report
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
predictions = model.predict(X_test)
print(classification_report(y_test, predictions))
print('Predicted labels: ', predictions)
print('F1-score: ', f1_score(y_test, predictions))
```
查看模型的得分板。考慮到你只有大約 1000 行數據,結果還不錯:
```output
precision recall f1-score support
0 0.94 0.98 0.96 166
1 0.85 0.67 0.75 33
accuracy 0.92 199
macro avg 0.89 0.82 0.85 199
weighted avg 0.92 0.92 0.92 199
Predicted labels: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0
0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 1 0 0 0 0 0 0 0 0 1 1]
F1-score: 0.7457627118644068
```
## 使用混淆矩陣更好地理解模型
雖然你可以通過打印上述項目獲得得分板報告 [術語](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.classification_report.html?highlight=classification_report#sklearn.metrics.classification_report),但使用 [混淆矩陣](https://scikit-learn.org/stable/modules/model_evaluation.html#confusion-matrix) 可能更容易理解模型的表現。
> 🎓 '[混淆矩陣](https://wikipedia.org/wiki/Confusion_matrix)'(或 '錯誤矩陣')是一個表格,用於表達模型的真實與錯誤的正例和負例,從而評估預測的準確性。
1. 要使用混淆矩陣,調用 `confusion_matrix()`
```python
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, predictions)
```
查看模型的混淆矩陣:
```output
array([[162, 4],
[ 11, 22]])
```
在 Scikit-learn 中,混淆矩陣的行(軸 0是實際標籤軸 1是預測標籤。
| | 0 | 1 |
| :---: | :---: | :---: |
| 0 | TN | FP |
| 1 | FN | TP |
這裡發生了什麼?假設模型被要求在兩個二元分類中對南瓜進行分類,分類為 '白色' 和 '非白色'。
- 如果模型預測南瓜為非白色,且實際屬於 '非白色' 類別,我們稱之為真負例,顯示在左上角。
- 如果模型預測南瓜為白色,且實際屬於 '非白色' 類別,我們稱之為假負例,顯示在左下角。
- 如果模型預測南瓜為非白色,且實際屬於 '白色' 類別,我們稱之為假正例,顯示在右上角。
- 如果模型預測南瓜為白色,且實際屬於 '白色' 類別,我們稱之為真正例,顯示在右下角。
如你所料,真正例和真負例的數量越多,假正例和假負例的數量越少,模型的表現就越好。
混淆矩陣如何與精確度和召回率相關?記住,上面列出的分類報告顯示精確度 (0.85) 和召回率 (0.67)。
精確度 = tp / (tp + fp) = 22 / (22 + 4) = 0.8461538461538461
召回率 = tp / (tp + fn) = 22 / (22 + 11) = 0.6666666666666666
✅ 問:根據混淆矩陣,模型表現如何?
答:還不錯;有相當多的真負例,但也有一些假負例。
讓我們再次回顧之前提到的術語,並結合混淆矩陣中 TP/TN 和 FP/FN 的映射來理解:
🎓 精確度TP/(TP + FP)
檢索到的實例中,相關實例的比例(例如,哪些標籤被正確標記)。
🎓 召回率TP/(TP + FN)
被檢索到的相關實例比例,無論是否被正確標記。
🎓 f1-score(2 * 精確度 * 召回率)/(精確度 + 召回率)
精確度和召回率的加權平均值,最佳值為 1最差值為 0。
🎓 支援度:檢索到的每個標籤的出現次數。
🎓 準確率:(TP + TN)/(TP + TN + FP + FN)
樣本中標籤被正確預測的百分比。
🎓 宏平均:每個標籤的未加權平均值計算,不考慮標籤的不平衡。
🎓 加權平均:每個標籤的平均值計算,根據支援度(每個標籤的真實實例數量)進行加權。
✅ 你能想到如果想減少假負例,應該關注哪個指標嗎?
## 可視化此模型的 ROC 曲線
[![初學者機器學習 - 使用 ROC 曲線分析邏輯回歸性能](https://img.youtube.com/vi/GApO575jTA0/0.jpg)](https://youtu.be/GApO575jTA0 "初學者機器學習 - 使用 ROC 曲線分析邏輯回歸性能")
> 🎥 點擊上方圖片觀看 ROC 曲線的簡短視頻概述
讓我們進行另一個可視化,來查看所謂的 "ROC" 曲線:
```python
from sklearn.metrics import roc_curve, roc_auc_score
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
y_scores = model.predict_proba(X_test)
fpr, tpr, thresholds = roc_curve(y_test, y_scores[:,1])
fig = plt.figure(figsize=(6, 6))
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr, tpr)
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.show()
```
使用 Matplotlib 繪製模型的 [接收者操作特徵曲線](https://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html?highlight=roc) 或 ROC。ROC 曲線通常用於查看分類器的輸出,從真陽性和假陽性的角度分析。"ROC 曲線通常在 Y 軸上顯示真陽性率,在 X 軸上顯示假陽性率。" 因此,曲線的陡峭程度以及曲線與中線之間的空間很重要:你希望曲線快速向上並超過中線。在我們的例子中,起初有一些假陽性,然後曲線正確地向上並超過中線:
![ROC](../../../../2-Regression/4-Logistic/images/ROC_2.png)
最後,使用 Scikit-learn 的 [`roc_auc_score` API](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_auc_score.html?highlight=roc_auc#sklearn.metrics.roc_auc_score) 計算實際的 "曲線下面積" (AUC)
```python
auc = roc_auc_score(y_test,y_scores[:,1])
print(auc)
```
結果是 `0.9749908725812341`。由於 AUC 的範圍是 0 到 1你希望分數越高越好因為一個完全正確預測的模型的 AUC 為 1在這個例子中模型表現 _相當不錯_
在未來的分類課程中,你將學習如何迭代以改進模型的分數。但目前,恭喜你!你已完成這些回歸課程!
---
## 🚀挑戰
關於邏輯回歸還有很多值得探索的內容!但最好的學習方式是進行實驗。找到一個適合此類分析的數據集並用它建立模型。你學到了什麼?提示:試試 [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) 上有趣的數據集。
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
閱讀 [這篇來自斯坦福的論文](https://web.stanford.edu/~jurafsky/slp3/5.pdf) 的前幾頁,了解邏輯回歸的一些實際用途。思考哪些任務更適合我們到目前為止所學的不同回歸類型。哪種方法效果最好?
## 作業
[重試此回歸](assignment.md)
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -0,0 +1,16 @@
# 重試一些回歸
## 說明
在課程中,你使用了南瓜數據的一個子集。現在,回到原始數據,嘗試使用所有清理和標準化後的數據,來建立一個邏輯回歸模型。
## 評分標準
| 標準 | 卓越表現 | 合格表現 | 需要改進 |
| -------- | ----------------------------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------- |
| | 提交了一個包含詳細解釋且表現良好的模型的筆記本 | 提交了一個包含最低限度表現的模型的筆記本 | 提交了一個表現不佳的模型的筆記本或未提交 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -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-08-29T22:57:39+00:00",
"source_file": "2-Regression/4-Logistic/notebook.ipynb",
"language_code": "mo"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

@ -0,0 +1,6 @@
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,685 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 建立邏輯迴歸模型 - 第四課\n",
"\n",
"![邏輯迴歸與線性迴歸資訊圖表](../../../../../../translated_images/zh-MO/linear-vs-logistic.ba180bf95e7ee667.webp)\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",
"在我們的情境中,我們將問題表述為二元分類:「白色」或「非白色」。在我們的數據集中還有一個「條紋」類別,但由於該類別的樣本數量很少,我們不會使用它。事實上,一旦我們從數據集中移除空值,這個類別就會消失。\n",
"\n",
"> 🎃 有趣的小知識,我們有時會稱白色南瓜為「幽靈南瓜」。它們不太容易雕刻,因此不像橙色南瓜那麼受歡迎,但它們看起來很酷!所以我們也可以將問題重新表述為:「幽靈」或「非幽靈」。👻\n",
"\n",
"## **關於邏輯回歸**\n",
"\n",
"邏輯回歸與之前學過的線性回歸有幾個重要的不同之處。\n",
"\n",
"#### **二元分類**\n",
"\n",
"邏輯回歸不提供與線性回歸相同的功能。前者提供對「二元類別」(例如「橙色或非橙色」)的預測,而後者則能夠預測「連續值」,例如根據南瓜的來源和收穫時間,*價格會上漲多少*。\n",
"\n",
"![Dasani Madipalli 的資訊圖表](../../../../../../translated_images/zh-MO/pumpkin-classifier.562771f104ad5436.webp)\n",
"\n",
"### 其他分類方式\n",
"\n",
"邏輯回歸還有其他類型,包括多項式和序列型:\n",
"\n",
"- **多項式**,涉及多於一個類別,例如「橙色、白色和條紋」。\n",
"\n",
"- **序列型**,涉及有序的類別,適合我們希望按邏輯順序排列結果的情境,例如南瓜按有限的尺寸(迷你、小、中、大、特大、超大)排序。\n",
"\n",
"![多項式 vs 序列型回歸](../../../../../../translated_images/zh-MO/multinomial-vs-ordinal.36701b4850e37d86.webp)\n",
"\n",
"#### **變數不需要相關**\n",
"\n",
"還記得線性回歸在變數相關性更高時效果更好嗎?邏輯回歸正好相反——變數不需要相關性。這對於我們的數據很有幫助,因為它的相關性相對較弱。\n",
"\n",
"#### **需要大量乾淨的數據**\n",
"\n",
"如果使用更多數據,邏輯回歸會給出更準確的結果;我們的小型數據集並不是完成此任務的最佳選擇,因此請記住這一點。\n",
"\n",
"✅ 思考哪些類型的數據適合邏輯回歸\n",
"\n",
"## 練習 - 整理數據\n",
"\n",
"首先,稍微清理一下數據,刪除空值並選擇部分欄位:\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": [
"您可以隨時使用 [*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()`,而不是手動使用 prep 和 bake 來估算 recipe。我們稍後會看到這些內容。\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": [
"#### 使用群集圖\n",
"\n",
"由於 Color 是一個二元分類(白色或非白色),因此需要「一種[專門的方法](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf)來進行視覺化」。\n",
"\n",
"嘗試使用 `群集圖` 來展示 item_size 與顏色分佈的關係。\n",
"\n",
"我們將使用 [ggbeeswarm 套件](https://github.com/eclarke/ggbeeswarm),該套件提供使用 ggplot2 創建蜜蜂群集風格圖的方法。蜜蜂群集圖是一種將原本會重疊的點排列在彼此旁邊的繪圖方式。\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",
"來自 yardstick 的 [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) 函數可以計算觀察值和預測值類別的交叉統計表。\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",
"- 如果模型預測南瓜是白色,且實際上屬於「白色」類別,我們稱之為 `真正例`,顯示在左上角的數字。\n",
"\n",
"- 如果模型預測南瓜是非白色,但實際上屬於「白色」類別,我們稱之為 `假負例`,顯示在左下角的數字。\n",
"\n",
"- 如果模型預測南瓜是白色,但實際上屬於「非白色」類別,我們稱之為 `假正例`,顯示在右上角的數字。\n",
"\n",
"- 如果模型預測南瓜是非白色,且實際上屬於「非白色」類別,我們稱之為 `真負例`,顯示在右下角的數字。\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 曲線通常在 Y 軸上顯示「真陽性率」/敏感度,在 X 軸上顯示「假陽性率」/1-特異性。因此,曲線的陡峭程度以及曲線與中線之間的距離非常重要:理想的曲線應該快速向上並超越中線。在我們的例子中,起初會有一些假陽性,接著曲線正確地向上並超越中線。\n",
"\n",
"最後,我們可以使用 `yardstick::roc_auc()` 來計算實際的曲線下面積AUC。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",
"閱讀 [這篇來自 Stanford 的論文](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-08-29T23:02:49+00:00",
"source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb",
"language_code": "mo"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,45 @@
# 機器學習中的回歸模型
## 區域主題:北美南瓜價格的回歸模型 🎃
在北美,南瓜常被雕刻成恐怖的臉孔以慶祝萬聖節。讓我們一起探索這些迷人的蔬菜吧!
![jack-o-lanterns](../../../translated_images/zh-MO/jack-o-lanterns.181c661a9212457d.webp)
> 照片由 <a href="https://unsplash.com/@teutschmann?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Beth Teutschmann</a> 提供,來自 <a href="https://unsplash.com/s/photos/jack-o-lanterns?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
## 你將學到什麼
[![回歸介紹](https://img.youtube.com/vi/5QnJtDad4iQ/0.jpg)](https://youtu.be/5QnJtDad4iQ "回歸介紹影片 - 點擊觀看!")
> 🎥 點擊上方圖片觀看本課程的快速介紹影片
本章節的課程涵蓋機器學習中回歸的類型。回歸模型可以幫助確定變數之間的_關係_。這類模型可以預測像是長度、溫度或年齡等數值從而在分析數據點時揭示變數之間的關聯。
在這系列課程中,你將了解線性回歸和邏輯回歸的差異,以及在什麼情況下應選擇其中一種。
[![機器學習入門 - 回歸模型介紹](https://img.youtube.com/vi/XA3OaoW86R8/0.jpg)](https://youtu.be/XA3OaoW86R8 "機器學習入門 - 回歸模型介紹")
> 🎥 點擊上方圖片觀看回歸模型的簡短介紹影片。
在這組課程中,你將準備開始機器學習任務,包括配置 Visual Studio Code 以管理筆記本,這是數據科學家常用的環境。你將了解 Scikit-learn一個機器學習的庫並在本章節中建立你的第一個模型重點放在回歸模型上。
> 有一些實用的低代碼工具可以幫助你學習如何使用回歸模型。試試 [Azure ML](https://docs.microsoft.com/learn/modules/create-regression-model-azure-machine-learning-designer/?WT.mc_id=academic-77952-leestott) 完成這項任務。
### 課程
1. [工具介紹](1-Tools/README.md)
2. [數據管理](2-Data/README.md)
3. [線性回歸與多項式回歸](3-Linear/README.md)
4. [邏輯回歸](4-Logistic/README.md)
---
### 致謝
"回歸模型的機器學習" 由 [Jen Looper](https://twitter.com/jenlooper) 用 ♥️ 編寫
♥️ 測驗貢獻者包括:[Muhammad Sakib Khan Inan](https://twitter.com/Sakibinan) 和 [Ornella Altunyan](https://twitter.com/ornelladotcom)
南瓜數據集由 [Kaggle 上的這個項目](https://www.kaggle.com/usda/a-year-of-pumpkin-prices) 提供建議,其數據來源於美國農業部發布的 [Specialty Crops Terminal Markets Standard Reports](https://www.marketnews.usda.gov/mnp/fv-report-config-step1?type=termPrice)。我們基於品種添加了一些關於顏色的數據點以使分佈正常化。這些數據屬於公共領域。
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,350 @@
# 建立一個使用機器學習模型的網頁應用程式
在這堂課中你將使用一個非常特別的資料集來訓練機器學習模型_過去一世紀的 UFO 目擊事件_資料來源為 NUFORC 的資料庫。
你將學到:
- 如何將訓練好的模型進行 'pickle' 處理
- 如何在 Flask 應用程式中使用該模型
我們將繼續使用筆記本來清理資料並訓練模型,但你可以更進一步,探索如何在真實世界中使用模型:例如在網頁應用程式中。
為了達成這個目標,你需要使用 Flask 建立一個網頁應用程式。
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
## 建立應用程式
有多種方法可以建立網頁應用程式來使用機器學習模型。你的網頁架構可能會影響模型的訓練方式。想像一下,你在一家公司工作,資料科學團隊已經訓練了一個模型,並希望你在應用程式中使用它。
### 考量因素
你需要問自己許多問題:
- **是網頁應用程式還是行動應用程式?** 如果你正在建立行動應用程式或需要在 IoT 環境中使用模型,你可以使用 [TensorFlow Lite](https://www.tensorflow.org/lite/) 並在 Android 或 iOS 應用程式中使用模型。
- **模型將存放在哪裡?** 是在雲端還是本地?
- **離線支援。** 應用程式是否需要離線運作?
- **使用什麼技術訓練模型?** 選擇的技術可能會影響你需要使用的工具。
- **使用 TensorFlow。** 如果你使用 TensorFlow 訓練模型,該生態系統提供了將 TensorFlow 模型轉換為可在網頁應用程式中使用的 [TensorFlow.js](https://www.tensorflow.org/js/)。
- **使用 PyTorch。** 如果你使用像 [PyTorch](https://pytorch.org/) 這樣的庫來建立模型,你可以選擇將其導出為 [ONNX](https://onnx.ai/) (開放神經網路交換格式),以便在使用 [Onnx Runtime](https://www.onnxruntime.ai/) 的 JavaScript 網頁應用程式中使用。這個選項將在未來的課程中探索,適用於使用 Scikit-learn 訓練的模型。
- **使用 Lobe.ai 或 Azure Custom Vision。** 如果你使用像 [Lobe.ai](https://lobe.ai/) 或 [Azure Custom Vision](https://azure.microsoft.com/services/cognitive-services/custom-vision-service/?WT.mc_id=academic-77952-leestott) 這樣的機器學習 SaaS 系統來訓練模型,這類軟體提供了多平台的模型導出方式,包括建立一個專屬 API供你的線上應用程式在雲端查詢。
你也可以建立一個完整的 Flask 網頁應用程式,能夠在網頁瀏覽器中自行訓練模型。這也可以在 JavaScript 環境中使用 TensorFlow.js 完成。
對於我們的目的,由於我們一直在使用基於 Python 的筆記本,讓我們來探索如何將訓練好的模型從筆記本導出為 Python 建立的網頁應用程式可讀的格式。
## 工具
完成這項任務你需要兩個工具Flask 和 Pickle這兩者都在 Python 上運行。
✅ [Flask](https://palletsprojects.com/p/flask/) 是什麼由其創建者定義為「微框架」Flask 提供了使用 Python 和模板引擎建立網頁的基本功能。看看 [這個學習模組](https://docs.microsoft.com/learn/modules/python-flask-build-ai-web-app?WT.mc_id=academic-77952-leestott) 來練習使用 Flask。
✅ [Pickle](https://docs.python.org/3/library/pickle.html) 是什麼Pickle 🥒 是一個 Python 模組,用於序列化和反序列化 Python 物件結構。當你對模型進行 'pickle' 處理時你會將其結構序列化或扁平化以便在網頁上使用。注意Pickle 本身並不安全因此如果被要求反序列化文件時要小心。Pickle 文件的後綴為 `.pkl`
## 練習 - 清理資料
在這堂課中,你將使用來自 [NUFORC](https://nuforc.org) (全國 UFO 報告中心) 的 80,000 次 UFO 目擊事件資料。這些資料包含一些有趣的 UFO 目擊描述,例如:
- **長描述範例。**「一束光照在夜晚的草地上,一名男子從光束中走出,跑向德州儀器的停車場。」
- **短描述範例。**「燈光追著我們。」
[ufos.csv](../../../../3-Web-App/1-Web-App/data/ufos.csv) 試算表包含目擊事件發生的 `city`、`state` 和 `country`,物體的 `shape` 以及其 `latitude``longitude`
在這堂課提供的空白 [notebook](../../../../3-Web-App/1-Web-App/notebook.ipynb) 中:
1. 像之前的課程一樣,匯入 `pandas`、`matplotlib` 和 `numpy`,並匯入 UFO 試算表。你可以查看一個樣本資料集:
```python
import pandas as pd
import numpy as np
ufos = pd.read_csv('./data/ufos.csv')
ufos.head()
```
1. 將 UFO 資料轉換為一個小型資料框,並重新命名欄位。檢查 `Country` 欄位中的唯一值。
```python
ufos = pd.DataFrame({'Seconds': ufos['duration (seconds)'], 'Country': ufos['country'],'Latitude': ufos['latitude'],'Longitude': ufos['longitude']})
ufos.Country.unique()
```
1. 現在,你可以通過刪除任何空值並僅匯入 1-60 秒之間的目擊事件來減少需要處理的資料量:
```python
ufos.dropna(inplace=True)
ufos = ufos[(ufos['Seconds'] >= 1) & (ufos['Seconds'] <= 60)]
ufos.info()
```
1. 匯入 Scikit-learn 的 `LabelEncoder` 庫,將國家的文字值轉換為數字:
✅ LabelEncoder 按字母順序編碼資料
```python
from sklearn.preprocessing import LabelEncoder
ufos['Country'] = LabelEncoder().fit_transform(ufos['Country'])
ufos.head()
```
你的資料應該看起來像這樣:
```output
Seconds Country Latitude Longitude
2 20.0 3 53.200000 -2.916667
3 20.0 4 28.978333 -96.645833
14 30.0 4 35.823889 -80.253611
23 60.0 4 45.582778 -122.352222
24 3.0 3 51.783333 -0.783333
```
## 練習 - 建立模型
現在你可以準備通過將資料分為訓練組和測試組來訓練模型。
1. 選擇三個特徵作為你的 X 向量y 向量將是 `Country`。你希望能夠輸入 `Seconds`、`Latitude` 和 `Longitude`,並返回一個國家代碼。
```python
from sklearn.model_selection import train_test_split
Selected_features = ['Seconds','Latitude','Longitude']
X = ufos[Selected_features]
y = ufos['Country']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
```
1. 使用邏輯回歸訓練你的模型:
```python
from sklearn.metrics import accuracy_score, classification_report
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
predictions = model.predict(X_test)
print(classification_report(y_test, predictions))
print('Predicted labels: ', predictions)
print('Accuracy: ', accuracy_score(y_test, predictions))
```
準確率相當不錯 **(約 95%)**,這並不意外,因為 `Country``Latitude/Longitude` 之間有相關性。
你建立的模型並不算非常創新,因為你應該能夠從 `Latitude``Longitude` 推斷出 `Country`,但這是一個很好的練習,嘗試從清理過的原始資料中訓練模型,導出模型,然後在網頁應用程式中使用它。
## 練習 - 將模型進行 'pickle' 處理
現在,是時候對你的模型進行 _pickle_ 處理了!你可以用幾行程式碼完成這個操作。一旦完成 _pickle_,載入你的 pickled 模型並用一個包含秒數、緯度和經度的樣本資料陣列進行測試。
```python
import pickle
model_filename = 'ufo-model.pkl'
pickle.dump(model, open(model_filename,'wb'))
model = pickle.load(open('ufo-model.pkl','rb'))
print(model.predict([[50,44,-12]]))
```
模型返回 **'3'**,這是英國的國家代碼。太酷了!👽
## 練習 - 建立 Flask 應用程式
現在你可以建立一個 Flask 應用程式來調用你的模型並以更具視覺吸引力的方式返回類似結果。
1. 首先,在 _notebook.ipynb_ 文件旁邊建立一個名為 **web-app** 的資料夾,該資料夾中存放你的 _ufo-model.pkl_ 文件。
1. 在該資料夾中再建立三個資料夾:**static**,其中包含一個 **css** 資料夾,以及 **templates**。你現在應該有以下文件和目錄:
```output
web-app/
static/
css/
templates/
notebook.ipynb
ufo-model.pkl
```
✅ 參考解決方案資料夾以查看完成的應用程式
1. 在 _web-app_ 資料夾中建立第一個文件 **requirements.txt**。像 JavaScript 應用程式中的 _package.json_ 一樣,這個文件列出了應用程式所需的依賴項。在 **requirements.txt** 中添加以下內容:
```text
scikit-learn
pandas
numpy
flask
```
1. 現在,通過導航到 _web-app_ 運行此文件:
```bash
cd web-app
```
1. 在你的終端中輸入 `pip install`,以安裝 _requirements.txt_ 中列出的庫:
```bash
pip install -r requirements.txt
```
1. 現在,你可以建立另外三個文件來完成應用程式:
1. 在根目錄中建立 **app.py**
2. 在 _templates_ 資料夾中建立 **index.html**
3. 在 _static/css_ 資料夾中建立 **styles.css**
1. 在 _styles.css_ 文件中添加一些樣式:
```css
body {
width: 100%;
height: 100%;
font-family: 'Helvetica';
background: black;
color: #fff;
text-align: center;
letter-spacing: 1.4px;
font-size: 30px;
}
input {
min-width: 150px;
}
.grid {
width: 300px;
border: 1px solid #2d2d2d;
display: grid;
justify-content: center;
margin: 20px auto;
}
.box {
color: #fff;
background: #2d2d2d;
padding: 12px;
display: inline-block;
}
```
1. 接下來,建立 _index.html_ 文件:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>🛸 UFO Appearance Prediction! 👽</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<body>
<div class="grid">
<div class="box">
<p>According to the number of seconds, latitude and longitude, which country is likely to have reported seeing a UFO?</p>
<form action="{{ url_for('predict')}}" method="post">
<input type="number" name="seconds" placeholder="Seconds" required="required" min="0" max="60" />
<input type="text" name="latitude" placeholder="Latitude" required="required" />
<input type="text" name="longitude" placeholder="Longitude" required="required" />
<button type="submit" class="btn">Predict country where the UFO is seen</button>
</form>
<p>{{ prediction_text }}</p>
</div>
</div>
</body>
</html>
```
查看此文件中的模板語法。注意變數周圍的「大括號」語法,例如預測文字:`{{}}`。還有一個表單會將預測結果發送到 `/predict` 路由。
最後,你準備好建立驅動模型消耗和預測顯示的 Python 文件:
1. 在 `app.py` 中添加:
```python
import numpy as np
from flask import Flask, request, render_template
import pickle
app = Flask(__name__)
model = pickle.load(open("./ufo-model.pkl", "rb"))
@app.route("/")
def home():
return render_template("index.html")
@app.route("/predict", methods=["POST"])
def predict():
int_features = [int(x) for x in request.form.values()]
final_features = [np.array(int_features)]
prediction = model.predict(final_features)
output = prediction[0]
countries = ["Australia", "Canada", "Germany", "UK", "US"]
return render_template(
"index.html", prediction_text="Likely country: {}".format(countries[output])
)
if __name__ == "__main__":
app.run(debug=True)
```
> 💡 提示:當你在使用 Flask 運行網頁應用程式時添加 [`debug=True`](https://www.askpython.com/python-modules/flask/flask-debug-mode),你對應用程式所做的任何更改都會立即反映,而無需重新啟動伺服器。注意!不要在生產應用程式中啟用此模式。
如果你運行 `python app.py``python3 app.py` - 你的網頁伺服器就會在本地啟動,你可以填寫一個簡短的表單來獲得關於 UFO 目擊地點的答案!
在此之前,看看 `app.py` 的各部分:
1. 首先,載入依賴項並啟動應用程式。
1. 然後,導入模型。
1. 接著,在首頁路由上渲染 index.html。
`/predict` 路由上,當表單提交時會發生以下幾件事:
1. 表單變數被收集並轉換為 numpy 陣列。然後將它們發送到模型並返回預測結果。
2. 我們希望顯示的國家代碼被重新渲染為可讀的文字,並將該值發送回 index.html在模板中渲染。
以這種方式使用模型,結合 Flask 和 pickled 模型,相對簡單。最困難的部分是理解必須發送到模型的資料形狀,以獲得預測結果。這完全取決於模型的訓練方式。這個模型需要輸入三個資料點才能獲得預測結果。
在專業環境中,你可以看到訓練模型的人和在網頁或行動應用程式中使用模型的人之間良好的溝通是多麼重要。在我們的案例中,只有一個人,那就是你!
---
## 🚀 挑戰
與其在筆記本中工作並將模型導入 Flask 應用程式,你可以直接在 Flask 應用程式中訓練模型!嘗試將筆記本中的 Python 程式碼轉換為在應用程式內的 `train` 路由上訓練模型,或許是在清理資料之後。追求這種方法的優缺點是什麼?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
有許多方法可以建立網頁應用程式來使用機器學習模型。列出你可以使用 JavaScript 或 Python 建立網頁應用程式以利用機器學習的方式。考慮架構:模型應該保留在應用程式中還是存放在雲端?如果是後者,你會如何存取它?繪製一個應用機器學習的網頁解決方案架構模型。
## 作業
[嘗試不同的模型](assignment.md)
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,16 @@
# 嘗試不同的模型
## 說明
現在您已經使用訓練好的回歸模型建立了一個網頁應用程式,請嘗試使用之前回歸課程中的其中一個模型重新製作這個網頁應用程式。您可以保留原有的風格,或者重新設計以反映南瓜數據的特性。請務必更改輸入內容以符合您模型的訓練方法。
## 評分標準
| 評分標準 | 優秀 | 合格 | 需要改進 |
| ------------------------ | --------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------- |
| | 網頁應用程式運行正常,並成功部署到雲端 | 網頁應用程式存在缺陷或出現意外結果 | 網頁應用程式無法正常運行 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -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-08-29T23:40:39+00:00",
"source_file": "3-Web-App/1-Web-App/solution/notebook.ipynb",
"language_code": "mo"
}
},
"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,26 @@
# 建立一個使用您的機器學習模型的網頁應用程式
在本課程的這一部分,您將學習一個應用機器學習的主題:如何將您的 Scikit-learn 模型保存為一個文件,並在網頁應用程式中使用它進行預測。一旦模型保存完成,您將學習如何在使用 Flask 建立的網頁應用程式中使用它。首先,您將使用一些關於 UFO 目擊事件的數據來建立模型!接著,您將建立一個網頁應用程式,允許您輸入秒數、緯度和經度值,來預測哪個國家報告了看到 UFO。
![UFO 停車場](../../../translated_images/zh-MO/ufo.9e787f5161da9d4d.webp)
照片由 <a href="https://unsplash.com/@mdherren?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Michael Herren</a> 提供,來自 <a href="https://unsplash.com/s/photos/ufo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
## 課程
1. [建立網頁應用程式](1-Web-App/README.md)
## 致謝
"建立網頁應用程式" 由 [Jen Looper](https://twitter.com/jenlooper) 用 ♥️ 撰寫。
♥️ 測驗由 Rohan Raj 撰寫。
數據集來源於 [Kaggle](https://www.kaggle.com/NUFORC/ufo-sightings)。
網頁應用程式架構部分參考了 [這篇文章](https://towardsdatascience.com/how-to-easily-deploy-machine-learning-models-using-flask-b95af8fe34d4) 和 [這個倉庫](https://github.com/abhinavsagar/machine-learning-deployment),由 Abhinav Sagar 提供。
---
**免責聲明**
本文件使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對於因使用本翻譯而引起的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,304 @@
# 分類簡介
在這四節課中您將探索經典機器學習的一個核心主題——_分類_。我們將使用一個關於亞洲和印度美食的數據集逐步了解各種分類算法的應用。希望您準備好大快朵頤了
![只需一點點!](../../../../4-Classification/1-Introduction/images/pinch.png)
> 在這些課程中慶祝泛亞洲美食!圖片由 [Jen Looper](https://twitter.com/jenlooper) 提供
分類是一種[監督式學習](https://wikipedia.org/wiki/Supervised_learning)與回歸技術有許多相似之處。如果機器學習的核心是通過使用數據集來預測事物的值或名稱那麼分類通常分為兩類_二元分類_和_多類分類_。
[![分類簡介](https://img.youtube.com/vi/eg8DJYwdMyg/0.jpg)](https://youtu.be/eg8DJYwdMyg "分類簡介")
> 🎥 點擊上方圖片觀看影片:麻省理工學院的 John Guttag 介紹分類
請記住:
- **線性回歸** 幫助您預測變量之間的關係並準確預測新數據點在該線性關係中的位置。例如您可以預測_南瓜在九月和十二月的價格_。
- **邏輯回歸** 幫助您發現「二元類別」在這個價格範圍內_這個南瓜是橙色還是非橙色_
分類使用各種算法來確定數據點的標籤或類別。讓我們使用這些美食數據,看看是否可以通過觀察一組食材來確定其美食的來源。
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
> ### [本課程提供 R 版本!](../../../../4-Classification/1-Introduction/solution/R/lesson_10.html)
### 簡介
分類是機器學習研究者和數據科學家的一項基本活動。從基本的二元值分類(「這封電子郵件是垃圾郵件還是非垃圾郵件?」),到使用計算機視覺進行複雜的圖像分類和分割,能夠將數據分成類別並提出問題始終是非常有用的。
用更科學的方式來描述這個過程,您的分類方法會創建一個預測模型,使您能夠將輸入變量與輸出變量之間的關係進行映射。
![二元分類與多類分類](../../../../4-Classification/1-Introduction/images/binary-multiclass.png)
> 二元分類與多類分類問題,供分類算法處理。信息圖由 [Jen Looper](https://twitter.com/jenlooper) 提供
在開始清理數據、可視化數據並為機器學習任務做好準備之前,讓我們先了解一下機器學習分類數據的各種方式。
分類源於[統計學](https://wikipedia.org/wiki/Statistical_classification),使用經典機器學習技術,通過特徵(例如 `smoker`、`weight` 和 `age`來確定_患某種疾病的可能性_。作為一種類似於您之前進行的回歸練習的監督式學習技術您的數據是有標籤的機器學習算法使用這些標籤來分類和預測數據集的類別或「特徵」並將它們分配到某個組或結果中。
✅ 花點時間想像一個關於美食的數據集。一個多類模型能回答什麼問題?一個二元模型能回答什麼問題?如果您想確定某種美食是否可能使用葫蘆巴葉呢?如果您想知道,假如收到一袋包含八角、洋薊、花椰菜和辣根的雜貨,您是否能做出一道典型的印度菜?
[![瘋狂的神秘食材籃](https://img.youtube.com/vi/GuTeDbaNoEU/0.jpg)](https://youtu.be/GuTeDbaNoEU "瘋狂的神秘食材籃")
> 🎥 點擊上方圖片觀看影片。節目《Chopped》的整個主題是「神秘食材籃」廚師必須用隨機選擇的食材做出一道菜。機器學習模型肯定能幫上忙
## 你好,分類器
我們想要問這個美食數據集的問題實際上是一個**多類問題**,因為我們有多個潛在的國家美食可以選擇。給定一批食材,這些食材會屬於哪一類?
Scikit-learn 提供了多種不同的算法來分類數據,具體取決於您想要解決的問題類型。在接下來的兩節課中,您將學習其中幾種算法。
## 練習 - 清理並平衡數據
在開始這個項目之前,第一項任務是清理並**平衡**您的數據,以獲得更好的結果。從此文件夾根目錄中的空白 _notebook.ipynb_ 文件開始。
首先需要安裝 [imblearn](https://imbalanced-learn.org/stable/)。這是一個 Scikit-learn 套件,可以幫助您更好地平衡數據(您將在稍後了解更多相關任務)。
1. 安裝 `imblearn`,運行 `pip install`,如下所示:
```python
pip install imblearn
```
1. 導入所需的包以導入數據並進行可視化,還需從 `imblearn` 中導入 `SMOTE`
```python
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from imblearn.over_sampling import SMOTE
```
現在您已準備好接下來導入數據。
1. 下一步是導入數據:
```python
df = pd.read_csv('../data/cuisines.csv')
```
使用 `read_csv()` 會讀取 csv 文件 _cusines.csv_ 的內容並將其放入變量 `df` 中。
1. 檢查數據的形狀:
```python
df.head()
```
前五行看起來像這樣:
```output
| | Unnamed: 0 | cuisine | almond | angelica | anise | anise_seed | apple | apple_brandy | apricot | armagnac | ... | whiskey | white_bread | white_wine | whole_grain_wheat_flour | wine | wood | yam | yeast | yogurt | zucchini |
| --- | ---------- | ------- | ------ | -------- | ----- | ---------- | ----- | ------------ | ------- | -------- | --- | ------- | ----------- | ---------- | ----------------------- | ---- | ---- | --- | ----- | ------ | -------- |
| 0 | 65 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 66 | indian | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 67 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3 | 68 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4 | 69 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
```
1. 通過調用 `info()` 獲取有關此數據的信息:
```python
df.info()
```
您的輸出類似於:
```output
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2448 entries, 0 to 2447
Columns: 385 entries, Unnamed: 0 to zucchini
dtypes: int64(384), object(1)
memory usage: 7.2+ MB
```
## 練習 - 了解美食
現在工作開始變得更有趣了。讓我們探索每種美食的數據分佈。
1. 通過調用 `barh()` 將數據繪製為條形圖:
```python
df.cuisine.value_counts().plot.barh()
```
![美食數據分佈](../../../../4-Classification/1-Introduction/images/cuisine-dist.png)
美食的數量是有限的,但數據分佈是不均勻的。您可以修正這一點!在修正之前,先多探索一下。
1. 找出每種美食的數據量並打印出來:
```python
thai_df = df[(df.cuisine == "thai")]
japanese_df = df[(df.cuisine == "japanese")]
chinese_df = df[(df.cuisine == "chinese")]
indian_df = df[(df.cuisine == "indian")]
korean_df = df[(df.cuisine == "korean")]
print(f'thai df: {thai_df.shape}')
print(f'japanese df: {japanese_df.shape}')
print(f'chinese df: {chinese_df.shape}')
print(f'indian df: {indian_df.shape}')
print(f'korean df: {korean_df.shape}')
```
輸出如下所示:
```output
thai df: (289, 385)
japanese df: (320, 385)
chinese df: (442, 385)
indian df: (598, 385)
korean df: (799, 385)
```
## 探索食材
現在您可以更深入地挖掘數據,了解每種美食的典型食材。您應該清理掉那些在美食之間造成混淆的重複數據,因此讓我們了解這個問題。
1. 在 Python 中創建一個名為 `create_ingredient()` 的函數,用於創建食材數據框。此函數將首先刪除一個無用的列,並根據食材的數量進行排序:
```python
def create_ingredient_df(df):
ingredient_df = df.T.drop(['cuisine','Unnamed: 0']).sum(axis=1).to_frame('value')
ingredient_df = ingredient_df[(ingredient_df.T != 0).any()]
ingredient_df = ingredient_df.sort_values(by='value', ascending=False,
inplace=False)
return ingredient_df
```
現在您可以使用該函數了解每種美食中最受歡迎的前十種食材。
1. 調用 `create_ingredient()` 並通過調用 `barh()` 繪製圖表:
```python
thai_ingredient_df = create_ingredient_df(thai_df)
thai_ingredient_df.head(10).plot.barh()
```
![泰國](../../../../4-Classification/1-Introduction/images/thai.png)
1. 對日本數據執行相同操作:
```python
japanese_ingredient_df = create_ingredient_df(japanese_df)
japanese_ingredient_df.head(10).plot.barh()
```
![日本](../../../../4-Classification/1-Introduction/images/japanese.png)
1. 現在是中國食材:
```python
chinese_ingredient_df = create_ingredient_df(chinese_df)
chinese_ingredient_df.head(10).plot.barh()
```
![中國](../../../../4-Classification/1-Introduction/images/chinese.png)
1. 繪製印度食材:
```python
indian_ingredient_df = create_ingredient_df(indian_df)
indian_ingredient_df.head(10).plot.barh()
```
![印度](../../../../4-Classification/1-Introduction/images/indian.png)
1. 最後,繪製韓國食材:
```python
korean_ingredient_df = create_ingredient_df(korean_df)
korean_ingredient_df.head(10).plot.barh()
```
![韓國](../../../../4-Classification/1-Introduction/images/korean.png)
1. 現在,通過調用 `drop()` 刪除那些在不同美食之間造成混淆的最常見食材:
每個人都喜歡米飯、大蒜和薑!
```python
feature_df= df.drop(['cuisine','Unnamed: 0','rice','garlic','ginger'], axis=1)
labels_df = df.cuisine #.unique()
feature_df.head()
```
## 平衡數據集
現在您已清理數據,使用 [SMOTE](https://imbalanced-learn.org/dev/references/generated/imblearn.over_sampling.SMOTE.html)——「合成少數類別過採樣技術」——來平衡數據。
1. 調用 `fit_resample()`,此策略通過插值生成新樣本。
```python
oversample = SMOTE()
transformed_feature_df, transformed_label_df = oversample.fit_resample(feature_df, labels_df)
```
通過平衡數據,您在分類時會獲得更好的結果。想想二元分類。如果您的大部分數據屬於一個類別,機器學習模型會更頻繁地預測該類別,僅僅因為該類別的數據更多。平衡數據可以消除這種不平衡。
1. 現在您可以檢查每種食材的標籤數量:
```python
print(f'new label count: {transformed_label_df.value_counts()}')
print(f'old label count: {df.cuisine.value_counts()}')
```
您的輸出如下所示:
```output
new label count: korean 799
chinese 799
indian 799
japanese 799
thai 799
Name: cuisine, dtype: int64
old label count: korean 799
indian 598
chinese 442
japanese 320
thai 289
Name: cuisine, dtype: int64
```
數據現在乾淨、平衡,而且非常美味!
1. 最後一步是將平衡後的數據,包括標籤和特徵,保存到一個新的數據框中,並導出到文件中:
```python
transformed_df = pd.concat([transformed_label_df,transformed_feature_df],axis=1, join='outer')
```
1. 您可以使用 `transformed_df.head()``transformed_df.info()` 再次查看數據。保存一份此數據以供未來課程使用:
```python
transformed_df.head()
transformed_df.info()
transformed_df.to_csv("../data/cleaned_cuisines.csv")
```
此新鮮的 CSV 現在可以在根目錄的數據文件夾中找到。
---
## 🚀挑戰
此課程包含多個有趣的數據集。翻閱 `data` 文件夾,看看是否有適合二元或多類分類的數據集?您會向這些數據集提出什麼問題?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
探索 SMOTE 的 API。它最適合用於哪些用例它解決了哪些問題
## 作業
[探索分類方法](assignment.md)
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,16 @@
# 探索分類方法
## 說明
在 [Scikit-learn 文件](https://scikit-learn.org/stable/supervised_learning.html) 中,你會發現有許多用於分類數據的方法。請在這些文件中進行一場尋寶遊戲:你的目標是尋找分類方法,並將其與本課程中的一個數據集、一個可以提出的問題,以及一種分類技術進行匹配。創建一個電子表格或在 .doc 文件中製作一個表格,並解釋該數據集如何與分類算法配合使用。
## 評分標準
| 評分標準 | 優秀 | 合格 | 有待改進 |
| -------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| | 提交了一份文件,概述了 5 種算法及其分類技術。概述解釋清楚且詳細。 | 提交了一份文件,概述了 3 種算法及其分類技術。概述解釋清楚且詳細。 | 提交了一份文件,概述了少於 3 種算法及其分類技術,且概述既不清楚也不詳細。 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -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-08-29T23:52:54+00:00",
"source_file": "4-Classification/1-Introduction/notebook.ipynb",
"language_code": "mo"
}
},
"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,6 @@
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,716 @@
{
"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-08-29T23:58:17+00:00",
"source_file": "4-Classification/1-Introduction/solution/R/lesson_10-R.ipynb",
"language_code": "mo"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "ItETB4tSFprR"
}
},
{
"cell_type": "markdown",
"source": [
"## 分類介紹:清理、準備和視覺化您的數據\n",
"\n",
"在這四節課中,您將探索經典機器學習的一個基本重點——*分類*。我們將使用關於亞洲和印度美食的數據集,逐步了解各種分類算法的應用。希望您已經準備好大快朵頤!\n",
"\n",
"<p >\n",
" <img src=\"../../images/pinch.png\"\n",
" width=\"600\"/>\n",
" <figcaption>在這些課程中一起慶祝泛亞洲美食吧!圖片由 Jen Looper 提供</figcaption>\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>分類算法處理二元與多類問題。信息圖由 Jen Looper 提供</figcaption>\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)旨在簡化和自動化探索性數據分析EDA過程及報告生成。\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` 列,並且沒有缺失值。我們還有一個離散欄位,*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/) 是一種現代化的資料框。\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",
"在 R 中建立一個名為 `create_ingredient()` 的函數,該函數會返回一個食材的數據框。這個函數將從刪除一個無用的欄位開始,並根據食材的出現次數進行排序。\n",
"\n",
"R 中函數的基本結構如下:\n",
"\n",
"`myFunction <- function(arglist){`\n",
"\n",
"**`...`**\n",
"\n",
"**`return`**`(value)`\n",
"\n",
"`}`\n",
"\n",
"可以在 [這裡](https://skirmer.github.io/presentations/functions_with_r.html#1) 找到一個簡潔的 R 函數入門介紹。\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",
"查看這個由 Allison Horst 製作的 [*藝術感滿滿* 的 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": [],
"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": [],
"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",
"既然這節課是關於料理的,我們就得將 `recipes` 放入情境中。\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",
"- 增加少數類別的觀測數:`過採樣`,例如使用 SMOTE 演算法\n",
"\n",
"- 減少多數類別的觀測數:`欠採樣`\n",
"\n",
"現在,我們來演示如何使用一個 `recipe` 處理不平衡數據集。一個 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` 資料作為參考,告訴 recipe 各變數的*角色*。例如,`cuisine` 欄位被指定為 `outcome` 角色,而其他欄位則被指定為 `predictor` 角色。\n",
"\n",
"- [`step_smote(cuisine)`](https://themis.tidymodels.org/reference/step_smote.html) 創建了一個 recipe 步驟的*規範*,該步驟使用這些案例的最近鄰,合成生成少數類別的新樣本。\n",
"\n",
"現在,如果我們想查看預處理後的資料,就需要 [**`prep()`**](https://recipes.tidymodels.org/reference/prep.html) 和 [**`bake()`**](https://recipes.tidymodels.org/reference/bake.html) 我們的 recipe。\n",
"\n",
"`prep()`:從訓練集估算所需的參數,這些參數之後可以應用到其他資料集。\n",
"\n",
"`bake()`:將已準備好的 recipe 應用到任何資料集上,並執行相關操作。\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",
"> 通常配方recipe通常用作建模的預處理器它定義了應對數據集進行哪些步驟以使其準備好進行建模。在這種情況下通常使用 `workflow()`(正如我們在之前的課程中已經看到的),而不是手動估算配方。\n",
">\n",
"> 因此,當使用 tidymodels 時,通常不需要使用 **`prep()`** 和 **`bake()`** 來處理配方,但這些函數在工具箱中是很有用的,可以用來確認配方是否按預期運作,就像我們的情況一樣。\n",
">\n",
"> 當你使用 **`new_data = NULL`** 來 **`bake()`** 一個已準備好的配方時,你會得到定義配方時提供的數據,但這些數據已經經過了預處理步驟。\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",
"- H. Wickham 和 G. Grolemund, [*R for Data Science: Visualize, Model, Transform, Tidy, and Import Data*](https://r4ds.had.co.nz/)。\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",
"<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,244 @@
# 美食分類器 1
在這節課中,您將使用上一節課保存的數據集,這是一個關於美食的平衡且乾淨的數據集。
您將使用這個數據集和多種分類器來_根據一組食材預測特定的國家美食_。在此過程中您將深入了解算法如何用於分類任務。
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
# 準備工作
假設您已完成[第一課](../1-Introduction/README.md),請確保在根目錄的 `/data` 文件夾中存在一個 _cleaned_cuisines.csv_ 文件,供這四節課使用。
## 練習 - 預測國家美食
1. 在本課的 _notebook.ipynb_ 文件夾中,導入該文件以及 Pandas 庫:
```python
import pandas as pd
cuisines_df = pd.read_csv("../data/cleaned_cuisines.csv")
cuisines_df.head()
```
數據看起來如下:
| | Unnamed: 0 | cuisine | almond | angelica | anise | anise_seed | apple | apple_brandy | apricot | armagnac | ... | whiskey | white_bread | white_wine | whole_grain_wheat_flour | wine | wood | yam | yeast | yogurt | zucchini |
| --- | ---------- | ------- | ------ | -------- | ----- | ---------- | ----- | ------------ | ------- | -------- | --- | ------- | ----------- | ---------- | ----------------------- | ---- | ---- | --- | ----- | ------ | -------- |
| 0 | 0 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 1 | indian | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 2 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3 | 3 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4 | 4 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
1. 現在,導入更多的庫:
```python
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report, precision_recall_curve
from sklearn.svm import SVC
import numpy as np
```
1. 將 X 和 y 坐標分成兩個數據框進行訓練。`cuisine` 可以作為標籤數據框:
```python
cuisines_label_df = cuisines_df['cuisine']
cuisines_label_df.head()
```
它看起來如下:
```output
0 indian
1 indian
2 indian
3 indian
4 indian
Name: cuisine, dtype: object
```
1. 使用 `drop()` 刪除 `Unnamed: 0` 列和 `cuisine` 列。將剩餘的數據保存為可訓練的特徵:
```python
cuisines_feature_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1)
cuisines_feature_df.head()
```
您的特徵看起來如下:
| | almond | angelica | anise | anise_seed | apple | apple_brandy | apricot | armagnac | artemisia | artichoke | ... | whiskey | white_bread | white_wine | whole_grain_wheat_flour | wine | wood | yam | yeast | yogurt | zucchini |
| ---: | -----: | -------: | ----: | ---------: | ----: | -----------: | ------: | -------: | --------: | --------: | ---: | ------: | ----------: | ---------: | ----------------------: | ---: | ---: | ---: | ----: | -----: | -------: |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
現在您可以開始訓練您的模型了!
## 選擇分類器
現在您的數據已清理並準備好訓練,您需要決定使用哪種算法來完成任務。
Scikit-learn 將分類歸類為監督學習,在這個類別中,您會發現許多分類方法。[種類繁多](https://scikit-learn.org/stable/supervised_learning.html),乍看之下可能令人眼花繚亂。以下方法都包含分類技術:
- 線性模型
- 支持向量機
- 隨機梯度下降
- 最近鄰
- 高斯過程
- 決策樹
- 集成方法(投票分類器)
- 多類和多輸出算法(多類多標籤分類,多類多輸出分類)
> 您也可以使用[神經網絡進行分類](https://scikit-learn.org/stable/modules/neural_networks_supervised.html#classification),但這超出了本課的範圍。
### 選擇哪個分類器?
那麼應該選擇哪個分類器呢通常通過嘗試多種分類器並尋找良好的結果是一種測試方法。Scikit-learn 提供了一個[並排比較](https://scikit-learn.org/stable/auto_examples/classification/plot_classifier_comparison.html),在創建的數據集上比較 KNeighbors、SVC 兩種方式、GaussianProcessClassifier、DecisionTreeClassifier、RandomForestClassifier、MLPClassifier、AdaBoostClassifier、GaussianNB 和 QuadraticDiscrinationAnalysis並以可視化方式展示結果
![分類器比較](../../../../4-Classification/2-Classifiers-1/images/comparison.png)
> 圖片來自 Scikit-learn 的文檔
> AutoML 可以輕鬆解決這個問題,通過在雲端運行這些比較,幫助您選擇最適合您數據的算法。試試看[這裡](https://docs.microsoft.com/learn/modules/automate-model-selection-with-azure-automl/?WT.mc_id=academic-77952-leestott)
### 更好的方法
比盲目猜測更好的方法是遵循這份可下載的[機器學習速查表](https://docs.microsoft.com/azure/machine-learning/algorithm-cheat-sheet?WT.mc_id=academic-77952-leestott)。在這裡,我們發現針對我們的多類問題,我們有一些選擇:
![多類問題速查表](../../../../4-Classification/2-Classifiers-1/images/cheatsheet.png)
> 微軟算法速查表的一部分,詳細介紹了多類分類選項
✅ 下載這份速查表,打印出來,掛在牆上!
### 推理
讓我們看看是否可以根據我們的限制推理出不同的方法:
- **神經網絡太重**。考慮到我們的數據集雖然乾淨但規模較小,以及我們通過筆記本本地運行訓練的事實,神經網絡對於這項任務來說太過繁重。
- **不使用二類分類器**。我們不使用二類分類器因此排除了一對多one-vs-all
- **決策樹或邏輯回歸可能有效**。決策樹可能有效,或者多類數據的邏輯回歸也可能有效。
- **多類增強決策樹解決不同問題**。多類增強決策樹最適合非參數任務,例如設計排名的任務,因此對我們來說並不適用。
### 使用 Scikit-learn
我們將使用 Scikit-learn 來分析數據。然而,在 Scikit-learn 中有許多方法可以使用邏輯回歸。查看[可傳遞的參數](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html?highlight=logistic%20regressio#sklearn.linear_model.LogisticRegression)。
基本上有兩個重要的參數 - `multi_class``solver` - 我們需要指定,當我們要求 Scikit-learn 執行邏輯回歸時。`multi_class` 值應用某種行為。solver 的值則是使用的算法。並非所有 solver 都可以與所有 `multi_class` 值配對。
根據文檔,在多類情況下,訓練算法:
- **使用一對多OvR方案**,如果 `multi_class` 選項設置為 `ovr`
- **使用交叉熵損失**,如果 `multi_class` 選項設置為 `multinomial`。(目前 `multinomial` 選項僅支持 lbfgssagsaganewton-cg solver。
> 🎓 這裡的“方案”可以是 'ovr'(一對多)或 'multinomial'。由於邏輯回歸主要設計用於支持二類分類,這些方案使其能更好地處理多類分類任務。[來源](https://machinelearningmastery.com/one-vs-rest-and-one-vs-one-for-multi-class-classification/)
> 🎓 solver 定義為“用於優化問題的算法”。[來源](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html?highlight=logistic%20regressio#sklearn.linear_model.LogisticRegression)。
Scikit-learn 提供了這張表格來解釋 solver 如何處理不同數據結構帶來的挑戰:
![solver](../../../../4-Classification/2-Classifiers-1/images/solvers.png)
## 練習 - 分割數據
我們可以專注於邏輯回歸作為我們的第一次訓練嘗試,因為您在上一節課中剛剛學習了它。
通過調用 `train_test_split()` 將數據分為訓練和測試組:
```python
X_train, X_test, y_train, y_test = train_test_split(cuisines_feature_df, cuisines_label_df, test_size=0.3)
```
## 練習 - 應用邏輯回歸
由於您正在使用多類情況您需要選擇使用哪種_方案_以及設置哪種_solver_。使用 LogisticRegression 並設置 multi_class 為 `ovr` 和 solver 為 `liblinear` 進行訓練。
1. 創建一個邏輯回歸,將 multi_class 設置為 `ovr`solver 設置為 `liblinear`
```python
lr = LogisticRegression(multi_class='ovr',solver='liblinear')
model = lr.fit(X_train, np.ravel(y_train))
accuracy = model.score(X_test, y_test)
print ("Accuracy is {}".format(accuracy))
```
✅ 嘗試使用其他 solver例如 `lbfgs`,它通常設置為默認值
> 注意,當需要將資料展平時,可以使用 Pandas 的 [`ravel`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.ravel.html) 函數。
準確率超過 **80%**
1. 您可以透過測試第 50 行數據來查看此模型的運作情況:
```python
print(f'ingredients: {X_test.iloc[50][X_test.iloc[50]!=0].keys()}')
print(f'cuisine: {y_test.iloc[50]}')
```
結果如下:
```output
ingredients: Index(['cilantro', 'onion', 'pea', 'potato', 'tomato', 'vegetable_oil'], dtype='object')
cuisine: indian
```
✅ 嘗試不同的行數並檢查結果
1. 更深入地探討,您可以檢查此預測的準確性:
```python
test= X_test.iloc[50].values.reshape(-1, 1).T
proba = model.predict_proba(test)
classes = model.classes_
resultdf = pd.DataFrame(data=proba, columns=classes)
topPrediction = resultdf.T.sort_values(by=[0], ascending = [False])
topPrediction.head()
```
結果如下 - 印度料理是模型的最佳猜測,且概率相當高:
| | 0 |
| -------: | -------: |
| indian | 0.715851 |
| chinese | 0.229475 |
| japanese | 0.029763 |
| korean | 0.017277 |
| thai | 0.007634 |
✅ 您能解釋為什麼模型非常確定這是印度料理嗎?
1. 透過列印分類報告獲取更多細節,就像您在回歸課程中所做的一樣:
```python
y_pred = model.predict(X_test)
print(classification_report(y_test,y_pred))
```
| | precision | recall | f1-score | support |
| ------------ | --------- | ------ | -------- | ------- |
| chinese | 0.73 | 0.71 | 0.72 | 229 |
| indian | 0.91 | 0.93 | 0.92 | 254 |
| japanese | 0.70 | 0.75 | 0.72 | 220 |
| korean | 0.86 | 0.76 | 0.81 | 242 |
| thai | 0.79 | 0.85 | 0.82 | 254 |
| accuracy | 0.80 | 1199 | | |
| macro avg | 0.80 | 0.80 | 0.80 | 1199 |
| weighted avg | 0.80 | 0.80 | 0.80 | 1199 |
## 🚀挑戰
在本課程中,您使用清理過的數據建立了一個機器學習模型,該模型可以根據一系列食材預測國家料理。花些時間閱讀 Scikit-learn 提供的多種分類數據選項。深入了解 "solver" 的概念,以理解其背後的運作原理。
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
深入了解邏輯回歸背後的數學原理:[這篇課程](https://people.eecs.berkeley.edu/~russell/classes/cs194/f11/lectures/CS194%20Fall%202011%20Lecture%2006.pdf)
## 作業
[研究 solvers](assignment.md)
---
**免責聲明**
本文件使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對於因使用此翻譯而產生的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,15 @@
# 研究解算器
## 說明
在本課程中,你學習了各種解算器,它們將演算法與機器學習過程相結合,以建立準確的模型。請回顧課程中列出的解算器,並選擇其中兩個。用自己的話比較和對比這兩個解算器。它們解決的是什麼類型的問題?它們如何與各種數據結構配合工作?為什麼你會選擇其中一個而不是另一個?
## 評分標準
| 評分標準 | 卓越 | 合格 | 需要改進 |
| -------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------- | ---------------------------- |
| | 提交了一份 .doc 文件,其中包含兩段文字,分別對每個解算器進行了深入的比較。 | 提交了一份 .doc 文件,但僅包含一段文字 | 作業未完成 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -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": "68829b06b4dcd512d3327849191f4d7f",
"translation_date": "2025-08-29T23:40:56+00:00",
"source_file": "4-Classification/2-Classifiers-1/notebook.ipynb",
"language_code": "mo"
}
},
"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,6 @@
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

File diff suppressed because one or more lines are too long

@ -0,0 +1,279 @@
{
"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": [],
"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-08-29T23:41:13+00:00",
"source_file": "4-Classification/2-Classifiers-1/solution/notebook.ipynb",
"language_code": "mo"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

@ -0,0 +1,240 @@
# 美食分類器 2
在這第二堂分類課中,您將探索更多分類數據的方法,並了解選擇不同分類器的影響。
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
### 前置條件
我們假設您已完成前面的課程,並在這個四堂課的資料夾根目錄中的 `data` 資料夾內擁有一個名為 _cleaned_cuisines.csv_ 的清理後數據集。
### 準備工作
我們已將您的 _notebook.ipynb_ 文件載入清理後的數據集,並將其分為 X 和 y 數據框,準備進行模型構建。
## 分類地圖
之前,您已學習如何使用 Microsoft 的速查表來分類數據。Scikit-learn 提供了一個類似但更細緻的速查表,可以進一步幫助您縮小估算器(分類器的另一個術語)的選擇範圍:
![Scikit-learn 的機器學習地圖](../../../../4-Classification/3-Classifiers-2/images/map.png)
> 提示:[在線查看此地圖](https://scikit-learn.org/stable/tutorial/machine_learning_map/),並點擊路徑以閱讀相關文檔。
### 計劃
當您對數據有清晰的理解時,這張地圖非常有幫助,因為您可以沿著它的路徑進行決策:
- 我們有超過 50 個樣本
- 我們想要預測一個類別
- 我們有標籤數據
- 我們的樣本少於 10 萬
- ✨ 我們可以選擇 Linear SVC
- 如果這不起作用,因為我們有數值數據
- 我們可以嘗試 ✨ KNeighbors Classifier
- 如果這也不起作用,嘗試 ✨ SVC 和 ✨ Ensemble Classifiers
這是一條非常有幫助的路徑。
## 練習 - 分割數據
按照這條路徑,我們應該從導入一些需要的庫開始。
1. 導入所需的庫:
```python
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report, precision_recall_curve
import numpy as np
```
2. 分割您的訓練和測試數據:
```python
X_train, X_test, y_train, y_test = train_test_split(cuisines_feature_df, cuisines_label_df, test_size=0.3)
```
## Linear SVC 分類器
支持向量聚類SVC是支持向量機SVM家族中的一員。通過這種方法您可以選擇一個「核函數」來決定如何聚類標籤。「C」參數指的是「正則化」用於調節參數的影響。核函數可以是[多種選項](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html#sklearn.svm.SVC)之一在這裡我們將其設置為「linear」以確保使用線性 SVC。預設情況下概率為「false」在這裡我們將其設置為「true」以獲取概率估計。我們將隨機狀態設置為「0」以便打亂數據以獲取概率。
### 練習 - 應用線性 SVC
從創建分類器數組開始。隨著測試的進行,您將逐步向該數組添加內容。
1. 從 Linear SVC 開始:
```python
C = 10
# Create different classifiers.
classifiers = {
'Linear SVC': SVC(kernel='linear', C=C, probability=True,random_state=0)
}
```
2. 使用 Linear SVC 訓練模型並打印報告:
```python
n_classifiers = len(classifiers)
for index, (name, classifier) in enumerate(classifiers.items()):
classifier.fit(X_train, np.ravel(y_train))
y_pred = classifier.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy (train) for %s: %0.1f%% " % (name, accuracy * 100))
print(classification_report(y_test,y_pred))
```
結果相當不錯:
```output
Accuracy (train) for Linear SVC: 78.6%
precision recall f1-score support
chinese 0.71 0.67 0.69 242
indian 0.88 0.86 0.87 234
japanese 0.79 0.74 0.76 254
korean 0.85 0.81 0.83 242
thai 0.71 0.86 0.78 227
accuracy 0.79 1199
macro avg 0.79 0.79 0.79 1199
weighted avg 0.79 0.79 0.79 1199
```
## K-Neighbors 分類器
K-Neighbors 屬於「鄰居」家族的機器學習方法,可用於監督學習和非監督學習。在這種方法中,預定義了一些點,並在這些點周圍收集數據,以便為數據預測通用標籤。
### 練習 - 應用 K-Neighbors 分類器
之前的分類器表現不錯,與數據配合良好,但也許我們可以獲得更好的準確性。嘗試使用 K-Neighbors 分類器。
1. 在分類器數組中添加一行(在 Linear SVC 項目後添加逗號):
```python
'KNN classifier': KNeighborsClassifier(C),
```
結果稍微差了一些:
```output
Accuracy (train) for KNN classifier: 73.8%
precision recall f1-score support
chinese 0.64 0.67 0.66 242
indian 0.86 0.78 0.82 234
japanese 0.66 0.83 0.74 254
korean 0.94 0.58 0.72 242
thai 0.71 0.82 0.76 227
accuracy 0.74 1199
macro avg 0.76 0.74 0.74 1199
weighted avg 0.76 0.74 0.74 1199
```
✅ 了解更多 [K-Neighbors](https://scikit-learn.org/stable/modules/neighbors.html#neighbors)
## 支持向量分類器
支持向量分類器屬於 [支持向量機](https://wikipedia.org/wiki/Support-vector_machine) 家族的機器學習方法用於分類和回歸任務。SVM 將訓練樣本映射到空間中的點,以最大化兩個類別之間的距離。隨後的數據被映射到這個空間中,以便預測其類別。
### 練習 - 應用支持向量分類器
讓我們嘗試使用支持向量分類器來獲得更好的準確性。
1. 在 K-Neighbors 項目後添加逗號,然後添加以下行:
```python
'SVC': SVC(),
```
結果相當不錯!
```output
Accuracy (train) for SVC: 83.2%
precision recall f1-score support
chinese 0.79 0.74 0.76 242
indian 0.88 0.90 0.89 234
japanese 0.87 0.81 0.84 254
korean 0.91 0.82 0.86 242
thai 0.74 0.90 0.81 227
accuracy 0.83 1199
macro avg 0.84 0.83 0.83 1199
weighted avg 0.84 0.83 0.83 1199
```
✅ 了解更多 [支持向量](https://scikit-learn.org/stable/modules/svm.html#svm)
## 集成分類器
即使之前的測試結果已經相當不錯,我們還是沿著路徑走到最後,嘗試一些「集成分類器」,特別是隨機森林和 AdaBoost
```python
'RFST': RandomForestClassifier(n_estimators=100),
'ADA': AdaBoostClassifier(n_estimators=100)
```
結果非常好,特別是隨機森林:
```output
Accuracy (train) for RFST: 84.5%
precision recall f1-score support
chinese 0.80 0.77 0.78 242
indian 0.89 0.92 0.90 234
japanese 0.86 0.84 0.85 254
korean 0.88 0.83 0.85 242
thai 0.80 0.87 0.83 227
accuracy 0.84 1199
macro avg 0.85 0.85 0.84 1199
weighted avg 0.85 0.84 0.84 1199
Accuracy (train) for ADA: 72.4%
precision recall f1-score support
chinese 0.64 0.49 0.56 242
indian 0.91 0.83 0.87 234
japanese 0.68 0.69 0.69 254
korean 0.73 0.79 0.76 242
thai 0.67 0.83 0.74 227
accuracy 0.72 1199
macro avg 0.73 0.73 0.72 1199
weighted avg 0.73 0.72 0.72 1199
```
✅ 了解更多 [集成分類器](https://scikit-learn.org/stable/modules/ensemble.html)
這種機器學習方法「結合了多個基估算器的預測」,以提高模型的質量。在我們的例子中,我們使用了隨機森林和 AdaBoost。
- [隨機森林](https://scikit-learn.org/stable/modules/ensemble.html#forest)一種平均方法構建了一個隨機性注入的「決策樹森林」以避免過擬合。n_estimators 參數設置為樹的數量。
- [AdaBoost](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.AdaBoostClassifier.html) 將分類器擬合到數據集,然後將該分類器的副本擬合到相同數據集。它專注於錯誤分類項的權重,並調整下一個分類器的擬合以進行修正。
---
## 🚀 挑戰
這些技術中的每一種都有大量參數可以調整。研究每種技術的默認參數,並思考調整這些參數對模型質量的影響。
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
這些課程中有很多術語,花點時間回顧[這份列表](https://docs.microsoft.com/dotnet/machine-learning/resources/glossary?WT.mc_id=academic-77952-leestott)中的有用術語!
## 作業
[參數調整](assignment.md)
---
**免責聲明**
本文件使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對於因使用此翻譯而產生的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,16 @@
# 參數遊戲
## 說明
在使用這些分類器時有許多參數是預設設定的。VS Code 中的 Intellisense 可以幫助你深入了解這些參數。在本課程中採用其中一種機器學習分類技術,並透過調整各種參數值重新訓練模型。建立一個筆記本,解釋為什麼某些更改能提升模型品質,而其他更改則會降低品質。請詳細回答。
## 評分標準
| 評分標準 | 卓越 | 合格 | 需要改進 |
| -------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ---------------------------- |
| | 提供一個完整的筆記本,包含已建構的分類器及其參數調整,並在文字框中解釋更改的原因 | 提供的筆記本不完整或解釋不充分 | 筆記本有錯誤或存在缺陷 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -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**免責聲明** \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-08-29T23:47:24+00:00",
"source_file": "4-Classification/3-Classifiers-2/notebook.ipynb",
"language_code": "mo"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

@ -0,0 +1,6 @@
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -0,0 +1,648 @@
{
"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-08-29T23:50:53+00:00",
"source_file": "4-Classification/3-Classifiers-2/solution/R/lesson_12-R.ipynb",
"language_code": "mo"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "jsFutf_ygqSx"
},
"source": []
},
{
"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",
"- 增加少數類別的觀測數量:`過採樣`,例如使用 SMOTE 演算法,該演算法通過少數類別案例的最近鄰居合成生成新的樣本。\n",
"\n",
"- 移除多數類別的觀測數量:`欠採樣`\n",
"\n",
"在之前的課程中,我們展示了如何使用 `recipe` 處理不平衡數據集。`recipe` 可以被視為一種藍圖,描述了應該對數據集應用哪些步驟以使其準備好進行數據分析。在我們的案例中,我們希望在 `訓練集` 中的菜系數量分佈是均等的。讓我們直接開始吧!\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",
"### 支援向量機\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是支持向量機SVM家族中的一種機器學習技術。在 SVC 中,超平面被選擇用來正確分隔`大部分`的訓練觀測值,但`可能會錯誤分類`一些觀測值。通過允許某些點位於錯誤的一側SVM 對異常值的抵抗力更強,因此對新數據的泛化能力更好。調節這種違規的參數稱為`cost`,其默認值為 1請參閱 `help(\"svm_poly\")`)。\n",
"\n",
"讓我們通過在多項式 SVM 模型中設置 `degree = 1` 來創建一個線性 SVC。\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": [
"現在我們已經將預處理步驟和模型規範整合到一個*工作流程*中,接下來可以進行線性 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 使用*核技巧*來擴展特徵空間,以適應類別之間的非線性關係。一種受歡迎且極具彈性的核函數是*徑向基函數*。讓我們來看看它在我們的數據上會有怎樣的表現。\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",
"> - [*支持向量機*](https://bradleyboehmke.github.io/HOML/svm.html)《Hands-on Machine Learning with R》\n",
">\n",
"> - [*支持向量機*](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",
"我們先從嘗試隨機森林模型開始。隨機森林模型會建立大量的決策樹,然後應用平均函數以生成更好的整體模型。\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",
"> - [社會科學家的機器學習](https://cimentadaj.github.io/ml_socsci/tree-based-methods.html#random-forests)\n",
">\n",
"> - [R 的實作機器學習](https://bradleyboehmke.github.io/HOML/)\n",
">\n",
"> - [統計學習入門R 應用](https://www.statlearning.com/)\n",
">\n",
"> - <https://algotech.netlify.app/blog/xgboost/> - 探討 AdaBoost 模型,它是 xgboost 的一個不錯替代方案。\n",
">\n",
"> 了解更多關於集成分類器的內容。\n",
"\n",
"## 4. 額外部分 - 比較多個模型\n",
"\n",
"在這次的實驗中,我們已經擬合了相當多的模型 🙌。如果要從不同的預處理器和/或模型規範中建立大量工作流程,然後逐一計算性能指標,可能會變得非常繁瑣或費力。\n",
"\n",
"讓我們看看是否可以通過創建一個函數來解決這個問題。該函數可以在訓練集上擬合一系列工作流程,然後基於測試集返回性能指標。我們將使用 [purrr](https://purrr.tidyverse.org/) 套件中的 `map()` 和 `map_dfr()` 來對列表中的每個元素應用函數。\n",
"\n",
"> [`map()`](https://purrr.tidyverse.org/reference/map.html) 函數可以讓你用更簡潔且易讀的代碼替代許多 for 迴圈。學習 [`map()`](https://purrr.tidyverse.org/reference/map.html) 函數的最佳地方是 R for Data Science 中的 [迭代章節](http://r4ds.had.co.nz/iteration.html)。\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",
"每種技術都有許多參數可以調整,例如 SVM 的 `cost`、KNN 的 `neighbors`、隨機森林的 `mtry`(隨機選擇的預測變數)。\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)Gold 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,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": [
"# 嘗試不同的分類器\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-08-29T23:47:44+00:00",
"source_file": "4-Classification/3-Classifiers-2/solution/notebook.ipynb",
"language_code": "mo"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

@ -0,0 +1,320 @@
# 建立一個美食推薦網頁應用程式
在這節課中,你將使用之前課程中學到的一些技術,並利用這個系列中使用的美味美食數據集,來建立一個分類模型。此外,你還將建立一個小型網頁應用程式,使用已保存的模型,並利用 Onnx 的網頁運行時環境。
機器學習最實用的應用之一就是建立推薦系統,而今天你可以邁出這個方向的第一步!
[![展示這個網頁應用程式](https://img.youtube.com/vi/17wdM9AHMfg/0.jpg)](https://youtu.be/17wdM9AHMfg "應用機器學習")
> 🎥 點擊上方圖片觀看影片Jen Looper 使用分類的美食數據建立了一個網頁應用程式
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
在這節課中,你將學到:
- 如何建立模型並將其保存為 Onnx 模型
- 如何使用 Netron 檢查模型
- 如何在網頁應用程式中使用你的模型進行推理
## 建立你的模型
建立應用型機器學習系統是將這些技術應用於業務系統的重要部分。你可以通過使用 Onnx將模型嵌入到你的網頁應用程式中因此在需要時也可以在離線環境中使用
在[之前的課程](../../3-Web-App/1-Web-App/README.md)中,你建立了一個關於 UFO 目擊事件的回歸模型將其“pickle”保存並在 Flask 應用程式中使用。雖然這種架構非常實用,但它是一個全棧的 Python 應用程式,而你的需求可能包括使用 JavaScript 應用程式。
在這節課中,你可以建立一個基於 JavaScript 的基本推理系統。不過,首先你需要訓練一個模型並將其轉換為 Onnx 格式。
## 練習 - 訓練分類模型
首先,使用我們之前清理過的美食數據集來訓練一個分類模型。
1. 開始時導入一些有用的庫:
```python
!pip install skl2onnx
import pandas as pd
```
你需要使用 '[skl2onnx](https://onnx.ai/sklearn-onnx/)' 來幫助將 Scikit-learn 模型轉換為 Onnx 格式。
1. 然後,像之前課程中一樣,使用 `read_csv()` 讀取 CSV 文件來處理數據:
```python
data = pd.read_csv('../data/cleaned_cuisines.csv')
data.head()
```
1. 刪除前兩列不必要的數據,並將剩餘數據保存為 'X'
```python
X = data.iloc[:,2:]
X.head()
```
1. 將標籤保存為 'y'
```python
y = data[['cuisine']]
y.head()
```
### 開始訓練流程
我們將使用具有良好準確性的 'SVC' 庫。
1. 從 Scikit-learn 導入相關庫:
```python
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report
```
1. 分離訓練集和測試集:
```python
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3)
```
1. 像之前課程中一樣,建立一個 SVC 分類模型:
```python
model = SVC(kernel='linear', C=10, probability=True,random_state=0)
model.fit(X_train,y_train.values.ravel())
```
1. 現在,測試你的模型,調用 `predict()`
```python
y_pred = model.predict(X_test)
```
1. 輸出分類報告以檢查模型質量:
```python
print(classification_report(y_test,y_pred))
```
如我們之前所見,準確性是很好的:
```output
precision recall f1-score support
chinese 0.72 0.69 0.70 257
indian 0.91 0.87 0.89 243
japanese 0.79 0.77 0.78 239
korean 0.83 0.79 0.81 236
thai 0.72 0.84 0.78 224
accuracy 0.79 1199
macro avg 0.79 0.79 0.79 1199
weighted avg 0.79 0.79 0.79 1199
```
### 將模型轉換為 Onnx 格式
確保使用正確的張量數進行轉換。這個數據集列出了 380 種食材,因此你需要在 `FloatTensorType` 中標註這個數字:
1. 使用 380 的張量數進行轉換。
```python
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
initial_type = [('float_input', FloatTensorType([None, 380]))]
options = {id(model): {'nocl': True, 'zipmap': False}}
```
1. 創建 onx 並保存為文件 **model.onnx**
```python
onx = convert_sklearn(model, initial_types=initial_type, options=options)
with open("./model.onnx", "wb") as f:
f.write(onx.SerializeToString())
```
> 注意,你可以在轉換腳本中傳入[選項](https://onnx.ai/sklearn-onnx/parameterized.html)。在這個例子中,我們將 'nocl' 設為 True'zipmap' 設為 False。由於這是一個分類模型你可以選擇移除 ZipMap它會生成一個字典列表非必要。`nocl` 表示是否在模型中包含類別信息。通過將 `nocl` 設為 'True',可以減小模型的大小。
運行整個筆記本後,將生成一個 Onnx 模型並保存到這個文件夾中。
## 查看你的模型
Onnx 模型在 Visual Studio Code 中不太容易查看,但有一個非常好的免費軟體,許多研究人員用來可視化模型,以確保其正確構建。下載 [Netron](https://github.com/lutzroeder/Netron) 並打開你的 model.onnx 文件。你可以看到你的簡單模型被可視化,顯示其 380 個輸入和分類器:
![Netron 可視化](../../../../4-Classification/4-Applied/images/netron.png)
Netron 是一個查看模型的有用工具。
現在你已經準備好在網頁應用程式中使用這個簡單的模型了。讓我們建立一個應用程式,當你查看冰箱並試圖找出哪些剩餘食材可以用來烹飪某種美食時,這個應用程式會派上用場。
## 建立推薦網頁應用程式
你可以直接在網頁應用程式中使用你的模型。這種架構還允許你在本地甚至離線運行它。首先,在存儲 `model.onnx` 文件的同一文件夾中創建一個 `index.html` 文件。
1. 在這個文件 _index.html_ 中,添加以下標記:
```html
<!DOCTYPE html>
<html>
<header>
<title>Cuisine Matcher</title>
</header>
<body>
...
</body>
</html>
```
1. 現在,在 `body` 標籤內添加一些標記,顯示一些反映食材的複選框列表:
```html
<h1>Check your refrigerator. What can you create?</h1>
<div id="wrapper">
<div class="boxCont">
<input type="checkbox" value="4" class="checkbox">
<label>apple</label>
</div>
<div class="boxCont">
<input type="checkbox" value="247" class="checkbox">
<label>pear</label>
</div>
<div class="boxCont">
<input type="checkbox" value="77" class="checkbox">
<label>cherry</label>
</div>
<div class="boxCont">
<input type="checkbox" value="126" class="checkbox">
<label>fenugreek</label>
</div>
<div class="boxCont">
<input type="checkbox" value="302" class="checkbox">
<label>sake</label>
</div>
<div class="boxCont">
<input type="checkbox" value="327" class="checkbox">
<label>soy sauce</label>
</div>
<div class="boxCont">
<input type="checkbox" value="112" class="checkbox">
<label>cumin</label>
</div>
</div>
<div style="padding-top:10px">
<button onClick="startInference()">What kind of cuisine can you make?</button>
</div>
```
注意,每個複選框都有一個值。這反映了數據集中食材所在的索引。例如,蘋果在這個按字母順序排列的列表中位於第五列,因此其值為 '4'(因為我們從 0 開始計數)。你可以查閱 [ingredients spreadsheet](../../../../4-Classification/data/ingredient_indexes.csv) 來找到某個食材的索引。
繼續在 index.html 文件中工作,在最後一個閉合的 `</div>` 後添加一個腳本塊,調用模型。
1. 首先,導入 [Onnx Runtime](https://www.onnxruntime.ai/)
```html
<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.9.0/dist/ort.min.js"></script>
```
> Onnx Runtime 用於在廣泛的硬體平台上運行你的 Onnx 模型,包括優化和使用的 API。
1. 一旦運行時環境就緒,你可以調用它:
```html
<script>
const ingredients = Array(380).fill(0);
const checks = [...document.querySelectorAll('.checkbox')];
checks.forEach(check => {
check.addEventListener('change', function() {
// toggle the state of the ingredient
// based on the checkbox's value (1 or 0)
ingredients[check.value] = check.checked ? 1 : 0;
});
});
function testCheckboxes() {
// validate if at least one checkbox is checked
return checks.some(check => check.checked);
}
async function startInference() {
let atLeastOneChecked = testCheckboxes()
if (!atLeastOneChecked) {
alert('Please select at least one ingredient.');
return;
}
try {
// create a new session and load the model.
const session = await ort.InferenceSession.create('./model.onnx');
const input = new ort.Tensor(new Float32Array(ingredients), [1, 380]);
const feeds = { float_input: input };
// feed inputs and run
const results = await session.run(feeds);
// read from results
alert('You can enjoy ' + results.label.data[0] + ' cuisine today!')
} catch (e) {
console.log(`failed to inference ONNX model`);
console.error(e);
}
}
</script>
```
在這段代碼中,發生了以下幾件事:
1. 你創建了一個包含 380 個可能值1 或 0的數組根據是否選中某個食材複選框來設置並發送到模型進行推理。
2. 你創建了一個複選框數組,以及一個在應用程式啟動時調用的 `init` 函數,用於確定複選框是否被選中。當複選框被選中時,`ingredients` 數組會被修改以反映所選食材。
3. 你創建了一個 `testCheckboxes` 函數,用於檢查是否有任何複選框被選中。
4. 當按下按鈕時,你使用 `startInference` 函數,如果有任何複選框被選中,就開始推理。
5. 推理過程包括:
1. 設置模型的異步加載
2. 創建一個張量結構,發送到模型
3. 創建反映你在訓練模型時創建的 `float_input` 輸入的 'feeds'(你可以使用 Netron 驗證該名稱)
4. 將這些 'feeds' 發送到模型並等待響應
## 測試你的應用程式
在 Visual Studio Code 中打開一個終端會話,進入存放 index.html 文件的文件夾。確保你已全局安裝 [http-server](https://www.npmjs.com/package/http-server),然後在提示符下輸入 `http-server`。一個本地主機應該會打開,你可以查看你的網頁應用程式。檢查基於不同食材推薦的美食:
![食材網頁應用程式](../../../../4-Classification/4-Applied/images/web-app.png)
恭喜你,你已經建立了一個帶有幾個字段的“推薦”網頁應用程式。花點時間擴展這個系統吧!
## 🚀挑戰
你的網頁應用程式非常簡單,因此繼續使用 [ingredient_indexes](../../../../4-Classification/data/ingredient_indexes.csv) 數據中的食材及其索引來擴展它。哪些味道組合可以用來創造某個國家的菜餚?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
雖然這節課只是簡單介紹了如何為食材創建推薦系統,但這個機器學習應用領域有非常豐富的例子。閱讀更多關於這些系統如何構建的內容:
- https://www.sciencedirect.com/topics/computer-science/recommendation-engine
- https://www.technologyreview.com/2014/08/25/171547/the-ultimate-challenge-for-recommendation-engines/
- https://www.technologyreview.com/2015/03/23/168831/everything-is-a-recommendation/
## 作業
[建立一個新的推薦系統](assignment.md)
---
**免責聲明**
本文件使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對於因使用此翻譯而產生的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,16 @@
# 建立推薦系統
## 說明
根據本課程中的練習,您現在已經了解如何使用 Onnx Runtime 和轉換後的 Onnx 模型來建立基於 JavaScript 的網頁應用程式。嘗試使用本課程中的資料或其他來源的資料(請記得給予來源信用)來建立一個新的推薦系統。您可以根據不同的性格特徵建立寵物推薦系統,或者根據個人情緒建立音樂類型推薦系統。發揮創意吧!
## 評分標準
| 評分標準 | 卓越表現 | 合格表現 | 需要改進 |
| -------- | ---------------------------------------------------------------------- | ------------------------------------- | --------------------------------- |
| | 提供了一個網頁應用程式和筆記本,且兩者均有良好的文件記錄並能正常運行 | 其中一項缺失或有缺陷 | 兩者皆缺失或有缺陷 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。

@ -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-08-29T23:46:52+00:00",
"source_file": "4-Classification/4-Applied/notebook.ipynb",
"language_code": "mo"
}
},
"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,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-08-29T23:47:08+00:00",
"source_file": "4-Classification/4-Applied/solution/notebook.ipynb",
"language_code": "mo"
}
},
"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**免責聲明** \n本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋不承擔責任。\n"
]
}
]
}

@ -0,0 +1,32 @@
# 開始學習分類
## 區域主題:美味的亞洲和印度料理 🍜
在亞洲和印度,飲食文化非常多樣化,而且非常美味!讓我們來看看有關區域料理的數據,試著了解它們的食材。
![泰國食物攤販](../../../translated_images/zh-MO/thai-food.c47a7a7f9f05c218.webp)
> 照片由 <a href="https://unsplash.com/@changlisheng?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Lisheng Chang</a> 提供,來自 <a href="https://unsplash.com/s/photos/asian-food?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
## 你將學到什麼
在本章節中,你將基於之前對回歸的學習,進一步了解其他分類器,幫助你更好地理解數據。
> 有一些實用的低代碼工具可以幫助你學習如何使用分類模型。試試 [Azure ML 完成這項任務](https://docs.microsoft.com/learn/modules/create-classification-model-azure-machine-learning-designer/?WT.mc_id=academic-77952-leestott)
## 課程
1. [分類介紹](1-Introduction/README.md)
2. [更多分類器](2-Classifiers-1/README.md)
3. [其他分類器](3-Classifiers-2/README.md)
4. [應用機器學習:建立網頁應用程式](4-Applied/README.md)
## 致謝
"開始學習分類" 由 [Cassie Breviu](https://www.twitter.com/cassiebreviu) 和 [Jen Looper](https://www.twitter.com/jenlooper) 用 ♥️ 撰寫。
美味料理數據集來源於 [Kaggle](https://www.kaggle.com/hoandan/asian-and-indian-cuisines)。
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

@ -0,0 +1,338 @@
# 聚類簡介
聚類是一種[無監督學習](https://wikipedia.org/wiki/Unsupervised_learning)方法,假設數據集是未標記的,或者其輸入未與預定義的輸出匹配。它使用各種算法來整理未標記的數據,並根據數據中識別出的模式提供分組。
[![PSquare 的 No One Like You](https://img.youtube.com/vi/ty2advRiWJM/0.jpg)](https://youtu.be/ty2advRiWJM "PSquare 的 No One Like You")
> 🎥 點擊上方圖片觀看影片。在學習聚類的機器學習時,欣賞一些尼日利亞舞廳音樂——這是 PSquare 在 2014 年的一首高評價歌曲。
## [課前測驗](https://ff-quizzes.netlify.app/en/ml/)
### 簡介
[聚類](https://link.springer.com/referenceworkentry/10.1007%2F978-0-387-30164-8_124)在數據探索中非常有用。讓我們看看它是否能幫助發現尼日利亞觀眾消費音樂的趨勢和模式。
✅ 花一分鐘思考一下聚類的用途。在日常生活中,聚類發生在你有一堆洗好的衣物需要分類成家人衣物的時候 🧦👕👖🩲。在數據科學中,聚類發生在分析用戶偏好或確定任何未標記數據集的特徵時。聚類在某種程度上幫助我們理解混亂,就像整理襪子抽屜一樣。
[![機器學習簡介](https://img.youtube.com/vi/esmzYhuFnds/0.jpg)](https://youtu.be/esmzYhuFnds "聚類簡介")
> 🎥 點擊上方圖片觀看影片:麻省理工學院的 John Guttag 介紹聚類
在專業環境中,聚類可以用於確定市場細分,例如確定哪些年齡段購買哪些商品。另一個用途是異常檢測,例如從信用卡交易數據集中檢測欺詐行為。或者你可能使用聚類來確定一批醫學掃描中的腫瘤。
✅ 花一分鐘思考一下你可能在銀行、電子商務或商業環境中遇到過的聚類。
> 🎓 有趣的是,聚類分析起源於 1930 年代的人類學和心理學領域。你能想像它可能是如何被使用的嗎?
另外,你可以用它來分組搜索結果,例如按購物鏈接、圖片或評論分組。當你有一個大型數據集需要縮減並進行更細緻的分析時,聚類技術非常有用,因此可以在構建其他模型之前用來了解數據。
✅ 一旦你的數據被組織成聚類,你可以為其分配一個聚類 ID。這種技術在保護數據集隱私時非常有用你可以用聚類 ID 而不是更具識別性的數據來引用數據點。你能想到其他使用聚類 ID 而不是聚類中其他元素來識別的原因嗎?
在這個[學習模組](https://docs.microsoft.com/learn/modules/train-evaluate-cluster-models?WT.mc_id=academic-77952-leestott)中深入了解聚類技術。
## 聚類入門
[Scikit-learn 提供了大量](https://scikit-learn.org/stable/modules/clustering.html)方法來執行聚類。你選擇的類型將取決於你的使用案例。根據文檔,每種方法都有不同的優勢。以下是 Scikit-learn 支持的方法及其適用場景的簡化表格:
| 方法名稱 | 使用場景 |
| :--------------------------- | :--------------------------------------------------------------------- |
| K-Means | 通用用途,歸納式 |
| Affinity propagation | 多個、不均勻的聚類,歸納式 |
| Mean-shift | 多個、不均勻的聚類,歸納式 |
| Spectral clustering | 少量、均勻的聚類,轉導式 |
| Ward hierarchical clustering | 多個、受限的聚類,轉導式 |
| Agglomerative clustering | 多個、受限的、非歐幾里得距離,轉導式 |
| DBSCAN | 非平面幾何、不均勻的聚類,轉導式 |
| OPTICS | 非平面幾何、不均勻且密度可變的聚類,轉導式 |
| Gaussian mixtures | 平面幾何,歸納式 |
| BIRCH | 大型數據集且有異常值,歸納式 |
> 🎓 我們如何創建聚類與我們如何將數據點分組有很大關係。讓我們解釋一些術語:
>
> 🎓 ['轉導式' vs. '歸納式'](https://wikipedia.org/wiki/Transduction_(machine_learning))
>
> 轉導式推理是基於觀察到的訓練案例並映射到特定測試案例。歸納式推理是基於訓練案例並映射到一般規則,然後應用於測試案例。
>
> 舉例假設你有一個部分標記的數據集。一些是“唱片”一些是“CD”一些是空白。你的任務是為空白部分提供標籤。如果你選擇歸納式方法你會訓練一個模型尋找“唱片”和“CD”並將這些標籤應用於未標記的數據。這種方法可能難以分類實際上是“磁帶”的物品。而轉導式方法則更有效地處理這些未知數據因為它努力將相似的物品分組然後為整個分組分配標籤。在這種情況下聚類可能反映“圓形音樂物品”和“方形音樂物品”。
>
> 🎓 ['非平面' vs. '平面'幾何](https://datascience.stackexchange.com/questions/52260/terminology-flat-geometry-in-the-context-of-clustering)
>
> 源自數學術語,非平面 vs. 平面幾何指的是通過“平面”([歐幾里得](https://wikipedia.org/wiki/Euclidean_geometry))或“非平面”(非歐幾里得)幾何方法測量點之間的距離。
>
> '平面'在此上下文中指的是歐幾里得幾何(部分被教為“平面”幾何),而非平面指的是非歐幾里得幾何。幾何與機器學習有什麼關係?作為兩個根植於數學的領域,必須有一種通用方法來測量聚類中點之間的距離,這可以根據數據的性質以“平面”或“非平面”的方式完成。[歐幾里得距離](https://wikipedia.org/wiki/Euclidean_distance)是通過兩點之間線段的長度來測量的。[非歐幾里得距離](https://wikipedia.org/wiki/Non-Euclidean_geometry)則沿曲線測量。如果你的數據在可視化後似乎不在平面上,你可能需要使用專門的算法來處理它。
>
![平面 vs 非平面幾何信息圖](../../../../5-Clustering/1-Visualize/images/flat-nonflat.png)
> 信息圖由 [Dasani Madipalli](https://twitter.com/dasani_decoded) 提供
>
> 🎓 ['距離'](https://web.stanford.edu/class/cs345a/slides/12-clustering.pdf)
>
> 聚類由其距離矩陣定義,例如點之間的距離。這些距離可以通過幾種方式測量。歐幾里得聚類由點值的平均值定義,並包含一個“中心點”或中心點。因此距離是通過到該中心點的距離來測量的。非歐幾里得距離指的是“聚類中心”,即最接近其他點的點。聚類中心可以通過多種方式定義。
>
> 🎓 ['受限'](https://wikipedia.org/wiki/Constrained_clustering)
>
> [受限聚類](https://web.cs.ucdavis.edu/~davidson/Publications/ICDMTutorial.pdf)在這種無監督方法中引入了“半監督”學習。點之間的關係被標記為“不能鏈接”或“必須鏈接”,因此對數據集施加了一些規則。
>
> 舉例:如果一個算法在一批未標記或半標記的數據上自由運行,它生成的聚類可能質量較差。在上述例子中,聚類可能會分組“圓形音樂物品”、“方形音樂物品”、“三角形物品”和“餅乾”。如果給出一些約束或規則(“物品必須由塑料製成”,“物品需要能夠產生音樂”),這可以幫助“約束”算法做出更好的選擇。
>
> 🎓 '密度'
>
> 被認為“噪聲”的數據被認為是“密集”的。每個聚類中的點之間的距離可能在檢查時顯示為更密集或更稀疏,因此需要使用適當的聚類方法來分析這些數據。[這篇文章](https://www.kdnuggets.com/2020/02/understanding-density-based-clustering.html)展示了使用 K-Means 聚類與 HDBSCAN 算法探索具有不均勻聚類密度的噪聲數據集的區別。
## 聚類算法
有超過 100 種聚類算法,其使用取決於手頭數據的性質。讓我們討論一些主要的算法:
- **層次聚類**。如果物品是根據其與附近物品的接近程度而分類而不是與更遠的物品則聚類是基於其成員與其他物品的距離形成的。Scikit-learn 的凝聚聚類是層次聚類。
![層次聚類信息圖](../../../../5-Clustering/1-Visualize/images/hierarchical.png)
> 信息圖由 [Dasani Madipalli](https://twitter.com/dasani_decoded) 提供
- **中心點聚類**。這種流行的算法需要選擇“k”即要形成的聚類數量之後算法確定聚類的中心點並圍繞該點收集數據。[K-means 聚類](https://wikipedia.org/wiki/K-means_clustering)是中心點聚類的一個流行版本。中心點由最近的平均值確定,因此得名。聚類的平方距離被最小化。
![中心點聚類信息圖](../../../../5-Clustering/1-Visualize/images/centroid.png)
> 信息圖由 [Dasani Madipalli](https://twitter.com/dasani_decoded) 提供
- **基於分佈的聚類**。基於統計建模,基於分佈的聚類集中於確定數據點屬於某個聚類的概率,並據此分配。高斯混合方法屬於此類。
- **基於密度的聚類**。數據點根據其密度或圍繞彼此的分組分配到聚類中。遠離群體的數據點被認為是異常值或噪聲。DBSCAN、Mean-shift 和 OPTICS 屬於此類聚類。
- **基於網格的聚類**。對於多維數據集,創建一個網格,並將數據分配到網格的單元中,從而創建聚類。
## 練習 - 聚類你的數據
聚類作為一種技術在適當的可視化支持下效果更佳,因此讓我們開始可視化我們的音樂數據。這個練習將幫助我們決定針對這些數據的性質最有效使用哪種聚類方法。
1. 打開此文件夾中的 [_notebook.ipynb_](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/notebook.ipynb)。
1. 導入 `Seaborn` 套件以進行良好的數據可視化。
```python
!pip install seaborn
```
1. 從 [_nigerian-songs.csv_](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/data/nigerian-songs.csv) 附加歌曲數據。加載一個包含歌曲數據的數據框。通過導入庫並輸出數據準備探索這些數據:
```python
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv("../data/nigerian-songs.csv")
df.head()
```
查看數據的前幾行:
| | name | album | artist | artist_top_genre | release_date | length | popularity | danceability | acousticness | energy | instrumentalness | liveness | loudness | speechiness | tempo | time_signature |
| --- | ------------------------ | ---------------------------- | ------------------- | ---------------- | ------------ | ------ | ---------- | ------------ | ------------ | ------ | ---------------- | -------- | -------- | ----------- | ------- | -------------- |
| 0 | Sparky | Mandy & The Jungle | Cruel Santino | alternative r&b | 2019 | 144000 | 48 | 0.666 | 0.851 | 0.42 | 0.534 | 0.11 | -6.699 | 0.0829 | 133.015 | 5 |
| 1 | shuga rush | EVERYTHING YOU HEARD IS TRUE | Odunsi (The Engine) | afropop | 2020 | 89488 | 30 | 0.71 | 0.0822 | 0.683 | 0.000169 | 0.101 | -5.64 | 0.36 | 129.993 | 3 |
| 2 | LITT! | LITT! | AYLØ | 獨立R&B | 2018 | 207758 | 40 | 0.836 | 0.272 | 0.564 | 0.000537 | 0.11 | -7.127 | 0.0424 | 130.005 | 4 |
| 3 | Confident / Feeling Cool | Enjoy Your Life | Lady Donli | 奈及利亞流行音樂 | 2019 | 175135 | 14 | 0.894 | 0.798 | 0.611 | 0.000187 | 0.0964 | -4.961 | 0.113 | 111.087 | 4 |
| 4 | wanted you | rare. | Odunsi (The Engine) | 非洲流行音樂 | 2018 | 152049 | 25 | 0.702 | 0.116 | 0.833 | 0.91 | 0.348 | -6.044 | 0.0447 | 105.115 | 4 |
1. 獲取數據框的基本資訊,呼叫 `info()`
```python
df.info()
```
輸出如下所示:
```output
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 530 entries, 0 to 529
Data columns (total 16 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 name 530 non-null object
1 album 530 non-null object
2 artist 530 non-null object
3 artist_top_genre 530 non-null object
4 release_date 530 non-null int64
5 length 530 non-null int64
6 popularity 530 non-null int64
7 danceability 530 non-null float64
8 acousticness 530 non-null float64
9 energy 530 non-null float64
10 instrumentalness 530 non-null float64
11 liveness 530 non-null float64
12 loudness 530 non-null float64
13 speechiness 530 non-null float64
14 tempo 530 non-null float64
15 time_signature 530 non-null int64
dtypes: float64(8), int64(4), object(4)
memory usage: 66.4+ KB
```
1. 通過呼叫 `isnull()` 並驗證總和是否為 0仔細檢查是否有空值
```python
df.isnull().sum()
```
看起來不錯:
```output
name 0
album 0
artist 0
artist_top_genre 0
release_date 0
length 0
popularity 0
danceability 0
acousticness 0
energy 0
instrumentalness 0
liveness 0
loudness 0
speechiness 0
tempo 0
time_signature 0
dtype: int64
```
1. 描述數據:
```python
df.describe()
```
| | release_date | length | popularity | danceability | acousticness | energy | instrumentalness | liveness | loudness | speechiness | tempo | time_signature |
| ----- | ------------ | ----------- | ---------- | ------------ | ------------ | -------- | ---------------- | -------- | --------- | ----------- | ---------- | -------------- |
| count | 530 | 530 | 530 | 530 | 530 | 530 | 530 | 530 | 530 | 530 | 530 | 530 |
| mean | 2015.390566 | 222298.1698 | 17.507547 | 0.741619 | 0.265412 | 0.760623 | 0.016305 | 0.147308 | -4.953011 | 0.130748 | 116.487864 | 3.986792 |
| std | 3.131688 | 39696.82226 | 18.992212 | 0.117522 | 0.208342 | 0.148533 | 0.090321 | 0.123588 | 2.464186 | 0.092939 | 23.518601 | 0.333701 |
| min | 1998 | 89488 | 0 | 0.255 | 0.000665 | 0.111 | 0 | 0.0283 | -19.362 | 0.0278 | 61.695 | 3 |
| 25% | 2014 | 199305 | 0 | 0.681 | 0.089525 | 0.669 | 0 | 0.07565 | -6.29875 | 0.0591 | 102.96125 | 4 |
| 50% | 2016 | 218509 | 13 | 0.761 | 0.2205 | 0.7845 | 0.000004 | 0.1035 | -4.5585 | 0.09795 | 112.7145 | 4 |
| 75% | 2017 | 242098.5 | 31 | 0.8295 | 0.403 | 0.87575 | 0.000234 | 0.164 | -3.331 | 0.177 | 125.03925 | 4 |
| max | 2020 | 511738 | 73 | 0.966 | 0.954 | 0.995 | 0.91 | 0.811 | 0.582 | 0.514 | 206.007 | 5 |
> 🤔 如果我們使用的是無需標籤數據的無監督方法(如聚類),為什麼還要顯示帶有標籤的數據?在數據探索階段,這些標籤很有用,但對於聚類算法來說並非必要。你完全可以移除列標題,僅通過列號來引用數據。
觀察數據的一般值。注意,受歡迎度可以為 "0",這表示歌曲沒有排名。我們稍後會移除這些數據。
1. 使用條形圖找出最受歡迎的音樂類型:
```python
import seaborn as sns
top = df['artist_top_genre'].value_counts()
plt.figure(figsize=(10,7))
sns.barplot(x=top[:5].index,y=top[:5].values)
plt.xticks(rotation=45)
plt.title('Top genres',color = 'blue')
```
![最受歡迎](../../../../5-Clustering/1-Visualize/images/popular.png)
✅ 如果你想查看更多的前幾名數據,可以將 `[:5]` 改為更大的值,或者移除它以查看全部。
注意,當最受歡迎的音樂類型顯示為 "Missing" 時,這表示 Spotify 沒有對其進行分類,因此我們需要將其移除。
1. 通過篩選移除缺失數據:
```python
df = df[df['artist_top_genre'] != 'Missing']
top = df['artist_top_genre'].value_counts()
plt.figure(figsize=(10,7))
sns.barplot(x=top.index,y=top.values)
plt.xticks(rotation=45)
plt.title('Top genres',color = 'blue')
```
現在重新檢查音樂類型:
![所有音樂類型](../../../../5-Clustering/1-Visualize/images/all-genres.png)
1. 顯然,前三大音樂類型在這個數據集中占據主導地位。我們專注於 `afro dancehall`、`afropop` 和 `nigerian pop`,並進一步篩選數據,移除任何受歡迎度為 0 的數據(這表示數據集中未分類的歌曲,對我們的目的來說可以視為噪聲):
```python
df = df[(df['artist_top_genre'] == 'afro dancehall') | (df['artist_top_genre'] == 'afropop') | (df['artist_top_genre'] == 'nigerian pop')]
df = df[(df['popularity'] > 0)]
top = df['artist_top_genre'].value_counts()
plt.figure(figsize=(10,7))
sns.barplot(x=top.index,y=top.values)
plt.xticks(rotation=45)
plt.title('Top genres',color = 'blue')
```
1. 快速測試數據是否有特別強的相關性:
```python
corrmat = df.corr(numeric_only=True)
f, ax = plt.subplots(figsize=(12, 9))
sns.heatmap(corrmat, vmax=.8, square=True)
```
![相關性](../../../../5-Clustering/1-Visualize/images/correlation.png)
唯一的強相關性是 `energy``loudness` 之間,這並不令人驚訝,因為響亮的音樂通常充滿活力。除此之外,相關性相對較弱。看看聚類算法如何處理這些數據會很有趣。
> 🎓 請注意,相關性並不意味著因果關係!我們有相關性的證據,但沒有因果關係的證據。一個[有趣的網站](https://tylervigen.com/spurious-correlations) 提供了一些強調這一點的視覺化內容。
在這個數據集中,歌曲的受歡迎度和舞蹈性是否存在某種趨同?使用 FacetGrid 可以顯示出無論音樂類型如何,都有一些同心圓的趨勢。這是否意味著奈及利亞的音樂品味在某種程度上對舞蹈性有一定的偏好?
✅ 嘗試不同的數據點(如 energy、loudness、speechiness以及更多或不同的音樂類型。你能發現什麼查看 `df.describe()` 表格,了解數據點的一般分佈。
### 練習 - 數據分佈
這三種音樂類型在受歡迎度和舞蹈性方面的感知是否有顯著差異?
1. 檢查我們前三大音樂類型在受歡迎度和舞蹈性上的數據分佈,沿著給定的 x 和 y 軸進行分析。
```python
sns.set_theme(style="ticks")
g = sns.jointplot(
data=df,
x="popularity", y="danceability", hue="artist_top_genre",
kind="kde",
)
```
你可以發現圍繞一個一般趨勢點的同心圓,顯示數據點的分佈。
> 🎓 請注意,此示例使用的是 KDE核密度估計該圖通過連續的概率密度曲線來表示數據。這在處理多個分佈時非常有用。
總體來看,這三種音樂類型在受歡迎度和舞蹈性方面大致一致。在這些大致對齊的數據中確定聚類將是一個挑戰:
![分佈](../../../../5-Clustering/1-Visualize/images/distribution.png)
1. 創建散點圖:
```python
sns.FacetGrid(df, hue="artist_top_genre", height=5) \
.map(plt.scatter, "popularity", "danceability") \
.add_legend()
```
同一軸上的散點圖顯示了類似的趨勢:
![Facetgrid](../../../../5-Clustering/1-Visualize/images/facetgrid.png)
總體來說,對於聚類分析,你可以使用散點圖來顯示數據的聚類,因此掌握這種類型的可視化非常有用。在下一課中,我們將使用 k-means 聚類來探索這些數據中有趣的重疊群組。
---
## 🚀挑戰
為了準備下一課,製作一個關於你可能在生產環境中發現並使用的各種聚類算法的圖表。這些聚類算法試圖解決哪些問題?
## [課後測驗](https://ff-quizzes.netlify.app/en/ml/)
## 回顧與自學
在應用聚類算法之前,正如我們所學,了解數據集的性質是一個好主意。閱讀更多相關內容:[這裡](https://www.kdnuggets.com/2019/10/right-clustering-algorithm.html)
[這篇有幫助的文章](https://www.freecodecamp.org/news/8-clustering-algorithms-in-machine-learning-that-all-data-scientists-should-know/) 介紹了不同聚類算法在不同數據形狀下的行為。
## 作業
[研究其他聚類的可視化方法](assignment.md)
---
**免責聲明**
本文件使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對於因使用此翻譯而產生的任何誤解或錯誤解讀概不負責。

@ -0,0 +1,16 @@
# 研究其他用於分群的視覺化方法
## 說明
在本課程中,你已經學習了一些視覺化技術,以便在進行分群之前更好地繪製數據。散佈圖特別有助於尋找物件群組。請研究不同的方法和不同的函式庫來創建散佈圖,並將你的研究記錄在筆記本中。你可以使用本課程的數據、其他課程的數據,或自行尋找的數據(請在筆記本中標註其來源)。使用散佈圖繪製一些數據,並解釋你發現了什麼。
## 評分標準
| 評分標準 | 優秀 | 合格 | 需要改進 |
| -------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------- | ----------------------------------- |
| | 提交了一個包含五個詳細記錄的散佈圖的筆記本 | 提交了一個包含少於五個散佈圖且記錄不夠詳細的筆記本 | 提交了一個不完整的筆記本 |
---
**免責聲明**
本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。

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

Loading…
Cancel
Save