R错误遗传编程实现

时间:2016-06-11 20:04:11

标签: r genetic-programming

所以我是R的新手。我昨天开始学习它,因为有一些数据非常不能自动导入Mathematica和Python。我正在构建一些机器学习技术来对我现在可以用R导入的数据进行分析。这是一个遗传编程实现,完成后应对某些数据进行符号回归。 (我还没有创建变异或交叉运算符,构建合法的函数列表等)。运行脚本时出现两个错误:

> Error: attempt to apply non-function
> print(bestDude)
> Error in print(bestDude) : object 'bestDude' not found

这是我的代码:

library("datasets")

#Allows me to map a name to each element in a numerical list.
makeStrName<-function(listOfItems)
{
  for(i in 1:length(listOfItems))
  {
        names(listOfItems)[i]=paste("x",i,sep="")
  }
  return(listOfItems)
}

#Allows me to replace each random number in a vector with the corresponding 
#function in a list of functions.

mapFuncList<-function(funcList,rndNumVector)
{
  for(i in 1:length(funcList))
  {
    replace(rndNumVector, rndNumVector==i,funcList[[i]])
  }
  return(rndNumVector)
}

#Will generate a random function from the list of functions and a random sample.
generateOrganism<-function(inputLen,inputSeed, functions)
{
  set.seed(inputSeed)
  rnd<-sample(1:length(functions),inputLen,replace=T)
  Org<-mapFuncList(functions,rnd)
  return(Org)
}

#Will generate a series of "Organisms"
genPopulation<-function(popSize,initialSeed,initialSize,functions)
{
  population<-list("null")
  for(i in 2:popSize)
  {
    population <- c(population,generateOrganism(initialSize,initialSeed, functions))
    initialSeed <- initialSeed+1
  }
  populationWithNames<-makeStrName(population)
  return(populationWithNames)
}

#Turns the population of functions (which are actually strings in "") into
#actual functions. (i.e. changes the mode of the list from string to function).

populationFuncList<-function(Population)
{
  Population[[1]]<-"x"
  funCreator<-function(snippet)
    txt=snippet
  function(x)
  {
    exprs <- parse(text = txt)
    eval(exprs) 
  }
  listOfFunctions <- lapply(setNames(Population,names(Population)),function(x){funCreator(x)})
  return(listOfFunctions)
}

#Applies a fitness function to the population. Puts the best organism in
#the hallOfFame.
evalPopulation<-function(populationFuncList, inputData,outputData)
{   
  #rmse <- sqrt( mean( (sim - obs)^2))

  hallOfFame<-list(1000000000)
  for(i in 1:length(populationFuncList))
  {
        total<-list()
        for(z in 1:length(inputData))
        {
          total<-c(total,(abs(populationFuncList[[i]](inputData[[z]])-outputData[[z]])))
        }
        rmse<-sqrt(mean(total*total))
                   if(rmse<hallOfFame[[1]]) {hallOfFame[[1]]<-rmse}
  }
  return(hallOfFame)
}

#Function list, input data, output data (data to fit to)
funcs<-list("x","log(x)","sin(x)","cos(x)","tan(x)")
desiredFuncOutput<-list(1,2,3,4,5)
dataForInput<-list(1,2,3,4,5)

#Function calls
POpulation<-genPopulation(4,1,1,funcs)
POpulationFuncList<-populationFuncList(POpulation)
bestDude<-evalPopulation(POpulationFuncList,dataForInput,desiredFuncOutput)
print(bestDude)

由于Hack-R的建议,代码现在正在运行。所以这是最终的代码,以防其他人遇到类似的麻烦。

library("datasets")

#Allows me to map a name to each element in a numerical list.
makeStrName<-function(listOfItems)
{
  for(i in 1:length(listOfItems))
  {
    names(listOfItems)[i]=paste("x",i,sep="")
  }
  return(listOfItems)
}

#Allows me to replace each random number in a vector with the corresponding 
#function in a list of functions.

mapFuncList<-function(funcList,rndNumVector)
{
  for(i in 1:length(funcList))
  {
    rndNumVector[rndNumVector==i]<-funcList[i]
  }
  return(rndNumVector)
}

#Will generate a random function from the list of functions and a random sample.
generateOrganism<-function(inputLen,inputSeed, functions)
{
  set.seed(inputSeed)
  rnd<-sample(1:length(functions),inputLen,replace=T)
  Org<-mapFuncList(functions,rnd)
  return(Org)
}

#Will generate a series of "Organisms"
genPopulation<-function(popSize,initialSeed,initialSize,functions)
{
  population<-list()
  for(i in 1:popSize)
  {
    population <- c(population,generateOrganism(initialSize,initialSeed,functions))
    initialSeed <- initialSeed+1
  }
  populationWithNames<-makeStrName(population)
  return(populationWithNames)
}

#Turns the population of functions (which are actually strings in "") into
#actual functions. (i.e. changes the mode of the list from string to function).

funCreator<-function(snippet)
{
  txt=snippet
  function(x)
  {
    exprs <- parse(text = txt)
    eval(exprs) 
  }
}

#Applies a fitness function to the population. Puts the best organism in
#the hallOfFame.
evalPopulation<-function(populationFuncList, inputData,outputData)
{   
  #rmse <- sqrt( mean( (sim - obs)^2))

  hallOfFame<-list(1000000000)
  for(i in 1:length(populationFuncList))
  {
    total<-vector(mode="numeric",length=length(inputData))
    for(z in 1:length(inputData))
    {
      total<-c(total,(abs(populationFuncList[[i]](inputData[[z]])-outputData[[z]])))
    }
    rmse<-sqrt(mean(total*total))
    if(rmse<hallOfFame[[1]]) {hallOfFame[[1]]<-rmse}
  }
  return(hallOfFame)
}

#Function list, input data, output data (data to fit to)
funcs<-list("x","log(x)","sin(x)","cos(x)","tan(x)")
desiredFuncOutput<-list(1,2,3,4,5)
dataForInput<-list(1,2,3,4,5)

#Function calls
POpulation<-genPopulation(4,1,1,funcs)
POpulationFuncList <- lapply(setNames(POpulation,names(POpulation)),function(x){funCreator(x)})

bestDude<-evalPopulation(POpulationFuncList,dataForInput,desiredFuncOutput)
print(bestDude)

1 个答案:

答案 0 :(得分:1)

在您的函数evalPopulation中,您尝试将populationFuncList[[i]]视为函数,但是当您传入参数POpulationFuncList以替换变量{{1}时它不是一个功能,它是一个列表。

我不确定你要做什么,所以我不确定你想要解决这个问题的方法。如果您打算使用函数,则应更改您引用该函数的对象的名称,并将其作为参数删除,或者至少将函数作为参数而不是列表传递。

OTOH如果您打算使用列表populationFuncList,那么您就不应该将其应用为函数而不是列表。

另一方面,如果你没有给他们这么相似的名字,这可能会更明显。

另一个潜在的问题是您的某个列表中似乎有非数字结果:

POpulationFuncList

您无法获取角色的绝对值&#34; x&#34;,所以我只是想确保您已经意识到这一点。

第三个问题是您在名为> populationFuncList(POpulation) $x1 [1] "x" $x2 [1] 2 $x3 [1] 1 $x4 [1] 1 的非数字数据类型对象上进行数学运算。您需要将类型更改为数字或将其正确编入索引。

现在我不可能确切地知道你应该选择哪种无限可能来解决这个问题,因为我不知道你的用例的细节。但是,这是一个可能的解决方案,您应该能够适应用例的细节:

total