تعلم الآلةمترجم

قابلية التفسير: فتح الصندوق الأسود، الجزء الثاني

كتابة: Manu Joseph   ترجمة: نضال إمام   مراجعة: فارس القنيعير   [للمقال الأصلي باللغة الإنجليزية اضغط هنا]

الجزء الثاني من السلسلة يتمحور حول الاستفادة من الطرق المختلفة لفتح الصندوق الأسود للذكاء الاصطناعي، يأخذ هذا الدليل في الاعتبار التفسير الإلحاقي (post-hoc interpretation) الذي يفيد عندما يكون النموذج غير شفاف (transparent).

في المشاركة السابقة من هذه السلسلة، قمنا بتعريف القابلية للتفسير (interpretability) وألقينا نظرة على بعض النماذج القابلة للتفسير ومشاكلها. دعونا الآن نتعمق أكثر في طرق التفسير الإلحاقي، والتي تكون مفيدة عندما يكون نموذجك نفسه غير شفاف. يتناسب هذا مع معظم حالات الاستخدام الواقعية (real-world)، لأنه سواءً أحببنا ذلك أم لا، فإننا نحصل على أداء أفضل مع نموذج الصندوق الأسود (black box model).

مجموعة البيانات (Data Set)

بالنسبة لهذا التمرين، اخترت مجموعة بيانات البالغين المعروفة أيضًا باسم مجموعة ببيانات تعداد الدخل. تعد (Census Income) مجموعة بيانات شائعة جدًا تحتوي على معلومات ديموغرافية مثل العمر والمهنة، بالإضافة إلى عمود يخبرنا ما إذا كان دخل شخص معين > ٥٠ ألفًا أم لا. سنستخدم هذا العمود لبناء مصنف ثنائي (binary classification) باستخدام الغابة العشوائية (Random Forest). أسباب اختيار هذه الخوارزمية من شقين:

      1. تعد الغابة العشوائية (Random Forest) واحدة من أكثر الخوارزميات استخدامًا، جنبًا إلى جنب مع الأشجار الاشتقاقية المعززة (Gradient Boosted Trees). كلاهما من عائلة خوارزميات أشجار القرار (Decision Trees)
      2. هناك بعض الطرق الخاصة بالنماذج القائمة على الأشجار، والتي أود مناقشتها

نظرة عامة على مجموعة بيانات تعداد الدخل (Census Income)

بيانات نموذجية من مجموعة بيانات تعداد الدخل (Census Income)

التفسير الإلحاقي (post-hoc interpretation)

دعونا الآن نلقي نظرة على بعض الطرق التي نستطيع من خلالها استخدام التفسير الإلحاقي لفهم نماذج الصندوق الأسود. في بقية التدوينة سوف تستند المناقشة إلى نماذج تعلم الآلة التقليدية (ML) (وليس التعلم العميق) وسوف تستند إلى البيانات المنظمة (structured data). في حين أن العديد من الأساليب هنا حيادية النموذج (model agnostic)، نظرًا لوجود العديد من الطرق المحددة لتفسير نماذج التعلم العميق، خاصةً على البيانات غير المنظمة، فإننا نترك ذلك خارج نطاقنا الحالي (ربما تدوينة أخرى في يوم آخر).

معالجة البيانات (DATA PREPROCESSING)

  • ترميز الهدف المتغير إلى متغيرات عددية (numerical variables)
  • التعامل مع القيم الناقصة (missing)
  • تحويل الحالة الاجتماعية (marital_status) إلى متغير ثنائي من خلال جمع بين بعض القيم
  • إسقاط التعليم (education) لأن education_num يعطي نفس المعلومات، ولكن بتنسيق رقمي
  • إسقاط capital_gainand capital_loss لأنها لا تحمل أية معلومات. أكثر من ٩٠٪ منها أصفار
  • إسقاط native_country بسبب ارتفاع عدد العناصر والانحراف نحو الولايات المتحدة
  • إسقاط العلاقة (relationship) بسبب الكثير من التداخل مع الحالة الاجتماعية (marital_status)

لقد قمنا بضبط وتدريب خوارزمية الغابة العشوائية (Random Forest) على البيانات بأداء ٨٣.٥٨٪. إنها درجة جيدة بالنظر إلى أن أفضل الدرجات تتراوح مابين ٧٨ إلى ٨٦٪  بناءً على طريقة التدريب والاختبار. ولكن هذا الأداء للنموذج يعد أكثر من كافٍ بالنسبة لنا.

١) متوسط الانخفاض في الشوائب (Mean Decrease in Impurity)

هذه هي الطريقة الأكثر شيوعًا لشرح النموذج القائم على الأشجار (tree-based model) ومجموعاته (ensembles). يرجع الكثير من ذلك إلى Sci-Kit Learn، وسهولة استخدامه في تنفيذ الطريقة. أصبحت الغابة العشوائية (Random Forest) أو نموذج الاشتقاق المعزز (Gradient Boosting) والرسم البياني “لأهمية الخصائص” أكثر الأساليب استخدامًا وسوء تنفيذ بين علماء البيانات.

يتم حساب متوسط الانخفاض في أهمية الشوائب لأي خاصية عن طريق قياس مدى فعالية الخاصية في تقليل عدم يقين (المصنفات) أو التباين (الانحدار) عند إنشاء أشجار القرار داخل أي مجموعة شجرة قرار (ensemble Decision Tree) مثلاً الغابة العشوائية، أو الإنحدار المعزز، إلخ.

مزايا هذا الأسلوب هي:

  • أحد أسهل وأسرع الطرق للحصول على أهمية الخاصية (feature importance)
  • متوفر بسهولة في مكتبة Sci-kit Learn و Decision Tree في R
  • يمكن شرحه للأشخاص غير المتخصصين بسهولة

