Skip to content

Commit

Permalink
Merge pull request #218 from tidymodels/reticulate-to-suggests
Browse files Browse the repository at this point in the history
Move keras and tensorflow imports to suggests
  • Loading branch information
EmilHvitfeldt authored Mar 20, 2024
2 parents 1651d1a + 8c33289 commit 3d119e2
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 55 deletions.
11 changes: 0 additions & 11 deletions .github/workflows/R-CMD-check-hard.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,6 @@ jobs:
any::rmarkdown
needs: check
pak-version: devel

- uses: actions/setup-python@v4
with:
python-version: 3.9

- name: Install TensorFlow
run: |
reticulate::virtualenv_create('r-reticulate', python='3.9')
reticulate::use_virtualenv('r-reticulate')
tensorflow::install_tensorflow(version='2.11.0')
shell: Rscript {0}

- uses: r-lib/actions/check-r-package@v2
with:
Expand Down
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ Imports:
glue,
dplyr (>= 1.1.0),
generics (>= 0.1.0),
keras,
lifecycle,
purrr,
rlang (>= 0.4.10),
rsample,
stats,
tensorflow,
tibble,
tidyr,
utils,
Expand All @@ -42,13 +40,15 @@ Suggests:
ggplot2,
hardhat,
irlba,
keras,
knitr,
lme4,
modeldata,
rmarkdown,
rpart,
rstanarm,
stringdist,
tensorflow,
testthat (>= 3.0.0),
VBsparsePCA,
xgboost
Expand Down
11 changes: 0 additions & 11 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,6 @@ importFrom(generics,required_pkgs)
importFrom(generics,tidy)
importFrom(generics,tunable)
importFrom(glue,glue)
importFrom(keras,backend)
importFrom(keras,compile)
importFrom(keras,fit)
importFrom(keras,get_layer)
importFrom(keras,keras_model)
importFrom(keras,keras_model_sequential)
importFrom(keras,layer_concatenate)
importFrom(keras,layer_dense)
importFrom(keras,layer_embedding)
importFrom(keras,layer_flatten)
importFrom(keras,layer_input)
importFrom(lifecycle,deprecated)
importFrom(recipes,remove_original_cols)
importFrom(stats,as.formula)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

