巴黎銀行貸款預測:誰能快速拿到貸款
https://www.kaggle.com/c/bnp-paribas-cardif-claims-management
煉數(shù)成金里的kaggle課程提過這個案例,對我而言比較特別的是combination函數(shù)的應用。在某位大神的方案里用了這個方法,下面分析一下:
首先看一下數(shù)據(jù),共有11萬4千多行,131個特征變量。

然后大神就簡單粗暴的把所有空缺值賦為-1(我上一篇帖子大概白寫了...)
再把id列刪掉,另外賦給兩個數(shù)據(jù)框。
data.train[is.na(data.train)] <- -1
data.test[is.na(data.test)] <- -1
x.train <- data.train[, -1]
y.train <- data.train$target
x.test <- data.test[, -1]
第二步,大刀闊斧的刪去不重要的值,
omit.var <- c(1:3,4:9,11,13,15:20,23,25:29,32:33,35:37,39,41:46,48:49,51,53:55,57:61,63:65,67:71,73:74,76:78,80:90,92:107,108:111,115:128,130:131)
x.train <- x.train[, -(omit.var+1)]
x.test <- x.test[, -omit.var]
這時x.train和x.test只有25個特征變量了。x.train比test多個target列。

刪掉哪些值當然也是各位大神反復試驗出來的,另外,發(fā)現(xiàn)v22列有特殊的意義!
這是cutomer id,所以大神們做了各種組合。案例這位就用了combination函數(shù),把customerid和其它字符串值結(jié)合起來。
第三步,將字符串的變量名歸到一個新的變量集
char.vars <- colnames(x.train)[sapply(x.train, is.character)]

然后,每次從這個數(shù)據(jù)集里隨機抽取兩個變量,兩兩組合,形成v22v24,v56v66這種新特征變量。并加入到train和test數(shù)據(jù)框后面。
cmb <- combinations(n=length(char.vars), r=2, v=char.vars)
#這時候cmd是可能含有v22的變量組合,比如v22v24,
for(i in 1:nrow(cmb)) {
x.train[[paste0(cmb[i,1], cmb[i,2])]] <- paste(x.train[[cmb[i,1]]], x.train[[cmb[i,2]]])
x.test[[paste0(cmb[i,1], cmb[i,2])]] <- paste(x.test[[cmb[i,1]]], x.test[[cmb[i,2]]])
}

再然后,再從這個數(shù)據(jù)集里抽出不是v22的兩個變量,繼續(xù)兩兩組合,再加上v22前綴,又形成新的特征變量,并賦給train和test,比如v22v56v66
cmb <- combinations(n=length(char.vars)-1, r=2, v=char.vars[-match("v22",char.vars)])
#這時候cmd是一定不含v22的組合比如v56v66
for(i in 1:nrow(cmb)) {
x.train[[paste0("v22", cmb[i,1], cmb[i,2])]] <- paste(x.train[["v22"]], x.train[[cmb[i,1]]], x.train[[cmb[i,2]]])
x.test[[paste0("v22", cmb[i,1], cmb[i,2])]] <- paste(x.test[["v22"]], x.test[[cmb[i,1]]], x.test[[cmb[i,2]]])
}
現(xiàn)在train和test的變量列已經(jīng)有170個了,比原來的還多。

第四步,是繼續(xù)變態(tài)的組合....把變量10個10個的組合,感覺已經(jīng)是被玩壞的節(jié)奏
cmb <- combinations(n=length(char.vars)-1, r=length(char.vars)-3, v=char.vars[-match("v22",char.vars)])
for(i in 1:nrow(cmb)) {
new.var.train <- x.train[["v22"]]
new.var.test <- x.test[["v22"]]
new.var.name <- "v22"
for(v in 1:ncol(cmb)) {
new.var.train <- paste(new.var.train , x.train[[cmb[i,v]]])
new.var.test <- paste(new.var.test, x.test[[cmb[i,v]]])
new.var.name <- paste0(new.var.name, cmb[i,v])
}
x.train[[new.var.name]] <- new.var.train
x.test[[new.var.name]] <- new.var.test
}
這里的雙重循環(huán)代碼我還不是很理解,大致是先按照行,再按照列的循環(huán)。如果自己來寫的話估計會寫錯...
用list(colnames(x.train))來看,又增加了不少新的特征變量,一共是236個。

下面我自己沒有運行出來,by=eval(var)那里總是報錯,就不班門弄斧了。僅附上源代碼供參考。
最后還是祭出了xgb大殺器,已經(jīng)是kaggle流行標配了。
# replace with target mean
for(var in colnames(x.test)) {
if(is.character(x.test[[var]])) {
target.mean <- x.train[, list(pr=mean(target)), by=eval(var)]
x.test[[var]] <- target.mean$pr[match(x.test[[var]], target.mean[[var]])]
temp <- rep(NA, nrow(x.train))
for(i in 1:4) {
ids.1 <- -seq(i, nrow(x.train), by=4)
ids.2 <- seq(i, nrow(x.train), by=4)
target.mean <- x.train[ids.1, list(pr=mean(target)), by=eval(var)]
temp[ids.2] <- target.mean$pr[match(x.train[[var]][ids.2], target.mean[[var]])]
}
x.train[[var]] <- temp
}
}
x.train <- as.matrix(x.train)
x.test <- as.matrix(x.test)
x.train <- matrix(as.numeric(x.train), nrow(x.train), ncol(x.train))
x.test <- matrix(as.numeric(x.test), nrow(x.test), ncol(x.test))
params <- list("eta"=0.1, "max_depth"=6,
"colsample_bytree"=0.45,
"objective"="binary:logistic",
"eval_metric"="logloss")
xgb.train <- xgb.DMatrix(x.train, label=y.train)
model.xgb <- xgb.train(param=params, data=xgb.train, nrounds=260, watchlist=list(train=xgb.train), print.every.n=50)
predict <- predict(model.xgb, x.test)
predict <- cbind(ID=data.test$ID, PredictedProb=predict)
write.csv(predict, paste0("Submission.csv"), row.names=FALSE)
運算結(jié)果應該是在30/1000名之內(nèi),這對于小白我來說,已經(jīng)是高不可攀的分數(shù)了...
總而言之,看來把變量各種組合也是算法的重要手段之一,在另一個競賽的帖子里,據(jù)說冠軍把20多個變量組合成了17000多個,也是服了。我們繼續(xù)努力吧!