深度學習模型的開發和佈署流程通常涉及多個框架和平臺,這使得模型的轉換和佈署變得複雜。ONNX 作為一種開放的模型交換格式,能有效解決這個問題。它允許開發者將訓練好的模型從一個框架(例如 PyTorch)轉換到另一個框架(例如 TensorFlow),並在不同的平臺上佈署。同時,結合 LangChain 和 MLOps 等工具,可以進一步簡化模型開發、佈署和管理流程,提高效率並降低成本。本文將詳細介紹 ONNX 的使用方法,並結合 LangChain 和 MLOps 的應用,提供一個更全面的模型開發和佈署。

實作細節

以下是實作微調轉換器的細節:

from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForSequenceClassification

# 載入資料集
dataset = load_dataset('rotten_tomatoes')

# 載入預訓練模型
tokenizer = AutoTokenizer.from_pretrained('distilbert-base-uncased')
model = AutoModelForSequenceClassification.from_pretrained('distilbert-base-uncased')

# 建立資料集類別
tok_dataset = dataset.map(
    lambda x: tokenizer(
        text=x['text'],
        padding='max_length',
        truncation=True
    ),
    batched=True
)

# 定義訓練迴圈
def train(model, dataset, epochs):
    for epoch in range(epochs):
        # 前向傳播
        outputs = model(**dataset)
        # 反向傳播
        loss = outputs.loss
        # 最佳化器更新
        optimizer = torch.optim.Adam(model.parameters(), lr=1e-5)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

# 訓練模型
train(model, tok_dataset, epochs=5)

這個程式碼載入了資料集和預訓練模型,建立了資料集類別,定義了訓練迴圈,然後訓練了模型。

使用 Transformers 進行文字分類別

在本文中,我們將使用 Transformers 進行文字分類別任務。首先,我們需要載入 DistilBERT 的組態,並為二元分類別任務設定模型頭。這個組態適合我們的任務,因為我們需要將電影評論分類別為兩個類別。

初始化 TrainingArguments

接下來,我們需要初始化 TrainingArguments 來指定模型預測和檢查點的輸出位置。我們還會在每個 epoch 後進行評估。

from transformers import TrainingArguments

training_args = TrainingArguments(
    output_dir='test_trainer',
    evaluation_strategy='epoch'
)

初始化準確度評估指標

然後,我們需要初始化準確度評估指標。

import evaluate

accuracy = evaluate.load('accuracy')

初始化 Trainer

現在,我們可以初始化 Trainer 並傳入所有必要的元件,包括模型、訓練資料集、評估資料集和 TrainingArguments。

from transformers import Trainer
import numpy as np

trainer = Trainer(
    model=model,
    train_dataset=tok_dataset['train'],
    eval_dataset=tok_dataset['test'],
    args=training_args,
    compute_metrics=lambda x: {'accuracy': accuracy.compute(
        predictions=np.argmax(x.predictions, axis=-1),
        references=x.label_ids
    )},
    preprocess_logits_for_metrics=lambda x, _: np.argmax(x.cpu(), axis=-1)
)

執行訓練

最後,我們可以執行訓練。

trainer.train()

這個模型在三個 epoch 後可以達到大約 85% 的準確度。

圖表翻譯:

  flowchart TD
    A[載入 DistilBERT 組態] --> B[設定模型頭]
    B --> C[初始化 TrainingArguments]
    C --> D[初始化準確度評估指標]
    D --> E[初始化 Trainer]
    E --> F[執行訓練]
    F --> G[模型達到 85% 準確度]

此圖表展示了使用 Transformers 進行文字分類別的流程,從載入 DistilBERT 組態到執行訓練,並最終達到 85% 的準確度。

Harnessing the Power of LLMs with LangChain

LangChain是一個強大的框架,能夠幫助我們克服LLM的限制,例如上下文視窗長度和知識更新問題。它提供了多個模組,包括Model I/O、Retrieval、Chains、Memory、Agents和Callbacks。

Model I/O

