---
title: LLM-stat # 簡報的名稱
tags: LLM # 簡報的標籤
slideOptions: # 簡報相關的設定
theme: black # 顏色主題
transition: 'fade' # 換頁動畫
spotlight:
enabled: true
---
# 統計數據 AI
基於大語言模型的發展,我們希望能夠訓練出專門回答統計與機器學習相關問題的 AI 模型
## 數據蒐集
我們採用了 stackoverflow 上面網友們的問題與答案,我們用問題的 tag 來區分該問題主要關注的領域,我們收錄了擁有回答的問題,並且只收錄 upvote 最高的相關回答,以下是該數據的相關統計資訊
| Info/Dataset | Overall | Math | Stat | ML | Python |
| -------------- | -------- | ------- | ------- | -------- | -------- |
| samples | 88873 | 12879 | 13062 | 34546 | 28386 |
| tokens | 50014715 | 5392047 | 6132554 | 21163892 | 17326222 |
| avg input len | 562.77 | 418.67 | 469.50 | 612.63 | 610.38 |
| max input len | 25549 | 24637 | 25537 | 24237 | 25549 |
| med input len | 324 | 268 | 250 | 336 | 382 |
| avg output len | 315.60 | 373.80 | 329.35 | 272.55 | 335.27 |
| max output len | 24336 | 24336 | 20411 | 12405 | 18157 |
| med output len | 190 | 218 | 205 | 166 | 202 |
Dataset columns 分別代表不同 tag 下我們蒐集資料的部分統計,我們分別計算每次問題與回答的 token 數量 (這裡我們並無節錄 instruction 統計量)
- **instruction:** 問題
- **input:** 問題詳細內容
- **output:** upvote 最高之回答
我們關注於 token 長度的中位數,可以發現皆坐落於 200 ~ 400 附近,因此在訓練過程中,我們可以設置參數 max_len 至 512 或者 2048 來減少模型顯存占用
### 數據清洗
網路上蒐集來的數據品質良莠不齊,因此我們需要做適當的資料清洗,在 stackoverflow 上面抓到的文本是 html 格式,以下我們介紹對於 html 文本的修飾方法。
我們使用下列代碼來修飾 html 文本
```python=
import html
import re
CLEANR = re.compile('<.*?>')
def cleanhtml(raw_html):
cleantext = re.sub(r'<pre.*code>', '\n```r\n', raw_html)
# Replace </code></pre> with triple backticks
cleantext = re.sub(r'</code></pre>', '```\n', cleantext)
cleantext = re.sub(CLEANR, '', cleantext)
cleantext = html.unescape(cleantext)
return cleantext
```
主要使用正則表達式來移除 html 中的 tag,並且在代碼區塊,改為用一對引號包含,具體作用如下
- 原始文本
```
<div class="s-prose js-post-body" itemprop="text">
<p>It doesn't make much sense to talk about the R-squared of individual variables in a multivariate model. Delta R-squared, as Zephryl mentions, or partial R-squared are two measures that will do something like what you want.</p>
<p>Discussion on delta R-squared and partial R-squared: <a href="https://stats.stackexchange.com/questions/64010/importance-of-predictors-in-multiple-regression-partial-r2-vs-standardized">https://stats.stackexchange.com/questions/64010/importance-of-predictors-in-multiple-regression-partial-r2-vs-standardized</a></p>
<p>Partial R-squared can be calculate like this:</p>
<pre><code>fm1 <- lm(rating ~ ., data=attitude)
# summary(fm1 <- lm(sr ~ ., data=LifeCycleSavings))
# summary(fm1 <- lm(Employed ~ ., data=longley))
# summary(fm1 <- lm(stack.loss ~ stack.x))
reduced <- lapply(seq_len(ncol(fm1$model)-1), function(x) update(fm1, terms(fm1)[-x]))
reduced.sse <- sapply(reduced, function(x) deviance(x))
fm1.sse <- deviance(fm1)
partial.r2 <- c(0, (reduced.sse - fm1.sse)/reduced.sse)
(fm1.coefs <- cbind(summary(fm1)$coefficients, partial.r2))
# Estimate Std. Error t value Pr(>|t|) partial.r2
# (Intercept) 10.787076386 11.58925724 0.93078238 0.36163372105 0.0000000000
# complaints 0.613187608 0.16098311 3.80901816 0.00090286788 0.3868076082
# privileges -0.073050143 0.13572469 -0.53822295 0.59559392051 0.0124382943
# learning 0.320332116 0.16852032 1.90085160 0.06992534595 0.1357684079
# raises 0.081732134 0.22147768 0.36903102 0.71548008844 0.0058861866
# critical 0.038381447 0.14699544 0.26110638 0.79633426421 0.0029554369
# advance -0.217056682 0.17820947 -1.21798623 0.23557704863 0.0605914609
</code></pre>
</div>
```
- 修飾後文本
```
It doesn't make much sense to talk about the R-squared of individual variables in a multivariate model. Delta R-squared, as Zephryl mentions, or partial R-squared are two measures that will do something like what you want.
Discussion on delta R-squared and partial R-squared: https://stats.stackexchange.com/questions/64010/importance-of-predictors-in-multiple-regression-partial-r2-vs-standardized
Partial R-squared can be calculate like this:
fm1 <- lm(rating ~ ., data=attitude)
# summary(fm1 <- lm(sr ~ ., data=LifeCycleSavings))
# summary(fm1 <- lm(Employed ~ ., data=longley))
# summary(fm1 <- lm(stack.loss ~ stack.x))
reduced <- lapply(seq_len(ncol(fm1$model)-1), function(x) update(fm1, terms(fm1)[-x]))
reduced.sse <- sapply(reduced, function(x) deviance(x))
fm1.sse <- deviance(fm1)
partial.r2 <- c(0, (reduced.sse - fm1.sse)/reduced.sse)
(fm1.coefs <- cbind(summary(fm1)$coefficients, partial.r2))
# Estimate Std. Error t value Pr(>|t|) partial.r2
# (Intercept) 10.787076386 11.58925724 0.93078238 0.36163372105 0.0000000000
# complaints 0.613187608 0.16098311 3.80901816 0.00090286788 0.3868076082
# privileges -0.073050143 0.13572469 -0.53822295 0.59559392051 0.0124382943
# learning 0.320332116 0.16852032 1.90085160 0.06992534595 0.1357684079
# raises 0.081732134 0.22147768 0.36903102 0.71548008844 0.0058861866
# critical 0.038381447 0.14699544 0.26110638 0.79633426421 0.0029554369
# advance -0.217056682 0.17820947 -1.21798623 0.23557704863 0.0605914609
```
## 數據對齊
要微調 LLM,並且保證回答的質量,資料品質自然非常重要,在訓練模型 backbone 部分,我們可以找網路上各種 paper 或相關論壇的回答來保證數據的高質量,然而,在問答模型中,我們對於數據需求是高質量的 "對齊" 數據,也就是 "問題" 與 "回答" 都要是高質量數據,才能夠保證模型品質。在網路論壇獲取的資料多半是良莠不齊的問答,進而可能產生數據污染的難題,那麼要如何獲取高質量對齊數據呢? 目前已知的管道如下
- **Self-Instruct:**
- 讓 ChatGPT 為你量身訂做一筆高質量的對齊數據,因為 ChatGPT 本身就是高質量的模型,但是該方案需要申請 API,並且也違反了 OpenAI 的規章
:::danger
禁止使用 ChatGPT 的輸出對 OpenAI 進行競爭
:::
- **私有數據:**
- 由機構各自蒐集數據,數據的問答主要由該機構提供,並非調用 API 生成
- **[ShareGPT](https://sharegpt.com/):**
- ShareGPT 是一個公開網站,讓用戶自主公開與 ChatGPT 的對話內容
## 模型選擇
目前問答模型的先驅有 Alpaca、Vicuna 等等。在 hf 網站上提供了一個 LLM 競技場,來比較不同 LLM 之間的能力
- [Leaderboard](https://huggingface.co/spaces/lmsys/chatbot-arena-leaderboard)
| Model Name | LLaMA | Alpaca | Vicuna | Bard/ChatGPT |
| ------------------- | -------------------------------------- | ------------------------------------------------ | --------------------------------------- | ------------ |
| Dataset | Publicly available datasets (1T token) | Self-instruct from davinci-003 API (52K samples) | User-shared conversations (70K samples) | N/A |
| Training code | N/A | Available | Available | N/A |
| Evaluation metrics | Academic benchmark | Author evaluation | GPT-4 assessment | Mixed |
| Training cost (7B) | 82K GPU-hours | $100 (training) $500 (data) | $140 (training) | N/A |
| Training cost (13B) | 135K GPU-hours | N/A | $300 (training) | N/A |
Alpaca 和 Vicuna 皆使用了 LLaMA 作為基礎模型,接下來我們來看看兩者之間的差別吧
### Alpaca
Standford Alpaca 在 Meta 開源的 LLaMA 上面進行全參數的微調。主要的目的是要讓 AI 學會
- 強大的基礎 LM
- 高質量的 instruction data
在 Alpaca 的設計中,Standford 選用 Meta 的 LLaMA-7B 做為 base model,並使用 Self-Instruct 的方式微調,所謂的 "Self-Instruct" 指的是使用較大的模型生成數據來訓練小的模型,其概念類似於知識蒸餾。

### Vicuna
Vicuna 使用 ShareGPT 來獲取 "多樣性" 的數據,在 ShareGPT 中,用戶多上傳自己認為有趣的問答,因此在多樣性上,相較於調用 API 生成的 Alpaca,Vicuna 表現更生動。但是相較於調用 API 生成的數據,用戶上傳數據多半包含格式錯誤,語法等問題,因此在數據清洗方面作者下了很大的功夫。

在訓練方面,作者改進了以下三點:
- **Multi-turn conversations:** 在一些問題中,答案不是通過一次提問就可以獲得的,當要透過多次提問才能夠獲取答案,我們就稱為 Multi-turn conversations,作者在計算 loss 時,只單獨計算 chatbox's output 作為損失
- **Memory Optimizations:** 為了讓模型在長文任務上表現更好,作者將 max_length 從 512 提升為 2048。並使用了 [gradient checkpoint](https://arxiv.org/pdf/1604.06174.pdf) 和 [FalshAttention](https://arxiv.org/pdf/2205.14135.pdf) 減少內存占用
- **Cost Reduction via Spot Instance:** 訓練長文本數據是一個非常耗時的任務,作者使用開源項目 [SkyPilot](https://github.com/skypilot-org/skypilot) [manage spot](https://skypilot.readthedocs.io/en/latest/examples/spot-jobs.html) 的方式減少開支與時間
## Reference
- [https://lmsys.org/blog/2023-03-30-vicuna/](https://lmsys.org/blog/2023-03-30-vicuna/)
- [https://zhuanlan.zhihu.com/p/618389519](https://zhuanlan.zhihu.com/p/618389519)