萬字帶你瞭解ChatGLM

华为云开发者联盟發表於2024-03-13

本文分享自華為雲社群《【雲駐共創】華為雲之昇思MindSpore大模型專題(第二期)-第一課:ChatGLM》,作者: 愚公搬程式碼。

前言

1.昇思MindSpore

昇思MindSpore是華為公司推出的一款全場景AI計算框架。它提供了自動微分、分散式訓練和推理、模型部署等功能,支援多種硬體平臺,包括CPU、GPU和Ascend AI 處理器。MindSpore採用圖和運算元相結合的程式設計模型,能夠高效地處理複雜的深度學習任務。它具有靈活的設計、高效的效能和易於使用的介面,使開發者能夠更快地開發和部署AI應用。MindSpore還支援自定義操作和演算法,可以滿足不同場景下的需求。

2.大模型

大模型是指具有數百萬到數十億個引數的深度學習模型。這些模型通常用於處理大規模資料集,並能夠在各種任務上取得出色的效能。大模型通常需要大量的計算資源進行訓練,並且需要更長的時間來收斂。然而,由於其具有更多的引數,大模型可以更好地捕捉資料中的複雜關係,從而提升模型的預測效能。大模型的應用範圍非常廣泛,包括自然語言處理、計算機視覺、語音識別等領域。

3.ChatGLM

ChatGLM是一種生成式語言模型,用於聊天和對話任務。它是基於OpenAI的GPT模型框架構建的,採用了大規模的預訓練資料集來學習語言模式和生成文字的能力。ChatGLM可以理解上下文並生成連貫、自然的回覆。它可以用於構建對話系統、智慧客服、聊天機器人等應用,能夠提供更加互動性和人性化的對話體驗。ChatGLM模型的訓練和最佳化過程需要大量的計算資源和資料,而且模型的生成性質也需要進行適當的監督和過濾,以確保生成的回覆符合預期的行為準則和標準。

一、GLM Model Architecture

1.Evolution Tree of LLMs

Evolution Tree of LLMs(Language Model Megasuite的演化樹)是指由OpenAI釋出的一系列語言模型的歷史和演化關係圖。

OpenAI的LLMs系列是一系列基於深度學習的語言模型,旨在生成人類語言的自然文字。這些模型中的每一個都是透過對大量文字進行訓練而得到的,可以用於自動回答問題、生成文章、翻譯文字等自然語言處理任務。

Evolution Tree of LLMs圖中展示了這些模型的發展歷程。從最早的模型開始,每個後續模型都是在前一個模型的基礎上進行改進和擴充套件。這些改進可能涉及模型的規模增加、訓練資料的增加、架構的改進等。透過不斷地改進和提升模型,OpenAI致力於推動語言模型的發展,使其在各種自然語言處理任務上表現更加出色。

Evolution Tree of LLMs圖不僅展示了各個模型之間的關係,還反映了OpenAI在不同時間點的研究重點和技術進展。這個圖可以幫助研究人員和開發者瞭解LLMs系列的發展歷程,從而更好地理解和應用這些語言模型。

萬字帶你瞭解ChatGLM

2.Autoregressive Blank Infilling

2.1 Autoregressive、Autoencoding、Encoder-Decoder

“Autoregressive”、"Autoencoding"和"Encoder-Decoder"是三種常見的神經網路模型結構,用於處理序列資料或生成模型。

Autoregressive(自迴歸)模型是一種生成模型,它將序列資料的生成建模為一個逐步預測每個元素的條件機率的過程。在每個時間步,模型根據之前生成的元素預測當前元素的機率分佈。常見的Autoregressive模型包括語言模型,如OpenAI GPT模型,它可以生成與輸入序列相似的新文字。

Autoencoding(自編碼)模型是一類無監督學習方法,用於學習輸入資料的緊湊表示。它由一個編碼器和一個解碼器組成。編碼器將輸入資料對映到低維表示,解碼器將該低維表示恢復到原始資料空間。Autoencoding模型的目標是儘可能準確地重建輸入資料,同時學習到有用的特徵表示。常見的Autoencoding模型包括Variational Autoencoder (VAE)和Denoising Autoencoder。

Encoder-Decoder(編碼器-解碼器)模型是一種常用的序列到序列(Sequence-to-Sequence)模型,用於處理輸入和輸出都是序列資料的任務。它由兩個部分組成:編碼器和解碼器。編碼器將輸入序列對映為固定大小的向量表示,解碼器使用該向量表示生成輸出序列。Encoder-Decoder模型可以在不同長度的輸入和輸出序列之間進行轉換,例如機器翻譯和文字摘要等任務。

GLM(自迴歸填空)模型是一種靈活且多樣化的語言模型,可以根據給定的上下文生成缺失的部分內容。根據已知的部分文字內容生成可能的填空內容。它可以用於自動文字補全、問答系統、語義理解和生成等多個自然語言處理任務中。

萬字帶你瞭解ChatGLM

萬字帶你瞭解ChatGLM

2.1 OpenAI GPT系列模型

自然語言處理領域的GPT(Generative Pre-trained Transformer)系列模型是由OpenAI開發的一系列強大的自然語言處理模型。下面是GPT系列模型的發展歷程:

GPT-1: GPT模型是於2018年釋出的第一代模型。它使用了Transformer架構,預訓練了一個大規模的語言模型,並使用無標籤的文字資料進行模型訓練。這個模型的特點是生成連貫的文字,能夠完成一些基礎的自然語言處理任務,如語言模型、文字分類和文字生成等。