الخوارزمية (ALGORITHM)

  • أثناء بناء الشجرة، كلما تم إجراء انقسام نتتبع الخاصية التي أدت إلى الانقسام، وما هي الشوائب الجينية (Gini impurity) قبل وبعد، وعدد العينات التي أثرت عليها
  • في نهاية عملية بناء الشجرة، يمكنك حساب الكسب (gain) الإجمالي في المؤشر الجيني (Gini Index) المنسوب لكل خاصية
  • وفي حال استخدام الغابة العشوائية (Random Forest) أو الأشجار الاشتقاقية المعززة (Gradient Boosted Tree)، نحسب متوسط هذه النتيجة لجميع الأشجار في المجموعة

التنفيذ (IMPLEMENTATION)

تقوم مكتبة Sci-kit Learn بتنفيذ هذا افتراضيًا في النماذج المستندة إلى الأشجار عند احتساب “أهمية الخاصية”. لذا فإن استعادتها وتخطيط أفضل ٢٥ خاصية أمر بسيط للغاية.

feat_imp = pd.DataFrame({'features': X_train.columns.tolist(), "mean_decrease_impurity": rf.feature_importances_}).sort_values('mean_decrease_impurity', ascending=False)
feat_imp = feat_imp.head(25)
feat_imp.iplot(kind='bar',
               y='mean_decrease_impurity',
               x='features',
               yTitle='Mean Decrease Impurity',
               xTitle='Features',
               title='Mean Decrease Impurity',
              )

أنقر هنا للاطلاع على المخطط التفاعلي الكامل

يمكننا أيضًا استرجاع ورسم متوسط الانخفاض في شوائب كل شجرة.

# get the feature importances from each tree and then visualize the
# distributions as boxplots
all_feat_imp_df = pd.DataFrame(data=[tree.feature_importances_ for tree in
                                     rf],
                               columns=X_train.columns)
order_column = all_feat_imp_df.mean(axis=0).sort_values(ascending=False).index.tolist()
  
all_feat_imp_df[order_column[:25]].iplot(kind='box', xTitle = 'Features', yTitle='Mean Decease Impurity')

أنقر هنا للاطلاع على المخطط التفاعلي الكامل

التفسير (INTERPRETATION)

  • أهم ٤ خصائص هي الحالة الاجتماعية (marital status) ورقم التعليم (education_num) والعمر(age) وساعات العمل (hours_worked). هذا منطقي تمامًا، لأن هذه الخصائص لها علاقة كبيرة بالمبلغ الذي تم اكتسابه
  • لاحظ الخاصيتين (fnlwgt) والعشوائية (random)، أهما أهم من مهنة الشخص (occupation)؟
  • أحد النقاط المهمة هنا هو أننا ننظر إلى خصائص الـ (one-hot) كل خاصية على حدة، وقد تقوم هذه الطريقة بتفسير سبب تصنيف المهنة (occupation) أقل من العشوائية (random). يعتبر التعامل مع خصائص الـ (one-hot) عند النظر إلى أهمية الخاصية موضوعًا آخر تمامًا

دعونا نلقي نظرة على هذه الخاصيتين (fnlwgt) والعشوائية (random):

  • يعد وصف مجموعة البيانات الخاصة بـ (fnlwgt) بالوصف الطويل والمعقد، حيث يصف الطريقة التي تستخدمها وكالة التعداد لأخذ العينات لإنشاء “الأعداد المرجحة” (weighted tallies) لأي خصائص اجتماعية-اقتصادية (socio-economic) محددة للسكان. باختصار، إنه وزن العينات (sampling weight) وليس له علاقة بالمبلغ الذي يكتسبه الشخص
  • والعشوائية (random) هي بالضبط ما يعنيه الاسم. فقد قمت بإنشاء عمود بأرقام عشوائية وسميته random قبل تدريب النموذج

بالتأكيد لا يمكن أن تكون هذه الخصائص أكثر أهمية من الخصائص الأخرى مثل المهنة (occupation)، فئة العمل (work_class)، الجنس (sex)، وما إلى ذلك. إذا كان هذا هو الحال، فهناك خطأ ما.

مشاكل الطريقة

يعتبر متوسط الانخفاض (mean decrease) في مقياس الشوائب (impurity measure) مقياسًا متحيزًا (biased) لأهمية الخاصية. إنه يفضل الخصائص المستمرة (continuous features) والخصائص ذات القيم الفريدة (high cardinality). في عام 2007، أشار ستروبل وآخرون [1] في أحد المقالات أن “مقاييس أهمية المتغير التي استخدمها بريمان للغابة العشوائية (Random Forest) الأصلية  … غير موثوقة في الحالات التي تختلف فيها متغيرات التنبؤ المحتملة في نطاق القياس أو عدد الفئات”.

دعونا نحاول فهم سبب الانحياز. أتذكر كيف يتم احتساب متوسط انخفاض الشوائب؟ في كل مرة يتم فيها تقسيم عقدة (node) على خاصية، يتم تسجيل الانخفاض في المؤشر الجيني (gini index). وعندما تكون الخاصية مستمرة أو بها عدد كبير من العناصر الأساسية، فقد يتم تقسيمها عدة مرات أكثر من الخصائص الأخرى. هذا يرفع مستوى مساهمة تلك الخاصية على وجه التحديد. والقاسم المشترك بين الخاصيتين (fnlwgt و random) هو أن كليهما متغيرات مستمرة.

2) إسقاط أهمية العمود ويعرف أيضًا باسم اترك متغيرًا واحدًا خارجًا (Leave One Co-variate Out LOOC)

يعد إسقاط أهمية العمود طريقة بديهية أخرى للنظر إلى أهمية الخاصية. كما يوحي الاسم، إنها طريقة لإزالة عنصر بشكل متكرر وحساب الاختلاف في الأداء.

