Machine Learning Academy · บทเรียน

การประเมินและการอนุมาน: จากลอจิตสู่ป้ายกำกับที่ทำนาย

ผู้เรียนจะคำนวณ softmax บนลอจิต ถอดรหัสดัชนีคลาสที่ทำนายเป็นป้ายกำกับ และประเมินแบบจำลองที่ปรับแต่งแล้วด้วยความแม่นยำและ F1 บนชุดทดสอบที่กันไว้

บทเรียน 4 จาก 413 ขั้นตอน

การประเมินและการอนุมาน: จากลอจิตสู่ป้ายกำกับที่ทำนาย เป็นบทเรียน Machine Learning Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Machine Learning Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Machine Learning Academy มีบทเรียนทั้งหมด 4 บทเรียน

โลจิตคืออะไร

ผลลัพธ์จากชั้นเชิงเส้นสุดท้ายของโมเดลจำแนกประเภทเรียกว่า โลจิต ซึ่งเป็นคะแนนดิบที่ยังไม่ปรับให้เป็นมาตรฐานสำหรับแต่ละคลาส สำหรับปัญหาแบบ 2 คลาส (ลบ/บวก) เวกเตอร์โลจิตอาจเป็น [-1.2, 3.5] ซึ่งหมายความว่าโมเดลให้น้ำหนักกับคลาส 1 (บวก) อย่างมาก โลจิตสามารถเป็นจำนวนจริงใดก็ได้ และไม่ใช่ค่าความน่าจะเป็น เราจึงต้องมีขั้นตอนเพิ่มเติม (ซอฟต์แมกซ์หรือซิกมอยด์) เพื่อแปลงเป็นค่าความน่าจะเป็นที่ตีความได้และมีผลรวมเป็น 1

import torch
import torch.nn.functional as F

# Example logits for 2-class problem (batch of 3)
logits = torch.tensor([[-1.2, 3.5], [2.1, -0.3], [0.4, 0.6]])
print('Logits:\n', logits)

# Convert to probabilities with softmax
probs = F.softmax(logits, dim=1)
print('Probabilities:\n', probs)
# Each row sums to 1
print('Row sums:', probs.sum(dim=1))

ซอฟต์แมกซ์: การแปลงโลจิตเป็นค่าความน่าจะเป็น

ฟังก์ชัน softmax จะแปลงเวกเตอร์โลจิตที่เป็นจำนวนจริงให้เป็นการแจกแจงความน่าจะเป็น สำหรับคลาส i: softmax(z_i) = exp(z_i) / sum(exp(z_j)) ฟังก์ชันเอ็กซ์โพเนนเชียลจะขยายความแตกต่าง ดังนั้นความแตกต่างของโลจิต 2 จะทำให้คลาสหนึ่งมีความน่าจะเป็นมากกว่าอีกคลาสประมาณ 7 เท่า ซอฟต์แมกซ์ใช้กับการจำแนกประเภทแบบ หลายคลาส ซึ่งมีคลาสที่ถูกต้องได้เพียงคลาสเดียว

import torch
import torch.nn.functional as F
import numpy as np

logits = torch.tensor([1.0, 3.0, 0.5])  # 3 classes
probs = F.softmax(logits, dim=0)
print('Class probabilities:', probs.numpy().round(4))
# [0.0900, 0.6652, 0.2449] -- class 1 is most likely
print('Sum:', probs.sum().item())  # 1.0

# argmax gives the predicted class index
pred_class = torch.argmax(probs).item()
print('Predicted class:', pred_class)  # 1

argmax: การดึงป้ายกำกับที่ทำนาย

