Vinculaciones de óxido para la API C ++ de Pytorch. El objetivo de la caja tch es proporcionar algunos envoltorios delgados alrededor de la API Pytorch C ++ (también conocido como Libtorch). Su objetivo es permanecer lo más cerca posible de la API C ++ original. Se podrían desarrollar más enlaces de óxido idiomáticos sobre esto. La documentación se puede encontrar en docs.rs.
colegio de cambios
La parte de generación de código para la API C sobre Libtorch proviene de Ocaml-Torch.
Esta caja requiere que la Biblioteca C ++ Pytorch (Libtorch) en la versión v2.5.1 esté disponible en su sistema. Tú puedes:
LIBTORCH .LIBTORCH_USE_PYTORCH=1 .LIBTORCH , el script de compilación puede descargar una versión binaria preconstruida de Libtorch utilizando la función download-libtorch . Por defecto, se usa una versión de CPU. La variable de entorno TORCH_CUDA_VERSION se puede configurar en cu117 para obtener un binario prebuilado usando CUDA 11.7. En las plataformas Linux, el script de compilación buscará una biblioteca de Libtorch de todo el sistema en /usr/lib/libtorch.so .
Si se establece la variable de entorno LIBTORCH_USE_PYTORCH , se llama al intérprete Python activo para recuperar información sobre el paquete de la antorcha Python. Esta versión está vinculada contra.
libtorch de la sección de descarga del sitio web de Pytorch y extraiga el contenido del archivo zip..bashrc o equivalente, donde /path/to/libtorch es la ruta al directorio que se creó al desabrochar el archivo. export LIBTORCH=/path/to/libtorchLa ubicación de los archivos de encabezado también se puede especificar por separado de la biblioteca compartida a través de lo siguiente:
# LIBTORCH_INCLUDE must contain `include` directory.
export LIBTORCH_INCLUDE=/path/to/libtorch/
# LIBTORCH_LIB must contain `lib` directory.
export LIBTORCH_LIB=/path/to/libtorch/ Para los usuarios de Windows, suponiendo que X:pathtolibtorch es el directorio de libtorch descomprimido.
LIBTORCH y estén en X:pathtolibtorch .X:pathtolibtorchlib a la variable Path .Si prefiere establecer temporalmente las variables de entorno, en PowerShell puede ejecutar
$ Env: LIBTORCH = " X:pathtolibtorch "
$ Env: Path += " ;X:pathtolibtorchlib "cargo run --example basics .Según los documentos de Pytorch, la depuración de Windows y las compilaciones de lanzamiento no son compatibles con ABI. Esto podría conducir a algunos Segfaults si se usa la versión incorrecta de Libtorch.
Se recomienda utilizar la cadena de herramientas de Rust MSVC (por ejemplo, instalando stable-x86_64-pc-windows-msvc a través de Rustup) en lugar de una basada en Mingw, ya que Pytorch tiene problemas de compatibilidad con MingW.
Al establecer la variable de entorno LIBTORCH_STATIC=1 , libtorch está estáticamente vinculado en lugar de usar las bibliotecas dinámicas. Los artefactos precompilados no parecen incluir libtorch.a por defecto, por lo que esto tendría que ser compilado manualmente, por ejemplo, a través de lo siguiente:
git clone -b v2.5.1 --recurse-submodule https://github.com/pytorch/pytorch.git pytorch-static --depth 1
cd pytorch-static
USE_CUDA=OFF BUILD_SHARED_LIBS=OFF python setup.py build
# export LIBTORCH to point at the build directory in pytorch-static. Esta caja proporciona un tipo de tensor que envuelve los tensores de Pytorch. Aquí hay un ejemplo mínimo de cómo realizar algunas operaciones de tensor.
use tch :: Tensor ;
fn main ( ) {
let t = Tensor :: from_slice ( & [ 3 , 1 , 4 , 1 , 5 ] ) ;
let t = t * 2 ;
t . print ( ) ;
} Pytorch proporciona diferenciación automática para la mayoría de las operaciones tensoras que admite. Esto se usa comúnmente para entrenar modelos con descenso de gradiente. La optimización se realiza sobre las variables que se crean a través de una nn::VarStore al definir sus formas e inicializaciones.
En el ejemplo a continuación, my_module usa dos variables x1 y x2 que los valores iniciales son 0. El pase hacia adelante aplicado al tensor xs devuelve xs * x1 + exp(xs) * x2 .
Una vez que se ha generado el modelo, se crea un optimizador nn::Sgd . Luego en cada paso del bucle de entrenamiento:
VarStore se modifican en consecuencia. use tch :: nn :: { Module , OptimizerConfig } ;
use tch :: { kind , nn , Device , Tensor } ;
fn my_module ( p : nn :: Path , dim : i64 ) -> impl nn :: Module {
let x1 = p . zeros ( "x1" , & [ dim ] ) ;
let x2 = p . zeros ( "x2" , & [ dim ] ) ;
nn :: func ( move |xs| xs * & x1 + xs . exp ( ) * & x2 )
}
fn gradient_descent ( ) {
let vs = nn :: VarStore :: new ( Device :: Cpu ) ;
let my_module = my_module ( vs . root ( ) , 7 ) ;
let mut opt = nn :: Sgd :: default ( ) . build ( & vs , 1e-2 ) . unwrap ( ) ;
for _idx in 1 .. 50 {
// Dummy mini-batches made of zeros.
let xs = Tensor :: zeros ( & [ 7 ] , kind :: FLOAT_CPU ) ;
let ys = Tensor :: zeros ( & [ 7 ] , kind :: FLOAT_CPU ) ;
let loss = ( my_module . forward ( & xs ) - ys ) . pow_tensor_scalar ( 2 ) . sum ( kind :: Kind :: Float ) ;
opt . backward_step ( & loss ) ;
}
} La API nn se puede utilizar para crear arquitecturas de redes neuronales, por ejemplo, el siguiente código define un modelo simple con una capa oculta y la entrena en el conjunto de datos MNIST utilizando el Optimizer Adam.
use anyhow :: Result ;
use tch :: { nn , nn :: Module , nn :: OptimizerConfig , Device } ;
const IMAGE_DIM : i64 = 784 ;
const HIDDEN_NODES : i64 = 128 ;
const LABELS : i64 = 10 ;
fn net ( vs : & nn :: Path ) -> impl Module {
nn :: seq ( )
. add ( nn :: linear (
vs / "layer1" ,
IMAGE_DIM ,
HIDDEN_NODES ,
Default :: default ( ) ,
) )
. add_fn ( |xs| xs . relu ( ) )
. add ( nn :: linear ( vs , HIDDEN_NODES , LABELS , Default :: default ( ) ) )
}
pub fn run ( ) -> Result < ( ) > {
let m = tch :: vision :: mnist :: load_dir ( "data" ) ? ;
let vs = nn :: VarStore :: new ( Device :: Cpu ) ;
let net = net ( & vs . root ( ) ) ;
let mut opt = nn :: Adam :: default ( ) . build ( & vs , 1e-3 ) ? ;
for epoch in 1 .. 200 {
let loss = net
. forward ( & m . train_images )
. cross_entropy_for_logits ( & m . train_labels ) ;
opt . backward_step ( & loss ) ;
let test_accuracy = net
. forward ( & m . test_images )
. accuracy_for_logits ( & m . test_labels ) ;
println ! (
"epoch: {:4} train loss: {:8.5} test acc: {:5.2}%" ,
epoch ,
f64 :: from ( & loss ) ,
100. * f64 :: from ( & test_accuracy ) ,
) ;
}
Ok ( ( ) )
}Se pueden encontrar más detalles sobre el bucle de entrenamiento en el tutorial detallado.
El ejemplo de los modelos previos a la aparición ilustra cómo usar un modelo de visión por computadora previamente capacitada en una imagen. Los pesos, que se han extraído de la implementación de Pytorch, se pueden descargar aquí resnet18.ot y aquí resnet34.ot.
El ejemplo se puede ejecutar a través del siguiente comando:
cargo run --example pretrained-models -- resnet18.ot tiger.jpgEsto debería imprimir las 5 mejores categorías de Imagenet para la imagen. El código para este ejemplo es bastante simple.
// First the image is loaded and resized to 224x224.
let image = imagenet :: load_image_and_resize ( image_file ) ? ;
// A variable store is created to hold the model parameters.
let vs = tch :: nn :: VarStore :: new ( tch :: Device :: Cpu ) ;
// Then the model is built on this variable store, and the weights are loaded.
let resnet18 = tch :: vision :: resnet :: resnet18 ( vs . root ( ) , imagenet :: CLASS_COUNT ) ;
vs . load ( weight_file ) ? ;
// Apply the forward pass of the model to get the logits and convert them
// to probabilities via a softmax.
let output = resnet18
. forward_t ( & image . unsqueeze ( 0 ) , /*train=*/ false )
. softmax ( - 1 ) ;
// Finally print the top 5 categories and their associated probabilities.
for ( probability , class ) in imagenet :: top ( & output , 5 ) . iter ( ) {
println ! ( "{:50} {:5.2}%" , class , 100.0 * probability )
} safetensors es un nuevo formato simple de Huggingface para almacenar tensores. No se basa en el módulo pickle de Python y, por lo tanto, los tensores no están vinculados a las clases específicas y la estructura exacta del directorio utilizada cuando se guarda el modelo. También es una copia cero, lo que significa que leer el archivo no requerirá más memoria que el archivo original.
Para obtener más información sobre safetensors , consulte https://github.com/huggingface/Safetensors
safetensors Puede instalar safetensors a través del Administrador de PIP:
pip install safetensors
import torchvision
from safetensors import torch as stt
model = torchvision . models . resnet18 ( pretrained = True )
stt . save_file ( model . state_dict (), 'resnet18.safetensors' ) NOTA: El nombre de archivo de la exportación debe nombrarse con un sufijo .safetensors para que sea decodificado correctamente por tch .
tch use anyhow :: Result ;
use tch :: {
Device ,
Kind ,
nn :: VarStore ,
vision :: {
imagenet ,
resnet :: resnet18 ,
}
} ;
fn main ( ) -> Result < ( ) > {
// Create the model and load the pre-trained weights
let mut vs = VarStore :: new ( Device :: cuda_if_available ( ) ) ;
let model = resnet18 ( & vs . root ( ) , 1000 ) ;
vs . load ( "resnet18.safetensors" ) ? ;
// Load the image file and resize it to the usual imagenet dimension of 224x224.
let image = imagenet :: load_image_and_resize224 ( "dog.jpg" ) ?
. to_device ( vs . device ( ) ) ;
// Apply the forward pass of the model to get the logits
let output = image
. unsqueeze ( 0 )
. apply_t ( & model , false )
. softmax ( - 1 , Kind :: Float ) ;
// Print the top 5 categories for this image.
for ( probability , class ) in imagenet :: top ( & output , 5 ) . iter ( ) {
println ! ( "{:50} {:5.2}%" , class , 100.0 * probability )
}
Ok ( ( ) )
}Otros ejemplos incluyen:
Material externo:
tch-rs y opencv para ejecutar una inferencia en una alimentación de cámara web para algún modelo capacitado en Python basado en MobileNet V3. Vea algunos detalles en este hilo.
Verifique este problema.
Vea este problema, esto podría ser causado por Rust-Analyzer sin saber sobre las variables de entorno adecuadas como LIBTORCH y LD_LIBRARY_PATH .
Es posible llamar al código de óxido/TCH desde Python a través de PYO3, TCH-EXT proporciona un ejemplo de tal extensión de Python.
Si recibe un error al no encontrar algunas bibliotecas compartidas al ejecutar los binarios generados (por ejemplo error while loading shared libraries: libtorch_cpu.so: cannot open shared object file: No such file or directory ). Puede intentar agregar lo siguiente a su .bashrc donde /path/to/libtorch es la ruta a su instalación de libtorch.
# For Linux
export LD_LIBRARY_PATH=/path/to/libtorch/lib:$LD_LIBRARY_PATH
# For macOS
export DYLD_LIBRARY_PATH=/path/to/libtorch/lib:$DYLD_LIBRARY_PATH
tch-rs se distribuye bajo los términos de la licencia MIT y la licencia Apache (versión 2.0), a su opción.
Vea la licencia-apache, licencia-mit para más detalles.