返回文章列表

預訓練生成模型生產環境佈署與評估

本文探討如何將預訓練生成模型佈署到生產環境,並使用LangChain簡化不同模型的評估流程。文章涵蓋了GPU環境設定、模型載入、測試資料準備,以及使用BLEU、ROUGE、METEOR和CLIP等指標進行量化評估,比較GPT-3和GPT-Neo模型在詞彙相似度、

機器學習 Web 開發

隨著模型規模增長,記憶體需求和計算資源的消耗也隨之增加,這對StyleSprint專案的預算和硬體提出了挑戰。大型模型需要專用硬體如GPU或TPU,並可能需要分散式佈署或分段載入,增加佈署和操作的複雜性。因此,需要仔細評估模型大小、計算複雜度與生成描述的品質之間的權衡。StyleSprint追求近乎即時的回應速度,但同時需要高品質的描述,這需要在模型大小和效能之間找到平衡點。透過基準測試,我們可以比較不同大小和複雜度模型的效能,並根據詞彙和語義相似度以及人工評估等指標,選擇最適合專案需求的模型。在更新後的原型環境中,我們將使用LangChain載入多個模型,並使用GPU加速計算,以評估模型在不同指標下的表現。

從原型到生產環境:應用預訓練生成模型

在開發StyleSprint專案的過程中,模型的計算複雜度和引數數量對專案的預算和硬體需求有著直接的影響。每個模型引數都是一個變數,在計算過程中(包括訓練和推理)都需要被儲存在記憶體中。以下是一些與計算需求相關的具體考慮:

記憶體和儲存需求

模型的記憶體總大小是引數數量和每個引數大小(通常是32位或64位浮點數)的乘積。例如,一個擁有1億個引數的模型,如果每個引數用32位浮點數表示,那麼它大約需要400 MB的記憶體(1億 * 32位 = 4億位 = 400 MB)。而對於一個擁有100億個引數的大型模型來說,記憶體需求將躍升至40 GB(100億 * 32位 = 400億位 = 40 GB)。這還僅僅是引數的記憶體需求,並不包括模型執行所需的其他資料和開銷。

載入記憶體

當模型用於推理時,其引數必須被載入執行機器上的RAM中。對於擁有100億個引數的大型模型,需要一台具有足夠RAM來容納整個模型的機器,同時還需要額外的記憶體來處理操作開銷、輸入資料和生成的輸出。如果模型太大,無法放入記憶體,可能需要將其分割或分佈在多台機器上,或分段載入,這會顯著增加模型的佈署和操作複雜度,並提高生成輸出的延遲。

專用硬體需求

更大的模型需要專用硬體,如強大的GPU或TPU,這可能會增加專案成本。如前所述,具有大量引數的模型需要強大的計算資源來進行訓練和推理。通常採用GPU和TPU等硬體加速器來滿足這些需求。這些硬體加速器旨在處理神經網路計算中固有的矩陣乘法和其他操作的平行計算能力,從而相比傳統的中央處理器(CPU)顯著加快處理速度。

雲端基礎設施可以減輕設定的複雜性,但通常採用根據使用的定價。瞭解基礎設施成本的細粒度對於確保StyleSprint保持在預算內至關重要。

延遲

我們已經簡要討論了延遲,但需要重申的是,更大的模型通常具有更高的延遲,這對於需要即時回應的應用程式來說可能是個問題。在我們的案例中,可以非同步地批次處理描述。然而,StyleSprint可能有一些專案需要快速完成,這需要在幾個小時內完成批次處理,而不是幾天。

更新原型環境

在StyleSprint的案例中,必須仔細評估模型效能和大小之間的權衡,以確保最終的模型在滿足專案效能要求的同時,保持在預算和硬體限制之內。StyleSprint希望實作近乎即時的回應,以提供個人化的描述,這通常意味著使用計算複雜度較低的較小模型。然而,保持模型的高準確性和與品牌標準的語氣和聲音一致性也非常重要,這可能需要一個更大、更精細的模型,或在更大的資料集上進行訓練或微調。實際上,我們可以透過基準測試來評估不同大小和複雜度的模型的效能。