Model I/O模組提供了幫助器提示範本,讓我們可以輕鬆地與LLM互動。它支援兩種型別的模型:經典LLM和聊天模型。經典LLM可以使用單個提示生成回應,而聊天模型則需要與人類進行互動式對話。

Retrieval

Retrieval模組可以從外部資料源中檢索資料,並將其餵入LLM的輸入序列中。它支援多種資料格式,包括CSV和JSON,並可以將大檔案分割成小塊以適應上下文視窗大小。

Chains

Chains模組允許我們組合多個LangChain元件,建立一個單一的應用程式。例如,我們可以建立一個鏈條,接收使用者輸入,格式化它,然後餵入LLM,然後解析LLM的輸出為JSON。

Memory

Memory模組維護輸入令牌序列在鏈條中的步驟或模型與外部世界的互動中。它可以動態地修改和擴充套件序列,並使用LLM的新興能力建立序列的摘要。

Agents

Agents模組允許我們建立可以與環境互動的實體。LLM作為代理的推理引擎,決定代理採取哪些行動和順序。代理可以使用特殊功能,例如API呼叫或其他鏈條。

Callbacks

Callbacks模組允許我們在LLM應用程式的各個點插入程式碼,例如日誌記錄、監控或流式傳輸。

實踐中的LangChain

讓我們使用LangChain解答一個問題:地球上最深的海洋部分和最高的山峰的海拔之和是多少?我們將使用LangChain的API包裝器、搜尋工具和計算器工具來解答這個問題。

首先,我們初始化LangChain的API包裝器,然後定義搜尋工具和計算器工具。搜尋工具使用SerpAPI進行Google搜尋,而計算器工具使用特殊的幾次學習LangChain提示範本來查詢LLM計算數學方程式。

from langchain.chat_models import ChatOpenAI
from langchain.agents.tools import Tool
from langchain import SerpAPIWrapper

model = ChatOpenAI(temperature=0)

search = Tool(
    name='Search',
    func=SerpAPIWrapper().run,
    description='Google search tool'
)

calculator = Tool(
    name='Calculator',
    func=lambda x: eval(x),
    description='Calculator tool'
)

圖表翻譯:

此圖示為LangChain的架構圖,展示了其各個模組之間的關係。Model I/O模組負責與LLM互動,Retrieval模組負責從外部資料源中檢索資料,Chains模組允許組合多個元件,Memory模組維護輸入令牌序列,Agents模組允許建立可以與環境互動的實體,Callbacks模組允許在LLM應用程式的各個點插入程式碼。

  flowchart TD
    A[Model I/O] --> B[Retrieval]
    B --> C[Chains]
    C --> D[Memory]
    D --> E[Agents]
    E --> F[Callbacks]

LangChain與LLM的應用

LangChain是一個強大的工具,能夠與大語言模型(LLM)合作,實作複雜任務的自動化。以下是使用LangChain和LLM解答問題的步驟:

初始化LLM和工具

首先,需要初始化LLM和工具,例如計算器和搜尋引擎。這些工具可以用來執行特定的任務,例如計算和搜尋。

from langchain import LLMMathChain

llm_math_chain = LLMMathChain.from_llm(
    llm=model,
    verbose=True)

calculator = Tool(
    name='Calculator',
    func=llm_math_chain.run,
    description='Calculator tool')

初始化PlanAndExecute代理

接下來,需要初始化PlanAndExecute代理。這個代理接受LLM、工具、計劃器和執行器代理作為引數。

from langchain_experimental.plan_and_execute import PlanAndExecute, load_agent_executor, load_chat_planner

agent = PlanAndExecute(
    planner=load_chat_planner(
        llm=model),
    executor=load_agent_executor(
        llm=model,
        tools=[search, calculator],
        verbose=True),
    verbose=True)

執行代理

最後,可以執行代理,傳入需要解答的問題。

agent.run('What is the sum of the elevations of the deepest section of the ocean and the highest peak on Earth? Use metric units only.')

分析結果

