Machine Learning Academy · บทเรียน

กลยุทธ์ลดอคติ: ก่อนประมวลผล ระหว่างประมวลผล และหลังประมวลผล

ผู้เรียนจะใช้การถ่วงน้ำหนักใหม่ (ก่อนประมวลผล) เพิ่มข้อจำกัดด้านความเป็นธรรมระหว่างการฝึก (ระหว่างประมวลผล) และปรับเทียบเกณฑ์การตัดสินใจแยกตามกลุ่ม (หลังประมวลผล) พร้อมเปรียบเทียบข้อแลกเปลี่ยน

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

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

สามขั้นตอนของการลดอคติ

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

การประมวลผลล่วงหน้า: การถ่วงน้ำหนักใหม่

การถ่วงน้ำหนักใหม่กำหนดน้ำหนักตัวอย่างที่แตกต่างกันให้ตัวอย่างฝึกสอน เพื่อให้การกระจายแบบถ่วงน้ำหนักมีความเป็นธรรมเมื่อพิจารณาคุณลักษณะที่ได้รับการคุ้มครอง ตัวอย่างจากการผสม (ป้ายกำกับ, กลุ่ม) ที่มีตัวแทนน้อยได้รับน้ำหนักสูงขึ้น ส่วนการผสมที่มีตัวแทนมากได้รับน้ำหนักต่ำลง จากนั้นจึงฝึกแบบจำลองด้วยน้ำหนักเหล่านี้ผ่านพารามิเตอร์ sample_weight ซึ่งตัวประมาณค่าส่วนใหญ่ของ scikit-learn รองรับ โดยไม่ต้องเปลี่ยนแปลงอัลกอริทึม

from fairlearn.preprocessing import CorrelationRemover
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler

# Reweighing: compute weights to balance (group, label) combinations
def compute_reweighing_weights(y, sensitive):
    n = len(y)
    weights = np.ones(n)
    for label in np.unique(y):
        for group in np.unique(sensitive):
            mask = (y == label) & (sensitive == group)
            expected = (y == label).mean() * (sensitive == group).mean()
            actual = mask.mean()
            if actual > 0:
                weights[mask] = expected / actual
    return weights

# Usage: model.fit(X_train, y_train, sample_weight=weights)

การประมวลผลล่วงหน้า: การลบคุณลักษณะตัวแทน

แม้ไม่มีคุณลักษณะที่ได้รับการคุ้มครอง คุณลักษณะตัวแทน เช่น รหัสไปรษณีย์หรือนามสกุล ก็อาจเข้ารหัสข้อมูลประชากรศาสตร์ได้ การลบสหสัมพันธ์ฉายคุณลักษณะเพื่อลดสหสัมพันธ์กับคุณลักษณะอ่อนไหว fairlearn.preprocessing.CorrelationRemover ทำเช่นนี้โดยลบการฉายของแต่ละคุณลักษณะบนคุณลักษณะอ่อนไหวออก ทำให้ได้คุณลักษณะที่ไม่มีสหสัมพันธ์ วิธีนี้ลดความสามารถของแบบจำลองในการเรียนรู้รูปแบบที่เลือกปฏิบัติผ่านตัวแปรตัวแทน

from fairlearn.preprocessing import CorrelationRemover
import numpy as np

X = np.random.randn(500, 5)
sensitive = np.random.choice([0, 1], 500)

# Project out correlation with sensitive attribute
cr = CorrelationRemover(sensitive_feature_ids=[0])  # column 0 is sensitive
X_fair = cr.fit_transform(X)

print('Original correlation with sensitive:', np.corrcoef(X[:, 0], sensitive)[0, 1])
print('After removal:', np.corrcoef(X_fair[:, 0], sensitive)[0, 1])

การประมวลผลระหว่างการฝึก: Exponentiated Gradient

อัลกอริทึม Exponentiated Gradient จาก fairlearn เป็นเมตาอัลกอริทึมที่ห่อหุ้มตัวจำแนกประเภทของ scikit-learn ใด ๆ และฝึกซ้ำหลายรอบโดยปรับน้ำหนักตัวอย่าง เพื่อให้เป็นไปตามข้อจำกัดด้านความเป็นธรรม (เช่น Equalized odds) อัลกอริทึมนี้แก้ปัญหาการหาค่าที่เหมาะสมภายใต้ข้อจำกัด โดยลดข้อผิดพลาดในการจำแนกประเภทให้ต่ำที่สุด ภายใต้เงื่อนไขว่าข้อจำกัดด้านความเป็นธรรมต้องอยู่ภายในค่าความคลาดเคลื่อนเอปไซลอน ผลลัพธ์คือกลุ่มตัวจำแนกประเภทแบบสุ่มที่สร้างสมดุลระหว่างความแม่นยำและความเป็นธรรม

from fairlearn.reductions import ExponentiatedGradient, EqualizedOdds
from sklearn.linear_model import LogisticRegression
import numpy as np

np.random.seed(42)
X = np.random.randn(600, 4)
sensitive = np.random.choice(['A', 'B'], 600)
y = (X[:, 0] + np.random.randn(600) * 0.5 > 0).astype(int)

