利用預訓練的CodeParrot模型,我們可以有效地生成程式碼。透過transformers函式庫提供的pipeline函式,可以輕鬆載入模型並設定其用於文字生成任務。為精確控制生成程式碼的長度和內容,我們可以使用正規表示式提取關鍵程式碼區塊,並利用生成管道產生多個候選結果,以便後續分析和選擇。透過設計適當的提示詞,例如提供函式簽名和檔案字串,可以引導模型生成符合預期的程式碼。實驗結果顯示,CodeParrot模型在生成簡單函式、從HTML提取URL以及進行程式碼轉換等任務上均展現出一定的潛力。然而,要全面評估模型的品質,仍需進一步探索更適合的評估指標,例如針對程式碼生成的特定指標,而非僅依賴於傳統的文字生成指標如BLEU分數。

結果與分析

在訓練完成CodeParrot模型後,我們可以利用它來生成程式碼。首先,我們將探討如何使用該模型進行程式碼生成,接著討論如何評估模型的表現。

使用CodeParrot生成程式碼

首先,我們使用transformers函式庫中的pipeline函式來載入預訓練的CodeParrot模型,並設定為文字生成任務。

from transformers import pipeline, set_seed

model_ckpt = 'transformersbook/codeparrot-small'
generation = pipeline('text-generation', model=model_ckpt, device=0)

程式碼生成邏輯實作

為了控制生成程式碼的長度和內容,我們定義了兩個函式:first_blockcomplete_codefirst_block函式使用正規表示式提取生成的程式碼中的第一個函式或類別定義。complete_code函式則利用generation管道生成多個候選程式碼完成,並列印出結果。

import re

def first_block(string):
    return re.split('\nclass|\ndef|\n#|\n@|\nprint|\nif', string)[0].rstrip()

def complete_code(pipe, prompt, max_length=64, num_completions=4, seed=1):
    set_seed(seed)
    gen_kwargs = {"temperature":0.4, "top_p":0.95, "top_k":0, "num_beams":1, "do_sample":True}
    code_gens = generation(prompt, num_return_sequences=num_completions, max_length=max_length, **gen_kwargs)
    code_strings = []
    for code_gen in code_gens:
        generated_code = first_block(code_gen['generated_text'][len(prompt):])
        code_strings.append(generated_code)
    print(('\n'+'='*80 + '\n').join(code_strings))

內容解密:

  1. first_block函式:該函式透過正規表示式將輸入字串分割,以提取第一個完整的函式或類別定義。這樣做可以避免生成過長或無關的程式碼。
  2. complete_code函式:此函式負責呼叫generation管道來生成程式碼。它透過設定種子值確保結果的可重現性,並使用特定的生成引數(如溫度、top-p等)來控制生成的品質和多樣性。

測試CodeParrot模型

我們首先測試模型生成一個簡單函式的能力,例如計算矩形面積的函式。

prompt = '''def area_of_rectangle(a: float, b: float):
"""Return the area of the rectangle."""'''
complete_code(generation, prompt)

輸出結果顯示,模型能夠生成正確的程式碼(return a * b),儘管其他結果不完全正確。

內容解密:

  1. 提示詞設計:透過提供函式簽名和檔案字串,模型能夠根據上下文生成合理的函式實作。
  2. 結果分析:儘管有多個候選結果,但大多數都正確或接近正確,顯示了模型的潛力。

接著,我們測試模型是否能夠完成更複雜的任務,例如從HTML字串中提取URL。

prompt = '''def get_urls_from_html(html):
"""Get all embedded URLs in a HTML string."""'''
complete_code(generation, prompt)

模型生成的結果大多正確,能夠提取出HTML中的URL。

內容解密:

  1. 正規表示式的使用:模型正確地使用了正規表示式來匹配和提取URL,顯示了其理解和應用程式碼模式的能力。
  2. 結果驗證:透過測試生成的函式,驗證了其正確性和可用性。

最後,我們測試了大型CodeParrot模型,將純Python函式轉換為NumPy實作。

prompt = '''# a function in native python:
def mean(a):
    return sum(a)/len(a)
# the same function using numpy:
import numpy as np
def mean(a):'''
complete_code(generation, prompt, max_length=64)

模型成功地將函式轉換為使用NumPy的版本。

