นี่ไม่ใช่คู่มือสไตล์อย่างเป็นทางการสำหรับ Pytorch เอกสารนี้สรุปแนวปฏิบัติที่ดีที่สุดจากประสบการณ์มากกว่าหนึ่งปีด้วยการเรียนรู้อย่างลึกซึ้งโดยใช้เฟรมเวิร์ก Pytorch โปรดทราบว่าการเรียนรู้ที่เราแบ่งปันส่วนใหญ่มาจากมุมมองการวิจัยและการเริ่มต้น
นี่คือโครงการเปิดและผู้ทำงานร่วมกันอื่น ๆ ได้รับการต้อนรับอย่างมากในการแก้ไขและปรับปรุงเอกสาร
คุณจะพบสามส่วนหลักของเอกสารนี้ ก่อนอื่นการสรุปแนวปฏิบัติที่ดีที่สุดใน Python อย่างรวดเร็วตามด้วยเคล็ดลับและคำแนะนำบางอย่างโดยใช้ Pytorch ในที่สุดเราแบ่งปันข้อมูลเชิงลึกและประสบการณ์โดยใช้กรอบอื่น ๆ ซึ่งช่วยให้เราปรับปรุงเวิร์กโฟลว์ของเราโดยทั่วไป
อัปเดต 20.12.2020
อัปเดต 30.4.2019
หลังจากการตอบรับเชิงบวกมากฉันยังได้เพิ่มบทสรุปของการสร้างบล็อกที่ใช้กันทั่วไปจากโครงการของเราที่เบา ๆ : คุณจะพบกับการสร้างบล็อกสำหรับ (การดูแลตนเอง, การสูญเสียการรับรู้โดยใช้ VGG, การทำให้เป็นมาตรฐานสเปกตรัม, การปรับอินสแตนซ์แบบปรับตัว, ... )
รหัสตัวอย่างสำหรับการสูญเสียเลเยอร์และหน่วยการสร้างอื่น ๆ
จากประสบการณ์ของเราเราแนะนำให้ใช้ Python 3.6+ เนื่องจากคุณสมบัติดังต่อไปนี้ซึ่งมีประโยชน์มากสำหรับรหัสที่สะอาดและเรียบง่าย:
เราพยายามติดตาม Google Styleguide สำหรับ Python โปรดดูคู่มือสไตล์ที่มีเอกสารที่ดีเกี่ยวกับรหัส Python ที่จัดทำโดย Google
เราให้ข้อมูลสรุปของกฎที่ใช้กันมากที่สุดที่นี่:
จาก 3.16.4
| พิมพ์ | การประชุม | ตัวอย่าง |
|---|---|---|
| แพ็คเกจและโมดูล | lower_with_under | จาก prefetch_generator import backgroundGenerator |
| ชั้นเรียน | คำสั่งซื้อ | คลาส dataloader |
| ค่าคงที่ | caps_with_under | batch_size = 16 |
| อินสแตนซ์ | lower_with_under | ชุดข้อมูล = ชุดข้อมูล |
| วิธีการและฟังก์ชั่น | lower_with_under () | def visualize_tensor () |
| ตัวแปร | lower_with_under | background_color = 'blue' |
โดยทั่วไปเราขอแนะนำให้ใช้ IDE เช่น Visual Studio Code หรือ Pycharm ในขณะที่รหัส VS ให้การเน้นไวยากรณ์และการเติมข้อความอัตโนมัติในโปรแกรมแก้ไขที่ค่อนข้างเบา Pycharm มีคุณสมบัติขั้นสูงมากมายสำหรับการทำงานกับกลุ่มระยะไกล รหัส VS มีประสิทธิภาพมากด้วยระบบนิเวศที่เติบโตอย่างรวดเร็วของส่วนขยาย
ตรวจสอบให้แน่ใจว่าคุณติดตั้งส่วนขยายต่อไปนี้:
หากตั้งค่าอย่างถูกต้องสิ่งนี้จะช่วยให้คุณทำสิ่งต่อไปนี้:
โดยทั่วไปเราขอแนะนำให้ใช้สมุดบันทึก Jupyter สำหรับการสำรวจ/ เล่นครั้งแรกด้วยรุ่นใหม่และรหัส ควรใช้สคริปต์ Python ทันทีที่คุณต้องการฝึกอบรมโมเดลในชุดข้อมูลที่ใหญ่กว่าซึ่งการทำซ้ำนั้นมีความสำคัญมากกว่า
เวิร์กโฟลว์ที่เราแนะนำ:
| สมุดบันทึก Jupyter | สคริปต์ Python |
|---|---|
| + การสำรวจ | + ทำงานอีกต่อไปโดยไม่หยุดชะงัก |
| + การดีบัก | + ง่ายต่อการติดตามการเปลี่ยนแปลงด้วย Git |
| - สามารถกลายเป็นไฟล์ขนาดใหญ่ได้ | - การดีบักส่วนใหญ่หมายถึงการเรียกใช้สคริปต์ทั้งหมด |
| - สามารถถูกขัดจังหวะ (อย่าใช้สำหรับการฝึกอบรมที่ยาวนาน) | |
| - มีแนวโน้มที่จะเกิดข้อผิดพลาดและกลายเป็นระเบียบ |
ห้องสมุดที่ใช้กันทั่วไป:
| ชื่อ | คำอธิบาย | ใช้สำหรับ |
|---|---|---|
| คบเพลิง | กรอบพื้นฐานสำหรับการทำงานกับเครือข่ายประสาท | การสร้างเทนเซอร์เครือข่ายและการฝึกอบรมโดยใช้ backprop |
| คบเพลิง | โมดูลวิสัยทัศน์คอมพิวเตอร์ Pytorch | การประมวลผลข้อมูลล่วงหน้าการเพิ่มการประมวลผลหลังการประมวลผล |
| หมอน (PIL) | Library Imaging Python | กำลังโหลดภาพและจัดเก็บไว้ |
| นม | แพ็คเกจสำหรับการคำนวณทางวิทยาศาสตร์ด้วย Python | การประมวลผลข้อมูลและการประมวลผลล่วงหน้า |
| prefetch_generator | ห้องสมุดสำหรับการประมวลผลพื้นหลัง | กำลังโหลดชุดถัดไปในพื้นหลังระหว่างการคำนวณ |
| TQDM | แถบความคืบหน้า | ความคืบหน้าในระหว่างการฝึกอบรมแต่ละยุค |
| Torchinfo | พิมพ์สรุปแบบจำลอง Keras เหมือน Pytorch | แสดงเครือข่ายพารามิเตอร์และขนาดในแต่ละเลเยอร์ |
| Torch.utils.tensorboard | Tensorboard ภายใน pytorch | การบันทึกการทดลองและแสดงใน tensorboard |
อย่าใส่เลเยอร์และรุ่นทั้งหมดลงในไฟล์เดียวกัน แนวทางปฏิบัติที่ดีที่สุดคือการแยกเครือข่ายสุดท้ายออกเป็นไฟล์แยกต่างหาก ( networks.py ) และเก็บเลเยอร์การสูญเสียและ OPS ในไฟล์ที่เกี่ยวข้อง ( layers.py , losses.py , ops.py ) โมเดลสำเร็จรูป (ประกอบด้วยหนึ่งหรือหลายเครือข่าย) ควรอ้างอิงในไฟล์ที่มีชื่อ (เช่น yolov3.py , dcgan.py )
กิจวัตรหลักตามลำดับรถไฟและสคริปต์ทดสอบควรนำเข้าจากไฟล์ที่มีชื่อของรุ่นเท่านั้น
เราขอแนะนำให้แบ่งเครือข่ายออกเป็นชิ้นส่วนเล็ก ๆ ที่นำกลับมาใช้ใหม่ได้ เครือข่ายเป็น nn.module ที่ประกอบด้วยการดำเนินการหรือ nn.module s อื่น ๆ เป็นหน่วยการสร้าง ฟังก์ชั่นการสูญเสียยังเป็น nn.module และสามารถรวมเข้ากับเครือข่ายโดยตรง
คลาสที่สืบทอดมาจาก nn.module จะต้องมีวิธี การส่งต่อ ที่ใช้การส่งต่อของเลเยอร์หรือการดำเนินการที่เกี่ยวข้อง
สามารถใช้ nn.module กับข้อมูลอินพุตโดยใช้ self.net (อินพุต) วิธีนี้ใช้วิธี การโทร () ของวัตถุเพื่อป้อนอินพุตผ่านโมดูล
output = self . net ( input )ใช้รูปแบบต่อไปนี้สำหรับเครือข่ายอย่างง่ายด้วยอินพุตเดียวและเอาต์พุตเดี่ยว:
class ConvBlock ( nn . Module ):
def __init__ ( self ):
super ( ConvBlock , self ). __init__ ()
self . block = nn . Sequential (
nn . Conv2d (...),
nn . ReLU (),
nn . BatchNorm2d (...)
)
def forward ( self , x ):
return self . block ( x )
class SimpleNetwork ( nn . Module ):
def __init__ ( self , num_resnet_blocks = 6 ):
super ( SimpleNetwork , self ). __init__ ()
# here we add the individual layers
layers = [ ConvBlock (...)]
for i in range ( num_resnet_blocks ):
layers += [ ResBlock (...)]
self . net = nn . Sequential ( * layers )
def forward ( self , x ):
return self . net ( x )สังเกตสิ่งต่อไปนี้:
class ResnetBlock ( nn . Module ):
def __init__ ( self , dim , padding_type , norm_layer , use_dropout , use_bias ):
super ( ResnetBlock , self ). __init__ ()
self . conv_block = self . build_conv_block (...)
def build_conv_block ( self , ...):
conv_block = []
conv_block += [ nn . Conv2d (...),
norm_layer (...),
nn . ReLU ()]
if use_dropout :
conv_block += [ nn . Dropout (...)]
conv_block += [ nn . Conv2d (...),
norm_layer (...)]
return nn . Sequential ( * conv_block )
def forward ( self , x ):
out = x + self . conv_block ( x )
return outที่นี่การเชื่อมต่อข้ามของ บล็อก resnet ได้ถูกนำไปใช้โดยตรงในบัตรผ่านไปข้างหน้า Pytorch อนุญาตให้มีการดำเนินการแบบไดนามิกในระหว่างการส่งต่อ
สำหรับเครือข่ายที่ต้องการเอาต์พุตหลายรายการเช่นการสร้างการสูญเสียการรับรู้โดยใช้เครือข่าย VGG ที่ได้รับการฝึกฝนเราใช้รูปแบบต่อไปนี้:
class Vgg19 ( nn . Module ):
def __init__ ( self , requires_grad = False ):
super ( Vgg19 , self ). __init__ ()
vgg_pretrained_features = models . vgg19 ( pretrained = True ). features
self . slice1 = torch . nn . Sequential ()
self . slice2 = torch . nn . Sequential ()
self . slice3 = torch . nn . Sequential ()
for x in range ( 7 ):
self . slice1 . add_module ( str ( x ), vgg_pretrained_features [ x ])
for x in range ( 7 , 21 ):
self . slice2 . add_module ( str ( x ), vgg_pretrained_features [ x ])
for x in range ( 21 , 30 ):
self . slice3 . add_module ( str ( x ), vgg_pretrained_features [ x ])
if not requires_grad :
for param in self . parameters ():
param . requires_grad = False
def forward ( self , x ):
h_relu1 = self . slice1 ( x )
h_relu2 = self . slice2 ( h_relu1 )
h_relu3 = self . slice3 ( h_relu2 )
out = [ h_relu1 , h_relu2 , h_relu3 ]
return outหมายเหตุที่นี่สิ่งต่อไปนี้:
แม้ว่า Pytorch จะมีฟังก์ชั่นการสูญเสียมาตรฐานจำนวนมาก แต่บางครั้งอาจจำเป็นต้องสร้างฟังก์ชั่นการสูญเสียของคุณเอง สำหรับสิ่งนี้ให้สร้าง losses.py ไฟล์แยกต่างหาก py และขยายคลาส nn.Module เพื่อสร้างฟังก์ชั่นการสูญเสียที่กำหนดเองของคุณ:
class CustomLoss ( nn . Module ):
def __init__ ( self ):
super ( CustomLoss , self ). __init__ ()
def forward ( self , x , y ):
loss = torch . mean (( x - y ) ** 2 )
return loss ตัวอย่างเต็มรูปแบบมีให้ในโฟลเดอร์ CIFAR10-Example ของที่เก็บนี้
โปรดทราบว่าเราใช้รูปแบบต่อไปนี้:
# import statements
import torch
import torch . nn as nn
from torch . utils import data
...
# set flags / seeds
torch . backends . cudnn . benchmark = True
np . random . seed ( 1 )
torch . manual_seed ( 1 )
torch . cuda . manual_seed ( 1 )
...
# Start with main code
if __name__ == '__main__' :
# argparse for additional flags for experiment
parser = argparse . ArgumentParser ( description = "Train a network for ..." )
...
opt = parser . parse_args ()
# add code for datasets (we always use train and validation/ test set)
data_transforms = transforms . Compose ([
transforms . Resize (( opt . img_size , opt . img_size )),
transforms . RandomHorizontalFlip (),
transforms . ToTensor (),
transforms . Normalize (( 0.5 , 0.5 , 0.5 ), ( 0.5 , 0.5 , 0.5 ))
])
train_dataset = datasets . ImageFolder (
root = os . path . join ( opt . path_to_data , "train" ),
transform = data_transforms )
train_data_loader = data . DataLoader ( train_dataset , ...)
test_dataset = datasets . ImageFolder (
root = os . path . join ( opt . path_to_data , "test" ),
transform = data_transforms )
test_data_loader = data . DataLoader ( test_dataset ...)
...
# instantiate network (which has been imported from *networks.py*)
net = MyNetwork (...)
...
# create losses (criterion in pytorch)
criterion_L1 = torch . nn . L1Loss ()
...
# if running on GPU and we want to use cuda move model there
use_cuda = torch . cuda . is_available ()
if use_cuda :
net = net . cuda ()
...
# create optimizers
optim = torch . optim . Adam ( net . parameters (), lr = opt . lr )
...
# load checkpoint if needed/ wanted
start_n_iter = 0
start_epoch = 0
if opt . resume :
ckpt = load_checkpoint ( opt . path_to_checkpoint ) # custom method for loading last checkpoint
net . load_state_dict ( ckpt [ 'net' ])
start_epoch = ckpt [ 'epoch' ]
start_n_iter = ckpt [ 'n_iter' ]
optim . load_state_dict ( ckpt [ 'optim' ])
print ( "last checkpoint restored" )
...
# if we want to run experiment on multiple GPUs we move the models there
net = torch . nn . DataParallel ( net )
...
# typically we use tensorboardX to keep track of experiments
writer = SummaryWriter (...)
# now we start the main loop
n_iter = start_n_iter
for epoch in range ( start_epoch , opt . epochs ):
# set models to train mode
net . train ()
...
# use prefetch_generator and tqdm for iterating through data
pbar = tqdm ( enumerate ( BackgroundGenerator ( train_data_loader , ...)),
total = len ( train_data_loader ))
start_time = time . time ()
# for loop going through dataset
for i , data in pbar :
# data preparation
img , label = data
if use_cuda :
img = img . cuda ()
label = label . cuda ()
...
# It's very good practice to keep track of preparation time and computation time using tqdm to find any issues in your dataloader
prepare_time = start_time - time . time ()
# forward and backward pass
optim . zero_grad ()
...
loss . backward ()
optim . step ()
...
# udpate tensorboardX
writer . add_scalar (..., n_iter )
...
# compute computation time and *compute_efficiency*
process_time = start_time - time . time () - prepare_time
pbar . set_description ( "Compute efficiency: {:.2f}, epoch: {}/{}:" . format (
process_time / ( process_time + prepare_time ), epoch , opt . epochs ))
start_time = time . time ()
# maybe do a test pass every x epochs
if epoch % x == x - 1 :
# bring models to evaluation mode
net . eval ()
...
#do some tests
pbar = tqdm ( enumerate ( BackgroundGenerator ( test_data_loader , ...)),
total = len ( test_data_loader ))
for i , data in pbar :
...
# save checkpoint if needed
...Pytorch มีสองรูปแบบที่แตกต่างกันเพื่อใช้ GPU หลายตัวสำหรับการฝึกอบรม จากประสบการณ์ของเราทั้งสองรูปแบบนั้นถูกต้อง ผลลัพธ์แรกที่ดีกว่าในรหัสที่ดีกว่าและน้อยกว่า คนที่สองดูเหมือนจะมีความได้เปรียบด้านประสิทธิภาพเล็กน้อยเนื่องจากการสื่อสารน้อยลงระหว่าง GPU ฉันถามคำถามในฟอรัม Pytorch อย่างเป็นทางการเกี่ยวกับวิธีการทั้งสองที่นี่
สิ่งที่พบบ่อยที่สุดคือการแยกแบทช์ของ เครือข่าย ทั้งหมดเป็น GPU แต่ละตัว
รุ่นที่ทำงานบน 1 GPU ที่มีขนาดแบทช์ 64 จะทำงานบน 2 GPUs โดยแต่ละขนาดแบทช์ 32 สามารถทำได้โดยอัตโนมัติโดยการห่อโมเดลโดย Nn.Dataparallel (รุ่น)
รูปแบบนี้มักใช้กันทั่วไป ที่เก็บที่ใช้วิธีนี้จะแสดงที่นี่ในการใช้งาน pix2pixhd โดย nvidia
Numpy ทำงานบน CPU และช้ากว่ารหัสไฟฉาย เนื่องจากคบเพลิงได้รับการพัฒนาโดยมีความคล้ายคลึงกับ numpy ในใจฟังก์ชั่น numpy ส่วนใหญ่ได้รับการสนับสนุนโดย pytorch แล้ว
การโหลดข้อมูลไปป์ไลน์ควรเป็นอิสระจากรหัสการฝึกอบรมหลักของคุณ Pytorch ใช้ผู้ปฏิบัติงานพื้นหลังในการโหลดข้อมูลได้อย่างมีประสิทธิภาพมากขึ้นและไม่รบกวนกระบวนการฝึกอบรมหลัก
โดยทั่วไปเราฝึกอบรมแบบจำลองของเราเป็นพัน ๆ ขั้นตอน ดังนั้นจึงเพียงพอที่จะบันทึกการสูญเสียและผลลัพธ์อื่น ๆ ทุกขั้นตอนในการลดค่าใช้จ่าย โดยเฉพาะอย่างยิ่งการประหยัดผลลัพธ์ตัวกลางเนื่องจากภาพอาจมีค่าใช้จ่ายสูงในระหว่างการฝึกอบรม
มีประโยชน์มากที่จะใช้อาร์กิวเมนต์บรรทัดคำสั่งเพื่อตั้งค่าพารามิเตอร์ในระหว่างการดำเนินการรหัส ( ขนาดแบทช์ อัตราการเรียนรู้ ฯลฯ ) วิธีง่ายๆในการติดตามข้อโต้แย้งสำหรับการทดลองคือเพียงแค่พิมพ์พจนานุกรมที่ได้รับจาก parse_args :
...
# saves arguments to config.txt file
opt = parser . parse_args ()
with open ( "config.txt" , "w" ) as f :
f . write ( opt . __str__ ())
...Pytorch ติดตามการดำเนินการทั้งหมดที่เกี่ยวข้องกับเทนเซอร์เพื่อความแตกต่างโดยอัตโนมัติ ใช้ . detach () เพื่อป้องกันการบันทึกการดำเนินงานที่ไม่จำเป็น
คุณสามารถพิมพ์ตัวแปรโดยตรงอย่างไรก็ตามขอแนะนำให้ใช้ ตัวแปร Detach () หรือ variable.item () ในรุ่น pytorch ก่อนหน้า <0.4 คุณต้องใช้ . data เพื่อเข้าถึงเทนเซอร์ของตัวแปร
สองวิธีไม่เหมือนกันตามที่ชี้ให้เห็นในประเด็นหนึ่งที่นี่:
output = self . net . forward ( input )
# they are not equal!
output = self . net ( input )เราขอแนะนำให้ตั้งค่าเมล็ดพันธุ์ต่อไปนี้ที่จุดเริ่มต้นของรหัสของคุณ:
np . random . seed ( 1 )
torch . manual_seed ( 1 )
torch . cuda . manual_seed ( 1 )บน Nvidia GPUs คุณสามารถเพิ่มบรรทัดต่อไปนี้ได้ที่จุดเริ่มต้นของรหัสของเรา สิ่งนี้จะช่วยให้แบ็กเอนด์ CUDA เพิ่มประสิทธิภาพกราฟของคุณในระหว่างการดำเนินการครั้งแรก อย่างไรก็ตามโปรดทราบว่าหากคุณเปลี่ยนขนาดเทนเซอร์อินพุต/เอาต์พุตของเครือข่ายกราฟจะได้รับการปรับให้เหมาะสมทุกครั้งที่มีการเปลี่ยนแปลง สิ่งนี้สามารถนำไปสู่การรันไทม์ที่ช้ามากและออกจากข้อผิดพลาดของหน่วยความจำ ตั้งค่าสถานะนี้เฉพาะในกรณีที่อินพุตและเอาต์พุตของคุณมีรูปร่างเหมือนกันเสมอ โดยปกติแล้วจะส่งผลให้มีการปรับปรุงประมาณ 20%
torch . backends . cudnn . benchmark = Trueขึ้นอยู่กับเครื่องที่ใช้ไปป์ไลน์การประมวลผลล่วงหน้าและขนาดเครือข่าย การทำงานบน SSD บน 1080Ti GPU เราเห็นประสิทธิภาพการคำนวณเกือบ 1.0 ซึ่งเป็นสถานการณ์ที่เหมาะ หากเครือข่ายตื้น (เล็ก) หรือฮาร์ดดิสก์ช้าจะใช้จำนวนอาจลดลงไปที่ประมาณ 0.1-0.2 ขึ้นอยู่กับการตั้งค่าของคุณ
ใน Pytorch เราสามารถใช้ขนาดแบทช์เสมือนจริงได้อย่างง่ายดาย เราเพียงแค่ป้องกันไม่ให้เครื่องมือเพิ่มประสิทธิภาพในการอัปเดตพารามิเตอร์และรวมการไล่ระดับสีสำหรับรอบ batch_size
...
# in the main loop
out = net ( input )
loss = criterion ( out , label )
# we just call backward to sum up gradients but don't perform step here
loss . backward ()
total_loss += loss . item () / batch_size
if n_iter % batch_size == batch_size - 1 :
# here we perform out optimization step using a virtual batch size
optim . step ()
optim . zero_grad ()
print ( 'Total loss: ' , total_loss )
total_loss = 0.0
...เราสามารถเข้าถึงอัตราการเรียนรู้โดยตรงโดยใช้เครื่องมือเพิ่มประสิทธิภาพแบบอินสแตนซ์ดังที่แสดงที่นี่:
...
for param_group in optim . param_groups :
old_lr = param_group [ 'lr' ]
new_lr = old_lr * 0.1
param_group [ 'lr' ] = new_lr
print ( 'Updated lr from {} to {}' . format ( old_lr , new_lr ))
...หากคุณต้องการใช้โมเดลที่ผ่านการฝึกอบรมเช่น VGG เพื่อคำนวณการสูญเสีย แต่ไม่ได้ฝึกอบรม (เช่นการสูญเสียการรับรู้ในรูปแบบการถ่ายโอน/ gans/ encoder อัตโนมัติ) คุณสามารถใช้รูปแบบต่อไปนี้:
...
# instantiate the model
pretrained_VGG = VGG19 (...)
# disable gradients (prevent training)
for p in pretrained_VGG . parameters (): # reset requires_grad
p . requires_grad = False
...
# you don't have to use the no_grad() namespace but can just run the model
# no gradients will be computed for the VGG model
out_real = pretrained_VGG ( input_a )
out_fake = pretrained_VGG ( input_b )
loss = any_criterion ( out_real , out_fake )
...วิธีการเหล่านั้นใช้ในการตั้งค่าเลเยอร์เช่น BatchNorm2D หรือ DropOut2D จากการฝึกอบรมไปยังโหมดการอนุมาน ทุกโมดูลที่สืบทอดมาจาก nn.module มีแอตทริบิวต์ที่เรียกว่า istraining .Eval () และ .train () เพียงแค่ตั้งค่าแอตทริบิวต์นี้เป็นจริง/ เท็จ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการใช้วิธีนี้โปรดดูที่รหัสโมดูลใน pytorch
ตรวจสอบให้แน่ใจว่าไม่มีการไล่ระดับสีและเก็บไว้ในระหว่างการดำเนินการรหัสของคุณ คุณสามารถใช้รูปแบบต่อไปนี้เพื่อรับรองว่า:
with torch . no_grad ():
# run model here
out_tensor = net ( in_tensor )ใน Pytorch คุณสามารถแช่แข็งเลเยอร์ สิ่งนี้จะป้องกันไม่ให้พวกเขาได้รับการปรับปรุงในระหว่างขั้นตอนการเพิ่มประสิทธิภาพ
# you can freeze whole modules using
for p in pretrained_VGG . parameters (): # reset requires_grad
p . requires_grad = Falseตั้งแต่ Pytorch 0.4 * ตัวแปร และ เทนเซอร์ ได้ถูกรวมเข้าด้วยกัน เราไม่จำเป็นต้องสร้างวัตถุ ตัวแปร อย่างชัดเจนอีกต่อไป
เวอร์ชัน C ++ นั้นเร็วขึ้นประมาณ 10%
สิ่งที่ต้องทำ ...
จากประสบการณ์ของเราคุณสามารถเพิ่มความเร็วได้ประมาณ 20% แต่ครั้งแรกที่คุณเรียกใช้โมเดลของคุณใช้เวลาพอสมควรในการสร้างกราฟที่ดีที่สุด ในบางกรณี (ลูปในการส่งผ่านไปข้างหน้าไม่มีรูปร่างอินพุตคงที่ถ้า/อื่น ๆ ในไปข้างหน้า ฯลฯ ) ธงนี้อาจส่งผลให้ เกิดจากหน่วยความจำ หรือข้อผิดพลาดอื่น ๆ
สิ่งที่ต้องทำ ...
หากปลดปล่อยเทนเซอร์จากกราฟการคำนวณ ภาพประกอบที่ดีแสดงที่นี่
โปรดให้ข้อเสนอแนะเกี่ยวกับวิธีที่เราสามารถปรับปรุงคู่มือสไตล์นี้ได้! คุณสามารถเปิดปัญหาหรือเสนอการเปลี่ยนแปลงโดยการสร้างคำขอดึง
ถ้าคุณชอบ repo นี้อย่าลืมตรวจสอบกรอบอื่น ๆ จากเรา: