日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

分类树/装袋法/随机森林算法的R语言实现

發布時間:2023/11/29 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分类树/装袋法/随机森林算法的R语言实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文首發于簡書于[2018.06.12]


本文是我自己動手用R語言寫的實現分類樹的代碼,以及在此基礎上寫的袋裝法(bagging)和隨機森林(random forest)的算法實現。全文的結構是:

  • 分類樹

    • 基本知識
    • pred
    • gini
    • splitrule
    • splitrule_best
    • splitrule_random
    • splitting
    • buildTree
    • predict
  • 裝袋法與隨機森林

    • 基本知識
    • bagging
    • predict_ensemble
  • 性能測試
  • 寫在后面

全部的代碼如下:

## x和y為自變量(矩陣)和因變量(列向量) ylevels = levels(y) nlevels = length(ylevels) n = length(y) k = dim(x)[2] pred = function(suby) {# majority vote 所占比例最大的值為預測值vote = rep(0,nlevels)for (i in 1:nlevels) { vote[i] = sum(suby==ylevels[i]) }return(ylevels[which.max(vote)]) }gini = function(suby,summary = FALSE) { # 給定一列因變量,計算它的基尼系數if (!summary) suby = as.vector(summary(suby))obs = sum(suby)return( 1-(drop(crossprod(suby)))/(obs*obs) ) }splitrule = function(subx,suby) { #這里subx和suby都是向量,給定一個自變量,求出它的最優劃分條件subylen = length(suby)xvalues = sort(unique(subx)) if (length(xvalues)>1) { #只有在自變量的取值不是完全相同時(有不同的x),才能夠對x劃分cutpoint = ( xvalues[1:(length(xvalues)-1)] + xvalues[2:length(xvalues)] )/2minimpurity = 1 #初始啟動值for ( i in 1:length(cutpoint) ) {lefty = suby[subx>=cutpoint[i]]righty = suby[subx<cutpoint[i]]impurity = ( gini(lefty)*length(lefty) + gini(righty)*length(righty) )/subylen# 如果一個點是父節點,它的不純度是它的兩個子節點的基尼系數加權和;# 如果是葉節點,則不純度為它本身的基尼系數if (impurity<minimpurity) {minimpurity = impuritysplitpoint = cutpoint[i]}}}else {splitpoint = xvaluesminimpurity = gini(suby)}return(c(splitpoint,minimpurity)) }splitrule_best = function(subx,suby) {# 這是對上面splitrule原有版本的改進。自變量按從小到大排列,每次劃分時,把落入到左邊的觀測記錄下來# 隨著劃分節點不斷增大,落入左節點的數據越來越多,在上一次的基礎上進行累加就行。suby_length = length(suby)xvalues = sort(unique(subx))if (length(xvalues)>1) {intervals = cut(subx,xvalues,right = FALSE) #區間左閉右開suby_splited = matrix(unlist(by(suby,intervals,summary)),ncol = nlevels, byrow = TRUE)suby_splited_left = matrix(apply(suby_splited,2,cumsum),ncol = nlevels)suby_splited_right = sweep(-suby_splited_left,2,as.vector(summary(suby)),FUN = "+") suby_splited_left_obs = apply(suby_splited_left,1,sum)suby_splited_right_obs = suby_length - suby_splited_left_obsimpurity = NULLfor (i in 1:(length(xvalues)-1) ) {impurity = c(impurity,(gini(suby_splited_left[i,],summary = TRUE)*suby_splited_left_obs[i]+ gini(suby_splited_right[i,],summary = TRUE)*suby_splited_right_obs[i])/suby_length)}minimpurity = min(impurity)splitpoint = xvalues[which.min(impurity)]} else {splitpoint = xvaluesminimpurity = gini(suby)}return(c(splitpoint,minimpurity)) }splitrule_random = function(subx,suby) {# splitrule的一個變形。較為極端的方法,不排序,不取唯一值,任意抽取一個數作劃分節點。suby_length = length(suby)subx_withoutmax = subx[subx!=max(subx)]if (length(subx_withoutmax)>0) {splitpoint = subx_withoutmax[sample(length(subx_withoutmax),1)]suby_splited_left = suby[subx<=splitpoint]suby_splited_right = suby[subx>splitpoint]impurity = (gini(suby_splited_left)*length(suby_splited_left) + gini(suby_splited_right)*length(suby_splited_right))/suby_length} else{splitpoint = 0impurity = 1}return(c(splitpoint,impurity)) }splitting = function(subx,suby,split,rf) {# subx是一個矩陣,suby是列向量。給定自變量矩陣,返還最優劃分變量和相應最優劃分條件if (!rf) chosen_variable = 1:kif (rf == TRUE) chosen_variable = sample(1:k,round(sqrt(k)))if (split == "best") temp = apply(subx[,chosen_variable],2,splitrule_best,suby=suby) if (split == "random") temp = apply(subx[,chosen_variable],2,splitrule_random,suby=suby) splitpoint = temp[1,]minimpurity = temp[2,]splitvariable = chosen_variable[which.min(minimpurity)] #確定第幾個變量是最優劃分變量splitpoint = splitpoint[which.min(minimpurity)]minimpurity = min(minimpurity)return(c(splitvariable,splitpoint,minimpurity)) } buildTREE = function(x,y,split = "best",rf = FALSE) {TREE = NULLindex = 1:n tree = as.data.frame(list(leftnode=0,rightnode=0,splitvariable=0,splitpoint=0,obs=n,pred=levels(y)[1],leaf=TRUE,begin=1,end=n)) cur = 1 #當前正在分析的節點編號,它要追趕nodes,每次循環過后增加1。nodes = 1 #當前這棵樹的總節點數量while ((cur<=nodes) ) {beginC = tree$begin[cur]; endC = tree$end[cur]indexCurrent = index[beginC:endC]subx = x[indexCurrent,]suby = y[indexCurrent]impurityCurrent = gini(suby)if (impurityCurrent>0.1) {temp <- splitting(subx,suby,split) if (temp[3]<impurityCurrent) {#如果能進一步劃分為兩個子節點(即不純度能夠降低),nodes增加2# 總會出現無法劃分的情況,即nodes不會增大,這種情況下cur就有可能追趕上nodes了tree$splitvariable[cur] = temp[1]tree$splitpoint[cur] = temp[2]tree$leftnode[cur] = nodes+1tree$rightnode[cur] = nodes+2nodes = nodes +2 tree$leaf[cur] = FALSE #一個節點默認是葉節點,滿足劃分條件時才設為FALSE,這樣寫比較方便。indexL = indexCurrent[subx[,tree$splitvariable[cur]] <= tree$splitpoint[cur]]indexR = indexCurrent[subx[,tree$splitvariable[cur]] > tree$splitpoint[cur]]index[beginC:endC] <- c(indexL,indexR) #這是最為聰明的一步,index被一步一步地精煉更新直至最后成品,搭配begin和end使用。predL = pred(y[indexL])predR = pred(y[indexR]) nodeL = as.data.frame(list(leftnode=0,rightnode=0,splitvariable=0,splitpoint=0,obs=length(indexL),pred=predL,leaf=TRUE,begin = beginC, end = beginC+length(indexL)-1) )nodeR = as.data.frame(list(leftnode=0,rightnode=0,splitvariable=0,splitpoint=0,obs=length(indexR),pred=predR,leaf=TRUE,begin = beginC+length(indexL),end = beginC+length(indexCurrent)-1) )tree = as.data.frame(rbind(tree,nodeL,nodeR))}}cur = cur + 1 #迭代循環iterator}TREE <- treereturn(TREE) }predict = function(TREE,newx) { #newx是一個自變量矩陣,返還一列因變量的預測值。subpredict = function(subx) { #給定一行觀測的自變量,我預測它的因變量row = 1 #從第一個節點開始出發while(TRUE) { if (TREE$leaf[row]==TRUE) {predicted = TREE$pred[row]break}#給定一個觀測值,判斷它是往左走還是往右走,一直走下去,直到抵達葉節點leaf為止if (subx[TREE$splitvariable[row]] <= TREE$splitpoint[row]) {row = TREE$leftnode[row]}else {row = TREE$rightnode[row]}}return(predicted)}return(apply(newx,1,subpredict)) } bagging = function(x,y,trees = 150,split = "best",rf = FALSE) {TREES = list()for (i in 1:trees) {bootstrap_index = sample(1:n,n,replace = TRUE)x_bagging = x[bootstrap_index,]y_bagging = y[bootstrap_index]tree = buildTREE(x_bagging,y_bagging,split,rf)TREES = c(TREES,list(tree)) }return(TREES) }predict_ensemble = function(newx,TREES) { #此處newx為自變量矩陣,TREES為bagging樹林或是隨機森林subpredict_ensemble = function(subx,TREES){ #給定一行觀測的自變量和一片樹林,我預測它的因變量subpredict = function(TREE,subx) { #給定一行觀測的自變量和一棵樹的結構,我預測它的因變量row = 1 #從第一個節點開始出發while(TRUE) { if (TREE$leaf[row]==TRUE) {predicted = TREE$pred[row]break}#給定一個觀測值,判斷它是往左走還是往右走,一直走下去,直到抵達葉節點leaf為止if (subx[TREE$splitvariable[row]] <= TREE$splitpoint[row]) {row = TREE$leftnode[row]}else {row = TREE$rightnode[row]}}return(predicted)}sub_predicted = unlist(lapply(TREES,subpredict,subx)) #對每一行數據進行預測return( names(summary(sub_predicted))[which.max(summary(sub_predicted))] ) #每棵樹進行投票,確定最終預測值}apply(newx,1,subpredict_ensemble,TREES) }