GPT-2: 在2019年,OpenAI釋出了GPT-2模型作為GPT的後續版本。GPT-2模型採用了更大的預訓練模型,使用無標籤的網際網路文字進行訓練。這個模型在生成文字方面取得了突破性的進展,可以生成高質量、連貫的文字,使得生成的文字內容更具有逼真性。由於考慮到模型被濫用可能帶來的風險,OpenAI最初限制了GPT-2的訪問,並未釋出完整的模型。

GPT-3: GPT-3是在2020年釋出的GPT系列的第三代模型。引數量達到了1750億個,訓練了十幾萬小時。GPT-3在文字生成、文字補全、問答系統等任務上表現出色,其生成的文字能夠接近人類水平的表達能力。GPT-3還可以透過提供一些文字提示來理解並回答問題,具有較強的語言理解和推理能力。

GPT-4:在2023年,OpenAI釋出了GPT-4,這是GPT系列的第四個模型。GPT-4比GPT-3系列大得多,具有1.8萬億個引數,而GPT-3只有1750億個引數。GPT4是一種多模態模型,而GPT3系列是一種自然語言處理模型。自然語言模型只能聽或看懂語言,而多模態模型可以處理多種媒體資料,並且將他們整合到統一的語義空間之中。GPT4可接收的文字輸入長度達到了驚人的32000字,而GPT3系列,只能輸入3000字。

萬字帶你瞭解ChatGLM

2.3 Autoregressive Blank Infilling

Autoregressive Blank Infilling(ABI)是一種用於填充時間序列資料中缺失值的方法。在時間序列資料中,由於種種原因,可能會存在一些缺失值,這些缺失值會影響資料的完整性和準確性。ABI方法透過基於自迴歸模型,利用其他已有的資料來預測並填補缺失值。

ABI方法的基本思想是根據時間序列資料的自相關性,使用已有的資料點來逐個預測缺失值。具體來說,ABI方法使用AR模型(自迴歸模型)來建模時間序列資料中的缺失值和非缺失值之間的關係。然後,根據該模型,利用其他已有的資料點來預測缺失值的數值。

ABI方法在填充缺失值時,通常還會考慮一些其他因素,如資料的趨勢、季節性和週期性等。透過綜合考慮這些因素,ABI方法能夠更準確地填充缺失值,從而提高資料的完整性和可靠性。

案例片段介紹如下:

順序分為A部分和B部分:

  • A部分:帶掩碼跨度的序列

  • B部分:在A部分中被掩蓋的原始跨度

萬字帶你瞭解ChatGLM

如果多個跨度被遮罩,它們將在B部分中被打亂

萬字帶你瞭解ChatGLM

B部分中的每個跨度都以[S]作為輸入,以[E]作為輸出。

該模型自迴歸生成B部分——它基於前一部分預測下一個令牌。

萬字帶你瞭解ChatGLM

A部分可以自行處理,但不能處理B部分

萬字帶你瞭解ChatGLM

B部分可以關注A及其在B中的經歷

萬字帶你瞭解ChatGLM

2.4 Multi-Task Pretraining

Multi-Task Pretraining是一種多工預訓練的方法。在傳統的預訓練方法中,語言模型透過在大規模文字資料上進行訓練來學習語言的通用模式和表示。然而,在Multi-Task Pretraining中,模型同時在多個任務上進行訓練,這些任務需要不同型別的語言理解能力。

Multi-Task Pretraining的思想是透過在多個任務上訓練語言模型,可以學習到更加通用和魯棒的語言表示。這是因為不同的任務需要不同的語言技能,如句法分析、語義理解或文件級連貫性。透過讓模型接觸多樣化的任務,它可以學習捕捉不同任務之間的共同語言模式,並利用這些模式更好地泛化到新任務上。

Multi-Task Pretraining已被證明可以提高語言模型在下游任務上的效能。例如,預訓練在多個任務上的模型在各種自然語言處理基準測試中取得了最先進的結果,如問答、文字分類和命名實體識別。

其中一種常見的Multi-Task Pretraining方法是基於Transformer的模型,如BERT(雙向編碼器表示來自Transformer的方法)和RoBERTa(經過最佳化的魯棒BERT方法)。這些模型在掩碼語言建模、下一個句子預測和其他輔助任務上進行預訓練。

案例片段介紹如下:

透過改變遮蓋內容的長度和數量,從而使模型能夠基於natural language understanding, conditional generation, unconditional generation三類任務進行預訓練,實現“三合一”

改變缺失跨度的數量和長度:

萬字帶你瞭解ChatGLM

2.5 Finetuning

Finetuning是指在預訓練的基礎上,將模型進一步調整和最佳化以適應特定任務或特定資料集的過程。在機器學習中,預訓練模型通常在大規模的資料上進行訓練,學習到通用的模式和特徵表示。然而,這些預訓練模型可能不直接適用於特定的任務或資料集。

透過Finetuning,可以利用預訓練模型的通用知識和特徵表示來快速適應特定的任務或資料集。這通常涉及解凍預訓練模型的一部分或全部層,並在目標任務上進行進一步的訓練。透過在目標任務上微調模型引數,可以使其更好地適應任務的特定要求和資料特徵。

Finetuning的過程通常包括以下步驟:

  1. 選擇預訓練模型:選擇與目標任務相匹配的預訓練模型,如BERT或GPT等。
  2. 初始化引數:將預訓練模型載入到模型中,並凍結所有或部分層的引數。
  3. 構建任務特定層:根據目標任務的需求,構建一個或多個任務特定的層。
  4. 訓練:使用目標任務的資料集,透過反向傳播和梯度下降等最佳化演算法,更新模型的引數。
  5. 調整超引數:對模型進行驗證和評估,並根據結果調整超引數,如學習率、批大小等。
  6. 重複迭代:根據需要,多次迭代訓練和調整模型,直到達到滿意的效能。

