‘cito’ simplifies the building and training of (deep) neural networks by relying on standard R syntax and familiar methods from statistical packages. Model creation and training can be done with a single line of code. Furthermore, all generic R methods such as print or plot can be used on the fitted model. At the same time, ‘cito’ is computationally efficient because it is based on the deep learning framework ‘torch’ (with optional GPU support). The ‘torch’ package is native to R, so no Python installation or other API is required for this package.
Before installing ‘cito’ make sure ‘torch’ is installed. See the code chunk below if you are unsure on how to check this
# check package
if(!require('torch',quietly = TRUE)) install.packages('torch')
library('torch')
#install torch
if(!torch_is_installed()) install_torch()
If you have trouble installing ‘torch’, please visit the website of the ‘torch’ package or create an issue on our github website. We are happy to help you.
A stable version of cito from CRAN can be installed with:
install.packages("cito")
The development version from GitHub can be installed by:
if(!require('devtools', quietly = TRUE)) install.packages('devtools')
::install_github('citoverse/cito') devtools
Once installed, the main function dnn()
can be used. See
the example below. A more in depth explanation can be found in the
vignettes or here under
articles.
library(cito)
<- dnn(Sepal.Length~., data = datasets::iris, bootstrap = 30L) nn.fit
analyze_training(nn.fit)
# At 1st glance, the networks converged since the loss is lower than the baseline loss and the training loss is on a plateau at the end of the training.
plot(nn.fit)
summary(nn.fit)
## Summary of Deep Neural Network Model
##
## ── Feature Importance
## Importance Std.Err Z value Pr(>|z|)
## Sepal.Width → Sepal.Length 1.755 0.570 3.08 0.0021 **
## Petal.Length → Sepal.Length 18.027 8.809 2.05 0.0407 *
## Petal.Width → Sepal.Length 0.521 0.716 0.73 0.4666
## Species → Sepal.Length 0.392 0.218 1.80 0.0720 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## ── Average Conditional Effects
## ACE Std.Err Z value Pr(>|z|)
## Sepal.Width → Sepal.Length 0.7326 0.0497 14.74 <2e-16 ***
## Petal.Length → Sepal.Length 0.6164 0.0901 6.84 8e-12 ***
## Petal.Width → Sepal.Length -0.1181 0.1587 -0.74 0.46
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## ── Standard Deviation of Conditional Effects
## ACE Std.Err Z value Pr(>|z|)
## Sepal.Width → Sepal.Length 0.1482 0.0432 3.43 0.0006 ***
## Petal.Length → Sepal.Length 0.1167 0.0396 2.94 0.0032 **
## Petal.Width → Sepal.Length 0.0470 0.0268 1.76 0.0790 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
dim(predict(nn.fit, newdata = datasets::iris))
## [1] 30 150 1
We can pass custom loss functions to ‘cito’, optionally with additional parameters that should be fitted. The only requirement is that all calculations must be written using the ‘torch’ package (cito automatically converts the initial values of the custom parameters to ‘torch’ objects).
We use a multivariate normal distribution as the likelihood function and we want to parameterize/fit the covariance matrix of the multivariate normal distribution:
We need one helper function, create_cov()
that
builds the covariance matrix based on a lower triangular matrix and the
diagonals (low-rank approximation of the covariance matrix)
We need our custom likelihood function which uses the
distr_multivariate_normal(…)
function from the torch
package:
= function(L, Diag) {
create_cov return(torch::torch_matmul(L, L$t()) + torch::torch_diag(Diag+0.01))
}
= function(true, pred) {
custom_loss_MVN = create_cov(SigmaPar, SigmaDiag)
Sigma = torch::distr_multivariate_normal(pred,
logLik covariance_matrix = Sigma)$
log_prob(true)
return(-logLik$mean())
}
<- dnn(cbind(Sepal.Length, Sepal.Width, Petal.Length)~.,
nn.fitdata = datasets::iris,
lr = 0.01,
epochs = 200L,
loss = custom_loss_MVN,
verbose = FALSE,
plot = FALSE,
custom_parameters =
list(SigmaDiag = rep(1, 3), # Our parameters with starting values
SigmaPar = matrix(rnorm(6, sd = 0.001), 3, 2)) # Our parameters with starting values
)
Estimated covariance matrix:
as.matrix(create_cov(nn.fit$loss$parameter$SigmaPar,
$loss$parameter$SigmaDiag)) nn.fit
## [,1] [,2] [,3]
## [1,] 0.24824733 0.06395083 0.13815881
## [2,] 0.06395083 0.11858207 0.03379684
## [3,] 0.13815881 0.03379684 0.24378222
Empirical covariance matrix:
cov(predict(nn.fit) - nn.fit$data$Y)
## Sepal.Length Sepal.Width Petal.Length
## Sepal.Length 0.25081444 0.06944643 0.15270816
## Sepal.Width 0.06944643 0.09439328 0.02924789
## Petal.Length 0.15270816 0.02924789 0.16690478