代理會將問題分解為子任務,然後執行這些子任務,最終得出答案。例如,代理可能會將問題分解為以下步驟:

  1. 搜尋最深海洋的深度
  2. 搜尋地球最高峰的高度
  3. 使用計算器計算這兩個值的總和

代理會執行這些步驟,最終得出答案。

內容解密:

以上程式碼展示瞭如何使用LangChain和LLM解答問題。首先,需要初始化LLM和工具,然後初始化PlanAndExecute代理,最後執行代理。代理會將問題分解為子任務,然後執行這些子任務,最終得出答案。

圖表翻譯:

以下是代理執行過程的Mermaid圖表:

  flowchart TD
    A[問題] --> B[分解為子任務]
    B --> C[執行子任務]
    C --> D[得出答案]
    D --> E[輸出答案]

這個圖表展示了代理執行過程的流程,從問題分解為子任務,到執行子任務,最終得出答案。

深度學習模型的開發和佈署

在深度學習的應用中,開發和佈署模型是一個非常重要的步驟。這個步驟不僅需要對模型進行精細的調整和最佳化,也需要考慮到模型的實用性和可擴充套件性。

LangChain 的應用

在前面的章節中,我們介紹了 LangChain 的基本概念和應用。LangChain 是一個根據大語言模型(LLM)的框架,允許使用者建立複雜的任務流程和工作流程。透過 LangChain,我們可以將複雜的任務分解為更小的子任務,並使用 LLM 來執行每個子任務。

模型開發和佈署的挑戰

在開發和佈署深度學習模型的過程中,會遇到許多挑戰。其中包括:

  • 模型複雜性:深度學習模型通常具有大量的引數和複雜的結構,使得模型的訓練和最佳化變得困難。
  • 資料品質:資料的品質對模型的效能有著重要的影響。資料中的噪音、缺失值和偏差都可能對模型的效能產生負面影響。
  • 計算資源:深度學習模型的訓練需要大量的計算資源,包括 GPU、CPU 和記憶體。
  • 模型佈署:模型的佈署需要考慮到模型的實用性、可擴充套件性和安全性。

MLOps 的應用

MLOps(Machine Learning Operations)是一個集合了機器學習和 DevOps 的方法論,旨在提高機器學習模型的開發和佈署效率。MLOps 的主要目標是自動化機器學習模型的開發、測試和佈署,從而提高模型的品質和可靠性。

MLOps 的關鍵組成部分

MLOps 的關鍵組成部分包括:

  • 資料管理:資料管理是 MLOps 的基礎,包括資料的收集、儲存、處理和分析。
  • 模型開發:模型開發是 MLOps 的核心,包括模型的設計、訓練和最佳化。
  • 模型佈署:模型佈署是 MLOps 的最終目標,包括模型的佈署、監控和維護。
  • 自動化:自動化是 MLOps 的關鍵,包括模型的自動訓練、自動最佳化和自動佈署。

MLOps 的工具和技術

MLOps 的工具和技術包括:

  • TensorFlow:TensorFlow 是一個流行的深度學習框架,提供了強大的模型開發和佈署功能。
  • PyTorch:PyTorch 是另一個流行的深度學習框架,提供了動態的模型開發和佈署功能。
  • Kubernetes:Kubernetes 是一個容器化的佈署工具,提供了強大的模型佈署和管理功能。
  • Docker:Docker 是一個容器化的佈署工具,提供了輕量級的模型佈署和管理功能。

機器學習營運(MLOps)

在本章中,我們已經探討了神經網路(NNs)的理論、各種NN架構,以及可以用它們解決的任務。本章將著重於NN開發的實際方面。NN模型(尤其是NN)的開發和生產佈署具有獨特的挑戰。這個過程可以分為三個步驟:

  1. 訓練資料集建立:資料收集、清理、儲存、轉換和特徵工程。
  2. 模型開發:實驗不同的模型和訓練演算法,並評估它們。
  3. 佈署:將訓練好的模型佈署在生產環境中,並監控其計算和準確性的表現。

