روابط الصدأ لـ C ++ API من Pytorch. الهدف من قفص tch هو توفير بعض الأغلفة الرفيعة حول API C ++ Pytorch (المعروف أيضًا باسم Libtorch). يهدف إلى البقاء أقرب ما يمكن إلى واجهة برمجة تطبيقات C ++ الأصلية. يمكن بعد ذلك تطوير المزيد من روابط الصدأ الاصطناعية فوق هذا. يمكن العثور على الوثائق على Docs.rs.
Changelog
جزء توليد الكود لـ C API أعلى libtorch يأتي من OCAML-TORCH.
يتطلب هذا الصندوق مكتبة C ++ Pytorch (libtorch) في الإصدار v2.5.1 لتتوفر على نظامك. يمكنك إما:
LIBTORCH .LIBTORCH_USE_PYTORCH=1 .LIBTORCH ، يمكن لبرنامج Build Script تنزيل إصدار ثنائي تم إنشاؤه مسبقًا من libtorch باستخدام ميزة download-libtorch . بشكل افتراضي ، يتم استخدام إصدار وحدة المعالجة المركزية. يمكن تعيين متغير بيئة TORCH_CUDA_VERSION إلى cu117 من أجل الحصول على ثنائي تم إنشاؤه مسبقًا باستخدام CUDA 11.7. على منصات Linux ، سيبحث برنامج Build Script عن مكتبة LiBtorch على مستوى النظام في /usr/lib/libtorch.so .
إذا تم تعيين متغير بيئة LIBTORCH_USE_PYTORCH ، يتم استدعاء مترجم بيثون النشط لاسترداد المعلومات حول حزمة بيثون الشعلة. ثم يتم ربط هذا الإصدار.
libtorch من قسم تنزيل موقع Pytorch واستخراج محتوى ملف zip..bashrc أو ما يعادله ، حيث /path/to/libtorch هو المسار إلى الدليل الذي تم إنشاؤه عند إلغاء زيادة الملف. export LIBTORCH=/path/to/libtorchيمكن أيضًا تحديد موقع ملفات الرأس بشكل منفصل عن المكتبة المشتركة عبر ما يلي:
# LIBTORCH_INCLUDE must contain `include` directory.
export LIBTORCH_INCLUDE=/path/to/libtorch/
# LIBTORCH_LIB must contain `lib` directory.
export LIBTORCH_LIB=/path/to/libtorch/ بالنسبة لمستخدمي Windows ، على افتراض أن X:pathtolibtorch هو دليل libtorch غير المصقول.
LIBTORCH وقم بتعيينه على X:pathtolibtorch .X:pathtolibtorchlib إلى متغير Path .إذا كنت تفضل تعيين متغيرات البيئة مؤقتًا ، فيمكنك تشغيل في PowerShell
$ Env: LIBTORCH = " X:pathtolibtorch "
$ Env: Path += " ;X:pathtolibtorchlib "cargo run --example basics .وفقًا لمستندات Pytorch ، فإن تصحيح Windows وتصميمات الإصدار غير متوافقة مع ABI. قد يؤدي هذا إلى بعض segfaults إذا تم استخدام النسخة غير الصحيحة من libtorch.
يوصى باستخدام مخطط أدوات MSVC RUST (على سبيل المثال عن طريق تثبيت stable-x86_64-pc-windows-msvc عبر Rustup) بدلاً من واحدة من Mingw لأن Pytorch لديها مشكلات التوافق مع MINGW.
عند ضبط البيئة المتغير LIBTORCH_STATIC=1 ، يكون libtorch مرتبطًا بشكل ثابت بدلاً من استخدام المكتبات الديناميكية. لا يبدو أن القطع الأثرية المبللة مسبقًا تتضمن libtorch.a افتراضيًا ، لذا يجب تجميع ذلك يدويًا ، على سبيل المثال عبر ما يلي:
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. يوفر هذا الصندوق نوعًا من الموتر الذي يلف موتر Pytorch. فيما يلي مثال أدنى على كيفية أداء بعض عمليات الموتر.
use tch :: Tensor ;
fn main ( ) {
let t = Tensor :: from_slice ( & [ 3 , 1 , 4 , 1 , 5 ] ) ;
let t = t * 2 ;
t . print ( ) ;
} يوفر Pytorch تمايزًا تلقائيًا لمعظم عمليات الموتر التي يدعمها. يستخدم هذا عادة لتدريب النماذج باستخدام نزول التدرج. يتم إجراء التحسين على المتغيرات التي يتم إنشاؤها عبر nn::VarStore من خلال تحديد أشكالها وتهيئةها.
في المثال أدناه ، يستخدم my_module متغيرين x1 و x2 أي القيم الأولية هي 0. تم تطبيق التمرير الأمامي المطبقة على Tensor xs إرجاع xs * x1 + exp(xs) * x2 .
بمجرد إنشاء النموذج ، يتم إنشاء مُحسّن nn::Sgd . ثم في كل خطوة من حلقة التدريب:
VarStore وفقًا لذلك. 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 ) ;
}
} يمكن استخدام nn API لإنشاء بنيات الشبكة العصبية ، على سبيل المثال ، يحدد الكود التالي نموذجًا بسيطًا مع طبقة مخفية واحدة ويدربها على مجموعة بيانات MNIST باستخدام 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 ( ( ) )
}يمكن العثور على مزيد من التفاصيل حول حلقة التدريب في البرنامج التعليمي التفصيلي.
يوضح مثال النماذج المسبقة كيفية استخدام نموذج رؤية الكمبيوتر الذي تم تدريبه مسبقًا على صورة. يمكن تنزيل الأوزان - التي تم استخلاصها من تطبيق Pytorch - هنا Resnet18.ot وهنا Resnet34.ot.
يمكن بعد ذلك تشغيل المثال عبر الأمر التالي:
cargo run --example pretrained-models -- resnet18.ot tiger.jpgهذا يجب أن يطبع أفضل 5 فئات ImageNet للصورة. رمز هذا المثال بسيط جدا.
// 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 هو تنسيق بسيط جديد من خلال Huggingface لتخزين الموترات. لا يعتمد على وحدة pickle في Python ، وبالتالي لا ترتبط الموتر بالفئات المحددة وهيكل الدليل الدقيق المستخدم عند حفظ النموذج. إنه أيضًا صفعة ، مما يعني أن قراءة الملف لن تتطلب ذاكرة أكثر من الملف الأصلي.
لمزيد من المعلومات حول safetensors ، يرجى مراجعة https://github.com/huggingface/safetensors
safetensors يمكنك تثبيت safetensors عبر مدير 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' ) ملاحظة: يجب تسمية اسم .safetensors للتصدير 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 ( ( ) )
}وتشمل الأمثلة الإضافية:
المواد الخارجية:
tch-rs و opencv لتشغيل التغذية على خلاصة كاميرا الويب لبعض النموذج المدرب على Python استنادًا إلى Mobilenet V3. انظر بعض التفاصيل في هذا الموضوع.
تحقق من هذه المشكلة.
شاهد هذه المشكلة ، يمكن أن يكون هذا ناتجًا عن عدم معرفة Rust-analyzer عن متغيرات البيئة المناسبة مثل LIBTORCH و LD_LIBRARY_PATH .
من الممكن استدعاء رمز Rust/TCH من Python عبر Pyo3 ، ويقدم TCH-EXT مثالًا على امتداد بيثون.
إذا تلقيت خطأً حول عدم العثور على بعض المكتبات المشتركة عند تشغيل الثنائيات التي تم إنشاؤها (مثل error while loading shared libraries: libtorch_cpu.so: cannot open shared object file: No such file or directory ). يمكنك محاولة إضافة ما يلي إلى .bashrc حيث /path/to/libtorch هو المسار إلى تثبيت 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 بموجب شروط كل من ترخيص MIT وترخيص Apache (الإصدار 2.0) ، في خيارك.
راجع ترخيص apache ، ترخيص-ميت لمزيد من التفاصيل.