base_estimator = LogisticRegression(max_iter=1000)
mitigator = ExponentiatedGradient(
    base_estimator,
    constraints=EqualizedOdds(),
    eps=0.05  # allowed violation
)
mitigator.fit(X, y, sensitive_features=sensitive)
y_pred_fair = mitigator.predict(X)
print('Predictions generated:', y_pred_fair[:10])

การประมวลผลระหว่างการฝึก: ความเป็นธรรมด้วย GridSearch

fairlearn.reductions.GridSearch เป็นทางเลือกที่เรียบง่ายกว่า โดยค้นหาแบบตารางเหนือค่าตัวคูณลากร็องฌ์สำหรับข้อจำกัดด้านความเป็นธรรม และฝึกแบบจำลองแยกกันสำหรับค่าตัวคูณแต่ละค่า ผลลัพธ์คือชุดจุดแลกเปลี่ยนระหว่าง (ความแม่นยำ, ความเป็นธรรม) ซึ่งรวมกันเป็นแนวพาเรโต จากนั้นคุณสามารถเลือกแบบจำลองที่ผ่านเกณฑ์ความเป็นธรรมขั้นต่ำด้วยความแม่นยำสูงสุดได้ วิธีนี้เข้ากันได้อย่างสมบูรณ์กับตัวประมาณค่า sklearn ใด ๆ

from fairlearn.reductions import GridSearch, DemographicParity
from sklearn.tree import DecisionTreeClassifier

gs = GridSearch(
    DecisionTreeClassifier(max_depth=4),
    constraints=DemographicParity(),
    grid_size=10
)
gs.fit(X, y, sensitive_features=sensitive)

# Inspect trade-off frontier
for pred in gs.predictors_:
    y_hat = pred.predict(X)
    acc = (y_hat == y).mean()
    dp_diff = abs(
        y_hat[sensitive == 'A'].mean() - y_hat[sensitive == 'B'].mean()
    )
    print(f'Accuracy={acc:.3f} | DP difference={dp_diff:.3f}')

การประมวลผลภายหลัง: การปรับเทียบเกณฑ์แยกตามกลุ่ม

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

import numpy as np
from sklearn.metrics import recall_score

# Assume model outputs probabilities: proba_A, proba_B for each group
np.random.seed(0)
proba = np.random.beta(2, 5, 600)  # model probability scores
y_true = (proba > 0.3 + np.random.randn(600) * 0.1).astype(int)

mask_A = sensitive == 'A'
mask_B = sensitive == 'B'

# Find threshold for group B to match group A's TPR at threshold 0.5
base_tpr = recall_score(y_true[mask_A], (proba[mask_A] >= 0.5).astype(int))
for thresh in np.arange(0.2, 0.7, 0.01):
    tpr_B = recall_score(y_true[mask_B], (proba[mask_B] >= thresh).astype(int))
    if abs(tpr_B - base_tpr) < 0.02:
        print(f'Equal-opportunity threshold for group B: {thresh:.2f} (TPR={tpr_B:.3f})')
        break

การประมวลผลภายหลัง: ThresholdOptimizer ใน fairlearn

fairlearn.postprocessing.ThresholdOptimizer ทำให้การปรับเทียบเกณฑ์แยกตามกลุ่มเป็นไปโดยอัตโนมัติ โดยรับตัวประมาณค่าที่ผ่านการฝึกแล้ว ห่อหุ้มตัวประมาณค่านั้น และค้นหาเกณฑ์เฉพาะกลุ่มที่ทำให้วัตถุประสงค์ที่เลือกมีค่าต่ำที่สุด (เช่น ความแม่นยำสมดุล) ภายใต้ข้อจำกัดด้านความเป็นธรรม ขณะทำนาย ระบบจะส่งตัวอย่างแต่ละรายการไปยังเกณฑ์ที่เหมาะสมตามการเป็นสมาชิกกลุ่มของตัวอย่างนั้น ซึ่งโปร่งใสและตรวจสอบได้

from fairlearn.postprocessing import ThresholdOptimizer
from fairlearn.metrics import equalized_odds_difference
from sklearn.linear_model import LogisticRegression

base_model = LogisticRegression(max_iter=1000)
base_model.fit(X, y)

to = ThresholdOptimizer(
    estimator=base_model,
    constraints='equalized_odds',
    objective='balanced_accuracy_score',
    predict_method='predict_proba'
)
to.fit(X, y, sensitive_features=sensitive)
y_pred_to = to.predict(X, sensitive_features=sensitive)

print('EO difference before:', equalized_odds_difference(y, base_model.predict(X), sensitive_features=sensitive))
print('EO difference after:', equalized_odds_difference(y, y_pred_to, sensitive_features=sensitive))

การเปรียบเทียบสามแนวทาง

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

