.. _sec_transformer: Dönüştürücü =========== :numref:`subsec_cnn-rnn-self-attention` içinde CNN , RNN ve özdikkati karşılaştırdık. Özellikle, özdikkat hem paralel hesaplamanın hem de en kısa maksimum yol uzunluğunun keyfini sürer. Bu nedenle doğal olarak, özdikkat kullanarak derin mimariler tasarlamak caziptir. Girdi temsilleri için RNN'lere güvenen önceki özdikkat modellerinin aksine :cite:`Cheng.Dong.Lapata.2016,Lin.Feng.Santos.ea.2017,Paulus.Xiong.Socher.2017`, dönüştürücü modeli :cite:`Vaswani.Shazeer.Parmar.ea.2017` sadece herhangi bir evrişimli veya yinelemeli tabaka olmadan dikkat mekanizmalarına dayanmaktadır. Başlangıçta metin verilerinde diziden diziye öğrenme için önerilmiş olsa da, dönüştürücüler dil, görme, konuşma ve pekiştirmeli öğrenme alanlarında olduğu gibi çok çeşitli modern derin öğrenme uygulamalarında yaygın olmuştur. Model ----- Kodlayıcı-kodçözücü mimarisinin bir örneği olarak, dönüştürücünün genel mimarisi :numref:`fig_transformer` içinde sunulmuştur. Gördüğümüz gibi, dönüştürücü bir kodlayıcı ve bir kodçözücüden oluşur. :numref:`fig_s2s_attention_details` içinde diziden diziye öğrenmede Bahdanau dikkatinden farklı olarak, girdi (kaynak) ve çıktı (hedef) dizi gömmeleri, özdikkate dayalı modülleri istifleyen kodlayıcıya ve kodçözücüye beslenmeden önce, konumsal kodlama ile toplanır. .. _fig_transformer: .. figure:: ../img/transformer.svg :width: 500px Dönüştürücü mimarisi. Şimdi :numref:`fig_transformer` figüründeki dönüştürücü mimarisine genel bir bakış sunuyoruz. Yüksek düzeyde, dönüştürücü kodlayıcısı, her katmanın iki alt katmana sahip olduğu (ikisi de :math:`\mathrm{altkatman}` olarak ifade edilir) çoklu özdeş katmandan oluşan bir yığındır. Birincisi, çoklu kafalı bir özdikkat ortaklamasıdır ve ikincisi ise konumsal olarak ileriye besleme ağıdır. Özellikle, özdikkatteki kodlayıcıda, sorgular, anahtarlar ve değerler tüm önceki kodlayıcı katmanının çıktılarından gelir. :numref:`sec_resnet` içindeki ResNet tasarımından esinlenerek, her iki alt katman etrafında artık bağlantı kullanılır. Dönüştürücüde, dizinin herhangi bir pozisyonunda :math:`\mathbf{x} \in \mathbb{R}^d` herhangi bir girdi için :math:`\mathrm{altkatman}(\mathbf{x}) \in \mathbb{R}^d`'ye ihtiyaç duyuyoruz, böylece :math:`\mathbf{x} + \mathrm{altkatman}(\mathbf{x}) \in \mathbb{R}^d`, artık bağlantı :math:`\mathbf{x} + \mathrm{altkatman}(\mathbf{x}) \in \mathbb{R}^d` mümkündür. Artık bağlantıya bu ilavenin hemen ardından katman normalleştirmesi :cite:`Ba.Kiros.Hinton.2016` gelir. Sonuç olarak, dönüştürücü kodlayıcısı, girdi dizisinin her konumu için :math:`d` boyutlu bir vektör temsilini çıkarır. Dönüştürücü kodçözücü ayrıca artık bağlantılar ve katman normalleştirmeleri ile birden çok özdeş katman yığınıdır. Kodlayıcıda açıklanan iki alt katmanın yanı sıra, kodçözücü bu ikisi arasında kodlayıcı-kodçözücü dikkat olarak bilinen üçüncü bir alt katman ekler. Kodlayıcı-kod özücü dikkatinde, sorgular önceki kodçözücü katmanının çıktılarından ve anahtarlar ve değerler dönüştürücü kodlayıcı çıktılarından kaynaklanır. Kodçözücünün özdikkatinde, sorgular, anahtarlar ve değerler tüm önceki kodçözücü katmanının çıktılarından gelir. Bununla birlikte, kodçözücüdeki her pozisyonun, yalnızca kodçözücünün bu konuma kadar tüm pozisyonlara ilgi göstermesine izin verilir. Bu *maskelenmiş* dikkat, otomatik bağlanım özelliğini korur ve tahminin yalnızca üretilen çıktı belirteçlerine bağlı olmasını sağlar. :numref:`sec_multihead-attention` içindeki ölçeklendirilmiş nokta çarpımlarına ve :numref:`subsec_positional-encoding` içindeki konumsal kodlamaya dayanan çoklu kafalı dikkati zaten tanımladık ve uyguladık. Aşağıda, dönüştürücü modelinin geri kalanını uygulayacağız. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python import math import pandas as pd from d2l import mxnet as d2l from mxnet import autograd, np, npx from mxnet.gluon import nn npx.set_np() .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python import math import pandas as pd import torch from torch import nn from d2l import torch as d2l .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python import numpy as np import pandas as pd import tensorflow as tf from d2l import tensorflow as d2l .. raw:: html
.. raw:: html
Konumsal Olarak İleriye Besleme Ağlar ------------------------------------- Konumsal olarak ileriye besleme ağı, aynı MLP'yi kullanarak tüm dizi pozisyonlarındaki temsili dönüştürür. Bu yüzden ona *konumsal olarak* diyoruz. Aşağıdaki uygulamada, (toplu iş boyutu, zaman adımlarının sayısı veya belirteç dizi uzunluğu, gizli birimlerin sayısı veya öznitelik boyutu) şekline sahip ``X`` girdisi iki katmanlı bir MLP tarafından (parti boyutu, zaman adımlarının sayısı, ``ffn_num_outputs``) şekilli çıktı tensörüne dönüştürülecektir . .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class PositionWiseFFN(nn.Block): """Konumsal olarak ileriye besleme ağı.""" def __init__(self, ffn_num_hiddens, ffn_num_outputs, **kwargs): super(PositionWiseFFN, self).__init__(**kwargs) self.dense1 = nn.Dense(ffn_num_hiddens, flatten=False, activation='relu') self.dense2 = nn.Dense(ffn_num_outputs, flatten=False) def forward(self, X): return self.dense2(self.dense1(X)) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class PositionWiseFFN(nn.Module): """Konumsal olarak ileriye besleme ağı.""" def __init__(self, ffn_num_input, ffn_num_hiddens, ffn_num_outputs, **kwargs): super(PositionWiseFFN, self).__init__(**kwargs) self.dense1 = nn.Linear(ffn_num_input, ffn_num_hiddens) self.relu = nn.ReLU() self.dense2 = nn.Linear(ffn_num_hiddens, ffn_num_outputs) def forward(self, X): return self.dense2(self.relu(self.dense1(X))) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class PositionWiseFFN(tf.keras.layers.Layer): """Konumsal olarak ileriye besleme ağı.""" def __init__(self, ffn_num_hiddens, ffn_num_outputs, **kwargs): super().__init__(*kwargs) self.dense1 = tf.keras.layers.Dense(ffn_num_hiddens) self.relu = tf.keras.layers.ReLU() self.dense2 = tf.keras.layers.Dense(ffn_num_outputs) def call(self, X): return self.dense2(self.relu(self.dense1(X))) .. raw:: html
.. raw:: html
Aşağıdaki örnek, tensörün en içteki boyutunun konumsal olarak ileriye besleme ağındaki çıktı sayısına değiştiğini göstermektedir. Aynı MLP tüm pozisyonlarda dönüştüğünden, tüm bu pozisyonlardaki girdiler aynı olduğunda, çıktıları da aynıdır. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python ffn = PositionWiseFFN(4, 8) ffn.initialize() ffn(np.ones((2, 3, 4)))[0] .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output array([[ 0.00239431, 0.00927085, -0.00021069, -0.00923989, -0.0082903 , -0.00162741, 0.00659031, 0.00023905], [ 0.00239431, 0.00927085, -0.00021069, -0.00923989, -0.0082903 , -0.00162741, 0.00659031, 0.00023905], [ 0.00239431, 0.00927085, -0.00021069, -0.00923989, -0.0082903 , -0.00162741, 0.00659031, 0.00023905]]) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python ffn = PositionWiseFFN(4, 4, 8) ffn.eval() ffn(torch.ones((2, 3, 4)))[0] .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output tensor([[-0.3031, 0.0522, -0.8444, -0.3835, 0.0093, -0.2866, -0.0185, 0.0244], [-0.3031, 0.0522, -0.8444, -0.3835, 0.0093, -0.2866, -0.0185, 0.0244], [-0.3031, 0.0522, -0.8444, -0.3835, 0.0093, -0.2866, -0.0185, 0.0244]], grad_fn=) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python ffn = PositionWiseFFN(4, 8) ffn(tf.ones((2, 3, 4)))[0] .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Artık Bağlantı ve Katman Normalleştirmesi ----------------------------------------- Şimdi :numref:`fig_transformer` figüründeki "topla ve normalleştir" bileşenine odaklanalım. Bu bölümün başında tanımladığımız gibi, bu, katman normalleştirmesinin hemen ardından geldiği bir artık bağlantıdır. Her ikisi de etkili derin mimarilerin anahtarıdır. :numref:`sec_batch_norm` bölümünde, toplu normalleştirmenin nasıl ortalandığını ve bir minigrup içindeki örnekler arasında nasıl yeniden ölçeklendiğini açıkladık. Katman normalleştirmesi, birincinin öznitelik boyutu boyunca normalleştirmesi dışında toplu normalleştirme ile aynıdır. Bilgisayarla görmede yaygın uygulamalarına rağmen, toplu normalleştirme deneysel olarak genellikle girdileri değişken uzunluktaki diziler olan doğal dil işleme görevlerinde katman normalleştirmesinden daha az etkilidir. Aşağıdaki kod parçacığı katman normalleştirme ve toplu normalleştirme ile farklı boyutlar arasında normalleştirmeyi karşılaştırır. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python ln = nn.LayerNorm() ln.initialize() bn = nn.BatchNorm() bn.initialize() X = np.array([[1, 2], [2, 3]]) # Eğitim modunda `X`'den ortalama ve varyansı hesaplayın with autograd.record(): print('layer norm:', ln(X), '\nbatch norm:', bn(X)) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output layer norm: [[-0.99998 0.99998] [-0.99998 0.99998]] batch norm: [[-0.99998 -0.99998] [ 0.99998 0.99998]] .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python ln = nn.LayerNorm(2) bn = nn.BatchNorm1d(2) X = torch.tensor([[1, 2], [2, 3]], dtype=torch.float32) # Eğitim modunda `X`'den ortalama ve varyansı hesaplayın print('layer norm:', ln(X), '\nbatch norm:', bn(X)) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output layer norm: tensor([[-1.0000, 1.0000], [-1.0000, 1.0000]], grad_fn=) batch norm: tensor([[-1.0000, -1.0000], [ 1.0000, 1.0000]], grad_fn=) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python ln = tf.keras.layers.LayerNormalization() bn = tf.keras.layers.BatchNormalization() X = tf.constant([[1, 2], [2, 3]], dtype=tf.float32) print('layer norm:', ln(X), '\nbatch norm:', bn(X, training=True)) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output layer norm: tf.Tensor( [[-0.998006 0.9980061] [-0.9980061 0.998006 ]], shape=(2, 2), dtype=float32) batch norm: tf.Tensor( [[-0.998006 -0.9980061 ] [ 0.9980061 0.99800587]], shape=(2, 2), dtype=float32) .. raw:: html
.. raw:: html
Artık ``AddNorm`` sınıfını bir artık bağlantı ve ardından katman normalleştirme kullanarak uygulayabiliriz. Düzenlileştirme için hattan düşürme de uygulanır. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class AddNorm(nn.Block): """Artık bağlantı ve ardından katman normalleştirme.""" def __init__(self, dropout, **kwargs): super(AddNorm, self).__init__(**kwargs) self.dropout = nn.Dropout(dropout) self.ln = nn.LayerNorm() def forward(self, X, Y): return self.ln(self.dropout(Y) + X) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class AddNorm(nn.Module): """Artık bağlantı ve ardından katman normalleştirme.""" def __init__(self, normalized_shape, dropout, **kwargs): super(AddNorm, self).__init__(**kwargs) self.dropout = nn.Dropout(dropout) self.ln = nn.LayerNorm(normalized_shape) def forward(self, X, Y): return self.ln(self.dropout(Y) + X) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class AddNorm(tf.keras.layers.Layer): """Artık bağlantı ve ardından katman normalleştirme.""" def __init__(self, normalized_shape, dropout, **kwargs): super().__init__(**kwargs) self.dropout = tf.keras.layers.Dropout(dropout) self.ln = tf.keras.layers.LayerNormalization(normalized_shape) def call(self, X, Y, **kwargs): return self.ln(self.dropout(Y, **kwargs) + X) .. raw:: html
.. raw:: html
Artık bağlantı, iki girdinin aynı şekle sahip olmasını gerektirir, böylece çıktı tensörünün toplama işleminden sonra da aynı şekle sahip olmasını sağlar. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python add_norm = AddNorm(0.5) add_norm.initialize() add_norm(np.ones((2, 3, 4)), np.ones((2, 3, 4))).shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output (2, 3, 4) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python add_norm = AddNorm([3, 4], 0.5) # Normalized_shape is input.size()[1:] add_norm.eval() add_norm(torch.ones((2, 3, 4)), torch.ones((2, 3, 4))).shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output torch.Size([2, 3, 4]) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python add_norm = AddNorm([1, 2], 0.5) # Normalized_shape is: [i for i in range(len(input.shape))][1:] add_norm(tf.ones((2, 3, 4)), tf.ones((2, 3, 4)), training=False).shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output TensorShape([2, 3, 4]) .. raw:: html
.. raw:: html
Kodlayıcı --------- Dönüştürücü kodlayıcıyı toparlamak için gerekli tüm bileşenlerle, kodlayıcı içinde tek bir katman uygulayarak başlayalım. Aşağıdaki ``EncoderBlock`` sınıfı iki alt katman içerir: Çoklu kafalı özdikkat ve konumsal ileri beslemeli ağlar, burada bir artık bağlantı ve ardından katman normalleştirme her iki alt katman etrafında kullanılır. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class EncoderBlock(nn.Block): """Dönüştürücü kodlayıcı bloğu.""" def __init__(self, num_hiddens, ffn_num_hiddens, num_heads, dropout, use_bias=False, **kwargs): super(EncoderBlock, self).__init__(**kwargs) self.attention = d2l.MultiHeadAttention( num_hiddens, num_heads, dropout, use_bias) self.addnorm1 = AddNorm(dropout) self.ffn = PositionWiseFFN(ffn_num_hiddens, num_hiddens) self.addnorm2 = AddNorm(dropout) def forward(self, X, valid_lens): Y = self.addnorm1(X, self.attention(X, X, X, valid_lens)) return self.addnorm2(Y, self.ffn(Y)) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class EncoderBlock(nn.Module): """Dönüştürücü kodlayıcı bloğu.""" def __init__(self, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, dropout, use_bias=False, **kwargs): super(EncoderBlock, self).__init__(**kwargs) self.attention = d2l.MultiHeadAttention( key_size, query_size, value_size, num_hiddens, num_heads, dropout, use_bias) self.addnorm1 = AddNorm(norm_shape, dropout) self.ffn = PositionWiseFFN( ffn_num_input, ffn_num_hiddens, num_hiddens) self.addnorm2 = AddNorm(norm_shape, dropout) def forward(self, X, valid_lens): Y = self.addnorm1(X, self.attention(X, X, X, valid_lens)) return self.addnorm2(Y, self.ffn(Y)) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class EncoderBlock(tf.keras.layers.Layer): """Dönüştürücü kodlayıcı bloğu.""" def __init__(self, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_hiddens, num_heads, dropout, bias=False, **kwargs): super().__init__(**kwargs) self.attention = d2l.MultiHeadAttention(key_size, query_size, value_size, num_hiddens, num_heads, dropout, bias) self.addnorm1 = AddNorm(norm_shape, dropout) self.ffn = PositionWiseFFN(ffn_num_hiddens, num_hiddens) self.addnorm2 = AddNorm(norm_shape, dropout) def call(self, X, valid_lens, **kwargs): Y = self.addnorm1(X, self.attention(X, X, X, valid_lens, **kwargs), **kwargs) return self.addnorm2(Y, self.ffn(Y), **kwargs) .. raw:: html
.. raw:: html
Gördüğümüz gibi, dönüştürücü kodlayıcısındaki herhangi bir katman girdisinin şeklini değiştirmez. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python X = np.ones((2, 100, 24)) valid_lens = np.array([3, 2]) encoder_blk = EncoderBlock(24, 48, 8, 0.5) encoder_blk.initialize() encoder_blk(X, valid_lens).shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output (2, 100, 24) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python X = torch.ones((2, 100, 24)) valid_lens = torch.tensor([3, 2]) encoder_blk = EncoderBlock(24, 24, 24, 24, [100, 24], 24, 48, 8, 0.5) encoder_blk.eval() encoder_blk(X, valid_lens).shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output torch.Size([2, 100, 24]) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python X = tf.ones((2, 100, 24)) valid_lens = tf.constant([3, 2]) norm_shape = [i for i in range(len(X.shape))][1:] encoder_blk = EncoderBlock(24, 24, 24, 24, norm_shape, 48, 8, 0.5) encoder_blk(X, valid_lens, training=False).shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output TensorShape([2, 100, 24]) .. raw:: html
.. raw:: html
Aşağıdaki dönüştürücü kodlayıcı uygulamasında, yukarıdaki ``EncoderBlock`` sınıflarının ``num_layers`` tane örneğini yığınlıyoruz. Değerleri her zaman -1 ile 1 arasında olan sabit konumsal kodlamayı kullandığımızdan, girdi gömmeyi ve konumsal kodlamayı toplamadan önce yeniden ölçeklendirmek için öğrenilebilir girdi gömmelerinin değerlerini gömme boyutunun kareköküyle çarparız. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class TransformerEncoder(d2l.Encoder): """Transformer encoder.""" def __init__(self, vocab_size, num_hiddens, ffn_num_hiddens, num_heads, num_layers, dropout, use_bias=False, **kwargs): super(TransformerEncoder, self).__init__(**kwargs) self.num_hiddens = num_hiddens self.embedding = nn.Embedding(vocab_size, num_hiddens) self.pos_encoding = d2l.PositionalEncoding(num_hiddens, dropout) self.blks = nn.Sequential() for _ in range(num_layers): self.blks.add( EncoderBlock(num_hiddens, ffn_num_hiddens, num_heads, dropout, use_bias)) def forward(self, X, valid_lens, *args): # # Konumsal kodlama değerleri -1 ile 1 arasında olduğundan, # gömme değerleri, toplanmadan önce yeniden ölçeklendirmek için # gömme boyutunun kareköküyle çarpılır X = self.pos_encoding(self.embedding(X) * math.sqrt(self.num_hiddens)) self.attention_weights = [None] * len(self.blks) for i, blk in enumerate(self.blks): X = blk(X, valid_lens) self.attention_weights[ i] = blk.attention.attention.attention_weights return X .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class TransformerEncoder(d2l.Encoder): """Transformer encoder.""" def __init__(self, vocab_size, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, num_layers, dropout, use_bias=False, **kwargs): super(TransformerEncoder, self).__init__(**kwargs) self.num_hiddens = num_hiddens self.embedding = nn.Embedding(vocab_size, num_hiddens) self.pos_encoding = d2l.PositionalEncoding(num_hiddens, dropout) self.blks = nn.Sequential() for i in range(num_layers): self.blks.add_module("block"+str(i), EncoderBlock(key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, dropout, use_bias)) def forward(self, X, valid_lens, *args): # # Konumsal kodlama değerleri -1 ile 1 arasında olduğundan, # gömme değerleri, toplanmadan önce yeniden ölçeklendirmek için # gömme boyutunun kareköküyle çarpılır X = self.pos_encoding(self.embedding(X) * math.sqrt(self.num_hiddens)) self.attention_weights = [None] * len(self.blks) for i, blk in enumerate(self.blks): X = blk(X, valid_lens) self.attention_weights[ i] = blk.attention.attention.attention_weights return X .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class TransformerEncoder(d2l.Encoder): """Transformer encoder.""" def __init__(self, vocab_size, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_hiddens, num_heads, num_layers, dropout, bias=False, **kwargs): super().__init__(**kwargs) self.num_hiddens = num_hiddens self.embedding = tf.keras.layers.Embedding(vocab_size, num_hiddens) self.pos_encoding = d2l.PositionalEncoding(num_hiddens, dropout) self.blks = [EncoderBlock( key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_hiddens, num_heads, dropout, bias) for _ in range( num_layers)] def call(self, X, valid_lens, **kwargs): # # Konumsal kodlama değerleri -1 ile 1 arasında olduğundan, # gömme değerleri, toplanmadan önce yeniden ölçeklendirmek için # gömme boyutunun kareköküyle çarpılır X = self.pos_encoding(self.embedding(X) * tf.math.sqrt( tf.cast(self.num_hiddens, dtype=tf.float32)), **kwargs) self.attention_weights = [None] * len(self.blks) for i, blk in enumerate(self.blks): X = blk(X, valid_lens, **kwargs) self.attention_weights[ i] = blk.attention.attention.attention_weights return X .. raw:: html
.. raw:: html
Aşağıda iki katmanlı bir dönüştürücü kodlayıcısı oluşturmak için hiper parametreleri belirtiyoruz. Dönüştürücü kodlayıcı çıktısının şekli (toplu iş boyutu, zaman adımlarının sayısı, ``num_hiddens``) şeklindedir. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python encoder = TransformerEncoder(200, 24, 48, 8, 2, 0.5) encoder.initialize() encoder(np.ones((2, 100)), valid_lens).shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output (2, 100, 24) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python encoder = TransformerEncoder( 200, 24, 24, 24, 24, [100, 24], 24, 48, 8, 2, 0.5) encoder.eval() encoder(torch.ones((2, 100), dtype=torch.long), valid_lens).shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output torch.Size([2, 100, 24]) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python encoder = TransformerEncoder(200, 24, 24, 24, 24, [1, 2], 48, 8, 2, 0.5) encoder(tf.ones((2, 100)), valid_lens, training=False).shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output TensorShape([2, 100, 24]) .. raw:: html
.. raw:: html
Kodçözücü --------- :numref:`fig_transformer` şeklinde gösterildiği gibi, dönüştürücü kodçözücüsü birden çok özdeş katmandan oluşur. Her katman, üç alt katman içeren aşağıdaki ``DecoderBlock`` sınıfında uygulanır: Kodçözücü özdikkat, kodlayıcı-kodçözücü dikkat ve konumsal olarak ileri beslemeli ağlar. Bu alt katmanlar çevrelerinde bir artık bağlantı ve ardından katman normalleştirmesi kullanır. Bu bölümde daha önce de açıklandığı gibi, maskelenmiş çoklu kafalı kodçözücü özdikkatinde (ilk alt katman), sorgular, anahtarlar ve değerler önceki kodçözücü katmanının çıktılarından gelir. Diziden diziye modellerini eğitirken, çıktı dizisinin tüm pozisyonlarında (zaman adımları) belirteçleri bilinir. Bununla birlikte, tahmin esnasında çıktı dizisi belirteç belirteç oluşturulur; böylece, herhangi bir kodçözücü zaman adımında yalnızca üretilen belirteçler kodçözücünün özdikkatinde kullanılabilir. Kodçözücünün otomatik regresyonunu korumak için, maskeli özdikkat ``dec_valid_lens``'ü belirtir, böylece herhangi bir sorgu yalnızca kodçözücünün sorgulama konumuna kadarki tüm konumlara ilgi gösterir. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python class DecoderBlock(nn.Block): # Kodçözücüdeki `i`. blok def __init__(self, num_hiddens, ffn_num_hiddens, num_heads, dropout, i, **kwargs): super(DecoderBlock, self).__init__(**kwargs) self.i = i self.attention1 = d2l.MultiHeadAttention(num_hiddens, num_heads, dropout) self.addnorm1 = AddNorm(dropout) self.attention2 = d2l.MultiHeadAttention(num_hiddens, num_heads, dropout) self.addnorm2 = AddNorm(dropout) self.ffn = PositionWiseFFN(ffn_num_hiddens, num_hiddens) self.addnorm3 = AddNorm(dropout) def forward(self, X, state): enc_outputs, enc_valid_lens = state[0], state[1] # Eğitim sırasında, herhangi bir çıktı dizisinin tüm belirteçleri # aynı anda işlenir, bu nedenle `state[2][self.i]` ilklendiği gibi # `None` olur. Tahmin sırasında herhangi bir çıktı dizisi # belirtecinin kodunu çözerken, `state[2][self.i]`, geçerli zaman # adımına kadar `i`. bloğundaki kodu çözülmüş çıktının # temsillerini içerir. if state[2][self.i] is None: key_values = X else: key_values = np.concatenate((state[2][self.i], X), axis=1) state[2][self.i] = key_values if autograd.is_training(): batch_size, num_steps, _ = X.shape # `dec_valid_lens` şekli: (`batch_size`, `num_steps`), # burada her satır [1, 2, ..., `num_steps`] dec_valid_lens = np.tile(np.arange(1, num_steps + 1, ctx=X.ctx), (batch_size, 1)) else: dec_valid_lens = None # Öz-dikkat X2 = self.attention1(X, key_values, key_values, dec_valid_lens) Y = self.addnorm1(X, X2) # Kodlayıcı - kodçözücüye dikkat. `enc_outputs` şekli: # (`batch_size`, `num_steps`, `num_hiddens`) Y2 = self.attention2(Y, enc_outputs, enc_outputs, enc_valid_lens) Z = self.addnorm2(Y, Y2) return self.addnorm3(Z, self.ffn(Z)), state .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python class DecoderBlock(nn.Module): # Kodçözücüdeki `i`. blok def __init__(self, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, dropout, i, **kwargs): super(DecoderBlock, self).__init__(**kwargs) self.i = i self.attention1 = d2l.MultiHeadAttention( key_size, query_size, value_size, num_hiddens, num_heads, dropout) self.addnorm1 = AddNorm(norm_shape, dropout) self.attention2 = d2l.MultiHeadAttention( key_size, query_size, value_size, num_hiddens, num_heads, dropout) self.addnorm2 = AddNorm(norm_shape, dropout) self.ffn = PositionWiseFFN(ffn_num_input, ffn_num_hiddens, num_hiddens) self.addnorm3 = AddNorm(norm_shape, dropout) def forward(self, X, state): enc_outputs, enc_valid_lens = state[0], state[1] # Eğitim sırasında, herhangi bir çıktı dizisinin tüm belirteçleri # aynı anda işlenir, bu nedenle `state[2][self.i]` ilklendiği gibi # `None` olur. Tahmin sırasında herhangi bir çıktı dizisi # belirtecinin kodunu çözerken, `state[2][self.i]`, geçerli zaman # adımına kadar `i`. bloğundaki kodu çözülmüş çıktının # temsillerini içerir. if state[2][self.i] is None: key_values = X else: key_values = torch.cat((state[2][self.i], X), axis=1) state[2][self.i] = key_values if self.training: batch_size, num_steps, _ = X.shape # `dec_valid_lens` şekli: (`batch_size`, `num_steps`), # burada her satır [1, 2, ..., `num_steps`] dec_valid_lens = torch.arange( 1, num_steps + 1, device=X.device).repeat(batch_size, 1) else: dec_valid_lens = None # Öz-dikkat X2 = self.attention1(X, key_values, key_values, dec_valid_lens) Y = self.addnorm1(X, X2) # Kodlayıcı - kodçözücüye dikkat. `enc_outputs` şekli: # (`batch_size`, `num_steps`, `num_hiddens`) Y2 = self.attention2(Y, enc_outputs, enc_outputs, enc_valid_lens) Z = self.addnorm2(Y, Y2) return self.addnorm3(Z, self.ffn(Z)), state .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python class DecoderBlock(tf.keras.layers.Layer): # Kodçözücüdeki `i`. blok def __init__(self, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_hiddens, num_heads, dropout, i, **kwargs): super().__init__(**kwargs) self.i = i self.attention1 = d2l.MultiHeadAttention(key_size, query_size, value_size, num_hiddens, num_heads, dropout) self.addnorm1 = AddNorm(norm_shape, dropout) self.attention2 = d2l.MultiHeadAttention(key_size, query_size, value_size, num_hiddens, num_heads, dropout) self.addnorm2 = AddNorm(norm_shape, dropout) self.ffn = PositionWiseFFN(ffn_num_hiddens, num_hiddens) self.addnorm3 = AddNorm(norm_shape, dropout) def call(self, X, state, **kwargs): enc_outputs, enc_valid_lens = state[0], state[1] # Eğitim sırasında, herhangi bir çıktı dizisinin tüm belirteçleri # aynı anda işlenir, bu nedenle `state[2][self.i]` ilklendiği gibi # `None` olur. Tahmin sırasında herhangi bir çıktı dizisi # belirtecinin kodunu çözerken, `state[2][self.i]`, geçerli zaman # adımına kadar `i`. bloğundaki kodu çözülmüş çıktının # temsillerini içerir. if state[2][self.i] is None: key_values = X else: key_values = tf.concat((state[2][self.i], X), axis=1) state[2][self.i] = key_values if kwargs["training"]: batch_size, num_steps, _ = X.shape # `dec_valid_lens` şekli: (`batch_size`, `num_steps`), # burada her satır [1, 2, ..., `num_steps`] dec_valid_lens = tf.repeat(tf.reshape(tf.range(1, num_steps + 1), shape=(-1, num_steps)), repeats=batch_size, axis=0) else: dec_valid_lens = None # Öz-dikkat X2 = self.attention1(X, key_values, key_values, dec_valid_lens, **kwargs) Y = self.addnorm1(X, X2, **kwargs) # Kodlayıcı - kodçözücüye dikkat. `enc_outputs` şekli: # (`batch_size`, `num_steps`, `num_hiddens`) Y2 = self.attention2(Y, enc_outputs, enc_outputs, enc_valid_lens, **kwargs) Z = self.addnorm2(Y, Y2, **kwargs) return self.addnorm3(Z, self.ffn(Z), **kwargs), state .. raw:: html
.. raw:: html
Kodlayıcı-kodçözücü dikkat ve artık bağlantılarda toplama işlemlerinde ölçeklendirilmiş nokta çarpımı işlemlerini kolaylaştırmak için, kodçözücünün öznitelik boyutu (``num_hiddens``) kodlayıcınınkiyle aynıdır. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python decoder_blk = DecoderBlock(24, 48, 8, 0.5, 0) decoder_blk.initialize() X = np.ones((2, 100, 24)) state = [encoder_blk(X, valid_lens), valid_lens, [None]] decoder_blk(X, state)[0].shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output (2, 100, 24) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python decoder_blk = DecoderBlock(24, 24, 24, 24, [100, 24], 24, 48, 8, 0.5, 0) decoder_blk.eval() X = torch.ones((2, 100, 24)) state = [encoder_blk(X, valid_lens), valid_lens, [None]] decoder_blk(X, state)[0].shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output torch.Size([2, 100, 24]) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python decoder_blk = DecoderBlock(24, 24, 24, 24, [1, 2], 48, 8, 0.5, 0) X = tf.ones((2, 100, 24)) state = [encoder_blk(X, valid_lens), valid_lens, [None]] decoder_blk(X, state, training=False)[0].shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output TensorShape([2, 100, 24]) .. raw:: html
.. raw:: html
Şimdi ``DecoderBlock`` ``DecoderBlock`` örneklerinden oluşan tam dönüştürücü kodçözücüyü oluşturuyoruz. Sonunda, tam bağlı bir katman tüm ``vocab_size`` olası çıktı belirteçleri için tahmin hesaplar. Hem dekoder öz-dikkat ağırlıkları hem de kodlayıcı-kodçözücü dikkat ağırlıkları daha sonra görselleştirme için saklanır. Şimdi, ``DecoderBlock``'un ``num_layers`` tane örnekten oluşan bütün dönüştürücü kodçözücüsünü oluşturuyoruz. Sonunda, tam bağlı bir katman, ``vocab_size`` boyutlu tüm olası çıktı belirteçleri için tahminleri hesaplar. Hem kodçözücü özdikkat ağırlıkları hem de kodlayıcı-kodçözücü dikkat ağırlıkları daha sonrasındaki görselleştirme için saklanır. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python class TransformerDecoder(d2l.AttentionDecoder): def __init__(self, vocab_size, num_hiddens, ffn_num_hiddens, num_heads, num_layers, dropout, **kwargs): super(TransformerDecoder, self).__init__(**kwargs) self.num_hiddens = num_hiddens self.num_layers = num_layers self.embedding = nn.Embedding(vocab_size, num_hiddens) self.pos_encoding = d2l.PositionalEncoding(num_hiddens, dropout) self.blks = nn.Sequential() for i in range(num_layers): self.blks.add( DecoderBlock(num_hiddens, ffn_num_hiddens, num_heads, dropout, i)) self.dense = nn.Dense(vocab_size, flatten=False) def init_state(self, enc_outputs, enc_valid_lens, *args): return [enc_outputs, enc_valid_lens, [None] * self.num_layers] def forward(self, X, state): X = self.pos_encoding(self.embedding(X) * math.sqrt(self.num_hiddens)) self._attention_weights = [[None] * len(self.blks) for _ in range (2)] for i, blk in enumerate(self.blks): X, state = blk(X, state) # Kodçözücü özdikkat ağırlıkları self._attention_weights[0][ i] = blk.attention1.attention.attention_weights # Kodlayıcı-kodçözücü dikkat ağırlıkları self._attention_weights[1][ i] = blk.attention2.attention.attention_weights return self.dense(X), state @property def attention_weights(self): return self._attention_weights .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python class TransformerDecoder(d2l.AttentionDecoder): def __init__(self, vocab_size, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, num_layers, dropout, **kwargs): super(TransformerDecoder, self).__init__(**kwargs) self.num_hiddens = num_hiddens self.num_layers = num_layers self.embedding = nn.Embedding(vocab_size, num_hiddens) self.pos_encoding = d2l.PositionalEncoding(num_hiddens, dropout) self.blks = nn.Sequential() for i in range(num_layers): self.blks.add_module("block"+str(i), DecoderBlock(key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, dropout, i)) self.dense = nn.Linear(num_hiddens, vocab_size) def init_state(self, enc_outputs, enc_valid_lens, *args): return [enc_outputs, enc_valid_lens, [None] * self.num_layers] def forward(self, X, state): X = self.pos_encoding(self.embedding(X) * math.sqrt(self.num_hiddens)) self._attention_weights = [[None] * len(self.blks) for _ in range (2)] for i, blk in enumerate(self.blks): X, state = blk(X, state) # Kodçözücü özdikkat ağırlıkları self._attention_weights[0][ i] = blk.attention1.attention.attention_weights # Kodlayıcı-kodçözücü dikkat ağırlıkları self._attention_weights[1][ i] = blk.attention2.attention.attention_weights return self.dense(X), state @property def attention_weights(self): return self._attention_weights .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python class TransformerDecoder(d2l.AttentionDecoder): def __init__(self, vocab_size, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_hidens, num_heads, num_layers, dropout, **kwargs): super().__init__(**kwargs) self.num_hiddens = num_hiddens self.num_layers = num_layers self.embedding = tf.keras.layers.Embedding(vocab_size, num_hiddens) self.pos_encoding = d2l.PositionalEncoding(num_hiddens, dropout) self.blks = [DecoderBlock(key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_hiddens, num_heads, dropout, i) for i in range(num_layers)] self.dense = tf.keras.layers.Dense(vocab_size) def init_state(self, enc_outputs, enc_valid_lens, *args): return [enc_outputs, enc_valid_lens, [None] * self.num_layers] def call(self, X, state, **kwargs): X = self.pos_encoding(self.embedding(X) * tf.math.sqrt(tf.cast(self.num_hiddens, dtype=tf.float32)), **kwargs) self._attention_weights = [[None] * len(self.blks) for _ in range(2)] # Kodçözücüdeki 2 dikkat katmanı for i, blk in enumerate(self.blks): X, state = blk(X, state, **kwargs) # Kodçözücü özdikkat ağırlıkları self._attention_weights[0][i] = blk.attention1.attention.attention_weights # Kodlayıcı-kodçözücü dikkat ağırlıkları self._attention_weights[1][i] = blk.attention2.attention.attention_weights return self.dense(X), state @property def attention_weights(self): return self._attention_weights .. raw:: html
.. raw:: html
Eğitim ------ Dönüştürücü mimarisini takip ederek bir kodlayıcı-kodçözücü modeli oluşturalım. Burada hem dönüştürücü kodlayıcının hem de dönüştürücü kodçözücünün 4 kafalı dikkat kullanan 2 katmana sahip olduğunu belirtiyoruz. :numref:`sec_seq2seq_training` içindekine benzer şekilde, dönüştürücü modelini İngilizce-Fransızca makine çevirisi veri kümelerinde diziden diziye öğrenmeye yönelik eğitiyoruz. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python num_hiddens, num_layers, dropout, batch_size, num_steps = 32, 2, 0.1, 64, 10 lr, num_epochs, device = 0.005, 200, d2l.try_gpu() ffn_num_hiddens, num_heads = 64, 4 train_iter, src_vocab, tgt_vocab = d2l.load_data_nmt(batch_size, num_steps) encoder = TransformerEncoder( len(src_vocab), num_hiddens, ffn_num_hiddens, num_heads, num_layers, dropout) decoder = TransformerDecoder( len(tgt_vocab), num_hiddens, ffn_num_hiddens, num_heads, num_layers, dropout) net = d2l.EncoderDecoder(encoder, decoder) d2l.train_seq2seq(net, train_iter, lr, num_epochs, tgt_vocab, device) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output loss 0.031, 2339.2 tokens/sec on gpu(0) .. figure:: output_transformer_5722f1_159_1.svg .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python num_hiddens, num_layers, dropout, batch_size, num_steps = 32, 2, 0.1, 64, 10 lr, num_epochs, device = 0.005, 200, d2l.try_gpu() ffn_num_input, ffn_num_hiddens, num_heads = 32, 64, 4 key_size, query_size, value_size = 32, 32, 32 norm_shape = [32] train_iter, src_vocab, tgt_vocab = d2l.load_data_nmt(batch_size, num_steps) encoder = TransformerEncoder( len(src_vocab), key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, num_layers, dropout) decoder = TransformerDecoder( len(tgt_vocab), key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, num_layers, dropout) net = d2l.EncoderDecoder(encoder, decoder) d2l.train_seq2seq(net, train_iter, lr, num_epochs, tgt_vocab, device) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output loss 0.034, 4753.8 tokens/sec on cuda:0 .. figure:: output_transformer_5722f1_162_1.svg .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python num_hiddens, num_layers, dropout, batch_size, num_steps = 32, 2, 0.1, 64, 10 lr, num_epochs, device = 0.005, 200, d2l.try_gpu() ffn_num_hiddens, num_heads = 64, 4 key_size, query_size, value_size = 32, 32, 32 norm_shape = [2] train_iter, src_vocab, tgt_vocab = d2l.load_data_nmt(batch_size, num_steps) encoder = TransformerEncoder( len(src_vocab), key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_hiddens, num_heads, num_layers, dropout) decoder = TransformerDecoder( len(tgt_vocab), key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_hiddens, num_heads, num_layers, dropout) net = d2l.EncoderDecoder(encoder, decoder) d2l.train_seq2seq(net, train_iter, lr, num_epochs, tgt_vocab, device) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output loss 0.028, 992.7 tokens/sec on .. figure:: output_transformer_5722f1_165_1.svg .. raw:: html
.. raw:: html
Eğitimden sonra dönüştürücü modelini birkaç İngilizce cümleyi Fransızca'ya çevirmek ve BLEU puanlarını hesaplamak için kullanıyoruz. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python engs = ['go .', "i lost .", 'he\'s calm .', 'i\'m home .'] fras = ['va !', 'j\'ai perdu .', 'il est calme .', 'je suis chez moi .'] for eng, fra in zip(engs, fras): translation, dec_attention_weight_seq = d2l.predict_seq2seq( net, eng, src_vocab, tgt_vocab, num_steps, device, True) print(f'{eng} => {translation}, ', f'bleu {d2l.bleu(translation, fra, k=2):.3f}') .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output go . => va !, bleu 1.000 i lost . => j’ai perdu ., bleu 0.687 he's calm . => il a calme ., bleu 0.658 i'm home . => je suis chez moi ., bleu 1.000 .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python engs = ['go .', "i lost .", 'he\'s calm .', 'i\'m home .'] fras = ['va !', 'j\'ai perdu .', 'il est calme .', 'je suis chez moi .'] for eng, fra in zip(engs, fras): translation, dec_attention_weight_seq = d2l.predict_seq2seq( net, eng, src_vocab, tgt_vocab, num_steps, device, True) print(f'{eng} => {translation}, ', f'bleu {d2l.bleu(translation, fra, k=2):.3f}') .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output go . => va !, bleu 1.000 i lost . => j'ai perdu ., bleu 1.000 he's calm . => il est calme ., bleu 1.000 i'm home . => je suis chez moi ., bleu 1.000 .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python engs = ['go .', "i lost .", 'he\'s calm .', 'i\'m home .'] fras = ['va !', 'j\'ai perdu .', 'il est calme .', 'je suis chez moi .'] for eng, fra in zip(engs, fras): translation, dec_attention_weight_seq = d2l.predict_seq2seq( net, eng, src_vocab, tgt_vocab, num_steps, True) print(f'{eng} => {translation}, ', f'bleu {d2l.bleu(translation, fra, k=2):.3f}') .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output go . => va !, bleu 1.000 i lost . => j'ai perdu ., bleu 1.000 he's calm . => il est riche ., bleu 0.658 i'm home . => je suis chez moi qui suis chez moi qui suis, bleu 0.481 .. raw:: html
.. raw:: html
Son İngilizce cümleyi Fransızcaya çevirirken dönüştürücünün dikkat ağırlıklarını görselleştirmemize izin verin. Kodlayıcı özdikkat ağırlıklarının şekli (kodlayıcı katmanlarının sayısı, dikkat kafalarının sayısı, ``num_steps`` veya sorgu sayısı, ``num_steps`` veya anahtar değer çiftlerinin sayısı) şeklindedir. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python enc_attention_weights = np.concatenate(net.encoder.attention_weights, 0).reshape((num_layers, num_heads, -1, num_steps)) enc_attention_weights.shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output (2, 4, 10, 10) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python enc_attention_weights = torch.cat(net.encoder.attention_weights, 0).reshape((num_layers, num_heads, -1, num_steps)) enc_attention_weights.shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output torch.Size([2, 4, 10, 10]) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python enc_attention_weights = tf.reshape( tf.concat(net.encoder.attention_weights, 0), (num_layers, num_heads, -1, num_steps)) enc_attention_weights.shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output TensorShape([2, 4, 10, 10]) .. raw:: html
.. raw:: html
Özdikkat kodlayıcısında, hem sorgular hem de anahtarlar aynı girdi dizisinden gelir. Dolgu belirteçleri anlam taşımadığından, girdi dizisinin belirlenmiş geçerli uzunluğu ile, dolgu belirteçlerinin konumlarına hiçbir sorgu ilgi göstermez. Aşağıda, çoklu kafalı iki katmanın dikkat ağırlıkları satır satır gösterilmektedir. Her kafa, sorguların, anahtarların ve değerlerin ayrı bir temsil altuzaylarına dayanarak bağımsız olarak ilgi gösterir. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python d2l.show_heatmaps( enc_attention_weights, xlabel='Key positions', ylabel='Query positions', titles=['Head %d' % i for i in range(1, 5)], figsize=(7, 3.5)) .. figure:: output_transformer_5722f1_195_0.svg .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python d2l.show_heatmaps( enc_attention_weights.cpu(), xlabel='Key positions', ylabel='Query positions', titles=['Head %d' % i for i in range(1, 5)], figsize=(7, 3.5)) .. figure:: output_transformer_5722f1_198_0.svg .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python d2l.show_heatmaps( enc_attention_weights, xlabel='Key positions', ylabel='Query positions', titles=['Head %d' % i for i in range(1, 5)], figsize=(7, 3.5)) .. figure:: output_transformer_5722f1_201_0.svg .. raw:: html
.. raw:: html
Hem kodçözücü özdikkat ağırlıklarını hem de kodlayıcı-kodçözücü dikkat ağırlıklarını görselleştirmek için daha fazla veri düzenlemeye ihtiyacımız var. Örneğin, maskelenmiş dikkat ağırlıklarını sıfırla dolduruyoruz. Kodçözücü özdikkat ağırlıklarının ve kodlayıcı-kodçözücü dikkat ağırlıklarının her ikisinin de aynı sorguları olduğunu unutmayın: Dizinin başlangıç belirteci ve ardından çıktı belirteçleri. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python dec_attention_weights_2d = [np.array(head[0]).tolist() for step in dec_attention_weight_seq for attn in step for blk in attn for head in blk] dec_attention_weights_filled = np.array( pd.DataFrame(dec_attention_weights_2d).fillna(0.0).values) dec_attention_weights = dec_attention_weights_filled.reshape((-1, 2, num_layers, num_heads, num_steps)) dec_self_attention_weights, dec_inter_attention_weights = \ dec_attention_weights.transpose(1, 2, 3, 0, 4) dec_self_attention_weights.shape, dec_inter_attention_weights.shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output ((2, 4, 6, 10), (2, 4, 6, 10)) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python dec_attention_weights_2d = [head[0].tolist() for step in dec_attention_weight_seq for attn in step for blk in attn for head in blk] dec_attention_weights_filled = torch.tensor( pd.DataFrame(dec_attention_weights_2d).fillna(0.0).values) dec_attention_weights = dec_attention_weights_filled.reshape((-1, 2, num_layers, num_heads, num_steps)) dec_self_attention_weights, dec_inter_attention_weights = \ dec_attention_weights.permute(1, 2, 3, 0, 4) dec_self_attention_weights.shape, dec_inter_attention_weights.shape .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output (torch.Size([2, 4, 6, 10]), torch.Size([2, 4, 6, 10])) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python dec_attention_weights_2d = [head[0] for step in dec_attention_weight_seq for attn in step for blk in attn for head in blk] dec_attention_weights_filled = tf.convert_to_tensor( np.asarray(pd.DataFrame(dec_attention_weights_2d).fillna( 0.0).values).astype(np.float32)) dec_attention_weights = tf.reshape(dec_attention_weights_filled, shape=( -1, 2, num_layers, num_heads, num_steps)) dec_self_attention_weights, dec_inter_attention_weights = tf.transpose( dec_attention_weights, perm=(1, 2, 3, 0, 4)) print(dec_self_attention_weights.shape, dec_inter_attention_weights.shape) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output (2, 4, 10, 10) (2, 4, 10, 10) .. raw:: html
.. raw:: html
Kodçözücünün özdikkatinin otomatik bağlanım özelliği nedeniyle, hiçbir sorgu sorgu konumundan sonra anahtar/değer çiftlerine ilgi göstermez. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python # Dizi başlangıç belirtecini içermek için 1 ekle d2l.show_heatmaps( dec_self_attention_weights[:, :, :, :len(translation.split()) + 1], xlabel='Key positions', ylabel='Query positions', titles=['Head %d' % i for i in range(1, 5)], figsize=(7, 3.5)) .. figure:: output_transformer_5722f1_219_0.svg .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python # Dizi başlangıç belirtecini içermek için 1 ekle d2l.show_heatmaps( dec_self_attention_weights[:, :, :, :len(translation.split()) + 1], xlabel='Key positions', ylabel='Query positions', titles=['Head %d' % i for i in range(1, 5)], figsize=(7, 3.5)) .. figure:: output_transformer_5722f1_222_0.svg .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python # Dizi başlangıç belirtecini içermek için 1 ekle d2l.show_heatmaps( dec_self_attention_weights[:, :, :, :len(translation.split()) + 1], xlabel='Key positions', ylabel='Query positions', titles=['Head %d' % i for i in range(1, 5)], figsize=(7, 3.5)) .. figure:: output_transformer_5722f1_225_0.svg .. raw:: html
.. raw:: html
Kodlayıcının özdikkatindeki duruma benzer şekilde, girdi dizisince belirtilen geçerli uzunluğu aracılığıyla, çıktı dizisinden gelen hiçbir sorgu bu girdi dizisinden dolgu belirteçlerine ilgi göstermez. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python d2l.show_heatmaps( dec_inter_attention_weights, xlabel='Key positions', ylabel='Query positions', titles=['Head %d' % i for i in range(1, 5)], figsize=(7, 3.5)) .. figure:: output_transformer_5722f1_231_0.svg .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python d2l.show_heatmaps( dec_inter_attention_weights, xlabel='Key positions', ylabel='Query positions', titles=['Head %d' % i for i in range(1, 5)], figsize=(7, 3.5)) .. figure:: output_transformer_5722f1_234_0.svg .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python d2l.show_heatmaps( dec_inter_attention_weights, xlabel='Key positions', ylabel='Query positions', titles=['Head %d' % i for i in range(1, 5)], figsize=(7, 3.5)) .. figure:: output_transformer_5722f1_237_0.svg .. raw:: html
.. raw:: html
Dönüştürücü mimarisi başlangıçta diziden-diziye öğrenme için önerilmiş olsa da, kitapta daha sonra keşfedeceğimiz gibi, dönüştürücü kodlayıcı ya da dönüştürücü kodçözücü genellikle farklı derin öğrenme görevleri için ayrı ayrı kullanılır. Özet ---- - Dönüştürücü, kodlayıcı-kodçözücü mimarisinin bir örneğidir, ancak kodlayıcı veya kodçözücü uygulamada ayrı ayrı kullanılabilir. - Dönüştürücüde, girdi dizisini ve çıktı dizisini temsil etmek için çoklu kafalı özdikkat kullanılır, ancak kodçözücünün maskelenmiş bir sürüm aracılığıyla otomatik bağlanım özelliğini korumak zorundadır. - Hem artık bağlantılar hem de dönüştürücüdeki katman normalleştirmesi, bir çok derin modeli eğitmek için önemlidir. - Dönüştürücü modelindeki konumsal olarak ileriye besleme ağı, aynı MLP'yi kullanarak tüm dizi konumlarındaki gösterimi dönüştürür. Alıştırmalar ------------ 1. Deneylerde daha derin bir dönüştürücü eğitin. Eğitim hızını ve çeviri performansını nasıl etkiler? 2. Dönüştürücüdeki ölçeklendirilmiş nokta çarpımı dikkatini toplayıcı dikkati ile değiştirmek iyi bir fikir midir? Neden? 3. Dil modellemesi için dönüştürücü kodlayıcısını mı, kodçözücüyü mü veya her ikisini birden mi kullanmalıyız? Bu yöntem nasıl tasarlanabilir? 4. Girdi dizileri çok uzunsa dönüştürücüler için ne zorluklar olabilir? Neden? 5. Dönüştürücülerin hesaplama ve bellek verimliliğini nasıl arttırılabilir? İpucu: Tay ve ark. tarafından hazırlanan çalışmaya başvurabilirsiniz. :cite:`Tay.Dehghani.Bahri.ea.2020`. 6. CNN kullanmadan imge sınıflandırma işleri için dönüştürücü tabanlı modelleri nasıl tasarlayabiliriz? İpucu: Görüntü dönüştürücüye başvurabilirsiniz :cite:`Dosovitskiy.Beyer.Kolesnikov.ea.2021` .. raw:: html
mxnetpytorch
.. raw:: html
`Tartışmalar `__ .. raw:: html
.. raw:: html
`Tartışmalar `__ .. raw:: html
.. raw:: html