Finetuning可以大大減少在特定任務上的訓練時間和樣本需求,同時利用預訓練模型的知識提供了更好的初始引數和特徵表示。它已經被廣泛應用於自然語言處理、計算機視覺和其他領域中的許多工,如文字分類、問答、命名實體識別等。

案例片段介紹如下:

GLM將NLG和NLU類下游任務統一為完型填空的生成式任務,如對於分類任務,將輸入x寫成一個填空問題c(x),後將生成的答案v(y)對映至標籤y

萬字帶你瞭解ChatGLM

2.6 LLM Reversal Curse

LLM(Large Language Model)是指一種非常大的語言模型,它由數十億個引數組成,具有強大的語言理解和生成能力。大模型LLM可以實現諸如問答、摘要、對話生成等任務,被廣泛應用於自然語言處理領域。

LLM Reversal Curse(逆轉詛咒)是指在使用大模型LLM進行任務生成時,其生成結果出現明顯的逆轉或反轉現象。具體而言,當模型用於生成某個任務的結果時,相比原始輸入,生成的結果可能會出現與原始意圖相反的內容或表達。

例如,在問答任務中,當使用者提出一個問題時,大模型LLM應該生成一個準確且與問題相符的答案。然而,由於模型的複雜性和訓練資料的特點,有時候模型會出現生成與問題相反甚至荒謬的答案的情況。

這種逆轉詛咒可能是由於模型在訓練過程中接觸到了大量的噪聲資料、錯誤標註的資料或具有偏見的資料,導致模型在生成過程中出現了一些意料之外的結果。

為了解決大模型LLM的逆轉詛咒問題,需要進一步最佳化模型的訓練資料、標註過程和生成演算法,以提高模型的生成質量和準確性。

案例片段介紹如下:

萬字帶你瞭解ChatGLM

3. 2D Positional Encoding

2D positional encoding是一種將2D網格或影像中元素的位置資訊進行編碼的技術。位置編碼通常在自然語言處理任務中使用,例如機器翻譯或語言建模,來表示句子中單詞的順序或位置。然而,它也可以應用於2D網格或影像。

對於2D網格或影像,位置編碼可以用於編碼每個元素的空間位置。這樣,模型可以有一種對元素之間的相對位置的感知,並捕捉它們之間的空間關係。

一個常見的2D位置編碼的方法是使用不同頻率的正弦和餘弦函式。其思想是建立一個根據網格或影像內位置而變化的正弦訊號。然後將這個位置編碼作為每個元素在網格或影像中的額外輸入或特徵。

位置編碼可以使用以下公式定義:

PE(x,2i) = sin(x / (10000^(2i / d_model)))
PE(x,2i+1) = cos(x / (10000^(2i / d_model)))

其中,PE(x, i)表示位置i處元素x的位置編碼,d_model是模型的維度。

透過使用正弦和餘弦函式的不同頻率,位置編碼可以捕捉位置資訊中的不同模式或關係。

案例片段介紹如下:

模型輸入的position ids分為兩種,從而使得模型可以學習到片段生成的長度

Position 1: Part A中token的絕對位置

  • Part A:從1開始排列

  • Part B:每一個span對應Part A中[MASK]的位置

Position 2:intra-span position,masked span內部的相對位置

  • Part A:0
  • Part B:每個span的token從1開始排列

萬字帶你瞭解ChatGLM

萬字帶你瞭解ChatGLM

3.1 大模型訓練最大挑戰:訓練穩定性

  • 權衡利弊:訓練穩定性(高精度低效)還是訓練效率(低精度高效)

  • 目前已開源訓練過程大模型的解決方案

    • FB OPT-175B:訓練崩潰時反覆調整學習率/跳過資料(權宜之計,損失效能)
    • HF BLOOM 176B:embedding norm和BF16(損失效能,有限適配平臺)

萬字帶你瞭解ChatGLM

3.2 GLM-130B:穩定訓練方法

GLM-130B是一個穩定訓練方法,它是機器學習中的一種演算法。GLM代表廣義線性模型,130B表示這個演算法的特定版本。

穩定訓練方法是指透過一定的技巧和策略來增強模型的穩定性和魯棒性,使其能夠更好地處理噪聲和異常資料。在訓練過程中,穩定訓練方法會對輸入樣本或特徵進行一些改變或調整,以減少模型對於噪聲的敏感性。

GLM-130B的穩定訓練方法可能包括以下幾個方面:

  1. 資料預處理:對輸入資料進行去噪、歸一化、特徵選擇等預處理操作,以減少噪聲對模型訓練的影響。
  2. 正則化:透過新增正則化項來限制模型的複雜度,防止過擬合,提高模型的泛化能力。
  3. 異常值處理:透過識別和處理異常值,減少它們對模型訓練的影響。
  4. 隨機化:引入隨機化因素,如隨機選擇樣本、隨機初始化引數等,以增加模型的穩定性和抗噪能力。
  5. 交叉驗證:使用交叉驗證來評估模型的效能,並選擇最佳的引數配置,避免對特定資料集過擬合。
  6. 整合學習:透過整合多個模型的預測結果,綜合考慮它們的意見,提高整體模型的效能和穩定性。

案例片段介紹如下:

Attention score 層:Softmax in 32 避免上下溢位

萬字帶你瞭解ChatGLM

調小 Embedding 層梯度,緩解前期梯度爆炸問題

word_embedding = word_embedding * alpha +  word_embedding .detach() * (1 ‒ alpha)