這個多步驟的複雜管道預設了一些解決機器學習任務的挑戰:

  • 多樣的軟體工具包:每一步都有多個競爭工具。
  • 模型開發很困難:每個訓練例項都有大量的變數。這些變數可能是NN架構的修改、訓練超引數的變化(例如學習率或動量)或不同的訓練資料分佈。此外,NN有隨機的來源,例如權重初始化或資料增強。因此,如果我們無法重現早期的結果,很難找出原因。即使我們在程式碼中有錯誤,也可能不會導致容易被檢測到的執行時異常。相反,它可能只會稍微降低模型的準確性。因此,我們需要一個強大的追蹤和監控系統,以避免失去所有實驗的軌跡。

機器學習營運(MLOps)

在本章中,我們將涵蓋以下主要主題:

  • 瞭解模型開發
  • 探索模型佈署

技術要求 我們將使用Python、PyTorch、TensorFlow(TF)和Hugging Face(HF)Transformers等工具實作本章的例子。如果您沒有設定好這些工具的環境,不要擔心 – 示例可在Google Colab上找到作為Jupyter Notebooks。

瞭解模型開發

在本文中,我們將討論各種工具,以幫助我們管理模型開發階段的機器學習解決方案生命週期。讓我們從最重要的問題開始 – 我們應該選擇哪個NN框架?

選擇NN框架 在本章中,我們主要使用PyTorch和TensorFlow。這些框架是整個NN軟體堆積堆疊的基礎。它們作為其他ML NN生態系統元件(例如Keras或HF Transformers)的基礎,這些元件可以使用它們作為後端。另外,它們支援GPU加速的NumPy運算和Autograd。其他流行的函式庫如scikit-learn不在此書中討論,因為它們與NN無直接關係。由於基礎函式庫的重要性,它們是我們工具箱中的第一個和最重要的選擇。但是,如果我們從頭開始一個專案,應該選擇哪一個?

PyTorch與TensorFlow與JAX 讓我們檢視這些函式庫的社群採用程度。首先,我們來看看Papers with Code網站。根據該網站,PyTorch是最受歡迎的函式庫,佔比為95%。TensorFlow和JAX分別排名第二和第三,佔比為3%和2%。這種趨勢並不新鮮 – PyTorch在2016年發布,但它已經在2019年超越了TensorFlow。這個特定的資料點表明PyTorch主導了最先進的研究,因此,如果您想始終使用最新和最好的技術,堅持使用PyTorch是一個好主意。

Open Neural Network Exchange(ONNX)

ONNX是一個開源格式,允許我們將NN模型從一個函式庫轉換為另一個函式庫。它定義了一個可擴充套件的計算圖模型、內建運運算元和標準資料型別。簡單地說,ONNX提供了一種通用的NN表示格式,允許我們將用一個函式庫實作的模型(例如PyTorch)轉換為另一個函式庫(例如TensorFlow),只要源函式庫和目標函式庫都支援ONNX。這樣,我們可以用一個函式庫訓練模型,然後在佈署到生產環境時將其轉換為另一個函式庫。

ONNX將NN表示為一個計算圖的運算,節點是運算(或ONNX運運算元),而邊是輸入/輸出連線(或ONNX變數)。此外,它實作了一個Python執行時環境,用於評估ONNX模型和運算。其目的是闡明ONNX的語義,幫助瞭解和除錯ONNX工具和轉換器,但它不適合生產環境,也未針對效能進行最佳化。

import onnx
import numpy as np

# 定義一個簡單的線性迴歸模型
X = np.array([[1], [2], [3]])
A = np.array([[2]])
B = np.array([[3]])

# 建立一個ONNX模型
model = onnx.ModelProto()
model.ir_version = 6

# 定義模型的輸入和輸出
input_tensor = onnx.ValueInfoProto(
    name='X',
    type=onnx.TypeProto(
        tensor_type=onnx.TypeProto.Tensor(
            elem_type=onnx.TensorProto.DataType.FLOAT,
            shape=[-1, 1]
        )
    )
)
output_tensor = onnx.ValueInfoProto(
    name='Y',
    type=onnx.TypeProto(
        tensor_type=onnx.TypeProto.Tensor(
            elem_type=onnx.TensorProto.DataType.FLOAT,
            shape=[-1, 1]
        )
    )
)

