離散型與連續型資料決策樹構建及列印實現 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語言,ID3,C4.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語言中,reg型與wire型的區別
對於初學者來說,首先一個大問題就是在讀程式時候,變數型別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
決策樹ID3、C4.5、CART、隨機森林的原理與例子
(寫在前面:作者是一名剛入學的模式識別專業的碩士生,第一次寫部落格,有錯誤的地方還請大家多多指教評論,一起交流呀~) 決策樹的基本流程 ①劃分特徵的選擇(常見的選擇方法有:資訊增益、增益率、基尼指數,下文會詳細介紹) ②劃分停止準則:停止準則表示該節點不再劃分
多型與多型案例
多型的思想 面向物件3大概念 封裝: 突破c函式的概念....用類做函式引數的時候,可以使用物件的屬性 和物件的方法 繼承: A B 程式碼複用 多型 : 可以使用未來... 多型很重要 實現多型的三個條件 好比C語言 間接賦值 是指標存在的最大意義是c語言的特有的現象 (
【轉】深入淺出理解決策樹演算法(二)-ID3演算法與C4.5演算法
從深入淺出理解決策樹演算法(一)-核心思想 - 知乎專欄文章中,我們已經知道了決策樹最基本也是最核心的思想。那就是其實決策樹就是可以看做一個if-then規則的集合。我們從決策樹的根結點到每一個都葉結點構建一條規則。 並且我們將要預測的例項都可以被一條路徑或者一條規則所覆蓋。 如下例:假設我
面向物件-多型與多型性
多型是指的多種形態;比如水的多種形態:水,冰多型性:在不考慮例項型別情況下使用例項,多型性分為靜態多型性和動態多型性靜態多型性:如任何型別都可以用運算子+進行運算 多型:同一類事物的多種形態 import abc class Animal(metaclass=abc.ABCMeta): #同一類事物:
機器學習 - 決策樹(下)- CART 以及與 ID3、C4.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'