1. 程式人生 > >離散型與連續型資料決策樹構建及列印實現 R語言,ID3,C4.5演算法

離散型與連續型資料決策樹構建及列印實現 R語言,ID3,C4.5演算法

本人的第一篇文章,趁著我們的資料探勘課設的時間,把實現的決策樹程式碼,拿出來分享下。有很多漏洞和缺陷,還有很多駭客思想的成分,但是總之,能實現,看網上的程式碼,能用的其實也沒幾個。廢話不多說,直接看程式碼

特別鳴謝博主skyonefly的程式碼
附上鍊接:R語言決策樹程式碼

#####
#####   C4.5演算法實現決策樹
#####



#############################################Part1 基礎函式#######################################################

#計算夏農熵
calShannonEnt <- function
(dataSet,labels)
{ numEntries<-length(dataSet[,labels]) key<-rep("a",numEntries) for(i in 1:numEntries) key[i]<-dataSet[i,labels] shannonEnt<-0 prob<-table(key)/numEntries for(i in 1:length(prob)) shannonEnt=shannonEnt-prob[i]*log(prob[i],2) return(shannonEnt) } #劃分資料集 splitDataSet <- function
(dataSet,axis,value,tempSet = dataSet)
{ retDataSet = NULL for(i in 1:nrow(dataSet)){ if(dataSet[i,axis] == value){ tempDataSet = tempSet[i,] retDataSet = rbind(retDataSet,tempDataSet) } } rownames(retDataSet) = NULL return (retDataSet) } #選擇資訊增益最大的內部節點 chooseBestFeatureToSplita <- function
(dataSet,labels, bestInfoGain)
{ numFeatures = ncol(dataSet) - 1 baseEntropy = calShannonEnt(dataSet,labels) #最大資訊增益 bestFeature = -1 for(i in 1: numFeatures){ featureLabels = levels(factor(dataSet[,i])) # featureLabels = as.numeric(featureLabels) newEntropy = 0.0 SplitInfo = 0.0 for( j in 1:length(featureLabels)){ subDataSet = splitDataSet(dataSet,i,featureLabels[j]) prob = length(subDataSet[,1])*1.0/nrow(dataSet) newEntropy = newEntropy + prob*calShannonEnt(subDataSet,labels) SplitInfo = -prob*log2(prob) + SplitInfo } infoGain = baseEntropy - newEntropy GainRadio = infoGain/SplitInfo if(SplitInfo > 0){ GainRadio = infoGain/SplitInfo if(GainRadio > bestInfoGain){ bestInfoGain = infoGain bestFeature = i } } } return (bestFeature) } #返回頻數最高的列標籤 majorityCnt <- function(classList){ classCount = NULL count = as.numeric(table(classList)) majorityList = levels(as.factor(classList)) if(length(count) == 1){ return (majorityList[1]) }else{ f = max(count) return (majorityList[which(count == f)][1]) } } #判斷類標籤是否只有一個因子水平 oneValue <- function(classList){ count = as.numeric(table(classList)) if(length(count) == 1){ return (TRUE) }else return (FALSE) } #樹的列印 printTree <- function(tree){ df <- data.frame() col <- 1 point <- c() count <- 0 for(i in 1:length(tree)){ if(rownames(tree)[[i]] == 'labelFeature'){ df[i,col] = tree[[i]] col = col + 1 count = count + 1 point[count] = col names(point)[count] = tree[[i]] }else if(rownames(tree)[[i]] == 'FeatureValue'){ for(j in 1:length(point)){ len = grep(names(point)[j],tree[[i]]) if(length(len) >= 1){ col = point[j] } } df[i,col] = tree[[i]] col = col + 1 }else{ df[i,col] = tree[[i]] col = col + 1 } } for(i in 1:nrow(df)){ for(j in 1:ncol(df)){ if(is.na(df[i,j])){ df[i,j] = "" } } } return(df) } numericCol <- NULL #載入資料 load <- function(filePath){ dataSet<-read.table(filePath,header = T) dataSet = dataSet[,-1] numericCol <<- c() for(i in 1:length(ncol(dataSet))){ if(is.numeric(dataSet[,i])){ numericCol[i] <<- colnames(dataSet)[i] } } dataSet = as.matrix(dataSet) trainSet = dataSet[1:14,] testSet = dataSet[15:21,] preSet = dataSet[22,,drop=FALSE] result = list(trainSet,testSet,preSet) return (result) } #############################################Part2 連續值處理##################################################### #將資料集全部轉換成離散型 toDiscrete <- function(numericCol,dataSet,labels){ s <- c() if(length(numericCol)>0){ for(i in 1:length(numericCol)){ if(numericCol[i] %in% colnames(dataSet)){ atr = dataSet[,numericCol[i]] atr = as.numeric(atr) Split = BestSplit(dataSet,numericCol[i],labels)#計算最佳分裂點 s[i] = Split names(s)[i] = numericCol[i] dataSet[,numericCol[i]] = toDiscreteCol(atr, Split)#將新離散型資料的寫入dataSet } } } result = list(dataSet,s) return(result) } #計算基尼係數 jini <- function(data,labels){ nument<-length(data[,1]) key<-rep("a",nument) for(i in 1:nument) { key[i]<-data[i,labels] } ent<-0 prob<-table(key)/nument for(i in 1:length(prob)) ent=ent+prob[i]*prob[i] ent = 1 - ent return(ent) } #找到基尼係數最小的中值,作為分裂點 BestSplit <- function(dataSet,colname,labels){ numFeatures = nrow(dataSet) - 1 bestSplit = -1 sorted = sort(as.numeric(dataSet[,colname])) atr = dataSet[,colname] bestGini = 999 for(i in 1: numFeatures){ middle = (sorted[i] + sorted[i+1])/2 tempCol = toDiscreteCol(atr,middle) dataSet[,colname] = tempCol featureLabels = levels(factor(dataSet[,colname])) Gini = 0.0 for( j in 1:length(featureLabels)){ subDataSet = splitDataSet(dataSet,colname,featureLabels[j]) prob = length(subDataSet[,1])*1.0/nrow(dataSet) Gini = Gini + prob*jini(subDataSet,labels) } if(Gini <= bestGini){ bestGini = Gini count = middle } } return (count) } #將該列轉換成離散型 toDiscreteCol <- function(atr, Split){ str <- c() for(i in 1:length(atr)){ if(atr[i] <= Split){ str[i] = 'a' }else{ str[i] = 'b' } } return(str) } #############################################Part3 決策樹的構建################################################### #遞迴建立生成樹 creatTree <- function(dataSet,labels,bestInfoGain){ result = toDiscrete(numericCol,dataSet,labels) tempSet = dataSet dataSet = result[[1]] Split = result[[2]] decision_tree = list() classList = dataSet[,labels] #判斷是否屬於同一類 if(oneValue(classList)){ label = classList[1] return (rbind(decision_tree,label)) } #是否在矩陣中只剩Label標籤了,若只剩Label標籤,則都分完了 if((ncol(dataSet) == 1)){ label = majorityCnt(classList) decision_tree = rbind(decision_tree,labels) return (decision_tree) } #選擇bestFeature作為分割屬性 bestFeature = chooseBestFeatureToSplita(dataSet,labels,bestInfoGain) bestFeatureName = colnames(dataSet)[bestFeature] #所有資訊增益都小於bestInfoGain if(bestFeature == -1){ label = majorityCnt(classList) decision_tree = rbind(decision_tree,label) return (decision_tree) } labelFeature = colnames(dataSet)[bestFeature] #新增內部節點 decision_tree = rbind(decision_tree,labelFeature) #選中了那個標籤作為此次分類標籤 attriCol = dataSet[,bestFeature] temp_tree = data.frame() stayData = dataSet factor=levels(as.factor(attriCol)) for(j in 1:length(factor)){ #分裂成小資料集 dataSet = splitDataSet(stayData,bestFeature,factor[j],tempSet) if(bestFeatureName %in% numericCol){ if(factor[j] == 'a'){ character = '<' }else{ character = '>' } numpd = paste(character,Split[bestFeature]) FeatureValue = paste(bestFeatureName,numpd) }else{ FeatureValue = paste(bestFeatureName,factor[j]) } decision_tree = rbind(decision_tree, FeatureValue ) #刪除已使用屬性列 dataSet = dataSet[,-bestFeature,drop=FALSE] #遞迴呼叫這個函式 temp_tree = creatTree(dataSet,labels,bestInfoGain) decision_tree = rbind(decision_tree,temp_tree) } return (decision_tree) } #############################################Part4 預測函式####################################################### #算正確率 test <- function(testSet,labels){ count <- 0 for(i in 1:nrow(testSet)){ pre = predict(testSet[i,,drop=FALSE],myTree) if(is.null(pre)){ }else{ if(pre == testSet[i,labels]){ count = count + 1 } } } return(count/nrow(testSet)) } #列印預測結果 pre <- function(testSet){ for(i in 1:nrow(testSet)){ pre = predict(testSet[i,,drop=FALSE],myTree) return(pre) } } #預測函式 predict <- function(testSet, df, row = 1, col = 1){ if(df[row,col] == "yes"| df[row,col] == "no"){ return(df[row,col]) }else{ if(length(grep(" ",df[row,col])) == 0 & nchar(df[row,col]) > 0){ labelFeature = df[row,col]#獲取屬性名稱 FeatureValue = testSet[,labelFeature][1]#獲取屬性值 if(labelFeature %in% numericCol){ count <- 1 rows <- c() Split <- NULL for(i in row:nrow(df)){ if(count > 2){ break } if(nchar(df[i,col+1]) > 0){ Split = as.numeric(strsplit(df[i,col+1]," ")[[1]][3]) rows[count] = i count = count + 1 } } if(as.numeric(FeatureValue) < Split){ prediction = predict(testSet, df, rows[1] + 1, col + 2) }else{ prediction = predict(testSet, df, rows[2] + 1, col + 2) } return(prediction) }else{ sum = paste(labelFeature, FeatureValue) for(i in row:nrow(df)){ if(df[i,col+1] == sum){ row = i break } } prediction = predict(testSet, df, row + 1, col + 2) return(prediction) } } } } ###########################################Part5 載入資料並執行################################################### #載入資料 myData = load("C:/Users/gino2/Desktop/R/DecisiontreeSampledata.txt") #"D:/littlestar/DecisiontreeSampledata.txt" 離散型資料 #"D:/littlestar/DecisiontreeSampledataContinue.txt" 連續型資料 #建立決策樹 #三個引數:訓練資料集,類標籤列,增益率的閾值 tree = creatTree(myData[[1]],'buys_computer',0.12) myTree <- printTree(tree) print(myTree) #預測函式 rightProb = test(myData[[2]],'buys_computer') print(paste("測試集的準確率為:",rightProb)) print(paste("第22行的預測結果為:",pre(myData[[3]])))

執行結果

這裡寫圖片描述

這裡寫圖片描述

下面是我用的資料

純離散型

ID  age income  student credit_rating    buys_computer
1    youth   high   no   fair   no
2    youth   high   no   excellent  no
3    middle_age      high   no   fair   yes
4    senior      medium     no   fair   yes
5    senior     low yes  fair   yes
6    senior     low yes  excellent  no
7    middle_age     low yes  excellent  yes
8    youth   medium     no   fair   no
9    youth  low yes  fair   yes
10   senior      medium     yes  fair   yes
11   youth   medium     yes  excellent  yes
12   middle_age      medium     no   excellent  yes
13   middle_age      high   yes  fair   yes
14   senior      medium     no   excellent  no
15  youth    medium     no   fair   no
16  youth   low yes  excellent  yes
17   middle_age      medium     yes  fair   yes
18   middle_age      high   no   excellent  yes
19   middle_age     low no   excellent  yes
20   senior     low yes  excellent  yes
21   senior     high    no   fair   no
22   middle_age      medium     no   fair   NA

連續型+離散型

Id  age income  student credit_rating buys_computer
1   16  high    no  fair    no
2   25  high    no  excellent   no
3   34  high    no  fair    yes
4   41  medium  no  fair    yes
5   45  low yes fair    yes
6   48  low yes excellent   no
7   39  low yes excellent   yes
8   27  medium  no  fair    no
9   25  low yes fair    yes
10  49  medium  yes fair    yes
11  18  medium  yes excellent   yes
12  36  medium  no  excellent   yes
13  38  high    yes fair    yes
14  50  medium  no  excellent   no
15  19  medium  no  fair    no
16  25  low yes excellent   yes
17  35  medium  yes fair    yes
18  31  high    no  excellent   yes
19  38  low no  excellent   yes
20  45  low yes excellent   yes
21  43  high    no  fair    no
22  36  medium  no  fair    NA

在文章的最後,我要感謝給予我動力和能量去完成這篇程式碼的人

相關推薦

離散連續資料決策構建列印實現 R語言ID3C4.5演算法

本人的第一篇文章,趁著我們的資料探勘課設的時間,把實現的決策樹程式碼,拿出來分享下。有很多漏洞和缺陷,還有很多駭客思想的成分,但是總之,能實現,看網上的程式碼,能用的其實也沒幾個。廢話不多說,直接看程式碼 特別鳴謝博主skyonefly的程式碼 附上鍊接:R

常見的離散連續隨機變數的概率分佈

目錄 1 基本概念 4 參考文獻 1 基本概念 在之前的博文中,已經明白了概率分佈函式和概率密度函式。下面來講解一下常見的離散型和連續型隨機變數概率分佈。 在此之前,介紹幾個基本概念: 均值(期望值exp

隨機變數概率分佈函式彙總-離散分佈+連續分佈

2018.08.18-更新 概率分佈用以表達隨機變數取值的概率規律,根據隨機變數所屬型別的不同,概率分佈取不同的表現形式 離散型分佈:二項分佈、多項分佈、伯努利分佈、泊松分佈 連續型分佈:均勻分佈、正態分佈、指數分佈、伽瑪分佈、偏態分佈、貝塔分佈、威布林分佈、卡方分佈、

變量數據類轉換

浮點 變量名 類型轉換 浮點型 整型 引號 格式 unicode編碼 十進制 目標:掌握java基礎語法知識 1變量 變量即變化中的量,變量中的值是變化的,在java中,使用變量時需要聲明變量,在聲明變量時需要聲明變量名,變量名必須是一個以字母開頭的由字母或數字構成的序列,

編譯解釋、動態語言靜態語言、強類語言弱類語言的區別

動態語言 動態 java語言 不同 編譯型 效率 編譯過程 .exe 檢查 (一)編譯型語言和解釋型語言   首先我們區分這樣一個概念,編譯型語言和解釋型語言。我們編程用的都是高級型語言(寫匯編和機器語言的除外),計算機只理解和運行機器語言,所以必須把高級語言翻譯成機器語言

面向物件【林老師版】:多性(十三)

一、多型 多型指的是一類事物有多種形態,比如 1、動物有多種形態:人,狗,豬 import abc class Animal(metaclass=abc.ABCMeta): #同一類事物:動物 @abc.abstractmethod def talk(self):

Java開發筆記(三十二)字符相互轉化

傳播 out 字母 href 不但 java 個數 進制數 com 前面提到字符類型是一種新的變量類型,然而編碼實踐的過程中卻發現,某個具體的字符值居然可以賦值給整型變量!就像下面的例子代碼那樣,把字符值賦給整型變量,編譯器不但沒報錯,而且還能正常運行! // 字符允許

Java開發筆記(三十二)字元相互轉化

前面提到字元型別是一種新的變數型別,然而編碼實踐的過程中卻發現,某個具體的字元值居然可以賦值給整型變數!就像下面的例子程式碼那樣,把字元值賦給整型變數,編譯器不但沒報錯,而且還能正常執行! // 字元允許直接賦值給整型變數 private static void charToInt() { i

決策構建演算法 -- ID3 C4.5 演算法

1. 概述 上一篇日誌中,我們介紹了最簡單的分類迴歸演算法 – K 近鄰演算法。 k 近鄰演算法 本篇日誌我們來介紹構建專家系統和資料探勘最常用的演算法 – 決策樹。 2. 決策樹 在系統流程圖中,我們常

verilog語言中regwire的區別

對於初學者來說,首先一個大問題就是在讀程式時候,變數型別reg型與wire型的區分。 最近做了點模擬工作,對兩種型別的變數有一些自己的見解,寫一寫,交流學習。 自己的理解: wire型相當於是一根連線。 reg型相當於是儲存器。 在wire型相當於連線的基礎上我們很

1022:整布林的轉換

時間限制: 1000 ms 記憶體限制: 65536 KB 提交數: 6546 通過數: 5766 【題目描述】 將一個整型變數的值賦給一個布林型變數,再將這個布林型變數的值賦給

java中整字元互轉

1、字元型轉換成整型:  1.轉換成Int型 int/Integer num  =  Integer.parseInt(String str); 2.轉換成long型 Long/long num    =  Long.parseLong(String str); 3

決策ID3C4.5、CART、隨機森林的原理例子

(寫在前面:作者是一名剛入學的模式識別專業的碩士生,第一次寫部落格,有錯誤的地方還請大家多多指教評論,一起交流呀~) 決策樹的基本流程 ①劃分特徵的選擇(常見的選擇方法有:資訊增益、增益率、基尼指數,下文會詳細介紹) ②劃分停止準則:停止準則表示該節點不再劃分

案例

多型的思想 面向物件3大概念 封裝: 突破c函式的概念....用類做函式引數的時候,可以使用物件的屬性 和物件的方法 繼承: A B 程式碼複用 多型 : 可以使用未來... 多型很重要 實現多型的三個條件 好比C語言 間接賦值 是指標存在的最大意義是c語言的特有的現象 (

【轉】深入淺出理解決策演算法(二)-ID3演算法C4.5演算法

從深入淺出理解決策樹演算法(一)-核心思想 - 知乎專欄文章中,我們已經知道了決策樹最基本也是最核心的思想。那就是其實決策樹就是可以看做一個if-then規則的集合。我們從決策樹的根結點到每一個都葉結點構建一條規則。 並且我們將要預測的例項都可以被一條路徑或者一條規則所覆蓋。 如下例:假設我

面向物件-多

多型是指的多種形態;比如水的多種形態:水,冰多型性:在不考慮例項型別情況下使用例項,多型性分為靜態多型性和動態多型性靜態多型性:如任何型別都可以用運算子+進行運算 多型:同一類事物的多種形態 import abc class Animal(metaclass=abc.ABCMeta): #同一類事物:

機器學習 - 決策(下)- CART 以及 ID3C4.5的比較

機器學習 - 決策樹(下)- CART 以及與 ID3、C4.5的比較 CART 迴歸樹 分類樹 剪枝 剪枝 選擇 決策樹特點總結 ID3,C4.

機器學習總結(四)——隨機森林GBDT(梯度提升決策)

1. 隨機森林簡介 隨機森林採用的是bagging的思想,bagging即:通過在訓練樣本集中進行有放回的取樣得到多個取樣集,基於每個取樣集訓練出一個基學習器,再將基學習器結合起來共同實現分類或者回歸。隨機森林在對決策樹進行bagging的基礎上,

物件模型

多型即多種形態。多型分兩種 編譯時多型:在編譯期間編譯器根據函式實參的型別確定要調哪個函式(這個我們之前已經接觸過了,和函式過載差不多,是同名函式,但是引數不同) 執行時多型:在程式執行期間才會去判斷到底會呼叫哪個函式。這裡我們主要講的就是動態多型。 C+

決策構建深度節點數簡單例子

1、構建treePlotter.py #coding:utf-8 import matplotlib.pyplot as plt # 定義決策樹決策結果的屬性,用字典來定義 # 下面的字典定義也可寫作 decisionNode={boxstyle:'sawtooth'