مزايا هذه الطريقة هي:

  • تعطي صورة دقيقة جدًا عن القدرة التنبؤية لكل خاصية
  • واحدة من أكثر الطرق التي نستطيع من خلالها النظر إلى أهمية الخاصية
  • نموذج حيادي (Model agnostic). يمكن تطبيقها على أي نموذج
  • الطريقة التي تتم بها العملية الحسابية تأخذ في الاعتبار تلقائيًا جميع التفاعلات (interactions) في النموذج. إذا تم إتلاف المعلومات الموجودة في الخاصية، يتم أيضًا إتلاف جميع تفاعلاتها

الخوارزمية (ALGORITHM)

  • استخدم معاملات النموذج المدرب واحسب المقياس الذي تختاره على عينة غير مستخدمة في التدريب Out-of-bag (OOB). الآن تستطيع استخدام التحقق المتقاطع (cross validation) للحصول على النتيجة. هذا هو خط الأساس (baseline) الخاص بك
  • الآن، قم بحذف عمود واحد في كل مرة من مجموعة التدريب الخاصة بك، وأعد تدريب النموذج (بنفس المعاملات والحالة العشوائية) واحسب درجة OOB
  • الأهمية = درجة OOB – خط الأساس (baseline)

التنفيذ (IMPLEMENTATION)

def dropcol_importances(rf, X_train, y_train, cv = 3):
    rf_ = clone(rf)
    rf_.random_state = 42
    baseline = cross_val_score(rf_, X_train, y_train, scoring='accuracy', cv=cv)
    imp = []
    for col in X_train.columns:
        X = X_train.drop(col, axis=1)
        rf_ = clone(rf)
        rf_.random_state = 42
        oob = cross_val_score(rf_, X, y_train, scoring='accuracy', cv=cv)
        imp.append(baseline - oob)
    imp = np.array(imp)
     
    importance = pd.DataFrame(
            imp, index=X_train.columns)
    importance.columns = ["cv_{}".format(i) for i in range(cv)]
    return importance

دعونا نجري عملية تحقق متقاطع ذات ٥٠ قسم (50 fold cross validation) لتقدير درجة OOB الخاصة بنا، (أعلم أن هذه عملية مفرطة، ولكن دعنا نحتفظ بها لزيادة العينات الخاصة بـ boxplot). كما هو الحال من قبل، نحن نخطط لمتوسط الانخفاض في الدقة بالإضافة إلى boxplot لفهم التوزيع عبر اختبارات التحقق المتقاطع.

drop_col_imp = dropcol_importances(rf, X_train, y_train, cv=50)
drop_col_importance = pd.DataFrame({'features': X_train.columns.tolist(), "drop_col_importance": drop_col_imp.mean(axis=1).values}).sort_values('drop_col_importance', ascending=False)
drop_col_importance = drop_col_importance.head(25)
drop_col_importance.iplot(kind='bar',
               y='drop_col_importance',
               x='features',
               yTitle='Drop Column Importance',
               xTitle='Features',
               title='Drop Column Importances',
              )
 
all_feat_imp_df = drop_col_imp.T
order_column = all_feat_imp_df.mean(axis=0).sort_values(ascending=False).index.tolist()
 
all_feat_imp_df[order_column[:25]].iplot(kind='box', xTitle = 'Features', yTitle='Drop Column Importance')

انقر هنا للاطلاع على المخطط التفاعلي الكامل

انقر هنا للاطلاع على المخطط التفاعلي الكامل

التفسير (INTERPRETATION)

  • لا تزال أهم ٤ خصائص هي الحالة الاجتماعية، ورقم التعليم (education_num) ، والعمر، وساعات العمل
  • قلّت أهمية الخاصية (fnlwgt) بشكل كبير ونزلت للأسفل عدة مواضع
  • العشوائية لا تزال تحتل مرتبة عالية، وتقع مباشرة بعد ساعات_العمل

كما هو متوقع، كان (fnlwgt) أقل أهمية بكثير مما كنا نتوقع بعد الأخذ في الاعتبار متوسط الانخفاض في أهمية الشوائب. لقد أربكتني المكانة العالية للعشوائية (random) قليلاً وأعدت حساب الأهمية مع الأخذ في الاعتبار أن جميع الخصائص هي من فئة (one-hot)، بالتحديد: إسقاط جميع أعمدة المهنة (occupation) والتحقق من القدرة التنبؤية لخاصية المهنة. عندما قمت بذلك، أستطيع أن أرى مرتبة العشوائية و fnlwgt أقل من المهنة، وفئة العمل. حتى لا يطول المقال بشكل كبير سأترك التعمق في التحقيق ربما في وقت آخر.

إذن ، هل حصلنا على الحل الأمثل؟ تتماشى النتائج مع متوسط الانخفاض في الشوائب، وهي ذات معنى متماسك، ويمكن تطبيقها على أي نموذج.

مشاكل الطريقة

المشكلة هنا تكمن في كمية الحوسبة المتضمنة. لتنفيذ هذا النوع من حسابات الأهمية عليك تدريب النموذج عدة مرات، مرة لكل خاصية لديك، وتكرار ذلك من خلال استخدام القيمة التي تريدها من التحقق المتقاطع. حتى إذا كان لديك نموذج يتدرب في أقل من دقيقة، فإن الوقت اللازم لحساب هذا طويل جداً، لأن لديك المزيد من الخصائص. لإعطائك فكرة، استغرق الأمر ساعتين و٤٤ دقيقة لحساب أهمية الخاصية من خلال ٣٦ سمة و٥٠ حلقة تكرار (loop) تحقق متقاطعة (والتي بالطبع يمكن تحسينها من خلال المعالجة المتوازية، ولكن أعتقد أن النقطة وصلت). وإذا كان لديك نموذج كبير يستغرق تدريبه يومين، فيمكنك أن تنسى هذه الطريقة.