基準測試

基準測試是一種系統性的過程,用於根據預定義的標準評估不同生成模型的效能。這個過程涉及比較不同模型在各種指標上的表現,以瞭解它們的優缺點以及對專案的適用性。這是一種根據觀察的經驗方法,可以獲得模型在相似條件下的效能資料,為模型選擇的決策過程提供參考。

GPU組態

為了獲得更好的效能,請確保啟用GPU。在Google Colab中,可以按照以下步驟啟用GPU加速:

  1. 點選頂部選單中的“Runtime”(執行時)(見圖4.2)。
  2. 從下拉選單中選擇“Change runtime type”(更改執行時型別),如前面的截圖所示。
  3. 在彈出的視窗中,從“Hardware accelerator”(硬體加速器)下拉選單中選擇“GPU”(見圖4.3)。
# 示例程式碼:檢查GPU是否可用
import torch
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")

內容解密:

這段程式碼檢查系統中是否有可用的GPU,並將其設定為PyTorch的預設裝置。如果GPU可用,則使用GPU(“cuda”),否則使用CPU。這是確保深度學習任務能夠利用GPU加速的重要步驟。

在StyleSprint案例中,基準測試可以是一種寶貴的練習,用於權衡模型大小、計算複雜度和生成的描述的準確性和創造力之間的關係。我們的基準測試練習可以回到Google Colab原型環境,快速載入各種生成模型,並透過測試來評估它們的效能,包括計算效率和文字生成品質。一旦我們完成了評估和比較,就可以對我們的生產應用程式碼進行一些簡單的更改,它將自動重新佈署。

基準測試將有助於衡量描述的品質與模型大小和複雜度之間的關係。回想一下,我們將根據幾個維度來衡量品質和整體模型效能,包括與“黃金標準”(即人工撰寫的描述)的詞彙和語義相似性,以及由多元化評審小組進行的定性評估。

下一步是重新審視和調整我們的原始原型程式碼,以包含一些競爭者模型並應用評估指標。為了進行評估,我們需要對原始的Google Colab實驗設定進行一些關鍵更改。首先,我們將確保利用效能加速。Google Colab提供了透過GPU或TPU環境進行加速的功能。在這個實驗中,我們將利用GPU。此外,我們還希望從Transformers函式庫轉移到稍微更通用的函式庫,如Langchain,它允許我們測試開源模型(如GPT-Neo)和商業模型(如GPT-3.5)。

更新原型開發環境與準備基準測試資料

在進行生成式模型的基準測試時,適當的硬體組態和環境設定至關重要。本章節將詳細介紹如何設定使用GPU的開發環境、如何使用LangChain載入預訓練模型,以及如何準備測試資料以進行模型評估。

設定GPU加速環境

為了顯著提升計算效能,我們需要在Colab環境中啟用GPU支援。以下是具體步驟:

  1. 進入Colab筆記本的「Runtime」選單,選擇「Change runtime type」。
  2. 在彈出的對話方塊中,選擇GPU作為硬體加速器。
  3. 點選「Save」以儲存更改。

驗證GPU可用性

# 驗證GPU是否可用
import torch
print(torch.cuda.is_available())

此程式碼段將傳回True如果GPU可用,否則傳回False。確保GPU可用對於後續的大規模模型評估至關重要。

內容解密:

  • import torch:匯入PyTorch函式庫,這是一個廣泛用於深度學習的函式庫。
  • torch.cuda.is_available():檢查當前環境是否支援GPU運算。

使用LangChain載入預訓練模型

LangChain提供了一個簡化不同生成式模型之間介面的函式庫,使得比較不同模型的任務變得更加容易。以下是使用LangChain載入模型的步驟:

  1. 安裝必要的函式庫:在Colab環境中安裝openailangchainhuggingface_hub

    !pip -q install openai langchain huggingface_hub
    
  2. 設定API金鑰:取得OpenAI和Hugging Face的API金鑰,並將其安全地儲存在環境變數中。

    import os
    os.environ['OPENAI_API_KEY'] = 'your_openai_api_key_here'
    os.environ['HUGGINGFACEHUB_API_TOKEN'] = 'your_huggingface_token_here'
    
  3. 載入模型:使用LangChain載入GPT-3和GPT-Neo模型。

    from langchain.llms import OpenAI, HuggingFaceHub
    
    # 載入GPT-3
    llm_gpt3 = OpenAI(model_name='text-davinci-003', temperature=0.9, max_tokens=256)
    
    # 從Hugging Face載入GPT-Neo
    llm_neo = HuggingFaceHub(repo_id='EleutherAI/gpt-neo-2.7B', model_kwargs={"temperature": 0.9})
    

