12.1. Derleyiciler ve Yorumlayıcılar¶ Open the notebook in SageMaker Studio Lab
Şimdiye kadar, bu kitap bir programın durumunu değiştirmek için
print
, +
ve if
gibi ifadeleri kullanan buyuru programlamaya
odaklanmıştır. Basit bir buyuru programın aşağıdaki örneğini göz önünde
bulundurun.
def add(a, b):
return a + b
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
10
def add(a, b):
return a + b
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
10
def add(a, b):
return a + b
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
10
Python bir yorumlanan dildir. Yukarıdaki fancy_func
işlevini
değerlendirirken fonksiyonun gövdesini oluşturan işlemleri sıra ile
gerçekleştirir. Yani, e = add(a, b)
’yi değerlendirecek ve sonuçları
e
değişkeni olarak saklayacak ve böylece programın durumunu
değiştirecektir. Sonraki iki ifade f = add(c, d)
ve
g = add(e, f)
benzer şekilde yürütülecek, toplamalar
gerçekleştirilecek ve sonuçları değişken olarak depolayacaktır.
Fig. 12.1.1, veri akışını göstermektedir.
Fig. 12.1.1 Bir buyuru programda veri akışı.¶
Buyuru programlama her ne kadar uygun olsa da, verimsiz olabilir. Bir
yandan, add
işlevi fancy_func
boyunca tekrar tekrar çağrılsa
bile, Python üç işlevin çağrılarını tek tek yürütür. Bunlar, örneğin,
bir GPU’da (veya birden fazla GPU’da) yürütülürse, Python
yorumlayıcısından kaynaklanan yükü bezdirici hale gelebilir. Ayrıca,
fancy_func
içindeki tüm ifadeler yürütülünceye kadar e
ve f
değişken değerlerini kaydetmesi gerekecektir. Bunun nedeni,
e = add(a, b)
ve f = add(c, d)
ifadeleri yürütüldükten sonra
e
ve f
değişkenlerinin programın diğer bölümleri tarafından
kullanılacağını bilmememizdir.
12.1.1. Sembolik Programlama¶
Hesaplamanın genellikle süreç tam olarak tanımlandıktan sonra gerçekleştirildiği alternatifi, sembolik programlamayı, göz önünde bulundurun. Bu strateji, Theano ve TensorFlow da dahil olmak üzere birden fazla derin öğrenme çerçevesi tarafından kullanılır (ikincisi buyuru uzantıları edindi). Genellikle aşağıdaki adımları içerir:
Yürütülecek işlemleri tanımlayın.
İşlemleri yürütülebilir bir programa derleyin.
Gerekli girdileri sağlayın ve yürütme için derlenmiş programı çağırın.
Bu, önemli miktarda optimizasyona izin verir. İlk olarak, birçok durumda
Python yorumlayıcısını atlayabiliriz, böylece bir CPU üzerinde tek bir
Python iş parçacığı ile eşleştirilmiş birden çok hızlı GPU’larda önemli
hale gelebilecek bir performans darboğazını kaldırabiliriz. İkincisi,
bir derleyici optimize edebilir ve yukarıdaki kodu
print((1 + 2) + (3 + 4))
veya hatta print(10)
içine yeniden
yazabilir. Bu, bir derleyici makine talimatlarına dönüştürmeden önce tam
kodu görebildiği için mümkündür. Örneğin, artık bir değişken
gerekmediğinde belleği serbest bırakabilir (veya asla tahsis etmez). Ya
da kodu tamamen eşdeğer bir parçaya dönüştürebilir. Daha iyi bir fikir
edinmek için aşağıdaki buyuru programlama benzetimini (sonuçta hepsi
Python) düşünün.
def add_():
return '''
def add(a, b):
return a + b
'''
def fancy_func_():
return '''
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
'''
def evoke_():
return add_() + fancy_func_() + 'print(fancy_func(1, 2, 3, 4))'
prog = evoke_()
print(prog)
y = compile(prog, '', 'exec')
exec(y)
def add(a, b):
return a + b
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
10
def add_():
return '''
def add(a, b):
return a + b
'''
def fancy_func_():
return '''
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
'''
def evoke_():
return add_() + fancy_func_() + 'print(fancy_func(1, 2, 3, 4))'
prog = evoke_()
print(prog)
y = compile(prog, '', 'exec')
exec(y)
def add(a, b):
return a + b
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
10
def add_():
return '''
def add(a, b):
return a + b
'''
def fancy_func_():
return '''
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
'''
def evoke_():
return add_() + fancy_func_() + 'print(fancy_func(1, 2, 3, 4))'
prog = evoke_()
print(prog)
y = compile(prog, '', 'exec')
exec(y)
def add(a, b):
return a + b
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
10
Buyuru (yorumlanan) programlama ve sembolik programlama arasındaki farklar şunlardır:
Buyuru programlama daha kolaydır. Python’da buyuru programlama kullanıldığında, kodun çoğunluğu basittir ve yazması kolaydır. Ayrıca buyuru programlama kodunda hata ayıklamak daha kolaydır. Bunun nedeni, ilgili tüm ara değişken değerlerini elde etmenin ve yazdırmanın veya Python’un yerleşik hata ayıklama araçlarını kullanmanın daha kolay olmasıdır.
Sembolik programlama daha verimli ve aktarması daha kolaydır. Sembolik programlama, derleme sırasında kodu optimize etmeyi kolaylaştırırken, programı Python’dan bağımsız bir formata aktarma yeteneğine de sahiptir. Bu, programın Python olmayan bir ortamda çalıştırılmasını sağlar, böylece Python yorumlayıcısı ile ilgili olası performans sorunlarından kaçınır.
12.1.2. Melez Programlama¶
Tarihsel olarak çoğu derin öğrenme çerçevesi buyuru veya sembolik yaklaşım arasında seçim yapar. Örneğin, Theano, TensorFlow (ilkinden esinlenerek), Keras ve CNTK modelleri sembolik olarak formüle eder. Tersine, Chainer ve PyTorch buyuru yaklaşımını benimsemektedir. TensorFlow 2.0 ve Keras’a sonraki düzeltmelerde buyuru modu eklendi.
Gluon’ı tasarlarken, geliştiriciler her iki programlama kiplerinin faydalarını birleştirmenin mümkün olup olmayacağını düşündü. Bu, kullanıcıların çoğunu ürün düzeyinde bilgi işlem performansı ve dağıtım gerektiğinde çalıştırılacak sembolik programlara dönüştürme yeteneğine sahipken, kullanıcıların saf buyuru programlama ile geliştirmelerine ve hata ayıklamasına olanak tanıyan bir karma modele yol açtı.
Pratikte bu, HybridBlock
veya HybridSequential
sınıfını
kullanarak modeller oluşturduğumuz anlamına gelir. Varsayılan olarak,
ikisinden herhangi biri, Block
veya Sequential
sınıfının buyuru
programlamada yürütüldüğü şekilde yürütülür. HybridSequential
sınıfı
HybridBlock
(Sequential
alt sınıfları Block
gibi) bir alt
sınıftır. hybridize
işlevi çağrıldığında, Gluon modeli sembolik
programlamada kullanılan biçime derler. Bu, bir modelin uygulanma
biçiminden ödün vermeden hesaplama yoğun bileşenlerin optimize
edilmesini sağlar. Dizili modellere ve bloklara odaklanarak aşağıdaki
faydaları göstereceğiz.
Yukarıda belirtildiği gibi, PyTorch buyuru programlamaya dayanır ve dinamik hesaplama çizgeleri kullanır. Geliştiriciler, sembolik programlamanın taşınabilirliğini ve verimliliğini artırmak amacıyla, her iki programlama modelinin faydalarını birleştirmenin mümkün olup olmayacağını düşündü. Bu, kullanıcıların çoğu programı ürün düzeyinde bilgi işlem performansı ve konuşlandırma gerektiğinde çalıştırılmak üzere sembolik programlara dönüştürme yeteneğine sahipken, yalnızca buyuru programlama kullanarak geliştirmelerine ve hata ayıklamalarına olanak tanıyan bir meşale betiğine yol açtı.
Buyuru programlama kipi artık Tensorflow 2’de varsayılan değerdir, bu
dile yeni olanlar için hoş bir değişiklik. Ancak aynı sembolik
programlama teknikleri ve sonraki hesaplama çizgeleri TensorFlow’da hala
mevcuttur ve kullanımı kolay tf.function
dekoratörü tarafından
erişilebilir. Bu, buyuru programlama kipini TensorFlow’a getirdi,
kullanıcıların daha sezgisel fonksiyonlar tanımlamalarına, ardından
bunları sarmalamalarına ve TensorFlow ekibinin
autograph
olarak ifade ettiği bir özelliği kullanarak otomatik olarak hesaplamalı
çizgelere derlemelerine olanak sağladı.
12.1.3. Sequential
Sınıfını Melezleme¶
Melezleştirmenin nasıl çalıştığını hissetmenin en kolay yolu, birden çok
katmanlı derin ağları düşünmektir. Geleneksel olarak Python
yorumlayıcısı, daha sonra bir CPU’ya veya GPU’ya iletilebilecek bir
komut oluştururken tüm katmanlar için kodu yürütmesi gerekir. Tek
(hızlı) bir bilgi işlem aygıtı için bu herhangi bir önemli soruna neden
olmaz. Öte yandan, AWS P3dn.24xlarge örneği gibi gelişmiş bir 8 GPU’lu
sunucusu kullanırsak Python tüm GPU’ları meşgul tutmaya çalışacaktır.
Tek iş parçacıklı Python yorumlayıcısı burada darboğaz olur.
Sequential
’i HybridSequential
ile değiştirerek kodun önemli
bölümleri için bunu nasıl ele alabileceğimizi görelim. Basit bir MLP
tanımlayarak başlıyoruz.
from d2l import mxnet as d2l
from mxnet import np, npx
from mxnet.gluon import nn
npx.set_np()
# Ag fabrikasi
def get_net():
net = nn.HybridSequential()
net.add(nn.Dense(256, activation='relu'),
nn.Dense(128, activation='relu'),
nn.Dense(2))
net.initialize()
return net
x = np.random.normal(size=(1, 512))
net = get_net()
net(x)
array([[ 0.16526186, -0.14005628]])
hybridize
işlevini çağırarak, MLP’deki hesaplamayı derleyebiliyoruz
ve optimize edebiliyoruz. Modelin hesaplama sonucu değişmeden kalır.
net.hybridize()
net(x)
array([[ 0.16526186, -0.14005628]])
Bu gerçek olamayacak kadar iyi görünüyor: HybridSequential
olarak
bir blok belirleyin, daha önce olduğu gibi aynı kodu yazın ve
hybridize
’yı çağırın. Bu gerçekleştiğinde ağ optimize edilir
(aşağıda performansı karşılaştıracağız). Ne yazık ki bu her katman için
sihirli bir şekilde çalışmıyor. Yani, HybridBlock
sınıfı yerine
Block
sınıfından kalıtım ile çoğalırsa, katman optimize
edilmeyecektir.
import torch
from torch import nn
from d2l import torch as d2l
# Ag fabrikasi
def get_net():
net = nn.Sequential(nn.Linear(512, 256),
nn.ReLU(),
nn.Linear(256, 128),
nn.ReLU(),
nn.Linear(128, 2))
return net
x = torch.randn(size=(1, 512))
net = get_net()
net(x)
tensor([[0.1160, 0.0584]], grad_fn=<AddmmBackward0>)
Modeli torch.jit.script
işlevini kullanarak dönüştürerek, MLP’deki
hesaplamayı derleyebiliyoruz ve optimize edebiliyoruz. Modelin hesaplama
sonucu değişmeden kalır.
net = torch.jit.script(net)
net(x)
tensor([[0.1160, 0.0584]], grad_fn=<AddmmBackward0>)
Bu gerçek olamayacak kadar iyi görünüyor: Daha önce olduğu gibi aynı
kodu yazın ve modeli torch.jit.script
’ü kullanarak dönüştürün. Bu
gerçekleştiğinde ağ optimize edilir (aşağıda performansı
karşılaştıracağız).
import tensorflow as tf
from d2l import tensorflow as d2l
from tensorflow.keras.layers import Dense
# Ag fabrikasi
def get_net():
net = tf.keras.Sequential()
net.add(Dense(256, input_shape = (512,), activation = "relu"))
net.add(Dense(128, activation = "relu"))
net.add(Dense(2, activation = "linear"))
return net
x = tf.random.normal([1,512])
net = get_net()
net(x)
<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[-0.26192454, -1.165848 ]], dtype=float32)>
Önceden, TensorFlow’da yerleşik olan tüm işlevler bir hesaplama çizgesi olarak oluşturulurdu ve bu nedenle JIT varsayılan olarak derlenmiştir. Bununla birlikte, TensorFlow 2.X ve EagerTensor’un piyasaya sürülmesiyle, bu artık varsayılan davranış değildir. Bu işlevselliği tf.function ile yeniden etkinleştiririz. tf.function daha yaygın bir işlev dekoratörü olarak kullanılır, ancak bunu aşağıda gösterilen normal bir python fonksiyonu olarak doğrudan çağırmak mümkündür. Modelin hesaplama sonucu değişmeden kalır.
net = tf.function(net)
net(x)
<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[-0.26192454, -1.165848 ]], dtype=float32)>
Bu gerçek olamayacak kadar iyi görünüyor: Daha önce olduğu gibi aynı
kodu yazın ve modeli tf.function
kullanarak dönüştürün. Bu
gerçekleştiğinde ağ TensorFlow’un MLIR ara temsilinde bir hesaplama
çizgesi olarak oluşturulur ve hızlı yürütme için derleyici düzeyinde
büyük ölçüde optimize edilir (aşağıda performansı karşılaştıracağız).
tf.function()
çağrısına açıkça jit_compile = True
bayrağının
eklenmesi TensorFlow’da XLA (Hızlandırılmış Doğrusal Cebir) işlevini
etkinleştirir. XLA, JIT derlenmiş kodu belirli durumlarda daha da
optimize edebilir. Çizge modunda yürütme, bu açık tanım olmadan
etkinleştirilir, ancak XLA, özellikle GPU ortamında, belirli büyük
doğrusal cebir işlemlerini (derin öğrenme uygulamalarında gördüğümüz
mizaçta) çok daha hızlı yapabilir.
12.1.3.1. Melezleştirme ile İvme¶
Derleme yoluyla elde edilen performans iyileştirmesini göstermek için
net(x)
’i melezleştirme öncesi ve sonrası değerlendirmek için gereken
süreyi karşılaştırıyoruz. Önce bu zamanı ölçmek için bir sınıf
tanımlayalım. Performansı ölçmek (ve geliştirmek) için yola çıktığımızda
bu, bölüm boyunca kullanışlı olacaktır.
#@save
class Benchmark:
"""For measuring running time."""
def __init__(self, description='Done'):
self.description = description
def __enter__(self):
self.timer = d2l.Timer()
return self
def __exit__(self, *args):
print(f'{self.description}: {self.timer.stop():.4f} sec')
Şimdi ağı bir kez melezleştirmeli ve bir kez de melezleştirme olmadan iki kez çağırabiliriz.
net = get_net()
with Benchmark('Without hybridization'):
for i in range(1000): net(x)
npx.waitall()
net.hybridize()
with Benchmark('With hybridization'):
for i in range(1000): net(x)
npx.waitall()
Without hybridization: 0.7048 sec
With hybridization: 0.1987 sec
Yukarıdaki sonuçlarda görüldüğü gibi, HybridSequential
örneği
hybridize
işlevini çağırdıktan sonra, sembolik programlama
kullanılarak bilgi işlem performansı iyileştirilir.
#@save
class Benchmark:
"""For measuring running time."""
def __init__(self, description='Done'):
self.description = description
def __enter__(self):
self.timer = d2l.Timer()
return self
def __exit__(self, *args):
print(f'{self.description}: {self.timer.stop():.4f} sec')
Artık ağı bir kez meşale betikli ve bir kez de meşale betiği olmadan iki kez çağırabiliriz.
net = get_net()
with Benchmark('Without torchscript'):
for i in range(1000): net(x)
net = torch.jit.script(net)
with Benchmark('With torchscript'):
for i in range(1000): net(x)
Without torchscript: 1.5656 sec
With torchscript: 1.6088 sec
Yukarıdaki sonuçlarda görüldüğü gibi, nn.Sequential
örneği
torch.jit.script
işlevi kullanılarak komut dosyası oluşturulduktan
sonra, sembolik programlama kullanılarak bilgi işlem performansı
artırılır.
#@save
class Benchmark:
"""For measuring running time."""
def __init__(self, description='Done'):
self.description = description
def __enter__(self):
self.timer = d2l.Timer()
return self
def __exit__(self, *args):
print(f'{self.description}: {self.timer.stop():.4f} sec')
Şimdi ağı, bir kez sabırsız yürütülen, bir kez çizge modu yürütme ile ve tekrar JIT derlenmiş XLA kullanarak olmak üzere üç kez çağırabiliriz.
net = get_net()
with Benchmark('Eager Mode'):
for i in range(1000): net(x)
net = tf.function(net)
with Benchmark('Graph Mode'):
for i in range(1000): net(x)
Eager Mode: 1.3467 sec
Graph Mode: 0.5409 sec
Yukarıdaki sonuçlarda görüldüğü gibi, tf.keras.Sequential
örneği
tf.function
işlevi kullanılarak komut dosyası oluşturulduktan sonra,
bilgi işlem performansı tensorflow içinde çizge modu yürütme yoluyla
sembolik programlama kullanılarak geliştirilir.
12.1.3.2. Seri Hale Getirme¶
Modelleri derlemenin faydalarından biri, modeli ve parametrelerini
diskte seri hale getirebilmemizdir (kaydedebiliriz). Bu, bir modeli
seçtiğiniz önişlemci dilinden bağımsız bir şekilde saklamamızı sağlar.
Bu, eğitilmiş modelleri diğer cihazlara konuşlandırmamıza ve diğer
önişlemci programlama dillerini kolayca kullanmamıza olanak tanır. Aynı
zamanda kod genellikle buyuru programlamadan elde edilebileceğinden daha
hızlıdır. export
işlevini iş başında görelim.
net.export('my_mlp')
!ls -lh my_mlp*
-rw-rw-r-- 1 d2l-worker d2l-worker 643K Oct 17 21:45 my_mlp-0000.params
-rw-rw-r-- 1 d2l-worker d2l-worker 3.0K Oct 17 21:45 my_mlp-symbol.json
Model, bir (büyük ikili) parametre dosyasına ve model hesaplamasını yürütmek için gereken programın bir JSON betimlemesine ayrıştırılır. Dosyalar C++, R, Scala ve Perl gibi Python veya MXNet tarafından desteklenen diğer önişlemci dilleri tarafından okunabilir. Model tanımlamasındaki ilk birkaç satıra bir göz atalım.
!head my_mlp-symbol.json
{
"nodes": [
{
"op": "null",
"name": "data",
"inputs": []
},
{
"op": "null",
"name": "dense3_weight",
Daha önce, hybridize
işlevini çağırdıktan sonra modelin üstün bilgi
işlem performansı ve taşınabilirlik elde edebildiğini gösterdik. Bu
melezlemenin, özellikle kontrol akışı açısından model esnekliğini
etkileyebileceğini unutmayın.
Ayrıca, forward
işlevini kullanması gereken Block
örneğinin
aksine, HybridBlock
örneği için hybrid_forward
işlevini
kullanmamız gerekiyor.
class HybridNet(nn.HybridBlock):
def __init__(self, **kwargs):
super(HybridNet, self).__init__(**kwargs)
self.hidden = nn.Dense(4)
self.output = nn.Dense(2)
def hybrid_forward(self, F, x):
print('module F: ', F)
print('value x: ', x)
x = F.npx.relu(self.hidden(x))
print('result : ', x)
return self.output(x)
Yukarıdaki kod, 4 gizli birime ve 2 çıktıya sahip basit bir ağ uygular.
hybrid_forward
işlevi ek bir argüman F
alır. Kodun
melezleştirilmiş olup olmamasına bağlı olarak, işlemek için biraz farklı
bir kütüphane (ndarray
veya symbol
) kullanacağından bu
gereklidir. Her iki sınıf da çok benzer işlevler gerçekleştirir ve
MXNet, bağımsız değişkeni otomatik olarak belirler. Neler olup bittiğini
anlamak için argümanları işlev çağırısının bir parçası olarak
yazdırıyoruz.
net = HybridNet()
net.initialize()
x = np.random.normal(size=(1, 3))
net(x)
module F: <module 'mxnet.ndarray' from '/home/d2l-worker/miniconda3/envs/d2l-tr-release-0/lib/python3.9/site-packages/mxnet/ndarray/__init__.py'>
value x: [[-0.6338663 0.40156594 0.46456942]]
result : [[0.01641375 0. 0. 0. ]]
array([[0.00097611, 0.00019453]])
İleri hesaplamayı tekrarlamak aynı çıktıya yol açacaktır (ayrıntıları
atlıyoruz). Şimdi hybridize
işlevini çağırırsak ne olacağını
görelim.
net.hybridize()
net(x)
module F: <module 'mxnet.symbol' from '/home/d2l-worker/miniconda3/envs/d2l-tr-release-0/lib/python3.9/site-packages/mxnet/symbol/__init__.py'>
value x: <_Symbol data>
result : <_Symbol hybridnet0_relu0>
array([[0.00097611, 0.00019453]])
ndarray
kullanmak yerine artık F
için symbol
modülünü
kullanıyoruz. Ayrıca, girdi ndarray
türünde olsa da, ağ üzerinden
akan veriler artık derleme işleminin bir parçası olarak symbol
türüne dönüştürülür. İşlev çağrısını tekrarlamak şaşırtıcı bir sonuca
yol açar:
net(x)
array([[0.00097611, 0.00019453]])
Bu daha önce gördüğümüzden oldukça farklı. hybrid_forward
’de
tanımlandığı gibi tüm yazdırma ifadeleri atlanır. Gerçekten de,
melezleştirmeden sonra net(x)
’in yürütülmesi artık Python
yorumlayıcısı içermez. Bu, herhangi bir yapay Python kodunun (yazdırma
-print- ifadeleri gibi) çok daha akıcı bir yürütme ve daha iyi bir
başarım lehine atlandığı anlamına gelir. Bunun yerine, MXNet doğrudan
C++ arka işlemcisini çağırır. Ayrıca bazı işlevlerin symbol
modülünde desteklenmediğini (örn. asnumpy
) ve a += b
ve
a[:] = a + b
gibi yerinde işlemlerin a = a + b
olarak yeniden
yazılması gerektiğini unutmayın. Bununla birlikte, hız önemli olduğunda
modellerin derlenmesi çabaya değer. Fayda, modelin karmaşıklığına,
CPU’nun hızına ve GPU’ların hızına ve sayısına bağlı olarak, küçük
yüzdelerden iki kattan fazla hıza kadar değişebilir.
Modelleri derlemenin faydalarından biri, modeli ve parametrelerini diske
seri hale getirebilmemizdir (kaydedebiliriz). Bu, bir modeli seçtiğiniz
önişlemci dilinden bağımsız bir şekilde saklamamızı sağlar. Bu,
eğitilmiş modelleri diğer cihazlara konuşlandırmamıza ve diğer önişlemci
programlama dillerini kolayca kullanmamıza olanak tanır. Aynı zamanda
kod genellikle buyuru programlamadan elde edilebileceğinden daha
hızlıdır. save
işlevini iş başında görelim.
net.save('my_mlp')
!ls -lh my_mlp*
-rw-rw-r-- 1 d2l-worker d2l-worker 652K Oct 17 22:47 my_mlp
Modelleri derlemenin faydalarından biri, modeli ve parametrelerini diske
seri hale getirebilmemizdir (kaydedebiliriz). Bu, bir modeli seçtiğiniz
önişlemci dilinden bağımsız bir şekilde saklamamızı sağlar. Bu,
eğitilmiş modelleri diğer cihazlara konuşlandırmamıza ve diğer önişlemci
programlama dillerini kolayca kullanmamıza veya bir sunucuda eğitilmiş
bir model yürütmemize olanak tanır. Aynı zamanda kod genellikle buyuru
programlamadan elde edilebileceğinden daha hızlıdır. Tensorflow’ta
tasarruf etmemizi sağlayan düşük seviyeli API tf.saved_model
’tir.
saved_model
örneğini iş başında görelim.
net = get_net()
tf.saved_model.save(net, 'my_mlp')
!ls -lh my_mlp*
INFO:tensorflow:Assets written to: my_mlp/assets
total 72K
drwxr-xr-x 2 d2l-worker d2l-worker 4.0K Apr 25 19:36 assets
-rw-rw-r-- 1 d2l-worker d2l-worker 64K Oct 18 00:08 saved_model.pb
drwxr-xr-x 2 d2l-worker d2l-worker 4.0K Oct 18 00:08 variables
12.1.4. Özet¶
Buyuru programlama, kontrol akışı ve çok miktarda Python yazılım ekosistemi kullanma yeteneği ile kod yazmak mümkün olduğundan, yeni modeller tasarlamayı kolaylaştırır.
Sembolik programlama, programı belirtmemizi ve çalıştırmadan önce derlemenizi gerektirir. Faydası arttırılmış performanstır.
MXNet gerektiğinde her iki yaklaşımın avantajlarını birleştirebilir.
HybridSequential
veHybridBlock
sınıfları tarafından oluşturulan modeller,hybridize
işlevini çağırarak buyuru programlarını sembolik programlara dönüştürebilir.
12.1.5. Alıştırmalar¶
x.asnumpy()
bu bölümdekiHybridNet
sınıfınınhybrid_forward
işlevinin ilk satırına ekleyin. Kodu çalıştırın ve karşılaştığınız hataları gözlemleyin. Neden büyle oluyorlar?Kontrol akışını eklersek, yani
hybrid_forward
işlevindeif
vefor
Python ifadelerini eklersek ne olur?Önceki bölümlerde ilginizi çeken modelleri gözden geçirin. Onları yeniden uygulayarak hesaplama performanslarını artırabilir misiniz?
Önceki bölümlerde ilginizi çeken modelleri gözden geçirin. Onları yeniden uygulayarak hesaplama performanslarını artırabilir misiniz?
Önceki bölümlerde ilginizi çeken modelleri gözden geçirin. Onları yeniden uygulayarak hesaplama performanslarını artırabilir misiniz?