萬字帶你瞭解ChatGLM

萬字帶你瞭解ChatGLM

3.2 GLM-130B:大量實驗確定最優架構

有時候需要進行多次實驗來確定最佳的架構設計。這些實驗可能包括調整不同的引數、新增或移除不同的元件,以及測試不同的配置選項。GLM-130B是根據這些實驗的結果和分析,確定出的最佳架構。

案例片段介紹如下:

DeepNorm:穩定訓練 1000 層 Post-LN 的方法

萬字帶你瞭解ChatGLM

旋轉位置編碼(RoPE):適用於 GLM 的相對位置編碼

萬字帶你瞭解ChatGLM

門控注意單元(GLU):FFN 層的替換,穩定提升模型效能

萬字帶你瞭解ChatGLM

萬字帶你瞭解ChatGLM

3.3 Post LayerNorm

Post LayerNorm(後層歸一化)是一種神經網路層歸一化的方法,用於解決深層神經網路中梯度消失和梯度爆炸問題。傳統的 LayerNorm(層歸一化)是在每個神經網路層的輸入上進行歸一化操作,而 Post LayerNorm 是在每個神經網路層的輸出上進行歸一化操作。

具體來說,在每個神經網路層的輸入和啟用函式之間,先進行 LayerNorm 的歸一化操作,然後再進行啟用函式的計算。這樣可以使得每個神經網路層的輸出都在相似的尺度上,避免了梯度消失和梯度爆炸的問題。

與之相比,傳統的 LayerNorm 在每個神經網路層的輸入上進行歸一化操作,但在深層網路中,由於每層的輸入分佈不穩定,因此歸一化操作的效果可能會下降。而 Post LayerNorm 能夠在每個神經網路層的輸出上進行歸一化操作,保證了歸一化的效果,提高了網路的穩定性和訓練效果。

Post LayerNorm 是在 Transformer 網路中被提出的,並在各個任務上取得了顯著的效能提升。它被認為是一種更加有效和穩定的歸一化方法,在大規模深層網路的訓練中具有重要的作用。

案例片段介紹如下:

重新排列層規範化和剩餘連線的順序

萬字帶你瞭解ChatGLM

3.4 GLU

GLU(Gated Linear Unit)是一種門控線性單元,用於增強神經網路的表示能力。透過將GLU應用於MindSpore框架中的大型模型,可以進一步提升模型的效能和效果。

GLU的核心思想是將輸入進行分割成兩部分,然後透過門控機制控制兩部分的資訊傳遞。這種門控機制可以幫助模型更好地理解輸入資料中的相關性,從而提高模型的表達能力和泛化能力。

在MindSpore框架中,GLU可以被用於各種任務,包括自然語言處理、計算機視覺和語音識別等。透過使用MindSpore大模型GLU,研究人員和開發人員可以更輕鬆地構建和訓練複雜的模型,並獲得更好的結果。

案例片段介紹如下:

用GeLU替換ReLU啟用

萬字帶你瞭解ChatGLM

3.5 並行策略:高效訓練千億模型

存下 GPT-3 模型需要 2.8T 視訊記憶體存放訓練狀態 + 中間啟用函式值

萬字帶你瞭解ChatGLM

挑戰:遠超單卡視訊記憶體(40GB),採取何種並行方式高效訓練?

  • 採用 ZeRO 最佳化器在資料並行組內分攤最佳化器狀態 → ~25%

萬字帶你瞭解ChatGLM

遠超單卡視訊記憶體,如何高效訓練?

模型並行:將模型引數分佈到多個 GPU 上

  • 張量並行:切分引數矩陣,每 GPU 計算一部分 → 額外通訊,降低計算粒度
  • 流水線並行:將網路分成多段並行 → 引入流水線氣泡
  • ZeRO-3:將引數分佈到資料並行組中,算之前先取回引數 → 額外通訊時間

分析:流水線的氣泡佔比: 𝑛⁄𝑡 $ 1 ,n / t << 4m 的時候可以忽略不計

並行策略:張量並行隨著模型規模增大緩慢擴充套件,但不超過單機規模(
<=8),其餘全部使用流水線並行,透過調整微批處理大小減少氣泡佔比

萬字帶你瞭解ChatGLM

其他最佳化

  • 運算元融合:融合多個 element-wise 運算元 → 提升 ~10% 計算速度
  • 流水線平衡:流水線首尾階段各少放置一個層平衡佔用 → 節省 ~10% 視訊記憶體

跨平臺相容:swDeepSpeed 訓練庫  與 DeepSpeed API 相容

  • 支援申威架構,一行程式碼無縫替換相容
  • 實現並行通訊策略,混合精度策略,ZeRO 最佳化器
  • 同一套訓練框架可在三個叢集上對齊訓練曲線
import swDeepSpeed as deepspeed
model, optimizer, _, _ = 
    deepspeed.initialize(  
        model=model,  
        model_parameters=param_groups,  
        args=args,
        mpu=mpu,
        dist_init_required=False,  
        config_params=config_params
)
萬字帶你瞭解ChatGLM

測試叢集配置:

  • A100 叢集(A100): 96 臺 DGX-A100,每臺 2 張 200GB IB 網路卡 硬體差異性大
  • 海光GPU(Hygon):3000 臺機器,每臺 4 張 DCU 加速卡、4 張 50G IB 網路卡
  • 申威處理器(Sunway):8192 個節點,每節點一塊 SW26010-PRO 處理器
訓練 GPT-3 175B 規模的模型,按照相同的 300B 單詞量估計訓練時間:

萬字帶你瞭解ChatGLM

