Libraries

  library(R6)
  library(cgraph)

R6 Class

  lr <- R6Class(
    classname = "lr",
    inherit = cgraph,
    public = list(
      error = c(),
      initialize = function(x, y, sigma = 0.1, ...)
      {
        super$initialize()
        
        x <- as.matrix(x)
        
        y <- as.numeric(y)
        
        input <- input(name = "input")
        
        target <- const(name = "target")
        
        w <- parm(matrix(rnorm(ncol(x), sd = sigma), 1, ncol(x)), name = "w")
        
        b <- parm(0, name = "b")
        
        output <- cg_linear(w, input, b, name = "output")
        
        cg_mean(cg_colSums((output - target)^const(2)), name = "loss")
        
        self$fit(x, y, ...)
      },
      fit = function(x, y, eta = 0.05, n.epochs = 1)
      {
        parms <- c("w", "b")

        x <- as.matrix(x)
        
        y <- as.numeric(y)
        
        for(i in 1:n.epochs)
        {
          values <- self$run("loss", list(
            input = t(x), target = y
          ))

          grads <- self$gradients("loss", values)
            
          for(parm in parms)
          {
            self$values[[parm]] <- self$values[[parm]] - eta * grads[[parm]]
          }

          self$error <- c(self$error, values$loss)
        }
      },
      predict = function(x)
      {
        x <- as.matrix(x)
        
        values <- self$run("output", list(
          input = t(x)
        ))
        
        as.numeric(values$output)
      }
    )
  )

Example

Let us test the linear regression model on the cars dataset (available in R).

  head(cars)
##   speed dist
## 1     4    2
## 2     4   10
## 3     7    4
## 4     7   22
## 5     8   16
## 6     9   10

The data is rescaled by performing z-normalization:

  train <- scale(cars)

We fit a linear regression model that predicts the distance driven by a car based on its speed.

  x <- lr$new(
    x = train[, "dist"],
    y = train[, "speed"],
    eta = 0.01,
    n.epochs = 200,
    sigma = 0.1
  )

The computational graph of the regression model looks as follows:

  plot(x)

Moreover, we can also visualize the MSE at each epoch during the model fitting.

  plot(x$error, type = "l", xlab = "Epoch", ylab = "MSE")

If we plot the linear function (red line) estimated by the regression model on the data (black circles), we see that the model fits reasonablly well.

plot(train)

lines(train[,"speed"], x$predict(train[,"speed"]), col = 2)