Estamos felices de anunciar que la versión 0.2.0 de torch
Acabo de aterrizar en CRAN.
Esta versión incluye muchas correcciones de errores y algunas características nuevas e interesantes que presentaremos en esta publicación de weblog. Puedes ver el registro de cambios completo en el NOTICIAS.md archivo.
Las características que discutiremos en detalle son:
- Soporte inicial para el rastreo JIT
- Cargadores de datos para múltiples trabajadores
- Métodos de impresión para
nn_modules
Cargadores de datos para múltiples trabajadores
dataloaders
ahora responde a la num_workers
argumento y ejecutará el preprocesamiento en trabajadores paralelos.
Por ejemplo, digamos que tenemos el siguiente conjunto de datos ficticio que realiza un cálculo largo:
library(torch)
dat <- dataset(
"mydataset",
initialize = operate(time, len = 10) {
self$time <- time
self$len <- len
},
.getitem = operate(i) {
Sys.sleep(self$time)
torch_randn(1)
},
.size = operate() {
self$len
}
)
ds <- dat(1)
system.time(ds[1])
consumer system elapsed
0.029 0.005 1.027
Ahora crearemos dos cargadores de datos, uno que se ejecute secuencialmente y otro que se ejecute en paralelo.
seq_dl <- dataloader(ds, batch_size = 5)
par_dl <- dataloader(ds, batch_size = 5, num_workers = 2)
Ahora podemos comparar el tiempo que lleva procesar dos lotes de forma secuencial con el tiempo que lleva en paralelo:
seq_it <- dataloader_make_iter(seq_dl)
par_it <- dataloader_make_iter(par_dl)
two_batches <- operate(it) {
dataloader_next(it)
dataloader_next(it)
"okay"
}
system.time(two_batches(seq_it))
system.time(two_batches(par_it))
consumer system elapsed
0.098 0.032 10.086
consumer system elapsed
0.065 0.008 5.134
Tenga en cuenta que son lotes los que se obtienen en paralelo, no observaciones individuales. De esta manera, podremos admitir conjuntos de datos con tamaños de lote variables en el futuro.
Usar varios trabajadores es no necesariamente más rápido que la ejecución en serie porque hay una sobrecarga appreciable al pasar tensores de un trabajador a la sesión principal, así como al inicializar los trabajadores.
Esta característica está habilitada por el poderoso callr
paquete y funciona en todos los sistemas operativos soportados por torch
. callr
Creemos sesiones de R persistentes y, por lo tanto, solo pagamos una vez los gastos generales de transferir objetos de conjuntos de datos potencialmente grandes a los trabajadores.
En el proceso de implementación de esta característica, hemos hecho que los cargadores de datos se comporten como coro
iteradores. Esto significa que ahora puedes usar coro
Sintaxis de para recorrer los cargadores de datos:
coro::loop(for(batch in par_dl) {
print(batch$form)
})
[1] 5 1
[1] 5 1
Este es el primero torch
versión que incluye la función de cargadores de datos para múltiples trabajadores, y es posible que se encuentre con casos extremos al usarlo. Háganos saber si encuentra algún problema.
Soporte JIT inicial
Programas que hacen uso de la torch
El paquete son inevitablemente programas R y, por lo tanto, siempre necesitan una instalación de R para poder ejecutarse.
A partir de la versión 0.2.0, torch
permite a los usuarios JIT rastro
torch
R funciona en TorchScript. El seguimiento JIT (justo a tiempo) invocará una función R con entradas de ejemplo, registrará todas las operaciones que ocurrieron cuando se ejecutó la función y devolverá un script_function
objeto que contiene la representación de TorchScript.
Lo bueno de esto es que los programas TorchScript son fácilmente serializables, optimizables y pueden cargarse mediante otro programa escrito en PyTorch o LibTorch sin necesidad de ninguna dependencia de R.
Suponga que tiene la siguiente función R que toma un tensor, realiza una multiplicación de matrices con una matriz de peso fijo y luego agrega un término de sesgo:
w <- torch_randn(10, 1)
b <- torch_randn(1)
fn <- operate(x) {
a <- torch_mm(x, w)
a + b
}
Esta función se puede rastrear JIT en TorchScript con jit_trace
pasando la función y las entradas de ejemplo:
x <- torch_ones(2, 10)
tr_fn <- jit_trace(fn, x)
tr_fn(x)
torch_tensor
-0.6880
-0.6880
[ CPUFloatType{2,1} ]
Ahora todos torch
Las operaciones que sucedieron al calcular el resultado de esta función fueron trazadas y transformadas en una gráfica:
graph(%0 : Float(2:10, 10:1, requires_grad=0, machine=cpu)):
%1 : Float(10:1, 1:1, requires_grad=0, machine=cpu) = prim::Fixed[value=-0.3532 0.6490 -0.9255 0.9452 -1.2844 0.3011 0.4590 -0.2026 -1.2983 1.5800 [ CPUFloatType{10,1} ]]()
%2 : Float(2:1, 1:1, requires_grad=0, machine=cpu) = aten::mm(%0, %1)
%3 : Float(1:1, requires_grad=0, machine=cpu) = prim::Fixed[value={-0.558343}]()
%4 : int = prim::Fixed[value=1]()
%5 : Float(2:1, 1:1, requires_grad=0, machine=cpu) = aten::add(%2, %3, %4)
return (%5)
La función rastreada se puede serializar con jit_save
:
jit_save(tr_fn, "linear.pt")
Se puede recargar en R con jit_load
pero también se puede recargar en Python con torch.jit.load
:
import torch
= torch.jit.load("linear.pt")
fn 2, 10)) fn(torch.ones(
tensor([[-0.6880],
[-0.6880]])
¡¿Qué tan genial es eso?!
Este es solo el soporte inicial para JIT en R. Continuaremos desarrollándolo. En concreto, en la próxima versión de torch
planeamos apoyar el rastreo nn_modules
directamente. Actualmente, es necesario separar todos los parámetros antes de rastrearlos; ver un ejemplo aquí. ¡Esto también le permitirá aprovechar TorchScript para hacer que sus modelos se ejecuten más rápido!
También tenga en cuenta que el seguimiento tiene algunas limitaciones, especialmente cuando su código tiene bucles o declaraciones de flujo de management que dependen de datos tensoriales. Ver ?jit_trace
para aprender más.
Nuevo método de impresión para nn_modules
En esta versión también hemos mejorado el nn_module
métodos de impresión para que sea más fácil entender lo que hay dentro.
Por ejemplo, si crea una instancia de un nn_linear
módulo verá:
An `nn_module` containing 11 parameters.
── Parameters ──────────────────────────────────────────────────────────────────
● weight: Float [1:1, 1:10]
● bias: Float [1:1]
Inmediatamente verá el número complete de parámetros en el módulo, así como sus nombres y formas.
Esto también funciona para módulos personalizados (posiblemente incluidos submódulos). Por ejemplo:
my_module <- nn_module(
initialize = operate() {
self$linear <- nn_linear(10, 1)
self$param <- nn_parameter(torch_randn(5,1))
self$buff <- nn_buffer(torch_randn(5))
}
)
my_module()
An `nn_module` containing 16 parameters.
── Modules ─────────────────────────────────────────────────────────────────────
● linear: <nn_linear> #11 parameters
── Parameters ──────────────────────────────────────────────────────────────────
● param: Float [1:5, 1:1]
── Buffers ─────────────────────────────────────────────────────────────────────
● buff: Float [1:5]
Esperamos que esto haga que sea más fácil de entender. nn_module
objetos. También hemos mejorado el soporte de autocompletar para nn_modules
y ahora mostraremos todos los submódulos, parámetros y buffers mientras escribe.
antorchaaudio
torchaudio
es una extensión para torch
desarrollado por Athos Damiani (@athospd
), que proporciona carga de audio, transformaciones, arquitecturas comunes para el procesamiento de señales, pesos previamente entrenados y acceso a conjuntos de datos de uso común. Una traducción casi literal de la biblioteca Torchaudio de PyTorch a R.
torchaudio
aún no está en CRAN, pero ya puedes probar la versión de desarrollo disponible aquí.
También puedes visitar el pkgdown
sitio internet para ejemplos y documentación de referencia.
Otras características y correcciones de errores
Gracias a las contribuciones de la comunidad, hemos encontrado y solucionado muchos errores en torch
. También hemos agregado nuevas características que incluyen:
Puedes ver la lista completa de cambios en el NOTICIAS.md archivo.
¡Muchas gracias por leer esta publicación de weblog y no dudes en comunicarte con GitHub para obtener ayuda o debates!
La foto utilizada en esta vista previa de la publicación es de Oleg Ilarionov en desempaquetar