diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index c9382ae..8b67d01 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -42,12 +42,12 @@ jobs: ## old keras/tf versions # - {os: 'ubuntu-latest', tf: '2.18', r: 'release'} - - {os: 'ubuntu-latest', tf: '2.17', r: 'release'} - - {os: 'ubuntu-latest', tf: '2.16', r: 'release'} - - {os: 'ubuntu-latest', tf: '2.15', r: 'release'} - - {os: 'ubuntu-latest', tf: '2.14', r: 'release'} - - {os: 'ubuntu-latest', tf: '2.13', r: 'release'} - - {os: 'ubuntu-latest', tf: '2.12', r: 'release'} + # - {os: 'ubuntu-latest', tf: '2.17', r: 'release'} + # - {os: 'ubuntu-latest', tf: '2.16', r: 'release'} + # - {os: 'ubuntu-latest', tf: '2.15', r: 'release'} + # - {os: 'ubuntu-latest', tf: '2.14', r: 'release'} + # - {os: 'ubuntu-latest', tf: '2.13', r: 'release'} + # - {os: 'ubuntu-latest', tf: '2.12', r: 'release'} # these are allowed to fail # - {os: 'ubuntu-latest', tf: '2.14.0rc1', r: 'release'} @@ -59,6 +59,7 @@ jobs: env: R_KEEP_PKG_SOURCE: yes GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + PY_REQUIRE_TENSORFLOW: true # R_REMOTES_NO_ERRORS_FROM_WARNINGS: 'true' # R_COMPILE_AND_INSTALL_PACKAGES: 'never' @@ -91,20 +92,20 @@ jobs: - uses: r-lib/actions/setup-r-dependencies@v2 with: - extra-packages: any::rcmdcheck local::. rstudio/reticulate - cache-version: 4 + extra-packages: any::rcmdcheck local::. + # rstudio/reticulate + cache-version: 5 upgrade: 'TRUE' - - name: Install TensorFlow - run: | - print(sessionInfo()) - print(Sys.info()) - version <- '${{ matrix.tf }}' - if (version != "default") - tensorflow::install_tensorflow(version = '${{ matrix.tf }}') - tensorflow::tf_config() + # - name: Install TensorFlow + # run: | + # print(sessionInfo()) + # print(Sys.info()) + # version <- '${{ matrix.tf }}' + # if (version != "default") + # tensorflow::install_tensorflow(version = '${{ matrix.tf }}') + # tensorflow::tf_config() - uses: r-lib/actions/check-r-package@v2 with: upload-snapshots: true - diff --git a/DESCRIPTION b/DESCRIPTION index df26208..5c6f8e9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: tensorflow Type: Package Title: R Interface to 'TensorFlow' -Version: 2.16.0.9000 +Version: 2.20.0.9000 Authors@R: c( person("JJ", "Allaire", role = c("aut", "cph")), person("Tomasz", "Kalinowski", role = c("ctb", "cph", "cre"), diff --git a/NAMESPACE b/NAMESPACE index a2ce6fd..a3279f2 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -142,6 +142,8 @@ export(iterate) export(np_array) export(parse_arguments) export(parse_flags) +export(py_require) +export(py_require_tensorflow) export(run_dir) export(set_random_seed) export(shape) @@ -162,6 +164,7 @@ export(use_python) export(use_session_with_seed) export(use_virtualenv) export(view_savedmodel) +if (getRversion() >= "4.3.0") S3method("%*%",tensorflow.tensor) import(reticulate) importFrom(grDevices,as.raster) importFrom(lifecycle,deprecated) @@ -171,6 +174,7 @@ importFrom(reticulate,dict) importFrom(reticulate,import) importFrom(reticulate,iterate) importFrom(reticulate,np_array) +importFrom(reticulate,py_require) importFrom(reticulate,tuple) importFrom(reticulate,use_condaenv) importFrom(reticulate,use_python) diff --git a/NEWS.md b/NEWS.md index 462e284..29e4225 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,9 +1,12 @@ # tensorflow (development version) -- Updates for reticulate 1.41. The tensorflow R package now calls - `reticuate::py_require()` when it is loaded. Calling `install_tensorflow()` +# tensorflow 2.20.0 + +- Updates for reticulate 1.41 and `reticuate::py_require()`. + New function `py_require_tensorflow()` which can be called at the start of an R session + to enable reticulate to resolve tensorflow. Calling `install_tensorflow()` in most circumstances is no longer necessary. -- `install_tensorflow()` installs TensorFlow v2.18 by default. +- `install_tensorflow()` installs TensorFlow v2.20 by default. - Fixed an issue where GPUs would not be found when running on Windows WSL Linux (reported in rstudio/keras3#1456, fixed in #599) - Fixes for NumPy 2.0 (#601) diff --git a/R/generics.R b/R/generics.R index 77bb300..14ba666 100644 --- a/R/generics.R +++ b/R/generics.R @@ -884,9 +884,7 @@ py_to_r.keras.src.utils.tracking.TrackedList <- function(x) import("builtins")$l #' @export py_to_r.keras.src.utils.tracking.TrackedSet <- function(x) import("builtins")$list(x) - -#' @rdname Ops-python-methods -#' @rawNamespace if (getRversion() >= "4.3.0") S3method("%*%",python.builtin.object) +#' @rawNamespace if (getRversion() >= "4.3.0") S3method("%*%",tensorflow.tensor) `%*%.tensorflow.tensor` <- function(x, y) { if (is.atomic(x) && is_tensor(y)) { if (length(x) > 1L) diff --git a/R/install.R b/R/install.R index ec66682..ff85bba 100644 --- a/R/install.R +++ b/R/install.R @@ -2,13 +2,23 @@ #' #' @description #' -#' Beginning with reticulate version 1.41, in most circumstances, calling the -#' `install_tensorflow()` function is no longer necessary, because reticulate -#' automatically registers python requirements with `reticulate::py_require()` -#' when tensorflow is loaded. +#' This function installs TensorFlow into a persistant virtual environment. +#' Beginning with reticulate version 1.41, in most circumstances, creating a +#' persistent virtual environment by calling the `install_tensorflow()` function +#' is no longer necessary, because reticulate automatically will resolve a +#' python environment that satisfies all python requirements declared with +#' `reticulate::py_require()`. #' -#' The Python packages registered with `py_require()` by the tensorflow R -#' package: +#' New code is recommended to call `py_require_tensorflow()` at the start of an +#' R session to declare tensorflow requirements via `py_requore()`. In a future +#' package update this will by default be done in tensorflow's `.onLoad` hook. +#' +#' The `py_require_tensorflow()` function that can dynamically modify the python +#' requirements to enable usage of a GPU if one is available and usable by the R +#' session. +#' +#' The Python packages registered with `py_require()` by +#' `py_require_tensorflow()`: #' #' - On Linux: if a GPU is detected: `"tensorflow[and-cuda]"`, otherwise, #' `"tensorflow-cpu"`. @@ -31,17 +41,6 @@ #' virtual environment with more complete set packages that includes additional #' optional dependencies, use [`keras3::install_keras()`]. #' -#' @details You may be prompted to download and install miniconda if reticulate -#' did not find a non-system installation of python. Miniconda is the -#' recommended installation method for most users, as it ensures that the R -#' python installation is isolated from other python installations. All python -#' packages will by default be installed into a self-contained conda or venv -#' environment named "r-reticulate". Note that "conda" is the only supported -#' method on M1 Mac. -#' -#' If you initially declined the miniconda installation prompt, you can later -#' manually install miniconda by running [`reticulate::install_miniconda()`]. -#' #' @section Custom Installation: `install_tensorflow()` or #' `keras3::install_keras()` isn't required to use tensorflow with the #' package. If you manually configure a python environment with the required @@ -131,6 +130,12 @@ #' @param new_env If `TRUE`, any existing Python virtual environment and/or #' conda environment specified by `envname` is deleted first. #' +#' @param use_gpu Only consulted if on Linux. It has no effect on macOS or +#' Windows. If `NA`, the R package will attempt to detect a GPU. If a GPU is +#' detected, then this is taken as `TRUE`, `FALSE` otherwise. If `TRUE`, then +#' `tensorflow[and-cuda]` is declared, otherwise, `tensorflow-cpu` is declared +#' via `py_require()`. +#' #' @param ... other arguments passed to [`reticulate::conda_install()`] or #' [`reticulate::virtualenv_install()`], depending on the `method` used. #' @@ -372,13 +377,15 @@ has_gpu <- function() { } -get_py_requirements <- function() { +get_py_requirements <- function(use_gpu = NA) { python_version <- NULL packages <- "tensorflow" if(is_linux()) { + if(is.na(use_gpu)) + use_gpu <- has_gpu() - if(has_gpu()) { + if(use_gpu) { packages <- "tensorflow[and-cuda]" } else { packages <- "tensorflow-cpu" @@ -402,7 +409,7 @@ get_py_requirements <- function() { list(packages = packages, python_version = python_version) } -default_version <- numeric_version("2.18") +default_version <- numeric_version("2.20") parse_tensorflow_version <- function(version) { # returns unquoted string directly passable to pip, e.g 'tensorflow==2.5.*' diff --git a/R/package.R b/R/package.R index 8fcc9ca..dad6a25 100644 --- a/R/package.R +++ b/R/package.R @@ -37,6 +37,13 @@ tf_v2 <- function() { .globals <- new.env(parent = emptyenv()) .globals$tensorboard <- NULL +#' @export +#' @rdname install_tensorflow +py_require_tensorflow <- function(use_gpu = NA) { + # register requirements with py_require() + reqs <- get_py_requirements(use_gpu) + reticulate::py_require(reqs$packages, reqs$python_version) +} .onLoad <- function(libname, pkgname) { @@ -61,9 +68,9 @@ tf_v2 <- function() { if (!is.null(cpp_log_opt)) Sys.setenv(TF_CPP_MIN_LOG_LEVEL = max(min(cpp_log_opt, 3), 0)) - # register requirements with py_require() - reqs <- get_py_requirements() - reticulate::py_require(reqs$packages, reqs$python_version) + if (tolower(Sys.getenv("PY_REQUIRE_TENSORFLOW")) %in% c("1", "true", "yes")) { + py_require_tensorflow() + } # delay load tensorflow tryCatch({ @@ -288,5 +295,8 @@ tf_config_error_message <- function() { message <- paste0(message, "\nYou can install TensorFlow using the install_tensorflow() function.\n") + base::message( + 'Hint: To use tensorflow with `py_require()`, call `py_require("tensorflow")` at the start of the R session' + ) message } diff --git a/R/reexports.R b/R/reexports.R index 9497268..24fc92c 100644 --- a/R/reexports.R +++ b/R/reexports.R @@ -30,6 +30,9 @@ reticulate::use_virtualenv #' @export reticulate::use_condaenv +#' @export +reticulate::py_require + #' @importFrom tfruns flags #' @export tfruns::flags diff --git a/man/install_tensorflow.Rd b/man/install_tensorflow.Rd index 74690a5..52df6b6 100644 --- a/man/install_tensorflow.Rd +++ b/man/install_tensorflow.Rd @@ -1,7 +1,8 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/install.R +% Please edit documentation in R/install.R, R/package.R \name{install_tensorflow} \alias{install_tensorflow} +\alias{py_require_tensorflow} \title{Install TensorFlow and its dependencies} \usage{ install_tensorflow( @@ -19,6 +20,8 @@ install_tensorflow( new_env = identical(envname, "r-tensorflow"), python_version = NULL ) + +py_require_tensorflow(use_gpu = NA) } \arguments{ \item{method}{Installation method. By default, "auto" automatically finds a @@ -32,7 +35,7 @@ See \strong{Finding Conda} and \code{\link[reticulate:conda_binary]{conda_binary \item{version}{TensorFlow version to install. Valid values include: \itemize{ -\item \code{"default"} installs 2.18 +\item \code{"default"} installs 2.20 \item \code{"release"} installs the latest release version of tensorflow (which may be incompatible with the current version of the R package) \item A version specification like \code{"2.4"} or \code{"2.4.0"}. Note that if the patch @@ -82,15 +85,31 @@ virtualenv. Pass a string with version constraints like \code{"3.8"}, or \code{reticulate::virtualenv_starter()}. Note that the Python version must be compatible with the requested TensorFlow version, documented here: \url{https://www.tensorflow.org/install/pip#system-requirements}} + +\item{use_gpu}{Only consulted if on Linux. It has no effect on macOS or +Windows. If \code{NA}, the R package will attempt to detect a GPU. If a GPU is +detected, then this is taken as \code{TRUE}, \code{FALSE} otherwise. If \code{TRUE}, then +\code{tensorflow[and-cuda]} is declared, otherwise, \code{tensorflow-cpu} is declared +via \code{py_require()}.} } \description{ -Beginning with reticulate version 1.41, in most circumstances, calling the -\code{install_tensorflow()} function is no longer necessary, because reticulate -automatically registers python requirements with \code{reticulate::py_require()} -when tensorflow is loaded. - -The Python packages registered with \code{py_require()} by the tensorflow R -package: +This function installs TensorFlow into a persistant virtual environment. +Beginning with reticulate version 1.41, in most circumstances, creating a +persistent virtual environment by calling the \code{install_tensorflow()} function +is no longer necessary, because reticulate automatically will resolve a +python environment that satisfies all python requirements declared with +\code{reticulate::py_require()}. + +New code is recommended to call \code{py_require_tensorflow()} at the start of an +R session to declare tensorflow requirements via \code{py_requore()}. In a future +package update this will by default be done in tensorflow's \code{.onLoad} hook. + +The \code{py_require_tensorflow()} function that can dynamically modify the python +requirements to enable usage of a GPU if one is available and usable by the R +session. + +The Python packages registered with \code{py_require()} by +\code{py_require_tensorflow()}: \itemize{ \item On Linux: if a GPU is detected: \code{"tensorflow[and-cuda]"}, otherwise, \code{"tensorflow-cpu"}. @@ -112,18 +131,6 @@ declared because at the time of this publishing, the pre-built binaries of virtual environment with more complete set packages that includes additional optional dependencies, use \code{\link[keras3:install_keras]{keras3::install_keras()}}. } -\details{ -You may be prompted to download and install miniconda if reticulate -did not find a non-system installation of python. Miniconda is the -recommended installation method for most users, as it ensures that the R -python installation is isolated from other python installations. All python -packages will by default be installed into a self-contained conda or venv -environment named "r-reticulate". Note that "conda" is the only supported -method on M1 Mac. - -If you initially declined the miniconda installation prompt, you can later -manually install miniconda by running \code{\link[reticulate:install_miniconda]{reticulate::install_miniconda()}}. -} \section{Custom Installation}{ \code{install_tensorflow()} or \code{keras3::install_keras()} isn't required to use tensorflow with the diff --git a/man/reexports.Rd b/man/reexports.Rd index 83fc2ec..5bc309a 100644 --- a/man/reexports.Rd +++ b/man/reexports.Rd @@ -13,6 +13,7 @@ \alias{use_python} \alias{use_virtualenv} \alias{use_condaenv} +\alias{py_require} \alias{flags} \alias{flag_numeric} \alias{flag_integer} @@ -26,7 +27,7 @@ These objects are imported from other packages. Follow the links below to see their documentation. \describe{ - \item{reticulate}{\code{\link[reticulate:with-as-operator]{\%as\%}}, \code{\link[reticulate]{array_reshape}}, \code{\link[reticulate]{dict}}, \code{\link[reticulate]{import}}, \code{\link[reticulate]{iterate}}, \code{\link[reticulate]{np_array}}, \code{\link[reticulate]{tuple}}, \code{\link[reticulate:use_python]{use_condaenv}}, \code{\link[reticulate]{use_python}}, \code{\link[reticulate:use_python]{use_virtualenv}}} + \item{reticulate}{\code{\link[reticulate:with-as-operator]{\%as\%}}, \code{\link[reticulate]{array_reshape}}, \code{\link[reticulate]{dict}}, \code{\link[reticulate]{import}}, \code{\link[reticulate]{iterate}}, \code{\link[reticulate]{np_array}}, \code{\link[reticulate]{py_require}}, \code{\link[reticulate]{tuple}}, \code{\link[reticulate:use_python]{use_condaenv}}, \code{\link[reticulate]{use_python}}, \code{\link[reticulate:use_python]{use_virtualenv}}} \item{tfruns}{\code{\link[tfruns:flags]{flag_boolean}}, \code{\link[tfruns:flags]{flag_integer}}, \code{\link[tfruns:flags]{flag_numeric}}, \code{\link[tfruns:flags]{flag_string}}, \code{\link[tfruns]{flags}}, \code{\link[tfruns]{run_dir}}} }}