0

I am attempting to write some classes in R. Here is the start of a neural network layer class. It is generating warnings and errors that I don't know how to correct.

# Slot definitions
setClass(
 Class="neuralNetworkLayer",
 representation=representation(
   input = "vector",
   linearOutput = "vector",
   squashedOutput = "vector",
   hasBias = "logical",
   bias = "vector",
   weights = "vector",
   gains = "matrix",
   squashFcn = "closure",
   squashFcnDerivative = "closure"
 )
)

# Constructors
NeuralNetworkLayer <- function(nInput,nOutput,hasBias=TRUE,squashFcn,squashFcnDerivative) {
  nc = list(
    input = c(rep(NA,nInput)),
    linearOutput = c(rep(NA,nOutput)),
    squashedOutput = c(rep(NA,nOutput)),
    hasBias = hasBias,
    bias = c(rep(NA,nOutput)),
    weights = c(rep(NA,nOutput)),
    gain = matrix(data=weights, nrow = nInput, ncol = nOutput),
    squashFcn = squashFcn,   # source of warning / error
    squashFcnDerivative = squashFcnDerivative,

    get = function(x) nc[[x]],
    set = function(x, value) nc[[x]] <<- value,
    props = list()
  )
  #Add a few more functions
  nc$addProp = function(name, value) {
    p <- nc$props
    p[[name]] <- value
    assign('props', p, envir=nc)
  }
  nc <- list2env(nc)
  class(nc) <- "NeuralNetwork"
  return(nc)
}

  tanhDerivative <- function(x) {
    d = 1 - tan(x)^2  
    return(d)
  }

  test <- NeuralNetworkLayer(nInput=4,nOutput=5,hasBias=TRUE,
                             squashFcn=tanh,squashFcnDerivative=tanhDerivative)

The messages generated are

Warning message:
undefined slot classes in definition of "neuralNetworkLayer": squashFcn(class "closure"),
squashFcnDerivative(class "closure")

Error in as.vector(x, mode) : 
  cannot coerce type 'closure' to vector of type 'any' 

Both messages indicate that the base class closure can not be used for a slot. How to pass a function?

Taking the advice from the two answers, the following code can be generated. This addresses the original question of passing a function to a slot, and then using that function. For completeness, the revised neural network layer class is present.

setClass(
  Class="neuralNetworkLayer",
  representation=representation(
    nInput = "numeric",
    nOutput = "numeric",
    squashFcn = "function",
    derivSquashFcn = "function",
    gains = "matrix",
    hasBias = "logical",
    bias = "matrix",
    linOutput = "matrix",
    squashOutput = "matrix"
  )
)
getClass("neuralNetworkLayer")
getSlots("neuralNetworkLayer")

sf <- function(x){
  f = tanh(x)
  return(f)
}
dsf <- function(x) {
  d = 1 - tan(x)^2  
  return(d)
}

# Create an object of class 
hh = new("neuralNetworkLayer",squashFcn=sf,nInput=5,nOutput=5,hasBias=TRUE,
                        derivSquashFcn = dsf) 

hh@squashFcn(3)
hh@derivSquashFcn(3)

2 Answers2

0

The error/warning :

 undefined slot classes in definition of "neuralNetworkLayer": squashFcn(class "closure")

means that slot is not defined beacuse the type "closure" is not defined.

You try To define a slot(attribute) as a generic function one idea is to use ANY ( the default for slot I think) type:

neuralNetworkLayer <- 
setClass(
  Class="neuralNetworkLayer",
  representation=representation(
    squashFcn = "ANY"
  )
)

Then ,for example you instantiate your class like this :

# Constructors
hh = neuralNetworkLayer(squashFcn=function(x)print(x)) ## dummy function here 
hh@squashFcn(10)
[1] 10

That's said , I think you should consider to define your functions slots as a real method(see setMethod) . Methods are to have typed (safer) objects Otheriwse there is no good reason the reason to use S4 system and easier to use S3 method.

agstudy
  • 119,832
  • 17
  • 199
  • 261
  • I updated the class, but now the evaluation of the matrix multiplication doesn't work. If you have a minute, could you review the updated code. –  Sep 22 '14 at 00:11
0

I don't get why you are defining a neuralNetworkLayer S4 class while your constructor doesn't make any use of it. You just are creating a normal R list (no slots in the returning object of NeuralNetworkLayer). In your constructor you should call new somewhere.

Anyhow, your error doesn't have nothing to do with closure as you might think. You just didn't define the weights object that it happens to be also an R function. When you say:

    weights = c(rep(NA,nOutput)),
    gains = matrix(data=weights, nrow = nInput, ncol = nOutput),

you are creating an element of a list named weights, but you are not creating an object named weights. When you define the gains element, R just finds for weights its R function and tries to coerce it to put it into a matrix, giving the error. You can just define weights in your first line of NeuralNetworkLayer:

    weights = c(rep(NA,nOutput))

and then, when you define nc, replace the first line I wrote above with:

    weights = weights,

and your function won't give any error.

For the warning part of the definition of the S4 class, just use function instead of closure. However, as you have defined your constructor, you may well not define it at all.

nicola
  • 24,005
  • 3
  • 35
  • 56
  • I used this information to correctly represent the class and data. –  Sep 21 '14 at 15:06
  • I updated the class, but now the evaluation of the matrix multiplication doesn't work. If you have a minute, could you review the updated code. –  Sep 22 '14 at 00:12
  • You should create another question. Anyway, it seems that you are using R like Java or C++. When you call `setWeights` you are not modifying your object. Objects in R are passed by copying them in the body of a function. Just check your `hh` before and after the call of the method. You may need to read `?setReferenceClass`. Another issue is that you are not properly defining the `signature` of `evaluate`: it has two args, while you defined it with just one. – nicola Sep 22 '14 at 05:45
  • typo: `setRefClass` instead of `setReferenceClass`. – nicola Sep 22 '14 at 05:54
  • The setRefClass recommendation guided implementation of the neural network layer class. –  Sep 22 '14 at 10:21