مصدر قلق آخر لدي بشأن هذه الطريقة هو أنه نظرًا لأننا نعيد تدريب النموذج في كل مرة بمجموعة جديدة من الخصائص، فإننا لا نقوم بإجراء مقارنة عادلة. نقوم بإزالة عمود واحد وندرب النموذج مرة أخرى. هكذا سوف يحاول النموذج إيجاد طريقة أخرى لاشتقاق نفس المعلومات إذا كان ذلك ممكنًا، ويتم تضخيم ذلك عند وجود خصائص خطية متداخلة (collinear features). لذلك نحن نخلط بين شيئين عندما نتحرى: القدرة التنبؤية للخاصية والطريقة التي يقوم بها النموذج بتكوين نفسه.

3) أهمية التبديل (Permutation Importance)

يتم تعريف أهمية تبديل الخاصية (permutation feature importance) على أنها انخفاض أداء النموذج عندما يتم تبديل قيمة خاصية واحدة عشوائيًا [2]. تقيس هذه الطريقة الاختلاف في الأداء إذا قمنا بخلط (shuffle) أو بتبديل (permute) قيم خاصية محددة. الفكرة الأساسية هي أن الخاصية تكون مهمة إذا انخفض أداء النموذج بعد تبديل قيمتها.

مزايا هذه الطريقة هي:

  • أنها بديهية. ما هو الانخفاض في الأداء إذا تم إتلاف المعلومات الموجودة في الخاصية من خلال خلطها عشوائيًا؟
  • حيادية النموذج (Model agnostic). على الرغم من أن الطريقة تم تطويرها في البداية للغابات العشوائية بواسطة Breiman، إلا أنها سرعان ما تم تكييفها للعمل في إطار نموذجي حيادي
  • الطريقة التي تتم بها العملية الحسابية، تأخذ في الاعتبار تلقائيًا جميع التفاعلات (interactions) في النموذج. إذا تم إتلاف المعلومات الموجودة في الخاصية، يتم أيضًا إتلاف جميع تفاعلاتها
  • لا يلزم إعادة تدريب النموذج، وبالتالي فإننا نقوم بتوفير العمليات الحوسبية (computation)

الخوارزمية (ALGORITHM)

  • قم بحساب خط الأساس (baseline score) باستخدام المقياس (metric) والنموذج المدرَّب ومصفوفة الخصائص ومتجه المستهدفات
  • قم بعمل نسخة لكل خاصية في مصفوفة الخصائص
  • قم بخلط عمود الخاصية، ثم تمريره للنموذج المدرب للحصول على تنبؤ واستخدم المقياس لحساب الأداء
  • الأهمية = خط الأساس – الدرجة
  • كرر لـ N مرات للاستقرار الإحصائي وأخذ متوسط الأهمية (average importance) عبر التجارب

التنفيذ (IMPLEMENTATION)

يوجد على الأقل ثلاث مكتبات في بايثون يمكن من خلالها  تطبيق طريقة أهمية التبديل: ELI5 و mlxtend و Sci-kit Learn. لقد اخترت mlxtend لأنه مريح بالنسبة لي. وفقًا لـ Strobl et al، “أهمية [التبديل] الخام (raw) … لها خصائص إحصائية أفضل”، على العكس من تسوية (normalizing) قيم الأهمية بالقسمة على الانحراف المعياري (standard deviation). لقد تحققت من الكود المصدري لـ mlxtend و Sci-kit Learn، وهما لا يعملان على تسويتهما.

from mlxtend.evaluate import feature_importance_permutation
#This takes sometime. You can reduce this number to make the process faster
num_rounds = 50
imp_vals, all_trials = feature_importance_permutation(
    predict_method=rf.predict, 
    X=X_test.values,
    y=y_test.values,
    metric='accuracy',
    num_rounds=num_rounds, 
    seed=1)
permutation_importance = pd.DataFrame({'features': X_train.columns.tolist(), "permutation_importance": imp_vals}).sort_values('permutation_importance', ascending=False)
permutation_importance = permutation_importance.head(25)
permutation_importance.iplot(kind='bar',
               y='permutation_importance',
               x='features',
               yTitle='Permutation Importance',
               xTitle='Features',
               title='Permutation Importances',
              )

نقوم أيضًا برسم box plot لجميع التجارب لفهم الانحراف.

all_feat_imp_df = pd.DataFrame(data=np.transpose(all_trials),
                               columns=X_train.columns, index = range(0,num_rounds))
order_column = all_feat_imp_df.mean(axis=0).sort_values(ascending=False).index.tolist()
 
all_feat_imp_df[order_column[:25]].iplot(kind='box', xTitle = 'Features', yTitle='Permutation Importance')

انقر للاطلاع على المخطط التفاعلي الكامل

انقر للاطلاع على المخطط التفاعلي الكامل

التفسير (INTERPRETATION)

  • تظل الأربعة الأوائل كما هي، لكن الثلاثة الأولى (الحالة الزوجية، والتعليم، والعمر) تكون أكثر وضوحًا في أهمية التبديل
  • Fnlwgt والعشوائية لا تصل حتى إلى أعلى ٢٥
  • كونك مديرًا تنفيذياً أو أستاذًا متخصصًا له علاقة كبيرة بدخلك ما إذا كان > ٥٠ ألفًا أم لا
  • في النهاية، يتوافق ذلك مع نموذجنا العقلي (mental model) للعملية

كل شيء جيد في عالم أهمية الخصائص؟ هل حصلنا على أفضل طريقة لشرح الخاصية التي يستخدمها النموذج للتنبؤات؟

مشاكل الطريقة

