转载︱案例 基于贪心算法的特征选择

转载︱案例 基于贪心算法的特征选择

用GA算法设计22个地点之间最短旅程-R语言实现

————————————————————————————————————————————————————————

greedy Algorithm Feature Selection

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑, 它所做出的是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心 策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

算法设计:

  1. 初始化问题的目标值
  2. while(实现优化目标的约束条件){

    利用筛选策略,求出解空间的一个可行解

    }

  3. 将所有可行解组合成目标解空间。
options(warn = -1)
require(magrittr)
require(dplyr)
require(glmnet)
# Greedy Algorithm
GreedyAlgorithm = function(dataSet) {
  # 基于逻辑回归,以AUC作为评价指标,采用贪心算法进行特征筛选
  #
  # Args:
  #   dataSet: A dataframe that contains a feature "label"
  #
  # Returns:
  #   A vector of selected features
  features = data.frame(name = colnames(dataSet)) %>%
    dplyr::filter(name != "label")  # select all features of the dataSet except "label"
  features = as.vector(features$name)    
  featureSelect = c("label")  # init the feature vector to be selected
  scoreBefore = data.frame()  # init the storage whice stores the (feature,aucScore) tuple from the end of each iteration
  while((nrow(scoreBefore)<2||scoreBefore[length(scoreBefore),2]>
        scoreBefore[length(scoreBefore) - 1,2])&&nrow(scoreBefore)<length(features)){
    score = data.frame()
    for(feature in features){
      if(length(intersect(feature,featureSelect)) == 0){
        trainData = dataSet[,append(featureSelect,feature)]
        model = glm(label~.,family = "binomial",data = trainData,epsilon = 1e-10)
        prediction = predict(model,trainData)
        aucValue = auc(trainData$label,prediction)
        score = rbind(score,data.frame(feature = feature,aucValue = aucValue))
      }
    }
    featureSelect = unique(append(featureSelect,as.character(score[which.max(score$aucValue),1])))
    scoreBefore = rbind(scoreBefore,score[which.max(score$aucValue),])
  }
  featureSelect = head(featureSelect,length(featureSelect)-1)  # delete the last feature that can‘t fit the iteration condition
  return(featureSelect[-1])  # reture the selected features except "label"
}

KS值表征了模型将正例和负例区分开来的能力。值越大,模型的预测准确性越好。通常情况下,KS>0.3即可认为模型有比较好的预测准确性。

KS值计算方法:

将所有样本根据预测得分从低到高排序均分成N组,分别计算这N组的实际好样本数、坏样本数、累积好样本数、累积坏样本数、累积好样本数占比、 累积坏样本数占比,差值。其中,实际好坏样本数分别为该组内的好坏样本数,累积好坏样本数为该组累积的好坏样本数,累积好坏样本数占比为 累积好坏样本数占总好坏样本数的比值,差值为累积坏样本数占比减去累计好样本数占比。KS指标为差值绝对值的最大值。

# ksValue
KsValue = function(prediction,n){
  # Compute the ks value of a model
  #
  # Args:
  #   prediction: A vector that the prediction of a model
  #   n: The group number
  #
  # Returns:
  #   A vector that the difference value between the rate cumulative bad sample and the rate of cumulative good sample
  dataResult = sort(prediction,decreasing = T)
  a = c()
  b = c()
  c = c()
  a[1] = 0
  b[1] = 0
  c[1] = 0
  if(length(dataResult)%%n==0){
    cut = length(dataResult)/n
    for (i in 2:(n+1)) {
      a[i] = sum(dataResult[(cut*(i-2)+1):(cut*(i-1))])
      b[i] = length(dataResult[(cut*(i-2)+1):(cut*(i-1))])-a[i]
    }
  }else{
    cut = round(length(dataResult)/n)
    for (i in 2:n) {
      a[i] = sum(dataResult[(cut*(i-2)+1):(cut*(i-1))])
      b[i] = length(dataResult[(cut*(i-2)+1):(cut*(i-1))])-a[i]
    }
    a[n+1] = sum(dataResult[(cut*(n-2)+1):(cut*(n-1))])
    b[n+1] = length(dataResult[(cut*(n-2)+1):(cut*(n-1))])-a[n+1]
  }
  c = abs(cumsum(a)/sum(a)-cumsum(b)/sum(b))
  return(c)
}
require(caret)
require(pROC)
data = read.csv("/data/workspace/Rworkspace/data_test.csv",encoding = "UTF-8")
data %<>%
  mutate(label = ifelse(target>30,1,0))
data = data[,-1]
data = data.frame(apply(data, 2, function(x) ifelse(is.na(x),median(x,na.rm = T),x)))
# 剔除近似常量的变量
# feature1 = nearZeroVar(data)
# data = data[,-feature1]
# 剔除相关度过高的自变量
# dataCor = cor(data)
# highcor = findCorrelation(dataCor,0.8)
# data = data[,-highcor]
# 利用贪心算法进行特征选择
# feature = GreedyAlgorithm(dataSet = data)
load("/data/workspace/Rworkspace/featureSelect.RData")  # 数据量较大,生成html过程中该算法比较耗时,所以直接加载测试时已经选取的特征
set.seed(521)
ind = base::sample(2,nrow(data),replace=T,prob=c(0.7,0.3))
trainData = data[ind==1,]
testData = data[ind==2,]
model = cv.glmnet(as.matrix(trainData[,feature]),trainData[,"label"],
                    family = "binomial",type.measure = "auc",alpha = 0,
                    lambda.min.ratio = 0.0001)