เมื่อมีเวกเตอร์โลจิตสำหรับตัวอย่างหนึ่งกลุ่มแล้ว torch.argmax(logits, dim=1) จะคืนค่าดัชนีของคลาสที่มีคะแนนสูงสุดสำหรับแต่ละตัวอย่าง นี่คือ ป้ายกำกับคลาสที่ทำนาย สำหรับ BERT ที่ปรับแต่งด้วย num_labels=2 ผลลัพธ์จะเป็น 0 (ลบ) หรือ 1 (บวก) เราไม่จำเป็นต้องใช้ซอฟต์แมกซ์ก่อน argmax เพราะซอฟต์แมกซ์เป็นฟังก์ชันเพิ่มตามลำดับ ดังนั้นโลจิตที่มากที่สุดจะแปลงเป็นค่าความน่าจะเป็นที่มากที่สุดเสมอ

import torch

# Logits from model output for a batch of 4 examples
logits = torch.tensor([
    [-2.1,  3.4],  # strongly positive
    [ 1.8, -0.5],  # negative
    [ 0.1,  0.2],  # uncertain, leans positive
    [-3.0, -1.0]   # both negative, less-negative wins
])

predictions = torch.argmax(logits, dim=1)
print('Predictions:', predictions.tolist())  # [1, 0, 1, 1]

labels = {'0': 'negative', '1': 'positive'}
for pred in predictions.tolist():
    print(labels[str(pred)])

การถอดรหัสดัชนีที่ทำนายเป็นชื่อคลาส

ผลลัพธ์ของโมเดลเป็นดัชนีจำนวนเต็ม ในระบบจริง คุณควรเก็บการจับคู่ระหว่างดัชนีกับป้ายกำกับที่มนุษย์อ่านเข้าใจได้ไว้ อาจจัดเก็บเป็นรายการหรือพจนานุกรม แล้วใช้จำนวนเต็มที่ทำนายเป็นดัชนี สำหรับ BERT ที่ปรับแต่งด้วย IMDB การจับคู่คือ {0: 'NEGATIVE', 1: 'POSITIVE'} สำหรับงานหลายคลาส เช่น การจำแนกหัวข้อ การจับคู่อาจมี 20 รายการขึ้นไป

import torch
from transformers import BertForSequenceClassification, BertTokenizer

# Assume model and tokenizer are already loaded and fine-tuned
id2label = {0: 'NEGATIVE', 1: 'POSITIVE'}

def predict(text, model, tokenizer, device):
    model.eval()
    inputs = tokenizer(text, return_tensors='pt',
                       truncation=True, max_length=256)
    inputs = {k: v.to(device) for k, v in inputs.items()}
    with torch.no_grad():
        logits = model(**inputs).logits
    pred_id = torch.argmax(logits, dim=1).item()
    return id2label[pred_id]

# result = predict('This film was absolutely wonderful!', model, tokenizer, device)
# print(result)  # POSITIVE

คะแนนความมั่นใจจากค่าความน่าจะเป็น

การคืนเฉพาะป้ายกำกับที่ทำนายมักไม่เพียงพอสำหรับการใช้งานจริง คะแนนความมั่นใจ (ค่าความน่าจะเป็นของคลาสที่ทำนาย) จะบอกผู้ใช้ว่าโมเดลมั่นใจเพียงใด การทำนายเป็น POSITIVE ด้วยความมั่นใจ 99% แตกต่างอย่างมากจากการทำนายด้วยความมั่นใจ 52% การส่งต่อผลการทำนายที่มีความมั่นใจต่ำให้มนุษย์ตรวจสอบเป็นแนวปฏิบัติทั่วไปในระบบจริงที่ใช้จัดการการตัดสินใจสำคัญ

import torch
import torch.nn.functional as F

def predict_with_confidence(text, model, tokenizer, device):
    model.eval()
    id2label = {0: 'NEGATIVE', 1: 'POSITIVE'}
    inputs = tokenizer(text, return_tensors='pt',
                       truncation=True, max_length=256)
    inputs = {k: v.to(device) for k, v in inputs.items()}
    with torch.no_grad():
        logits = model(**inputs).logits
    probs = F.softmax(logits, dim=1).squeeze()
    pred_id = torch.argmax(probs).item()
    confidence = probs[pred_id].item()
    return id2label[pred_id], round(confidence, 4)