4.Rotary Positional Embedding

4.1 Introduction of Positional Embedding

Positional Embedding(位置編碼)是一種用於處理序列資料的技術,主要應用於自然語言處理(NLP)任務中。在序列資料中,單詞的順序和位置對於語義的理解非常重要。位置編碼的目的是為了將單詞的位置資訊融入到模型的表示中,使得模型能夠更好地理解單詞的順序和上下文關係。

傳統的詞向量表示只考慮了單詞的語義資訊,而沒有考慮單詞的位置。位置編碼透過為每個單詞分配一個唯一的位置向量來解決這個問題。常用的位置編碼方法包括相對位置編碼、絕對位置編碼、正弦位置編碼等。

在相對位置編碼中,每個單詞的位置編碼是相對於其他單詞的位置差異而得到的。絕對位置編碼則是將每個單詞的位置對映為一個唯一的位置向量。正弦位置編碼是一種常用的絕對位置編碼方法,透過使用正弦和餘弦函式來生成位置向量,從而捕捉到不同位置之間的相對關係。

位置編碼的作用是為模型提供位置資訊,幫助模型在處理序列資料時更好地理解單詞的上下文和關係。它通常與注意力機制和Transformer等模型結構一起使用,為模型提供更豐富的上下文資訊。

案例片段介紹如下:

自注意力機制主要關注詞語之間的相互關係,在計算中,根據詞語之間的語義關係來計算注意力分數,並不會考慮詞語之間的位置關係。

即使打亂序列中詞語的順序,依舊會得到相同的語義表達因此需要額外增加位置資訊。

The dog chased the pig. 
= The pig chased the dog. 
= chased pig The the dog.

萬字帶你瞭解ChatGLM

位置資訊的表示有很多種,如

absolute positional embeddings:

  • 原理:對於第k個位置的向量xk,新增位置向量pk(僅依賴於位置編號k),得到xk+pk
  • 舉例/應用模型:sinusoidal positional embedding(Transformer)、learned absolute positional embedding(BERT/RoBERTa/GPT)

relative positional embeddings:

  • 原理:對於第m個和第n個位置的向量xm、xn,將相對位置m-n的資訊新增到self-attention matrix中
  • 舉例/應用模型:T5

rotary positional embeddings

  • 原理:使用旋轉矩陣對絕對位置進行編碼,並同時在自注意力公式中引入了顯式的相對位置依賴。
  • 舉例/應用模型:PaLM/GPT-Neo/GPT-J/LLaMa1&2/ChatGLM1&2

4.2 Sinusoidal Positional Embedding

Sinusoidal Positional Embedding(正弦位置編碼)是一種用於編碼序列資料中單詞位置資訊的方法,最初在Transformer模型中被引入。它是一種絕對位置編碼方法,透過正弦和餘弦函式來生成位置向量,從而捕捉到不同位置之間的相對關係。

在正弦位置編碼中,每個單詞的位置編碼由兩個維度的正弦和餘弦函式計算得到。具體計算公式如下:

PE(pos,2i) = sin(pos / 10000^(2i/d_model))
PE(pos,2i+1) = cos(pos / 10000^(2i/d_model))

其中,pos表示單詞在序列中的位置,i表示位置向量的維度索引,d_model表示模型的維度。這樣,每個單詞的位置編碼可以由位置索引pos和維度索引i計算得到。

正弦位置編碼的特點是,不同位置之間的位置向量是正弦和餘弦函式的週期函式。這使得不同位置之間的位置向量能夠保持一定的相似性,從而幫助模型更好地理解位置資訊並捕捉到序列中的順序關係。

正弦位置編碼通常與注意力機制和Transformer模型一起使用,用於為模型提供序列資料的位置資訊。它的優點是簡單且可解釋,能夠有效地表達不同位置之間的相對關係。

案例片段介紹如下:

透過sine和cosine函式計算每個位置的positional embedding

  • 優點:1. 可以反應相對位置資訊;2. 模型可以接受不同長度的輸入

  • 缺點:數值為固定值,無法參與學習

PE(pos, 2i)=sin(pos/10000^2i/d_model)

PE(pos, 2i+1)=cos⁡(pos/10000^2i/d_model)

萬字帶你瞭解ChatGLM

4.3 Learned Positional Embedding

Learned Positional Embedding是一種在自然語言處理任務中用於編碼位置資訊的技術。在傳統的Transformer模型中,位置編碼是透過固定的數學公式(如正弦函式或餘弦函式)來計算得到的。而Learned Positional Embedding則是透過在模型的嵌入層中引入可學習的引數來學習位置資訊的表示。

傳統的位置編碼方法只能對句子的位置進行大致的編碼,而Learned Positional Embedding可以更準確地表示不同位置的資訊。當模型學習到不同位置的嵌入表示時,它可以更好地區分不同位置的詞語,並捕捉到位置資訊對任務的影響。

Learned Positional Embedding的一個優點是可以根據任務的需要進行調整。傳統的位置編碼是固定的,不會隨著訓練進行調整。而Learned Positional Embedding可以透過反向傳播演算法來最佳化引數,以更好地適應不同任務的需求。

案例片段介紹如下:

將表示位置的position ids放入nn.Embedding,獲取大小為hidden size的positional embedding

  • 優點:可以隨模型訓練進行引數更新

  • 缺點:可擴充套件性差,只能表徵在max_seq_length以內的位置

萬字帶你瞭解ChatGLM

4.4 Relative Positional Embedding

相對位置嵌入(Relative Positional Embedding)是一種用於編碼序列中元素之間相對位置關係的技術,常用於自然語言處理和序列建模任務中。

