# 課程名稱: 深度學習之應用 ADL
- **課程全名**: Applied Deep Learning
- **學期**: 113-1
- **教授**: 陳縕儂教授
---
## Lecture 0 : Introduction
### 什麼是AL和ML?
- **Artificial Intelligence(AI)** : 用機器來模擬人類行為。
- **Machine Learning(ML)** : 讓機器從**資料**裡面學,屬於一種實踐人工智慧(AI)的方法。
- Learning ~= look for a function
可以理解為機器學習的目的根據給定的資料,尋找一個函數或模型,這個函數能夠有效地對資料進行描述、預測或分類。
### 什麼是DL?
- **Deep Learning(DL)** : Deep Learning可以理解為類神經網路(Neural network)-將模型堆疊很多層,而得到很好的performance。
<figure>
<img src="https://hackmd.io/_uploads/BkANYyDnA.png" alt="DL Model">
<figcaption>上圖為Neural Network模型示意圖,只要hidden layers數量大於等於1即可稱為Neural Network。</figcaption>
</figure>
### ML和DL的差異
<div style="text-align: center;">
<img src="https://hackmd.io/_uploads/HysYskvh0.png" alt="Machine Learning" width="300">
<p>ML的訓練資料由專家標註哪些特徵features是重要的。</p>
</div>
<div style="text-align: center;">
<img src="https://hackmd.io/_uploads/H1hqsJvn0.png" alt="Deep Learning" width="300">
<p>DL由機器自行去學習尋找哪些特徵對於這個任務是重要的。</p>
</div>
### 常用的數學工具
#### Sigmoid function
一個常被作為activate function的non-linear function,定義如下
$$
\sigma(z) = \frac{1}{1 + e^{-z}}
$$
<div style="text-align: center;">
<img src="https://hackmd.io/_uploads/ryJMRZP3A.png" alt="Sigmoid Function" width="350"/>
</div>
Sigmoid 函數可以將實數範圍的輸入對應至[0,1]範圍內,並有著特點:
- **平滑性**:函數是連續的,且導數也連續。
- **非線性**:能夠引入非線性因素,使模型能夠學習複雜的數據模式。
#### Softmax
將一組k維向量σ對應至另一組k維向量σ(z),並且σ(z)中的每個元素範圍都在(0,1)之間,所有元素總和為1。

### A Single Neuron
* 單一Neuron的功能為將“別人傳過來的很多資訊(x~1~,x~2~....,x~N~這個N維向量 )做一些運算後,再傳y這個數值)給其他人”。
* 我們將Neuron輸出的數值y與threshold(通常為0.5)做比較,**bias用來調整要讓 input向量X 多容易使得輸出 數值y 超過threshold**。

### Fat + Shallow vs. Thin + Deep ?
<figure>
<img src="https://hackmd.io/_uploads/rJYwXev2R.png" alt="Fat + Shallow vs. Thin + Deep">
<figcaption>越深的模型能用較少的參數量來達到和淺模型一樣好的效果。</figcaption>
</figure>
---
## Lecture 1 : Neural Network Basics
### Classification Task
#### 依照輸出的可能數量分為
* **Binary Classification** : 輸出只有yes或no
例子: Sentiment Analysis - 判斷一個句子的語意為正面(yes),負面(no)
* **Multi-class Classification** : 輸出種類大於2種
例子: Speech Phoneme Recognition, Handwritten Recognition
#### Vector Representation


vector X 內的數值為從 input image 中取得的特徵(以圖片辨識為例-當該像素有顏色,則對應的數值為1,反之為0)。將X輸入函數f後,輸出vector Y,Y為**One-Hot Vector**,即向量內只有一個元素為1,代表屬於那個分類;其餘均為0。
### Perceptron - A Layer of Neurons

只有一層Neurons的model我們稱之為Perceptron,Perceptron只能做線性的分類(如:AND,OR,NOT),但沒辦法做非線性(如:XOR)。
### Neural Networks – Multi-Layer Perceptron
為了能表示更複雜的函數(如:XOR),因此將Neurons層層堆疊。

### 符號定義
$$ x為一個向量,代表整個模型初始的輸入 $$ $$ a_i^l為第l層的第i個Neural的輸出; $$ $$ a^l為一個長度N_l的向量,代表著第l層的N_l個Neural的輸出;$$ $$ W^l為一個大小為N_l*N_{l-1}的二維陣列,代表第l-1層的N_{l-1}個Neurals傳遞至第l層的N_l個Neurals的權重關係;$$ $$
\mathbf{z}^l = \mathbf{W}^l \mathbf{a}^{l-1} + \mathbf{b}^l
$$
$$
\mathbf{a}^l = \sigma(\mathbf{z}^l)
$$