نعلم أنه لا يوجد شيء مثالي في الحياة، ولا هذه الطريقة أيضًا. تشكل العلاقة (correlation) بين الخصائص أهمية مماثلة لطريقة إسقاط العمود (drop column)، تتأثر هذه الطريقة أيضًا بتأثير الارتباط بين الخصائص. في احدى مقالات ستروبل وآخرون والتي تتحدث عن أهمية المتغير الشرطي (Conditional variable importance) للغابات العشوائية [3] أظهر الباحثون أن “أهمية التبديل تبالغ في تقدير (over-estimates) أهمية متغيرات التوقع المرتبطة (correlated predictor variables).” خاصة في مجموعة الأشجار، إذا كان لديك متغيرين مرتبطين، فقد تحتوي بعض الأشجار على خاصية المنتقى (picker feature) أ والبعض الآخر قد يكون قد اختار الخاصية ب. وأثناء إجراء هذا التحليل، في غياب الخاصية أ، الأشجار التي اختارت الخاصية ب ستعمل بشكل جيد وتحافظ على الأداء مرتفعًا، والعكس صحيح. ما سينتج عن ذلك هو أن كل من الخصائص المترابطة أ و ب سيكون لها أهمية مبالغ فيها.

العيب الآخر لهذه الطريقة هو أن الفكرة الأساسية لها تدور حول تبديل الخصائص. لكن هذه عشوائية ليست تحت سيطرتنا. وبسبب هذا قد تختلف النتائج بشكل كبير. لا نراه هنا، ولكن إذا أظهرت الرسمة box plot تباينًا كبيرًا في الأهمية لخاصية عبر عدة تجارب فسأكون مرتاباً في تفسيراتي.

معامل الارتباط [7] (التنميط المدمج في الباندا (pandas) الذي يأخذ في الاعتبار المتغيرات الفئوية أيضًا)

هناك عيب آخر لهذه الطريقة، والذي في رأيي هو الأكثر إثارة للقلق. جايلز هوكر وآخرون [6] يقولون “عندما تُظهر الخصائص في مجموعة التدريب اعتمادًا إحصائيًا (statistical dependence)، يمكن أن تكون طرق التبديل مضللة للغاية عند تطبيقها على النموذج الأصلي.”

دعونا ننظر في المهنة والتعليم. يمكننا أن نفهم المشكلة من منظورين:

  1. منطقياً: إذا فكرت في الأمر، فإن المهنة والتعليم لهما تبعية محددة. يمكنك الحصول على عدد قليل من الوظائف فقط إذا كان لديك تعليم كافٍ، وإحصائيًا يمكنك رسم أوجه تشابه بينهما. لذلك إذا قمنا بتبديل أي عمود من هذه الأعمدة، فسيؤدي ذلك إلى إنشاء مجموعات من الخصائص التي لا معنى لها. الشخص الذي حصل على تعليم في المرتبة العاشرة ووظيفة أستاذ ليس له معنى كبير، أليس كذلك؟ لذلك، عندما نقوم بتقييم النموذج فإننا نقوم بتقييم حالات غير منطقية مثل هذه مما يؤدي إلى تشويش المقياس الذي نستخدمه لتقييم أهمية الخاصية.
  2. حسابيًا: المهنة والتعليم لديهما اعتماد إحصائي قوي (statistical dependence) (يمكننا أن نرى ذلك من مخطط الارتباط أعلاه). لذلك، عندما نبدل أيًا من هذه الخصائص فإننا نجبر النموذج على استكشاف المساحات الفرعية غير المرئية في مساحة الخاصية عالية الأبعاد. وهذا يجبر النموذج على الاستقراء (extrapolate) وهذا الاستقراء مصدر مهم للخطأ.

جايلز هوكر وآخرون [6] اقترحوا منهجيات بديلة تجمع بين إسقاط أهمية العمود (LOOC) وطريقة التبديل (permutation)، ولكن جميع البدائل أكثر كلفة من الناحية الحوسبية وليس لديها ضمان نظري قوي لامتلاك خصائص إحصائية أفضل.

التعامل مع الخصائص المترابطة

بعد تحديد الخصائص شديدة الارتباط، هناك طريقتان للتعامل معها:

  1. قم بتجميع المتغيرات شديدة الارتباط معًا وقم بتقييم خاصية واحدة فقط من المجموعة كممثل لها
  2. عند تبديل الأعمدة قم بتبديل مجموعة الخصائص بأكملها في تجربة واحدة

ملحوظة: الطريقة الثانية هي نفس الطريقة التي أقترحها للتعامل مع متغيرات الـ (one-hot).

ملاحظة جانبية: (تدريب أم تحقق)

أثناء مناقشة أهمية إسقاط العمود وأهمية التبديل، يجب أن يتبادر إلى ذهنك سؤال. لقد قمنا بإستخدام مجموعة الاختبار/التحقق (test/validation set) لإحتساب الأهمية (importance)، لماذا لا يتم استخدام مجموعة التدريب (training set)؟

هذه منطقة رمادية عند تطبيق بعض هذه الأساليب. ليس هناك صواب أو خطأ لأن هناك حجج مع كليهما. في تعلم الآلة القابل للتفسير(Interpretable Machine Learning)، يناقش كريستوف مولنار حالة لكل من مجموعات التدريب والتحقق.

حالة بيانات الاختبار/التحقق لا تحتاج إلى تفكير. لنفس السبب الذي يجعلنا لا نحكم على نموذج من خلال الخطأ في مجموعة التدريب، لا يمكننا الحكم على أهمية الخاصية من خلال الأداء في مجموعة التدريب (خاصة وأن الأهمية مرتبطة ارتباطًا جوهريًا بالخطأ).