內容解密:

  1. 程式碼轉換能力:模型展示了將純Python程式碼轉換為使用特定函式庫(如NumPy)的能力,體現了其對不同程式碼正規化的理解。
  2. 生成引數設定:透過調整生成引數,模型能夠產生符合預期的結果。

評估模型的品質

雖然我們透過幾個例子展示了CodeParrot的能力,但要全面評估模型的品質,需要使用諸如BLEU分數等指標進行系統性的評估。然而,由於程式碼生成的特殊性,BLEU分數可能不是最佳的評估指標。

內容解密:

  1. 評估指標的選擇:由於程式碼生成的自由度較高,傳統的文字生成評估指標可能不完全適用,需要探索更適合的評估方法。
  2. 未來改進方向:除了BLEU分數,還可以考慮其他評估指標或方法,以更全面地評估模型的表現。

未來方向:擴充套件與創新

在整本文中,我們探討了Transformer在廣泛的自然語言處理(NLP)任務中的強大能力。在最後一章,我們將轉變視角,檢視這些模型目前面臨的一些挑戰,以及正在嘗試克服它們的研究趨勢。首先,我們將探討擴充套件Transformer的議題,無論是在模型還是語料函式庫的大小方面。接著,我們將關注各種被提出來提高自注意力機制效率的技術。最後,我們將探索多模態Transformer這個新興且令人興奮的領域,它能夠跨多個領域(如文字、影像和音訊)建模輸入。

擴充套件Transformer

2019年,研究人員Richard Sutton撰寫了一篇發人深省的文章,題為《苦澀的教訓》,其中他認為:

七十年的AI研究中可以讀到的最大教訓是,利用計算的通用方法最終是最有效的,而且差距很大……在短期內尋求改進的研究人員試圖利用他們對領域的人類知識,但從長遠來看,唯一重要的是利用計算。這兩者並不一定相互對立,但在實踐中它們往往……而人類知識的方法往往使方法複雜化,使它們不太適合利用通用方法來利用計算。

這篇文章提供了幾個歷史例子,如下棋或圍棋,編碼人類知識在AI系統中的方法最終被增加的計算量所超越。Sutton將這稱為AI研究領域的「苦澀教訓」:

我們必須學習到,將我們認為的思考方式構建進去並不會在長期內奏效……從苦澀教訓中應該學到的一件事是通用方法的巨大力量,這些方法即使在可用計算量變得非常大時也能繼續擴充套件。有兩種方法似乎以這種方式任意擴充套件,即搜尋和學習。

現在有跡象表明,Transformer也存在類別似的教訓;雖然許多早期的BERT和GPT後代專注於調整架構或預訓練目標,但2021年中期表現最佳的模型,如GPT-3,本質上是原始模型的基本擴充套件版本,沒有太多的架構修改。在圖11-1中,您可以看到自2017年原始Transformer架構發布以來最大模型的開發時間軸,這表明模型大小在短短幾年內增加了超過四個數量級!

圖示:Transformer架構引數數量隨時間的變化

此圖示展示了Transformer架構引數數量隨時間的變化,表明模型大小呈指數級增長。

這種戲劇性的增長是由實證證據推動的,即大語言模型在下游任務上表現更好,並且在100億至1000億引數範圍內出現了有趣的能力,如零樣本和少樣本學習。然而,引數數量並不是影響模型效能的唯一因素;計算量和訓練資料也必須同步擴充套件,以訓練這些龐大的模型。鑑於像GPT-3這樣的大語言模型的訓練成本估計為460萬美元,顯然能夠提前估計模型的效能是非常理想的。令人驚訝的是,語言模型的效能似乎遵循著可預測的模式。

內容解密:

圖11-1展示了Transformer模型大小隨時間的指數級增長趨勢,主要由計算能力和資料量的同步增長推動。這種趨勢反映了「苦澀教訓」的觀點,即通用方法的擴充套件能力最終會超越人類知識的限制。

提高效率與多模態Transformer

為了應對大型模型的挑戰,研究人員提出了各種技術來提高自注意力機制的效率,例如稀疏注意力機制和線性注意力機制等。與此同時,多模態Transformer的發展也為跨領域建模提供了新的可能性,能夠同時處理文字、影像和音訊等多種輸入模式。

擴充套件定律:語言模型的新視野

