---
# System prepended metadata

title: TQA

---

<details>
<summary>解釋 mAP</summary>

對於一張圖片，如何算是檢測正確需考慮三種情況:

1. IoU 是否大於閥值
2. 類別是否正確
3. Confidence 是否大於閥值

先說明三個指標定義:
    
* TP: 預測正確的預測框數量，代表 IoU 大於閾值（同一個 GT 只計算一次）
* FP: 檢測到同一個 GT 的多餘預測框數量，代表 IoU 小於閾值
* FN: 沒有檢測到 GT 的預測框數量（漏檢的數量）

==下面篇幅中所有談到的 TP、FP、FN 都是已經過 NMS 處理完的預測框。==
    
舉例來說，設定 IoU 閥值為 0.5，綠色為 GT、紅色為預測框:

* 中間預測框（cat 0.9）和 GT 的 IoU 大於 0.5，是一個 TP
* 左邊預測框（cat 0.3）和 GT 的 IoU 小於 0.5，是一個 FP
* 右下角 GT 沒有預測框，漏檢了，是一個 FN

<div class="text-center">
    <img src="https://hackmd.io/_uploads/S1WikBiyyl.jpg" style="width: 500px; object-fit: cover;">
</div>

&nbsp;
接著，舉二個例子談談 Precision 和 Recall:

\begin{gathered}
Precision=\frac{TP}{TP+FP}; Recall=\frac{TP}{TP+FN}
\end{gathered}

* 下圖左，五個 GT 只給 1 個預測框，TP=1、FP=0、FN=4

\begin{gathered}
Precision=\frac{1}{1+0}=1; Recall=\frac{1}{1+4}=0.2
\end{gathered}

* 下圖右，五個 GT 給了 50 個預測框，每個都有框到目標物，TP=5、FP=45、FN=0

\begin{gathered}
Precision=\frac{5}{5+45}=0.1; Recall=\frac{5}{5+0}=1
\end{gathered}

<div class="text-center">
    <img src="https://hackmd.io/_uploads/r1gA-rjJJx.jpg" style="width: 310px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/rk8A-BoJJl.jpg" style="width: 310px; object-fit: cover;">
</div>

&nbsp;
由上述結果可知，用上述任一個單一指標來衡量檢測問題，都很有可能會 Fail:
* 預測框太少，可能會讓 Precision 很高、Recall 很低
* 預測框太多，可能會讓 Precision 很低、Recall 很高

==檢測問題的 AP（Average precision）並不是平均精確度，而是 P-R Curve 下的面積。==

舉例說明，假設一個檢測模型已訓練好做三張影像的檢測，如何衡量其 AP:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/B1MLqBs1Jg.jpg" style="width: 600px; object-fit: cover;">
</div>

&nbsp;
第一張圖，累積 GT 數量為 2:
* GT id: 預測框匹配 GT 的編號
* Confidence: 預測框判別為該類別的信心分數
* OB: 判斷預測框是否為 TP
* 對於 GT id=2，模型沒有給出預測框，所以下表無資訊

<div class="text-center">
    <img src="https://hackmd.io/_uploads/SJLYjHi1yl.png" style="width: 700px; object-fit: cover;">
</div>

&nbsp;
第二張圖，累積 GT 數量為 2+1=3:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/BkFuhBiJJg.png" style="width: 700px; object-fit: cover;">
</div>

&nbsp;
第三張圖，累積 GT 數量為 3+4=7:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/HJtT2rs1kg.png" style="width: 700px; object-fit: cover;">
</div>

&nbsp;
接著，根據設定不同的 Confidence 閥值去得到 Precision 和 Recall:

> 所有高於 Confidence 閥值的都稱為 Positive，而在此 FP 代表的是它不是真正的 Positive，因為它和 GT 的 IoU 小於 0.5

1. 將閥值設為 0.98（Confidence $\ge$ 0.98 才算預測正確）
    TP=1、FP=0（看 OB）、FN=6（GT 數量 - TP）
    \begin{gathered}
    Precision=\frac{1}{1+0}=1; Recall=\frac{1}{1+6}=0.14
    \end{gathered}
2. 將閥值設為 0.89
    TP=2、FP=0、FN=5
    \begin{gathered}
    Precision=\frac{2}{2+0}=1; Recall=\frac{2}{2+5}=0.28
    \end{gathered}
