Skip to content

Commit

Permalink
merge with last changes in master
Browse files Browse the repository at this point in the history
Merge branch 'master' into docs_revision

# Conflicts:
#	R/obtain_derivatives_list.R
  • Loading branch information
moralapablo committed Oct 30, 2023
2 parents 716d1bd + 7aa7b9a commit 6ff164d
Show file tree
Hide file tree
Showing 65 changed files with 1,432 additions and 773 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ jobs:
build:
if: ${{ !contains(github.event.head_commit.message, '[ci skip]') }}
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
name: ${{ matrix.config.os }} ${{ matrix.config.arch }} (${{ matrix.config.r }})

strategy:
fail-fast: false
matrix:
config:
- {os: macOS-latest, tf: 'default', r: 'release'}
- {os: macOS-latest, tf: 'default', r: 'release', arch: 'x86'}
- {os: macOS-latest, tf: 'default', r: 'release', arch: 'arm64'}
- {os: windows-latest, tf: 'default', r: 'release'}
- {os: ubuntu-latest, tf: 'default', r: 'devel', http-user-agent: 'release'}
- {os: ubuntu-latest, tf: 'default', r: 'release', covr: 'yes'}
Expand All @@ -34,10 +35,11 @@ jobs:
with:
extra-packages: any::rcmdcheck, any::covr, [email protected]
needs: check, coverage
- name: Miniconda + Tensorflow + Keras installation
- name: Miniconda + Tensorflow + Keras + Torch installation
run: |
reticulate::install_miniconda()
keras::install_keras(tensorflow = '${{ matrix.tf }}-cpu')
torch::install_torch()
shell: Rscript {0}

- name: Check
Expand Down
3 changes: 3 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Encoding: UTF-8
LazyData: true
Depends: R (>= 3.5.0)
Imports:
generics,
matrixStats,
pracma,
Rcpp
Expand All @@ -27,12 +28,14 @@ Suggests:
ggplot2,
keras,
knitr,
luz,
patchwork,
rmarkdown,
R6,
tensorflow,
testthat (>= 3.0.0),
tidytext,
torch,
vdiffr
LinkingTo:
Rcpp,
Expand Down
11 changes: 8 additions & 3 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# Generated by roxygen2: do not edit by hand

S3method(add_constraints,keras.engine.training.Model)
S3method(add_constraints,luz_module_generator)
S3method(fit,nn2poly)
S3method(nn2poly,default)
S3method(nn2poly,keras.engine.training.Model)
S3method(nn2poly,list)
S3method(plot_taylor_and_activation_potentials,default)
S3method(plot_taylor_and_activation_potentials,keras.engine.training.Model)
S3method(plot_taylor_and_activation_potentials,list)
S3method(predict,nn2poly)
export(add_constraints)
export(change_string_to_function)
export(eval_poly)
export(fit)
export(luz_model_sequential)
export(nn2poly)
export(obtain_derivatives_list)
export(plot_diagonal)
export(plot_n_important_coeffs)
export(plot_taylor_and_activation_potentials)
importFrom(Rcpp,sourceCpp)
importFrom(generics,fit)
importFrom(stats,density)
useDynLib(nn2poly, .registration = TRUE)
46 changes: 23 additions & 23 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

select_allowed_partitions <- function(equivalent_label, q_previous_layer, labels, partitions) {
.Call(`_nn2poly_select_allowed_partitions`, equivalent_label, q_previous_layer, labels, partitions)
}

alg_non_linear <- function(coeffs_input, labels_input, labels_output, q_taylor_vector, current_layer, g, partitions_labels, partitions) {
.Call(`_nn2poly_alg_non_linear`, coeffs_input, labels_input, labels_output, q_taylor_vector, current_layer, g, partitions_labels, partitions)
}

combinations_with_repetition <- function(n, k) {
.Call(`_nn2poly_combinations_with_repetition`, n, k)
}

generate_partitions <- function(p, q_max) {
.Call(`_nn2poly_generate_partitions`, p, q_max)
}

generate_partitions_full <- function(p, q_max) {
.Call(`_nn2poly_generate_partitions_full`, p, q_max)
}

# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

select_allowed_partitions <- function(equivalent_label, q_previous_layer, labels, partitions) {
.Call(`_nn2poly_select_allowed_partitions`, equivalent_label, q_previous_layer, labels, partitions)
}

alg_non_linear <- function(coeffs_input, labels_input, labels_output, q_taylor_vector, current_layer, g, partitions_labels, partitions) {
.Call(`_nn2poly_alg_non_linear`, coeffs_input, labels_input, labels_output, q_taylor_vector, current_layer, g, partitions_labels, partitions)
}

combinations_with_repetition <- function(n, k) {
.Call(`_nn2poly_combinations_with_repetition`, n, k)
}

generate_partitions <- function(p, q_max) {
.Call(`_nn2poly_generate_partitions`, p, q_max)
}

generate_partitions_full <- function(p, q_max) {
.Call(`_nn2poly_generate_partitions_full`, p, q_max)
}

39 changes: 28 additions & 11 deletions R/add_constraints.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
# but L1 is preferred, with 1 as it maximum norm bound.


# Set Python vars to NULL to avoid global variable notes in package check
super <- self <- constraint_maxnorm <- NULL


