機器學習實作步驟
第一階段: 訓練評估
- 載入訓練資料 : 準備好要餵給機器人的資料→教材
- 處理資料(Pre-processing):資料可能會有缺失、錯誤、雜訊等,需要預先處理再餵給機器人
- 特徵抽取(Feature Extraction):
- 資料轉換 : 文字轉成二進位
- 去除雜訊
- 切割訓練 / 測試資料: 資料不能全部拿來教,要拿一部分出來考試,確保他真的學會。
常見比例: 80/20,70/30
- 選擇演算法 / 建立模型 / 開始訓練:
什麼是Model?
學生的大腦: 裡面記錄他從資料學到的規律
- 常見的機器學習模型
- 線性回歸(Linear Regression): 根據過去資料,找出一條最適合的直線來預測未來。
透過機器學習找到最好的斜率和截距
y=b+wx
- 決策樹(Decision Tree):不斷問問題,把資料一步一步分類,最後得到答案。
天氣 = 晴天
↓
假日 = 是
↓
出去玩 = 是
結果→出去玩
- SVM: 畫最佳分類線,如果畫不出來,就升維
- 神經網路:模仿人腦神經元。
- 訓練: 把訓練資料丟給模型學習
- 使用測試資料驗證結果: 考試時間
- 使用陌生資料驗證模型: 訓練時,拿家裡養的貓,現在拿網站抓的貓,如果判斷正確,代表模型真的學會了,如果變60%,有可能是因為模型背答案了。
- 儲存模型 / 發布模型 : 將訓練完成的大腦儲存起來
第二階段: 上線階段(推導/ 推理)
- 服務端載入模型: 將已經訓練好的模型上線提供服務,已經可以回答問題。
- 使用者呼叫模型功能
圖解流程:
資料收集
↓
資料前處理
↓
切分資料
↓
模型訓練
↓
模型評估
↓
儲存模型
↓
=================
上線 {color=“gray_bg”}
=================
↓
載入模型
↓
使用者輸入
↓
模型推論
↓
回傳結果
認識ScikitLearn
| 功能 |
工具 |
解釋 |
實際例子 |
| 切割資料 |
`train_test_split()` |
把資料分成訓練集和測試集,避免模型只會背答案 |
1000筆房價資料 → 800筆訓練、200筆測試 |
| 資料標準化 |
`StandardScaler()` |
把不同尺度的資料拉到相近範圍 |
月薪 50000、年齡 25,數值差太大會影響模型 |
| 線性迴歸 |
`LinearRegression()` |
根據已知資料找出數值之間的關係,用來預測連續數值 |
根據坪數預測房價 |
| 決策樹 |
`DecisionTreeClassifier()` |
像問答樹一樣逐步判斷 |
收入 \> 5萬?→ 是 → 可能購買保險 |
| 隨機森林 |
`RandomForestClassifier()` |
多棵決策樹一起投票決定答案 |
100棵樹中有80棵認為是「貓」,結果就是貓 |
| SVM |
`SVC()` |
找出最佳分類界線 |
將貓和狗的特徵分開 |
| 分群 |
`KMeans()` |
自動把相似資料分組 |
將會員分成學生族群、上班族群、高消費族群 |
| 模型評估 |
`accuracy_score()` |
計算預測準確率 |
100題答對95題 → 準確率95% |
# **Scikit-Learn 的三大核心元件**
| 元件 |
作用 |
常見函數 |
生活例子 |
| Transformer |
資料加工 |
fit()、transform()、fit_transform() |
洗菜、切菜 |
| Estimator |
學習資料規律 |
fit() |
廚師學習食譜 |
| Predictor |
預測結果 |
predict()、score() |
根據食譜做菜 |
原始資料
↓
Transformer(加工資料)
↓
Estimator(學習規律)
↓
Predictor(預測答案)
假設我們要做一個「房價預測模型」。
原始資料:
| 坪數 |
房價(萬) |
| 20 |
800 |
| 30 |
1200 |
| 40 |
1600 |
| 50 |
2000 |
---
| 函數 |
功能 |
舉例 |
執行後結果 |
| `fit()` |
學習資料規律 |
`model.fit(X_train, y_train)` |
模型學到「坪數越大,房價越高」 |
| `transform()` |
套用規律轉換資料 |
`scaler.transform(X_test)` |
把測試資料依照之前學到的標準化規則轉換 |
| `fit_transform()` |
先學習再轉換 |
`scaler.fit_transform(X_train)` |
計算平均值、標準差,並立即完成標準化 |
| `predict()` |
預測結果 |
`model.predict([[35]])` |
預測 35 坪房價約 1400 萬 |
| `score()` |
評估模型 |
`model.score(X_test, y_test)` |
回傳模型準確度或 R² 分數 |
| 套件 |
處理對象 |
功能 |
代表工具 |
| Scikit-Learn |
表格資料 |
機器學習 |
Random Forest |
| Scikit-Image |
圖片 |
影像處理 |
Segmentation |
| Scikit-Optimize |
模型參數 |
自動調參 |
Bayesian Optimization |
## Scikit-Learn 優點與缺點
| 類別 |
項目 |
說明 |
實際例子 |
| ✅ 優點 |
開源免費(BSD License) |
使用限制少,可自由用於學習、研究及商業用途 |
公司開發房價預測系統時可直接使用,不需付授權費 |
| ✅ 優點 |
容易學習與使用 |
API 設計統一,大部分模型使用方式相同 |
`LinearRegression()`、`RandomForestClassifier()` 都使用 `fit()` 和 `predict()` |
| ✅ 優點 |
解決實際問題 |
提供大量機器學習演算法 |
客戶流失預測、垃圾郵件分類、房價預測 |
| ✅ 優點 |
大型企業支持 |
由眾多企業及開發者共同維護 |
包括 Microsoft、Intel、NVIDIA 等 |
| ✅ 優點 |
文件完整 |
官方文件、教學、範例豐富 |
遇到問題通常都能找到範例程式 |
| ✅ 優點 |
演算法豐富 |
提供分類、迴歸、分群、降維等功能 |
SVM、Random Forest、K-Means、PCA |
| ❌ 缺點 |
不適合深度學習 |
無法建立複雜神經網路模型 |
CNN、RNN、Transformer 需使用 TensorFlow 或 PyTorch |
| ❌ 缺點 |
不支援 Model Serving |
不提供模型部署服務 |
無法直接讓使用者透過網站呼叫模型 |
## Scikit-Learn vs TensorFlow
| 項目 |
Scikit-Learn |
TensorFlow |
| 類型 |
機器學習(Machine Learning) |
深度學習(Deep Learning) |
| 學習難度 |
⭐⭐ 簡單 |
⭐⭐⭐⭐ 較難 |
| 程式碼量 |
少 |
較多 |
| 適合新手 |
✅ |
⚠️ |
| GPU加速 |
不強調 |
✅ 支援 |
| 神經網路 |
基本支援(MLP) |
✅ 強大支援 |
| 圖片辨識 |
小型專案可用 |
✅ 非常適合 |
| 語音辨識 |
較少使用 |
✅ |
| ChatGPT類模型 |
❌ |
✅ |
| 訓練速度 |
快 |
視模型而定 |
| 部署大型AI模型 |
❌ |
✅ |
## Scikit-Learn 支援的演算法整理
### 1. Classification(分類)
> 預測資料屬於哪一個類別
| 項目 |
說明 |
| 功能 |
將資料分類到特定類別 |
| 輸出結果 |
類別(Label) |
| 常見應用 |
垃圾郵件判斷、疾病診斷、客戶是否流失 |
| 生活例子 |
判斷 Email 是「垃圾郵件」還是「正常郵件」 |
| 常見演算法 |
SVC、KNN(Nearest Neighbor)、Random Forest、Decision Tree |
### 範例
| 郵件內容 |
分類結果 |
| 免費領獎金 |
垃圾郵件 |
| 公司會議通知 |
正常郵件 |
---
### 2. Clustering(分群)
> 將相似的資料自動分成群組
| 項目 |
說明 |
| 功能 |
找出資料間的相似性並分群 |
| 輸出結果 |
群組編號 |
| 常見應用 |
客戶分群、市場分析、推薦系統 |
| 生活例子 |
將購物網站會員分成不同消費族群 |
| 常見演算法 |
K-Means、Spectral Clustering、Mean Shift、GMM |
### 範例
| 客戶 |
年消費金額 |
分群結果 |
| A |
2,000 |
群組1 |
| B |
2,500 |
群組1 |
| C |
50,000 |
群組2 |
| D |
60,000 |
群組2 |
---
### 3. Regression(迴歸)
> 預測一個連續數值
| 項目 |
說明 |
| 功能 |
預測數值 |
| 輸出結果 |
數字 |
| 常見應用 |
房價預測、股價預測、銷售額預測 |
| 生活例子 |
根據坪數預測房價 |
| 常見演算法 |
Linear Regression、SVR、Ridge Regression、Lasso Regression |
### 範例
| 坪數 |
預測房價 |
| 20坪 |
800萬 |
| 30坪 |
1200萬 |
| 40坪 |
1600萬 |
---
## 4. Multi-Layer Perceptron(MLP)
> Scikit-Learn 內建的神經網路
| 項目 |
說明 |
| 功能 |
模擬神經網路進行學習 |
| 類型 |
深度學習入門版 |
| 常見應用 |
分類、迴歸 |
| 優點 |
使用簡單 |
| 缺點 |
不適合大型深度學習專案 |
### 相關模型
| 模型 |
用途 |
| MLPClassifier |
分類 |
| MLPRegressor |
數值預測 |
| BernoulliRBM |
特徵學習 |
### 範例
```plain text
fromsklearn.neural_networkimportMLPClassifier
model=MLPClassifier()
---
## 5. Dimensionality Reduction(降維)
> 減少特徵數量,提高訓練效率
<table header-row="true">
<tr>
<td>項目</td>
<td>說明</td>
</tr>
<tr>
<td>功能</td>
<td>刪除不重要特徵</td>
</tr>
<tr>
<td>目的</td>
<td>降低運算量、避免過擬合</td>
</tr>
<tr>
<td>常見應用</td>
<td>視覺化、大數據分析</td>
</tr>
<tr>
<td>生活例子</td>
<td>履歷有100項資訊,只保留最重要10項</td>
</tr>
</table>
### 常見演算法
<table header-row="true">
<tr>
<td>演算法</td>
<td>功能</td>
</tr>
<tr>
<td>PCA</td>
<td>主成分分析</td>
</tr>
<tr>
<td>Feature Selection</td>
<td>特徵選擇</td>
</tr>
<tr>
<td>NMF</td>
<td>非負矩陣分解</td>
</tr>
</table>
### 範例
原始資料:
特徵數
---
100個欄位
---
降維後:
特徵數
---
10個欄位
---
---
## 6. Model Selection(模型選擇)
> 找出最佳模型與最佳參數
<table header-row="true">
<tr>
<td>項目</td>
<td>說明</td>
</tr>
<tr>
<td>功能</td>
<td>比較模型效果</td>
</tr>
<tr>
<td>目的</td>
<td>找到最佳參數組合</td>
</tr>
<tr>
<td>常見應用</td>
<td>調整 Random Forest、SVM 參數</td>
</tr>
<tr>
<td>生活例子</td>
<td>找出考試成績最好的讀書方法</td>
</tr>
</table>
### 常見工具
<table header-row="true">
<tr>
<td>工具</td>
<td>功能</td>
</tr>
<tr>
<td>GridSearchCV</td>
<td>暴力搜尋最佳參數</td>
</tr>
<tr>
<td>RandomizedSearchCV</td>
<td>隨機搜尋最佳參數</td>
</tr>
<tr>
<td>Cross Validation</td>
<td>交叉驗證</td>
</tr>
<tr>
<td>Metrics</td>
<td>評估模型表現</td>
</tr>
</table>
### 範例
Random Forest:
```plain text
RandomForestClassifier(
n_estimators=100
)
GridSearchCV 自動測試:
50棵樹
100棵樹
200棵樹
300棵樹
最後找出最佳組合。
7. Preprocessing(資料前處理)
將資料整理成模型容易學習的格式
| 項目 |
說明 |
| 功能 |
清理、轉換、標準化資料 |
| 目的 |
提高模型效果 |
| 常見應用 |
資料清理、特徵抽取 |
| 生活例子 |
將文字轉成數字 |
### 常見工具
| 工具 |
功能 |
| StandardScaler |
標準化 |
| MinMaxScaler |
正規化 |
| LabelEncoder |
文字轉數字 |
| OneHotEncoder |
類別編碼 |
| Feature Extraction |
特徵抽取 |
### 範例
原始資料:
性別
---
男
---
女
---
男
---
轉換後:
性別
---
0
---
1
---
0
---
## Encoder(類別資料編碼)總整理
| 項目 |
LabelEncoder |
OneHotEncoder |
OrdinalEncoder |
Learned Embedding |
| **定義** |
每個類別給一個數字編號 |
每個類別拆成獨立欄位 |
將有順序的類別轉成數字 |
用神經網路學習類別向量 |
| **主要用途** |
分類標籤(y) |
類別特徵(X) |
有順序的類別資料 |
深度學習、NLP |
| **輸出形式** |
單一數字 |
多個0/1欄位 |
單一數字 |
多維向量 |
| **是否保留順序** |
❌(可能誤判) |
❌ |
✅ |
自動學習 |
| **Scikit-Learn支援** |
✅ |
✅ |
✅ |
❌ |
| **TensorFlow/PyTorch支援** |
❌ |
❌ |
❌ |
✅ |
# LabelEncoder
| 項目 |
內容 |
| 定義 |
將每個類別直接轉換成數字 |
| 解釋 |
系統自動建立類別與數字對照表 |
| 原始資料 |
台灣、日本、美國 |
| 轉換結果 |
0、1、2 |
### 範例
### 優點
| 優點 |
說明 |
| 簡單 |
一行程式即可完成 |
| 快速 |
運算速度快 |
| 節省空間 |
不增加欄位數 |
### 缺點
| 缺點 |
說明 |
| 產生假順序 |
美國(2) \> 日本(1) \> 台灣(0) |
| 容易誤導模型 |
模型誤認數字大小有意義 |
### 適用情境
| 資料 |
適用 |
| 分類標籤(y) |
✅ |
| 國家 |
❌ |
| 品牌 |
❌ |
| 顏色 |
❌ |
---
# OneHotEncoder
| 項目 |
內容 |
| 定義 |
將每個類別拆成獨立欄位 |
| 解釋 |
使用 0 和 1 表示是否屬於該類別 |
| 原始資料 |
台灣、日本、美國 |
| 轉換結果 |
三個新欄位 |
### 範例
| 國家 |
台灣 |
日本 |
美國 |
| 台灣 |
1 |
0 |
0 |
| 日本 |
0 |
1 |
0 |
| 美國 |
0 |
0 |
1 |
### 優點
| 優點 |
說明 |
| 不產生順序 |
類別彼此平等 |
| 預測效果佳 |
多數機器學習模型適用 |
| 最常使用 |
業界標準做法 |
### 缺點
| 缺點 |
說明 |
| 欄位爆炸 |
類別越多欄位越多 |
| 記憶體增加 |
大型資料集耗資源 |
### 適用情境
| 資料 |
適用 |
| 性別 |
✅ |
| 國家 |
✅ |
| 品牌 |
✅ |
| 顏色 |
✅ |
| 學歷 |
❌ |
---
# OrdinalEncoder
| 項目 |
內容 |
| 定義 |
將有順序的類別轉換成數字 |
| 解釋 |
保留類別之間的高低順序 |
| 原始資料 |
高中、大學、碩士、博士 |
| 轉換結果 |
0、1、2、3 |
### 範例
| 學歷 |
編碼後 |
| 高中 |
0 |
| 大學 |
1 |
| 碩士 |
2 |
| 博士 |
3 |
### 優點
| 優點 |
說明 |
| 保留順序 |
符合實際意義 |
| 不增加欄位 |
仍維持單一欄位 |
| 記憶體需求低 |
比 One-Hot 小很多 |
### 缺點
| 缺點 |
說明 |
| 不適合無順序資料 |
國家、品牌、顏色 |
| 容易造成誤判 |
若類別本身沒有大小關係 |
### 適用情境
| 資料 |
適用 |
| 學歷 |
✅ |
| 員工績效 |
✅ |
| 會員等級 |
✅ |
| 國家 |
❌ |
| 顏色 |
❌ |
---
# Learned Embedding
| 項目 |
內容 |
| 定義 |
使用神經網路自動學習向量表示 |
| 解釋 |
將類別轉成高維向量 |
| 使用框架 |
TensorFlow、PyTorch |
| 使用領域 |
NLP、推薦系統、LLM |
### 範例
| 類別 |
Embedding向量 |
| 台灣 |
\[0.21, 0.66, 0.38\] |
| 日本 |
\[0.24, 0.61, 0.40\] |
| 美國 |
\[-0.12, 0.90, 0.55\] |
### 優點
| 優點 |
說明 |
| 可表示類別關係 |
台灣與日本較接近 |
| 適合大量類別 |
商品、使用者、單字 |
| 記憶體較省 |
比 One-Hot 更有效率 |
| 深度學習必備 |
ChatGPT、BERT 都使用 |
### 缺點
| 缺點 |
說明 |
| 需大量資料 |
小資料集效果差 |
| 較難解釋 |
向量意義不直觀 |
| 需深度學習框架 |
TensorFlow 或 PyTorch |
使用Encoder處理Categorical欄位
程式目的
| 功能 |
說明 |
| 讀取 Excel |
將 Excel 資料載入 DataFrame |
| LabelEncoder |
將單一類別欄位轉換成數字 |
| OrdinalEncoder |
將多個類別欄位轉換成數字 |
| OneHotEncoder |
將類別拆成多個 0/1 欄位 |
| get_dummies |
Pandas版本的 One-Hot Encoding |
| LabelBinarizer |
二元分類編碼工具 |
---
## 原始資料範例
假設 Excel.xlsx:
| Name |
Age |
Gender |
JobTitle |
| Tom |
30 |
Male |
Engineer |
| Amy |
25 |
Female |
Manager |
| John |
35 |
Male |
Engineer |
語法補充解釋
機器學習專案最常見流程
| 步驟 |
程式 |
| 1. 找檔案路徑 |
`data_path = os.path.join(currdir,'Datasets','Excel.xlsx')` |
| 2. 讀取資料 |
`df = pd.read_excel(data_path)` |
| 3. 檢查資料 |
`df.head()`、`df.info()` |
| 4. 清理資料 |
`df.dropna()` |
| 5. 特徵工程 |
`LabelEncoder()`、資料轉換 |
| 6. 訓練模型 |
`model.fit(X, y)` |
| 7. 預測 |
`model.predict(X_test)` |
| 8. 儲存結果 |
`df.to_csv('result.csv')` |
路徑處理:
| 函式 |
功能 |
範例 |
| `os.path.join()` |
組合路徑 |
`os.path.join('Data','test.csv')` |
| `os.getcwd()` |
取得目前工作目錄 |
`os.getcwd()` |
| `os.path.dirname(__file__)` |
取得目前 `.py` 所在資料夾 |
`os.path.dirname(__file__)` |
| `os.path.exists()` |
檢查檔案或資料夾是否存在 |
`os.path.exists('data.csv')` |
| `os.path.getsize()` |
取得檔案大小(Byte) |
`os.path.getsize('data.csv')` |
檔案操作
| 類別 |
函式 |
功能 |
範例 |
| 讀取檔案 |
`open(..., 'r')` |
讀取文字檔 |
`open('test.txt','r')` |
| 讀取 Excel |
`pd.read_excel()` |
讀取 Excel 檔案 |
`pd.read_excel('data.xlsx')` |
| 讀取 CSV |
`pd.read_csv()` |
讀取 CSV 檔案 |
`pd.read_csv('data.csv')` |
| 讀取 JSON |
`pd.read_json()` |
讀取 JSON 檔案 |
`pd.read_json('data.json')` |
| 寫入檔案 |
`open(..., 'w')` |
建立或覆蓋檔案 |
`open('test.txt','w')` |
| 追加內容 |
`open(..., 'a')` |
在檔案尾端新增內容 |
`open('test.txt','a')` |
| 儲存 Excel |
`df.to_excel()` |
將 DataFrame 存成 Excel |
`df.to_excel('result.xlsx')` |
| 儲存 CSV |
`df.to_csv()` |
將 DataFrame 存成 CSV |
`df.to_csv('result.csv')` |
| 儲存 JSON |
`df.to_json()` |
將 DataFrame 存成 JSON |
`df.to_json('result.json')` |
| 儲存資料庫 |
`df.to_sql()` |
將資料存入資料庫 |
`df.to_sql('Staff', conn)` |
資料夾操作
| 函式 |
功能 |
範例 |
| `os.listdir()` |
查看資料夾內容 |
`os.listdir('Datasets')` |
| `os.mkdir()` |
建立單層資料夾 |
`os.mkdir('Results')` |
| `os.makedirs()` |
建立多層資料夾 |
`os.makedirs('Result/2026/June')` |
| `os.rmdir()` |
刪除空資料夾 |
`os.rmdir('Results')` |
檔案管理
| 函式 |
功能 |
範例 |
| `os.remove()` |
刪除檔案 |
`os.remove('test.txt')` |
| `os.rename()` |
重新命名 |
`os.rename('old.txt','new.txt')` |
| `shutil.copy()` |
複製檔案 |
`shutil.copy('a.txt','b.txt')` |
| `shutil.move()` |
移動檔案 |
`shutil.move('a.txt','backup/a.txt')` |
Pandas DataFrame 常用操作
| 函式 |
功能 |
範例 |
| `df.head()` |
查看前 5 筆資料 |
`df.head()` |
| `df.tail()` |
查看後 5 筆資料 |
`df.tail()` |
| `df.shape` |
查看資料維度 |
`df.shape` |
| `df.columns` |
查看欄位名稱 |
`df.columns` |
| `df.info()` |
查看資料型態與缺失值 |
`df.info()` |
| `df.describe()` |
查看統計資訊 |
`df.describe()` |
| `df.dropna()` |
刪除缺失值 |
`df.dropna()` |
| `df.fillna()` |
填補缺失值 |
`df.fillna(0)` |
| `df.sort_values()` |
排序資料 |
`df.sort_values('年齡')` |
| `df.groupby()` |
分組統計 |
`df.groupby('部門').mean()` |
```python
#Learning embeddings for your machine learning model
#https://medium.com/spikelab/learning-embeddings-for-your-machine-learning-model-a6cb4bc6542e
#Categorical Embedding and Transfer Learning
#https://towardsdatascience.com/categorical-embedding-and-transfer-learning-dd3c4af6345d
#載入套件
import pandas as pd
from sklearn.preprocessing import LabelEncoder
import os
#取得excel路徑 file代表現在正在執行的.py檔案位置
currdir=os.path.dirname(file)
#將Excel檔案的路徑加進去 用 join
data_path=os.path.join(currdir, ‘Datasets’, ‘Excel.xlsx’)
#讀取Excel檔的工作表1
df=pd.read_excel(data_path, sheet_name=‘工作表1’)
print(df)
我的excel dataframe
ID Name Gender JobTitle Salary Age
0 1 John Male Manager 35000 30
1 2 Mary Female Sales 40000 40
2 3 Jack Male President 50000 50
ID Name Gender JobTitle Salary Age
0 1 John 1 Manager 35000 30
1 2 Mary 0 Sales 40000 40
2 3 Jack 1 President 50000 50
#LabelEncoder 編碼器
le = LabelEncoder()
先le.fit(df.Gender) 學習資料內容 [‘Female’,‘Male’]
df.Gender=le.fit_transform(df.Gender)
#df=df.apply(LabelEncoder().fit_transform) # encode所有欄位
print(df)
#===============
from sklearn.preprocessing import OrdinalEncoder
from sklearn.compose import ColumnTransformer
對 Gender 與 JobTitle 使用 OrdinalEncoder
encoder = ColumnTransformer(
裡面再包一個tuple來存放規則
transformers=[
(
‘ordinal’, OrdinalEncoder(), [‘Gender’, ‘JobTitle’],
)
])
df.iloc[第幾列, 第幾欄]
取出工作表的前兩欄 ID, Salary
df1=df.iloc[:, 0:2]
對工作表1的[‘Gender’, ‘JobTitle’]兩個欄位做轉換
result會回傳<class ‘numpy.ndarray’> 不是DataFrame
result=encoder.fit_transform(df) #內含LabelEncoder的ColumnTransformer無法處理多個欄位
把result的array轉成DataFrame
df2=pd.DataFrame(result, columns=[‘Gender’, ‘JobTitle’], dtype=int)
print(df2)
合併表格
df=pd.concat([df1, df2], axis=1)
print(df)
#=======================
from sklearn.preprocessing import OneHotEncoder
#one-hot encoder
encoder = ColumnTransformer(
transformers=[
(‘Gender’, OneHotEncoder(), [‘Gender’])])
onehotgender = encoder.fit_transform(df)
onehotgender=pd.DataFrame(onehotgender, columns=[‘Gender_Female’,‘Gender_Male’], dtype=int)
df = pd.concat([df, onehotgender], axis=1).drop([‘Gender’], axis=1)
print(df)
#Pandas get_dummies
df1=df.iloc[:, 0:2]
print(df1)
df2=pd.get_dummies(df.Gender)
print(df2)
df=pd.concat([df1, df2], axis=1)
print(df)
df=df.rename(columns = {‘Female’:‘Gender_Female’, ‘Male’:‘Gender_Male’})
print(df)
#LabelBinarizer
from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
print(encoder.fit_transform(df.Gender))
df.Gender=encoder.fit_transform(df.Gender)
print(df)
#OrdinalEncoder
from sklearn.preprocessing import OrdinalEncoder
encoder = OrdinalEncoder()
df=encoder.fit_transform(df)
print(df)
<table header-row="true">
<tr>
<td>方法</td>
<td>結果</td>
<td>適用情況</td>
</tr>
<tr>
<td>LabelEncoder</td>
<td>Male→1 Female→0</td>
<td>二元類別</td>
</tr>
<tr>
<td>OrdinalEncoder</td>
<td>類別→整數</td>
<td>多個類別欄位</td>
</tr>
<tr>
<td>OneHotEncoder</td>
<td>變成多個0/1欄位</td>
<td>最常用</td>
</tr>
<tr>
<td>get_dummies</td>
<td>OneHot簡易版</td>
<td>Pandas快速處理</td>
</tr>
<tr>
<td>LabelBinarizer</td>
<td>二元分類</td>
<td>Gender、Yes/No</td>
</tr>
<tr>
<td>Embedding</td>
<td>轉成向量</td>
<td>深度學習、TensorFlow</td>
</tr>
</table>
程式流程
Pokemon.csv<br>↓<br>讀取資料<br>↓<br>LabelEncoder<br>↓<br>Fire → 6<br>Water → 15<br>Grass → 8<br>...<br>↓<br>Embedding Layer<br>↓<br>轉成向量<br>↓<br>利用 Total 能力值訓練<br>↓<br>得到 Pokemon Type 的特徵向量<br>↓<br>3D視覺化
```python
#載入套件
import numpy as np
import pandas as pd
import os
# 取得檔案路徑 組裝路徑 讀取檔案
currdir=os.path.dirname(__file__)
data_path=os.path.join(currdir, 'Datasets', 'Pokemon.csv')
df = pd.read_csv(data_path)
# drop刪除欄位 ( 要刪除的欄位, 要刪除欄還是列, inplace=True直接修改原資料)
# axis = 0 修改資料列, axis = 1 修改資料欄
df.drop(labels="#", axis=1, inplace=True)
# fillna填補空值 axis = 0 往下填,axis = 1 往右填
df.fillna(value="No Type", axis=1, inplace=True)
# rename更改欄位名稱 {'舊名稱':'新名稱'} axis=1 更改欄位 axis=0 更改列
df.rename({'Type 1': 'type'}, inplace=True, axis=1)
print(df)
# nunique = Number of Unique計算不重複值的個數
n_types = df['type'].nunique()
print("We have:",n_types, "differents pokemons types")
from sklearn.preprocessing import LabelEncoder, MinMaxScaler
encoder = LabelEncoder()
# 建立一個 Min-Max 標準化工具,準備把數值資料縮放到 0 到 1 的範圍。
scaler = MinMaxScaler()
df['encoded_type'] = encoder.fit_transform(df['type'])
df['scaled_total'] = scaler.fit_transform(df[['Total']])
types = df['encoded_type']
total = df['scaled_total']
# Embedding = 把類別資料轉換成有意義的數字向量。
# 先計算類別數的一半(無條件進位),作為 Embedding 維度
# 如果超過 50,就限制在 50。這是一個常見的經驗法則,用來避免 Embedding 維度過大造成模型參數浪費。
embedding_size = min(np.ceil((n_types)/2),50) #Jeremy Howard suggest
from keras.models import Sequential #建模型
from keras.layers import Dense, Embedding, Flatten #往模型裡面加東西
# 建立一個 空的 神經網路模型(Neural Network Model)。
model = Sequential()
# Embedding Layer
model.add(Embedding(input_dim=n_types,output_dim=int(embedding_size), input_length=1, name="poke_embedding"))
# 將二維的矩陣攤平成一維的
model.add(Flatten())
#Dense = Fully Connected Layer(全連接層)的隱藏層
# 第一層先找到特徵
model.add(Dense(30, activation="relu"))
# 再拼湊特徵
model.add(Dense(15, activation="relu"))
# 最後輸出
model.add(Dense(1, activation="linear"))
#告訴神經網路使用 Adam 演算法來調整權重,並使用 MSE(均方誤差)來衡量預測與真實答案之間的差距。訓練時會不斷降低 MSE,讓模型預測得越來越準。
# compile編譯模型 告訴模型怎麼學?(optimizer) 怎麼判斷自己做得好不好?(loss)
# loss 損失函數 mse均方差 用均方差的方式量化誤差
# optimizer 優化器 adam梯度下降法
model.compile(optimizer="adam", loss="mse")
# 開始訓練模型(Train Model)
# 訓練模型30次 loss值如果越來越小代表我的正確率越來越高
model.fit(x=types.values, y=total.values, epochs=30)
# 取權重
# 取得poke_embedding的這一層
embedding_layer = model.get_layer(name="poke_embedding")
# 從上面取到的那一層emdedding layer物件 再從中取得他的權重也就是18*9的array
# 最後將array轉換成dataframe
embedding_df = pd.DataFrame(embedding_layer.get_weights()[0])
# 更改欄位名稱 方便閱讀
embedding_layer.columns = ['C1','C2','C3','C4','C5','C6','C7','C8','C9']
print(embedding_layer)
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d, Axes3D
# inverse_transform()把encoder轉換得到的數值再轉回原文字,最後放到list中
types_names = list(encoder.inverse_transform([x for x in range(0,n_types)]))
# 畫出一個三位的圖所以給定三個維度 雖然有九個維度 但人類可以看到的只有三維 所以取前三維來看
# 從 Embedding 向量中取出第 1、2、3 個維度,分別作為 X、Y、Z 座標,用來將 Pokémon 類別的 Embedding 視覺化成三維空間中的點。
xs = embedding_layer['C1'] -> 回傳值會是一個serise一維資料 也可用一直欄來理解
ys = embedding_layer['C2']
zs = embedding_layer['C3']
# plt.figure()建立一個空白畫布 尺寸寬8 高4 inch
fig = plt.figure(figsize=(8, 4))
#fig.add_subpolt() 在fig畫布上建立一個3d座標軸 111代表 1, 1, 1, 一列一欄第一個位置
ax = fig.add_subplot(111, projection='3d') -> # return Axes3D的物件
#逐一讀取每個 Pokémon 類型的 Embedding。
for index, embedding in embedding_layer.iterrows():
#取得該類型在 Embedding 空間中的三維座標。
x = embedding['C1']
y = embedding['C2']
z = embedding['C3']
# 在 3D 圖中畫出藍色點。
ax.scatter(x, y, z, color='b')
#在點旁邊標示:名稱
ax.text(x, y, z, '%s' % (types[index]), size=9, zorder=1, color='k')
#plt.draw()
plt.show()