內容解密:

  • OpenAIHuggingFaceHub類別用於例項化不同的語言模型。
  • model_namerepo_id引數用於指定要使用的特定模型版本。
  • temperature引數控制生成文字的多樣性。

準備測試資料

測試資料的準備對於評估生成式模型的效能至關重要。我們需要收集產品屬性資料和現有的產品描述,並將其格式化以便輸入到模型中。

import pandas as pd

# 載入產品資料
product_data = pd.read_csv('product_data.csv')

# 將資料分割為測試集和參考集
test_data = product_data.sample(frac=0.2, random_state=42)
reference_data = product_data.drop(test_data.index)

# 儲存測試和參考資料
test_data.to_csv('test_data.csv', index=False)
reference_data.to_csv('reference_data.csv', index=False)

# 提取參考描述和產品圖片路徑
reference_descriptions = reference_data['product_description'].tolist()
product_images = reference_data['product_image'].tolist()

# 格式化輸入資料
model_input_data = reference_data['product_metadata'].tolist()

內容解密:

  • 使用pandas函式庫讀取CSV檔案中的產品資料。
  • 將資料隨機分割為測試集和參考集,以評估模型的效能。
  • 提取參考描述和產品圖片路徑,用於後續的模型評估。

透過上述步驟,我們完成了原型開發環境的更新、預訓練模型的載入,以及測試資料的準備。這些工作為進行生成式模型的基準測試奠定了基礎。

應用預訓練生成模型:從原型到生產環境的評估

匯入必要的函式庫與生成產品描述

首先,我們使用Langchain來載入多個模型並準備測試資料,接著對生成的產品描述進行評估。

from langchain import LLMChain, PromptTemplate
from tqdm.auto import tqdm

template = """
為以下產品撰寫創意的產品描述:
{product_metadata}
"""
PROMPT = PromptTemplate(template=template, input_variables=["product_metadata"])

def generate_descriptions(llm: object, prompt: PromptTemplate = PROMPT) -> list:
    # 初始化LLM鏈
    llm_chain = LLMChain(prompt=prompt, llm=llm)
    descriptions = []
    for i in tqdm(range(len(model_input_data))):
        description = llm_chain.run(model_input_data[i])
        descriptions.append(description)
    return descriptions

gpt3_descriptions = generate_descriptions(llm_gpt3)
gptneo_descriptions = generate_descriptions(llm_neo)

內容解密:

  • 使用Langchain的LLMChainPromptTemplate來生成產品描述。
  • generate_descriptions函式接受一個語言模型和一個提示範本,傳回生成的描述列表。
  • 我們為GPT-3和GPT-Neo模型分別生成了產品描述。

量化評估指標

為了評估生成的產品描述與人類撰寫的描述之間的相似度,我們使用了詞彙相似度和語義相似度兩類別指標。

!pip install rouge sumeval nltk
import nltk
nltk.download('wordnet')
from nltk.translate.bleu_score import sentence_bleu
from rouge import Rouge
from sumeval.metrics.rouge import RougeCalculator
from nltk.translate.meteor_score import meteor_score

def evaluate(reference_descriptions: list, generated_descriptions: list) -> tuple:
    # 計算BLEU分數
    bleu_scores = [sentence_bleu([ref], gen) for ref, gen in zip(reference_descriptions, generated_descriptions)]
    average_bleu = sum(bleu_scores) / len(bleu_scores)
    
    # 計算ROUGE分數
    rouge = RougeCalculator()
    rouge_scores = [rouge.rouge_n(gen, ref, 2) for ref, gen in zip(reference_descriptions, generated_descriptions)]
    average_rouge = sum(rouge_scores) / len(rouge_scores)
    
    # 計算METEOR分數
    meteor_scores = [meteor_score([ref.split()], gen.split()) for ref, gen in zip(reference_descriptions, generated_descriptions)]
    average_meteor = sum(meteor_scores) / len(meteor_scores)
    
    return average_bleu, average_rouge, average_meteor