### Neural Network Formulation
$$
y = f(x) = \sigma(W^l...\sigma(W^2\sigma(W^1x+b^1)+b^2)+...+b^l)
$$ $$
代表這個model的參數\ \theta = \{W^1,b^1,W^2,b^2...,W^l,b^l\}
$$

### 如何評估模型的好壞?
定義一個函數來評估模型的好壞,評估模型有多好(O)或多差(C)

$$ 以\ supervise\ learning\ 為例 $$ $$ 目標: 預測的和真實的資料越接近越好 $$ $$ => 預測值\ f(x;\theta)\ 很接近真實值\ y $$ $$ => |y-f(x;\theta)|\ 很接近\ 0 $$ $$ 因此定義\ C(\theta)\ = \ \Sigma\ |y-f(x;\theta)|$$
一些常見的loss functions

### Optimization
$$ 目標: 尋找合適的參數\ \theta\ 使得C(\theta)\ 的值最小 $$ $$
\text{方法:}
$$
$$
\text{1. Brute force:遍歷所有可能的 } \theta
$$
$$
\text{2. Calculus:將 } C(\theta) \text{ 對 } \theta \text{ 做偏微分}
$$
以下介紹一系列基於Calculus的優化方法。
#### Gradient Descent
**一次用全部訓練集**的數據去計算損失函數的梯度就更新一次參數。

以上是單一參數的Gradient Descent示意圖,將loss function C對θ做偏微,並將參數θ減去偏微後的數值乘上learning rate η。
η(讀作/ita/)代表的意義為學習的過程中**調整的步伐要多大**。

以上為雙參數的例子


Example - Square error loss

#### Stochastic Gradient Descent(SGD) 隨機梯度下降法
每次隨機抽取**一個樣本**,計算梯度並更新。
* 優點: 頻繁地更新,更容易跳出局部最佳解(local optimal)
* 缺點: 不穩定

#### Mini-Batch SGD
**一次跑一個小批次(mini-batch)樣本**然後算出一次梯度或是小批次梯度的平均後就更新一次。每次抽取的mini-batch是隨機的。

#### training time
Modern computers run **matrix-matrix multiplication**(mini-Batch) faster than matrix-vector multiplication(SGD)

### Backpropagation 反向傳播
類神經網路有個缺點是有著大量的重複計算,Backpropagation(反向傳播) 的精髓就在於利用鏈鎖率(Chain rule),有效地從輸出層(末端)開始逐層向前計算各層權重對於損失的影響,**減少計算量**。

$$ Backpropagation的計算分為兩個部分,\frac{\partial z_i^l}{\partial w_{ij}^l}的計算為forward\ pass, \frac{\partial C(\theta)}{\partial z_i^l}的計算為backward\ pass $$
Forward:

Backward: 定義δ為 loss function C 對於某一層某個Neural輸入z的偏微分





---
## Lecture 2 : Sequence Modeling, Attention, Transformer
### Word Representations
用機器看得懂的方式表示詞彙
有兩種表示方式:
* **Knowledge-Based Representation**:
透過語文學家定義詞彙間的關係,建立**WordNet**。

缺點:
1. 由於新詞彙會不斷出現,沒辦法涵蓋所有詞彙。
2. 主觀
3. 不容易根據距離定義兩個字間的相似性,如:(motorcar, go-kart)和 (compact, motor vehicle)距離都是2,但一組的關係為sibling,另一組為grand parent。
* **Corpus-Based Representation**:
起初想將每個字作 one-hot representation,但是有相似關係的兩個相異字為正交(orthogonal),不容易計算similarity(AND起來都變成0)。於是後來出現**考慮哪些字常一起出現**的**Neighbor-based** representation。
* Window-Based Co-occurence Matrix
直接計算每對 words pair 相鄰的次數。

缺點 - sparsity : Matirx內大部分元素都是0,浪費空間,效率低。
* Low-Dimentional Dense Word Vector
方法:
1. 用SVD分解降維 - 計算困難...
2. Directly learn low-dimentional word vector
一些著名方法: word2vec, Glove
### Word Embeddings 詞嵌入
把一個維數為所有詞的數量的**高維空間嵌入到一個維數低得多的連續向量空間**中。
#### Word2Vec [Visualization tool](https://ronxin.github.io/wevi/)


#### Glove


#### Word Vector Evaluation
* Intrinsic: 直接用單詞的類比問題評估
Word Analogies: Wa:Wb = Wc:Wx => 用Word a,b,c推測x
Word Correlation: 比較人類標註詞彙間的similarity score與機器標注的score
* Extrinsic: 用下游任務表現的好壞來評估
### Language Modeling
目標: 評估一段文字出現的機率
#### N-gram language model
**只考慮前n-1個字**來決定第n個字出現什麼的機率。(太久以前出現的字對現在的影響小到可以忽略)