* Documentation for tidy methods for all steps has been improved to describe the return value more accurately. (#217)

* {keras} and {tensorflow} have been moved to Suggests instead of Imports. (#218)

# embed 1.1.3

* `step_collapse_stringdist()` will now return predictors as factors. (#204)
Expand Down
11 changes: 0 additions & 11 deletions R/embed-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,6 @@
#' @importFrom dplyr mutate
#' @importFrom dplyr one_of
#' @importFrom glue glue
#' @importFrom keras backend
#' @importFrom keras compile
#' @importFrom keras fit
#' @importFrom keras get_layer
#' @importFrom keras keras_model
#' @importFrom keras keras_model_sequential
#' @importFrom keras layer_concatenate
#' @importFrom keras layer_dense
#' @importFrom keras layer_embedding
#' @importFrom keras layer_flatten
#' @importFrom keras layer_input
#' @importFrom lifecycle deprecated
#' @importFrom recipes remove_original_cols
#' @importFrom stats as.formula
Expand Down
32 changes: 17 additions & 15 deletions R/embed.R
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
#' "Concatenate Embeddings for Categorical Variables with Keras"
#' \url{https://flovv.github.io/Embeddings_with_keras_part2/}
#'
#' @examplesIf !embed:::is_cran_check() && rlang::is_installed("modeldata")
#' @examplesIf !embed:::is_cran_check() && rlang::is_installed(c("modeldata", "keras"))
#' data(grants, package = "modeldata")
#'
#' set.seed(1)
Expand Down Expand Up @@ -273,6 +273,8 @@ is_tf_2 <- function() {

tf_coefs2 <- function(x, y, z, opt, num, lab, h, seeds = sample.int(10000, 4),
...) {
rlang::check_installed("keras")

vars <- names(x)
p <- length(vars)

Expand Down Expand Up @@ -306,40 +308,40 @@ tf_coefs2 <- function(x, y, z, opt, num, lab, h, seeds = sample.int(10000, 4),
inputs <- vector(mode = "list", length = p)
# For each categorical predictor, make an input layer
for (i in 1:p) {
inputs[[i]] <- layer_input(shape = 1, name = paste0("input_", vars[i]))
inputs[[i]] <- keras::layer_input(shape = 1, name = paste0("input_", vars[i]))
}

layers <- vector(mode = "list", length = p)
# Now add embedding to each layer and then flatten
for (i in 1:p) {
layers[[i]] <-
inputs[[i]] %>%
layer_embedding(
keras::layer_embedding(
input_dim = length(lvl[[i]]) + 1,
output_dim = num,
input_length = 1,
name = paste0("layer_", vars[i])
) %>%
layer_flatten()
keras::layer_flatten()
}

if (is.null(z)) {
if (p > 1) {
all_layers <- layer_concatenate(layers)
all_layers <- keras::layer_concatenate(layers)
} else {
all_layers <- layers[[1]]
}
} else {
mats$z <- as.matrix(z)
pred_layer <- layer_input(shape = ncol(z), name = "other_pred")
all_layers <- layer_concatenate(c(layers, pred_layer))
pred_layer <- keras::layer_input(shape = ncol(z), name = "other_pred")
all_layers <- keras::layer_concatenate(c(layers, pred_layer))
inputs <- c(inputs, pred_layer)
}

if (h > 0) {
all_layers <-
all_layers %>%
layer_dense(
keras::layer_dense(
units = h, activation = "relu", name = "hidden_layer",
kernel_initializer = keras::initializer_glorot_uniform(seed = seeds[3])
)
Expand All @@ -348,14 +350,14 @@ tf_coefs2 <- function(x, y, z, opt, num, lab, h, seeds = sample.int(10000, 4),
if (factor_y) {
all_layers <-
all_layers %>%
layer_dense(
keras::layer_dense(
units = ncol(y), activation = "softmax", name = "output_layer",
kernel_initializer = keras::initializer_glorot_uniform(seed = seeds[4])
)
} else {
all_layers <-
all_layers %>%
layer_dense(
keras::layer_dense(
units = 1, activation = "linear", name = "output_layer",
kernel_initializer = keras::initializer_glorot_uniform(seed = seeds[4])
)
Expand All @@ -365,15 +367,15 @@ tf_coefs2 <- function(x, y, z, opt, num, lab, h, seeds = sample.int(10000, 4),
keras::keras_model(inputs = inputs, outputs = all_layers)

model %>%
compile(
keras::compile(
loss = opt$loss,
metrics = opt$metrics,
optimizer = opt$optimizer
)

history <-
model %>%
fit(
keras::fit(
x = unname(mats),
y = y,
epochs = opt$epochs,
Expand All @@ -387,7 +389,7 @@ tf_coefs2 <- function(x, y, z, opt, num, lab, h, seeds = sample.int(10000, 4),

for (i in 1:p) {
layer_values[[i]] <-
get_layer(model, paste0("layer_", vars[i]))$get_weights() %>%
keras::get_layer(model, paste0("layer_", vars[i]))$get_weights() %>%
as.data.frame() %>%
setNames(names0(num, paste0(vars[i], "_embed_"))) %>%
as_tibble() %>%
Expand Down Expand Up @@ -477,9 +479,9 @@ print.step_embed <-

#' @export
#' @rdname step_embed
#' @param optimizer,loss,metrics Arguments to pass to [keras::compile()]
#' @param optimizer,loss,metrics Arguments to pass to keras::compile()
#' @param epochs,validation_split,batch_size,verbose,callbacks Arguments to pass
#' to [keras::fit()]
#' to keras::fit()
embed_control <- function(loss = "mse",
metrics = NULL,
optimizer = "sgd",
Expand Down
4 changes: 3 additions & 1 deletion R/feature_hash.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
#' Approach for Predictive Models_. CRC/Chapman Hall
#' \url{https://bookdown.org/max/FES/encoding-predictors-with-many-categories.html}
#' @seealso [recipes::step_dummy()], [recipes::step_zv()]
#' @examplesIf !embed:::is_cran_check() && rlang::is_installed("modeldata")
#' @examplesIf !embed:::is_cran_check() && rlang::is_installed(c("modeldata", "keras"))
#' data(grants, package = "modeldata")
#' rec <-
#' recipe(class ~ sponsor_code, data = grants_other) %>%
Expand Down Expand Up @@ -164,6 +164,8 @@ make_hash_vars <- function(x, prefix, num_hash = 2^8) {

uni_x <- unique(x)

rlang::check_installed("keras")

column_int <-
purrr::map_int(
uni_x,
Expand Down
6 changes: 3 additions & 3 deletions man/step_embed.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/step_feature_hash.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions tests/testthat/test-embed.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ withr::local_envvar(TF_CPP_MIN_LOG_LEVEL = "2")

test_that("factor encoded predictor", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

class_test <- recipe(x2 ~ ., data = ex_dat) %>%
Expand Down Expand Up @@ -76,6 +77,7 @@ test_that("factor encoded predictor", {

test_that("character encoded predictor", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

class_test <- recipe(x2 ~ ., data = ex_dat_ch) %>%
Expand Down Expand Up @@ -144,6 +146,7 @@ test_that("character encoded predictor", {

test_that("factor encoded predictor", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

class_test <- recipe(x1 ~ ., data = ex_dat) %>%
Expand Down Expand Up @@ -213,6 +216,7 @@ test_that("factor encoded predictor", {

test_that("character encoded predictor", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

class_test <- recipe(x1 ~ ., data = ex_dat_ch) %>%
Expand Down Expand Up @@ -281,6 +285,7 @@ test_that("character encoded predictor", {

test_that("bad args", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

three_class <- iris
Expand All @@ -297,6 +302,7 @@ test_that("bad args", {

test_that("check_name() is used", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

dat <- ex_dat
Expand Down Expand Up @@ -330,6 +336,7 @@ test_that("tunable", {

test_that("bake method errors when needed non-standard role columns are missing", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())
rec <- recipe(x2 ~ ., data = ex_dat) %>%
step_embed(
Expand All @@ -351,6 +358,7 @@ test_that("bake method errors when needed non-standard role columns are missing"

test_that("empty printing", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

rec <- recipe(mpg ~ ., mtcars)
Expand Down Expand Up @@ -396,6 +404,7 @@ test_that("empty selection tidy method works", {

test_that("keep_original_cols works", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

new_names <- c("x2", "x3_embed_1", "x3_embed_2")
Expand Down Expand Up @@ -427,6 +436,7 @@ test_that("keep_original_cols works", {

test_that("keep_original_cols - can prep recipes with it missing", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

rec <- recipe(x2 ~ x3, data = ex_dat) %>%
Expand All @@ -446,6 +456,7 @@ test_that("keep_original_cols - can prep recipes with it missing", {

test_that("printing", {
skip_on_cran()
skip_if_not_installed("keras")
skip_if(!embed:::is_tf_available())

rec <- recipe(x2 ~ ., data = ex_dat_ch) %>%
Expand Down

0 comments on commit 3d119e2

Please sign in to comment.