語言模型的研究近年來取得重大突破,其中「擴充套件定律」(Scaling Laws)的發現為模型效能的提升提供了新的方向。擴充套件定律透過研究計算資源(C)、資料集大小(D)和模型大小(N)之間的關係,量化了「越大越好」正規化的有效性。

擴充套件定律的核心概念

擴充套件定律的核心思想是研究交叉熵損失(L)與計算資源、資料集大小和模型大小之間的依賴關係。對於像GPT家族這樣的自迴歸模型,損失曲線呈現出特定的規律,如圖11-2所示。每條藍色曲線代表一個單獨模型的訓練過程。

圖11-2展示了測試損失與計算資源(左)、資料集大小(中)和模型大小(右)之間的冪律關係。從這些損失曲線中,可以得出以下結論:

  1. 效能與規模的關係:許多NLP研究人員關注架構調整或超引數最佳化以提高效能,但擴充套件定律意味著,更有效的途徑是同時增加N、C和D。

  2. 平滑的冪律關係:測試損失L與N、C和D之間存在冪律關係,這種關係在雙對數尺度上呈現為線性。對於$X = N, C, D$,可以將這種冪律關係表示為 $L(X) \sim \frac{1}{X^\alpha}$,其中$\alpha$是透過擬合損失曲線確定的縮放指數。

    內容解密:

    • $L(X)$代表測試損失,是評估模型效能的重要指標。
    • $X$可以是模型大小(N)、計算資源(C)或資料集大小(D),代表影響模型效能的三個主要因素。
    • $\alpha$是縮放指數,其值通常在0.05到0.095之間,決定了損失隨著$X$變化的速率。
    • 冪律關係允許透過早期損失曲線的外推來預測長時間訓練後的損失。
  3. 樣本效率:大型模型能夠以較少的訓練步驟達到與小型模型相同的效能。這可以透過比較損失曲線趨於平緩的區域看出,這表明繼續訓練的收益遞減,而擴大模型規模則更為有效。

擴充套件定律的普遍性

令人驚訝的是,擴充套件定律也被觀察到適用於其他模態,如影像、影片和數學問題求解,如圖11-3所示。這種現象是否為Transformer語言模型的普遍特性仍是未知,但目前可以利用擴充套件定律來推斷大型模型的效能,而無需實際訓練它們。

擴充套件面臨的挑戰

儘管擴充套件模型看似簡單,但在實踐中存在許多困難。以下是一些主要的挑戰:

  1. 基礎設施:管理和維護可能跨越數百或數千個節點的基礎設施,需要非常不同的技能組合,通常涉及熟悉大規模分散式實驗的專門工程師。

@startuml skinparam backgroundColor #FEFEFE skinparam componentStyle rectangle

title CodeParrot模型程式碼生成與分析

package “CodeParrot 程式碼生成” { package “模型載入” { component [Transformers 函式庫] as transformers component [Pipeline 設定] as pipeline component [預訓練模型] as pretrained }

package "程式碼生成" {
    component [提示詞設計] as prompt
    component [生成參數控制] as params
    component [候選結果產生] as candidates
}

package "結果處理" {
    component [正規表示式提取] as regex
    component [程式碼區塊分析] as block
    component [品質評估] as quality
}

}

transformers –> pipeline : 載入模型 pipeline –> pretrained : 設定任務 pretrained –> prompt : 模型就緒 prompt –> params : 函式簽名 params –> candidates : 溫度/top-p candidates –> regex : 多個候選 regex –> block : 提取程式碼 block –> quality : 第一區塊

note right of params 生成參數:

  • temperature: 0.4
  • top_p: 0.95
  • num_beams: 1 end note

note right of quality 評估指標:

  • 正確性檢驗
  • BLEU 分數
  • 功能測試 end note

@enduml

   此圖示展示了大規模基礎設施管理中的關鍵步驟,包括節點組態、通訊最佳化、資源排程和穩定性保障。

   #### 內容解密:
   - 節點組態是基礎設施管理的第一步,需要根據實驗需求組態適當的硬體和軟體環境。
   - 通訊最佳化旨在減少節點間的通訊延遲和提高資料傳輸效率。
   - 資源排程確保計算資源被有效分配和利用,以最大化實驗效率。
   - 穩定性保障涉及監控系統狀態、故障檢測和還原機制,以確保實驗的連續性和可靠性。