缺點: 並不是所有可能的sequences都出現在訓練資料集內。
#### Neural Language Modeling

#### Recurrent Neural Network Language Modeling (RNNLM)
有**記憶力**的神經網路,過去出現的資訊透過hidden stage(藍色箭頭)傳播到後面。

### RNN (Recurrent Neural Network)
架構圖:

訓練方式(類似一般NN):

#### Backpropagation through Time (BPTT)


RNN的training issue:
* 對於RNN的error signal δ每往前傳一次要乘上一次W,最後乘了很多次W,所以會導致gradient最後乘起來不是變很大(exploding gradient)就是變很小(vanishing gradient)。

對應到error surface就是有些位置很緩,有些位置很陡,不利於學習。

* Exploding gradient解法:Clipping
當gradient大於某個值時,將其下降某個比例。

* Vanishing Gradient解法:Gating
做一些小門,讓某些通道直接通過去到後面,不用乘上中間的一些matrices。
解決了傳統的 RNN 在長時間的記憶表現並不好的問題(少乘幾次 -> 權重下降的沒那麼快 -> 忘得沒麼快,記憶力提升)

著名例子:
Long Short-Term Memory (LSTM), Gated Recurrent Unit (GRU)
---
## Lecture 3 : Attention Mechanism
* 概念:**不同時間注意在encoding的不同地方**。
* 想解決的問題:當任務的類型為**seq2seq**(輸入為一串資料,輸出也為一串資料)時,用RNN一個字一個字逐一計算(encoding),當輸入很長時,經過多次神經元的運算,**開頭的資訊可能會遺失**。
* 解決方式:讓輸入的資料不會因為遠近而有所不同,而且可以比較注意當前需要用到的資訊片段。 -> 每個步驟都計算一個向量Z,用Z表示要**注意輸入資料的哪個部分**。
### Machine Translation with Attention






### Dot-Product Attention

### Attention的應用
最早用於電腦視覺,現在則應用在NLP,語音辨識(聲音轉文字),圖像辨識(圖片轉文字),影像辨識。
## Lecture 4 : Transformer
### Self-Attention
[論文-Attention Is All You Need](https://arxiv.org/pdf/1706.03762)
* 任兩個輸入之間位置的距離相同 -> 不易受距離順序影響
* 易於**平行運算** -> 將向量合併成矩陣再運算
* 缺點: **缺乏**序列中文字**位置的資訊**,所以只要句子中包含一樣的字,就會獲得同樣的資訊,如“我愛你”和“你愛我”文字相同,但意思不同。
encoding向量a^1^,a^2^,...各自乘上矩陣 W^q^, W^k^, W^v^而獲得向量**query vecter q^1^, q^2^**,...和**key vecter k^1^, k^2^**,...和**value vecter v^1^, v^2^**,...。
將其中一個query q與其他key k做內積,獲得各個位置的attention score a,代表這個位置的資訊此時的重要程度(權重)。
我們在訓練模型就是在**調整矩陣 W^q^, W^k^, W^v^的值**。(通常會直接將a的值當成query,所以取W^q^為identity matrix)

$$ q^1 = W^qa^1 \qquad q^2 = W^qa^2 \qquad ...
$$ $$ k^1 = W^ka^1 \qquad k^2 = W^ka^2 \qquad ...
$$ $$ v^1 = W^va^1 \qquad v^2 = W^va^2 \qquad ...
$$
將 向量query q 乘上 向量key k **合併為矩陣相乘**的形式,易於之後加速做平行運算。
矩陣A經過softmax處理成為矩陣A'。


### Multi-Head Attention
* 概念:把不同的資訊分開來,每組 query q 專注於不同的面向上。
待補充...
### Transformer
* 想解決的問題:Self-Attention**缺乏對於空間,順序上的資訊**。
* 解法:**positional encoding** allows word at different locations to have different embeddings with fixed dimensions. (把位置的資訊一起encode進去)
#### Positional Encoding

將原本的Multi-Head Attention加上Positional Encoding:

小結:

## Lecture 5 : Tokenization, BERT
### Tokenization
可以理解為把一段長資料切割成數個短資料單位,用這個短資料單位來理解文字的意思。
#### Byte-Pair Encoding (BPE)
將出現次數最多的pair以資料中沒有出現的新位元組替換,重複直到覺得VOCAB的位元組數量夠多為止。
以下為BPE Tokenization的示意流程:


pair(e,s)和pair(t,</w>)出現最多次,任選一組合併。(例子選pair(e,s))於是,VOCAB中新增位元組"es"。










### BERT
[論文 - BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805)



上圖說明:原始的 BERT model 過於general,原本當我們要做特定任務時就要重新訓練模型來配合新任務。後來提出一個新概念為 **Fine-tuning** 是指在一個預訓練 (**pre-trained**) 好的模型(如BERT)的基礎上,通過**少量的訓練資料對模型進行調整**,以適應特定任務。
## Lecture 6 : NLG (Natural Language Generation)
很多事情與自然語言生成有關,如:翻譯, 摘要, 對話等。
### Decoding Algorithm
概念:當我們有一個訓練好的模型,生成出一個機率分佈後,decoding algorithm 的功能為**決定要生成什麼字**。
#### 1. Greedy
根據之前生成的字生成**機率最高的下一個字**。

缺點 - 只關注local optimal,會重複產生一樣的句子。
#### 2. Beam Search
每一步只追蹤**機率最高的前k個sequence**。


beam size 大小的 trade off:
* 小 beam size : 比較focus在topic上,但可能會較為**不通順**
* 大 beam size : 很safe,**general**,但**不符合當下的使用情境**
#### 3. Top-k Sampling
限制**只從出現機率前 k 高**的字裡來sample出要輸出的下一個字。

Top-k sampling issue:
* **Narrow Distribution**:
當機率都在少數幾個(x個)字上面,而 x << k,則可能會sample到出現機率較低,不適合的字。

* **Broad Distribution**:
若每個字出現的機率都差不多接近時,使用 top-k sampling 反而會限制其輸出的多樣性。

#### 4. Nucleus(Top-p) Sampling
* 想解決的問題: Top-k Sampling 沒辦法根據詞彙的機率分佈來調整 sampling 的詞彙數。
* 概念: 根據distribution來改動top-k的k值,只**sample機率累加超過p的set**。
當distribution越 narrow,只需要從越少的詞彙數中sample;當distribution越 Broad,需要從越多的詞彙數中sample。

### Generation Control
#### Temperature τ
* 功能: 一個調控模型輸出**多樣性**, **穩定性**的手段。
* 效果: **τ 越大**,會使每個詞的機率分佈變更**uniform**,增加模型sample不一樣詞彙的機率(**多樣性**);**τ 越小**,會使每個詞的機率分佈變更**narrow**,使模型更趨向於sample少數詞彙(**穩定性**)。

#### Repetition Penalty
* 想解決的問題: 當模型沒有訓練好的話,**容易產生重複的句子**( 寫過HW2就知道:) ),因為模型是根據輸入的內容來生成句子。當輸入屬於某個topic時,生成出與該topic相關的詞彙的機率會上升,進而容易重複sample出那些詞彙。
* 解法: 當某個詞彙被sample出來後,**下降**該詞彙被sample出來的**機率**。