分類樹

基本知識

有監督的機器學習中有兩類主要問題,回歸問題(預測房價、預測銷售量)和分類問題(預測性別、預測是否信貸違約)。對應地,決策樹有回歸樹和分類樹兩種。決策樹算是最接近人類思考模式的算法之一,從圖像上來看就是一連串的流程圖,給定一個個體的信息,沿著流程往下走,判斷它最終的歸屬。下面放兩張馬老師的課件,對應的場景是預測某位用戶是否會拖欠貸款。

生成決策樹的規則是不斷地使得不純度下降,對于不純度的計算,可以采用基尼系數,公式為:

例如,十個用戶中有六個拖欠貸款,四個按時還貸,那么不純度為:1 - 0.4^2 - 0.6^2 = 1 - 0.16 - 0.36 = 0.48

給定一個樹節點,是否進行劃分,取決于劃分之后不純度是否會下降,如果下降,則繼續劃分,如果不能下降,該節點成為葉節點。如果能夠劃分,使得不純度下降幅度最大的那個自變量和劃分節點便是最優劃分變量和最優劃分條件。

講完基本概念,我們來看用R代碼實現分類樹,涉及到了下面幾個函數。

  • pred:給定一列因變量,求出其中占比例最大的值。分類樹中,對于最終的結果的預測,是由落入到這個葉節點中的占比例最大的值確定的。
  • gini:給定一列因變量,求出其基尼系數。
  • splitrule:給定一列自變量和因變量,求出這個自變量的最優劃分條件和劃分之后的不純度。
  • split_best:對上一版splitrule的改進,減少了計算量。
  • split_random:對split_best的再改進,減少了計算量,同時有一定幾率能帶來預測精度的提高(沒有嚴謹的數學證明)。
  • splitting:給定一個自變量矩陣和一列因變量,求出所有自變量中最優的劃分變量,以及對應的最優劃分條件和不純度。
  • buildTREE:主函數,在上面各個基本函數的基礎上,給定一套數據,生成一棵分類樹。

下面逐個說明。


pred()

