Rostbindungen für die C ++ - API von Pytorch. Das Ziel der tch -Kiste ist es, einige dünne Wrapper um die C ++ - Pytorch -API (auch bekannt als Libtorch) zu liefern. Es zielt darauf ab, der ursprünglichen C ++ - API so nah wie möglich zu bleiben. Anschließend könnten idiomatische Rostbindungen darüber entwickelt werden. Die Dokumentation finden Sie in Docs.rs.
Changelog
Der Code-Erzeugungsteil für die C-API über Libtorch stammt von OCAML-TORCH.
Diese Kiste erfordert, dass die C ++ Pytorch Library (LIBTORCH) in Version V2.5.1 in Ihrem System verfügbar ist. Sie können entweder:
LIBTORCH -Umgebungsvariable.LIBTORCH_USE_PYTORCH=1 zu tun.LIBTORCH nicht festgelegt ist, kann das Build-Skript eine vorgefertigte binäre Version von Libtorch mithilfe der Funktion download-libtorch herunterladen. Standardmäßig wird eine CPU -Version verwendet. Die Variable Umgebungsvariable TORCH_CUDA_VERSION kann auf cu117 eingestellt werden, um eine vorgefertigte Binärdatei mit CUDA 11.7 zu erhalten. Auf Linux-Plattformen sucht das Build-Skript nach einer systemweiten Libtorch-Bibliothek in /usr/lib/libtorch.so .
Wenn die Umgebungsvariable LIBTORCH_USE_PYTORCH festgelegt ist, wird der aktive Python -Interpreter aufgerufen, um Informationen über das Torch -Python -Paket abzurufen. Diese Version wird dann gegen verknüpft.
libtorch aus dem Abschnitt "Pytorch -Website Download" und extrahieren Sie den Inhalt der ZIP -Datei..bashrc oder gleichwertig hinzu, wobei /path/to/libtorch der Pfad zum Verzeichnis ist, der beim Entpacken der Datei erstellt wurde. export LIBTORCH=/path/to/libtorchDer Speicherort der Header -Dateien kann auch separat von der freigegebenen Bibliothek über Folgendes angegeben werden:
# LIBTORCH_INCLUDE must contain `include` directory.
export LIBTORCH_INCLUDE=/path/to/libtorch/
# LIBTORCH_LIB must contain `lib` directory.
export LIBTORCH_LIB=/path/to/libtorch/ Für Windows -Benutzer ist unter der Annahme, dass X:pathtolibtorch das nicht ausgeputzte Libtorch -Verzeichnis ist.
LIBTORCH -Variable und setzen Sie sie auf X:pathtolibtorch .X:pathtolibtorchlib an die Path .Wenn Sie vorübergehend Umgebungsvariablen festlegen möchten, können Sie in PowerShell ausführen
$ Env: LIBTORCH = " X:pathtolibtorch "
$ Env: Path += " ;X:pathtolibtorchlib "cargo run --example basics .Gemäß den Pytorch-Dokumenten sind die Windows-Debug- und Release-Builds nicht abi-kompatibel. Dies könnte zu einigen Segfaults führen, wenn die falsche Version von Libtorch verwendet wird.
Es wird empfohlen, die MSVC-Rust-Toolchain (z. B. durch Installieren stable-x86_64-pc-windows-msvc über Rustup) zu verwenden, anstatt eine Mingw-basierte, als Pytorch Probleme mit Mingw hat.
Bei der Festlegung der Umgebungsvariablen LIBTORCH_STATIC=1 ist libtorch statisch verknüpft, anstatt die dynamischen Bibliotheken zu verwenden. Die vorkompilierten Artefakte scheinen nicht libtorch.a zu enthalten. Ein standardmäßig müsste dies manuell zusammengestellt werden, z. B. über Folgendes:
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. Diese Kiste bietet einen Tensor -Typ, der Pytorch -Tensoren umhüllt. Hier ist ein minimales Beispiel dafür, wie einige Tensoroperationen durchgeführt werden können.
use tch :: Tensor ;
fn main ( ) {
let t = Tensor :: from_slice ( & [ 3 , 1 , 4 , 1 , 5 ] ) ;
let t = t * 2 ;
t . print ( ) ;
} Pytorch bietet eine automatische Differenzierung für die meisten von ihm unterstützten Tensoroperationen. Dies wird üblicherweise verwendet, um Modelle mithilfe von Gradientenabsenken zu trainieren. Die Optimierung wird über Variablen durchgeführt, die über einen nn::VarStore erstellt werden, indem ihre Formen und Initialisierungen definiert werden.
Im folgenden Beispiel verwendet my_module zwei Variablen x1 und x2 , welche Anfangswerte 0 sind. Der auf Tensor xs angewendete Vorwärtspass gibt xs * x1 + exp(xs) * x2 zurück.
Sobald das Modell generiert wurde, wird ein nn::Sgd -Optimierer erstellt. Dann bei jedem Schritt der Trainingsschleife:
VarStore werden entsprechend geändert. 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 ) ;
}
} Die nn -API kann verwendet werden, um neuronale Netzwerkarchitekturen zu erstellen, z. B. der folgende Code definiert ein einfaches Modell mit einer versteckten Schicht und trainiert es mit dem Adam -Optimierer auf dem MNIST -Datensatz.
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 ( ( ) )
}Weitere Details zur Trainingsschleife finden Sie im detaillierten Tutorial.
Das Beispiel für vorbereitete Modelle zeigt, wie ein vorgebildetes Computer-Vision-Modell für ein Bild verwendet wird. Die Gewichte, die aus der Pytorch -Implementierung extrahiert wurden, können hier heruntergeladen werden.
Das Beispiel kann dann über den folgenden Befehl ausgeführt werden:
cargo run --example pretrained-models -- resnet18.ot tiger.jpgDies sollte die Top 5 ImageNet -Kategorien für das Bild drucken. Der Code für dieses Beispiel ist ziemlich einfach.
// 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 ist ein neues einfaches Format, indem er Tensoren speichert. Es beruht nicht auf Pythons pickle , und daher sind die Tensoren nicht an die spezifischen Klassen und die genaue Verzeichnisstruktur gebunden, die beim Speichern des Modells verwendet wird. Es ist auch keine Kopie, was bedeutet, dass das Lesen der Datei keinen Speicher mehr als die Originaldatei erfordert.
Weitere Informationen zu safetensors finden Sie unter https://github.com/huggingface/safetensors
safetensors installieren Sie können safetensors über den PIP -Manager installieren:
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' ) HINWEIS: Der Dateiname des Exports muss mit einem Suffix .safetensors benannt werden, damit er von tch ordnungsgemäß dekodiert wird.
tch importieren 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 ( ( ) )
}Weitere Beispiele sind:
Externes Material:
tch-rs und opencv , um in einem Webcam-Feed für ein Python-geschulter Modell zu geleitet, das auf Mobilenet V3 basiert. In diesem Thread finden Sie einige Details.
Überprüfen Sie dieses Problem.
Sehen Sie sich dieses Problem an, dies könnte durch Rost-Analyzer verursacht werden, ohne die richtigen Umgebungsvariablen wie LIBTORCH und LD_LIBRARY_PATH zu kennen.
Es ist möglich, Rust/TCH Code von Python über Pyo3 aufzurufen.
Wenn Sie beim Ausführen der generierten Binärdateien einen Fehler darüber erhalten, einige gemeinsam genutzte Bibliotheken nicht zu finden (z. B. error while loading shared libraries: libtorch_cpu.so: cannot open shared object file: No such file or directory ). Sie können versuchen, Ihr .bashrc hinzuzufügen, wobei /path/to/libtorch der Weg zu Ihrer Libtorch -Installation ist.
# 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 wird sowohl in der MIT-Lizenz als auch in der Apache-Lizenz (Version 2.0) nach Ihrer Option verteilt.
Weitere Informationen finden Sie unter Lizenz-Apache, Lizenz-Mitarbeit.