### Evaluation
Automatic evaluation 又可分為 **Word overlap** metrics 和 **Embedding** metrics。 **Word overlap** metrics 考慮模型生成的句子與ground truth之間**用詞的相似性**,如:BLEU, ROUGE, METEOR。 **Embedding** metrics 評估兩個句子在hidden layer是否相近(意思是否相近,而不是單純比較用詞)。
#### BLEU
[論文 - BLEU: a Method for Automatic Evaluation of Machine Translation](https://aclanthology.org/P02-1040.pdf)
基於 N-gram overlap,考慮 **precision** - 模型產生的句子的n-gram是否是正確的(有出現在正確答案句子的n-gram裡面)。

#### ROUGE (Recall-Oriented Understudy for Gisting Evaluation)
[論文 - ROUGE: A Package for Automatic Evaluation of Summaries](https://aclanthology.org/W04-1013/)
基於 N-gram overlap,考慮 **recall** - 正確答案句子的n-gram是否被包含在模型產生的句子的n-gram裡面。

## Lecture 7 : Prompt Based Learning

### Prompt Tuning
x-Shot 的意思是先給模型x個例子,才問模型問題。

Question: 現在的LLM參數量太大了,當我們沒有足夠的運算資源去訓練,改變其內部參數,還能做什麼呢? Ans: 適當地下prompt能夠去影響模型的output。



## Lecture 8 : Adaptation
### PEFT (Parameter-Efficient Fine-Tuning)
#### Adapter

#### [LoRA](https://arxiv.org/abs/2106.09685)

---
## Homework 1: Chinese Extractive Question Answering (QA)
作業一要參加一個舉辦在Kaggle平台上的機器學習比賽-[連結](https://www.kaggle.com/competitions/ntu-adl-2024-hw-1-chinese-extractive-qa/data)。這次的任務要訓練模型**根據給定的四個文章段落來回答一個問題**,助教保證問題可以根據四個文章中的其中一個來回答,並且檢查答案的機制為Exact Match (EM)。
### 任務流程圖

上圖說明: 整個流程又可以分為兩個子任務。第一個任務為**從四個文章中找出問題的答案藏在哪個文章內**(4選1的單選題);第二個任務為**從一個給定的文章內找出某個問題的答案所在的位置**(輸出的形式會像是從第x個字元到第y個字元)。
### [資料](https://www.kaggle.com/competitions/ntu-adl-2024-hw-1-chinese-extractive-qa/data) & 環境說明
| **檔名** | **說明** |
|--------------------|------------------------------------------------------------------------------------------|
| context.json | 一個包含所有文章的list。 |
| train.json | 含21714筆用於訓練模型的標記訓練集。(標記:有正確答案的意思) |
| valid.json | 含3009筆用於訓練模型或驗證的標記驗證集。 |
| test.json | 含2213筆未標記的測試集。(比賽方在檢查的就是你的模型在test.json的作答情形) |
| sample_submission.csv | 一個樣本提交文件。您應該以相同的格式提交您的提交。 |
| **欄位** | **說明** |
|--------------------|------------------------------------------------------------------------------------------|
| id | 問題 ID。 |
| question | 問題。 |
| paragraphs | 一個包含 4 個段落 ID 的列表(0-base)。 |
| relevant | 相關段落的 ID(0-base)(test.json 沒有這部分)。 |
| answer | 問題的答案(test.json 沒有這部分)。 |
| text | 答案文本。 |
| start | 答案範圍在相關段落中的起始位置。 |
執行於 **Python3.10** 環境
建議用 [Miniconda](https://docs.anaconda.com/miniconda/) 開 conda 虛擬環境。
```bash=
# 下載並啟用miniconda
mkdir -p miniconda3
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda3/miniconda.sh
bash miniconda3/miniconda.sh -b -u -p miniconda3
rm miniconda3/miniconda.sh
source miniconda3/bin/activate
# 創建並啟用 python3.10 虛擬環境
conda create -n ADL_HW1_env python=3.10
conda activate ADL_HW1_env
```
### 任務一方法
第一個任務要我們讓模型**從4個文章中選擇出有給定的問題的答案的文章(4選1單選題)**,所以我們可以套用[**MC sample code**](https://github.com/huggingface/transformers/blob/main/examples/pytorch/multiple-choice/run_swag_no_trainer.py)來fine tune模型,模型可以從[這裡](https://huggingface.co/models)選(我的作法是選[chinese-bert-wwm](https://huggingface.co/hfl/chinese-bert-wwm),也有人用[chinese-roberta-wwm-ext](https://huggingface.co/hfl/chinese-roberta-wwm-ext))。Sampel code名稱中的[SWAG](https://huggingface.co/datasets/allenai/swag/blob/main/README.md#data-instances)為一種定義好的資料格式,有 sent1, sent2, ending0, ending1, ending2, ending3, label...等欄位。
#### 任務一第一件難事
把 train.json 和 valid.json 中的欄位 question, paragraphs, relevant 轉換為 SWAG格式 中的 sent1, sent2 ...。 其對應可以參考[ADL-2024-HW1-SWAG資料](https://huggingface.co/datasets/Binga288/ADL-2024-HW1-SWAG)。 其中,sent2 的部分我直接以 “*請問上述問題的答案出現在以下哪個文章內?*” 取代。
```
文章為sent1;問題為sent2;四個選項分別為ending0~3;label為問題根據文章內容從四個選項選出的正確答案的index
```
接好後就可以開始train(fine tune)了。
#### 任務一第二件難事
fine tune 完後可以在 \-\-output_dir 資料夾內獲得模型的資料,但由於 sample code 沒辦法直接 inference test data,所以我們要稍微改動一下 sample code 讓它的功能從 fine tune 變為 inference。
觀察一下程式碼會發現最後幾行有一段程式碼似乎可以利用,這段程式碼原本的功能為預測 validation data 的 tag。
```python=
predictions = outputs.logits.argmax(dim=-1)
```
我們可以將 test.json 丟到原本 valid.json 的位置,如此一來上面這段程式碼就會變成去預測 test data 的 tag,將 predictions 記錄下來,即可知道 test.json 內每個題目的答案所可能在的文章是哪個。(這部分概念簡單,但實際要改的東西很多)
[註] 在 inference 時,參數 *model_name_or_path* 放跟之前 fine tune 時的參數 *output_dir* 一樣即可,裡頭有模型的種類,權重(model.safetensors)等參數資訊。
**[注意] 在inference時,記得刪除 metric = evaluate.load(...),這個步驟需要連接到 hugging face 的網站。**
### 任務二方法
第二個任務要**拿第一個任務輸出的文章當輸入,並從文章內截取出問題的答案**(QA)。我們可以套用[**QA sample code**](https://github.com/huggingface/transformers/blob/main/examples/pytorch/question-answering/run_qa_no_trainer.py)來fine tune模型,模型可以選擇[chinese-lert-large](https://huggingface.co/hfl/chinese-lert-large)或 [bert-base-chinese](https://huggingface.co/google-bert/bert-base-chinese)。sample code所讀取的資料格式為[squad](https://huggingface.co/datasets/rajpurkar/squad),有 id, title, context, question, answers 欄位。
```
任務一輸出的文章為context;問題為question;標準答案的內容與起始位置為answers
```
接好後就可以開始train(fine tune)了。
任務二的 sample code 比任務一的 sample code 好的一點在於有寫 inference 的邏輯,但若你和我一樣 fine tune 和 inference 是分兩步執行的話,要記得把程式碼內 training 和 validation 的部分刪除。
**[注意] 在inference時,記得刪除 metric = evaluate.load(...),這個步驟需要連接到 hugging face 的網站。**
inference 完的輸出放在 output_dir 內的 eval_predictions.json,儲存方式類似 `"7f4f68726faed6b987e348340a9e6a61": "\u77f3\u6cb9"`,key 是 id,value 是 answer,要將 answer 的 unicode 編碼轉換為中文。
[註] 當初第一次 fine tune QA model 時,seed 設很大,結果 valid_Acc 超低;第二次 seed 設為 1,valid_Acc 很好,但是 test_Acc 為 0;最後我又試了另一個 seed 後,valid_Acc 和 test_Acc 的效果都接近80%。 如果 inference 效果不好時,可以考慮換個 seed 再試看看。
### Bonus 任務
Bonus 部分要求我們訓練一個 end-to-end model ,目標是單一 model 能夠直接運用給定的 test.json 及 context.json 得到所要求的結果,而不需如先前一般使用兩個模型分開 inference。助教給出的建議是使用能夠接受較長 input 的 bert 變體來做 fine-tuning ,這固然是可行的方法之一,但目前 huggingface 上能接受此類 Question Answering 接口的 long-form bert variants 模型並不多。事實上,我們可以仿造先前任務二中運用 window_size 與 doc_stride 的演算法來做處理。該演算法將一段長度大於 512 的 paragraph 進行切割處理,每隔 doc_stride 的距離切一刀,並自動取一段適當的文章範圍與問題本身合併,進行 padding 後作為 bert 的 input 輸入。文章會因此被分為多段,我們可將 test.json 中給出的四段可能文章合併成一長串,並紀錄在每個 window 中所採集的 max(prob_start + prob_end) 位置作為該切片中最有可能的答案(此處可進行 top_k 過濾以得到更準確的結果),接著考慮所有文章切片,取其中機率總和最高者即可。
[註] 此方法甚至不需要重新訓練模型,只需要取先前任務二中訓練的便能完成,且理論上準確度並不會和基礎任務相差太多,甚至可能更好
### 相關連結
[Kaggle比賽連結](https://www.kaggle.com/competitions/ntu-adl-2024-hw-1-chinese-extractive-qa)
[助教說明投影片](https://docs.google.com/presentation/d/1V5KE-AOTiVXWZjMVnr3GXyy_EjEMHeRKfeyudyeevl8/edit#slide=id.p)
[NLP Course - Question answering](https://huggingface.co/learn/nlp-course/en/chapter7/7?fw=pt)
---
## Homework 2: Chinese News Summarization (Title Generation)
作業二要我們 fine tune 一個 model,讓 model **做中文新聞文章摘要**,並用 [**ROUGE** score](#ROUGE-Recall-Oriented-Understudy-for-Gisting-Evaluation) 來評估我們訓練的 model 的輸出與標準答案的相似程度,分數越高代表越相似。我們的目標是讓訓練完的模型在 public 和 private test case 上的 rouge score 大於 baseline。
### 任務示意圖

上圖說明:模型讀入一個文章,生成出其摘要

上圖說明:這是bench mark,比較模型生成的摘要與參考答案的相似程度
### [資料](https://drive.google.com/drive/folders/1PMa25MwIVWTRhUtkWTfBFgqbqmGAxG2-) & 環境說明
| **檔名** | **說明** |
|--------------------|------------------------------------------------------------------------------------------|
| train.jsonl | 含**21710**筆資料,每筆資料的結構為{"date_publish", "**title**", "source_domain", "maintext", "split", "id"},"split"鍵的值固定為"train"。 請自行切割成 train 和 validation set 來訓練模型。 |
| public.jsonl | 含**5494**筆資料,結構同上, "spilt"鍵的值固定為"dev"。 這個檔案為 public testcase 的內容,**請勿用它來 train 模型**!! |
| sample_test.jsonl | 結構為每列有{"date_publish", "source_domain", "maintext", "split", "id"}。**沒有"title"**,因為"title"是這個模型要預測的東西。|
| sample_submission.jsonl | 結構為每列有{"title", "id"} |
| 欄位 | 說明 |
| -------- | -------- |
| "title" | 關於報導內容的重點摘要(這是模型要預測的東西) |
| "maintext" | 完整文章報導內容 |
執行於 **Python3.8.10** 環境
### 任務方法
從cool討論區看起來可以使用 [**Sum sample code**](https://github.com/huggingface/transformers/blob/main/examples/pytorch/summarization/run_summarization_no_trainer.py) 來 fine tune [**mt5-small**](https://huggingface.co/google/mt5-small) 。
打開data資料夾會發現裡頭只有提供 train data,可以先自行將其分割成 train 和 validation data(我的比例是19:1,但 validation data 不會影響模型更新權重的過程,因此以作業分數為導向的話可以試著降低 validation data 的比例)。接著就可以開始訓練模型了,以下是一些可以調整的參數 -
1. train時 (python指令傳入的): **batch_size**, **learning_rate**, **epochs**。
2. inference時 (使用 Transformers 庫中的 generate 方法進行文本生成時的參數,在 sample code 裡於變數 gen_kwargs 內設定): **num_beams**, **top_k**, **top_p**, **temperature**, repetition_penalty, length_penalty。若使用除了 beam search, Greedy 之外的具有**隨機性**的策略,要在 generate 函數中傳入 **do_sample=True**,代表隨機取樣(不傳的話預設 do_sample=False,會導致無論怎麼改 top_k, top_p, temperature 的值 inference 結果都一樣)。
此外,助教在執行 inference 的環境是斷網的,若用到 [nltk](https://www.nltk.org/) 的 tokenizer 請預先下載好,並把它加入環境變數內。
**[注意] 在inference時,記得刪除 metric = evaluate.load(...),這個步驟需要連接到 hugging face 的網站。**
Report 部分需要我們在訓練模型的過程畫出 ROUGE Score v.s. training steps 的圖,我每訓練 1 epoch 做一次 inference valid dataset 並用eval.py檢驗輸出的ROUGE score。當 epoch==0 時,模型還沒學到任何東西,因此可能在摘要內輸出包含"(雙引號)的字串。當執行 [eval.py](https://github.com/deankuo/ADL24-HW2/blob/master/eval.py) 解析輸出的 jsonl 檔時會出現錯誤,需要對 inference 輸出的字串做預處理-把每個\"(雙引號)前加上\\(跳脫字元)。
```python=
pred_ = pred.replace('\"', '\\\"') # 將 " 替換為 \"
```
想要簡單一點就從 epoch == 1 才開始做 inference,就不會在摘要內出現"(雙引號)了。
### Bonus 任務
Bonus 部分要求我們試著將 GPT-2 應用在摘要生成上。這項任務其實對 GPT-2 挺困難的,因為 GPT-2 擅長的是僅根據上文選擇機率最高的字作為下一個輸出,因此無論是否經過微調,改善的幅度都非常有限。要完成 Bonus ,會需要在 Report 中解釋 GPT-2 的 architecture 和你使用的超參數,並且使用任何和 GPT-2 相關的模型(有無微調皆可)輸出摘要,計算 ROUGE score 再和 T5 的結果進行比較即可,沒有意外的話效果應不如 T5 。順帶一題,我選擇使用的 prompt engineering 方法似乎能夠使模型的輸出「稍微」自然一些(但效果依然很差)。
### Baseline
用 [**ROUGE** score](#ROUGE-Recall-Oriented-Understudy-for-Gisting-Evaluation) 來評估模型**輸出和參考答案間的相似程度**,數值越高代表越相似。表格內的值為 f1-score * 100 。
#### public test case
| rouge-1 | rouge-2 | rouge-L |
| -------- | -------- | -------- |
| 22.0 | 8.5 | 20.5 |
#### private test case
作業截止後才會公布。
| rouge-1 | rouge-2 | rouge-L |
| -------- | -------- | -------- |
| 23.6 | 9.3 | 21.3 |
### 相關連結
[助教說明投影片](https://docs.google.com/presentation/d/1C9dhFQvz--9sDtjGukSL6Lmfp8CPQgmG/edit#slide=id.p1)
[Hugging Face從零到一 — 從初始化到fine tune教學](https://shengyanlin0503.medium.com/hugging-face%E5%BE%9E%E9%9B%B6%E5%88%B0%E4%B8%80-%E5%BE%9E%E5%88%9D%E5%A7%8B%E5%8C%96%E5%88%B0fine-tune%E6%95%99%E5%AD%B8-da0f19c74acc)
[Fine-tuning the multilingual T5 model from Huggingface with Keras](https://medium.com/@radicho/fine-tuning-the-multilingual-t5-model-from-huggingface-with-keras-f7f619ec5cfe)
[NLP Course - Summarization](https://huggingface.co/learn/nlp-course/en/chapter7/5)
---
## Homework 3
訓練模型將**文言文翻譯成白話文**或將**白話文翻譯成文言文**。
### 任務說明

### [資料](https://drive.google.com/drive/folders/1HCG8EPoY7JE4XQQpxz41cEk0tfR05IUG) & 環境說明
| **檔名** | **說明** |
|--------------------|------------------------------------------------------------------------------------------|
| train.json | 含**10000**筆資料,每筆資料含有{id, instruction, output}。instruction內會包含請翻譯成文言文的指示(如果沒有指示,預設是翻譯成白話文)和文章。 |
| public_test.json | 含**250**筆資料,每筆資料含有{id, instruction, output}。請勿拿 public_test 來訓練模型!! |
| private_test.json | 含**250**筆資料,每筆資料含有{id, instruction}。 |
執行於 **Python3.10** 環境
### 任務方法
可參考的 source 包括 [Fine-Tuning Gemma Models in Hugging Face 教學](https://huggingface.co/blog/gemma-peft) or [qlora](https://github.com/artidoro/qlora)。
在本次作業中需要 fine tune [zake7749/gemma-2-2b-it-chinese-kyara-dpo](https://huggingface.co/zake7749/gemma-2-2b-it-chinese-kyara-dpo) ,若想親自刻 training 的 code 的話,可以使用 trl 套件中的 SFTTrainer 來進行高效的 qlora finetuning。資料處理方面,通常會想將助教提供的 train.json 分割為 train set 及 valid set,但實作時發現,本作業通常只需訓練 1 epoch 即可,也許我們可以嘗試將全部資料用來訓練。
助教另外提供了 utils.py ,主要方便我們進行訓練和推理時能夠直接載入 bnb_config 和 prompt 做使用,前者能夠用於 model quantization ,幫助我們減少訓練時所使用的 VRAM ,後者對於我們達到作業要求的 baseline 可說是至關重要。
以下是助教提供的預設 prompt :
```python=
def get_prompt(instruction: str) -> str:
'''Format the instruction as a prompt for LLM.'''
return f"你是人工智慧助理,以下是用戶和人工智能助理之間的對話。你要對用戶的問題提供有用、安全、詳細和禮貌的回答。USER: {instruction} ASSISTANT:"
```
請試著修改以上 prompt,盡可能降低 model 的 perplexity 吧!
修改 prompt 後,我們還需要設定 lora 的 configuration,以下提供了一個範例:
```python=
lora_config = LoraConfig(
r=64,
lora_alpha=32,
lora_dropout=0.1,
target_modules=["q_proj", "o_proj", "k_proj", "v_proj", "gate_proj", "up_proj", "down_proj"],
bias="none",
task_type="CAUSAL_LM"
)
model = get_peft_model(model, lora_config)
```
上例的重點在於我們僅選擇所有的 projection layer ,屬於進行普通 lora 微調時的慣用做法, task_type 也建議設為 CAUSAL_LM 即可。設定完 config 後只需要使用 get_peft_model 進行 apply 就能開始微調了。
最後,使用 SFTTrainer 對 model 進行 finetuning,這裡使用 peft_config 參數讀入以上設定的 lora config。
完成訓練後,我們可以使用助教提供的 ppl.py 檢驗 adapter 是否有達到 baseline 。
### Bonus 任務
同樣是 fine-tune LLM,只是對象從 gemma2 改成了彥廷學長的 [yentinglin/Llama-3-Taiwan-8B-Instruct](https://huggingface.co/yentinglin/Llama-3-Taiwan-8B-Instruct),整體大同小異,不過這顆 model 有專注在台灣本土的中文資料上 fine-tune 過,理論上會有更好的表現。
### baseline
* Public baseline: ppl = 17.500↓
* Private baseline: ppl = 24.000↓
* prediction.json: Human evaluation
### 相關連結
[助教說明投影片](https://docs.google.com/presentation/d/1gbutje764HPndSCmS-I6TZuaGvJqPZwNQj-DR4x2H3o/edit?usp=sharing)
---
## Final Project
今年有兩個選擇,完成助教提供的 kaggle 競賽 - [Medical Diagnosis](https://www.kaggle.com/competitions/adl-2024-final-project-medical-diagnosis) & [Text-to-SQL Generation](https://www.kaggle.com/competitions/adl-2024-final-project-text-to-sql-generation),或自行發想題目進行,3~5人一組。今年很榮幸請到 Appier 的 researcher ,為我們講解 kaggle 的部分。(沒可能讓你抄,自己想吧!)
[助教說明投影片](https://docs.google.com/presentation/d/1sG7cwG52AIDTf736F6IjFEDEQ59vzbt_JJlNMMFRUVA)