دعونا نكتب ونفهم شجرة القرار في بايثون من الصفر! الجزء 1. نظرة عامة

مرحبا هبر! أقدم انتباهكم إلى ترجمة المقال " بايثون で 0 か ら デ ィ シ ジ ョ ン ツ リ ー を 作 て 理解 す る (1. 概要 編) ".



1.1 ما هي شجرة القرار؟



1.1.1 مثال شجرة القرار



على سبيل المثال ، لدينا مجموعة البيانات التالية (مجموعة التاريخ): الطقس ودرجة الحرارة والرطوبة والرياح والجولف. اعتمادًا على الطقس وكل شيء آخر ، ذهبنا () أو لم نلعب (×) الجولف. افترض أن لدينا 14 خيارًا مسبقًا.







من هذه البيانات ، يمكننا تكوين هيكل بيانات يوضح الحالات التي ذهبنا فيها للعب الجولف. تسمى هذه البنية بشجرة القرار نظرًا لشكلها المتفرّع.







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



1.1.2 حول هذه المقالة



توجد خوارزميات تنشئ مثل هذه الأشجار القرار تلقائيًا بناءً على البيانات المتاحة. في هذه المقالة ، سنستخدم خوارزمية ID3 في Python.



هذه المقالة هي الأولى في سلسلة. المقالات التالية:



(ملاحظة للمترجم: "إذا كنت مهتمًا بالتتمة ، فيرجى إخبارنا بذلك في التعليقات.")



  • أساسيات برمجة بايثون
  • أساسيات المكتبة الأساسية لتحليل بيانات Pandas
  • أساسيات بنية البيانات (في حالة شجرة القرار)
  • أساسيات إنتروبيا المعلومات
  • تعلم خوارزمية لتوليد شجرة القرار


1.1.3 قليلا عن شجرة القرار



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



تعد ميزة Decision Tree هذه جيدة ليس فقط للتعلم الآلي ، ولكن أيضًا لتعدين التاريخ ، حيث يكون فهم البيانات من قبل المستخدم مهمًا أيضًا.



1.2 حول خوارزمية ID3



ID3 هي خوارزمية إنشاء شجرة القرار التي طورها روس كوينلان في عام 1986. لها ميزتان مهمتان:



  1. بيانات تسلسلية. هذه بيانات مشابهة لمثالنا أعلاه (اذهب للجولف أم لا) ، بيانات تحمل تصنيفًا فئويًا محددًا. لا يمكن لـ ID3 استخدام البيانات الرقمية.
  2. إنتروبيا المعلومات هو مؤشر يشير إلى سلسلة من البيانات بأقل تباين في خصائص فئة من القيم.


1.2.1 حول استخدام البيانات الرقمية



الخوارزمية C4.5 ، وهي إصدار أكثر تقدمًا من ID3 ، يمكنها استخدام البيانات الرقمية ، ولكن نظرًا لأن الفكرة الأساسية هي نفسها ، في هذه السلسلة من المقالات ، سنستخدم ID3 أولاً.



1.3 بيئة التطوير



البرنامج الذي وصفته أدناه ، اختبرته وتشغيله في ظل الظروف التالية:



  • Jupyter Notebooks (باستخدام Azure Notebooks)
  • Python 3.6.0 تحديث
  • المكتبات: الرياضيات ، الباندا ، functools (لم تستخدم scikit-Learn ، Tensorflow ، إلخ)


1.4 نموذج البرنامج



1.4.1 في الواقع ، البرنامج



أولاً ، لنقم بنسخ البرنامج إلى Jupyter Notebook وتشغيله.



import math
import pandas as pd
from functools import reduce

#  
d = {
    "":["","","","","","","","","","","","","",""],
    "":["","","","","","","","","","","","","",""], 
    "":["","","","","","","","","","","","","",""],
    "":["","","","","","","","","","","","","",""],
    #   -    ,  , 
    #    .
    "":["×","×","○","○","○","×","○","×","○","○","○","○","○","×"],
}
df0 = pd.DataFrame(d)

# -   ,  - pandas.Series, 
#   -      
#    s   value_counts()     , 
#       ,   ,  items().
#         ,   sorted, 
#       
#  ,  ,     :  (k)   (v).
cstr = lambda s:[k+":"+str(v) for k,v in sorted(s.value_counts().items())]