在傳統的位置嵌入方法中,如正弦/餘弦位置嵌入(Sinusoidal Positional Embedding)或學習位置嵌入(Learned Positional Embedding),每個位置的嵌入向量是固定的,不考慮其與其他位置的關係。但在很多工中,序列中的元素之間的相對位置關係對於理解序列的語義和結構非常重要。

相對位置嵌入透過將每個元素的位置嵌入向量與其他位置的偏移向量進行組合,來編碼元素之間的相對距離。這樣,每個元素的位置嵌入向量會隨著其與其他元素的位置關係而變化,從而更好地捕捉序列中的區域性結構資訊。

相對位置嵌入常用於Transformer模型中,在自注意力機制(Self-Attention)中使用。透過引入相對位置嵌入,Transformer可以更好地處理序列中元素之間的相對位置關係,從而提高序列建模的效能。在相對位置嵌入中,常見的方法是使用距離編碼矩陣(Distance Encoding Matrix)來計算偏移向量,然後與位置嵌入向量相加。

案例片段介紹如下:

在計算自注意力分數時,在query和key的dot product,以及最終注意力權重和value矩陣乘時,分別額外新增一個表示位置m和位置n相對位置資訊的bias,僅依賴於m-n

優點:

  • 可以直觀記錄詞語的相對位置資訊

  • 模型可接受不同長度的輸入

缺點:

  • 訓練和推理速度慢(尤其是長序列的時候)

萬字帶你瞭解ChatGLM

萬字帶你瞭解ChatGLM

4.5 Rotary Positional Embedding

相關程式碼如下:

萬字帶你瞭解ChatGLM

4.5.1 2D case

Rotary Positional Embedding - 2D case是一種用於編碼二維序列中位置資訊的方法,特別適用於Transformer等模型中的注意力機制。

在傳統的位置嵌入方法中,如正弦/餘弦位置嵌入(Sinusoidal Positional Embedding)或學習位置嵌入(Learned Positional Embedding),每個位置的嵌入向量是固定的,不考慮其與其他位置的關係。但對於二維序列,僅使用位置索引的編碼方法無法很好地捕捉到元素在二維空間中的相對位置關係。

Rotary Positional Embedding - 2D case透過引入角度資訊,能夠更好地編碼二維序列中元素的位置關係。具體來說,它使用了旋轉操作來編碼位置資訊,這可以看作是將位置嵌入向量繞原點旋轉一定的角度。透過在嵌入向量中引入角度資訊,可以更好地表示元素在二維空間中的相對位置。

在2D案例中,Rotary Positional Embedding通常與自注意力機制(Self-Attention)一起使用。在注意力機制中,透過將位置嵌入向量與注意力權重相乘,並進行相應的運算,將位置資訊引入注意力計算中。這樣,模型可以更好地理解元素之間的相對位置關係,從而提高序列建模的效能。

案例片段介紹如下:

以2D word vector為例,第m個位置的詞語可以用一個二維的向量xm表示,我們將它的query和key向量在2D平面上進行逆時針旋轉,旋轉角度取決於位置索引m

  • dog:單詞dog在第0位,不進行旋轉

  • The dog:單詞dog在第1位,旋轉角度θ

  • The pig chased the dog:單詞dog在第4位,旋轉角度4

萬字帶你瞭解ChatGLM

這樣在計算xm和xnquery,key的點積時,結果僅和(m-n)θ有關,而非m或n

優點:

  • 計算self-attention q,k點積時,保留了詞語的相對位置資訊(不會因詞語的絕對位置發生改變)

  • 前面位置的positional embedding不受後續新增token的影響(easier to cache)

  • token之間的依賴會隨著相對距離的增長而逐步衰減(符合認知,距離越遠的詞普遍關聯不大)

萬字帶你瞭解ChatGLM

4.5.2 general form

Rotary Positional Embedding - general form是一種用於編碼位置資訊的方法,通用形式適用於各種序列資料,包括一維、二維或其他維度的序列。

在傳統的位置嵌入方法中,如正弦/餘弦位置嵌入(Sinusoidal Positional Embedding)或學習位置嵌入(Learned Positional Embedding),每個位置的嵌入向量是固定的,不考慮其與其他位置的關係。但是,這種方法無法很好地捕捉到元素在序列中的相對位置關係。

Rotary Positional Embedding - general form透過引入旋轉操作,能夠更好地編碼序列中元素的位置關係。具體來說,它使用了旋轉矩陣來對位置嵌入進行變換,這可以看作是將位置嵌入向量繞一個固定的軸旋轉一定的角度。透過在嵌入向量中引入旋轉資訊,可以更好地表示元素在序列中的相對位置。

在一般形式中,Rotary Positional Embedding可以與注意力機制(Attention Mechanism)一起使用。在注意力機制中,透過將位置嵌入向量與注意力權重相乘,並進行相應的運算,將位置資訊引入注意力計算中。這樣,模型可以更好地理解元素之間的相對位置關係,從而提高序列建模的效能。

案例片段介紹如下:

  • 將單詞的詞向量大小設定為2的倍數
  • 第m個位置的詞向量在第i組2D sub-space(即向量中的2i,2i+1元素)的旋轉角度為mθ_i,θ_i與i以及詞向量的hidden size有關

萬字帶你瞭解ChatGLM

二、From GLM to ChatGLM

1.傳統NLP的挑戰

1.1 挑戰1:傳統NLP vs 複雜問題

傳統NLP(自然語言處理)方法通常用於處理簡單的文字任務,例如文字分類、命名實體識別和情感分析等。這些方法主要依賴於規則和模式,以及統計和機器學習演算法。