2. **成本**:訓練大型模型(如GPT-3)的成本極高,可能達到數百萬美元,這對許多公司來說是難以負擔的。

3. **資料集整理**:大型模型需要高品質的大規模資料集。在使用大量文字資料時,確保資料品質、控制偏見(如性別歧視和種族主義)以及處理授權和隱私問題成為挑戰。

4. **模型評估**:評估大型模型在下游任務上的表現需要時間和資源。此外,還需要檢查模型是否存在有偏見或有害的生成結果。

總之,擴充套件定律為語言模型的效能提升提供了一個重要的研究方向,但同時也伴隨著諸多挑戰。未來需要在基礎設施、成本控制、資料集整理和模型評估等方面取得進展,以充分發揮擴充套件定律的潛力。

## 擴充套件 Transformer 的挑戰與解決方案

在前面的章節中,我們探討瞭如何利用各種技術來最佳化 Transformer 架構,使其能夠處理更大的模型、資料集和計算資源。然而,在擴充套件 Transformer 的過程中,我們仍然面臨著許多挑戰。

### 佈署大語言模型的挑戰

佈署大語言模型是一項艱巨的任務。雖然我們在第 8 章中討論了一些技術,如蒸餾、剪枝和量化,可以幫助解決這些問題,但對於數百 GB 的大型模型來說,這些技術可能仍然不夠。像 OpenAI API 或 Hugging Face 的 Accelerated Inference API 等託管服務,可以幫助那些無法或不想處理這些佈署挑戰的公司。

### 社群驅動的專案

目前,有兩個社群驅動的專案,旨在開發和研究大語言模型:

#### BigScience

BigScience 是一個為期一年的研究工作坊,於 2021 年至 2022 年間舉行,專注於大語言模型的研究。該工作坊旨在促進圍繞這些模型的研究問題的討論和反思,包括能力、限制、潛在改進、偏差、倫理、環境影響等。參與者共同建立、分享和評估一個大型多語言資料集和一個大語言模型。

#### EleutherAI

EleutherAI 是一個由志願研究人員、工程師和開發人員組成的分散式集體,專注於 AI 對齊、擴充套件和開源 AI 研究。其中一個目標是訓練和開源一個與 GPT-3 相當的模型。他們已經發布了一些令人印象深刻的模型,如 GPT-Neo 和 GPT-J,後者是一個擁有 60 億引數的模型,目前是公開可用的最佳零樣本效能的 Transformer 模型。

### 使自注意力更高效的研究方向

自注意力機制是 Transformer 架構的核心,但它也是一個計算瓶頸。最近的研究重點是使自注意力更高效。研究方向大致可分為以下幾類別,如圖 11-4 所示。

#### 稀疏注意力

一種減少自注意力層計算量的方法是限制生成的查詢鍵對數量。可以根據某些預定義的模式來實作這一點。文獻中已經探索了許多稀疏模式,但大多數可以分解為圖 11-5 中所示的幾種「原子」模式。

##### 常見的原子稀疏注意力模式

* **全域注意力**:定義序列中幾個特殊的 token,可以與所有其他 token 進行互動。
* **頻帶注意力**:計算對角頻帶上的注意力。
* **擴張注意力**:使用具有間隙的擴張視窗跳過一些查詢鍵對。
* **隨機注意力**:為每個查詢隨機取樣幾個鍵來計算注意力分數。
* **區塊區域性注意力**:將序列分成區塊,並將注意力限制在這些區塊內。

在實踐中,大多數使用稀疏注意力的 Transformer 模型都會混合使用圖 11-5 中所示的原子稀疏模式來生成最終的注意力矩陣。如圖 11-6 所示,像 Longformer 這樣的模型使用全域和頻帶注意力的混合,而 BigBird 則增加了隨機注意力。

#### 線性化注意力

另一種使自注意力更高效的方法是改變計算注意力分數的操作順序。回想一下,為了計算查詢和鍵的自注意力分數,我們需要一個相似度函式。對於 Transformer 來說,這個相似度函式就是簡單的點積。但是,對於一般的相似度函式 `sim(q_i, k_j)`,我們可以將注意力輸出表示為以下等式:

`y_i = ∑_j sim(Q_i, K_j) / ∑_k sim(Q_i, K_k) * V_j`

這種方法可以減少自注意力的計算複雜度。

## 超越文字:Transformer 的新視野