#' Custom keras L1 constraint.
#'
Expand All @@ -25,6 +22,7 @@ super <- self <- constraint_maxnorm <- NULL
#' the custom layers implemented here, where bias and weights will be joined
#' together.
#'
#' @noRd
constraint_l1_norm <- function(w) {
norms = keras::k_sum(keras::k_abs(w), axis = 1, keepdims = TRUE)
desired = keras::k_clip(norms, 0, 1)
Expand All @@ -42,19 +40,29 @@ constraint_l1_norm <- function(w) {
#' layers that impose L1 and L2 norm constraints
#'
#' @param model A keras model to which the restrictions on the weights are to be applied.
#' @param constraint_type The type of constraint you want to apply on the model. Currently,
#' @param type The type of constraint you want to apply on the model. Currently,
#' 'l1_norm' and 'l2_norm' can be applied.
#' @param keep_old_weights Binary parameters that controls if the weights of
#' \code{model} are kept in the new constrained network.
#' @param ... Additional arguments (unused).
#'
#' @return A keras model with the custom constraints applied.
#'
#' @export
add_constraints <- function(model,
constraint_type = "l1_norm",
keep_old_weights = FALSE) {
if (!requireNamespace("keras", quietly = TRUE)) {
type = c("l1_norm", "l2_norm"),
keep_old_weights = FALSE,
...) {
UseMethod("add_constraints")
}

#' @export
add_constraints.keras.engine.training.Model <- function(model,
type = c("l1_norm", "l2_norm"),
keep_old_weights = FALSE,
...) {
if (!requireNamespace("keras", quietly = TRUE))
stop("package 'keras' is required for this functionality", call.=FALSE)
}

# Custom keras layers using L1 and L2 norms. These are needed to impose
# constraints simultaneously to the weights and bias.
Expand Down Expand Up @@ -100,7 +108,7 @@ add_constraints <- function(model,
initializer = "random_normal",
trainable = TRUE,
# maxnorm uses the L2 norm with a given max value
constraint = constraint_maxnorm(max_value = 1, axis = 0)
constraint = keras::constraint_maxnorm(max_value = 1, axis = 0)
)
},
call = function(inputs) {
Expand All @@ -115,12 +123,12 @@ add_constraints <- function(model,
layer_combined_L1 <- keras::create_layer_wrapper(Layer_Combined_L1)
layer_combined_L2 <- keras::create_layer_wrapper(Layer_Combined_L2)

params <- get_model_parameters(model)
params <- get_parameters(model)
nlayers <- length(params$weights_list)
new_layers <- vector(mode = "list", length = nlayers) # create a list of new layers

# choose the custom layer to use
custom_layer <- switch(constraint_type,
custom_layer <- switch(match.arg(type),
"l1_norm" = layer_combined_L1,
"l2_norm" = layer_combined_L2,
layer_combined_L1)
Expand Down Expand Up @@ -161,3 +169,12 @@ add_constraints <- function(model,
new_model
}

#' @export
add_constraints.luz_module_generator <- function(model,
type = c("l1_norm", "l2_norm"),
...) {
luz_model_sequential_check(model)
attr(model, "constraint") <- match.arg(type)
class(model) <- c("nn2poly", class(model))
model
}
28 changes: 28 additions & 0 deletions R/callback.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#' Build the appropriate callback based on the model class
#' @noRd
build_callback <- function(object,
type = c("l1_norm", "l2_norm")) {
UseMethod("build_callback")
}

norm_order <- function(type = c("l1_norm", "l2_norm")) {
as.numeric(substr(match.arg(type), 2, 2))
}

build_callback.luz_module_generator <- function(object,
type = c("l1_norm", "l2_norm")) {
luz_callback <- luz::luz_callback(
name = paste0(type, "_callback"),

initialize = function() {
self$constraint <- torch_constraint(norm_order(type))
},

on_train_batch_end = function() {
for (layer in utils::head(ctx$model$children, -1))
layer$apply(self$constraint)
}
)

luz_callback()
}
2 changes: 1 addition & 1 deletion R/change_string_to_function.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#' activation functions, i.e., "softplus", "tanh", "sigmoid" or "linear".
#'
#' @return List of R functions associated with the string names provided.
#' @export
#'
#' @noRd
change_string_to_function <- function(af_string_list) {
n <- length(af_string_list)

Expand Down
2 changes: 1 addition & 1 deletion R/check_weight_constraints.R
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

#' Check weight's vector constraints (including bias)
#'
#' @param weights List of matrices with the weights of each layer.
#' @param maxnorm List of 2 elements: the name of the used norm and its max value.
#'
#' @return List across all layers with a vector containing the norms of each weight vector.
#'
#' @noRd
check_weight_constraints <- function(weights, maxnorm) {
#### Compute the norm for the full matrix ####

Expand Down
1 change: 1 addition & 0 deletions R/check_weight_dimensions.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#'
#' @return `TRUE` if the dimensiones are correct, `FALSE` if not.
#'
#' @noRd
check_weights_dimensions <- function(weights_matrices_list) {
for (matrix_index in 2:length(weights_matrices_list)) {
nrows_current <- nrow(weights_matrices_list[[matrix_index]])
Expand Down
2 changes: 0 additions & 2 deletions R/eval_poly.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@
#' eval_poly(x,poly)
#'
#' @export
#'

eval_poly <- function(x, poly) {

# Remove names and transform into matrix (variables as columns)
Expand Down
9 changes: 9 additions & 0 deletions R/fit.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#' @importFrom generics fit
#' @export
generics::fit

#' @export
fit.nn2poly <- function(object, ...) {
callback <- build_callback(object, attr(object, "constraint"))
NextMethod(callbacks = append(as.list(list(...)[["callbacks"]]), callback))
}
58 changes: 0 additions & 58 deletions R/get_model_parameters.R

This file was deleted.

Loading

0 comments on commit 6ff164d

Please sign in to comment.