---
# System prepended metadata

title: 機器學習基本概念簡介（機器學習 2021）筆記
tags: [機器學習, 筆記]

---

# 機器學習基本概念簡介（機器學習 2021）筆記

[TOC]

機器學習：讓機器幫我們找一個函式來解決問題。  
（⇔ 傳統：我們寫出函式叫機器執行）

用來解決「解決問題的函式」會複雜到人寫不出來的問題。例如：

* 語音辨識
* 影像辨識
* ⋯⋯

![](https://hackmd.io/_uploads/SJQbYnKXh.png)
<small>https://youtu.be/Ye018rCVvOo?t=0</small>

## 基本步驟

以預測 YouTube 頻道觀看人數為例。

### 1. 選擇 Model － 寫出帶有未知參數的函式

![](https://hackmd.io/_uploads/rJSeO3Fm2.png)
<small>https://youtu.be/Ye018rCVvOo?t=650</small>

* 猜測：未來觀看人數跟過去觀看人數有關。
    * 好的猜測還自於對問題的了解 (domain knowledge)。

簡單的例子：未來某天的觀看人數 $y$，是過去某天的觀看人數 $x_1$ 乘上 $w$ 再加上 $b$，可以寫出一個 function：$y = b + wx_1$。

* Model 就是帶有未知參數的 funciton。
* Feature ($x_1$) 是 function 裡已知的東西。
* Weight ($w$)、bias ($b$) 是 unknown paramter。
    * Weight (權重) 是會跟 feature 做相乘的。
    * Bias (偏置) 是不會跟 feature 做相乘的，是加上去的。

### 2. 定義 Loss：一個用來評估 model 輸出的優劣的 function

* Loss ($L$) 是一個 function，輸入是 model 裡的參數 ($b$、$w$)，輸出是一個代表模型表現的數值。

![](https://hackmd.io/_uploads/rkhnRhtX3.png)
<small>https://youtu.be/Ye018rCVvOo?t=911</small>

舉例：

假設我們想計算 $L(0.5k, 1)$：也就是 $b$ 帶 $0.5k$，$w$ 帶 $1$ 的話，model 的表現有多好。

$$
y = 0.5k + 1x_1
$$

拿出訓練資料（過去真實的資料）來帶入，假設 2017/1/1 的觀看次數是 4.8K，帶入模型：$0.5k + 1 \times 5.3k$ 得到 $y = 5.3k$；但真實的資料顯示 1/2 的觀看次數是 4.9k ($\hat{y}$)，因此，預測出的結果與真實差距是 $e_1 = |y - \hat{y}| = 0.4k$。

* 正確、真實的數值 ($\hat{y}$) 叫做 label。

![](https://hackmd.io/_uploads/ryeBZTtm2.png)
<small style="text-align: center;">https://youtu.be/Ye018rCVvOo?t=1232</small>

不過訓練資料不只有一筆，我們可以跑過過去一年的所有資料，得到許多 $e$，然後取平均：

$$
L = \frac{1}{N} \sum\limits_{n} e_n
$$

$L$ 越小，代表這組參數越好。

> $e$ 的計算不只有稱作 mean absolute error (MAE) 的 $|y - \hat{y}|$ 一種，還有像是稱作 mean square error (MSE) 的 $(y - \hat{y})^2$，適用於 $y$ 和 $\hat{y}$ 是機率分佈的 Cross-entrophy。

#### Error Surface（等高線圖）

我們窮舉所有 $w$ 和 $b$，為每個組合都算一個 Loss，可以獲得一個等高線圖。越紅代表 Loss 越大，越藍代表 Loss 越小。

![](https://hackmd.io/_uploads/r1pf4ptQh.png)
<small>https://youtu.be/Ye018rCVvOo?t=1369</small>

畫出來的等高線圖就叫 Error Surface。

### 3. Optimization － 解一個最佳化問題

我們要找一組 $w$ 和 $b$，讓 $L$ 最小。

![](https://hackmd.io/_uploads/B1S-8TYQ2.png)
<small>https://youtu.be/Ye018rCVvOo?t=1506</small>

把最好的一組 $w$ 和 $b$ 定義為 $w^*, b^*$。

其中一個 optimization 的辦法是 Gradient Descent。

為了方便解釋 Gradient Descent，我們先假設未知參數只有一個 $w$，先不管 $b$。現在只有一個參數，我們可以得到一個曲線圖，也是一個二維的 Error Surface。

步驟：

![](https://hackmd.io/_uploads/r1dyJCtQ3.png)
<small>https://youtu.be/Ye018rCVvOo?t=1554</small>

1. 隨機選擇一個初始的點 $w^0$。(在某些情況下會有比隨機選擇還更好的做法，現在先不管這件事)
2. 計算 $w^0$ 在曲線上的切線斜率 (藍色虛線)，也就是微分 $\frac{\partial{L}}{\partial{W}} |w = w^0$。以此判斷下一個 $w$ 要取在哪才會再好一點。
    * 想像有一個人站在 $w^0$ 點上，左右環視一下 (就是算微分)，就知道哪邊比較低，就往哪邊跨出一步。
    * 要跨多大步？有兩個考量：
        1. 斜率有多大？斜率大，就跨大一點。
        2. 在訓練模型時，我們自己決定的一個*超參數* (*hyperparamter*)：learning rate ($\eta$)。Learing rate 越大，跨的就越大。
        > 在機器學習中，需要自己設定的參數會叫做 hyperparamters，來跟「機器會自己找出來的參數」paramters (例如 $w$、$b$) 做區別。
3. 把 $w$ 移動一步，變成 $w^1$。
4. 重複步驟 2 跟 3，反覆更新 $w$，直到⋯⋯
    * 失去耐心了：在訓練時通常會設定更新次數的上限，這個上限也是個*超參數* (*hyperparamter*)。
    * 微分值是 0：理想狀況，表示走到平地了。


但以上步驟可能有個問題，我們最終可能會走到由隨機初始位置不斷往下走所能達到的最低點 (local minima)，但永遠走不到整個 error surface 真正的最低點 (global minima)。

![](https://hackmd.io/_uploads/SyMIyCKXh.png)
<small>https://youtu.be/Ye018rCVvOo?t=2060</small>

雖然在教科書上，Gradient Descent 的 local minima 問題是個大問題，但在實務上卻是個假議題，有其他更麻煩的問題。

#### 有兩個參數，怎麼使用 Gradient Descent？

其實跟一個參數沒什麼不同。

![](https://hackmd.io/_uploads/B1uHbAK72.png)
<small>https://youtu.be/Ye018rCVvOo?t=2188</small>

> 做機器學習不需要會算微分，在 PyTorch 只要 call 一個 function 就好了。

![](https://hackmd.io/_uploads/HJlJGAtQn.png)
<small>https://youtu.be/Ye018rCVvOo?t=2313</small>

### 基本步驟：小結

![](https://hackmd.io/_uploads/B1ub70Fmn.png)
<small>https://youtu.be/Ye018rCVvOo?t=2430</small>

但以上這個模型在真實的預測上，表現沒有很好。

## 進一步改善

### 依照對問題的理解來更新模型

![](https://hackmd.io/_uploads/rk0KS0t72.png)
<small>https://youtu.be/Ye018rCVvOo?t=2594</small>

觀察真實數據後，我們發現觀看人數有每七天一個循環的週期，因此，我們應該要把前七天的觀看人次都列入考量。

我們寫了一個新的模型，把過去七天的資料 ($x_j$) 分別乘上不同的 weights ($w_j$)，通通加起來之後再加上一個 bias ($b$)：

$$
y = b + \sum\limits_{j=1}^{7} w_j x_j
$$

確實有了進步 (對真實預測資料的 loss $L'$ 從 $0.58k$ 降到 $0.49k$)。

![](https://hackmd.io/_uploads/BJFyLRKX2.png)
<small>https://youtu.be/Ye018rCVvOo?t=2768</small>

如果更進一步的提升 input 的天數，例如到 28 天，模型的表現還可以再進步一點 ($L' = 0.46k$)。但是，再提高到 56 天，就卡住沒有再進步了 ($L'$ 仍然是 $0.46k$)。

### 更強的 Model

回顧我們模型的基本邏輯，$y = b + wx_1$，會發現無論如何改參數，它能做到的還是非常有限，$x_1$ 對 $y$ 永遠是線性的關係 (藍線)。這樣的 model 稱為 linear model。


![](https://hackmd.io/_uploads/rkPyq0tmn.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=0</small>

但也許現實中，當前一天的觀看人數 $x_1$ 小於某個數值時，$y$ 與 $x_1$ 是成正比，而當 $x_1$ 超過某個數值時，$y$ 與 $x_1$ 反而會成反比 (紅線)，物極必反。

原先用的 model 不管如何調整 $w$ 和 $b$ 也永遠造不出紅色的那條線。顯然 linear model 有很大的限制。這種來自於 model 的限制叫做 Model Bias。

> Model Bias 和參數 $b$ 的 bias 是不同的概念！

要如何找一個有可能表達出紅線的 model 呢？

也就是，要如何寫一個，有辦法可以變成紅線的，帶有未知參數的 function？

紅色曲線的 function 可以由一群長得像這樣 (固定格式)：<img height="20" src="https://hackmd.io/_uploads/rypc30tmh.png"> 的不同藍色 function 相加之後組合出來。

![](https://hackmd.io/_uploads/SyF4T0tX2.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=146</small>

不管是怎樣的 piecewise linear curve (由很多直線線段組合出來的 curve ) 都可以用這個方式組合出來，只是越複雜 (區段越多) 的 curve 就需要越多的 <img height="20" src="https://hackmd.io/_uploads/rypc30tmh.png"> 才能組出來。

![](https://hackmd.io/_uploads/Sk9gACt72.png)

就算不是 piecewise linear curve，也可以用 piecewise linear curve 來逼近它。

![](https://hackmd.io/_uploads/B1OzC0tm2.png)

因此，我們可以用一堆 <img height="20" src="https://hackmd.io/_uploads/rypc30tmh.png"> 的組合，來逼近任何可能的 function。

要如何定義 <img height="20" src="https://hackmd.io/_uploads/rypc30tmh.png">？可以用一個叫做 Sigmoid 的 function 來逼近它。

![](https://hackmd.io/_uploads/Hydqkk5Xn.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=508</small>

總之就是有 $w$、$b$ 和 constant $c$ 三個參數可以調整的 function。當 $x_1$ 非常大，$y$ 會收斂於 $c$，而當 $x_1$ 非常小，$y$ 會收斂於 $0$。

這個 function 可以簡單記為：

$$
y = c\ sigmoid(b + wx_1)
$$

> 而那個原本的、轉折是硬的 function <img height="20" src="https://hackmd.io/_uploads/rypc30tmh.png">，則叫做 Hard Sigmoid。

$w$、$b$ 和 $c$ 對 Sigmoid Function 的影響：

![](https://hackmd.io/_uploads/SyS8byqX3.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=692</small>

* $w$ 控制斜度。
* $b$ 控制左右移動。
* $c$ 控制高度。

如此我們就能做出不同的 Sigmoid Function，再用各種 Sigmoid Function 疊加出近似各種 piecewise linear curve，去逼近各式各樣的 function。

![](https://hackmd.io/_uploads/B1PPfk9m3.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=761</small>

$$
y = b + \sum\limits_{i}c_i\ sigmoid(b_i + w_i x_1)
$$

這就是一個非常有彈性的、有未知參數的 function。

#### Non-linear Model

![](https://hackmd.io/_uploads/ryMLIJ573.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=913</small>

我們最初的 model 是：

$$
y = b + w x_1
$$

利用 sigmoid，我們可以有一個更有彈性的 model：

$$
y = b + \sum\limits_{i}c_i\ sigmoid(b_i + w_i x_1)
$$

> $i$ 代表可以用多少個 sigmoid function 來組合。

而在上一小段，我們也曾把最初的 model，$y = b + w x_1$，改成支援多個 feature (例如可以用前 $j$ 天的資料來做預測) 的版本：

$$
y = b + \sum\limits_{j} w_j x_j
$$

> $j$ 代表可以輸入多少個 feature。

而要把它擴展更有彈性的 sigmoid 版本，我們可以把 $b + \sum\limits_{j} w_j x_j$「套進」sigmoid 版的 function 裡：

$$
y = b + \sum\limits_{i}c_i\ sigmoid\left(b_i + \sum\limits_{j} w_{ij} x_j\right)
$$

畫個圖來解釋一個實際的例子：如果我們取前三天的觀看人數來預測下一天的觀看人數 ($j: 1, 2, 3$)，並且使用 3 個 sigmoid function ($i: 1, 2, 3$)。

首先，單獨看一個藍色的部分，也就是當 $i = 1$ 時、第一個 $sigmoid$ 的括號裡做的事：

![](https://hackmd.io/_uploads/B1akF1cmn.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=1039</small>

就是把三個 feature，$x_1$、$x_2$、$x_3$ 分別乘上一個 weight ($w_{i1}$、$w_{i2}$) 之後，加總起來，再加上一個 bias $bi$。

> * $w_{ij}$ 是指在第 $i$ 個 $sigmoid$ 裡，乘給第 $j$ 個 feature 的 weight。
> * $b_{i}$ 就是在第 $i$ 個 $sigmoid$ 裡，feture 都乘上 weight 之後相加再加上的 bias。

以此類推⋯⋯

![](https://hackmd.io/_uploads/r1hZok5X2.png)

為了簡化，我們把第 $i$ 個 `sigmoid` 裡的東西 (也就是藍框裡的式子) 表示為 $r_i$。分別有 $r_1$、$r_2$ 和 $r_3$。

> 再來為了要把 $x_j$ 和 $r_i$ 的關係用比較簡化的方法來表示，我們可以用線性代數中，矩陣相乘 (向量) 的表示法：
>
> ![](https://hackmd.io/_uploads/SJognJqmn.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=1194</small>
>
> $$
> r = b + Wx
> $$
>
> 向量 $x$ 乘上矩陣 $w$ 加上 $b$ 得到向量 $r$。這樣就可以省下寫一堆 $x$、一堆 $+$ ⋯⋯ 的時間。


在式子 $y = b + \sum\limits_{i}c_i\ sigmoid\left(b_i + \sum\limits_{j} w_{ij} x_j\right)$ 中，接下來，就是讓 $r_1$、$r_2$ 和 $r_3$ 分別通過 $sigmoid$：

![](https://hackmd.io/_uploads/SJmZAy9Q3.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=1342</small>

> 這裡也有一個簡潔的表示法：
> 
> $$
> a = \sigma(r)
> $$
> 
> 代表 $r$ 這個向量裡的東西分別通過 $sigmoid$，然後得到 $a$ 這個向量。

最後，就是把三個 $sigmoid$ 出來的結果，分別乘上 $c_i$ 之後加總，再加上一個 $b$ 之後得到 $y$。

![](https://hackmd.io/_uploads/Hkrskgcmh.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=1406</small>

> 向量的表示法：
>
> <img height="300" src="https://hackmd.io/_uploads/rJZ1bg9Xh.png" />
> 
> $$
> y = b + c^T a
> $$
> 
> 代表 $r$ 這個向量裡的東西分別通過 $sigmoid$，乘上轉置（transpose，也就是讓原本直的 $c$ 躺成平的）後的 $c$ ，然後得到 $a$ 這個向量。

總上，我們的「比較有彈性」的 model：

$$
y = b + \sum\limits_{i}c_i\ sigmoid\left(b_i + \sum\limits_{j} w_{ij} x_j\right)
$$

畫成圖可以表示為：

![](https://hackmd.io/_uploads/SkstGe97h.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=1448</small>

> 而用線性代數的方式可以記為：
> 
> * ${\bf r} = {\bf b} + W{\bf x}$
> * ${\bf a} = \sigma({\bf r})$
> * $y = b + {\bf c}^T {\bf a}$
> 
> 合併後：
> 
> $$
> y = b + {\bf c}^T \sigma({\bf b} + W{\bf x})
> $$
>
> * $\bf x$ 是所有 feature 的向量，共有 $j$ 個項目。
> * $W$ 是有 $i \times j$ 個項目 (有多少個 sigmoid $\times$ 有多少個 feature) 的矩陣。
> * $\bf b$ 是放在每個 sigmoid 的 bias 的向量，有 $i$ 個項目。
> * $\bf c$ 對每個 sigmoid 出來的東西要乘上的常數的向量，有 $i$ 個項目。
> * $b$ 是最後加上去的 bias。
>
> 其中 $W$、$\bf b$、$\bf c$、$b$ 四個是未知參數，也就是訓練模型時要找出的東西。
> ![](https://hackmd.io/_uploads/ry1F8xcX2.png)
> <small>https://youtu.be/bHcJCp2Fyxs?t=1533</small>
> 我們可以把這個四個東西的內容通通合併成一個向量，然後統稱它為 $\theta$。

這邊的 $sigmoid$ 除了 $sigmoid$ 之外，其實還有不同的 function 可以選擇。而像 $sigmoid$ 這樣的 function，就稱為 Activation Function。

> Q&A
> 
> Q1：可不可以暴力搜尋所有的參數來找到最好的？
> A1：在只有兩個參數 $w$ 和 $b$ 的時候可能可以，但很快的參數就會變得非常的多，不可能用暴力搜尋的，因此就需要用 Gradient Descent 之類的方法來找。
> 
> Q2：Sigmoid 的數目？
> A2：Sigmoid 的數目是自己決定的，sigmoid 的數量越多，越能組出更複雜的 function。要有多少 sigmoid 又是另一個 hyperparamter。
> 
> Q2：可以用 hard sigmoid 嗎？
> A2：可以，但寫出來的 function 會比較複雜，所以這邊先用 sigmoid 來介紹。

### Loss 的定義是一樣的

只是現在我們的參數太多了，通通寫出來太累了，所以就用 $L(\theta)$ 來表示。$\theta$ 代表所有未知的參數。

![](https://hackmd.io/_uploads/HyD8tlc7h.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=1852</small>

### Optimization 也是一樣的

還是可以用 Gradient Descent。只是有一堆東西要微分，全部微分後得到一個很大的向量，而這個向量 $\bf g$ 就叫做 gradient。

![](https://hackmd.io/_uploads/BkIVjxcX3.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=1937</small>

常看到的表示方式是：

$$
{\bf g} = \nabla L(\theta^0)
$$

$\nabla$ 的意思是把所有 $\theta$ 通通拿去對 $L$ 做微分。$\theta^0$ 的 "$^0$" 表示 算微分的位置在 $\theta = \theta^0$ 的地方。

更新參數的方法也是一樣的，只是從更新兩個參數變成更新一堆參數。

![](https://hackmd.io/_uploads/r1uKjx9Qn.png)

也是一樣，重複更新很多次直到不想再做為止。

![](https://hackmd.io/_uploads/rJpTsxq73.png)

#### 實作細節：分 Batch

實務上，我們不會一次把所有資料一次通通丟進去算 loss 和 gradient。

![](https://hackmd.io/_uploads/H1pSTgcmh.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=2208</small>

我們會把 data 分成好幾個 batch (隨機分組就好)，每次用一個 batch 算 loss $L^n$，算出 gradient 來更新參數。

* 每次更新參數，叫一次 update。
* 把所有 batch 都看過一次，叫一次 epoch。

舉例：

![](https://hackmd.io/_uploads/r10jpe5Q3.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=2356</small>

## 更多模型的變形

### Hard Sigmoid

Hard Sigmoid 是兩個 Rectified Linear Unit (ReLU，一條水平的線走到一個地方突然有個轉折) 的加總。

![](https://hackmd.io/_uploads/r1ru0xcQn.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=2463</small>

要用 Hard Sigmoid，可以把 activation function 換成 $max$，然後把原本的 $i$ 變兩倍，因為兩個 ReLU 才能組出一個 hard sigmoid。
![](https://hackmd.io/_uploads/H1w-y-57n.png)

實際上 ReLU 似乎比較好用？之後會介紹。

### 疊更多層

把經過一層 activation function 的 $a$ 當作 feature $x$ 再丟進另一層 activation function。

![](https://hackmd.io/_uploads/rJyZlZ973.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=2713</small>

參數又更多了。

要過幾層？又是另一個 hyperparamter。


## Neural Network & Deep Learning

這樣的機器學習模型要叫什麼名字？

1. 有很多 sigmoid 或 ReLU 串再一起，就像神經元一樣，很多神經元串在一起，就叫神經網路。
![](https://hackmd.io/_uploads/BksVZWqmn.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=2953</small>
    * 但在 80-90 年代已經把這個名字玩爛了。
2. 有很多層 neuron，每一層 neuron 叫一個 layer (hidden layer)，有很多 hidden layer 就叫做 deep，於是就叫做 Deep Learning。
![](https://hackmd.io/_uploads/Hy4IzWqmh.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=3051</small>


人們就開始把 layer 越疊越多、越疊越深⋯⋯錯誤率也在降低，從 16.4% 到 7.3%、6.7% ⋯⋯。

![](https://hackmd.io/_uploads/rJ7RzW97n.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=3083</small>
「比 101 還要多層」

### 「Deep」的意義何在？為什麼要疊很多層？

通通攤成一層不好嗎？是不是因為可以叫「deep」比較厲害，攤開變「fat」就不潮了？

![](https://hackmd.io/_uploads/BJAIX-5m2.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=3133</small>

之後會講。

### Overfitting

指「在訓練資料上表現良好，但對沒看過的真實資料反而表現變差」。

![](https://hackmd.io/_uploads/ryuEEW9Q2.png)
<small>https://youtu.be/bHcJCp2Fyxs?t=3221</small>

## 延伸



* 更有效率的算 gradient 的方法：Backpropagation https://www.youtube.com/watch?v=ibJpTrp5mcE