#   Decision Tree
tree = {
    # name:    ()
    "name":"decision tree "+df0.columns[-1]+" "+str(cstr(df0.iloc[:,-1])),
    # df: ,     ()
    "df":df0,
    # edges:   (),    , 
    #   ,     .
    "edges":[],
}

#  ,      ,   open
open = [tree]

# -   . 
#  - pandas.Series、  -  
entropy = lambda s:-reduce(lambda x,y:x+y,map(lambda x:(x/len(s))*math.log2(x/len(s)),s.value_counts()))

# ,  open   
while(len(open)!=0):
    #    open  ,
    #   ,    
    n = open.pop(0)
    df_n = n["df"]

    #  ,      0,         
    #      
    if 0==entropy(df_n.iloc[:,-1]):
        continue
    #  ,          
    attrs = {}
    #   ,     
    for attr in df_n.columns[:-1]:
        #  ,         ,
        #      ,  .
        attrs[attr] = {"entropy":0,"dfs":[],"values":[]}
        #      . 
        #  , sorted      , 
        #       ,    .
        for value in sorted(set(df_n[attr])):
            #     
            df_m = df_n.query(attr+"=='"+value+"'")
            #  ,    
            attrs[attr]["entropy"] += entropy(df_m.iloc[:,-1])*df_m.shape[0]/df_n.shape[0]
            attrs[attr]["dfs"] += [df_m]
            attrs[attr]["values"] += [value]
            pass
        pass
    #      ,    , 
    #    .
    if len(attrs)==0:
        continue
    #      
    attr = min(attrs,key=lambda x:attrs[x]["entropy"])
    #     
    #  ,   ,      open.
    for d,v in zip(attrs[attr]["dfs"],attrs[attr]["values"]):
        m = {"name":attr+"="+v,"edges":[],"df":d.drop(columns=attr)}
        n["edges"].append(m)
        open.append(m)
    pass

#   
print(df0,"\n-------------")
#     ,  - tree:  ,
# indent:    indent,
#   -   .
#            .
def tstr(tree,indent=""):
    #     .
    #       (      0), 
    #      df,   ,   .
    s = indent+tree["name"]+str(cstr(tree["df"].iloc[:,-1]) if len(tree["edges"])==0 else "")+"\n"
    #     .
    for e in tree["edges"]:
        #          .
        #      indent  .
        s += tstr(e,indent+"  ")
        pass
    return s
#      .
print(tstr(tree))




1.4.2 النتيجة



إذا قمت بتشغيل البرنامج أعلاه ، فسيتم تمثيل شجرة القرار لدينا كجدول رموز كما هو موضح أدناه.

decision tree  ['×:5', '○:9']
  =
    =['○:2']
    =['×:3']
  =['○:4']
  =
    =['×:2']
    =['○:3']


1.4.3 قم بتغيير السمات (مصفوفات البيانات) التي نريد استكشافها



المصفوفة الأخيرة في مجموعة التاريخ d هي سمة فئة (مجموعة البيانات التي نريد تصنيفها).



d = {    
"":["","","","","","","","","","","","","",""],    
"":["","","","","","","","","","","","","",""],     
"":["","","","","","","","","","","","","",""],    
"":["×","×","○","○","○","×","○","×","○","○","○","○","○","×"],}    
#   -    ,  ,    .    
"":["","","","","","","","","","","","","",""],
}


على سبيل المثال ، إذا قمت بتبديل المصفوفتين "Golf" و "Wind" ، كما هو موضح في المثال أعلاه ، فستحصل على النتيجة التالية:



decision tree  [':6', ':8']
    =
      =
        =[':1', ':1']
      =[':1']
    =[':2']
  =○
    =
      =[':1']
      =[':1']
    =
      =[':2']
      =[':1']
      =[':1']
    =[':3']


من حيث الجوهر ، نقوم بإنشاء قاعدة نخبر فيها البرنامج أن يتفرع أولاً عن طريق وجود الرياح وغيابها وما إذا كنا سنلعب الجولف أم لا.



شكرا للقراءة!



سنكون سعداء جدا إذا أخبرتنا ما إذا كنت قد أحببت هذا المقال ، هل كانت الترجمة واضحة ، هل كانت مفيدة لك؟



All Articles