使用決策樹ID3算法,預測收入是否大于50k

數據集是在UCI上下載的:http://archive.ics.uci.edu/ml/datasets/Adult

算法比較簡單,沒有涉及剪枝和限制樹深,懶得寫.. 實現完算法在數據集上跑了一遍,發現數據集太大導致棧溢出,所以只能預測部分數據了,誰知道比較好的優化辦法歡迎交流~

數據:


列描述信息


代碼:

import pandas as pd 
import numpy as np
import math
import sys
col_names=['age','workclass','fnlwgt','education','education_num',
'marital_status','occupation','relationship','race','sex',
'capital_gain','capital_loss','hours_per_week','native_country','high_income']
income=pd.read_table('./data/income.data',sep=',',names=col_names)


#sys.setrecursionlimit(1000) 嘗試用sys解決溢出,無效


#處理數據
columns=['workclass','education','marital_status', 'occupation', 'relationship', 'race', 'sex', 'native_country','high_income']
for name  in columns:
    col=pd.Categorical.from_array(income[name])
    income[name]=col.codes

#Splitting data
private_incomes=income[income['workclass']==4]
public_incomes=income[income['workclass']!=4]

#Calculating_entropy
def calc_entropy(column):
    counts=np.bincount(column)
    probabilities=counts/len(column)
    entropy=0
    for prob in probabilities:
        if prob>0:
            entropy+=prob*math.log(prob,2)
    return -entropy

#Calculating information_gain
def calc_information_gain(data,split_name,target_name):
    original_entropy=calc_entropy(data[target_name])
    column=data[split_name]
    median=column.median()
    
    left_split=data[column<=median]
    right_split=data[column>median]
    
    to_subtract=0
    for subset in [left_split,right_split]:
        prob=(subset.shape[0]/data.shape[0])
        to_subtract+=prob*calc_entropy(subset[target_name])
    return original_entropy - to_subtract   

#Finding best split column
def find_best_column(data,columns,target_column):

    information_gains=[]
    for col in columns:
        information_gains.append(calc_information_gain(data,col,target_column))
    highest_gain=columns[information_gains.index(max(information_gains))]
    return highest_gain


#Constructing DecisionTree-using id3 algorithm and storing it .
def id3(data,columns,target,tree):
    unique_targets=pd.unique(data[target])
    
    nodes.append(len(nodes)+1)
    tree['number']=nodes[-1]
    if len(unique_targets)==1 :
        tree['label']=unique_targets[0]
        return tree  
    
    best_column=find_best_column(data,columns,target)
    column_median=data[best_column].median()
    
    tree['column']=best_column
    tree['median']=column_median
    
    left_split=data[data[best_column] <= column_median]
    right_split=data[data[best_column] > column_median]

    split_dict=[["left",left_split],["right",right_split]]
    for name,split in split_dict:
        tree[name]={}
        id3(split,columns,target,tree[name])


#Printing a more attractive tree
def print_with_depth(string,depth):
    prefix="   "*depth
    print("{0}{1}".format(prefix,string))
def print_node(tree,depth):
    if 'label' in tree:
        print_with_depth("Leaf:Label {0}".format(tree['label']),depth)
        return
    print_with_depth("{0}>{1}".format(tree['column'],tree['median']),depth)
    branches=[tree['left'],tree['right']]
    for branch in branches:
        print_node(branch,depth+1)

#Making predictions
def predict(tree,row):
    if 'label' in tree:
        return tree['label']
    column=tree['column']
    median=tree['median']
    if row[column]<=median:
        return predict(tree['left'],row)
    else:
        return predict(tree['right'],row)
def batch_predict(tree,df):
    predictions=df.apply(lambda x:predict(tree,x),axis=1)
    return predictions

columns = ["age", "workclass", "education_num", "marital_status", "occupation", "relationship", "race", "sex", "hours_per_week", "native_country"]
tree={} 
nodes=[] #保存節點編號
train=income[:100]  #預測全部時發生棧溢出現象,所以只預測部分數據
test=income[100:110]
id3(train,columns,'high_income',tree)

actual_prediction=pd.DataFrame({'actual':batch_predict(tree,test),'pred':test['high_income']})
actual_prediction.index=range(10)

print("======>>>Decision Tree:")
print(print_node(tree,0))
print("=====>>>>>預測:")
print(actual_prediction)

結果:


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容