# Python機器學習、深度學習 #2
## 資料的前處理
* 在把資料丟進模型之前,我們通常要對資料進行一些預處理,因為機器學習的資料量通常很大,事前做一些整理或運算可以增快訓練的成效或速度,也可以讓人更直觀的去看資料的特性。而要如何處理則要根據資料的特性去決定。
## 數值資料中常見的預處理
### Normalizing(正規化)
* 重新定義數字範圍,並將資料縮放或位移。
* 常見的縮放是縮放至`0~1`或是`-1~1`。
* 幾種正規化的方法:
* scaling to a range
* 修正資料範圍用,其分布不變。
* $x'=(x-x_{min})/(x_{max}-x_{min})$
* clipping
* 當出現極端特徵時可過濾掉。
* if x > n then x = n
* log scaling
* 當特徵有次方關係時可使用。
* $x'=log(x)$
* z-score
* 當特徵**沒有**極端值時使用。
* $x'=(x-\mu)/\sigma$
### Bucketing(桶分類)
* 當你不希望資料有浮點數出現時,可以使用Bucketing的技巧。
* 所謂Bucketing就是將資料分區塊,落在該區塊的資料統一視為平均值。
* 如:40~50的資料都當作45。
#### Buckets with equally spaced boundaries
* 分區的時候將每個桶子大小都切成一樣的,純粹將資料做一個壓縮的概念。
* 如:老師將成績分為100\~90分、90\~80分...
#### Buckets with quantile boundaries
* 根據資料特性或人數而去定義不同的桶子大小。
* 如:0\~16視為小孩、16\~60視為青年、60以上視為老人等。
## 資料的轉換
* 當資料中有非數值化的特徵時,我們可能要事先將資料做轉換,好讓模型可以有效訓練。
* 舉個例子,現在有個花朵相關的資料集,裡面有特徵欄位長這樣...
| ID | Color |
| -------- | -------- |
| ... | ... |
|80|Yellow|
|81|Blue|
|82|Red|
* 我們可以先將這些字串做一個一對一的轉換,變成下面這樣...
| ID | Color |
| -------- | -------- |
| ... | ... |
|80|1|
|81|2|
|82|3|
* 然後可以進一步表示成**One-hot encoding**的格式,可以套用到輸出時的機率表示...
| ID | Color |
| -------- | -------- |
| ... | ... |
|80|{[1.0],[0.0],[0.0]...}|
|81|{[0.0],[1.0],[0.0]...}|
|82|{[0.0],[0.0],[1.0]...}|
* 如此一來就可以將非數值的資料,轉換為數值,更方便訓練。
## Linear Regression
* 基本上機器學習能分類成三類:
1. 分類
2. 回歸
3. 分群
* 現在就來介紹回歸方法中的線性回歸法。
* 
* 線性回歸的目標就是在一群資料(上圖黑點)中找到一條線(上圖藍線),盡可能讓每個點都離這條線越近越好。
* 找到線之後,將來如果給定特徵`X`,就可以對照線找到標籤`y`,達到預測的效果。
### 模型架構
$score = \begin{bmatrix}
\theta_{0,0} &\theta_{1,0} &\theta_{2,0} \\
\theta_{1,0} &\theta_{1,1} &\theta_{2,1} \\
\theta_{2,0} &\theta_{1,2} & \theta_{2,2}
\end{bmatrix}
*
\begin{bmatrix}
X_0 \\ X_1 \\X_2
\end{bmatrix}
+
\begin{bmatrix}
b_0 \\ b_1 \\b_2
\end{bmatrix}$
* $\theta$: 每個特徵的權重。
* $X$: 特徵。
* $b$: 偏差常數。
* 也可以將式子簡單表示為:$y=h(x;\theta)+\epsilon$
### 訓練方法
* 要找到這條線,其實就像解工程數學中的最佳化問題,可以用兩種方法解。
#### Analytical
* 第一種解法就是直接用公式$\theta=(X^TX)^{-1}X^Ty$。
* 雖然看起來很完美,可以一步直接解出答案,但是矩陣的運算是十分耗時的!
* 尤其上面的公式需要解反矩陣,複雜度為$O(n^3)$。
* 基本上這種等級的複雜度,維度稍微大一點就爆了,因此需要下面的逼近法。
#### Gradient Descent
* 逼近法其實方法有很多種,這邊就簡單介紹一個**牛頓法**。
* 牛頓法是利用斜率去得到方向,逼近目標點。如果誤差值夠小就停下,否則繼續逼近。
* 需要注意的是步伐大小太大會跳過頭,太小會跑很久。
* 公式:$X_{n+1}=X_n-\frac{f(X_n)}{f'(X_n)}$
* ※補充資料-常用的誤差值計算方法:Loss Design:$\frac{1}{2}\sum_{i=1}^{n}(\theta^Tx_i-y_i)^2$
### 優點和缺點
#### 優點
* 訓練快速
* 執行快速
* 只需要儲存訓練好的模型,不需要留下訓練用的資料(空間不用太大)
#### 缺點
* 訓練資料必須獨立,不能彼此影響
* 線性的結果有極限
---
- 針對最後一點,來張圖解釋。

- 今天如果資料像這樣,我們看的出來應該用sin的樣子去表示這個資料,但是你如果用LR去做模型,不管怎麼拉線都無法完美的表示的每個地方。
- 那麼...該怎麼辦呢?
### 改變模型,提高維度
$score = \begin{bmatrix}
\theta_{0,0}^0 &\theta_{1,0}^1 &\theta_{2,0}^2 \\
\theta_{1,0}^0 &\theta_{1,1}^1 &\theta_{2,1}^2 \\
\theta_{2,0}^0 &\theta_{1,2}^1 & \theta_{2,2}^2
\end{bmatrix}
*
\begin{bmatrix}
X_0 \\ X_1 \\X_2
\end{bmatrix}
+
\begin{bmatrix}
b_0 \\ b_1 \\b_2
\end{bmatrix}$
* 其實只要如上方表示,稍微改一下權重的部分就可以將模型變為高維度的樣子。
* 更細節的部分會在之後討論...
* 這邊先給個觀念:維度越大越好?
- 首先,維度越大訓練越慢,這應該沒有問題。
- 再來,雖然維度越大可以讓曲線越複雜,更貼合資料點,但是請看看下圖

> 圖片來源:https://scikit-learn.org/stable/auto_examples/model_selection/plot_underfitting_overfitting.html
- 當維度大到變成第三張圖的時候,雖然每個點幾乎都完美貼合,但是圖形在其他地方嚴重扭曲,進而造成後面的判別有問題。
- 這種現象我們叫做**overfitting**,後續可能會更詳細的說明,現在只要知道維度絕對不是越大越好。
## 線性回歸實戰練習
* Code
```python=1
from sklearn.datasets import load_iris
iris = load_iris()
X = iris['data']
y = iris['target']
features = iris.feature_names
print("---Dataset Data--- \n")
print("Data Shape : ",X.shape)
for index,f in enumerate(X[:3]):
print(index + 1,"-> ",f)
print("\n---Dataset Content---\n")
for index,f in enumerate(features):
print(index + 1,"). ",f)
from sklearn import linear_model
from sklearn.metrics import mean_squared_error
train_num = int(X.shape[0] * 0.9)
x_train = X[:train_num]
y_train = y[:train_num]
x_test = X[train_num+1:]
y_test = y[train_num+1:]
print("Training Data Shape : ",x_train.shape)
print("Training Label Shape : ",y_train.shape)
print("Testing Data Shape : ",x_test.shape)
print("Testing Label Shape : ",y_test.shape)
reg = linear_model.LinearRegression()
reg.fit(x_train,y_train)
print('Coefficients: \n', reg.coef_)
print("Mean squared error: %.2f"
% mean_squared_error(reg.predict(x_test), y_test))
```
* Output
```
---Dataset Data---
Data Shape : (150, 4)
1 -> [5.1 3.5 1.4 0.2]
2 -> [4.9 3. 1.4 0.2]
3 -> [4.7 3.2 1.3 0.2]
---Dataset Content---
1 ). sepal length (cm)
2 ). sepal width (cm)
3 ). petal length (cm)
4 ). petal width (cm)
Training Data Shape : (135, 4)
Training Label Shape : (135,)
Testing Data Shape : (14, 4)
Testing Label Shape : (14,)
Coefficients:
[-0.10962032 -0.03634593 0.2507714 0.53522511]
Mean squared error: 0.06
```
* 因為最近有點忙,就將上周的code稍微改一下拿來用了。
* 理論上有空之後該部分都會修正得更好,包含上周的部分。
###### tags: `ML/DL` `note` `python`