average_bleu_gpt3, average_rouge_gpt3, average_meteor_gpt3 = evaluate(reference_descriptions, gpt3_descriptions)
print(average_bleu_gpt3, average_rouge_gpt3, average_meteor_gpt3)

average_bleu_neo, average_rouge_neo, average_meteor_neo = evaluate(reference_descriptions, gptneo_descriptions)
print(average_bleu_neo, average_rouge_neo, average_meteor_neo)

內容解密:

  • 使用BLEU、ROUGE和METEOR指標來評估詞彙相似度。
  • evaluate函式計算生成的描述與參考描述之間的平均BLEU、ROUGE和METEOR分數。
  • 這些指標幫助我們瞭解生成的描述在詞彙層面與人類撰寫的描述的相似程度。

語義相似度評估

我們使用句子嵌入(sentence embeddings)來評估生成的描述與參考描述之間的語義相似度。

!pip install sentence-transformers
from sentence_transformers import SentenceTransformer, util

model = SentenceTransformer('paraphrase-MiniLM-L6-v2')

def cosine_similarity(reference_descriptions, generated_descriptions):
    # 計算生成的描述的餘弦相似度
    cosine_scores = [util.pytorch_cos_sim(model.encode(ref), model.encode(gen)) for ref, gen in zip(reference_descriptions, generated_descriptions)]
    average_cosine = sum(cosine_scores) / len(cosine_scores)
    return average_cosine

average_cosine_gpt3 = cosine_similarity(reference_descriptions, gpt3_descriptions)
print(average_cosine_gpt3)

average_cosine_neo = cosine_similarity(reference_descriptions, gptneo_descriptions)
print(average_cosine_neo)

內容解密:

  • 使用句子嵌入模型來計算生成的描述與參考描述之間的餘弦相似度。
  • cosine_similarity函式傳回生成的描述與參考描述之間的平均餘弦相似度。
  • 這幫助我們瞭解生成的描述在語義層面與人類撰寫的描述的相似程度。

與CLIP模型的對齊評估

我們使用CLIP模型來評估生成的產品描述與對應圖片之間的對齊程度。

clip_model = "openai/clip-vit-base-patch32"

def clip_scores(images, descriptions, model=clip_model, processor=clip_processor):
    scores = []
    # 處理所有圖片和描述
    inputs = process_inputs(processor, descriptions, images)
    # 取得模型輸出
    outputs = model(**inputs)
    logits_per_image = outputs.logits_per_image  # 影像到文字的logits
    
    # 對角線上的值給出了每個影像-描述對的得分
    for i in range(logits_per_image.size(0)):
        score = logits_per_image[i, i].item()
        scores.append(score)
    return scores

reference_images = [load_image_from_path(image_path) for image_path in reference_data.product_image_path]
gpt3_generated_scores = clip_scores(reference_images, gpt3_descriptions)
reference_scores = clip_scores(reference_images, reference_descriptions)

# 比較得分
for i, (gen_score, ref_score) in enumerate(zip(gpt3_generated_scores, reference_scores)):
    print(f"圖片 {i}: 生成得分 = {gen_score:.2f}, 參考得分 = {ref_score:.2f}")

內容解密:

  • 使用CLIP模型來評估生成的描述與對應圖片之間的對齊程度。
  • clip_scores函式計算每個影像-描述對的CLIP得分。
  • 這些得分幫助我們瞭解生成的描述與圖片的對齊程度。

結果解釋

詞彙相似度

模型BLEUROUGEMETEOR
GPT-3.50.1470.0940.261
GPT-Neo0.1320.050.059

從表中可以看出,GPT-3.5在所有詞彙相似度指標上都優於GPT-Neo,表明其生成的描述在詞彙層面更接近人類撰寫的描述。