12.1. Derleyiciler ve Yorumlayıcılar
Open the notebook in Colab
Open the notebook in Colab
Open the notebook in Colab
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.

../_images/computegraph.svg

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:

  1. Yürütülecek işlemleri tanımlayın.

  2. İşlemleri yürütülebilir bir programa derleyin.

  3. 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 ve HybridBlock 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

  1. x.asnumpy() bu bölümdeki HybridNet sınıfının hybrid_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?

  2. Kontrol akışını eklersek, yani hybrid_forward işlevinde if ve for Python ifadelerini eklersek ne olur?

  3. Önceki bölümlerde ilginizi çeken modelleri gözden geçirin. Onları yeniden uygulayarak hesaplama performanslarını artırabilir misiniz?

Tartışmalar

  1. Önceki bölümlerde ilginizi çeken modelleri gözden geçirin. Onları yeniden uygulayarak hesaplama performanslarını artırabilir misiniz?

Tartışmalar

  1. Önceki bölümlerde ilginizi çeken modelleri gözden geçirin. Onları yeniden uygulayarak hesaplama performanslarını artırabilir misiniz?

Tartışmalar