# label, conf = predict_with_confidence('Terrible movie.', model, tokenizer, device)
# print(label, conf)  # NEGATIVE 0.9732

การประเมินด้วยความแม่นยำและ F1

หลังรวบรวมผลการทำนายจากชุดทดสอบทั้งหมดแล้ว ให้คำนวณตัวชี้วัดมาตรฐานด้วย scikit-learn ความแม่นยำ คือสัดส่วนของผลการทำนายที่ถูกต้อง เหมาะสำหรับกรณีที่คลาสมีสัดส่วนสมดุล คะแนน F1 คือค่าเฉลี่ยฮาร์มอนิกของความเที่ยงและการเรียกคืน ซึ่งสำคัญเมื่อคลาสหนึ่ง (เช่น รีวิวเชิงบวก) มีความสำคัญมากกว่า หรือเมื่อคลาสมีสัดส่วนไม่สมดุล classification_report จะแสดงตัวชี้วัดทั้งหมดในตารางเดียวที่อ่านง่าย

from sklearn.metrics import classification_report, accuracy_score
import torch

all_preds, all_labels = [], []

model.eval()
with torch.no_grad():
    for batch in test_loader:
        outputs = model(
            input_ids=batch['input_ids'].to(device),
            attention_mask=batch['attention_mask'].to(device)
        )
        preds = torch.argmax(outputs.logits, dim=1).cpu().numpy()
        all_preds.extend(preds)
        all_labels.extend(batch['label'].numpy())

print('Accuracy:', accuracy_score(all_labels, all_preds))
print(classification_report(all_labels, all_preds,
      target_names=['NEGATIVE', 'POSITIVE']))

เมทริกซ์ความสับสนสำหรับ BERT

เมทริกซ์ความสับสน แสดงรายละเอียดของผลการทำนายเทียบกับป้ายกำกับจริง สำหรับการวิเคราะห์ความรู้สึก ช่องนอกแนวทแยงจะแสดงผลบวกลวง (ทำนายเป็น POSITIVE แต่จริง ๆ เป็น NEGATIVE) และผลลบลวง (ทำนายเป็น NEGATIVE แต่จริง ๆ เป็น POSITIVE) การแสดงภาพด้วยแผนที่ความร้อนของ seaborn ช่วยเผยให้เห็นข้อผิดพลาดที่เกิดเป็นรูปแบบ เช่น โมเดลทำนายคลาสใดคลาสหนึ่งมากเกินไปหรือไม่ หรือรีวิวบางประเภทถูกจำแนกผิดอย่างต่อเนื่องหรือไม่

from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

cm = confusion_matrix(all_labels, all_preds)

plt.figure(figsize=(6, 5))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
            xticklabels=['NEG', 'POS'],
            yticklabels=['NEG', 'POS'])
plt.ylabel('True Label')
plt.xlabel('Predicted Label')
plt.title('BERT Confusion Matrix on IMDB Test Set')
plt.tight_layout()
plt.savefig('bert_confusion.png')

การอนุมานเป็นกลุ่มเพื่อประสิทธิภาพ

การอนุมานทีละตัวอย่างทำได้ช้า ควรประมวลผลตัวอย่างเป็นกลุ่มเพื่อใช้ประโยชน์จากการประมวลผลแบบขนานของ GPU กำหนด batch_size คงที่ใน DataLoader ส่งข้อมูลทั้งกลุ่มผ่านโมเดล แล้วรวบรวมผลลัพธ์ บน GPU การอนุมานเป็นกลุ่มอาจเร็วกว่าแบบทีละตัวอย่างถึง 50 เท่า ใช้ torch.no_grad() และย้ายเทนเซอร์ไปยังอุปกรณ์ที่ถูกต้องเพื่อประสิทธิภาพสูงสุด

