日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用决策树实现分类

發(fā)布時(shí)間:2023/12/16 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用决策树实现分类 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載請(qǐng)注明出處:

http://blog.csdn.net/gane_cheng/article/details/53897669

http://www.ganecheng.tech/blog/53897669.html (瀏覽效果更好)

決策樹是一種樹形結(jié)構(gòu),為人們提供決策依據(jù),決策樹可以用來回答yes和no問題,它通過樹形結(jié)構(gòu)將各種情況組合都表示出來,每個(gè)分支表示一次選擇(選擇yes還是no),直到所有選擇都進(jìn)行完畢,最終給出正確答案。

本文介紹決策樹如何來實(shí)現(xiàn)分類,并用來預(yù)測結(jié)果。

先拋出問題?,F(xiàn)在統(tǒng)計(jì)了14天的氣象數(shù)據(jù)(指標(biāo)包括outlook,temperature,humidity,windy),并已知這些天氣是否打球(play)。如果給出新一天的氣象指標(biāo)數(shù)據(jù):sunny,cool,high,TRUE,判斷一下會(huì)不會(huì)去打球。

outlooktemperaturehumiditywindyplay
sunnyhothighFALSEno
sunnyhothighTRUEno
overcasthothighFALSEyes
rainymildhighFALSEyes
rainycoolnormalFALSEyes
rainycoolnormalTRUEno
overcastcoolnormalTRUEyes
sunnymildhighFALSEno
sunnycoolnormalFALSEyes
rainymildnormalFALSEyes
sunnymildnormalTRUEyes
overcastmildhighTRUEyes
overcasthotnormalFALSEyes
rainymildhighTRUEno

現(xiàn)在,我們想讓所有輸入情況可以更快的得到答案。也就是要求平均查找時(shí)間更短。當(dāng)一堆數(shù)據(jù)區(qū)分度越高的話,比較的次數(shù)就會(huì)更少一些,也就可以更快的得到答案。

下面介紹一些概念來描述這個(gè)問題。

概念簡介

決策樹

決策樹是一種樹形結(jié)構(gòu),其中每個(gè)內(nèi)部節(jié)點(diǎn)表示一個(gè)屬性上的測試,每個(gè)分支代表一個(gè)測試輸出,每個(gè)葉節(jié)點(diǎn)代表一種類別。

決策樹是一種十分常用的分類方法。他是一種監(jiān)管學(xué)習(xí),所謂監(jiān)管學(xué)習(xí)就是給定一堆樣本,每個(gè)樣本都有一組屬性和一個(gè)類別,這些類別是事先確定的,那么通過學(xué)習(xí)得到一個(gè)分類器,這個(gè)分類器能夠?qū)π鲁霈F(xiàn)的對(duì)象給出正確的分類。這樣的機(jī)器學(xué)習(xí)就被稱之為監(jiān)督學(xué)習(xí)

香農(nóng)熵

香農(nóng)熵(entropy),簡稱熵,由美國數(shù)學(xué)家、信息論的創(chuàng)始人香農(nóng)提出。用來定量表示信息的聚合程度,是信息的期望值。

劃分?jǐn)?shù)據(jù)集的大原則是:將無序的數(shù)據(jù)變得更加有序。自然界各種物體已經(jīng)在我們基礎(chǔ)教育,高等教育中被學(xué)到。世界本來是充滿各種雜亂信息的,但是被人類不停地認(rèn)識(shí)到,認(rèn)識(shí)的過程還是循序漸進(jìn)的。原本雜亂的信息卻被我們系統(tǒng)地組織起來了,這就要?dú)w功于分類了。

學(xué)語文時(shí),我們學(xué)習(xí)白話文,文言文,詩歌,唐詩,宋詞,散文,雜文,小說,等等。
學(xué)數(shù)學(xué)時(shí),加減乘除,指數(shù),對(duì)數(shù),方程,幾何,微積分,概率論,圖論,線性,離散,等等。
學(xué)英語時(shí),名詞,動(dòng)詞,形容詞,副詞,口語,語法,時(shí)態(tài),等等。
學(xué)歷史時(shí),中國史,世界史,原始社會(huì),奴隸社會(huì),封建社會(huì),現(xiàn)代社會(huì),等等。

