歡迎閱讀《Hugging Face Transformers 萌新完全指南》,本指南面向那些意欲瞭解有關如何使用開源 ML 的基本知識的人群。我們的目標是揭開 Hugging Face Transformers 的神秘面紗及其工作原理,這麼做不是為了把讀者變成機器學習從業者,而是讓為了讓讀者更好地理解 transformers 從而能夠更好地利用它。同時,我們深知實戰永遠是最好的學習方法,因此,我們將以在 Hugging Face Space 中執行 Microsoft 的 Phi-2 LLM 為例,開啟我們的 Hugging Face Transformers 之旅。
你可能心裡會犯嘀咕,現在市面上已有大量關於 Hugging Face 的教程,為什麼還要再搞一個新的呢?答案在於門檻: 大多數現有資源都假定讀者有一定的技術背景,包括假定讀者有一定的 Python 熟練度,這對非技術人員學習 ML 基礎知識很不友好。作為 AI 業務線 (而不是技術線) 的一員,我發現我的學習曲線阻礙重重,因此希望為背景與我相似的學習者提供一條更平緩的路徑。
因此,本指南是為那些渴望跳過 Python 學習而直接開始瞭解開源機器學習的非技術人員量身定製的。無需任何先驗知識,從頭開始解釋概念以確保人人都能看懂。如果你是一名工程師,你會發現本指南有點過於基礎,但對於初學者來說,這很合他們胃口。
我們開始吧……,首先了解一些背景知識。
Hugging Face Transformers 是什麼?
Hugging Face Transformers 是一個開源 Python 庫,其提供了數以千計的預訓練 transformer 模型,可廣泛用於自然語言處理 (NLP) 、計算機視覺、音訊等各種任務。它透過對底層 ML 框架 (如 PyTorch、TensorFlow 和 JAX) 進行抽象,簡化了 transformer 模型的實現,從而大大降低了 transformer 模型訓練或部署的複雜性。
庫是什麼?
庫是可重用程式碼段的集合,大家將其整合到各種專案中以有效複用其各種功能,而無需事事都從頭實現。
特別地,transformers 庫提供的可重用的程式碼可用於輕鬆實現基於 PyTorch、TensorFlow 和 JAX 等常見框架的新模型。開發者可以呼叫庫中的函式 (也稱為方法) 來輕鬆建立新的模型。
Hugging Face Hub 是什麼?
Hugging Face Hub 是一個協作平臺,其中託管了大量的用於機器學習的開源模型和資料集,你可以將其視為 ML 的 Github。該 hub 讓你可以輕鬆地找到、學習開源社群中有用的 ML 資產並與之互動,從而促進共享和協作。我們已將 hub 與 transformers 庫深度整合,使用 transformers 庫部署的模型都是從 hub 下載的。
Hugging Face Spaces 是什麼?
Hugging Face Spaces 是 Hugging Face Hub 上提供的一項服務,它提供了一個易於使用的 GUI,用於構建和部署 Web 託管的 ML 演示及應用。該服務使得使用者可以快速構建 ML 演示、上傳要託管的自有應用,甚至即時部署多個預配置的 ML 應用。
本文,我們將透過選擇相應的 docker 容器來部署一個預配置的 ML 應用程式 (JupyterLab notebook)。
Notebook 是什麼?
Notebook 是一種互動式的應用,使用者可用它編寫並共享一些實時的可執行程式碼,它還支援程式碼與文字內容交織在一起。Notebook 對資料科學家和機器學習工程師特別有用,有了它大家可以實時對程式碼進行實驗並輕鬆查閱及共享結果。
- 建立一個 Hugging Face 賬號
- 如果你還沒有賬號,可至 hf.co,點選
Sign Up
以建立新賬號。
- 新增賬單資訊
- 在你的 HF 帳號中,轉到
Settings > Billing
,在付款資訊部分新增你的信用卡資訊。
為什麼需要信用卡資訊?
大多數 LLM 的執行需要用到 GPU,但 GPU 並非是免費的,Hugging Face 提供了 GPU 租賃服務。別擔心,並不太貴。本文所需的 GPU 是 NVIDIA A10G,每小時只要幾美金。
- 建立一個 Space 以託管你的 notebook
- 在 hf.co 頁面點選
Spaces > Create New
- 配置 Space
- 給你的 Space 起個名字
- 選擇
Docker > JupyterLab
以新建一個預配置的 notebook 應用 - 將
Space Hardware
設為Nvidia A10G Small
- 其餘都保留為預設值
- 點選
Create Space
Docker 模板是什麼?
Docker 模板規定了一個預定義的軟體環境,其中包含必要的軟體及其配置。有了它,開發人員能夠以一致且隔離的方式輕鬆快速地部署應用。
為什麼我需要選擇 Space 硬體選為 GPU?
預設情況下,我們為 Space 配備了免費的 CPU,這對於某些應用來說足夠了。然而,LLM 中的許多計算能大大受益於並行加速,而這正是 GPU 所擅長的。
此外,在選擇 GPU 時,選擇足夠的視訊記憶體以利於儲存模型並提供充足的備用工作記憶體也很重要。在我們的例子中,24GB 的 A10G Small 對於 Phi-2 來說夠用了。
- 登入 JupyterLab
- 新建好空間後,你會看到登入頁。如果你在模板中把令牌保留為預設值,則可以填入 “huggingface” 以登入。否則,只需使用你設定的令牌即可。
- 建立一個新 notebook
- 在
Launcher
選項卡中,選擇Notebook
一欄下的Python 3
圖示,以建立一個安裝了 Python 的新 notebook 環境
- 安裝所需包
-
在新 notebook 中,安裝 PyTorch 和 transformers 庫,因為其並未預裝在環境中。
-
你可以透過在 notebook 中輸入 !pip 命令 + 庫名來安裝。單擊播放按鈕以執行程式碼你可以看到庫的安裝過程 (也可同時按住 CMD + Return / CTRL + Enter 鍵)
!pip install torch
!pip install transformers
!pip install 是什麼?
!pip
是一個從 Python 包倉庫中 (PyPI) 安裝 Python 包的命令,Python 包倉庫是一個可在 Python 環境中使用的庫的 Web 儲存庫。它使得我們可以引入各種第三方附加元件以擴充套件 Python 應用程式的功能。
既然我們用了 transformers,為什麼還需要 PyTorch?
Hugging Face 是一個構建在 PyTorch、TensorFlow 和 JAX 等框架之上的上層庫。在本例中,我們使用的是基於 PyTorch 的 transformers 庫,因此需要安裝 PyTorch 才能使用其功能。
- 從 transformers 中匯入 AutoTokenizer 和 AutoModelForCausalLM 類
- 另起一行,輸入以下程式碼並執行
from transformers import AutoTokenizer, AutoModelForCausalLM
類是什麼?
你可將類視為可用於建立物件的程式碼配方。類很有用,因為其允許我們使用屬性和函式的組合來儲存物件。這反過來又簡化了編碼,因為特定物件所需的所有資訊和操作都可以從同一處訪問。我們會使用 transformers 提供的類來建立兩個物件: 一個是 model
,另一個是 tokenizer
。
為什麼安裝 transformers 後需要再次匯入所需類?
儘管我們已安裝 transformers,但其中的特定類並不會自動在你的環境中使能。Python 要求我們顯式匯入各類,這樣做有助於避免命名衝突並確保僅將庫的必要部分載入到當前工作上下文中。
- 定義待執行的模型
- 想要指明需從 Hugging Face Hub 下載和執行哪個模型,你需要在程式碼中指定模型儲存庫的名稱。
- 我們透過設定一個表明模型名稱的變數來達成這一點,本例我們使用的是
model_id
變數。 - 我們選用 Microsoft 的 Phi-2 模型,這個模型雖小但功能驚人,使用者可以在 https://huggingface.co/microsoft/phi-2 上找到它。注意: Phi-2 是一個基礎模型,而不是指令微調模型,因此如果你想將它用於聊天,其響應會比較奇怪。
model_id = "microsoft/phi-2"
什麼是指令微調模型?
指令微調語言模型一般是透過對其基礎版本進一步訓練而得,透過該訓練過程,我們希望其能學會理解和響應使用者給出的命令或提示,從而提高其遵循指令的能力。基礎模型能夠自動補全文字,但通常響應命令的能力較弱。稍後我們使用 Phi 時,會看到這一點。
- 建立模型物件並載入模型
- 要將模型從 Hugging Face Hub 載入到本地,我們需要例項化模型物件。我們透過將上一步中定義的
model_id
作為引數傳遞給AutoModelForCausalLM
類的.from_pretrained
來達到此目的。 - 執行程式碼並喝口水,模型可能需要幾分鐘才能下載完畢。
model = AutoModelForCausalLM.from_pretrained(model_id)
引數是什麼?
引數是傳遞給函式以便其計算輸出的資訊。我們透過將引數放在函式括號之間來將引數傳遞給函式。本例中,模型 ID 是唯一的引數。但其實,函式可以有多個引數,也可以沒有引數。
方法是什麼?
方法是函式的另一個名稱,其與一般函式的區別在於其可使用本物件或類的資訊。本例中, .from_pretrained
方法使用本類以及 model_id
的資訊建立了新的 model
物件。
- 建立分詞器物件並載入分詞器
- 要載入分詞器,你需要建立一個分詞器物件。要執行此操作,需再次將
model_id
作為引數傳遞給AutoTokenizer
類的.from_pretrained
方法。 - 請注意,本例中還使用了其他一些引數,但當前而言,理解它們並不重要,因此我們不會解釋它們。
tokenizer = AutoTokenizer.from_pretrained(model_id, add_eos_token=True, padding_side='left')
分詞器是什麼?
分詞器負責將句子分割成更小的文字片段 (詞元) 併為每個詞元分配一個稱為輸入 id 的值。這麼做是必需的,因為我們的模型只能理解數字,所以我們首先必須將文字轉換 (也稱為編碼) 為模型可以理解的形式。每個模型都有自己的分詞器詞表,因此使用與模型訓練時相同的分詞器很重要,否則它會誤解文字。
- 為模型建立輸入
- 定義一個新變數
input_text
,用於接受輸入給模型的提示文字。本例中,我們使用的是“Who are you?”
, 但你完全可以選擇自己喜歡的任何內容。 - 將新變數作為引數傳遞給分詞器物件以建立
input_ids
- 將傳給
tokenizer
物件的第二個引數設為return_tensors="pt"
,這會確保token_id
表示為我們正在使用的底層框架所需的正確格式的向量 (即 PyTorch 所需的格式而不是 TensorFlow 所需的)。
input_text = "Who are you?"
input_ids = tokenizer(input_text, return_tensors="pt")
- 生成文字並對輸出進行解碼
- 現在,我們需要將正確格式的輸入傳給模型,我們透過對
model
物件呼叫.generate
方法來執行此操作,將input_ids
作為引數傳給.generate
方法並將其輸出賦給outputs
變數。我們還將第二個引數max_new_tokens
設為 100,這限制了模型需生成的詞元數。 - 此時,輸出還不是人類可讀的,為了將它們轉換至文字,我們必須對輸出進行解碼。我們可以使用
.decode
方法來完成此操作,並將其儲存到變數decoded_outputs
中。 - 最後,將
decoded_output
變數傳遞給print
函式以利於我們在 notebook 中檢視模型輸出。 - 可選: 將
outputs
變數傳遞給print
函式,以比較其與decoded_output
的異同。
outputs = model.generate(input_ids["input_ids"], max_new_tokens=100)
decoded_outputs = tokenizer.decode(outputs[0])
print(decoded_outputs)
為什麼需要解碼?
模型只理解數字,因此當我們提供 input_ids
作為輸入時,它會返回相同格式的輸出。為了將這些輸出轉換為文字,我們需要反轉之前使用分詞器所做的編碼操作。
為什麼輸出讀起來像一個故事?
還記得之前說的嗎?Phi-2 是一個基礎模型,尚未針對對話場景進行指令微調,因此它實際上是一個大型自動補全模型。根據你的輸入,它會根據之前見過的所有網頁、書籍以及其他內容來預測它認為接下來最有可能出現的內容。
恭喜,你已經完成了你的第一個 LLM 推理之旅!
希望透過這個例子可以幫助大家更好地瞭解開源機器學習世界。如果你想繼續你的 ML 學習之旅,推薦大家試試我們最近與 DeepLearning AI 合作推出的這個 Hugging Face 課程。
英文原文: https://hf.co/blog/noob_intro_transformers
原文作者: Andrew Jardine
譯者: Matrix Yao (姚偉峰),英特爾深度學習工程師,工作方向為 transformer-family 模型在各模態資料上的應用及大規模模型的訓練推理。