import torch
from torch.utils.data import DataLoader, TensorDataset
from transformers import BertTokenizer

def batch_predict(texts, model, tokenizer, device, batch_size=32):
    model.eval()
    all_predictions = []
    for i in range(0, len(texts), batch_size):
        batch_texts = texts[i:i+batch_size]
        enc = tokenizer(batch_texts, truncation=True, padding=True,
                        max_length=256, return_tensors='pt')
        enc = {k: v.to(device) for k, v in enc.items()}
        with torch.no_grad():
            logits = model(**enc).logits
        preds = torch.argmax(logits, dim=1).cpu().tolist()
        all_predictions.extend(preds)
    return all_predictions

ซิกมอยด์สำหรับการจำแนกหลายป้ายกำกับ

เมื่อข้อความหนึ่งสามารถอยู่ใน หลายคลาสพร้อมกัน (เช่น รีวิวที่ทั้ง “ตลก” และ “สะเทือนอารมณ์”) ให้ใช้ sigmoid แทน softmax ซิกมอยด์จะทำงานแยกกันกับโลจิตของแต่ละคลาส และสร้างค่าความน่าจะเป็นระหว่าง 0 ถึง 1 สำหรับแต่ละคลาส โดยผลรวมไม่จำเป็นต้องเป็น 1 ใช้ค่าขีดแบ่ง (โดยทั่วไปคือ 0.5) กับค่าความน่าจะเป็นแต่ละค่าเพื่อสร้างผลการทำนายแบบไบนารีสำหรับแต่ละคลาส กำหนด problem_type='multi_label_classification' ใน BertForSequenceClassification

import torch
import torch.nn.functional as F

# 5 classes, multi-label: a text can have multiple labels
logits = torch.tensor([[1.2, -0.5, 2.1, -1.8, 0.3]])
probs = torch.sigmoid(logits)
print('Per-class probabilities:', probs)

threshold = 0.5
predicted_labels = (probs > threshold).int()
print('Predicted labels (multi-hot):', predicted_labels)
# e.g., [1, 0, 1, 0, 0] -- classes 0 and 2 are predicted

การจัดการตัวอย่างที่จำแนกผิด

ควรตรวจสอบตัวอย่างที่จำแนกผิดด้วยตนเองเสมอ แสดงตัวอย่างที่โมเดลทำนายเป็น 0 แต่ป้ายกำกับจริงเป็น 1 (ผลลบลวง) และในทางกลับกัน รูปแบบที่พบบ่อย ได้แก่ การประชดประชัน (“ช่างเป็นหายนะของภาพยนตร์ที่ยอดเยี่ยมจริง ๆ”), การเปลี่ยนแปลงของขอบเขตข้อมูล (การใช้คำศัพท์แบบโบราณ) หรือ รีวิวยาว ที่โมเดลเห็นเพียง 256 โทเค็นแรก การทำความเข้าใจรูปแบบความล้มเหลวช่วยชี้แนวทางการสร้างคุณลักษณะหรือการรวบรวมข้อมูล

import numpy as np

all_preds = np.array(all_preds)
all_labels = np.array(all_labels)
texts = test_dataset['text'] if hasattr(test_dataset, '__getitem__') else []

false_negatives = np.where((all_preds == 0) & (all_labels == 1))[0]
false_positives = np.where((all_preds == 1) & (all_labels == 0))[0]

print('False negatives (predicted NEG, true POS):')
for idx in false_negatives[:3]:
    print(' -', str(texts[idx])[:120] if texts else idx)

print('False positives (predicted POS, true NEG):')
for idx in false_positives[:3]:
    print(' -', str(texts[idx])[:120] if texts else idx)

การส่งออกผลการทำนายเป็น CSV