分類分的越好,我們理解,掌握起來就會(huì)更輕松。并且一個(gè)新事物出現(xiàn),我們可以基于已經(jīng)學(xué)習(xí)到的經(jīng)驗(yàn)預(yù)測到它大概是什么。

熵就是用來描述信息的這種確定與不確定狀態(tài)的,信息越混亂,熵越大,信息分類越清晰,熵越小。

我們來看一個(gè)例子,馬上要舉行世界杯賽了。大家都很關(guān)心誰會(huì)是冠軍。假如我錯(cuò)過了看世界杯,賽后我問一個(gè)知道比賽結(jié)果的觀眾“哪支球隊(duì)是冠軍”? 他不愿意直接告訴我, 而要讓我猜,并且我每猜一次,他要收一元錢才肯告訴我是否猜對(duì)了,那么我需要付給他多少錢才能知道誰是冠軍呢? 我可以把球隊(duì)編上號(hào),從 1 到 32, 然后提問: “冠軍的球隊(duì)在 1-16 號(hào)中嗎?” 假如他告訴我猜對(duì)了, 我會(huì)接著問: “冠軍在 1-8 號(hào)中嗎?” 假如他告訴我猜錯(cuò)了, 我自然知道冠軍隊(duì)在 9-16 中。 這樣最多只需要五次, 我就能知道哪支球隊(duì)是冠軍。所以,誰是世界杯冠軍這條消息的信息量只值五塊錢。(球隊(duì)第一種分類方式)

我們實(shí)際上可能不需要猜五次就能猜出誰是冠軍,因?yàn)橄蟀臀?、德國、意大利這樣的球隊(duì)得冠軍的可能性比日本、美國、韓國等隊(duì)大的多。因此,我們第一次猜測時(shí)不需要把 32 個(gè)球隊(duì)等分成兩個(gè)組,而可以把少數(shù)幾個(gè)最可能的球隊(duì)分成一組,把其它隊(duì)分成另一組。然后我們猜冠軍球隊(duì)是否在那幾只熱門隊(duì)中。我們重復(fù)這樣的過程,根據(jù)奪冠概率對(duì)剩下的候選球隊(duì)分組,直到找到冠軍隊(duì)。這樣,我們也許三次或四次就猜出結(jié)果。因此,當(dāng)每個(gè)球隊(duì)奪冠的可能性(概率)不等時(shí),“誰世界杯冠軍”的信息量的信息量比五比特少。(球隊(duì)第二種分類方式)

熵定義為信息的期望值。求得熵,需要先知道信息的定義。如果待分類的事務(wù)可能劃分在多個(gè)分類之中,則信息定義為

l(xi)=?log2p(xi)(1)

其中,xi 表示第 i 個(gè)分類,p(xi) 表示選擇第 i 個(gè)分類的概率。

假如有變量X,其可能的分類有n種,熵,可以通過下面的公式得到:

H(X)=?i=1np(xi)log2p(xi)(2)

其中,n 表示分類的數(shù)量。

以上面球隊(duì)為例,第一種分類的話,所得球隊(duì)的熵為:

H=?i=1np(xi)log2p(xi)=?(132log2132)×32=?log2132=?log232?1=log232=5()

如果是按第二種方式分類的話,假如,每個(gè)隊(duì)得冠軍的概率是這樣的。

球隊(duì)分類獲勝概率
中國強(qiáng)隊(duì)18%
巴西強(qiáng)隊(duì)18%
德國強(qiáng)隊(duì)18%
意大利炮強(qiáng)隊(duì)18%
剩下的28只球隊(duì)每隊(duì)獲勝概率都為1%弱隊(duì)1%

現(xiàn)在分成了兩個(gè)隊(duì)強(qiáng)隊(duì)和弱隊(duì),需要分別計(jì)算兩隊(duì)的熵,然后再計(jì)算總的熵。

強(qiáng)隊(duì)的熵為:

H=?i=1np(xi)log2p(xi)=?(14log214)×4=?log214=?log24?1=log24=2()

弱隊(duì)的熵為:

H=?i=1np(xi)log2p(xi)=?(128log2128)×28=?log2128=?log228?1=log2284.8()

所得球隊(duì)的總的熵為:

H=0.72×2+0.28×4.82.784()