# 定義模型的運算
node = onnx.NodeProto(
    op_type='MatMul',
    inputs=['X', 'A'],
    outputs=['Y']
)

# 將模型的運算增加到模型中
model.graph.node.append(node)

# 將模型儲存為ONNX檔案
with open('model.onnx', 'wb') as f:
    f.write(model.SerializeToString())

內容解密:

在上面的程式碼中,我們定義了一個簡單的線性迴歸模型,並使用ONNX建立了一個模型。然後,我們定義了模型的輸入和輸出,包括輸入張量X和輸出張量Y。接下來,我們定義了一個運算,將輸入張量X和權重A相乘,得到輸出張量Y。最後,我們將模型儲存為ONNX檔案。

圖表翻譯:

此圖示為ONNX模型的計算圖,顯示了輸入張量X、權重A和輸出張量Y之間的關係。

  graph LR
    X -->|MatMul|> Y
    A -->|MatMul|> Y

在這個圖中,XA是輸入,Y是輸出。MatMul運運算元代表矩陣乘法運算。這個圖表闡明瞭ONNX模型的結構和運算過程。

根據ONNX的模型開發

在這個章節中,我們將探討如何使用ONNX(Open Neural Network Exchange)來開發和佈署神經網路模型。ONNX是一個開源的格式,允許使用者將訓練好的模型從一個框架轉換到另一個框架,從而實作跨平臺和跨框架的模型佈署。

定義圖表輸入和輸出變數

首先,我們需要定義圖表的輸入和輸出變數。這可以透過使用ONNX的make_tensor_value_info函式來完成。以下是定義輸入變數X和輸出變數Y的示例程式碼:

import numpy as np
from onnx import TensorProto, numpy_helper
from onnx.helper import make_tensor_value_info

X = make_tensor_value_info(
    name='X',
    elem_type=TensorProto.FLOAT,
    shape=[None, None]
)

Y = make_tensor_value_info(
    name='Y',
    elem_type=TensorProto.FLOAT,
    shape=[None]
)

在這裡,make_tensor_value_info函式用於定義圖表的輸入和輸出變數。name引數指定變數的名稱,elem_type引數指定變數的資料型別,shape引數指定變數的形狀。

定義圖表引數

接下來,我們需要定義圖表的引數。這可以透過使用ONNX的numpy_helper函式來完成。以下是定義引數A和B的示例程式碼:

A = numpy_helper.from_array(
    np.array([0.5, -0.6], dtype=np.float32),
    name='A'
)

B = numpy_helper.from_array(
    np.array([0.4], dtype=np.float32),
    name='B'
)

在這裡,numpy_helper函式用於定義圖表的引數。from_array方法用於從NumPy陣列中建立一個ONNX張量。

定義圖表操作

最後,我們需要定義圖表的操作。這可以透過使用ONNX的make_node函式來完成。以下是定義矩陣乘法和加法操作的示例程式碼:

from onnx.helper import make_node

mat_mul = make_node(
    op_type='MatMul',
    inputs=['X', 'A'],
    outputs=['XA']
)

addition = make_node(
    op_type='Add',
    inputs=['XA', 'B'],
    outputs=['Y']
)

在這裡,make_node函式用於定義圖表的操作。op_type引數指定操作的型別,inputs引數指定操作的輸入,outputs引數指定操作的輸出。

內容解密:

在這個章節中,我們探討瞭如何使用ONNX來開發和佈署神經網路模型。ONNX是一個開源的格式,允許使用者將訓練好的模型從一個框架轉換到另一個框架,從而實作跨平臺和跨框架的模型佈署。透過使用ONNX的make_tensor_value_infonumpy_helpermake_node函式,我們可以定義圖表的輸入和輸出變數、引數和操作。

圖表翻譯:

  graph LR
    X -->|MatMul|> XA
    XA -->|Add|> Y
    A -->|MatMul|> XA
    B -->|Add|> Y