Transformer 語言模型的成功主要歸功於文字訓練和遷移學習。一方面,文字資料豐富,能夠實作大型模型的自監督訓練;另一方面,諸如分類別和問答等文字任務很常見,開發有效的策略來解決這些任務能幫助我們應對廣泛的現實問題。

### 目前方法的侷限性

然而,這種方法存在一些侷限性,包括:

- **人類報告偏差**:文字中事件的頻率可能無法代表其真實頻率。僅在網際網路文字上訓練的模型可能會對世界有扭曲的認識。
- **常識**:常識是人類推理的基本品質,但很少被寫下來。因此,在文字上訓練的語言模型可能知道很多關於世界的事實,但缺乏基本的常識推理。
- **事實儲存**:機率語言模型無法可靠地儲存事實,可能會產生事實錯誤的文字。同樣,這些模型可以檢測命名實體,但無法直接存取有關它們的資訊。
- **模態限制**:語言模型無法連線到其他模態,例如音訊或視覺訊號或表格資料,這些模態可以解決上述某些問題。

### 克服模態限制

如果我們能夠解決模態限制,也許就能解決其他一些問題。最近,在將 Transformer 推向新的模態,甚至構建多模態模型方面取得了很大進展。在本文中,我們將重點介紹其中一些進展。

### 視覺領域

視覺領域一直是卷積神經網路(CNN)的強項,自從深度學習革命以來便是如此。最近,Transformer 開始被應用於這一領域,並取得了與 CNN 相當甚至更好的效率。讓我們來看看幾個例子。

#### iGPT

受 GPT 系列模型在文字上的成功啟發,iGPT(影像 GPT 的縮寫)將相同的方法應用於影像。透過將影像視為畫素序列,iGPT 使用 GPT 架構和自迴歸預訓練目標來預測下一個畫素值。在大型影像資料集上進行預訓練使 iGPT 能夠“自動完成”部分影像,如圖 11-8 所示。當在模型上新增分類別頭時,它也在分類別任務上取得了良好的結果。

```python
from PIL import Image
import matplotlib.pyplot as plt

image = Image.open("images/doge.jpg")
plt.imshow(image)
plt.axis("off")
plt.show()

ViT

Vision Transformer(ViT)是另一種將 Transformer 用於視覺任務的方法,如圖 11-9 所示。首先,將影像分成較小的補丁,每個補丁透過線性投影嵌入。這些嵌入與位置嵌入結合,然後饋送到普通的 Transformer 編碼器。在預訓練期間,一些補丁被遮罩或扭曲,目標是預測被遮罩補丁的平均顏色。

import pandas as pd
from transformers import pipeline

image_classifier = pipeline("image-classification")
preds = image_classifier(image)
preds_df = pd.DataFrame(preds)
preds_df

成果與未來方向

儘管這種方法在標準 ImageNet 資料集上進行預訓練時沒有產生更好的結果,但它在更大的資料集上擴充套件得比 CNN 好得多。ViT 已整合到 Transformers 中,使用它與我們在這本文中使用的 NLP 管道非常相似。影像模型的自然擴充套件是影片模型。除了空間維度之外,影片還具有時間維度。這使得任務更加具有挑戰性,因為資料量變得更大,需要處理額外的維度。諸如 TimeSformer 之類別的模型引入了空間和時間注意力機制來解決這兩個問題。在未來,這些模型可以幫助構建用於廣泛任務的工具,例如影片序列的分類別或註解。

內容解密:

  1. iGPT 與 ViT 的主要區別:iGPT 使用自迴歸預訓練目標來預測下一個畫素值,而 ViT 則使用遮罩或扭曲補丁的方法來預測被遮罩補丁的平均顏色。
  2. Transformer 在視覺領域的應用:Transformer 不僅可以用於 NLP 任務,也可以應用於視覺任務,如影像和影片處理。
  3. 未來的研究方向:將 Transformer 推向新的模態,如音訊或視覺訊號,並構建多模態模型,以克服目前方法的侷限性。

Transformer 的未來發展將朝著多模態和更高效的架構方向邁進。這不僅能夠提升模型的表現,也能夠讓 Transformer 在更多領域中發揮作用,例如影片理解和多媒體處理。透過不斷的研究和創新,我們可以期待 Transformer 在未來會帶來更多的突破和應用。