可以看到,如果我們按照強(qiáng)弱隊(duì)的方式來分類,然后再猜的話,平均只需要2.8次就可以猜出冠軍球隊(duì)。

信息增益

信息增益(information gain) 指的是劃分?jǐn)?shù)據(jù)集前后信息發(fā)生的變化。

在信息增益中,衡量標(biāo)準(zhǔn)是看特征能夠?yàn)榉诸愊到y(tǒng)帶來多少信息,帶來的信息越多,該特征越重要。對(duì)一個(gè)特征而言,系統(tǒng)有它和沒它時(shí)信息量將發(fā)生變化,而前后信息量的差值就是這個(gè)特征給系統(tǒng)帶來的信息量。所謂信息量,就是熵。

特征T給聚類C或分類C帶來的信息增益可以定義為

IG(T)=H(C)?H(C|T)(3)

其中,IG(T) 表示特征 T 帶來的信息增益,H(C) 表示未使用特征 T 時(shí)的熵,H(C|T) 表示使用特征 T 時(shí)的熵。并且 H(C) 一定會(huì)大于等于 H(C|T) 。

例如,上面的球隊(duì)按第一種分類得到的熵為 5,第二種分類得到的熵為 2.8,則強(qiáng)弱隊(duì)這個(gè)特征為 32 只球隊(duì)帶來的信息增益則為:5-2.8=2.2 。

信息增益最大的問題在于它只能考察特征對(duì)整個(gè)系統(tǒng)的貢獻(xiàn),而不能具體到某個(gè)類別上,這就使得它只適合用來做所謂“全局”的特征選擇。

一個(gè)特征帶來的信息增益越大,越適合用來做分類的特征。

構(gòu)造決策樹

ID3 算法

構(gòu)造樹的基本想法是隨著樹深度的增加,節(jié)點(diǎn)的熵迅速地降低。熵降低的速度越快越好(即信息增益越大越好),這樣我們有望得到一棵高度最矮的決策樹。

好,現(xiàn)在用此算法來分析天氣的例子。

在沒有使用任何特征情況下。根據(jù)歷史數(shù)據(jù),我們只知道新的一天打球的概率是9/14,不打的概率是5/14。此時(shí)的熵為:

H=?i=1np(xi)log2p(xi)=?(514log2514+914log2914)?(0.357×(?1.486)+0.643×(?0.637))0.940

如果按照每個(gè)特征分類的話。屬性有4個(gè):outlook,temperature,humidity,windy。我們首先要決定哪個(gè)屬性作樹的根節(jié)點(diǎn)。

對(duì)每項(xiàng)指標(biāo)分別統(tǒng)計(jì):在不同的取值下打球和不打球的次數(shù)。

outlookyesno
sunny23
overcast40
rainy32

H(sunny)=?i=1np(xi)log2p(xi)=?(25log225+35log235)0.971

H(overcast)=?i=1np(xi)log2p(xi)=?(log21)=0

H(rainy)=?i=1np(xi)log2p(xi)=?(35log235+25log225)0.971

因此如果用特征outlook來分類的話,總的熵為

H(outlook)=514×0.971+0+514×0.9710.714×0.9710.694

然后,求得特征outlook獲得的信息增益。

IG(outlook)=0.940?0.694=0.246(outlook)

用同樣的方法,可以分別求出temperature,humidity,windy的信息增益。IG(temperature)=0.029,IG(humidity)=0.152,IG(windy)=0.048。

因?yàn)?IG(outlook)>IG(humidity)>IG(windy)>IG(temperature)。所以根節(jié)點(diǎn)應(yīng)該選擇outlook特征來進(jìn)行分類。

接下來要繼續(xù)判斷取temperature、humidity還是windy?在已知outlook=sunny的情況,根據(jù)歷史數(shù)據(jù),分別計(jì)算IG(temperature)、IG(humidity)和IG(windy),選最大者為特征。

依此類推,構(gòu)造決策樹。當(dāng)系統(tǒng)的信息熵降為0時(shí),就沒有必要再往下構(gòu)造決策樹了,此時(shí)葉子節(jié)點(diǎn)都是純的–這是理想情況。最壞的情況下,決策樹的高度為屬性(決策變量)的個(gè)數(shù),葉子節(jié)點(diǎn)不純(這意味著我們要以一定的概率來作出決策,一般采用多數(shù)表決的方式確定此葉子節(jié)點(diǎn))。