在這個圖表中,我們可以看到圖表的輸入和輸出變數、引數和操作。矩陣乘法操作用於計算X和A的乘法,然後加法操作用於計算XA和B的和。最終的輸出是Y。

ONNX 運運算元與模型建立

ONNX(Open Neural Network Exchange)是一個開源格式,允許使用者在不同的深度學習框架之間交換神經網路模型。ONNX 支援多種神經網路構建塊,包括啟用函式、卷積、池化、張量運運算元(例如 concat、pad、reshape 和 flatten)等。此外,ONNX 還支援控制流運運算元,可以建立動態計算圖。例如,if 運運算元可以根據布林值執行不同的子圖。

ONNX 運運算元的使用

ONNX 本身不實作運運算元,而是由支援 ONNX 的函式庫(如 PyTorch)實作自己的運運算元。相反,如果您的函式庫模型包含不被 ONNX 支援的運運算元,則 ONNX 轉換將失敗。

建立計算圖

現在,我們有了定義計算圖的所需成分:

from onnx.helper import make_graph

graph = make_graph(
    nodes=[mat_mul, addition],
    name='Linear regression',
    inputs=[X],
    outputs=[Y],
    initializer=[A, B]
)

我們可以看到計算圖,如下圖所示: 圖 10.1 – 線性迴歸 ONNX 計算圖

建立 ONNX 模型

使用圖來建立一個 ONNX 模型例項。模型允許您向圖增加額外的元資料,例如 docstring、版本、作者和許可證等:

from onnx.helper import make_model

onnx_model = make_model(graph)

onnx_model.doc_string = '測試模型'

onnx_model.model_version = 1

模型一致性檢查

檢查模型的一致性,以驗證輸入型別或形狀是否在模型元件之間匹配:

from onnx.checker import check_model

check_model(onnx_model)

print(onnx_model)

計算模型輸出

最後,我們可以使用 ReferenceEvaluator 例項計算模型對兩個隨機輸入樣本的輸出:

from onnx.reference import ReferenceEvaluator

sess = ReferenceEvaluator(onnx_model)

內容解密:

在這個例子中,我們使用 ONNX 建立了一個簡單的線性迴歸模型。首先,我們定義了計算圖,然後建立了 ONNX 模型例項。接下來,我們檢查模型的一致性,最後,我們計算模型對隨機輸入樣本的輸出。

圖表翻譯:

  graph TD
    A[計算圖] --> B[ONNX 模型]
    B --> C[模型一致性檢查]
    C --> D[計算模型輸出]

在這個圖表中,我們展示了 ONNX 模型的建立和計算過程。首先,我們定義計算圖,然後建立 ONNX 模型例項。接下來,我們檢查模型的一致性,最後,我們計算模型對隨機輸入樣本的輸出。

使用ONNX進行模型序列化和反序列化

ONNX(Open Neural Network Exchange)是一個開源格式,允許使用者將神經網路模型從一個框架序列化為ONNX格式,然後在另一個框架中反序列化。這使得不同框架之間的模型分享和轉換成為可能。

從技術架構視角來看,本文深入淺出地介紹了使用Transformers和LangChain進行深度學習模型開發和佈署的流程,並特別強調了ONNX在模型轉換和最佳化中的關鍵作用。藉由程式碼範例和圖表,我們清晰地理解了從資料集載入、模型訓練、評估到最終佈署的完整流程。其中,LangChain框架的應用,有效地解決了LLM應用中的上下文視窗和知識更新等限制,展現了其在構建複雜AI應用程式方面的強大潛力。ONNX的引入則有效簡化了跨平臺模型佈署的複雜性,提升了模型開發效率。然而,模型的訓練和佈署仍面臨諸多挑戰,例如模型複雜性、資料品質、計算資源限制等。對於追求高效能和跨平臺佈署的開發者而言,需要更深入地研究模型最佳化策略和MLOps最佳實務。玄貓認為,掌握這些核心技術和工具,將成為未來AI工程師的必備技能,並在推動AI技術的產業落地中扮演至關重要的角色。