3. ...
4. 將閥值設為 0.66
    TP=4、FP=1、FN=3
    \begin{gathered}
    Precision=\frac{4}{4+1}=0.8; Recall=\frac{4}{4+3}=0.57
    \end{gathered}
5. ...

全部計算完成後列出下表:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/HJx_18skke.png" style="width: 700px; object-fit: cover;">
</div>

&nbsp;
並繪製出 P-R Curve:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/ry4tJLjkye.png" style="width: 500px; object-fit: cover;">
</div>

&nbsp;
計算面積時將僅去除重複數值（同一個 Recall 上有多個 Precision）:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/rkxCyIskye.png" style="width: 700px; object-fit: cover;">
</div>

&nbsp;
計算陰影面積，最後得 AP=0.6694，而上述流程僅對於一個類別去做計算，實務上有多個類別，那麼就是所有類別的 AP 取平均:

\begin{gathered}
mAP=\frac{1}{n_c}\sum_{i=1}^{n_c}AP_i
\end{gathered}

其中，$n_c$ 是類別的數量。

參考資料:
* [MS COCO数据集的评价标准以及不同指标的选择推荐](https://blog.csdn.net/weixin_44878336/article/details/134030021)

</details>


<details>
<summary>什麼是 Type-I / Type-II Error</summary>

1. Type-I error 就是 False positive，當實際上沒發生卻預測為有發生，例如: 實際上是 OK 卻預測為 NG，也就是過殺
2. Type-II error 就是 False negative，當實際上有發生卻預測為沒發生，例如: 實際上是 NG 卻預測為 OK，也就是漏放

範例1: 一個預測癌症模型，Type-II error 的成本相當高，要盡量壓低
> * False positive: 實際上沒有病（Negative），卻預測為 Positive，預測錯了（False），Type-I error -> 過殺
> * False negative: 實際上有病（Postive），卻預測為 Negative，預測錯了（False），Type-II error -> 漏放

範例2: 一個瑕疵辨識模型，Type-II error 的成本相當高，要盡量壓低
> * False positive: 實際上是 OK（Negative），卻預測為 Positive，預測錯了（False），Type-I error -> 過殺
> * False negative: 實際上是 NG（Postive），卻預測為 Negative，預測錯了（False），Type-II error -> 漏放

Precision: 在所有預測結果中，實際上有多少真的是這個結果（預測所有的 OK 當中，實際上也是 OK 的比率）
> 
> Precision is also called the positive predictive value (PPV).

Recall: 在所有真實結果中，預測了多少為這個結果（在所有的 OK 當中，預測是 OK 的比率）
> 
> Recall is also called the true positive rate (TPR), sensitivity (SEN) and hit rate.

</details>


<details>
<summary>不平衡數據集的處理方式?</summary>

簡單來說，有以下方法可以做:
1. 收集更多資料
2. 修改模型指標，避免使用像是 Accuracy 這樣的指標（假設某類別占了數據量的 99%，只要模型無腦猜該類別就有 99% 的準確率）；應採用 F1 Score 這樣的指標同時考慮 Precision 和 Recall:
    \begin{gathered}
    F1=\frac{2·Precision·Recall}{Precision+Recall}
    \end{gathered}
    
3. 抽樣: 過採樣（Oversampling）或欠採樣（Undersampling）
    過採樣: 在數量小的資料上不斷重複抽樣，容易取到一樣資料，有過擬合風險。可以在重複抽樣的過程中加入雜訊去減輕這個問題
    欠採樣: 在數量大的資料上選取部分樣本，容易丟失訊息，有欠擬合風險。其中，又有二者比較常用，分別是 EasyEnsemble 和 BalanceCascade:
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/HJ6mLLIkkg.png" style="width: 500px; object-fit: cover;">
    </div>
    
    其中，[BalanceCascade 和 EasyEnsemble](https://www.cupoy.com/qa/club/ai_tw/0000016D6BA22D97000000016375706F795F72656C656173654B5741535354434C5542/0000017BEEF59488000000196375706F795F72656C656173655155455354) 相仿，差異在於它還會通過調整閥值去控制 FPR，並在每次訓練弱分類器後將分類正確的樣本刪除，只保留下分類錯誤的樣本來降低多數類別的樣本數量。

4. 加權
    分配不同的損失權重給樣本，例如數量小的樣本有較大的權重，但難題在於如何分配合理的權重。
    
5. 合成資料
    常見的算法如 SMOTE，利用數量小的樣本在特徵空間的相似性來生成新樣本。
6. 可以嘗試樹類（Tree-based）模型
    * 特徵選擇: 樹模型在每次分裂時，都會根據當前的數據狀況做決策，而不需要明確調整每個類別的重要性。因此，即使數據集存在類別不平衡，模型依然能從中找出少數類別的關鍵特徵
    * 分類標準: 分裂主要根據如基尼係數、熵等標準做劃分，因此儘管少數類別樣本較少，但目標是最大化樣本純度
    * 異常值穩健性: 同上，由於分類標準的關係，異常值並不影響分裂的決策過程
    * 避免過擬合: 可以透過控制樹的深度、剪枝等技巧控制模型複雜度，也可搭配集成學習的方式，用多個弱分類器更好識別少數量類別的樣本

資料差異相當懸殊時，就換一個想法，採用異常檢測的方式來訓練一元分類模型，重點不放在捕捉類別間的差異，而是只為其中一種去建模。

參考資料:
* [機器學習中如何處理不平衡資料（imbalanced data）？](https://iter01.com/154571.html)
* [机器学习︱非平衡数据处理方式与评估](https://blog.csdn.net/sinat_26917383/article/details/75890859)
* [【QA】欠採樣(Undersampling)的常用技術－隨機欠採樣、Easyensemble、BalanceCascade??](https://www.cupoy.com/qa/club/ai_tw/0000016D6BA22D97000000016375706F795F72656C656173654B5741535354434C5542/0000017BEEF59488000000196375706F795F72656C656173655155455354)

</details>


<details>
<summary>機器學習業界與學術的差別?</summary>
    
* Computation priority: 計算優先級
    * Research: fast training and high throughput
    （為快速比對多個算法，注重訓練速度）
    * Production: fast inference and low latency
    （在意預測速度及延遲）
    
* Data: 學術著重靜態資料，業界則關注動態資料
    * Research: static
    （為比對算法優劣，通常在數量、特徵不會變動的靜態資料上進行測試）  
    * Production: constantly shifting
    （隨時間動態產生的資料，資料來源可能品質不穩定）

* Interpretability: 學界要求預測力，業界則需要解釋力才能信任
    * Research: often focus on prediction ability
    （追求 SOTA，關注模型的預測能力）
    * Production: only trust explainable result
    （面對終端使用者，無法接受模型預測力好，但無法解釋為何去做這樣的決策，相當於在流程上塞入了一個不確定性高的元素，不知何時會出錯、為什麼會出錯）
    
</details>


<details>
<summary>CNN 各層功能解釋</summary>

* [卷積神經網路 (Convolutional Neural, CNN)](https://hackmd.io/@allen108108/rkn-oVGA4)
* [CNN网络的pooling层有什么用？](https://www.zhihu.com/question/36686900)
* Pooling layer 有三個重要的特性:
    1. 降低 Feature map 尺寸達到運算量降低的效果
    2. 讓特徵具有不變性（Invariance），類似正規化、抗雜訊干擾的作用:
        * 平移（Translation）
        * 旋轉（Rotation）
        * 尺寸（Scale）
    3. 增加 Receptive field（一般的 Convolution layer 也能做到這件事）
* Activation layer 是將 Feature map 數值做非線性轉換，如果不使用它，基本上整個神經網路只是一連串的矩陣相乘，依然是線性關係
* Fully connected layer 是把提取的 Feature 對映到樣本 Label 或數值的空間。若每個學習的 Filter 是在圖像局部做特徵加權，那麼全連接層就是對全域圖像關注部分做特徵加權

</details>


<details>
<summary>空洞卷積（Dilated convolution）</summary>

一般來說，想要增大感受野可將普通卷積層設定 Stride>1，但同時會導致 Downsampling，讓卷積後的特徵圖尺寸减小、分辨率降低；而空洞卷積是針對上述造成資訊遺失情況提出的一種想法，==Dilated 的好處是取代 Pooling 會損失資訊的缺點，同時保有增加感受野的優勢，讓每個卷積輸出都涵蓋較大範圍的資訊。==

[如何增加感受野？](https://www.youtube.com/watch?v=Q0S8s5xjHlQ&ab_channel=AnakAI)
* 左圖: 用一般 3X3 Kernel 掃 Input 得到 Feature map
* 右圖: 再用 Dilated=2 的3X3 Kernel 掃 Feature map

<div class="text-center">
    <img src="https://hackmd.io/_uploads/S1R0vlAh2.png" style="width: 330px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/rJDx_lCh3.png" style="width: 330px; object-fit: cover;">
</div>

&nbsp;
分析上述操作，將 Convolution layer 都往回推來看:
* 左圖: Dilated=2 的 3X3 Kernel 往回推，==其實對應到 7X7 的 Input，感受野為 7==
* 右圖: 一般的 3X3 Kernel 往回推，是對應到 5X5 的 Input，感受野只有 5

<div class="text-center">
    <img src="https://hackmd.io/_uploads/Hko3KgC23.png" style="width: 330px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/Sy9ZnlC33.png" style="width: 330px; object-fit: cover;">
</div>

&nbsp;
感受野的計算公式如下:

\begin{gathered}
F_{i+1}=(2^{i+2}-1)*(2^{i+2}-1)
\end{gathered}

其中，$i+1$ 表示 Dilated rate，一般 Convolution 的 Dilated rate=1。

---

在相同的計算條件下空洞卷積提供了更大的感受野，在計算資源受限、又需要較大感受野時可以考慮，但也有下列問題需要克服:

* Gridding effect
    假設僅僅多次疊加 Dilated rate=2 的 3x3 Kernel，會由於 Kernel 不連續（空洞卷積類似棋盤格的 Kernel）而損失資訊連續性，因為不是所有的 Pixel 都參與計算。這對 Pixel-level 的 Dense prediction 任務來說會有缺陷，例如圖像分割。

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/HyWThx0h3.png" style="width: 330px; object-fit: cover;">
        <img src="https://hackmd.io/_uploads/SJE03eAn3.png" style="width: 330px; object-fit: cover;">
        <img src="https://hackmd.io/_uploads/Hykgpl033.png" style="width: 330px; object-fit: cover;">
        <img src="https://hackmd.io/_uploads/Bkz-pxR3h.png" style="width: 330px; object-fit: cover;">
    </div>

* Long-ranged information might be not relevant
    Dilated convolution 的設計雖是用來獲取 Long-ranged information，但只對一些大物體有不錯的效果、對小物體來說可能有弊無利。如何同時處理不同大小的物體的關係，則需透過設計良好空洞卷機架構，可參考[卷積神經網路 (Hybrid Dilated Convolution, HDC)](https://www.zhihu.com/question/54149221)。

</details>


<details>
<summary>網路加寬和加深有什麼影響?</summary>

* 深度的意義
    CNN 每一層都做特徵提取且都是接著上一層往下學習，==意即深度決定了一個函數的表示能力，在影像上就是圖像特徵的表達能力。==

* 寬度的意義
    網路越寬，代表每層的 Filter 數量越多，對同一張圖能提取出更豐富的特徵，例如不同方向、不同紋理等，==意即寬度決定網路在每層學習到的訊息量。==

基本上 CNN 每層學到的訊息量需要先多，也就是寬度要先足夠，再透過深度來將這些豐富訊息組合成更好的特徵或函數表達能力，因此
* 太寬太淺: 還沒學到表達能力就停止，容易 Underfitting
* 太窄太深: 每層學不到有意義的特徵，加深也只是在無用訊息上做組合，一樣 Underfitting

==一般來說，較寬的網路具有較佳的泛化能力，因為有更多的 Filter 去找出資料中共同 Feature。==
    
</details>


<details>
<summary>如何解決梯度消失?</summary>

* 可以改變 Activation function，例如: ReLU 或 LeakyReLU，因為像是 Sigmoid 在二旁的微分趨近為 0，導致即使有很大的 Loss 也會讓梯度更新變得很小，讓模型訓練不動
* 如果是 CNN 的話可以透過 Shortcut 來去引導函數學習到 Identity matrix: [Resnet](https://hackmd.io/tnus8PHvROaNGs7jnLFeZg)
    
</details>


<details>
<summary>為何使用 ReLU</summary>

ReLU 能使部分神經元的輸出為 0，讓網路變得稀疏，進而解決 Overfitting，且計算量也會稍微節省，因為不需要去做指數運算。
    
</details>


<details>
<summary>如何解決 Overfitting</summary>

Overfitting 代表數據過擬合，通常是由模型在測試集中的表現不佳得知，需要增加泛化能力:

1. Early stopping: 減少非相關梯度的過多影響，提高泛化性
    ==模型訓練時，具有共通特性的樣本往往比困難樣本更早擬合，因此訓練前期由這些梯度做主導==；而訓練後期，會由困難樣本的梯度來主導計算，導致泛化能力變差。

2. Regularization: 加入 L1 或 L2 正規化
    * L1 正規化容易得到稀疏模型，它讓某些參數權重直接為 0，降低模型複雜度
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/B1CU1E7h3.png" style="width: 400px; object-fit: cover;">
    </div>

    * L2 正規化將參數做平滑化，能夠得到較泛化的模型，也就是減少特徵權重差異，讓某些特徵的權重不要太突出（L2 正規化希望參數值愈小愈好，==當輸入有變化時，讓輸出的變化不敏感，是較為泛化的模型==，例如: 輸入被一些 Noise 影響，對於模型的輸出影響也會是小的）

    其中，
    * L1 計算效率低，因為它是一個稀疏向量矩陣，其最重要的特點是把不重要的特徵變成 0，可以看作是一個天然的特徵選擇器。L1 對損失函數微分時梯度都會是 1 或 -1，每次梯度下降都走固定的更新步長
    * L2 則是在梯度愈靠近 0，步長就變得愈小，所以參數權重永遠不會是 0

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/Sy37xE7hn.png" style="width: 400px; object-fit: cover;">
        <img src="https://hackmd.io/_uploads/rkhNx4Q2n.png" style="width: 200px; object-fit: cover;">
    </div>

3. 進階梯度下降算法
    * Momentum、Adam 等梯度下降算法: 參數 W 更新方向不僅由當前梯度決定，也與此前累積的梯度方向有關（即保留累積的相關梯度的作用）。使參數中梯度方向變化不大的維度可以加速更新和收斂，同時減少梯度方向變化大的維度更新幅度，減小震蕩效果
    * 抑制弱梯度方向的梯度下降: 通過批次梯度下降，來抑制弱梯度方向的梯度更新，進一步提高泛化能力，也可以搭配或使用梯度截斷，排除梯度異常值後再取平均值、中位數，降低梯度異常值的影響

4. Dropout
    透過捨棄部分參數權重來達到等同於正規化的泛化的效果。

5. Data augmentation
    透過增加訓練資料方式，避免讓模型只學習到訓練集中特定的特徵。

</details>


<details>
<summary>如何解決 Underfitting</summary>

Underfitting 就是在訓練集上就已經表現不好，需要做更多調整:

1. Data augmentation: 透過增加訓練資料方式，讓模型學習到訓練集中的更多特徵
2. 重新設計網路架構: 增加網路寬度和深度，變寬提取更多特徵、變深獲得更佳函數表達能力
3. 調整 Activation function: 增加非線性轉換能力、解決梯度消失問題
4. 調整 Learning rate、改變優化器

</details>


<details>
<summary>常見優化器介紹</summary>

1. Momentum
    參數更新不僅由當前梯度決定，也與此前累積的梯度有關，==也就是保留至今所有梯度的影響==

2. RMSProp
    ==利用超參數調整先前梯度和這次要更新梯度的權重==，可視為動態調整 Learning rate 的方法

3. Adam=Momentum+RMSProp
    讓參數中梯度方向變化不大的維度加速更新、減少梯度方向變化大的維度的更新幅度
 
</details>


<details>
<summary>取樣定理（Sampling theorem）</summary>

一個有限頻寬（Band-limited）的訊號，==若採樣頻率大於訊號最高頻率的 2 倍==，那麼原始的連續信號就可以從採樣的樣本中完全重建出來。

</details>


<details>
<summary>短時傅立葉轉換（STFT）和傅立葉轉換（FFT）</summary>

[時頻分析之STFT：短時傅里葉變換的原理與代碼實現](https://blog.csdn.net/frostime/article/details/106816373)

Why using STFT rather then FFT? 
* 二個時域分佈相反的信號，頻譜圖卻是一致的，FFT 無法捕捉訊號在時域分佈上的不同

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/HJqMmGQAn.png" style="width: 330px; object-fit: cover;">
        <img src="https://hackmd.io/_uploads/BkNQXGQ0n.png" style="width: 330px; object-fit: cover;">
    </div>

* 一個突波或擾動通常是一系列高頻信號疊加，FFT 無法很好地反映突波或擾動的變化

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/B13J4zm0n.png" style="width: 330px; object-fit: cover;">
        <img src="https://hackmd.io/_uploads/HkSeEzmA2.png" style="width: 330px; object-fit: cover;">
    </div>

==傅立葉轉換擅長分析頻率特徵均一穩定的平穩信號==，假設還想知道各成分出現的時間，或訊號頻率隨時間變化的情況，就需要做時頻分析，而所謂時頻分析，就是既要考慮到頻率特徵，又要考慮到時間序列變化，常用的方法有短時傅立葉轉換、小波轉換。

* 短時傅立葉轉換（STFT）
    既然直接對整個訊號做 FFT 會丟失時間信息，==STFT 就是分割時間序列後，對一小段一小段序列做FFT:==

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/HJcJPM7A3.png" style="width: 400px; object-fit: cover;">
    </div>

    完成第一個區間的 FFT 後將 Window 移往下一個區間，窗框移動距離稱為 Hop size，移動距離一般小於窗框的寬度，通常前後兩個窗框之間存在一定的重疊（Overlap）:

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/SySCPGmC3.png" style="width: 500px; object-fit: cover;">
    </div>

    重複以上，不斷滑動窗口和做 FFT，最終得到所有分段的頻譜結果 S，就是 STFT 轉換後的結果:

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/SyXluMXAh.png" style="width: 500px; object-fit: cover;">
    </div>

    其中，調整不同 Window size 可得知:
    * 窗框小，窗內訊號太短，導致頻率分析不夠精準，頻率分辨率差，但時間分辨率高，具體表現為縱軸黃色區間愈來愈寬、愈來愈模糊
    * 窗框大，時域上滑動又不夠精細，時間分辨率低，但頻率分辨率高，具體表現是橫軸淡藍區間越來越寬、越來越模糊

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/HyDZ9zXR3.png" style="width: 600px; object-fit: cover;">
    </div>

    從定量的角度來看，STFT 的時間分辨率取決於滑移寬度 $H$，而頻率分辨率則取決於 $\cfrac{F_s}{H}$，一方的增加意味著另一方的減小，這就是所謂的時頻測不準原理:

    \begin{gathered}
    \Delta{t}\cdot\Delta{f}\ge{C}
    \end{gathered}

    另外，固定的窗口大小過於死板。對低頻信號而言，有時可能連一個週期都無法覆蓋，但對高頻信號而言，可能又覆蓋過多周期，不能反映信號變化，也就是說一個 Trade-off 問題。

</details>


<details>
<summary>為什麼選擇使用 YOLOv5</summary>

YOLO 的版本相當多，最多人使用的是 v5 和 v8 版本，二者幾乎都是 Real-time 等級的檢測器，會選擇 v5 最主要的原因如下:
    
1. v5 是 Anchor-based，需配置先驗框，前處理和後處理較多，v8 雖然是 Anchor-free 不需要這些，但在訓練上 v5 收斂速度在 200 epochs 就有不錯的結果，而 v8 官方推薦則需要至少 500 epochs，在開發上速度差二倍多
2. 因為 v5 是 Anchor-based，我在後處理可以調整「是物件或背景的門檻」、「類別分數門檻」、「NMS門檻」，可以看我的應用需要著重 Recall 比較多、還是 Precision 比較多，來做彈性調整；v8 是 Anchor-free，少了「是物件或背景的門檻」這項參數做調整
3. v5 的開源資源相當多，包含模型架構修改和優化都有很多可以參考的地方，對於開發上的彈性很高
4. 在自定義的多類別數據集訓練中，v5 的 Loss 更快速且穩定的下降，代表在多類別的目標檢測任務中泛化能力更好

</details>


<details>
<summary>請解釋 kNN 和 k-Means</summary>

* kNN
    和一般的機器學習算法不同，一般的算法會根據訓練資料學到權重，再用權重乘以測試資料去做預測，而 KNN 則可以想成將整個訓練集記下來，若設定 k=5，預測時就去找出距離最接近的五筆訓練資料，看哪個類別多就預測那個類別，因此它並沒有學習的過程，稱作是一個 Lazy learner，因此計算瓶頸往往落在預測階段時，如何找出最相近的 k 個點。

* k-Means
    是一個非監督算法，資料都不具有標籤，概念上就是物以類聚。我們會根據對資料的了解先給定 k 個群心，每筆資料都會和 k 個群心計算距離，將每筆資料判給距離最近的那個群心，第一輪做完後，用這些資料更新一次新的群心，接著再做第二輪、第三輪...直到群心收斂後結束。
    
</details>


<details>
<summary>Top-1 / Top-5 Accuracy</summary>

* Top-1 Accuracy
    
* Top-5 Accuracy
    
    
</details>
