SetFit 文件

SetFit 用於基於方面的情感分析

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

SetFit 用於基於方面的情感分析

SetFitABSA 是一個高效的少樣本基於方面的情感分析框架,只需少量訓練資料即可獲得具有競爭力的效能。它由三個階段組成:

  1. 使用 spaCy 查詢潛在的方面候選。
  2. 使用 SetFit 模型過濾這些方面候選。
  3. 使用 SetFit 模型對過濾後的方面候選進行分類。

本指南將向您展示如何訓練、預測、儲存和載入這些模型。

入門

首先,SetFitABSA 還需要安裝 spaCy,所以我們必須安裝它。

!pip install "setfit[absa]"
# or
# !pip install spacy

然後,我們必須下載我們打算使用的 spaCy 模型。預設情況下,SetFitABSA 使用 en_core_web_lg,但 en_core_web_smen_core_web_md 也是不錯的選擇。

!spacy download en_core_web_lg
!spacy download en_core_web_sm

訓練 SetFitABSA

首先,我們必須透過 AbsaModel.from_pretrained() 例項化一個新的 AbsaModel。這可以透過為 SetFitABSA 的三個階段中的每個階段提供配置來完成:

  1. 提供要用於方面過濾 SetFit 模型的 Sentence Transformer 模型的名稱或路徑作為第一個引數。
  2. (可選)提供要用於極性分類 SetFit 模型的 Sentence Transformer 模型的名稱或路徑作為第二個引數。如果未提供,則與方面過濾模型相同的 Sentence Transformer 模型也將用於極性分類模型。
  3. (可選)透過 spacy_model 關鍵字引數提供要使用的 spaCy 模型。

例如:

from setfit import AbsaModel

model = AbsaModel.from_pretrained(
    "sentence-transformers/all-MiniLM-L6-v2",
    "sentence-transformers/all-mpnet-base-v2",
    spacy_model="en_core_web_sm",
)

或者一個最小示例:

from setfit import AbsaModel

model = AbsaModel.from_pretrained("BAAI/bge-small-en-v1.5")

然後我們必須準備一個訓練/測試集。這些資料集必須有 "text""span""label""ordinal" 列。

  • "text":包含方面的完整句子或文字。例如:"But the staff was so horrible to us."
  • "span":來自完整句子中的一個方面。可以是多個單詞。例如:"staff"
  • "label":與方面跨度對應的(極性)標籤。例如:"negative"
  • "ordinal":如果方面跨度在文字中出現多次,則此序數表示這些出現的索引。通常這只是 0。例如:0

已經符合此格式的兩個資料集是 SemEval-2014 Task 4 的這些評論資料集:

from dataset import load_dataset

# The training/eval dataset must have `text`, `span`, `label`, and `ordinal` columns
dataset = load_dataset("tomaarsen/setfit-absa-semeval-restaurants", split="train")
train_dataset = dataset.select(range(128))
eval_dataset = dataset.select(range(128, 256))

我們可以像正常的 SetFit 一樣開始訓練,但現在使用 AbsaTrainer 代替。

如果需要,您可以透過同時使用 argspolarity_args 關鍵字引數來為方面模型和極性模型指定單獨的訓練引數。

from setfit import AbsaTrainer, TrainingArguments
from transformers import EarlyStoppingCallback

args = TrainingArguments(
    output_dir="models",
    num_epochs=5,
    use_amp=True,
    batch_size=128,
    eval_strategy="steps",
    eval_steps=50,
    save_steps=50,
    load_best_model_at_end=True,
)

trainer = AbsaTrainer(
    model,
    args=args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    callbacks=[EarlyStoppingCallback(early_stopping_patience=5)],
)
trainer.train()
***** Running training *****
  Num examples = 249
  Num epochs = 5
  Total optimization steps = 1245
  Total train batch size = 128
{'aspect_embedding_loss': 0.2542, 'learning_rate': 1.6e-07, 'epoch': 0.0}                                                                                          
{'aspect_embedding_loss': 0.2437, 'learning_rate': 8.000000000000001e-06, 'epoch': 0.2}                                                                            
{'eval_aspect_embedding_loss': 0.2511, 'learning_rate': 8.000000000000001e-06, 'epoch': 0.2}                                                                       
{'aspect_embedding_loss': 0.2209, 'learning_rate': 1.6000000000000003e-05, 'epoch': 0.4}                                                                           
{'eval_aspect_embedding_loss': 0.2385, 'learning_rate': 1.6000000000000003e-05, 'epoch': 0.4}                                                                      
{'aspect_embedding_loss': 0.0165, 'learning_rate': 1.955357142857143e-05, 'epoch': 0.6}                                                                            
{'eval_aspect_embedding_loss': 0.2776, 'learning_rate': 1.955357142857143e-05, 'epoch': 0.6}                                                                       
{'aspect_embedding_loss': 0.0158, 'learning_rate': 1.8660714285714287e-05, 'epoch': 0.8}                                                                           
{'eval_aspect_embedding_loss': 0.2848, 'learning_rate': 1.8660714285714287e-05, 'epoch': 0.8}                                                                      
{'aspect_embedding_loss': 0.0015, 'learning_rate': 1.7767857142857143e-05, 'epoch': 1.0}                                                                           
{'eval_aspect_embedding_loss': 0.3133, 'learning_rate': 1.7767857142857143e-05, 'epoch': 1.0}                                                                      
{'aspect_embedding_loss': 0.0012, 'learning_rate': 1.6875e-05, 'epoch': 1.2}                                                                                       
{'eval_aspect_embedding_loss': 0.2966, 'learning_rate': 1.6875e-05, 'epoch': 1.2}                                                                                  
{'aspect_embedding_loss': 0.0009, 'learning_rate': 1.598214285714286e-05, 'epoch': 1.41}                                                                           
{'eval_aspect_embedding_loss': 0.2996, 'learning_rate': 1.598214285714286e-05, 'epoch': 1.41}                                                                      
 28%|██████████████████████████████████▎                                                                                       | 350/1245 [03:40<09:24,  1.59it/s] 