عند استخدام بيانات التدريب، فسترى أن ما نريد قياسه هو كيفية استخدام النموذج للخصائص. وما هي البيانات الأفضل للحكم على ذلك من مجموعة التدريب التي تم تدريب النموذج عليها؟ هناك مشكلة أخرى وهي أننا سنقوم بتدريب النموذج بشكل مثالي على جميع البيانات المتاحة، وفي مثل هذا السيناريو المثالي لن يكون هناك اختبار أو بيانات للتحقق من الأداء. في تعلم الآلة القابل للتفسير [5]، يناقش القسم 5.5.2 هذه المشكلة مطولاً وحتى مع مثال اصطناعي لفرط التخصيص عند استخدام آلة المتجهات الداعمة (SVM).

يعود كل شيء إلى ما إذا كنت تريد معرفة الخاصية التي يعتمد عليها النموذج لعمل تنبؤات أو القدرة التنبؤية لكل خاصية على البيانات التي لم يراها النموذج من قبل (unseen data). على سبيل المثال، إذا كنت تقوم بتقييم أهمية الخاصية في سياق اختيارها، فلا تستخدم بيانات الاختبار في أي ظرف من الظروف (هناك فرط في اختيار الخاصية الخاصة بك لتلائم بيانات الاختبار).

4) رسومات الاعتماد الجزئي (PDP) ورسومات التوقع الفردي المشروط (ICE)

جميع الطرق التي تم استعراضها حتى الآن تتمحور حول الأهمية النسبية للخصائص المختلفة. الآن دعنا نتوجه قليلاً في اتجاه مختلف ونلقي نظرة على بعض الطرق التي تستكشف كيفية تفاعل خاصية معينة مع المتغير المستهدف (target variable).

تساعدنا رسومات الاعتماد الجزئي (Partial Dependence Plots) ورسومات التوقع الفردي المشروط (Individual Conditional Expectation plots) على فهم العلاقة الوظيفية بين الخصائص والهدف. إنها تصويرات رسومية للتأثير الهامشي لمتغير معين (أو متغيرات متعددة) على النتيجة. قدم فريدمان (2001) هذه التقنية في ورقته الأساسية: Greedy function approximation: A gradient boosting machine.

تُظهر رسومات الاعتماد الجزئي تأثيرًا متوسطًا، بينما تُظهر رسومات ICE العلاقة الوظيفية للملاحظات الفردية. تُظهر رسومات PD متوسط التأثير بينما تُظهر رسومات ICE تشتت أو عدم تجانس التأثير.

مزايا هذه الطريقة هي:

  • الحساب سهل للغاية ويمكن شرحه بعبارات عامة
  • يمكننا فهم العلاقة بين خاصية أو مجموعة من الخصائص مع الهدف المتغير، أي إذا كانت خطية (linear) أو رتيبة (monotonic)، أو أسية (exponential)، إلخ
  • من السهل حسابها وتنفيذها
  • تعطي تفسيرًا سببيًا (causal interpretation)، بدلاً من أسلوب  تفسير أهمية الخاصية. لكن ما يجب أن نضعه في الاعتبار هو أن التفسير السببي هو لكيفية رؤية النموذج للعالم وليس للعالم الحقيقي

الخوارزمية (ALGORITHM)

لنفكر في حالة بسيطة، حيث نرسم PD لخاصية واحدة x، بقيم فريدة \{x_1, x_2, .... x_n\}. يمكن إنشاء رسمة PD على النحو التالي:

  • لـ  i\: \epsilon \: \{1,2,...k\}
    • انسخ بيانات التدريب واستبدل القيم الأصلية لـ x بـ x_i.
    • استخدم النموذج المدرب لتوليد تنبؤات للنسخة المعدلة من بيانات التدريب بأكملها
    • قم بتخزين جميع التوقعات مقابل x_i في بنية بيانات على شكل خريطة
  • لرسمة PD:
    • احسب متوسط ​​التوقعات لكل x_i \: for \: i \: \epsilon \: \{1,2,...k\}
    • ارسم الأزواج \{x_i, mean(all\: predictions \:with\: x_i)\}
  • لرسمة ICE:
    • ارسم كل الأزواج \{x_i, f(x_i,rest\:of\:features)_n\} \:where\:n\epsilon\{1, 2, ...N\}، N هو العدد الإجمالي للملاحظات في مجموعة التدريب
  • في الممارسة العملية، بدلاً من أخذ جميع القيم الممكنة لخاصية ما، نحدد جدول من الفواصل الزمنية للمتغير المستمر لحفظها عند الحساب
  • بالنسبة للمتغير الفئوي (categorical variable) أيضًا، فإن هذا التعريف صحيح، لكننا لن نحدد جدولاً هنا. بدلاً من ذلك نأخذ جميع القيم الفريدة في الفئة (أو جميع المتغيرات المشفرة ذات الترميز الواحد (one-hot encoded) المتعلقة بسمة فئوية) ونحسب مخططات ICE و PD باستخدام نفس المنهجية
  • إذا كانت العملية لا تزال غير واضحة بالنسبة لك، أقترح النظر في هذا المنشور ​​(بواسطة مؤلف PDPbox، مكتبة Python لرسم PD)

التنفيذ (IMPLEMENTATION)

لقد وجدت رسومات PD تم تنفيذها في مكتبات PDPbox و Skater و Sci-kit Learn. ورسومات ICE في مكتبات PDPbox و pyCEbox وskater. من بين كل هذه المكتبات وجدت أن PDPbox هو الأفضل من ناحية النضج. كما أنها تدعم رسومات PDP المتغيرة أيضًا.

from pdpbox import pdp, info_plots
pdp_age = pdp.pdp_isolate(
    model=rf, dataset=X_train, model_features=X_train.columns, feature='age'
)
#PDP Plot
fig, axes = pdp.pdp_plot(pdp_age, 'Age', plot_lines=False, center=False, frac_to_plot=0.5, plot_pts_dist=True,x_quantile=True, show_percentile=True)
#ICE Plot
fig, axes = pdp.pdp_plot(pdp_age, 'Age', plot_lines=True, center=False, frac_to_plot=0.5, plot_pts_dist=True,x_quantile=True, show_percentile=True)

