.. _sec_hybridize: Derleyiciler ve Yorumlayıcılar ============================== Ş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. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python 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)) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 10 .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python 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)) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 10 .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python 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)) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 10 .. raw:: html
.. raw:: html
Python bir *yorumlanan dil*\ dir. 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. :numref:`fig_compute_graph`, veri akışını göstermektedir. .. _fig_compute_graph: .. figure:: ../img/computegraph.svg 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. Sembolik Programlama -------------------- Hesaplamanın genellikle süreç tam olarak tanımlandıktan sonra gerçekleştirildiği alternatifi, *sembolik programlama*\ yı, 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. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python 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) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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 .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python 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) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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 .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python 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) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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 .. raw:: html
.. raw:: html
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. 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. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
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. .. raw:: html
.. raw:: html
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ı. .. raw:: html
.. raw:: html
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ı. .. raw:: html
.. raw:: html
``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. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python 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) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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. .. raw:: latex \diilbookstyleinputcell .. code:: python net.hybridize() net(x) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python 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) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output tensor([[0.1160, 0.0584]], grad_fn=) 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. .. raw:: latex \diilbookstyleinputcell .. code:: python net = torch.jit.script(net) net(x) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output tensor([[0.1160, 0.0584]], grad_fn=) 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). .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python 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) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output Ö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. .. raw:: latex \diilbookstyleinputcell .. code:: python net = tf.function(net) net(x) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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. .. raw:: html
.. raw:: html
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. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@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. .. raw:: latex \diilbookstyleinputcell .. code:: python 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() .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@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. .. raw:: latex \diilbookstyleinputcell .. code:: python 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) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@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. .. raw:: latex \diilbookstyleinputcell .. code:: python 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) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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. .. raw:: html
.. raw:: html
Seri Hale Getirme ~~~~~~~~~~~~~~~~~ .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
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. .. raw:: latex \diilbookstyleinputcell .. code:: python net.export('my_mlp') !ls -lh my_mlp* .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output -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. .. raw:: latex \diilbookstyleinputcell .. code:: python !head my_mlp-symbol.json .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output { "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. .. raw:: latex \diilbookstyleinputcell .. code:: python 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. .. raw:: latex \diilbookstyleinputcell .. code:: python net = HybridNet() net.initialize() x = np.random.normal(size=(1, 3)) net(x) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output module F: value x: [[-0.6338663 0.40156594 0.46456942]] result : [[0.01641375 0. 0. 0. ]] .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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. .. raw:: latex \diilbookstyleinputcell .. code:: python net.hybridize() net(x) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output module F: value x: <_Symbol data> result : <_Symbol hybridnet0_relu0> .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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: .. raw:: latex \diilbookstyleinputcell .. code:: python net(x) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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. .. raw:: html
.. raw:: html
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. .. raw:: latex \diilbookstyleinputcell .. code:: python net.save('my_mlp') !ls -lh my_mlp* .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output -rw-rw-r-- 1 d2l-worker d2l-worker 652K Oct 17 22:47 my_mlp .. raw:: html
.. raw:: html
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. .. raw:: latex \diilbookstyleinputcell .. code:: python net = get_net() tf.saved_model.save(net, 'my_mlp') !ls -lh my_mlp* .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 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 .. raw:: html
.. raw:: html
Ö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. .. raw:: html
mxnet
.. raw:: html
- 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. .. raw:: html
.. raw:: html
Alıştırmalar ------------ .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
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 `__ .. raw:: html
.. raw:: html
1. Önceki bölümlerde ilginizi çeken modelleri gözden geçirin. Onları yeniden uygulayarak hesaplama performanslarını artırabilir misiniz? `Tartışmalar `__ .. raw:: html
.. raw:: html
1. Önceki bölümlerde ilginizi çeken modelleri gözden geçirin. Onları yeniden uygulayarak hesaplama performanslarını artırabilir misiniz? `Tartışmalar `__ .. raw:: html
.. raw:: html