今天來試Zero-Shot Classification,它的厲害之處在於,它不需要額外訓練,就能直接幫文字分到指定的類別。
舉例來說,在醫院或護理系統裡的AI客服,病人可能會輸入各種問題:
「我要怎麼預約掛號?」
「這個藥要飯前還是飯後吃?」
「我現在有點頭暈,該怎麼辦?」
這些問題的主題都不一樣,但如果透過Zero-Shot Classification,就可以即時幫它們歸類:
行政相關(掛號、病房探視時間)
用藥資訊(服藥方法、副作用)
臨床症狀(需要醫護評估的情況)
這樣一來,AI客服就能先做初步的分流:簡單的問題直接回覆,複雜或危險的情況則立刻轉給真人護理師處理。
實際操作
使用zero-shot-classification pipeline在Colab輸入程式碼
from transformers import pipeline
classifier = pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
# 病人常見問題
questions = [
"我要怎麼預約掛號?",
"這個藥要飯前還是飯後吃?",
"我現在有點頭暈,該怎麼辦?"
]
# 我預設的類別
labels = ["行政相關", "用藥資訊", "臨床症狀"]
# 逐一分類
for q in questions:
result = classifier(q, candidate_labels=labels)
print(f"問題:{q}")
print("分類結果:", result["labels"][0], "\n")
得出的結果為
這邊發現一個很嚴重的問題,所有問題都被分到同一個類別,完全沒有分流的效果。
後來仔細查了一下,才發現問題出在模型上。我當時使用的facebook/bart-large-mnli 是英文專用的NLI模型,拿來做中文分類時,模型其實看不懂中文內容,加上預設的假設模板(This example is {})是英文,等於要模型用英文邏輯判斷中文標籤,難怪會亂掉。
對於這個錯誤,有兩種改正方式:
from transformers import pipeline
classifier = pipeline(
"zero-shot-classification",
model="joeddav/xlm-roberta-large-xnli" # 多語模型
)
questions = [
"我要怎麼預約掛號?",
"這個藥要飯前還是飯後吃?",
"我現在有點頭暈,該怎麼辦?"
]
labels = ["行政相關", "用藥資訊", "臨床症狀"]
template = "這句話的主題是 {}。"
for q in questions:
result = classifier(q, candidate_labels=labels,
hypothesis_template=template,
multi_label=False)
print(f"問題:{q}")
print("分類結果:", result["labels"][0], "\n")
得出的結果如圖所示,雖然不像第一次跑的程式碼完全沒有分類。但發現第一個問題「我要怎麼預約掛號?」被錯誤分類到臨床症狀。會出現這個情況的原因可能是,一開始的標籤只有三個名詞(行政相關/用藥資訊/臨床症狀),語意太抽象;模型看到問句或帶有「怎麼辦」這類求助語氣時,容易被「臨床症狀」這個詞吸走。這部分未來還可以再精進。
from transformers import pipeline
classifier = pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
questions = [
"How can I make an appointment?",
"Should I take this medicine before or after meals?",
"I'm feeling dizzy now. What should I do?"
]
labels = ["administrative", "medication", "clinical symptom"]
template = "The topic of this sentence is {}."
for q in questions:
result = classifier(q, candidate_labels=labels,
hypothesis_template=template,
multi_label=False)
print(f"Question: {q}")
print("Predicted:", result["labels"][0], "\n")
發現這個方法更加穩定和正確。但對於在台灣使用的系統不可能全部都是英文,因此針對今天的文字分類功能,我還有需要學習的地方。