Loading best SentenceTransformer model from step 100.
{'train_runtime': 226.7429, 'train_samples_per_second': 702.822, 'train_steps_per_second': 5.491, 'epoch': 1.41}
***** Running training *****
  Num examples = 39
  Num epochs = 5
  Total optimization steps = 195
  Total train batch size = 128
{'polarity_embedding_loss': 0.2267, 'learning_rate': 1.0000000000000002e-06, 'epoch': 0.03}                                                                        
{'polarity_embedding_loss': 0.1038, 'learning_rate': 1.6571428571428574e-05, 'epoch': 1.28}                                                                        
{'eval_polarity_embedding_loss': 0.1946, 'learning_rate': 1.6571428571428574e-05, 'epoch': 1.28}                                                                   
{'polarity_embedding_loss': 0.0116, 'learning_rate': 1.0857142857142858e-05, 'epoch': 2.56}                                                                        
{'eval_polarity_embedding_loss': 0.2364, 'learning_rate': 1.0857142857142858e-05, 'epoch': 2.56}                                                                   
{'polarity_embedding_loss': 0.0059, 'learning_rate': 5.142857142857142e-06, 'epoch': 3.85}                                                                         
{'eval_polarity_embedding_loss': 0.2401, 'learning_rate': 5.142857142857142e-06, 'epoch': 3.85}                                                                    
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 195/195 [00:54<00:00,  3.58it/s]
Loading best SentenceTransformer model from step 50.
{'train_runtime': 54.4104, 'train_samples_per_second': 458.736, 'train_steps_per_second': 3.584, 'epoch': 5.0}

評估也像正常一樣,儘管您現在可以分別從方面模型和極性模型中獲得結果。

metrics = trainer.evaluate(eval_dataset)
print(metrics)
***** Running evaluation *****
{'aspect': {'accuracy': 0.7130649876321116}, 'polarity': {'accuracy': 0.7102310231023102}}

請注意,方面準確性是指將 spaCy 模型中的方面候選跨度分類為真實方面與否的準確性,而極性準確性是指僅將過濾後的方面候選跨度分類到正確類別的準確性。

儲存 SetFitABSA 模型

訓練完成後,我們可以使用熟悉的 AbsaModel.save_pretrained()AbsaTrainer.push_to_hub()/AbsaModel.push_to_hub() 方法來儲存模型。但是,與通常不同的是,儲存 AbsaModel 涉及儲存兩個獨立的模型:方面 SetFit 模型和極性 SetFit 模型。因此,我們可以提供兩個目錄或 repo_id

model.save_pretrained(
    "models/setfit-absa-model-aspect",
    "models/setfit-absa-model-polarity",
)
# or
model.push_to_hub(
    "tomaarsen/setfit-absa-bge-small-en-v1.5-restaurants-aspect",
    "tomaarsen/setfit-absa-bge-small-en-v1.5-restaurants-polarity",
)

但是,您也可以只提供一個目錄或 repo_id,並且會自動新增 -aspect-polarity。因此,以下程式碼與之前的程式碼片段等效:

model.save_pretrained("models/setfit-absa-model")
# or
model.push_to_hub("tomaarsen/setfit-absa-bge-small-en-v1.5-restaurants")

載入 SetFitABSA 模型

載入訓練好的 AbsaModel 涉及呼叫 AbsaModel.from_pretrained(),並提供 SetFitABSA 三個階段的詳細資訊:

  1. 提供用於方面過濾模型的已訓練 SetFit ABSA 模型的名稱或路徑作為第一個引數。
  2. 提供用於極性分類模型的已訓練 SetFit ABSA 模型的名稱或路徑作為第二個引數。
  3. (可選)透過 spacy_model 關鍵字引數提供要使用的 spaCy 模型。建議使其與訓練期間使用的模型匹配。預設值為 "en_core_web_lg"

例如:

from setfit import AbsaModel

model = AbsaModel.from_pretrained(
    "tomaarsen/setfit-absa-bge-small-en-v1.5-restaurants-aspect",
    "tomaarsen/setfit-absa-bge-small-en-v1.5-restaurants-polarity",
    spacy_model="en_core_web_lg",
)

我們現在已成功從以下位置載入了 SetFitABSA 模型:

使用 SetFitABSA 模型進行推理

要使用訓練好的 AbsaModel 執行推理,我們可以使用 AbsaModel.predict()

preds = model.predict([
    "Best pizza outside of Italy and really tasty.",
    "The food variations are great and the prices are absolutely fair.",
    "Unfortunately, you have to expect some waiting time and get a note with a waiting number if it should be very full."
])
print(preds)
# [
#     [{'span': 'pizza', 'polarity': 'positive'}],
#     [{'span': 'food variations', 'polarity': 'positive'}, {'span': 'prices', 'polarity': 'positive'}],
#     [{'span': 'waiting number', 'polarity': 'negative'}]
# ]

挑戰

如果你願意,我挑戰你根據此文件訓練並上傳一個用於筆記型電腦評論的 SetFitABSA 模型。

< > 在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.