ในการใช้งานจริงหรือการแข่งขัน คุณมักต้องส่งออกผลการทำนายเป็นไฟล์ CSV ใช้ pandas สร้าง DataFrame ที่มีข้อความต้นฉบับ ป้ายกำกับจริง ป้ายกำกับที่ทำนาย และคะแนนความมั่นใจ รูปแบบนี้สะดวกต่อการแบ่งปันกับผู้เกี่ยวข้อง การตรวจสอบ และการใช้เป็นข้อมูลเข้าสำหรับกระบวนการรายงานขั้นต่อไป ควรรวมรุ่นของโมเดลและเวลาประทับของการทำนายไว้ในข้อมูลกำกับเสมอ

import pandas as pd
import torch.nn.functional as F
import torch

results = []
id2label = {0: 'NEGATIVE', 1: 'POSITIVE'}

model.eval()
for i, text in enumerate(sample_texts):
    inputs = tokenizer(text, return_tensors='pt',
                       truncation=True, max_length=256)
    with torch.no_grad():
        logits = model(**inputs).logits
    probs = F.softmax(logits, dim=1).squeeze()
    pred = torch.argmax(probs).item()
    results.append({
        'text': text[:80],
        'true_label': id2label[sample_labels[i]],
        'predicted_label': id2label[pred],
        'confidence': round(probs[pred].item(), 4)
    })

df = pd.DataFrame(results)
df.to_csv('bert_predictions.csv', index=False)
print(df.head())

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจแนวคิดการเรียนรู้ของเครื่องด้วย Python จากบทเรียนนี้

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า โลจิตคือคะแนนดิบของโมเดลที่แปลงเป็นค่าความน่าจะเป็นด้วยซอฟต์แมกซ์สำหรับงานหลายคลาส หรือด้วยซิกมอยด์สำหรับงานหลายป้ายกำกับ argmax ให้ดัชนีคลาสที่ทำนาย ซึ่งจับคู่กับป้ายกำกับที่มนุษย์อ่านเข้าใจได้ผ่านพจนานุกรม id2label และ classification_report กับเมทริกซ์ความสับสนร่วมกันช่วยให้เห็นประสิทธิภาพของโมเดลได้ครบถ้วนนอกเหนือจากความแม่นยำ ต่อไปเราจะสำรวจ MLflow สำหรับติดตามการทดลอง พารามิเตอร์ และตัวชี้วัดจากการฝึกหลายรอบ

เริ่มต้นได้ฟรี

เรียนรู้ Python ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
30
บทเรียน
120

คำถามที่พบบ่อย

บทเรียน “การประเมินและการอนุมาน: จากลอจิตสู่ป้ายกำกับที่ทำนาย” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การประเมินและการอนุมาน: จากลอจิตสู่ป้ายกำกับที่ทำนาย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Machine Learning Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Machine Learning Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การประเมินและการอนุมาน: จากลอจิตสู่ป้ายกำกับที่ทำนาย”

ผู้เรียนจะคำนวณ softmax บนลอจิต ถอดรหัสดัชนีคลาสที่ทำนายเป็นป้ายกำกับ และประเมินแบบจำลองที่ปรับแต่งแล้วด้วยความแม่นยำและ F1 บนชุดทดสอบที่กันไว้ คุณปฏิบัติ Machine Learning Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Machine Learning Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Machine Learning Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “การประเมินและการอนุมาน: จากลอจิตสู่ป้ายกำกับที่ทำนาย” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Machine Learning Academy นี้ได้ไหม

ได้ บทเรียน Machine Learning Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สถาปัตยกรรม Transformer: ความใส่ใจ โทเค็น และบริบท
  2. ตัวแยกโทเค็น Hugging Face: การเข้ารหัสข้อความสำหรับ BERT
  3. การปรับแต่ง BertForSequenceClassification
  4. การประเมินและการอนุมาน: จากลอจิตสู่ป้ายกำกับที่ทำนาย
← กลับไปที่ Machine Learning Academy