comparison = {
    'Pre-processing (reweighing/removal)': {
        'requires_retraining': True,
        'model_agnostic': True,
        'typical_accuracy_cost': 'Low to medium'
    },
    'In-processing (Exp. Gradient)': {
        'requires_retraining': True,
        'model_agnostic': True,
        'typical_accuracy_cost': 'Medium'
    },
    'Post-processing (threshold optimizer)': {
        'requires_retraining': False,
        'model_agnostic': True,
        'typical_accuracy_cost': 'Low (if scores are calibrated)'
    }
}
for method, props in comparison.items():
    print(method, '->', props)

การวัดประสิทธิผลของการลดอคติ

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

from fairlearn.metrics import MetricFrame, demographic_parity_difference
from sklearn.metrics import accuracy_score
import numpy as np

results = []
for threshold_offset in [0.0, -0.05, -0.10, -0.15]:
    y_hat = np.where(
        sensitive == 'B',
        (proba >= 0.5 + threshold_offset).astype(int),
        (proba >= 0.5).astype(int)
    )
    acc = accuracy_score(y_true, y_hat)
    dp = demographic_parity_difference(y_true, y_hat, sensitive_features=sensitive)
    results.append({'offset': threshold_offset, 'accuracy': acc, 'dp_diff': abs(dp)})
    print(f'offset={threshold_offset:.2f}: accuracy={acc:.3f}, dp_diff={abs(dp):.3f}')

ความเป็นธรรมนอกเหนือจากเมตริกทางเทคนิค

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

# Non-technical checklist for responsible deployment
checklist = [
    'Affected community consulted on fairness definition',
    'Model card documents protected attributes, metrics, and mitigation',
    'Fairness metrics monitored in production alongside accuracy',
    'Individual appeal process exists for adverse decisions',
    'Third-party audit scheduled before high-stakes deployment',
    'Data provenance documented to detect historical bias sources'
]
for item in checklist:
    print('[x]', item)

กระบวนการทำงานด้านความเป็นธรรมแบบครบวงจร

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

# Sketch of a full fairness-aware pipeline
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from fairlearn.reductions import ExponentiatedGradient, EqualizedOdds
from sklearn.linear_model import LogisticRegression

# Step 1: pre-process (reweighing done externally via sample_weight)
preprocessor = StandardScaler()
X_scaled = preprocessor.fit_transform(X)

# Step 2: in-processing with fairness constraint
mitigator = ExponentiatedGradient(
    LogisticRegression(max_iter=1000),
    constraints=EqualizedOdds(),
    eps=0.05
)
mitigator.fit(X_scaled, y, sensitive_features=sensitive)

# Step 3: evaluate and document
y_fair = mitigator.predict(X_scaled)
print('Fair model accuracy:', (y_fair == y).mean().round(3))

ตรวจสอบความเข้าใจอย่างรวดเร็ว

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

ทบทวนบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า วิธีการประมวลผลล่วงหน้า (การถ่วงน้ำหนักใหม่และการลบสหสัมพันธ์) ปรับเปลี่ยนข้อมูลฝึกสอนก่อนการปรับแบบจำลอง วิธีการประมวลผลระหว่างการฝึก (Exponentiated Gradient และ GridSearch) ผนวกข้อจำกัดด้านความเป็นธรรมเข้ากับวัตถุประสงค์การเรียนรู้ และ วิธีการประมวลผลภายหลัง (ThresholdOptimizer) ปรับเทียบเกณฑ์แยกตามกลุ่มหลังการฝึก เครื่องมือเหล่านี้ช่วยให้คุณลดอคติที่วัดด้วยความเท่าเทียมทางประชากรศาสตร์ โอกาสที่เท่าเทียมกัน และ Equalized odds ได้อย่างเป็นระบบ ต่อไป เราจะเริ่มโครงงานสรุปด้วยการกำหนดขอบเขตปัญหาการเรียนรู้ของเครื่องจริงตั้งแต่ต้นจนจบ

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

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

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

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

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

บทเรียน “กลยุทธ์ลดอคติ: ก่อนประมวลผล ระหว่างประมวลผล และหลังประมวลผล” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “กลยุทธ์ลดอคติ: ก่อนประมวลผล ระหว่างประมวลผล และหลังประมวลผล”

ผู้เรียนจะใช้การถ่วงน้ำหนักใหม่ (ก่อนประมวลผล) เพิ่มข้อจำกัดด้านความเป็นธรรมระหว่างการฝึก (ระหว่างประมวลผล) และปรับเทียบเกณฑ์การตัดสินใจแยกตามกลุ่ม (หลังประมวลผล) พร้อมเปรียบเทียบข้อแลกเปลี่ยน คุณปฏิบัติ 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. ค่า SHAP: ความสำคัญของคุณลักษณะระดับภาพรวมและเฉพาะกรณี
  2. LIME: คำอธิบายโมเดลเฉพาะกรณีที่ตีความได้โดยไม่ยึดติดกับโมเดล
  3. ตัวชี้วัดความเป็นธรรม: ความเสมอภาคทางประชากรและโอกาสที่เท่าเทียม
  4. กลยุทธ์ลดอคติ: ก่อนประมวลผล ระหว่างประมวลผล และหลังประมวลผล
← กลับไปที่ Machine Learning Academy