構(gòu)造決策樹的一般過程

  • 手機(jī)數(shù)據(jù):可以使用任何方法。
  • 準(zhǔn)備數(shù)據(jù):樹構(gòu)造算法只適用于標(biāo)稱型數(shù)據(jù),因此數(shù)值型數(shù)據(jù)必須離散化。
  • 分析數(shù)據(jù):可以使用任何方法,構(gòu)造樹完成之后,我們應(yīng)該檢查圖形是否符合預(yù)期。
  • 訓(xùn)練算法:構(gòu)造樹的數(shù)據(jù)結(jié)構(gòu)。
  • 測試算法:使用經(jīng)驗(yàn)樹計(jì)算錯(cuò)誤率。
  • 使用算法:此步驟可以適用于任何監(jiān)督學(xué)習(xí)算法,而使用決策樹可以更好地理解數(shù)據(jù)的內(nèi)在含義。
  • Java實(shí)現(xiàn)

    定義數(shù)據(jù)結(jié)構(gòu)

    根據(jù)決策樹的形狀,我將決策樹的數(shù)據(jù)結(jié)構(gòu)定義如下。lastFeatureValue表示經(jīng)過某個(gè)特征值的篩選到達(dá)的節(jié)點(diǎn),featureName表示答案或者信息增益最大的特征。childrenNodeList表示經(jīng)過這個(gè)特征的若干個(gè)值分類后得到的幾個(gè)節(jié)點(diǎn)。

    public class Node {/*** 到達(dá)此節(jié)點(diǎn)的特征值*/public String lastFeatureValue;/*** 此節(jié)點(diǎn)的特征名稱或答案*/public String featureName;/*** 此節(jié)點(diǎn)的分類子節(jié)點(diǎn)*/public List<Node> childrenNodeList = new ArrayList<Node>(); }

    定義輸入數(shù)據(jù)格式

    文章最開始拋出的問題中的數(shù)據(jù)的輸入格式是這樣的。

    @feature outlook,temperature,humidity,windy,play@data sunny,hot,high,FALSE,no sunny,hot,high,TRUE,no overcast,hot,high,FALSE,yes rainy,mild,high,FALSE,yes rainy,cool,normal,FALSE,yes rainy,cool,normal,TRUE,no overcast,cool,normal,TRUE,yes sunny,mild,high,FALSE,no sunny,cool,normal,FALSE,yes rainy,mild,normal,FALSE,yes sunny,mild,normal,TRUE,yes overcast,mild,high,TRUE,yes overcast,hot,normal,FALSE,yes rainy,mild,high,TRUE,no

    存儲(chǔ)輸入數(shù)據(jù)

    在代碼中,特征和特征值用List來存儲(chǔ),數(shù)據(jù)用Map來存儲(chǔ)。

    //特征列表public static List<String> featureList = new ArrayList<String>();// 特征值列表public static List<List<String>> featureValueTableList = new ArrayList<List<String>>();//得到全局?jǐn)?shù)據(jù)public static Map<Integer, List<String>> tableMap = new HashMap<Integer, List<String>>();

    初始化輸入數(shù)據(jù)

    對(duì)輸入數(shù)據(jù)進(jìn)行初始化。

    /*** 初始化數(shù)據(jù)* * @param file*/public static void readOriginalData(File file){int index = 0;try{FileReader fr = new FileReader(file);BufferedReader br = new BufferedReader(fr);String line;while ((line = br.readLine()) != null){// 得到特征名稱if (line.startsWith("@feature")){line = br.readLine();String[] row = line.split(",");for (String s : row){featureList.add(s.trim());}}else if (line.startsWith("@data")){while ((line = br.readLine()) != null){if (line.equals("")){continue;}String[] row = line.split(",");if (row.length != featureList.size()){throw new Exception("列表數(shù)據(jù)和特征數(shù)目不一致");}List<String> tempList = new ArrayList<String>();for (String s : row){if (s.trim().equals("")){throw new Exception("列表數(shù)據(jù)不能為空");}tempList.add(s.trim());}tableMap.put(index++, tempList);}// 遍歷tableMap得到屬性值列表Map<Integer, Set<String>> valueSetMap = new HashMap<Integer, Set<String>>();for (int i = 0; i < featureList.size(); i++){valueSetMap.put(i, new HashSet<String>());}for (Map.Entry<Integer, List<String>> entry : tableMap.entrySet()){List<String> dataList = entry.getValue();for (int i = 0; i < dataList.size(); i++){valueSetMap.get(i).add(dataList.get(i));}}for (Map.Entry<Integer, Set<String>> entry : valueSetMap.entrySet()){List<String> valueList = new ArrayList<String>();for (String s : entry.getValue()){valueList.add(s);}featureValueTableList.add(valueList);}}else{continue;}}br.close();}catch (IOException e1){e1.printStackTrace();}catch (Exception e){e.printStackTrace();}}

    計(jì)算給定數(shù)據(jù)集的香農(nóng)熵

    /*** 計(jì)算熵* * @param dataSetList* @return*/public static double calculateEntropy(List<Integer> dataSetList){if (dataSetList == null || dataSetList.size() <= 0){return 0;}// 得到結(jié)果int resultIndex = tableMap.get(dataSetList.get(0)).size() - 1;Map<String, Integer> valueMap = new HashMap<String, Integer>();for (Integer id : dataSetList){String value = tableMap.get(id).get(resultIndex);Integer num = valueMap.get(value);if (num == null || num == 0){num = 0;}valueMap.put(value, num + 1);}double entropy = 0;for (Map.Entry<String, Integer> entry : valueMap.entrySet()){double prob = entry.getValue() * 1.0 / dataSetList.size();entropy -= prob * Math.log10(prob) / Math.log10(2);}return entropy;}

    按照給定特征劃分?jǐn)?shù)據(jù)集

    /*** 對(duì)一個(gè)數(shù)據(jù)集進(jìn)行劃分* * @param dataSetList* 待劃分的數(shù)據(jù)集* @param featureIndex* 第幾個(gè)特征(特征下標(biāo),從0開始)* @param value* 得到某個(gè)特征值的數(shù)據(jù)集* @return*/public static List<Integer> splitDataSet(List<Integer> dataSetList, int featureIndex, String value){List<Integer> resultList = new ArrayList<Integer>();for (Integer id : dataSetList){if (tableMap.get(id).get(featureIndex).equals(value)){resultList.add(id);}}return resultList;}

    選擇最好的數(shù)據(jù)集劃分方式

    /*** 在指定的幾個(gè)特征中選擇一個(gè)最佳特征(信息增益最大)用于劃分?jǐn)?shù)據(jù)集* * @param dataSetList* @return 返回最佳特征的下標(biāo)*/public static int chooseBestFeatureToSplit(List<Integer> dataSetList, List<Integer> featureIndexList){double baseEntropy = calculateEntropy(dataSetList);double bestInformationGain = 0;int bestFeature = -1;// 循環(huán)遍歷所有特征for (int temp = 0; temp < featureIndexList.size() - 1; temp++){int i = featureIndexList.get(temp);// 得到特征集合List<String> featureValueList = new ArrayList<String>();for (Integer id : dataSetList){String value = tableMap.get(id).get(i);featureValueList.add(value);}Set<String> featureValueSet = new HashSet<String>();featureValueSet.addAll(featureValueList);// 得到此分類下的熵double newEntropy = 0;for (String featureValue : featureValueSet){List<Integer> subDataSetList = splitDataSet(dataSetList, i, featureValue);double probability = subDataSetList.size() * 1.0 / dataSetList.size();newEntropy += probability * calculateEntropy(subDataSetList);}// 得到信息增益double informationGain = baseEntropy - newEntropy;// 得到信息增益最大的特征下標(biāo)if (informationGain > bestInformationGain){bestInformationGain = informationGain;bestFeature = temp;}}return bestFeature;}

    多數(shù)表決不確定結(jié)果

    如果所有屬性都劃分完了,答案還沒確定,需要通過多數(shù)表決的方式得到答案。

    /*** 多數(shù)表決得到出現(xiàn)次數(shù)最多的那個(gè)值* * @param dataSetList* @return*/public static String majorityVote(List<Integer> dataSetList){// 得到結(jié)果int resultIndex = tableMap.get(dataSetList.get(0)).size() - 1;Map<String, Integer> valueMap = new HashMap<String, Integer>();for (Integer id : dataSetList){String value = tableMap.get(id).get(resultIndex);Integer num = valueMap.get(value);if (num == null || num == 0){num = 0;}valueMap.put(value, num + 1);}int maxNum = 0;String value = "";for (Map.Entry<String, Integer> entry : valueMap.entrySet()){if (entry.getValue() > maxNum){maxNum = entry.getValue();value = entry.getKey();}}return value;}

    創(chuàng)建決策樹

    /*** 創(chuàng)建決策樹* * @param dataSetList* 數(shù)據(jù)集* @param featureIndexList* 可用的特征列表* @param lastFeatureValue* 到達(dá)此節(jié)點(diǎn)的上一個(gè)特征值* @return*/public static Node createDecisionTree(List<Integer> dataSetList, List<Integer> featureIndexList, String lastFeatureValue){// 如果只有一個(gè)值的話,則直接返回葉子節(jié)點(diǎn)int valueIndex = featureIndexList.get(featureIndexList.size() - 1);// 選擇第一個(gè)值String firstValue = tableMap.get(dataSetList.get(0)).get(valueIndex);int firstValueNum = 0;for (Integer id : dataSetList){if (firstValue.equals(tableMap.get(id).get(valueIndex))){firstValueNum++;}}if (firstValueNum == dataSetList.size()){Node node = new Node();node.lastFeatureValue = lastFeatureValue;node.featureName = firstValue;node.childrenNodeList = null;return node;}// 遍歷完所有特征時(shí)特征值還沒有完全相同,返回多數(shù)表決的結(jié)果if (featureIndexList.size() == 1){Node node = new Node();node.lastFeatureValue = lastFeatureValue;node.featureName = majorityVote(dataSetList);node.childrenNodeList = null;return node;}// 獲得信息增益最大的特征int bestFeatureIndex = chooseBestFeatureToSplit(dataSetList, featureIndexList);// 得到此特征在全局的下標(biāo)int realFeatureIndex = featureIndexList.get(bestFeatureIndex);String bestFeatureName = featureList.get(realFeatureIndex);// 構(gòu)造決策樹Node node = new Node();node.lastFeatureValue = lastFeatureValue;node.featureName = bestFeatureName;// 得到所有特征值的集合List<String> featureValueList = featureValueTableList.get(realFeatureIndex);// 刪除此特征featureIndexList.remove(bestFeatureIndex);// 遍歷特征所有值,劃分?jǐn)?shù)據(jù)集,然后遞歸得到子節(jié)點(diǎn)for (String fv : featureValueList){// 得到子數(shù)據(jù)集List<Integer> subDataSetList = splitDataSet(dataSetList, realFeatureIndex, fv);// 如果子數(shù)據(jù)集為空,則使用多數(shù)表決給一個(gè)答案。if (subDataSetList == null || subDataSetList.size() <= 0){Node childNode = new Node();childNode.lastFeatureValue = fv;childNode.featureName = majorityVote(dataSetList);childNode.childrenNodeList = null;node.childrenNodeList.add(childNode);break;}// 添加子節(jié)點(diǎn)Node childNode = createDecisionTree(subDataSetList, featureIndexList, fv);node.childrenNodeList.add(childNode);}return node;}

    使用決策樹對(duì)測試數(shù)據(jù)進(jìn)行預(yù)測

    /*** 輸入測試數(shù)據(jù)得到?jīng)Q策樹的預(yù)測結(jié)果* @param decisionTree 決策樹* @param featureList 特征列表* @param testDataList 測試數(shù)據(jù)* @return*/public static String getDTAnswer(Node decisionTree, List<String> featureList, List<String> testDataList){if (featureList.size() - 1 != testDataList.size()){System.out.println("輸入數(shù)據(jù)不完整");return "ERROR";}while (decisionTree != null){// 如果孩子節(jié)點(diǎn)為空,則返回此節(jié)點(diǎn)答案.if (decisionTree.childrenNodeList == null || decisionTree.childrenNodeList.size() <= 0){return decisionTree.featureName;}// 孩子節(jié)點(diǎn)不為空,則判斷特征值找到子節(jié)點(diǎn)for (int i = 0; i < featureList.size() - 1; i++){// 找到當(dāng)前特征下標(biāo)if (featureList.get(i).equals(decisionTree.featureName)){// 得到測試數(shù)據(jù)特征值String featureValue = testDataList.get(i);// 在子節(jié)點(diǎn)中找到含有此特征值的節(jié)點(diǎn)Node childNode = null;for (Node cn : decisionTree.childrenNodeList){if (cn.lastFeatureValue.equals(featureValue)){childNode = cn;break;}}// 如果沒有找到此節(jié)點(diǎn),則說明訓(xùn)練集中沒有到這個(gè)節(jié)點(diǎn)的特征值if (childNode == null){System.out.println("沒有找到此特征值的數(shù)據(jù)");return "ERROR";}decisionTree = childNode;break;}}}return "ERROR";}

    測試結(jié)果

    構(gòu)建的決策樹輸出是這樣的。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Node><featureName>outlook</featureName><childrenNodeList><lastFeatureValue>rainy</lastFeatureValue><featureName>windy</featureName><childrenNodeList><lastFeatureValue>FALSE</lastFeatureValue><featureName>yes</featureName></childrenNodeList><childrenNodeList><lastFeatureValue>TRUE</lastFeatureValue><featureName>no</featureName></childrenNodeList></childrenNodeList><childrenNodeList><lastFeatureValue>sunny</lastFeatureValue><featureName>humidity</featureName><childrenNodeList><lastFeatureValue>normal</lastFeatureValue><featureName>yes</featureName></childrenNodeList><childrenNodeList><lastFeatureValue>high</lastFeatureValue><featureName>no</featureName></childrenNodeList></childrenNodeList><childrenNodeList><lastFeatureValue>overcast</lastFeatureValue><featureName>yes</featureName></childrenNodeList> </Node>

    轉(zhuǎn)換成圖是這樣的。

    此時(shí)輸入數(shù)據(jù)進(jìn)行測試。

    rainy,cool,high,TRUE

    得到結(jié)果為:

    判斷結(jié)果:no

    與圖中結(jié)果一致。

    源碼下載

    本文實(shí)現(xiàn)代碼可以從這里下載。

    http://download.csdn.net/detail/gane_cheng/9724922

    GitHub地址在這兒。

    https://github.com/ganecheng/DecisionTree

    決策樹的優(yōu)缺點(diǎn)

    優(yōu)點(diǎn)

    計(jì)算復(fù)雜度不高,輸出結(jié)果易于理解,對(duì)中間值的缺失不敏感,可以處理不相關(guān)特征數(shù)據(jù)。

    缺點(diǎn)

    可能會(huì)產(chǎn)生過度匹配問題。

    當(dāng)特征和特征值過多時(shí),這些匹配選項(xiàng)可能太多了,我們將這種問題稱之為過度匹配(overfitting)。為了減少過度匹配問題,我們可以裁剪決策樹,去掉一些不必要的葉子節(jié)點(diǎn)。如果葉子節(jié)點(diǎn)只能增加少許信息,則可以刪除該結(jié)點(diǎn),將它并入到其他葉子節(jié)點(diǎn)中去。

    另外,對(duì)于標(biāo)稱型數(shù)據(jù) 字符串還比較好說,對(duì)于數(shù)值型數(shù)據(jù)卻無法直接處理,雖然可以將數(shù)值型數(shù)據(jù)劃分區(qū)間轉(zhuǎn)化為標(biāo)稱型數(shù)據(jù),但是如果有很多特征都是數(shù)值型數(shù)據(jù),還是會(huì)比較麻煩。

    參考文獻(xiàn)

    《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》(Machine Learning in Action),Peter Harrington著,人民郵電出版社。

    http://www.99cankao.com/numbers/log-antilog.php

    http://www.cnblogs.com/zhangchaoyang/articles/2196631.html

    http://baike.baidu.com/item/%E9%A6%99%E5%86%9C%E7%86%B5

    http://www.cnblogs.com/bourneli/archive/2013/03/15/2961568.html

    http://www.cnblogs.com/leoo2sk/archive/2010/09/19/decision-tree.html

    總結(jié)

    以上是生活随笔為你收集整理的使用决策树实现分类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。