9.6 文章續寫&問答對話-GPT
前言
本節介紹生成式對話模型的基座——GPT(Generative Pre-Training),將會從OpenAI的四篇論文入門,瞭解GPT的概念及發展歷程。隨後通過GPT2的訓練及推理,加深對GPT的理解。最後對本節進行小結。
GPT系列論文簡讀
生成式對話模型(以ChatGPT為代表)的發展歷史可以關注OpenAI在GPT系列上的研究,這裡通過GPT1, 2, 3和InstructGPT來瞭解GPT的發展及變化,有助於理解大語言模型。
- GPT: Improving Language Understanding by Generative Pre-Training https://www.mikecaptain.com/resources/pdf/GPT-1.pdf
- GPT2:Language Models are Unsupervised Multitask Learners https://insightcivic.s3.us-east-1.amazonaws.com/language-models.pdf
- GPT3:Language Models are Few-Shot Learners https://arxiv.org/abs/2005.14165
- Instruct GPT:Training language models to follow instructions with human feedback https://arxiv.org/pdf/2203.02155.pdf
GPT1
GPT1《Improving Language Understanding by Generative Pre-Training》由OpenAI團隊在2018年6月公開,首次將Transformer的decoder用於大規模預訓練,從而實現從無標籤資料從訓練具備語言理解的基礎模型,為NLP下游任務提供強大底座。
GPT關鍵字:預訓練+微調(全文似乎就沒有其它關鍵點了...)
GPT模型結構及下游應用範式,可以根據文中圖1來理解。
GPT模型結構:12層Transformer的decoder,再根據不同任務接不同的輸出頭。
下游任務微調範式:論文介紹了GPT應用於四種下游任務,分別是文本分類、蘊含、句子相似性、閱讀理解(多項選擇題)
- 文本分類:輸出特徵向量接入一個linear層做分類;
- 蘊含:蘊含是涉及兩個句子的二分類問題,這裡為了保證基礎模型架構不變動,把兩個句子通過特殊的token Delim來拼接,然後接linear做二分類。
- 句子相似性:兩個句子拼接為一個序列,根據句子前後順序,可以獲得兩個序列,分別輸入模型,將兩個特徵向量相加,再接linear做二分類。
- 多項選擇題:多選題有3部分資訊,原始文本、問題、答案,將不同的選項拼接起來得到多個序列,每個序列最終輸出一個概率,最後把多個選項通過softmax得到最終的概率。
訓練情況:
- 預訓練7000本書,具體資料量未說明,100個epoch,bs=64, lr=1e-4級別
- 微調,通常3個epoch,bs=32, lr=1e-5級別。
小結:GPT採用Transformer的Decoder作為元件,採用MLM進行預訓練獲取基礎模型,基於預訓練好的模型,實現一個模型架構四種NLP任務微調,獲取9個任務的SOTA,表明了預訓練+微調範式有效。
GPT2
GPT2:《Language Models are Unsupervised Multitask Learners》
在BERT提出後的4個月,GPT2出世,繼續堅定採用decoder架構(BERT是encoder模組堆疊),在更大尺寸、更多資料上進行預訓練,並在多個NLP任務(GPT提及4個任務,BERT提及4類任務)上達到SOTA。
GPT2的文章沒有過多介紹演算法,這裡簡單記錄幾個關鍵點:
- 爬取4500萬連結,清洗出800萬文檔,共計40GB。
- 詞表大小50257,上下文從512變為1024.
- 詞表策略採用優化後的BPE,可將詞表大小縮減2-3倍(13萬-->5萬)
- 探索zero-shot learning:gpt中在微調時採用了特殊token來讓模型理解人類的意思,需要執行特定任務;GPT2希望做到在無需微調,即預訓練階段就讓模型具備根據輸入資訊來執行特定任務的能力,這就是零樣本學習,預訓練好之後,模型就可以完成特定任務,無需樣本。如何讓模型能完成特定任務呢?舉個機器翻譯的例子,只要將輸入給模型的文本構造成 translate english to chinese, [english text], [chinese text] 就好了。比如:translate english to chinese, [machine learning]。這就是prompt的概念,預訓練模型可以根據使用者的輸入來理解任務。這需要預訓練模型具備大量類似的訓練資料(這也是後續大模型有base和chat的區別,chat模型加入更多的對話資料,實現對話能力,base模型更多的是知識能力)。
GPT3
GPT3:《Language Model are Few-Shot Learners》
隨著資料與算力的發展,同時預訓練的具體潛力被認可,OpenAI在GPT2的基礎上進行了多方面的投入,資料增長1000倍(40GB->45TB),模型擴大100倍(1.5B -> 175B),論文作者增大7倍(4人->31人)。由此可見,GPT3是一個大力出奇跡的作品,耗費大約1200 萬美金訓練。
GPT3的論文有75頁之多, 這裡簡要梳理整體內容。
本文主旨:利用大模型、大資料來無監督訓練GPT,探索它在少樣本學習上的能力,希望讓GPT模型更接近人類的思考方式。
本文關鍵字:Few-Shot learning,任務無關 (Task-agnostic)
- 數據量:來自互聯網、高品質書籍文章等的45TB資料,總token達到260B(0.26T;2024年大模型訓練資料一般在2-5T的tokens)。
- 資料處理:互聯網爬取資料中過濾低質量數據;文檔級別的數據去重;加入高品質資料;
- 資料處理的bug:為了讓模型在評估資料集上公平的測評,需要把訓練集中的資料污染過濾掉,雖然做了,但最後發現還是存在資料污染。遺憾的是,因模型訓練過於昂貴,無法重新訓練了。
- 模型設置:做了8個不同尺寸的模型,最大的1750億參數,命名為GPT3,結構與GPT2沒有過多差別
- 模型訓練:batchsize也做了預熱,逐步增大batchsize;學習率預熱 375 M tokens,總共訓練260 B tokens。樣本全部組裝為長度是2048的序列。
- 模型評估:在各類NLP任務上評估了少樣本學習的能力。
- 模型缺點:會出現重複、缺乏連貫、以及單向結構的弊端(BERT那樣的是雙向結構)
- 模型的潛在影響:模型可能存在濫用,例如垃圾郵件、欺詐性學術論文寫作等;性別、種族、宗教的偏見問題;能源問題;
一句話總結GPT3:採用大資料大模型訓練GPT3,可實現少樣本的學習能力,可以完成多種NLP任務,其模式更接近人類的1-shot learning。
ChatGPT(Instruct GPT)
Instruct GPT:Training language models to follow instructions with human feedback 於2022年3月發表。
關鍵字Language Model Alignment;Following Instructions, Reinforcement Learning from Human Feedback
摘要
GPT3已經能進行各類的文本生成任務,但TA不太能夠遵循人類的意圖,為了讓GPT更好的遵循人類意圖,回答人類的問題,本文採用RLHF的強化學習方式,來微調GPT,結果表明微調後的GPT,即使僅1.3B參數,也比175B參數模型,更受人們青睞。
指令跟隨的理解
簡單回顧GPT機制。GPT是Language Model,根據左邊的序列預測下一個token,在GPT-123系列中,已經看到在各類文本生成任務中表現不錯,但是要利用GPT來完成具體的文本分類、句子相似性判斷、多項選擇題時,需要在推理時加入特殊的token,例如GPT1中的start、delim、extra這樣的“指令”來組裝序列。
這是由於GPT並不能直接根據人類語言來完成這些任務,例如希望實現機器翻譯時,期望輸入的應該是:translate english to chinese, [english text], [chinese text] 。這裡的translate english to chinese就是人類的指令,但在GPT1、2和3的預訓練中,採用大多是書籍、互聯網文本資料,缺乏這樣的指令對話,因而GPT3也不能很好的滿足人類的美好需求。
為了讓GPT模型能更好的理解人類意圖,需要進行模型對齊、指令跟隨的微調訓練,本文訓練出來的GPT就稱為Instruct GPT,這也是ChatGPT背後強大的技術支撐——滿足人類意圖。
訓練過程
訓練的目標是讓GPT輸出的內容,讓人類更滿意,本文巧妙的利用模型輸出多個答案,讓人類進行排序的方式進行衡量,實現對模型輸出結果好壞的評估。
第一步,訓練基礎模型,讓GPT3能夠回答人類問題。由人工撰寫問題,以及希望模型回答的內容作為示例,對GPT-3進行監督學習微調,得到一個基線監督模型。
第二步,訓練獎勵模型(Reward Model)。又人類對模型的輸出進行排序,然後訓練一個能打分的RM模型。這個模型會在強化學習中評估GPT模型輸出的好壞。
第三步,訓練Instruct GPT。獎勵模型的輸出作為獎勵信號,通過proximal policy optimization (PPO)演算法,進一步微調第一步得到的基線模型。微調目標是最大化獎勵模型預測的偏好分數,從而使模型輸出逐步符合人類意圖。最終得到nstructGPT。
更多細節:
- 第一步監督微調所用資料集大約有28,000個示例,主要來自標注員編寫和OpenAI API用戶提交的提示。
- 第二步獎勵模型訓練資料集包含約13,000個標注員對不同模型輸出的偏好排序實例。
- 第三步強化學習階段除了基於獎勵模型的PPO目標外,還混合了與原始GPT-3預訓練資料的似然目標(PPO-ptx),以緩解在下游任務上的性能下降。
下面通過表格對比GPT系列模型的變化
GPT |
GPT2-s |
GPT2-m |
GPT2-l |
GPT2-xl |
GPT3 |
|
---|---|---|---|---|---|---|
參數量 |
~117 M |
117 M |
345 M |
762 M |
1.5 B |
175 B |
訓練數據 |
7000本書 |
40GB |
40GB |
40GB |
40GB |
45TB |
Block |
12 |
12 |
24 |
36 |
48 |
96 |
d_model |
768 |
1024 |
1024 |
1280 |
1600 |
12888 |
論文小結
ChatGPT的出圈不是一蹴而就,自2017年微軟發佈Transformer,再到OpenAI從2019年基於Transformer的decoer提出GPT,經過3年多的發展,從預訓練-微調範式,不斷加大模型尺寸,探索模型能力邊界,再到基於強化學習的微調讓GPT模型具備說人話的能力,最終有了ChatGPT這樣的作品。
GPT訓練
本小節採用中文預料,預訓練一個GPT2-small的模型,基於wiki百科訓練的模型可以實現一定程度的文章續寫,基於百科QA的資料可以實現類似的問答效果。
通過GPT論文的學習,可以知道GPT要實現與人順暢的交流,需要特定對話資料進行微調,在這裡暫時不具備此能力。
在這裡希望通過代碼,強化對GPT運行機制的瞭解,包括訓練資料如何組裝、拼接、特殊token的處理、推理時的處理細節,為後續LLM的研發打下基礎。
這裡整體訓練代碼參考自:https://github.com/Morizeyao/GPT2-Chinese
環境配置說明: transformers==2.1.1 (高版本不適配)
GPT訓練數據準備
由於是預訓練預料,因此可以採用互利網上的文本資訊,這個repo收集了5個資料集,有上千萬的句子可用。分別有:
1.維琪百科(wiki2019zh),100萬個結構良好的中文詞條
2.新聞語料(news2016zh),250萬篇新聞,含關鍵字、描述
3.百科問答(baike2018qa),150萬個帶問題類型的問答
4.社區問答json版(webtext2019zh),410萬個高品質社區問答,適合訓練超大模型
5.翻譯語料(translation2019zh),520萬個中英文句子對
在這裡,受限於計算資源,只採用了維琪百科(wiki2019zh)和百科問答(baike2018qa)兩個資料集,分別訓練了兩次GPT2,用於觀察不同資料下模型的差異。
GPT預訓練的資料主要是文本序列,不同文章、段落的文本可以拼接到一起輸入給模型。
因此,資料處理就比較簡單,將所有文本拼接,然後在文章開頭、結束加入特殊token來標識,最後劃分為batch的形式輸入到模型即可。
這部分邏輯參考train.py中的build_files函數。build_files大致邏輯如下:
- 讀取資料夾中的原始檔,所有字串以list為單位,存儲於lines_total中
- 根據分片的數量,對lines_total進行切割,過濾單條文本長度小於min_length的文本
- 不同文本之間加入特殊token進行分隔,並用tokenizer轉為index
- 寫入txt文件
PS:代碼中沒有採用pytorch的dataset和dataloader的概念,直接對txt檔進行讀取,在訓練代碼中處理。
GPT模型構建
基於transformers庫中的modeling_gpt2的GPT2LMHeadModel實現,代碼也很簡單,沒有特殊的,需要提一點就是在GPT2LMHeadModel中的forward實現了計算loss功能,只需要在forward的時候吧labels傳入,由於是masked langurage model的任務,標籤就是輸入右移一位,具體看如下代碼:
# ... GPT2LMHeadModel中的forward())
if labels is not None:
shift_logits = lm_logits[..., :-1, :].contiguous() # 取輸入n-1個
shift_labels = labels[..., 1:].contiguous() # 取n-1個標籤
loss_fct = CrossEntropyLoss(ignore_index=-1)
loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))
outputs = (loss,) + outputs
Copy
GPT模型訓練
模型訓練採用了兩個資料集,通過不同的資料類型,觀察GPT模型對於人類意圖的跟隨能力。
這裡採用了wiki2019和baike2018qa兩個資料集,wiki2019中的文本主要是陳述句,baike2018qa裡則會有對話和問答。
首先看wiki2019的訓練,wiki2019,總token數5億(508478004),在1080ti(12GB)上訓練需要5天左右,5個epoch後loss基本穩定在2。
python train.py --raw --raw_data_path ./wiki_raw/wiki_zh --epochs 10 --batch_size 4 --log_step 100 --num_pieces 1000
Copy
接著看baike2018qa的訓練,總token數也是5億(505564900),在1080ti(12GB)上訓練需要5天左右,5個epoch後loss基本穩定在2+。
python train.py --raw --raw_data_path ../data/baike2018qa --epochs 5 --batch_size 4 --log_step 100 --num_pieces 1000
Copy
GPT推理
訓練完成,在model檔下獲取模型權重,採用generate.py進行推理,推理時需要設置prefix,模型根據首碼進行後續文字生成。
推理示例:
python generate.py --model_path ./model/model_epoch5_baikeqa --prefix 我肚子痛了,要怎麼辦?
python generate.py --model_path ./model/model_epoch5_wiki_alldata --prefix 秦始皇,名嬴政,是中國歷史上著名的君主,也是中國歷史上第一個使用“皇帝”稱號的君主。他出生於西元前259年,卒於
Copy
這裡暫時沒有做停止符處理,先讓模型輸出到最大長度,正常情況應該判斷是否輸出了停止符。(停止符是兩個回車\n\n)
具體的推理、採樣邏輯如下代碼所示:
def sample_sequence(model, context, length, n_ctx, tokenizer, temperature=1.0, top_k=30, top_p=0.0, repitition_penalty=1.0,
device='cpu'):
context = torch.tensor(context, dtype=torch.long, device=device)
context = context.unsqueeze(0)
generated = context
with torch.no_grad():
for _ in trange(length):
inputs = {'input_ids': generated[0][-(n_ctx - 1):].unsqueeze(0)}
# 模型推理
outputs = model(**inputs) # Note: we could also use 'past' with GPT-2/Transfo-XL/XLNet (cached hidden-states)
next_token_logits = outputs[0][0, -1, :] # 輸出l個logits,但只需要取最後一個
# 加入溫度懲罰
for id in set(generated):
next_token_logits[id] /= repitition_penalty
next_token_logits = next_token_logits / temperature
next_token_logits[tokenizer.convert_tokens_to_ids('[UNK]')] = -float('Inf')
# 採樣
filtered_logits = top_k_top_p_filtering(next_token_logits, top_k=top_k, top_p=top_p)
next_token = torch.multinomial(F.softmax(filtered_logits, dim=-1), num_samples=1)
# 拼接
generated = torch.cat((generated, next_token.unsqueeze(0)), dim=1)
return generated.tolist()[0]
Copy
------------------------------------------------------------------ 看第一個推理例子 ------------------------------------------------------------------
(模型權重可以從這裡下載提取碼:lwzr)
python generate.py --model_path ./model/model_epoch5_wiki_alldata --prefix 秦始皇,名嬴政,是中國歷史上著名的君主,也是中國歷史上第一個使用“皇帝”稱號的君主。他出生於西元前259年,卒於
Copy
模型輸出:
秦始皇,名嬴政,是中國歷史上著名的君主,也是中國歷史上第一個使用“皇帝”稱號的君主。他出生於西元前259年,卒於154年,享年68歲。\n\n"}
{"id":"3704970","url":"https://zh.wikipedia.org/wiki?curid=3704970","title":"中國人民解放軍海軍航空兵","text":"中國人民解放軍海軍航空兵\n\n中國人民解放軍海軍航空
兵(,縮寫為)是中國海軍的一支現役軍事部隊,由現役部隊改編而成,是中國人民解放軍陸軍中的最新式軍事部隊。\n\n1962年,在海軍的改編和建立之初,海軍航空兵的基礎上開展
以航空兵為主體的軍事訓練。隨著1985年7月20日成立了第一屆海軍大學校,海軍航空兵開始進行部隊建設,並且在1990年12月28日舉行了首屆海軍大學體育訓練班。1996年3月18日,,
軍航空兵正式開始招收軍事戰鬥部隊,這一年開始實施大學體育運動。1999年,海軍航空兵正式進入國防部直屬的軍訓,並且在2003年7月19日起正式開始招收軍事戰鬥部隊,同時開
始招收專業的軍事戰鬥部隊。目前中國人民解放軍的各級軍事戰鬥部隊包括陸軍航空兵第二十二集團軍,第六十七集團軍,海軍軍事學校航空兵第四十五集團軍。\n\n2005年,陸軍航空
開始進行全軍裝備升級,並且在2006年1月1日起開始進行了大規模的現場演練,並且在一天的時間裡將部隊裝備的現役軍事戰鬥部隊改為現役部隊。現役部隊裝備的現役部隊裝備已經經
全轉型到現役部隊,並且陸續進駐陸軍航空兵、海軍軍事戰鬥部隊及海軍軍事戰鬥部隊等。陸軍航空兵的現役部隊現役部隊包括陸軍航空兵第二十二集團軍、海軍軍事戰鬥部隊、海軍軍
事戰鬥部隊、海軍航空兵第四十五集團軍、海軍航空兵第一十一集團軍和空軍航空兵第二十六集團軍。\n\n陸軍航空兵現役的部隊包括陸軍航空兵、空軍航空兵、空軍航空兵、海軍軍軍
戰鬥部隊、海軍航空兵、海軍航空兵、海軍航空兵等,部隊裝備的現役部隊還包括海軍航空兵、海軍航空兵、海軍航空兵和空軍軍事戰鬥部隊。\n\n現役部隊裝備的現役部隊包括陸軍軍
空兵第九十一集團軍、海軍航空兵第四十五集團軍、空軍航空兵第九十六集團軍、海軍軍事戰鬥部隊、海軍航空兵第四十五集團軍、空軍航空兵第一十六集團軍、空軍航空兵第二十六六
團軍、海軍航空兵第十六集團軍、海軍航空兵第十八集團軍、空軍航空兵第二十九集團軍、空軍航空兵第二十九集團軍、空軍航空兵第九十四集團軍和空軍航空兵第九十五集團軍。\n n\n現役部隊裝備的現役部隊包括陸軍航空兵第九十八集團軍、海軍航空兵第九十七集團軍、空軍航空兵第九十七集團軍及空軍航空兵第十八集團軍。
...略......略......略......略...
Copy
從輸出來看,文字讀起來都是人話,但是深究邏輯就有明顯錯誤,例如秦始皇的逝世年份是不對的。並且在後續的文本中,輸出了一個wiki不存在的詞條,同時文本裡面還出現了大量的重複,這些都是GPT3論文中提到的問題——重複。
------------------------------------------------------------------ 看第二個例子 ------------------------------------------------------------------
python generate.py --model_path ./model/model_epoch5_wiki_alldata --prefix 我感冒了怎麼辦?
Copy
模型輸出:
我感冒了怎麼辦?」()這句話在電影界中引起了一片好的關注,在電影中也常出現一些不好的場景。在2002年,電影的劇照已經被刪除過一次,並且由於其他原因,它在電影中被刪除。\n\n"}
{"id":"3543288","url":"https://zh.wikipedia.org/wiki?curid=3543288","title":"阿爾及爾航空330號班機空難","text":"阿爾及爾航空330號班機空難\n\n阿爾及爾航空330號班機
阿爾及爾國內首班國內航班,機型為波音747-2er,於1983年7月22日起執飛,是一班從利比亞布林加斯-首都貝魯特經利比亞首都貝魯特、貝魯特抵達巴林國際機場的定期航班,機上8 87人當中,50人是來自利比亞的阿爾及爾航空公司。\n\n事發時阿爾及爾國內有16名乘客和53名機師的生還。\n\n機上16名乘客和12名機師生還。\n\n"}
...略......略......略......略...
Copy
很明顯,模型完全沒能理解使用者輸入資訊,也就是無法進行對話功能。這與訓練資料有關,屬於Instruct GPT裡提到的指令跟隨內容,wiki預料中都是陳述句,沒有這些問句以及人類提出的需求文本,因此模型無法跟隨人類指令。如果需要讓模型能夠進行指令跟隨,應當用一系列問答、對話、命令式的文本來訓練。
------------------------------------------------------------------ 看第三個例子 ------------------------------------------------------------------
(模型權重可以從這裡下載提取碼:4hua
python generate.py --model_path ./model/model_epoch5_baikeqa --prefix 我肚子痛了,要怎麼辦?
Copy
模型輸出:
我肚子痛了,要怎麼辦?是有什麼問題
如果是腸炎,就應該是腸梗阻了,建議用中藥治療一下,平時要多喝水,飲食要清淡,多運動,要注意飲食,忌煙酒。
我是新手,剛玩。請問怎樣才能玩到15級啊!!還有我現在的號是52級的,怎樣升級才能升到13級啊?我是新手,請高手指點一下,我現在是17級。謝啦
怎樣才能玩到15級!!!我是新手,剛玩。請問怎樣才能玩到15級啊!
你的號已經是新手了,你的級別是在40級前的,那你可以到新手村,那裡會有很多的怪,你可以從40級以上的怪物身上找到一些相關怪物,你會獲得一定經驗,還可以去找別人成一定數量的裝備和你需要的金錢。
...略......略......略......略...
Copy
可以看到模型會續寫使用者的輸入,並且換行之後進行“回答”,看似模型已經會回答問題了,這是因為baike2018qa資料集就是大量問答對的資料,從以上三個案例也可知道,生成式模型的對話能力,需要用對話資料、人類指令資料進行微調。這也是當下大模型中有base版和chat版的區別。base版模型是在大量的預料資料庫上訓練的,那些都是陳述句,屬於資訊的描述。要想讓模型理解人類意圖,還需要訓練chat版。
推理速度分析
通過以上案例,可以發現token推理速度隨著輸出長度增加而增加,這個很好理解,因為是自回歸式的輸出,預測token越多,下一個token推理時需要處理的QKV計算相應增加,從而速度變慢,並且顯存佔用是逐漸增加的。
在這裡也是Transformer架構可優化的地方,每個token的推理時,其實有一大部分K,V是重複運算了的,因此可以將這部分K,V緩存下來,減少運算量,這就是KV-Cache的由來。
小結
本節通過梳理GPT1,2,3到chatGPT的技術發展歷程,對GPT模型有了詳細的瞭解,並通過GPT2-small模型的訓練,進一步瞭解GPT的運行機制,為後續大語言模型的學習打下基礎。
本節值得重點關注的點有:
- GPT1,2,3模型從GPT1中採用特殊token來讓模型完成特定任務,到Instruct GPT通過自然語言讓模型完成特定任務,是ChatGPT得以破圈,被人類所接受的重要改變,這樣的對話模式,也是大家耳熟能詳的Prompt Engineering。
- GPT系列是一個模型、資料、計算基礎設施的複雜系統性工程,三者缺一不可,從GPT3論文中提及資料污染的bug無法重新訓練模型可知,訓練175B模型太貴了。
- GPT訓練時,句子之間用特殊token進行拼接,變為一個長序列輸入給到模型訓練。一般loss在2上下是一個還過得去的區間。
- 指令跟隨的理解,可以用GPT1如何應用到下游任務思考,結合Instruct GPT的內容,即可理解指令跟隨本意就是預訓練資料需要包含人類指令、人類命令,這樣預訓練模型才能在推理時,理解人類意圖。
- GPT的推理是自回歸的,模型一次推理,對於人類而言有價值意義的是最後一個概率向量,對於迴圈多少次,要輸出多少個token,取決於人類的代碼邏輯。
- KV-cache的理解,在最原始的代碼推理中,可以發現輸出的token越長時,越靠後的token耗時約長,這是因為單次推理時,輸入的token變長了,需要計算的注意力變多,因而變慢,但大部分注意力的計算在前序推理時已經計算過的,因此可以通過緩存存儲那些計算值,以此加快推理速度。