pred = function(suby) {# majority vote 所占比例最大的值為預測值vote = rep(0,nlevels)for (i in 1:nlevels) { vote[i] = sum(suby==ylevels[i]) }return(ylevels[which.max(vote)]) }

給定一列因變量,求出其中占比例最大的值。分類樹中,對于最終的結果的預測,是由落入到這個葉節點中的占比例最大的值確定的。


gini()

gini = function(suby,summary = FALSE) { # 給定一列因變量,計算它的基尼系數if (!summary) suby = as.vector(summary(suby))obs = sum(suby)return( 1-(drop(crossprod(suby)))/(obs*obs) ) }

這個函數就是照著數學公式來寫的,沒什么特別。

summary是R里面一個相當好用的函數,它能夠統計一個factor的頻數:

> example[1] absent absent present absent absent absent absent [8] absent absent present present absent absent absent [15] absent absent absent absent absent absent Levels: absent present > summary(example)absent present 17 3

因為不知道你要傳入的因變量是以像example這樣逐個列出的形式,還是以像summary(example)這樣進行頻數統計的形式,所以設置了一個summary參數,默認FALSE,即默認以前者的形式傳入因變量。


splitrule()

splitrule = function(subx,suby) { #這里subx和suby都是向量,給定一個自變量,求出它的最優劃分條件subylen = length(suby)xvalues = sort(unique(subx)) if (length(xvalues)>1) { #只有在自變量的取值不是完全相同時(有不同的x),才能夠對x劃分cutpoint = ( xvalues[1:(length(xvalues)-1)] + xvalues[2:length(xvalues)] )/2minimpurity = 1 #初始啟動值for ( i in 1:length(cutpoint) ) {lefty = suby[subx>=cutpoint[i]]righty = suby[subx<cutpoint[i]]impurity = ( gini(lefty)*length(lefty) + gini(righty)*length(righty) )/subylen# 如果一個點是父節點,它的不純度是它的兩個子節點的基尼系數加權和;# 如果是葉節點,則不純度為它本身的基尼系數if (impurity<minimpurity) {minimpurity = impuritysplitpoint = cutpoint[i]}}}else {splitpoint = xvaluesminimpurity = gini(suby)}return(c(splitpoint,minimpurity)) }

寫得很直觀的一個函數,完全就是按照上面的決策樹的流程圖來寫的。傳入一列因變量和一列自變量,對自變量進行從小到大排序,給定一個劃分點cutpoint,自變量小于等于cutpoint的觀測落入左邊的子節點,自變量大于cutpoint的觀測落入到右邊的子節點,劃分之后,計算不純度并記錄一下。遍歷所有可能的cutpoint,記錄最小的不純度,以及對應的cutpoint值。


splitrule_best()

splitrule_best = function(subx,suby) {# 這是對上面splitrule原有版本的改進。自變量按從小到大排列,每次劃分時,把落入到左邊的觀測記錄下來# 隨著劃分節點不斷增大,落入左節點的數據越來越多,在上一次的基礎上進行累加就行。suby_length = length(suby)xvalues = sort(unique(subx))if (length(xvalues)>1) {intervals = cut(subx,xvalues,right = FALSE) #區間左閉右開suby_splited = matrix(unlist(by(suby,intervals,summary)),ncol = nlevels, byrow = TRUE)suby_splited_left = matrix(apply(suby_splited,2,cumsum),ncol = nlevels)suby_splited_right = sweep(-suby_splited_left,2,as.vector(summary(suby)),FUN = "+") suby_splited_left_obs = apply(suby_splited_left,1,sum)suby_splited_right_obs = suby_length - suby_splited_left_obsimpurity = NULLfor (i in 1:(length(xvalues)-1) ) {impurity = c(impurity,(gini(suby_splited_left[i,],summary = TRUE)*suby_splited_left_obs[i]+ gini(suby_splited_right[i,],summary = TRUE)*suby_splited_right_obs[i])/suby_length)}minimpurity = min(impurity)splitpoint = xvalues[which.min(impurity)]} else {splitpoint = xvaluesminimpurity = gini(suby)}return(c(splitpoint,minimpurity)) }

這個是對剛才的splitrule的改進,最終實現的效果是相同的。上一版的缺點在于,每給一個cutpoint,所有的自變量值都要和它進行比較,從而判斷是要落入左邊還是落入右邊。這其實做了很多輪的大小比較,浪費了時間。改進的想法是,把所有的cutpoint都擺出來,把自變量值相應地劃入到不同的區間中,進行記錄。這個時候,R自帶的cut函數就派上用場了。

> example = 1:15 > example[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 > cut(example,breaks = c(0,3,7,15))[1](0,3] (0,3] (0,3] (3,7] (3,7] (3,7] (3,7] (7,15](7,15](7,15](7,15](7,15](7,15](7,15](7,15] Levels: (0,3](3,7](7,15]

如上,自變量有15個取值,若以3和7作為劃分點,可以把所有的自變量歸入到三個區間內。這樣一來,通過命令`
intervals = cut(subx,xvalues,right = FALSE)
`就能夠把所有的自變量取值進行劃分。

以rpart包中的kyphosis數據集為例,該數據共有81個觀測,其中有64個因變量取值"absent",有17個因變量取值"present"。

左邊是每個區間內的因變量情況,中間是累積的落入到左邊子節點的情況,右邊是累積的落入到右邊子節點的情況。先看第一行,能夠看到,第一次劃分時,有5個觀測落入到左節點,剩余的76個觀測落入右節點;同樣地,第二行可以看出,有8個觀測落入到左節點,剩下的73個觀測落入到右節點。這樣,只通過一輪的比較大小,就能夠完成任務,成功減少了運算量。


splitrule_random()

splitrule_random = function(subx,suby) {# splitrule的一個變形。較為極端的方法,不排序,不取唯一值,任意抽取一個數作劃分節點。suby_length = length(suby)subx_withoutmax = subx[subx!=max(subx)]if (length(subx_withoutmax)>0) {splitpoint = subx_withoutmax[sample(length(subx_withoutmax),1)]suby_splited_left = suby[subx<=splitpoint]suby_splited_right = suby[subx>splitpoint]impurity = (gini(suby_splited_left)*length(suby_splited_left) + gini(suby_splited_right)*length(suby_splited_right))/suby_length} else{splitpoint = 0impurity = 1}return(c(splitpoint,impurity)) }

即便進行了改進,splitrule_best的運算量還是大,因為每次調用這個函數時都要對所有的自變量取值進行排序。splitrule_random函數的做法是,不進行排序,從自變量中隨便挑出一個值作為cutpoint,并記錄不純度。例如,自變量取值是1:20,隨機挑選一個值(例如,選出7),那么自變量取1:7的觀測落入左節點,取8:20的落入右節點。

這是一種相當簡單粗暴的做法,因為計算得到的不純度有可能非常高,而上面的splitrule_best函數計算得到的,是所有可能的不純度里最低的那個,一定是優于splitrule_random得到的不純度的。但是,這種做法有它的道理,具體的會在下面講隨機森林的時候談到。

splitting()

splitting = function(subx,suby,split,rf) {# subx是一個矩陣,suby是列向量。給定自變量矩陣,返還最優劃分變量和相應最優劃分條件if (!rf) chosen_variable = 1:kif (rf == TRUE) chosen_variable = sample(1:k,round(sqrt(k)))if (split == "best") temp = apply(subx[,chosen_variable],2,splitrule_best,suby=suby) if (split == "random") temp = apply(subx[,chosen_variable],2,splitrule_random,suby=suby) splitpoint = temp[1,]minimpurity = temp[2,]splitvariable = chosen_variable[which.min(minimpurity)] #確定第幾個變量是最優劃分變量splitpoint = splitpoint[which.min(minimpurity)]minimpurity = min(minimpurity)return(c(splitvariable,splitpoint,minimpurity)) }

之前的splitrule函數是把一列自變量的最優劃分點給求出來,現在的這個splitting函數是把所有自變量的最優劃分點和相應的不純度都求出來。不純度最低的劃分變量,便是我們要的最優劃分變量。


buildTREE()

buildTREE = function(x,y,split = "best",rf = FALSE ) {TREE = NULLindex = 1:n tree = as.data.frame(list(leftnode=0,rightnode=0,splitvariable=0,splitpoint=0,obs=n,pred=levels(y)[1],leaf=TRUE,begin=1,end=n)) cur = 1 #當前正在分析的節點編號,它要追趕nodes,每次循環過后增加1。nodes = 1 #當前這棵樹的總節點數量while ((cur<=nodes) ) {beginC = tree$begin[cur]; endC = tree$end[cur]indexCurrent = index[beginC:endC]subx = x[indexCurrent,]suby = y[indexCurrent]impurityCurrent = gini(suby)if (impurityCurrent>0.1) {temp <- splitting(subx,suby,split) if (temp[3]<impurityCurrent) {#如果能進一步劃分為兩個子節點(即不純度能夠降低),nodes增加2# 總會出現無法劃分的情況,即nodes不會增大,這種情況下cur就有可能追趕上nodes了tree$splitvariable[cur] = temp[1]tree$splitpoint[cur] = temp[2]tree$leftnode[cur] = nodes+1tree$rightnode[cur] = nodes+2nodes = nodes +2 tree$leaf[cur] = FALSE #一個節點默認是葉節點,滿足劃分條件時才設為FALSE,這樣寫比較方便。indexL = indexCurrent[subx[,tree$splitvariable[cur]] <= tree$splitpoint[cur]]indexR = indexCurrent[subx[,tree$splitvariable[cur]] > tree$splitpoint[cur]]index[beginC:endC] <- c(indexL,indexR) #這是最為聰明的一步,index被一步一步地精煉更新直至最后成品,搭配begin和end使用。predL = pred(y[indexL])predR = pred(y[indexR]) nodeL = as.data.frame(list(leftnode=0,rightnode=0,splitvariable=0,splitpoint=0,obs=length(indexL),pred=predL,leaf=TRUE,begin = beginC, end = beginC+length(indexL)-1) )nodeR = as.data.frame(list(leftnode=0,rightnode=0,splitvariable=0,splitpoint=0,obs=length(indexR),pred=predR,leaf=TRUE,begin = beginC+length(indexL),end = beginC+length(indexCurrent)-1) )tree = as.data.frame(rbind(tree,nodeL,nodeR))}}cur = cur + 1 #迭代循環iterator}TREE <- treereturn(TREE) }

這是分類樹算法的主函數,也是最難寫的一個函數。代碼不多,但是寫了很長時間。它的作用是,在上面幾個基本函數的基礎上,把一棵分類樹給生成出來。寫這個函數時,一個首要的問題是:怎么表達一棵樹?


首先映入腦海的是這樣的圖像,一棵樹應該用這樣一幅圖來表達,把劃分變量和劃分條件講得很清楚。可是,R里面怎么用代碼把一幅圖給寫出來?

上了馬老師的課之后,我認識到,分類樹從表面上看是一幅圖,實際上它的結構是一張表(data.frame),圖像只不過是直觀地表達這張表格罷了。buildTREE這個函數,最終生成的便是這樣一個data.frame。

每一行表示一個節點的相關信息,節點的編號由最左端的1,2,3,4...確定。leftnode和rightnode表示這個節點劃分之后的子節點的編號,如果都是0,則表明這個節點是葉節點。splitvariable表示最優劃分變量是第幾個自變量,splitpoint表示劃分點,小于等于這個值的觀測落入左節點,大于這個值的觀測落入右節點。obs表示有多少個觀測落入到這個節點中,leaf表示該節點是否為葉節點,如果是,pred表示這個葉節點的預測值。

這個函數中最關鍵的三行代碼是

indexL = indexCurrent[subx[,tree$splitvariable[cur]] <= tree$splitpoint[cur]] indexR = indexCurrent[subx[,tree$splitvariable[cur]] > tree$splitpoint[cur]] index[beginC:endC] <- c(indexL,indexR)

index是一個十分重要的變量,用來標記落入每一個節點中的觀測編號。還是舉剛才的kyphosis的例子,觀測量有81個,index最初是1:81,在第一次劃分后,有62個觀測落入到左邊,19個觀測落入到右邊,此時對index進行順序調整,使其前62個數字表示左節點的觀測編號,后19個數字表示右節點的觀測編號。按照這種方法進行下去,每輪迭代都對index進行更新,在完成了所有的劃分之后,最終的index記錄了所有的葉節點的觀測編號。

使用index這個向量的意義在于,你不必每輪迭代都使用一個list來記錄落入到某個節點的觀測(我第一次實現分類樹就是這么做的),不必要浪費內存。能夠想到使用向量來記錄觀測,用data.frame來表達一棵決策樹,需要對數據結構有足夠深的理解,這一點我在上一篇博客里提到了。


predict()

predict = function(TREE,newx) { #newx是一個自變量矩陣,返還一列因變量的預測值。subpredict = function(subx) { #給定一行觀測的自變量,我預測它的因變量row = 1 #從第一個節點開始出發while(TRUE) { if (TREE$leaf[row]==TRUE) {predicted = TREE$pred[row]break}#給定一個觀測值,判斷它是往左走還是往右走,一直走下去,直到抵達葉節點leaf為止if (subx[TREE$splitvariable[row]] <= TREE$splitpoint[row]) {row = TREE$leftnode[row]}else {row = TREE$rightnode[row]}}return(predicted)}return(apply(newx,1,subpredict)) }

這個函數比較簡單。上一步已經把一棵樹(data.frame)給訓練出來了,現在給定一套數據,通過劃分變量和劃分條件,判斷觀測是往左節點走還是往右節點走,沿著樹一直走下去,直到走到葉節點為止。至此,預測就完成了。


裝袋法與隨機森林

基本知識

bagging和random forest都是基于bootstrap的集成學習方法(ensemble learning method),所謂集成學習,指的是把多個機器學習器給整合起來,綜合考慮它們的結果。例如,你訓練了100個學習器去做考試題,有7臺機器選擇A,4臺機器選擇B,80臺機器選擇C,9臺機器選擇D,那么你最后應該選擇C選項,這就是所謂的集體智慧(Wisedom of the Crowd)。

給定原始數據,通過bootstrap生成一套新數據,在這基礎上訓練出一棵樹,再bootstrap得到又一套數據,再訓練出一棵樹,持續進行下去,便得到了一片樹林。bagging和隨機森林便是這樣得到的樹林。之所以要種植多棵分類樹,是因為單棵分類樹有著嚴重的過度擬合問題,在訓練集上表現良好,在測試集上卻做得一塌糊涂。通過綜合多棵樹,能夠大幅度降低variance,而只是小幅度地增加bias,這樣一來測試集的MSE也就能夠顯著下降了。

隨機森林和bagging的區別在于,bagging每一輪迭代都會遍歷所有的自變量,從而找到最優的劃分變量,而隨機森林限定了搜索的自變量數量,在這自變量的子集里尋找最優劃分變量。例如,現有25個自變量,bagging在每一個樹節點處都要進行25輪循環,找到最優的那個,而隨機森林在每個節點處隨機地挑選出5個自變量,在這5個里找到最優的。至于這種做法究竟有什么道理,Hastie在中講得非常生動和清楚。

In other words, in building a random forest, at each split in the tree, the algorithm is not even allowed to consider a majority of the available predictors. This may sound crazy, but it has a clever rationale. Suppose that there is one very strong predictor in the data set, along with a number of other moderately strong predictors. Then in the collection of bagged trees, most or all of the trees will use this strong predictor in the top split. Consequently, all of the bagged trees will look quite similar to each other. Hence the predictions from the bagged trees will be highly correlated. In particular, this means that bagging will not lead to a substantial reduction in variance over a single tree in this setting.

決策樹的決策規則是,每一次劃分節點,都要使用不純度下降最多的劃分變量,一個變量能使不純度下降0.15,另一個變量使不純度下降0.1,決策樹便會選擇前一個變量。這種做法的問題在于,后者雖然效果不好,但是可能在劃分以后,再次劃分能夠使不純度再下降0.2,而前一個變量可能再次劃分時只能使不純度下降0.05。決策樹的問題在于,它能夠保證每一個節點處的劃分都是最有效的,但沒法保證這樣生成的一棵樹就是最好的。這有些像宏觀經濟學里講的動態不一致,每一步的最優和整體上的最優不一致。所以Hastie說,做決策樹的時候,目光要放得長遠一些。

The splitting rule is too short-sighted since a seemingly worthless split early on in the tree might be followed by a very good split — that is, a split that leads to a large reduction in RSS later on.

決策樹會按照最優劃分準則一根筋地生成下去,而隨機森林這一算法的意義在于改變這個最優劃分準側,使得每棵樹之間的相似度下降,隨機森林隨機便體現在隨機挑選自變量上。

下面介紹一下bagging和隨機森林的實現。

bagging()

bagging = function(x,y,trees = 150,split = "best",rf = FALSE) {TREES = list()for (i in 1:trees) {bootstrap_index = sample(1:n,n,replace = TRUE)x_bagging = x[bootstrap_index,]y_bagging = y[bootstrap_index]tree = buildTREE(x_bagging,y_bagging,split,rf)TREES = c(TREES,list(tree)) }return(TREES) }

這個函數能夠得到一片樹林。做法非常簡單,從原本的數據中隨機抽樣出新數據,生成新的一棵樹就行了,默認是生成150棵樹。bagging和隨機森林都是使用這個函數,通過參數rf就能夠在兩種方法之間進行切換了,之前的splitting函數里也相應地設置了參數rf,其中k是原始數據的自變量個數,bagging遍歷全部k個自變量,而隨機森林只隨機挑選其中sqrt(k)個。

if (!rf) chosen_variable = 1:k if (rf == TRUE) chosen_variable = sample(1:k,round(sqrt(k)))

上面提到的split_random函數,實際上是受到了隨機森林算法的啟發。既然你能隨機地選取劃分變量,那么我為什么不能夠隨機地選取劃分條件呢?同樣是為了降低樹與樹之間的相似性,我這樣做應該也是合理的。只要保證總體上不純度是在下降就行,不必要追求每一次劃分都能帶來大幅度的下降。


predict_ensemble()

predict_ensemble = function(newx,TREES) { #此處newx為自變量矩陣,TREES為bagging樹林或是隨機森林subpredict_ensemble = function(subx,TREES){ #給定一行觀測的自變量和一片樹林,我預測它的因變量subpredict = function(TREE,subx) { #給定一行觀測的自變量和一棵樹的結構,我預測它的因變量row = 1 #從第一個節點開始出發while(TRUE) { if (TREE$leaf[row]==TRUE) {predicted = TREE$pred[row]break}#給定一個觀測值,判斷它是往左走還是往右走,一直走下去,直到抵達葉節點leaf為止if (subx[TREE$splitvariable[row]] <= TREE$splitpoint[row]) {row = TREE$leftnode[row]}else {row = TREE$rightnode[row]}}return(predicted)}sub_predicted = unlist(lapply(TREES,subpredict,subx)) #對每一行數據進行預測return( names(summary(sub_predicted))[which.max(summary(sub_predicted))] ) #每棵樹進行投票,確定最終預測值}apply(newx,1,subpredict_ensemble,TREES) }

這個函數和之前的單棵樹的predict函數基本上一樣的,無非是給定數據判斷它向左走還是向右走的問題罷了。唯一的區別是加了個多數投票的函數,對應的是上面舉的例子,100棵樹里,80棵樹選了C選項,所以最后我選C。


性能測試

現在試著用mlbench包里LetterRecognition數據集來做一下預測性能測試,數據的預處理過程就不寫了,一個簡單的分層抽樣。

### 單棵分類樹 > tree = buildTREE(train_x,train_y) > predicted1 = predict(tree,test_x) > result1 = mean(predicted1!=test_y)### Bagging > system.time(baggingtrees1 <- bagging(train_x,train_y,split = "best",rf = FALSE))user system elapsed 349.58 0.38 354.38 > system.time(predicted2 <- predict_ensemble(test_x,baggingtrees1))user system elapsed 7.72 0.00 7.80 > result2 = mean(predicted2!=test_y)> system.time(baggingtrees2 <- bagging(train_x,train_y,split = "random",rf = FALSE))user system elapsed 126.17 0.25 129.95 > system.time(predicted3 <- predict_ensemble(test_x,baggingtrees2))user system elapsed 7.15 0.00 7.18 > result3 = mean(predicted3!=test_y)### 隨機森林 > system.time(randomforest1 <- bagging(train_x,train_y,split = "best",rf = TRUE))user system elapsed 155.83 0.06 157.02 > system.time(predicted4 <- predict_ensemble(test_x,randomforest1))user system elapsed 7.84 0.00 7.99 > result4 = mean(predicted4!=test_y)> system.time(randomforest2 <- bagging(train_x,train_y,split = "random",rf = TRUE))user system elapsed 108.47 0.01 109.62 > system.time(predicted5 <- predict_ensemble(test_x,randomforest2))user system elapsed 7.64 0.02 7.66 > result5 = mean(predicted5!=test_y)## ### 結果展示 > result1 [1] 0.38 > result2 [1] 0.215 > result3 [1] 0.235 > result4 [1] 0.23 > result5 [1] 0.215###

從錯誤率來看,單棵分類樹是最差的,bagging和隨機森林差不多,可能是數據量小沒有體現出隨機森林的優勢。使用random的劃分和使用best的劃分在精度上差別不大,但是運算時間明顯減少了,這可以看做是算法改進成功了。

再用R里的randomforest包來試試,發現和我寫的函數性能差別并不大(也許是因為數據量太小了)。

### library(randomForest) bag = randomForest(x = train_x,y = train_y,ntree = 150, mtry = k) predicted6 = predict(bag,newdata = test_x,type = "response") result6 = mean(predicted6!=test_y)rf = randomForest(x = train_x,y = train_y,ntree = 150, mtry = sqrt(k)) predicted7 = predict(rf,newdata = test_x,type = "response") result7 = mean(predicted7!=test_y)> result6 [1] 0.23 > result7 [1] 0.21

寫在后面

這份代碼是我入門機器學習以來寫得比較完整的代碼,源代碼來自于馬老師的數據挖掘課,我是全部讀懂了之后憑著理解再自己寫出來的。相當吃力,前前后后大概花了20多個小時,把各個變量整合起來尤其困難,系統報錯太多的時候心態都有些崩。雖然過程有些辛苦,但總歸是寫了出來,算是對自己的一次鍛煉,寫了這篇文章記錄一下。

總結

以上是生活随笔為你收集整理的分类树/装袋法/随机森林算法的R语言实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

午夜国产一区二区 | 久久综合在线 | 区一区二区三区中文字幕 | 天堂在线视频免费观看 | 国产精品av久久久久久无 | 97超碰色偷偷 | 国产精品久久久久久久久久三级 | 日韩在线看片 | 激情五月婷婷综合网 | 亚洲a免费 | 黄色特一级| 精品久久一区二区三区 | 最新成人av| 欧美日韩在线看 | 亚洲一区精品人人爽人人躁 | 日韩在线 一区二区 | 狠狠色丁香久久婷婷综合丁香 | 欧美精品午夜 | 日韩免费看片 | 国产亚洲欧美日韩高清 | 三级黄色三级 | 欧美大片大全 | 人人爽人人爽人人爽学生一级 | 欧美亚洲精品在线观看 | 国产玖玖精品视频 | 麻豆视频在线看 | 国产高清在线免费 | 国产美女免费看 | 国产精品久久久久久久久久三级 | 又黄又爽又湿又无遮挡的在线视频 | 国产小视频免费在线观看 | 国产一级二级在线 | 999久久久免费视频 午夜国产在线观看 | 99视频导航 | www.日日日.com | 欧美 高跟鞋交 xxxxhd | 五月在线视频 | 亚洲美女久久 | 日韩,精品电影 | 日本三级不卡视频 | 婷婷福利影院 | 91热| 亚洲最大av网 | 一区二区中文字幕在线 | 欧美一性一交一乱 | 99热精品久久 | 日日夜精品 | 色多视频在线观看 | 九九久久成人 | 久久综合色播五月 | 99爱爱| 狠狠色伊人亚洲综合网站色 | 欧美精品久久久久性色 | 国产一区91 | 超碰成人网 | 国产在线播放一区二区 | 手机在线观看国产精品 | 亚洲精品小视频 | 国精产品满18岁在线 | 中文字幕精品久久 | 欧美日韩免费一区二区 | 人人插人人舔 | 丁香婷婷亚洲 | 久久国产精品99久久久久 | 久久高清av| 午夜三级大片 | 91麻豆文化传媒在线观看 | 成人av资源网站 | 欧洲性视频 | 国产一区电影在线观看 | 操操日日 | 美女视频一区 | 日韩中文字幕免费视频 | 丝袜美腿av| 成人在线视频一区 | 日韩成人免费在线电影 | 久久草在线精品 | 韩日精品中文字幕 | 丁香五香天综合情 | 美女一级毛片视频 | 92av视频 | 六月丁香激情综合色啪小说 | 福利视频一区二区 | 91香蕉视频污在线 | 特级西西444www大精品视频免费看 | 精品国产123| 免费合欢视频成人app | 国产一二三四在线观看视频 | 色综合久久网 | 亚洲精品国产自产拍在线观看 | 欧美日韩国产色综合一二三四 | 国产福利一区二区三区在线观看 | 五月婷婷操 | 91秒拍国产福利一区 | 999一区二区三区 | 香蕉国产91| 在线 高清 中文字幕 | 在线视频免费观看 | 色先锋av资源中文字幕 | 国产精品国产自产拍高清av | 国产伦精品一区二区三区在线 | 在线黄频 | 成年人国产在线观看 | 亚洲综合导航 | 国产精品女同一区二区三区久久夜 | 欧美精品你懂的 | 色婷婷狠狠18 | 成人av中文字幕 | 狠狠操导航 | 超碰人人av | 色激情五月| 性色av一区二区三区在线观看 | 国产激情小视频在线观看 | 91在线日韩 | 亚洲女人av| 国产99久久久国产精品免费二区 | 夜夜操天天摸 | 91精品久久久久 | 91精品婷婷国产综合久久蝌蚪 | av不卡免费看 | 亚洲色视频 | 欧美成人中文字幕 | 国产伦精品一区二区三区无广告 | 久久久久日本精品一区二区三区 | 夜夜躁狠狠躁日日躁 | 91色综合 | 久久久 激情 | 少妇av网 | 在线观看视频三级 | 免费看的黄网站 | 久久久久久激情 | 午夜性生活片 | 欧美日韩国产一区二区三区 | 欧美日韩国产色综合一二三四 | 国产精品久久久久久久久久久久冷 | 最新色站 | 91视频高清 | 欧美日韩激情视频8区 | www黄在线 | 久久人人97超碰国产公开结果 | 公开超碰在线 | 欧美老女人xx | 黄色av一区 | 天天鲁天天干天天射 | 中文免费在线观看 | 国产视频在线观看一区 | 综合久久久久久 | 日韩精品在线观看av | 超级碰碰碰碰 | 精品国精品自拍自在线 | 精品一区二区久久久久久久网站 | 国产 一区二区三区 在线 | 草久在线观看视频 | 色综合夜色一区 | 国产精品久久久久久久久久久不卡 | 又粗又长又大又爽又黄少妇毛片 | 久久福利小视频 | av免费试看 | 国产日韩亚洲 | 成人免费xxx在线观看 | 91久久在线观看 | 又黄又爽又刺激的视频 | 成人在线视频你懂的 | 天堂网一区| 欧美黑人xxxx猛性大交 | 91精品一区在线观看 | 国产亚洲婷婷免费 | 精品一区二区三区久久 | 狠狠干狠狠操 | av在线免费不卡 | 欧美一二区在线 | 亚洲欧美少妇 | 日韩网站免费观看 | 国产又粗又猛又爽 | 四虎永久免费在线观看 | 亚洲国产999| 免费网站观看www在线观看 | 成人午夜剧场在线观看 | 看国产黄色片 | 欧美色图30p | 欧美精品久久人人躁人人爽 | 成人a视频在线观看 | 97视频久久久 | 日韩精品亚洲专区在线观看 | 天天综合亚洲 | 97视频免费 | 天堂va欧美va亚洲va老司机 | 久久久精品久久 | 国产一区二区在线影院 | 久久理论片 | 激情视频一区二区三区 | 91亚洲精品在线观看 | 亚洲国产剧情av | 日韩视频在线不卡 | 美女一二三区 | 香蕉色综合 | 亚洲精品久久久蜜臀下载官网 | 日韩高清精品一区二区 | 黄网站色视频 | 欧美男同视频网站 | 91精品国产91久久久久福利 | 婷婷视频在线观看 | 国产一二三在线视频 | 婷婷激情5月天 | 99热只有精品在线观看 | 久久精品国产99国产 | 亚洲涩涩色 | 福利电影一区二区 | 天堂av在线7 | 免费看一级特黄a大片 | 国产中文字幕在线看 | 精品99久久久久久 | 天天碰天天操 | 欧美激情综合色综合啪啪五月 | 欧美极品在线播放 | 久久久久这里只有精品 | 国产成人av免费在线观看 | 激情网五月 | 久久精品视频国产 | 一本一道波多野毛片中文在线 | 亚洲精品小区久久久久久 | 草久视频在线观看 | 99视频在线观看视频 | 精品在线观看一区二区 | 麻豆影视在线观看 | 在线观看免费日韩 | 欧美激情精品久久久久久 | 久久精品爱爱视频 | 成年人视频在线免费观看 | 日韩中文在线视频 | 玖玖玖在线观看 | 黄色大片日本免费大片 | 国产99久久精品一区二区永久免费 | av线上免费观看 | 91日韩在线播放 | 久久久久久久久久久久影院 | 亚洲成色777777在线观看影院 | 涩涩网站在线观看 | 日产乱码一二三区别免费 | 国产成人精品一区在线 | 日本在线观看一区二区 | 亚洲1区 在线 | 日韩精品一区二区三区电影 | 碰碰影院| a在线免费 | 婷婷丁香视频 | 国产福利一区二区在线 | 麻豆一区二区三区视频 | 国产成人精品一区二区三区免费 | 久久久www成人免费精品 | 伊人久操 | 国产又粗又猛又爽又黄的视频免费 | 亚洲最快最全在线视频 | 五月激情丁香图片 | 免费av片在线| 国产最顶级的黄色片在线免费观看 | 最近中文字幕高清字幕在线视频 | 国产亚洲情侣一区二区无 | 不卡国产在线 | 日本少妇视频 | 国产又粗又猛又色 | 天天综合入口 | 伊人春色电影网 | 97精品国自产拍在线观看 | 极品久久久久 | 色综合久久88色综合天天免费 | 国产中文字幕视频在线观看 | 97超级碰碰碰视频在线观看 | 欧美在线视频二区 | 日韩在线视频网 | 成人午夜性影院 | 91亚洲夫妻 | 黄色毛片电影 | 少妇视频一区 | 欧美日韩啪啪 | 日韩av手机在线看 | av大片网站 | 欧美日韩超碰 | 亚洲精品乱码久久久久久蜜桃不爽 | 欧美综合在线视频 | 一区二区三区三区在线 | 天天综合在线观看 | 日韩免费网址 | 久草视频在线资源站 | 国产一区二区三区黄 | 欧美日韩在线免费视频 | 91人人爽久久涩噜噜噜 | 人人爽人人舔 | 成人在线观看免费视频 | 一区二区三区免费在线观看视频 | av观看久久久 | 91麻豆看国产在线紧急地址 | 99久久精品久久久久久动态片 | 在线看片视频 | 日本精品久久久久 | 欧美一区二区三区免费观看 | 国产成人一区二区三区在线观看 | 精品久久久99 | 天天射成人| 亚州日韩中文字幕 | 国产精品资源 | 婷婷激情综合五月天 | a资源在线 | 国产剧情在线一区 | 国产激情电影综合在线看 | www.色婷婷 | 97网站| 国产亚洲精品久久久久久久久久久久 | 国产福利av在线 | 日韩精品一区二区三区三炮视频 | 97av免费视频 | 精品久久91| 国产高清日韩欧美 | 久热免费在线观看 | 福利视频午夜 | 国产精品爽爽久久久久久蜜臀 | 色99色| 中文字幕专区高清在线观看 | 日韩成人免费观看 | 国产精品白虎 | 成人91在线| 久久国产经典 | 亚洲欧美怡红院 | 99色视频 | 黄污网站在线观看 | 成人在线免费观看网站 | 成人免费视频网站在线观看 | 国产一二三精品 | 精品无人国产偷自产在线 | 亚洲va欧美va人人爽春色影视 | 久草网免费| 国产精品白浆 | 91网址在线 | 精品字幕在线 | 九九热精品国产 | 久久免费的视频 | 国产高清久久久 | 久久久久久久久久久综合 | 黄网站污 | 成人小视频在线观看免费 | 久久人人爽人人人人片 | 最新日韩电影 | 色黄视频免费观看 | 国产专区在线播放 | 97视频在线观看网址 | 久久精品xxx | 日韩av午夜 | 国产精品你懂的在线观看 | 2019av在线视频 | 日韩欧美综合 | 国产成人一区在线 | 国产精品一区二区三区电影 | 国内精品久久久久影院一蜜桃 | 天天干天天色2020 | 久久99影院 | 久久久片| 999在线观看视频 | 爱爱av在线 | 久久久91精品国产一区二区精品 | 久久这里精品视频 | 日韩高清免费电影 | 狠狠狠狠狠狠天天爱 | 99精品国产福利在线观看免费 | 天天操天天摸天天干 | 中字幕视频在线永久在线观看免费 | 久久久久国产一区二区三区四区 | 另类老妇性bbwbbw高清 | 99热国产精品 | 色综合婷婷久久 | 四虎在线免费观看 | 午夜av片| 韩日精品在线 | 97免费公开视频 | 99久久婷婷国产一区二区三区 | 麻豆视频免费在线观看 | 精品在线播放视频 | 欧洲精品视频一区二区 | 精品国产乱码久久久久久1区2匹 | 干天天| 欧美日韩一级视频 | 免费看91的网站 | 久久久久久久久久免费视频 | 91成人午夜| 色美女在线 | 激情综合六月 | 99热.com| 精品国产成人在线 | 国产成人三级在线观看 | 国产淫片免费看 | 久久在线视频精品 | 久久久久久久久网站 | 国产精品视频永久免费播放 | 免费观看性生交大片3 | 天天干国产 | 国内揄拍国内精品 | 久久国产精品一区二区三区四区 | 国产原创av在线 | 国产精品麻豆果冻传媒在线播放 | 日本特黄特色aaa大片免费 | 免费情趣视频 | 超碰精品在线 | 成人aⅴ视频 | 国产一区高清在线 | 精品99在线观看 | 中文字幕av有码 | 中文字幕一区二区三区在线视频 | aav在线| 成年人在线观看视频免费 | 91理论片午午伦夜理片久久 | 国产精品久久久久久婷婷天堂 | 久久精精品视频 | 久久99热精品 | 99视频在线免费播放 | 五月婷婷毛片 | 视频在线观看国产 | 日韩欧美视频在线免费观看 | 亚洲人av免费网站 | 欧美韩国在线 | 日韩精品久久一区二区三区 | 丁香综合 | 国产18精品乱码免费看 | 97精品视频在线播放 | 一级理论片在线观看 | 日本黄色免费大片 | 成人在线一区二区 | 超碰av在线播放 | 亚洲手机天堂 | 伊人久久在线观看 | 国产精品com| 91av视频网 | 久久久久久久久久久久久久免费看 | 成人免费网视频 | 免费观看一区二区三区视频 | 国产日韩欧美在线播放 | 欧美成人性战久久 | www久| 欧美性久久久 | 美女在线免费视频 | 亚洲精品久久久久中文字幕m男 | 一级电影免费在线观看 | 93久久精品日日躁夜夜躁欧美 | 国产精品美女在线 | 中文在线天堂资源 | 超级碰碰免费视频 | 丁香 婷婷 激情 | 狠狠操夜夜操 | av一区在线播放 | 国产专区日韩专区 | 亚洲一区欧美激情 | 99re亚洲国产精品 | 久久免费视频6 | 国产精品成人一区 | 久久男人中文字幕资源站 | 成人网在线免费视频 | 欧美一级免费高清 | 国产一区成人在线 | 美女免费黄网站 | 精品亚洲va在线va天堂资源站 | 午夜精品一二三区 | 欧美成人tv | 奇米导航| 国产一区二区精品久久91 | av在线免费在线观看 | 久久精品小视频 | 亚洲欧美日本一区二区三区 | 国产视频亚洲精品 | 日本最新一区二区三区 | av千婊在线免费观看 | 亚洲第一久久久 | 色搞搞| 婷婷网站天天婷婷网站 | 日韩极品在线 | 色综合久久网 | 99久久99久久精品国产片 | 日韩高清免费在线 | 欧美日韩在线播放一区 | 在线观看激情av | 国产探花视频在线播放 | 综合色婷婷| 久久国产亚洲精品 | 超黄视频网站 | 亚洲jizzjizz日本少妇 | 国产婷婷一区二区 | 日韩欧美视频 | 天天操夜夜爱 | 国产精品手机看片 | 国内精品久久久久久久久久清纯 | 欧美日韩不卡一区二区 | 久久夜av | 91传媒在线看 | 欧美日韩国产色综合一二三四 | 久久久久在线观看 | 欧美日韩国产精品一区二区亚洲 | 天堂av在线免费观看 | 国产玖玖在线 | 91视频久久久 | 人人插人人玩 | a在线观看视频 | 91资源在线播放 | 黄色软件视频大全免费下载 | 在线之家官网 | 国产在线观看高清视频 | 欧美另类xxxx | 免费黄av| 国产精品久久久久久久7电影 | 97精品伊人 | 黄av免费在线观看 | 一区二区三区电影在线播 | 激情av一区二区 | 中文字幕一区二区在线播放 | 精品二区久久 | 免费看的黄色的网站 | 韩日在线一区 | 免费在线观看av的网站 | 国产精品久久艹 | 九九热99视频 | 91免费观看国产 | 天天天在线综合网 | 美女网站黄免费 | 在线观看av国产 | 国产在线精品观看 | 国产精品乱码久久久 | 四虎影视成人精品 | 欧美一区成人 | 亚洲91精品在线观看 | 天天视频亚洲 | 狠狠干综合 | 久久久久久久久久久久久影院 | 欧美动漫一区二区三区 | 制服丝袜天堂 | 亚洲欧美色婷婷 | 九七视频在线 | 成年人在线免费视频观看 | 中文字幕精品一区二区精品 | 国产精品mm | 亚洲色视频 | 日韩在线观看的 | 黄色大片网 | 人人模人人爽 | 国产福利91精品 | av电影不卡 | 在线观看日韩精品 | 在线视频日韩欧美 | 免费看片网页 | 97超碰在线免费观看 | 91精品成人久久 | 国产亚洲91| www.com久久| 国内外成人免费在线视频 | 可以免费观看的av片 | 精品久久久久久久久久 | 国产精品大片免费观看 | 国产超碰在线观看 | 国产白浆视频 | 亚洲精品视频在线观看免费视频 | 国语精品视频 | 2023天天干 | 欧美 亚洲 另类 激情 另类 | 久久久久久亚洲精品 | 天天干天天射天天爽 | 色婷婷激情四射 | 曰本免费av | 色视频成人在线观看免 | 亚洲国产免费 | 男女啪啪免费网站 | 精品国产一区二区三区不卡 | 久久成人亚洲欧美电影 | www视频在线免费观看 | 91成人精品一区在线播放69 | 99久久精品国产欧美主题曲 | 一二三区在线 | 激情丁香 | 九九在线国产视频 | 五月婷婷视频在线 | 亚洲女在线 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 人人澡超碰碰97碰碰碰软件 | 亚洲精品乱码久久久久久蜜桃动漫 | 高清不卡一区二区三区 | 国产精品 亚洲精品 | 激情www| 九九久久影院 | 九草在线观看 | 久久久久久久久福利 | 在线观看国产www | 免费av电影网站 | 欧美一级视频免费看 | 久久国产美女 | 日本一区二区高清不卡 | 蜜桃视频成人在线观看 | 国产精品久久久久久a | 国产精品一区久久久久 | 奇米影视8888 | 国产福利精品一区二区 | 久久国产精品免费一区二区三区 | 久久久免费精品视频 | 有没有在线观看av | 国产福利专区 | 久久精彩免费视频 | 精品一区在线看 | 在线视频一区二区 | av色网站 | 黄色a在线| 一区二区三区国产精品 | 91成人破解版 | 人人看黄色 | 韩国av在线播放 | 国产精品成人自产拍在线观看 | 精品国产一区二区三区在线 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 午夜精选视频 | 五月婷网 | 中文字幕丰满人伦在线 | 色av男人的天堂免费在线 | 日本中文字幕电影在线免费观看 | 手机在线小视频 | 国产一级视频在线免费观看 | 国产精品一区二区久久久 | 久久国产视频网站 | 免费特级黄色片 | 国产日韩欧美在线看 | 欧美一级裸体视频 | 国产丝袜一区二区三区 | 国产黄免费看 | www麻豆视频| 久久视频一区 | 少妇bbw搡bbbb搡bbbb | 欧美片一区二区三区 | 在线观看视频精品 | 丁香婷婷激情国产高清秒播 | 97香蕉视频 | 久久精品精品 | 国产无遮挡又黄又爽在线观看 | 美女视频黄免费网站 | 国产99久久九九精品 | 伊人色**天天综合婷婷 | 亚洲人片在线观看 | 成人免费在线观看入口 | 最新国产在线观看 | 成人在线免费看 | 成人免费一级 | 992tv又爽又黄的免费视频 | 亚洲精品国产精品乱码不99热 | av免费福利 | 中文字幕av最新更新 | 亚洲永久国产精品 | 成人福利在线观看 | 亚洲成人网av | 日韩午夜电影 | 日韩欧美有码在线 | a久久久久久 | 97看片吧| 一区二区在线影院 | 日韩三级视频 | 亚洲精品在线观看不卡 | 久久免费a | 中文字幕制服丝袜av久久 | 国产一级二级三级视频 | 97超视频免费观看 | 国产精品毛片久久蜜 | 久久九九久久精品 | 成人日韩av | 天天操天天色综合 | 深爱激情综合 | 五月婷香蕉久色在线看 | 中文字幕欧美日韩va免费视频 | 国产成人精品日本亚洲999 | 久久国产精品免费一区二区三区 | 五月天中文在线 | 中文字幕乱码日本亚洲一区二区 | 99在线观看视频 | 精品国产一区二区三区久久影院 | 亚洲免费不卡 | 97超级碰碰| 婷婷色狠狠 | 欧美日韩精品网站 | 免费观看v片在线观看 | 在线免费观看亚洲视频 | 婷婷色中文 | 黄色大片日本 | 国产精品12| 成人免费xyz网站 | 中文不卡视频 | 欧美成人区 | 天天射综合网站 | 黄色片亚洲 | 国产九九精品视频 | 91精品小视频 | 亚洲五月综合 | 一二区电影 | 能在线看的av | 日日日日| 98久9在线 | 免费 | 日韩av女优视频 | 久久精品视频在线看 | 特级黄色片免费看 | 国产男女免费完整视频 | 亚洲激情五月 | 成年人免费在线看 | 黄色www| 久草视频99 | 美女黄频视频大全 | 91免费视频网站在线观看 | 久久理论影院 | 亚洲v欧美v国产v在线观看 | 国产亚洲人成网站在线观看 | 国产亚洲精品久久久久久大师 | 狠狠狠狠狠狠狠干 | 国产中文自拍 | 日韩av一区二区三区在线观看 | 日韩在线网址 | 在线观看日韩精品 | 日韩免费福利 | 精品国产乱码久久久久 | 精品国产片 | 久久综合综合久久综合 | 黄色1级大片 | 91热爆视频 | 欧美亚洲一区二区在线 | 91av网址 | 亚洲aⅴ免费在线观看 | 色先锋资源网 | 三级午夜片 | 人人精品 | 日本韩国精品一区二区在线观看 | 日本九九视频 | 伊人婷婷综合 | 欧美性色综合 | 高清免费在线视频 | 国产一区福利在线 | 一本一本久久aa综合精品 | 日韩在线视频线视频免费网站 | 天天插综合网 | 国产精品久久久久久久免费大片 | 久久黄色网址 | 99精品在线观看视频 | 2019中文字幕第一页 | 婷婷在线看 | 国产精品理论片在线播放 | 激情久久一区二区三区 | 成人啊 v | 亚洲综合婷婷 | 性色av免费在线观看 | 成片视频在线观看 | 婷婷视频在线 | 国产精品久久久久久久久久久久午 | 日韩性色 | 国产成人av网站 | 国产91学生粉嫩喷水 | 亚洲人久久久 | 成人97人人超碰人人99 | 日韩在线视频一区 | 国产最新精品视频 | 久久亚洲二区 | 日韩在线视频免费看 | 91大神dom调教在线观看 | 黄色亚洲大片免费在线观看 | 国产精品毛片一区 | 国产又粗又猛又黄视频 | 精品在线一区二区 | 久草在线视频首页 | 最近中文字幕大全中文字幕免费 | 亚洲精品自拍 | 91成人区| 日韩视频免费播放 | 久久美女电影 | 亚洲国产精品va在线 | 欧美性极品xxxx娇小 | 国产精品久久99综合免费观看尤物 | 日韩在线免费看 | 在线视频国产区 | 天天躁天天操 | 国产日本亚洲 | 久久综合中文字幕 | 亚洲成人黄色在线观看 | 久久国产品 | 国产日韩欧美在线一区 | 欧美一区二视频在线免费观看 | 亚洲综合精品在线 | 日日综合 | 国产成年人av| 国产一区二区日本 | 国产精品嫩草在线 | 国产在线a免费观看 | 四虎www com | 国产字幕在线看 | 亚洲视频1 | 在线播放日韩av | 国产黄在线 | 久久久免费少妇 | 免费在线激情电影 | 最近日本中文字幕a | 国产一区电影在线观看 | 在线观看aa | 国产精久久 | 中文字幕色在线视频 | www亚洲精品 | 国产一级特黄毛片在线毛片 | 中文字幕在线日 | 中文字幕乱码日本亚洲一区二区 | 亚洲视频在线免费观看 | 色欧美88888久久久久久影院 | 欧美精品一区在线 | 欧美一级电影免费观看 | 日韩三级久久 | 亚洲一级特黄 | 又爽又黄又无遮挡网站动态图 | 国产成人在线综合 | 亚洲国产成人精品在线 | 人人干狠狠操 | 久久国产精品视频免费看 | 粉嫩av一区二区三区四区 | 碰超人人 | 国产一二三区av | 色视频成人在线观看免 | 亚洲午夜精品福利 | 五月婷婷六月综合 | 欧美另类性 | 久久久久久久久久久高潮一区二区 | 久久免费电影 | 久久免费99精品久久久久久 | 中文字幕亚洲精品在线观看 | 97看片网 | 免费观看一级成人毛片 | 久久久久国 | 国产91亚洲精品 | 婷婷色 亚洲 | 五月激情久久久 | 最新婷婷色| 亚洲永久精品在线 | 91精选 | 国产伦精品一区二区三区无广告 | 欧美xxxx性xxxxx高清 | 国产精品成人久久久久 | 国产亚洲一区二区在线观看 | 国产在线观看91 | 97超碰超碰 | 麻豆成人小视频 | 在线小视频国产 | 欧美不卡视频在线 | 国产精品com| 久久免费毛片 | 久久视频免费 | 99热手机在线 | 国产免费一区二区三区最新6 | 最近中文字幕免费大全 | 97香蕉久久国产在线观看 | 超级碰碰视频 | 欧洲一区二区三区精品 | 97久久精品午夜一区二区 | 久草在线综合 | 五月综合激情婷婷 | 四虎影视国产精品免费久久 | 91香蕉视频好色先生 | 2018好看的中文在线观看 | www免费黄色 | 狠狠操天天射 | 91九色在线观看视频 | 黄色av网站在线观看免费 | 91视频成人免费 | 麻豆传媒视频在线播放 | 中文字幕在线国产精品 | 久久国产女人 | 日韩色爱 | 99视频在线精品免费观看2 | 国产精品1区2区3区在线观看 | 成人动态视频 | 精品国产伦一区二区三区观看体验 | 成人免费视频免费观看 | 午夜av大片 | 日韩欧美视频 | 免费在线观看国产精品 | 欧美精品亚洲精品日韩精品 | www欧美日韩| 成人在线观看免费视频 | 久久婷婷一区 | 久久久国产一区 | 国产精品高潮在线观看 | 日韩手机在线观看 | 干干操操| 日韩亚洲精品电影 | 久久久久久亚洲精品 | 91.精品高清在线观看 | 午夜视频久久久 | 国产在线观看a | 国产原创av在线 | 最近中文字幕在线播放 | 欧美电影黄色 | 日本三级中文字幕在线观看 | 欧美a视频在线观看 | 天天操天天干天天摸 | 国产成人免费在线 | 伊人五月综合 | 久久久久成人精品 | 国产亚洲精品日韩在线tv黄 | 亚洲一区二区三区四区在线视频 | 一区二区三区视频网站 | 日日操操操 | 欧美色综合久久 | 亚洲精品午夜久久久久久久久久久 | 久久久久99999 | 日韩在线视频观看免费 | 天天操夜夜操夜夜操 | 欧美91成人网 | 最近高清中文字幕 | 欧美日韩国产在线精品 | 国产精品无 | 精品国内自产拍在线观看视频 | 国内精品久久久久久久97牛牛 | 国产 中文 日韩 欧美 | 激情五月伊人 | 国产精品系列在线 | 久久久国产在线视频 | 久久久午夜电影 | 色小说av | 天天操天天色综合 | 国产一级黄色片免费看 | 亚洲免费视频在线观看 | 欧美一区二区在线免费看 | 色视频在线看 | 中文字幕欲求不满 | 999久久a精品合区久久久 | 国产日产欧美在线观看 | 免费a级观看 | 日日夜夜天天久久 | 九九精品在线观看 | 免费福利视频导航 | 免费看片成人 | 久久影视一区 | 免费进去里的视频 | 五月天天天操 | 九九九九九精品 | 久久理论电影 | 九九热免费在线视频 | 久久国产经典 | 免费h视频 | 狠狠躁日日躁夜夜躁av | 99精彩视频在线观看免费 | 99在线观看免费视频精品观看 | 深爱激情五月网 | 中文有码在线视频 | 欧美精品中文字幕亚洲专区 | 超碰在线91 | 91精品1区2区 | 色婷婷av一区 | 精品久久久久久久久久久久久久久久久久 | 国产精品成人aaaaa网站 | 免费av一级电影 | 亚洲精品久久久久中文字幕m男 | 中文字幕在线观看av | 超碰成人网 | 久久试看| 国产精品 9999 | 男女拍拍免费视频 | 国产高清av免费在线观看 | 国产涩图 | 欧美一级xxxx | 黄色软件视频大全免费下载 | 久久这里有| 日本公妇色中文字幕 | 91看片在线免费观看 | 午夜精品一区二区三区免费视频 | 免费看片网址 | 欧美日一级片 | 成片人卡1卡2卡3手机免费看 | 天天激情综合网 | 91在线观看视频网站 | 天天人人综合 | 美国av片在线观看 | 国产精品中文 | 天天色官网 | 久久久免费视频播放 | 精品视频免费久久久看 | 亚洲另类视频在线 | 精品一区二区6 | 日韩精品视频久久 | 激情欧美一区二区三区 | 亚洲爽爽网 | 国产精品不卡在线 | 一区二区三区电影 | 精品国产一区二区三区久久久久久 | 国产一区二区三区黄 | av高清一区二区三区 | 成人在线观看av | 日本在线h | 99在线高清视频在线播放 | 在线观看一级视频 | 日韩精品一区二 | 亚洲精品国产日韩 | 久久亚洲私人国产精品va | 免费看三级黄色片 | 99精品久久99久久久久 | 亚洲女同ⅹxx女同tv | 激情五月婷婷综合 | 国产亚洲一区二区三区 | av三级在线看 | 一区二区三区影院 | 五月天天在线 |