對於複雜問題,傳統NLP方法可能面臨一些挑戰。複雜問題通常具有多義性、歧義性和上下文依賴性。例如,理解一個句子的意思可能需要考慮上下文資訊和背景知識。此外,複雜問題還可能涉及多種語言和跨語言的處理。

為了應對複雜問題,研究者們開始使用深度學習方法,如迴圈神經網路(RNN)和注意力機制等。這些方法能夠更好地處理語義理解和生成,以及更好地捕捉文字的上下文資訊。

複雜問題還可能需要結合其他領域的知識,例如知識圖譜、計算機視覺和知識推理等。這樣可以提供更全面的語義理解和推理能力。

萬字帶你瞭解ChatGLM

1.2 挑戰2:傳統NLP vs 動態知識

傳統NLP(自然語言處理)是一種基於規則和模式的方法,它主要依賴於人工編碼的語言規則和語法結構來理解和處理文字。這些規則和結構需要事先定義,並且通常需要大量的人工工作。

動態知識(Dynamic Knowledge)則是一種基於知識圖譜和自動學習的方法,它能夠根據實時的資料來自動更新和擴充套件知識庫。動態知識利用機器學習和圖譜技術,可以從大量的文字和語料庫中自動提取和建立知識模型。

傳統NLP的一個主要優勢是其可解釋性,因為所有的規則和模式都是人工定義的,所以可以清楚地理解其工作原理。然而,它也存在一些缺點,例如需要大量的人工工作來編寫和維護規則,而且對於複雜的語言現象和變化的語言規則往往無法適應。

相比之下,動態知識能夠透過機器學習和自動學習的方式,自動地從大量的文字中提取和建立知識模型。它可以自動學習語言現象和規則的變化,並且可以根據實時的資料來更新和擴充套件知識庫。動態知識的優點是其能夠處理複雜的語言現象和變化的語言規則,並且具有較強的適應性和靈活性。

但動態知識也存在一些挑戰,例如其可解釋性相對較差,因為知識模型是透過機器學習自動學習的,所以很難直觀地理解其工作原理。此外,動態知識的構建和維護也需要大量的計算資源和資料支援。

案例片段介紹如下:

千億模型的動態知識欠缺、知識陳舊、缺乏可解釋性

  • 知識欠缺:長尾知識

    • 例如: 世界第二高的山峰(答案: K2格里峰)
  • 知識陳日:GPT-3的訓練資料截止2020年前

  • 不可解釋:缺乏答案的參考源

萬字帶你瞭解ChatGLM

1.3 挑戰3:傳統NLP vs 人類對齊

傳統NLP是基於機器學習和統計的方法,利用大量已標註的語料庫來訓練模型。這些模型可以識別和理解文字的語法結構、詞義和語義關係等。傳統NLP方法包括語法分析、詞性標註、命名實體識別、情感分析等技術。這些技術可以自動處理大規模的文字資料,並提供一些高階的語言處理功能。

人類對齊是指透過人工的方式對文字進行處理和理解。人類對齊可以是透過人工標註和標記的方式,也可以是透過人工閱讀和理解的方式。人類對齊可以更準確地理解文字的含義和語境,尤其在處理一些複雜的語言結構和語義問題時更具優勢。人類對齊可以包括人工智慧助手和人工翻譯等應用。

傳統NLP和人類對齊兩種方法各有優缺點。傳統NLP方法可以在處理大規模資料時提供高效的處理能力,但在面對複雜語義問題時可能存在理解不準確或無法捕捉語境的問題。而人類對齊可以更準確地理解文字的含義和語境,但在大規模處理和實時處理方面可能存在效率和成本的問題。

案例片段介紹如下:

例如:請用幾句話給一個6歲小孩解釋登月

  • 缺少高效"Prompt工程",GPT-3和GLM-130B都很難盡人意

萬字帶你瞭解ChatGLM

2.從千億模型到ChatGLM的技術路線

千億模型GLM-130B是一個大規模語言模型,具有130億個引數,用於自然語言處理任務。它採用了Transformer架構和大規模預訓練技術,可以生成高質量的文字。

GLM-130B+是在GLM-130B的基礎上進行了改進和最佳化。它針對語言模型的訓練過程進行了一些調整,提升了模型的效能和效果。GLM-130B+在更多的自然語言處理任務上具有更好的表現。

GLM-130B++是在GLM-130B+的基礎上進一步改進的版本。它引入了更多的新技術和最佳化策略,使得模型在處理長文字、多語種和多工上表現更出色。GLM-130B++具有更強大的表達能力和更好的泛化能力。

ChatGLM模型是基於GLM系列模型的一種變種,專門用於生成對話文字。它在GLM-130B++的基礎上進行了一些改進,使得模型在對話生成任務上更加適用和有效。ChatGLM模型在生成對話內容時可以更好地理解上下文和語境,並生成更具連貫性和合理性的對話文字。

萬字帶你瞭解ChatGLM

3.ChatGLM的應用場景

3.1 撰寫部落格提綱

萬字帶你瞭解ChatGLM

3.2 寫郵件

萬字帶你瞭解ChatGLM

3.3 介紹自己的優點缺點

萬字帶你瞭解ChatGLM

3.4 寫劇本梗概

萬字帶你瞭解ChatGLM

3.5 寫程式碼

萬字帶你瞭解ChatGLM

3.6 查詢常見知識/教程

萬字帶你瞭解ChatGLM

3.7 多輪問答

萬字帶你瞭解ChatGLM

萬字帶你瞭解ChatGLM

3.8 文字冒險遊戲

萬字帶你瞭解ChatGLM

