Реализация генетического программирования ошибок R

Так что я новичок в 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 ответ

В вашей функции evalPopulation вы пытаетесь подать заявку populationFuncList[[i]] как будто это была функция, но когда вы передаете аргумент POpulationFuncList заменить переменную populationFuncList это не функция, это список.

Я не уверен, что вы пытались сделать, поэтому я не уверен, каким образом вы хотите это исправить. Если вы хотели использовать функцию, вы должны изменить имя объекта, на который вы ссылаетесь, и удалить его в качестве аргумента или, по крайней мере, передать функцию в качестве аргумента вместо списка.

OTOH, если вы хотели использовать список POpulationFuncList тогда вам просто не следует применять его, как если бы это была функция вместо списка.

Кстати, это, вероятно, было бы более очевидно, если бы вы не дали им такие похожие имена.

Другая потенциальная проблема заключается в том, что в одном из ваших списков вы видите нечисловые результаты:

> populationFuncList(POpulation)
$x1
[1] "x"

$x2
[1] 2

$x3
[1] 1

$x4
[1] 1

Вы не можете принять абсолютное значение символа "x", поэтому я просто хотел убедиться, что вы знаете об этом.

Третья проблема заключается в том, что вы выполняете математические операции с нечисловым типом данных, который называется total, Вам нужно либо изменить тип на числовой, либо индексировать его соответствующим образом.

Теперь я не могу точно знать, какую из бесконечного числа возможностей вы должны решить, чтобы это исправить, потому что я не знаю деталей вашего варианта использования. Однако вот одно из возможных решений, которое вы должны быть в состоянии адаптировать к специфике варианта использования:

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(myList=myList, dataForInput,desiredFuncOutput)
{   
  #rmse <- sqrt( mean( (sim - obs)^2))

  hallOfFame<-list(1000000000)
  for(i in 1:length(populationFuncList))
  {
    total<-0
    for(z in 1:length(dataForInput))
    {
      total<-c(total,(abs(myList[[i]]+(dataForInput[[z]])-desiredFuncOutput[[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)
myList <-populationFuncList(POpulation)[2:4]
bestDude<-evalPopulation(myList,dataForInput,desiredFuncOutput)
print(bestDude)
[[1]]
[1] 1.825742
Другие вопросы по тегам