<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    pingpang

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      21 Posts :: 0 Stories :: 3 Comments :: 0 Trackbacks

    一、決策樹簡介:

     

    關于決策樹,幾乎是數據挖掘分類算法中最先介紹到的。

    決策樹,顧名思義就是用來做決定的樹,一個分支就是一個決策過程。

     

    每個決策過程中涉及一個數據的屬性,而且只涉及一個。然后遞歸地,貪心地直到滿足決策條件(即可以得到明確的決策結果)。

     

    決策樹的實現首先要有一些先驗(已經知道結果的歷史)數據做訓練,通過分析訓練數據得到每個屬性對結果的影響的大小,這里我們通過一種叫做信息增益的理論去描述它,期間也涉及到的概念。也可參考文章信息增益與熵.

     

    下面我們結合實例說一下決策樹實現過程中的上述關鍵概念:

     

    假設我們有如下數據:

     

    agejobhousecreditclass
    10010
    10020
    11021
    11111
    10010
    20010
    20020
    21121
    20131
    20131
    30131
    30121
    31021
    31031
    30010

    (一)

    我們首先要通過計算找到哪個屬性的所有屬性值能更好地表達class字段的不同。通過計算,我們發現house的屬性值最能表現class字段的不同。這個衡量標準其實就是信息增益。計算方法是:首先計算全部數據的,然后除class之外的其他屬性逐個遍歷,找到最小的那個屬性(house),然后將全部數據的減去按照house屬性劃分數據之后的數據的

     

    這個值如果滿足條件假如(>0.1),我們認為數據應該按照這個節點進行分裂,也就是說這個屬性(house)構成了我們的一次決策過程。

     

    (二)

    然后

    在按照house分裂的每個數據集上,針對其他屬性(house除外)進行與(一)相同的過程,直到信息增益不足以滿足數據分裂的條件。

     

    這樣,我們就得到了一個關于屬性數據劃分的一棵樹。可以作為class字段未知的數據的決策依據。

     

     

    二、決策樹代碼實現:

     

    具體計算代碼如下:---假設上述數據我們保存為descision.dat文件,以及需要bash4.0及以上支持運行。

     

    Bash代碼  收藏代碼
    1. #!/home/admin/bin/bash_bin/bash_4  
    2.   
    3. input=$1;  
    4.   
    5. if [ -z $input ]; then  
    6.     echo "please input the traning file";  
    7.     exit 1;  
    8. fi   
    9.   
    10. ## pre calculate the log2 value for the later calculate operation  
    11. declare -a log2;  
    12. logi=0;  
    13. records=$(cat $input | wc -l);  
    14. for i in `awk -v n=$records 'BEGIN{for(i=1;i<n;i++) print log(i)/log(2);}'`  
    15. do  
    16.     ((logi+=1));  
    17.     log2[$logi]=$i;  
    18. done  
    19.   
    20.   
    21. ## function for calculating the entropy for the given distribution of the class  
    22. function getEntropy {  
    23.     local input=`echo $1`;  
    24.     if [[ $input == *" "* ]]; then  
    25.         local current_entropy=0;  
    26.         local sum=0;  
    27.         local i;  
    28.         for i in $input  
    29.         do  
    30.             ((sum+=$i));  
    31.             current_entropy=$(awk -v n=$i -v l=${log2[$i]} -v o=$current_entropy 'BEGIN{print n*l+o}');  
    32.         done  
    33.         current_entropy=$(awk -v n=$current_entropy -v b=$sum -v l=${log2[$sum]} 'BEGIN{print n/b*-1+l;}')  
    34.         eval $2=$current_entropy;  
    35.     else  
    36.         eval $2=0;  
    37.     fi  
    38. }  
    39.   
    40.   
    41. ### the header title of the input data  
    42. declare -A header_info;  
    43. header=$(head -1 $input);  
    44. headers=(${header//,/ })  
    45. length=${#headers[@]};  
    46. for((i=0;i<length;i++))  
    47. do  
    48.     attr=${headers[$i]};  
    49.     header_info[$attr]=$i;  
    50. done  
    51.   
    52.   
    53.   
    54. ### the data content of the input data  
    55. data=${input}_dat;  
    56. sed -n '2,$p' $input > $data  
    57.   
    58.   
    59.   
    60. ## use an array to store the information of a descision tree  
    61. ## the node structure is {child,slibling,parent,attr,attr_value,leaf,class}  
    62. ## the root is a virtual node with none used attribute  
    63. ## only the leaf node has class flag and the "leaf,class" is meaningfull  
    64. ## the descision_tree  
    65. declare -a descision_tree;  
    66.   
    67. ## the root node with no child\slibing and anythings else  
    68. descision_tree[0]="0:0:0:N:N:0:0";  
    69.   
    70.   
    71. ## use recursive algrithm to build the tree   
    72. ## so we need a trace_stack to record the call level infomation  
    73. declare -a trace_stack;  
    74.   
    75. ## push the root node into the stack  
    76. trace_stack[0]=0;  
    77. stack_deep=1;  
    78.   
    79. ## begin to build the tree until the trace_stack is empty  
    80. while [ $stack_deep -ne 0 ]  
    81. do  
    82.     ((stack_deep-=1));  
    83.     current_node_index=${trace_stack[$stack_deep]};  
    84.     current_node=${descision_tree[$current_node_index]};  
    85.     current_node_struct=(${current_node//:/ });  
    86.   
    87.     ## select the current data set   
    88.     ## get used attr and their values  
    89.     attrs=${current_node_struct[3]};  
    90.     attrv=${current_node_struct[4]};  
    91.   
    92.     declare -a grepstra=();  
    93.   
    94.     if [ $attrs != "N" ];then  
    95.         attr=(${attrs//,/ });  
    96.         attrvs=(${attrv//,/ });  
    97.         attrc=${#attr[@]};  
    98.         for((i=0;i<attrc;i++))  
    99.         do  
    100.             a=${attr[$i]};  
    101.             index=${header_info[$a]};  
    102.             grepstra[$index]=${attrvs[$i]};  
    103.         done  
    104.     fi  
    105.   
    106.     for((i=0;i<length;i++))  
    107.     do  
    108.         if [ -z ${grepstra[$i]} ]; then  
    109.             grepstra[$i]=".*";  
    110.         fi  
    111.     done  
    112.     grepstrt=${grepstra[*]};  
    113.     grepstr=${grepstrt// /,};  
    114.     grep $grepstr $data > current_node_data  
    115.   
    116.     ## calculate the entropy before split the records  
    117.     entropy=0;  
    118.     input=`cat current_node_data | cut -d "," -f 5 | sort | uniq -c | sed 's/^ \+//g' | cut -d " " -f 1`  
    119.     getEntropy "$input" entropy;  
    120.   
    121.     ## calculate the entropy for each of the rest attrs  
    122.     ## and select the min one  
    123.     min_attr_entropy=1;   
    124.     min_attr_name="";  
    125.     min_attr_index=0;  
    126.     for((i=0;i<length-1;i++))  
    127.     do  
    128.         ## just use the rest attrs  
    129.         if [[ "$attrs" != *"${headers[$i]}"* ]]; then  
    130.             ## calculate the entropy for the current attr  
    131.             ### get the different values for the headers[$i]  
    132.             j=$((i+1));  
    133.             cut -d "," -f $j,$length current_node_data > tmp_attr_ds  
    134.             dist_values=`cut -d , -f 1 tmp_attr_ds | sort | uniq -c | sed 's/^ \+//g' | sed 's/ /,/g'`;  
    135.             totle=0;  
    136.             totle_entropy_attr=0;  
    137.             for k in $dist_values  
    138.             do  
    139.                 info=(${k//,/ });  
    140.                 ((totle+=${info[0]}));  
    141.                 cur_class_input=`grep "^${info[1]}," tmp_attr_ds | cut -d "," -f 2 | sort | uniq -c | sed 's/^ \+//g' | cut -d " " -f 1`  
    142.                 cur_attr_value_entropy=0;  
    143.                 getEntropy "$cur_class_input" cur_attr_value_entropy;  
    144.                 totle_entropy_attr=$(awk -v c=${info[0]} -v e=$cur_attr_value_entropy -v o=$totle_entropy_attr 'BEGIN{print c*e+o;}');  
    145.             done  
    146.             attr_entropy=$(awk -v e=$totle_entropy_attr -v c=$totle 'BEGIN{print e/c;}');  
    147.             if [ $(echo "$attr_entropy < $min_attr_entropy" | bc) = 1 ]; then  
    148.                 min_attr_entropy=$attr_entropy;  
    149.                 min_attr_name="${headers[$i]}";  
    150.                 min_attr_index=$j;  
    151.             fi  
    152.         fi  
    153.     done  
    154.   
    155.     ## calculate the gain between the original entropy of the current node   
    156.     ## and the entropy after split by the attribute which has the min_entropy  
    157.     gain=$(awk -v b=$entropy -v a=$min_attr_entropy 'BEGIN{print b-a;}');  
    158.   
    159.     ## when the gain is large than 0.1 and  then put it as a branch  
    160.     ##      and add the child nodes to the current node and push the index to the trace_stack  
    161.     ## otherwise make it as a leaf node and get the class flag  
    162.     ##      and do not push trace_stack  
    163.     if [ $(echo "$gain > 0.1" | bc)  = 1 ]; then  
    164.         ### get the attribute values  
    165.         attr_values_str=`cut -d , -f $min_attr_index current_node_data | sort | uniq`;  
    166.         attr_values=($attr_values_str);  
    167.   
    168.         ### generate the node and add to the tree and add their index to the trace_stack  
    169.         tree_store_length=${#descision_tree[@]};  
    170.         current_node_struct[0]=$tree_store_length;  
    171.         parent_node_index=$current_node_index;  
    172.          
    173.         attr_value_c=${#attr_values[@]};  
    174.         for((i=0;i<attr_value_c;i++))  
    175.         do  
    176.             tree_store_length=${#descision_tree[@]};  
    177.             slibling=0;  
    178.             if [ $i -lt $((attr_value_c-1)) ]; then  
    179.                 slibling=$((tree_store_length+1));  
    180.             fi  
    181.   
    182.             new_attr="";  
    183.             new_attrvalue="";  
    184.             if [ $attrs != "N" ]; then  
    185.                 new_attr="$attrs,$min_attr_name";  
    186.                 new_attrvalue="$attrv,${attr_values[$i]}";  
    187.             else  
    188.                 new_attr="$min_attr_name";  
    189.                 new_attrvalue="${attr_values[$i]}";  
    190.             fi  
    191.             new_node="0:$slibling:$parent_node_index:$new_attr:$new_attr_value:0:0";  
    192.             descision_tree[$tree_store_length]="$new_node";  
    193.             trace_stack[$stack_deep]=$tree_store_length;  
    194.             ((stack_deep+=1));  
    195.         done  
    196.         current_node_update=${current_node_struct[*]};  
    197.         descision_tree[$current_node_index]=${current_node_update// /:};  
    198.     else   ## current node is a leaf node   
    199.         current_node_struct[5]=1;  
    200.         current_node_struct[6]=`cut -d , -f $length current_node_data | sort | uniq -c | sort -n -r | head -1 | sed 's/^ \+[^ ]* //g'`;  
    201.         current_node_update=${current_node_struct[*]};  
    202.         descision_tree[$current_node_index]=${current_node_update// /:};  
    203.     fi   
    204.       
    205.     ## output the descision tree after every step for split or leaf node generater  
    206.     echo ${descision_tree[@]};  
    207. done  
     

    執行代碼:

     

    Bash代碼  收藏代碼
    1. ./descision.sh descision.dat  

     執行結果為:

     

    Java代碼  收藏代碼
    1. 1:0:0:N:N:0:0 0:2:0:house:0:0:0 0:0:0:house:1:0:0  
    2. 1:0:0:N:N:0:0 0:2:0:house:0:0:0 0:0:0:house:1:1:1  
    3. 1:0:0:N:N:0:0 3:2:0:house:0:0:0 0:0:0:house:1:1:1 0:4:1:house,job:0,0:0:0 0:0:1:house,job:0,1:0:0  
    4. 1:0:0:N:N:0:0 3:2:0:house:0:0:0 0:0:0:house:1:1:1 0:4:1:house,job:0,0:0:0 0:0:1:house,job:0,1:1:1  
    5. 1:0:0:N:N:0:0 3:2:0:house:0:0:0 0:0:0:house:1:1:1 0:4:1:house,job:0,0:1:0 0:0:1:house,job:0,1:1:1  

    輸出結果中展示了決策樹結構生成過程的細節,以及生成過程中樹的變化過程

     

    本代碼中使用了一維數組結構來存儲整棵決策樹,輸出的先后順序按照數組下標輸出。

     

    輸出結果中最后一行表示最終的決策樹。它表示的樹形結構其實是:

     

    決策樹結果

    這樣看著是不是就爽多了。

     

    說明:

    關于上述決策樹結果中其實有部分存在誤導:

    默認根節點是放在數組的第一個位置的,即索引值為0,而子節點中的child與sibling為0時并不表示指向跟節點,而是表示無意義,即沒有子節點或兄弟節點。

     

    該決策樹所代表的分類規則:

    根據該決策樹輸出,我們挖掘的規則是這樣的:

    首先根據house屬性判斷,當house屬性為1時,走到索引為2的節點,此時該節點是葉子節點,預測值class為1.

    當house屬性為0時,接著按照job屬性來判斷,當job屬性為0時走到索引為3的節點,預測值class為0。如果job屬性為1時走到索引值為4的節點,此時預測值class為1.

    posted on 2012-07-21 22:21 往事隨風 閱讀(1293) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 免费精品国产自产拍观看| 亚洲av无码国产精品色午夜字幕 | 高潮毛片无遮挡高清免费| 久久精品国产亚洲7777| 未满十八18禁止免费无码网站| 亚洲AV无码专区国产乱码不卡| 全部免费a级毛片| 国产免费高清69式视频在线观看| 国产妇乱子伦视频免费| 欧美亚洲国产SUV| 亚洲五月激情综合图片区| 无码人妻一区二区三区免费手机 | 国产亚洲精品资源在线26u| av无码久久久久不卡免费网站| 一级毛片a免费播放王色电影| 亚洲日本中文字幕| 午夜亚洲福利在线老司机| 18禁免费无码无遮挡不卡网站| 一区在线免费观看| 亚洲日本va午夜中文字幕久久| www.免费在线观看| 99久久免费国产精品热| 亚洲性无码一区二区三区| 亚洲国产成人私人影院| 亚洲成aⅴ人片久青草影院| 99在线精品免费视频九九视| 99热在线日韩精品免费| 亚洲AV无码精品国产成人| 久久丫精品国产亚洲av| 黄页网站在线看免费| 日本高清不卡aⅴ免费网站| 国内成人精品亚洲日本语音| 亚洲人成网站日本片| 成年大片免费视频| 国产亚洲精品国产福利在线观看| 亚洲综合男人的天堂色婷婷| 亚洲人成中文字幕在线观看| 亚洲Av无码乱码在线观看性色 | 欧洲一级毛片免费| 两个人看的www免费高清| 边摸边脱吃奶边高潮视频免费|