prediction = predict(model,as.matrix(testData[,feature]),s="lambda.min",type="response")
# compute ksValue
ksValue = KsValue(prediction,10)
par(mfrow = c(2,1))
plot(density(ksValue),type = ‘l‘,main = "ksValue Plot",xlab = "cutPoint",ylab = "density_ks")
ks_value = max(ksValue)
text(.2,1.0,paste("ksValue = ",ks_value))
roc(testData$label, as.vector(prediction), auc = T,plot = T,print.auc=T)

##
## Call:
## roc.default(response = testData$label, predictor = as.vector(prediction),     auc = T, plot = T, print.auc = T)
##
## Data: as.vector(prediction) in 5130 controls (testData$label 0) < 429 cases (testData$label 1).
## Area under the curve: 0.7385
par(mfrow=c(1,1))

 

时间: 2024-12-25 16:45:07

转载︱案例 基于贪心算法的特征选择的相关文章

基于贪心算法求解TSP问题(JAVA)

前段时间在搞贪心算法,为了举例,故拿TSP来开刀,写了段求解算法代码以便有需之人,注意代码考虑可读性从最容易理解角度写,没有优化,有需要可以自行优化! 一.TSP问题 TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市.路径的选择目标是要求得的路径路程为所有路径之中的最小值. TSP问题

贪心算法求解活动选择问题

问题描述:  有一个需要使用每个资源的n个活动组成的集合S= {a1,a2,···,an },资源每次只能由一个活动使用.每个活动a都有一个开始时间和结束时间,且 0<= s < f .一旦被选择后,活动a就占据半开时间区间[s,f].如果[si,fi]和[sj,fj]互不重叠,则称两个ai,aj活动是兼容的.该问题就是要找出一个由互相兼容的活动组成的最大子集.假设输入的活动集合S已经按照结束时间的单调递增顺寻进行了排序. i 1 2 3 4 5 6 7 8 9 10 11 si 1 3 0

贪心算法正确性证明(转载from刘子韬)

这里主要是介绍一种证明贪心算法是最优的一种方法:Exchange Argument (不知道应该怎么翻译到中文,交换参数?感觉听起来挺别扭的,不像是一个方法的名字~o(╯□╰)o) Exchange Argument的主要的思想也就是 先假设 存在一个最优的算法和我们的贪心算法最接近,然后通过交换两个算法里的一个步骤(或元素),得到一个新的最优的算法,同时这个算法比前一个最优算法更接近于我们的贪心算法,从而得到矛盾,原命题成立. 下面来看一个更为formal的解释: 步骤: Step0: 给出贪

【转载】夜深人静写算法(四)——差分约束

[转载]夜深人静写算法(四) - 差分约束  目录     一.引例       1.一类不等式组的解   二.最短路       1.Dijkstra       2.图的存储       3.链式前向星       4.Dijkstra + 优先队列       5.Bellman-Ford       6.SPFA       7.Floyd-Warshall   三.差分约束        1.数形结合        2.三角不等式        3.解的存在性        4.最大值

五大常用算法之三贪心算法

贪心算法 贪心算法简介: 贪心算法是指:在每一步求解的步骤中,它要求"贪婪"的选择最佳操作,并希望通过一系列的最优选择,能够产生一个问题的(全局的)最优解. 贪心算法每一步必须满足一下条件: 1.可行的:即它必须满足问题的约束. 2.局部最优:他是当前步骤中所有可行选择中最佳的局部选择. 3.不可取消:即选择一旦做出,在算法的后面步骤就不可改变了. 贪心算法案例: 1.活动选择问题  这是<算法导论>上的例子,也是一个非常经典的问题.有n个需要在同一天使用同一个教室的活动a

贪心算法练习(一)

贪心算法_删数问题 AYYZOJ p1420 删数问题,算法在上一篇中讲得很详细,注意最后输出数前的零要去掉. 1 var n:string; 2 s,i:integer; 3 begin 4 readln(n); 5 readln(s); 6 while s>0 do 7 begin 8 i:=1; 9 while(i<length(n))and(n[i]<=n[i+1])do inc(i); 10 delete(n,i,1); 11 dec(s); 12 end; 13 while

贪心算法:最优装载问题

/*----------------------------------------------------- 给出n个物体,第i个物体的重量为wi. 选择尽量多的物体,使得总重量不超过C. 输入: n和C以及n个整数表示的wi. 输出: 按照输入物体的顺序输出n个用空格分隔的Y或N. Y表示该物体被选中,N表示不被选中. 最后一行输出所选中的物体的个数num和总重量w,用空格分隔. 注意:这个地方每个物体是不可再分割的整体. 思路: 先把所有物体按重量排序(从小到大排序) , 然后贪心选择重量

贪心算法练习:乘船问题

/*-------------------------------------------------------------- 有n个人,第i个的重量为wi,每艘船的最大载重为c, 而且最多只能乘两个人.用最少的船装载所有人. 输入: 第一行两个整数n和c 第二行n个整数,分别是wi 输出: 第一行输出使用船的数量num 第二行到第n+1行每行输出两个数, 分别“人的编号”以及他所乘坐的“船的编号”. 人的编号按输入的顺序从1到n编号.船的编号从1开始编号. 第2行到第n+1行按人的编号从小到

贪心算法总结——读书笔记

1.基本概念 贪心算法是一种求解组合优化问题的算法设计技术,其求解过程由一系列决策构成, 每一步决策仅依赖于某种局部优化的性质. 与动态规划算法不同,贪心算法在做决策时候不必考虑所有子问题的选择结果. 贪心算法适用的条件 问题的求解可以由一系列的决策步骤构成,每步决策依赖于某种局部最优的贪心策略.正确的贪心策略要保证每一步基于局部优化性质的选择最终导致全局的最优解. 如果不具有上述性质,贪心法对某些实例只能得到近似解. 主要设计步骤: 将问题的求解看作是一系列的决策: 确定每一步决策所依据的局部