رسم ICE للعمر

اسمحوا لي أن آخذ بعض الوقت لشرح الرسمة. على المحور س، يمكنك العثور على قيم الخاصية التي تحاول فهمها، أي العمر هنا. على المحور ص تجد التنبؤ. في حالة التصنيف (classification)، فهو التنبؤ المحتمل (prediction probability) وفي حالة الانحدار (regression)، فهو التنبؤ الحقيقي (real-valued prediction). يمثل الشريط الموجود في الأسفل توزيع نقاط بيانات التدريب بكميات مختلفة. يساعدنا في قياس جودة الاستدلال. في الأجزاء التي يكون فيها عدد النقاط أقل بكثير، فإن النموذج شاهد عددًا أقل من الأمثلة ويمكن أن يجعل ذلك التفسير صعبًا. يُظهر السطر الفردي في رسمة PD متوسط العلاقة الوظيفية بين الخاصية والهدف. توضح جميع الخطوط في رسمة ICE عدم التجانس في بيانات التدريب، أي كيف تتغير جميع الملاحظات في بيانات التدريب مع القيم المختلفة للعمر.

التفسير (INTERPRETATION)

  • العمر له علاقة رتيبة إلى حد كبير مع قدرة الشخص على الكسب. كلما كان الشخص أكبر سنًا، زاد احتمال ربحه أكثر من ٥٠ ألفًا
  • تظهر مخططات ICE الكثير من التشتت. لكن كل ذلك يظهر نفس النوع من السلوك الذي نراه في مخطط PD
  • ملاحظات التدريب متوازنة بشكل جيد عبر الكميات المختلفة

الآن، دعونا نتحدث عن خاصية فئوية (categorical feature) مثل التعليم. يحتوي PDPbox على ميزة رائعة جدًا حيث يتيح لك تمرير قائمة الخصائص كمدخلات وسوف يقوم PDP بالتعامل معها كخصائص فئوية.

# All the one-hot variables for the occupation feature
occupation_features = ['occupation_ ?', 'occupation_ Adm-clerical', 'occupation_ Armed-Forces', 'occupation_ Craft-repair', 'occupation_ Exec-managerial', 'occupation_ Farming-fishing', 'occupation_ Handlers-cleaners', 'occupation_ Machine-op-inspct', 'occupation_ Other-service', 'occupation_ Priv-house-serv', 'occupation_ Prof-specialty', 'occupation_ Protective-serv', 'occupation_ Sales', 'occupation_ Tech-support', 'occupation_ Transport-moving']
#Notice we are passing the list of features as a list with the feature parameter
pdp_occupation = pdp.pdp_isolate(
    model=rf, dataset=X_train, model_features=X_train.columns, 
    feature=occupation_features
)
#PDP
fig, axes = pdp.pdp_plot(pdp_occupation, 'Occupation', center = False, plot_pts_dist=True)
#Processing the plot for aesthetics
_ = axes['pdp_ax']['_pdp_ax'].set_xticklabels([col.replace("occupation_","") for col in occupation_features])
axes['pdp_ax']['_pdp_ax'].tick_params(axis='x', rotation=45)
bounds = axes['pdp_ax']['_count_ax'].get_position().bounds
axes['pdp_ax']['_count_ax'].set_position([bounds[0], 0, bounds[2], bounds[3]])
_ = axes['pdp_ax']['_count_ax'].set_xticklabels([])

التفسير (INTERPRETATION)

  • معظم المهن لها تأثير ضئيل للغاية على مقدار ما تكسبه
  • تلك التي تبرز عن البقية هي، Exec-manager  Prof-Specialty، و Tech Support
  • ولكن من التوزيع نعلم أنه كان هناك القليل جدًا من الأمثلة التدريبية للدعم الفني (Tech Support)، وبالتالي فإننا نأخذ ذلك بحذر

التفاعل بين العديد من الخصائص

يمكن رسم PD نظريًا لأي عدد من الخصائص لإظهار تأثير تفاعلها (interaction effect). لكن من الناحية العملية لا يمكننا فعل ذلك إلا لعدد محدود من الخصائص، بحد أقصى ثلاثة. دعنا نلقي نظرة على رسمة التفاعل بين خاصيتين مستمرتين: العمر والتعليم (التعليم والعمر ليست خصائص مستمرة حقًا، لكننا قمنا بإختيارهما لعدم وجود مثال أفضل).

هناك طريقتان نستطيع من خلالهما رسم PD بين خاصيتين. هناك ثلاثة أبعاد هنا، قيمة الخاصية ١، وقيمة الخاصية ٢، وهدف التنبؤ. نستطيع رسم رسمة ثلاثية الأبعاد أو رسمة ثنائية الأبعاد مع البعد الثالث المصور على أنه لون. أنا أفضل الرسمة ثنائية الأبعاد لأنني أعتقد أنها تنقل المعلومات بطريقة أكثر وضوحًا من الرسمة ثلاثية الأبعاد، حيث يتعين عليك إلقاء نظرة على الشكل ثلاثي الأبعاد لاستنتاج العلاقة. ينفذ PDPbox رسومات التفاعل ثنائية الأبعاد، كالرسم المحيطي (contour plot) والشبكي (grid). يعمل الرسم المحيطي بشكل أفضل مع الخصائص المستمرة والشبكة مع الخصائص الفئوية.

# Age and Education
inter1 = pdp.pdp_interact(
    model=rf, dataset=X_train, model_features=X_train.columns, features=['age', 'education_num']
)
fig, axes = pdp.pdp_interact_plot(
    pdp_interact_out=inter1, feature_names=['age', 'education_num'], plot_type='contour', x_quantile=False, plot_pdp=False
)
axes['pdp_inter_ax'].set_yticklabels([edu_map.get(col) for col in axes['pdp_inter_ax'].get_yticks()])