三、ChatGLM Demo

完整的課程學習地址:完整的課程學習地址

萬字帶你瞭解ChatGLM

1.使用NPU+MindSpore Transformers試用ChatGLM推理

1.1 OpenI啟智執行ChatGLM模型

1、到OpenI啟智申請賬號,開啟雲腦任務(NPU)/自己用GPU建立環境

OpenI啟智申請賬號地址:https://openi.pcl.ac.cn/user/sign_up

萬字帶你瞭解ChatGLM

2、建立專案

萬字帶你瞭解ChatGLM

3、開啟新建立的專案,點選雲腦,新建除錯任務

萬字帶你瞭解ChatGLM

4、點選除錯

萬字帶你瞭解ChatGLM
5、進入終端

萬字帶你瞭解ChatGLM

萬字帶你瞭解ChatGLM

其他操作如下面1.2小結,這邊只是用OpenI啟智NPU+MindSpore進行線上部署除錯,部署結果如下圖:

萬字帶你瞭解ChatGLM

1.2 MindSpore執行ChatGLM模型

安裝MindSpore和MindSpore Transformers

a) MindSpore安裝:參考:MindSpore官網(如果用OpenI啟智NPU+MindSpore,可以忽略這一步,這步屬於本地部署)

b) MindSpore Transformers安裝:

1、git clone -b dev https://gitee.com/mindspore/mindformers.git

2、cd mindformers

3、bash build.sh

4、如果使用MindSpore1.10版本,請安裝MindFormers 0.6版本(git clone -b r0.6 …)

c) 克隆昇思MindSpore技術公開課程式碼倉:

git clone https://github.com/mindspore-courses/step_into_llm.git

d) cd step_into_llm/Season2.step_into_llm/01.ChatGLM/

e) 下載ckpt和tokenizer檔案

1、ckpt:wget https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/XFormer_for_mindspore/glm/glm_6b.ckpt

2、tokenizer:wget https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/XFormer_for_mindspore/glm/ice_text.model

f) 執行推理部署檔案:python cli_demo.py

import os
import platform
import signal
import numpy as np

import mindspore as ms
from mindformers.models.glm import GLMConfig, GLMChatModel
from mindformers.models.glm.chatglm_6b_tokenizer import ChatGLMTokenizer
from mindformers.models.glm.glm_processor import process_response

config = GLMConfig(
    position_encoding_2d=True,
    use_past=True,
    is_sample_acceleration=True)

ms.set_context(mode=ms.GRAPH_MODE, device_target="GPU", device_id=0)
model = GLMChatModel(config)
# https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/XFormer_for_mindspore/glm/glm_6b.ckpt
ms.load_checkpoint("./glm_6b.ckpt", model)
# https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/XFormer_for_mindspore/glm/ice_text.model
tokenizer = ChatGLMTokenizer('./ice_text.model')
os_name = platform.system()
clear_command = 'cls' if os_name == 'Windows' else 'clear'
stop_stream = False
def build_prompt(history):
    prompt = "歡迎使用 ChatGLM-6B 模型,輸入內容即可進行對話,clear 清空對話歷史,stop 終止程式"
    for query, response in history:
        prompt += f"\n\n使用者:{query}"
        prompt += f"\n\nChatGLM-6B:{response}"
    return prompt
def signal_handler():
    global stop_stream
    stop_stream = True
def main():
    history = []
    global stop_stream
    print("歡迎使用 ChatGLM-6B 模型,輸入內容即可進行對話,clear 清空對話歷史,stop 終止程式")
    while True:
        query = input("\n使用者:")
        if query.strip() == "stop":
            break
        if query.strip() == "clear":
            history = []
            os.system(clear_command)
            print("歡迎使用 ChatGLM-6B 模型,輸入內容即可進行對話,clear 清空對話歷史,stop 終止程式")
            continue
        count = 0

        inputs = tokenizer(query)
        outputs = model.generate(np.expand_dims(np.array(inputs['input_ids']).astype(np.int32), 0),
                                 max_length=config.max_decode_length, do_sample=False, top_p=0.7, top_k=1)

        response = tokenizer.decode(outputs)
        response = process_response(response[0])
        history = history + [(query, response)]

        if stop_stream:
            stop_stream = False
            break
        else:
            count += 1
            if count % 8 == 0:
                os.system(clear_command)
                print(build_prompt(history), flush=True)
                signal.signal(signal.SIGINT, signal_handler)
        os.system(clear_command)
        print(build_prompt(history), flush=True)
if __name__ == "__main__":
    main()

總結

MindSpore作為一種強大的深度學習框架,提供了豐富的工具和功能,使得模型的開發和訓練更加高效和靈活。其支援端到端的深度學習解決方案,可以應用於各種任務和場景。而ChatGLM作為一種生成式語言模型,透過對話的方式生成自然流暢的文字,可以用於智慧對話和智慧客服等應用。

結合使用MindSpore和ChatGLM,我們可以實現更加智慧和互動性的應用。首先,MindSpore可以用來訓練ChatGLM模型,透過大量的對話資料進行學習,使得生成的文字更加貼近真實的對話。MindSpore提供了分散式訓練的功能,可以在多個裝置和計算節點上進行模型的並行訓練,加速訓練過程。其自動微分功能也可以幫助最佳化ChatGLM模型的訓練效果。

透過MindSpore的強大功能和ChatGLM的生成式語言模型,我們可以構建出高效、準確和自然流暢的智慧對話系統,提升使用者體驗並開拓更多的應用領域。這種結合使用不僅有助於推動機器學習和人工智慧的發展,還為帶來更多的創新和可能性。

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章