التفسير (INTERPRETATION)

  • على الرغم من أننا لاحظنا علاقة رتيبة مع العمر عند النظر إليه بشكل منعزل، فإننا نعلم الآن أنها ليست ملاحظة شاملة. على سبيل المثال، انظر إلى الخط المحيطي على يمين المستوى التعليمي الثاني عشر. إنها مسطحة جدًا مقارنة بخطوط بعض الجامعات وما فوقها. ما يُظهر حقًا أن احتمال حصولك على أكثر من ٥٠ ألفًا لا يزداد مع تقدم العمر فحسب، بل يتأثر أيضًا بمستوى تعليمك. تضمن لك الشهادة الجامعية زيادة إمكاناتك في الكسب مع تقدمك في السن

هذه أيضًا طريقة مفيدة جدًا للتحقق من التحيز (النوع الأخلاقي) في خوارزمياتك. لنفترض ما إذا كنا نريد أن ننظر إلى التحيز الحسابي في خاصية الجنس.

#PDP Sex
pdp_sex = pdp.pdp_isolate(
    model=rf, dataset=X_train, model_features=X_train.columns, feature='sex'
)
fig, axes = pdp.pdp_plot(pdp_sex, 'Sex', center=False, plot_pts_dist=True)
_ = axes['pdp_ax']['_pdp_ax'].set_xticklabels(sex_le.inverse_transform(axes['pdp_ax']['_pdp_ax'].get_xticks()))
 
# marital_status and sex
inter1 = pdp.pdp_interact(
    model=rf, dataset=X_train, model_features=X_train.columns, features=['marital_status', 'sex']
)
fig, axes = pdp.pdp_interact_plot(
    pdp_interact_out=inter1, feature_names=['marital_status', 'sex'], plot_type='grid', x_quantile=False, plot_pdp=False
)
axes['pdp_inter_ax'].set_xticklabels(marital_le.inverse_transform(axes['pdp_inter_ax'].get_xticks()))
axes['pdp_inter_ax'].set_yticklabels(sex_le.inverse_transform(axes['pdp_inter_ax'].get_yticks()))

رسمة PD لخاصية الجنس على اليسار ورسمة تفاعل PD لخاصية الحالة الإجتماعية على اليمين

  • إذا نظرنا فقط إلى رسمة PD للجنس، فسنستنتج أنه لا يوجد تمييز حقيقي على أساس جنس الشخص
  • ولكن عليك إلقاء نظرة على مخطط التفاعل مع الحالة الإجتماعية. على الجانب الأيسر (متزوج)، كلا المربعين لهما نفس اللون والقيمة، ولكن على الجانب الأيمن (أعزب) يوجد فرق بين الأنثى والذكر
  • يمكننا أن نستنتج أن كونك ذكرًا أعزباً يعطيك فرصة أفضل بكثير في الحصول على أكثر من ٥٠ ألفًا من كونك أنثى عزباء. (على الرغم من أنني لن أبدأ حربًا شاملة ضد التمييز الجنسي بناءً على ذلك، إلا أنها ستكون بالتأكيد نقطة انطلاق في البحث عن الموضوع)

مشاكل الطريقة

يفترض هذا النهج الاستقلال بين الخصائص وهذا يعد أحد أكبر العيوب. نفس الخلل الموجود في (LOOC) وأهمية التبديل (permutation) ينطبق على رسومات PDP و ICE. تعد رسومات التأثيرات المحلية المتراكمة (Accumulated Local Effects) حلاً لهذه المشكلة. تحل رسومات ALE هذه المشكلة عن طريق حساب -استنادًا إلى التوزيع الشرطي للخصائص- الاختلافات في التنبؤات بدلاً من المتوسطات.

الخلاصة، كيفية قيام كل نوع من أنواع الرسم (PDP ، ALE) بحساب تأثير خاصية عند قيمة جدولية معينة v:

رسومات الاعتماد الجزئي: “دعني أوضح لك ما يتوقعه النموذج في المتوسط عندما يكون لكل مثال بيانات (data instance) قيمة v لتلك الخاصية. أتجاهل ما إذا كانت القيمة v منطقية لجميع البيانات”.

رسومات ALE: “دعني أوضح لك كيف تتغير تنبؤات النموذج في نافذة صغيرة للخاصية حول v لعينات البيانات في تلك النافذة.”

في لغة بايثون، لا توجد مكتبة جيدة ومستقرة لـ ALE. لقد وجدت فقط ALEpython، والتي لا تزال قيد التطوير. عملت على رسمة  ALE للعمر، يمكنك الاطلاع عليها أدناه. لكن حصلت على خطأ عندما حاولت استخدام رسمة التفاعل. كما أنه لم يتم تطويره للخصائص الفئوية.

رسمة ALE للعمر

هذا هو المكان الذي نتوقف فيه مرة أخرى وندفع بقية الأشياء إلى منشور المدونة التالي. في الجزء التالي ، نلقي نظرة على LIME و SHAP و Anchors والمزيد.

الكود الكامل متاح في Github الخاص بي.

السيرة الذاتية: Manu Joseph @manujosephv هو عالم بيانات فضولي بطبيعته و قام بتعليم نفسه بنفسه ولديه أكثر من ٨ سنوات من خبرة المهنية في شركة Fortune 500 ، و ايضاً باحث في Thoucentric Analytics.

اظهر المزيد

نضال إمام

طالب دكتوراة بجامعة يورك بالمملكة المتحدة. مهتم بالأمن السيبراني، امن الشبكات، امن تعليم الآلة و اصتياد الرسائل الخبيثة في مواقع التواصل الإجتماعي

‫3 تعليقات

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى