” bitiştirilmedir. "BERT girdi
dizisi" terminolojisini diğer "diziler" türlerinden sürekli olarak ayırt
edeceğiz. Örneğin, bir *BERT girdi dizisi*, bir *metin dizisi* veya iki
*metin dizisi* içerebilir.
Metin çiftlerini ayırt etmek için, öğrenilmiş bölüm gömmeleri
:math:`\mathbf{e}_A` ve :math:`\mathbf{e}_B` sırasıyla birinci dizinin
ve ikinci dizinin belirteç gömmelerine eklenir. Tek metin girdileri için
sadece :math:`\mathbf{e}_A` kullanılır.
Aşağıdaki ``get_tokens_and_segments`` girdi olarak bir veya iki cümle
alır, daha sonra BERT girdi dizisinin belirteçlerini ve bunlara karşılık
gelen bölüm kimliklerini döndürür.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
def get_tokens_and_segments(tokens_a, tokens_b=None):
"""BERT girdi dizisinin belirteçlerini ve bunların bölüm kimliklerini alın."""
tokens = [''] + tokens_a + ['']
# 0 and 1 are marking segment A and B, respectively
segments = [0] * (len(tokens_a) + 2)
if tokens_b is not None:
tokens += tokens_b + ['']
segments += [1] * (len(tokens_b) + 1)
return tokens, segments
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
def get_tokens_and_segments(tokens_a, tokens_b=None):
"""BERT girdi dizisinin belirteçlerini ve bunların bölüm kimliklerini alın."""
tokens = [''] + tokens_a + ['']
# 0 and 1 are marking segment A and B, respectively
segments = [0] * (len(tokens_a) + 2)
if tokens_b is not None:
tokens += tokens_b + ['']
segments += [1] * (len(tokens_b) + 1)
return tokens, segments
.. raw:: html
.. raw:: html
BERT, çift yönlü mimari olarak dönüştürücü kodlayıcıyı seçer.
Dönüştürücü kodlayıcısında yaygın olarak, BERT girdi dizisinin her
pozisyonuna konumsal gömme eklenir. Ancak, orijinal dönüştürücü
kodlayıcısından farklı olan BERT, *öğrenilebilen* konumsal gömme
kullanır. Özetlemek gerekirse, :numref:`fig_bert-input`, BERT girdi
dizisinin gömmelerinin, belirteç gömmelerinin, bölüm gömmelerinin ve
konum gömmelerinin toplamı olduğunu gösterir.
|BERT girdi dizisinin gömmeleri belirteç gömme, bölüm gömme ve konumsal
gömme toplamıdır.| .. _fig_bert-input:
Aşağıdaki ``BERTEncoder`` sınıfı :numref:`sec_transformer` içinde
uygulanan gibi ``TransformerEncoder`` sınıfına benzer.
``TransformerEncoder``'dan farklı olan ``BERTEncoder``, bölüm gömme ve
öğrenilebilir konumsal gömme parçaları kullanır.
.. |BERT girdi dizisinin gömmeleri belirteç gömme, bölüm gömme ve konumsal gömme toplamıdır.| image:: ../img/bert-input.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
class BERTEncoder(nn.Block):
"""BERT kodlayıcı."""
def __init__(self, vocab_size, num_hiddens, ffn_num_hiddens, num_heads,
num_layers, dropout, max_len=1000, **kwargs):
super(BERTEncoder, self).__init__(**kwargs)
self.token_embedding = nn.Embedding(vocab_size, num_hiddens)
self.segment_embedding = nn.Embedding(2, num_hiddens)
self.blks = nn.Sequential()
for _ in range(num_layers):
self.blks.add(d2l.EncoderBlock(
num_hiddens, ffn_num_hiddens, num_heads, dropout, True))
# BERT'te konumsal gömmeler öğrenilebilir, bu nedenle yeterince
# uzun bir konumsal gömme parametresi oluşturuyoruz
self.pos_embedding = self.params.get('pos_embedding',
shape=(1, max_len, num_hiddens))
def forward(self, tokens, segments, valid_lens):
# Aşağıdaki kod parçacığında `X`'in şekli değişmeden kalır:
# (parti boyutu, maksimum dizi uzunluğu, `num_hiddens`)
X = self.token_embedding(tokens) + self.segment_embedding(segments)
X = X + self.pos_embedding.data(ctx=X.ctx)[:, :X.shape[1], :]
for blk in self.blks:
X = blk(X, valid_lens)
return X
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
class BERTEncoder(nn.Module):
"""BERT kodlayıcı."""
def __init__(self, vocab_size, num_hiddens, norm_shape, ffn_num_input,
ffn_num_hiddens, num_heads, num_layers, dropout,
max_len=1000, key_size=768, query_size=768, value_size=768,
**kwargs):
super(BERTEncoder, self).__init__(**kwargs)
self.token_embedding = nn.Embedding(vocab_size, num_hiddens)
self.segment_embedding = nn.Embedding(2, num_hiddens)
self.blks = nn.Sequential()
for i in range(num_layers):
self.blks.add_module(f"{i}", d2l.EncoderBlock(
key_size, query_size, value_size, num_hiddens, norm_shape,
ffn_num_input, ffn_num_hiddens, num_heads, dropout, True))
# BERT'te konumsal gömmeler öğrenilebilir, bu nedenle yeterince
# uzun bir konumsal gömme parametresi oluşturuyoruz
self.pos_embedding = nn.Parameter(torch.randn(1, max_len,
num_hiddens))
def forward(self, tokens, segments, valid_lens):
# Aşağıdaki kod parçacığında `X`'in şekli değişmeden kalır:
# (parti boyutu, maksimum dizi uzunluğu, `num_hiddens`)
X = self.token_embedding(tokens) + self.segment_embedding(segments)
X = X + self.pos_embedding.data[:, :X.shape[1], :]
for blk in self.blks:
X = blk(X, valid_lens)
return X
.. raw:: html
.. raw:: html
Kelime dağarcığının 10000 olduğunu varsayalım. ``BERTEncoder``'in ileri
çıkarımını göstermek için, bunun bir örneğini oluşturalım ve
parametrelerini ilkleyelim.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
vocab_size, num_hiddens, ffn_num_hiddens, num_heads = 10000, 768, 1024, 4
num_layers, dropout = 2, 0.2
encoder = BERTEncoder(vocab_size, num_hiddens, ffn_num_hiddens, num_heads,
num_layers, dropout)
encoder.initialize()
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
vocab_size, num_hiddens, ffn_num_hiddens, num_heads = 10000, 768, 1024, 4
norm_shape, ffn_num_input, num_layers, dropout = [768], 768, 2, 0.2
encoder = BERTEncoder(vocab_size, num_hiddens, norm_shape, ffn_num_input,
ffn_num_hiddens, num_heads, num_layers, dropout)
.. raw:: html
.. raw:: html
``tokens``'ı, her bir belirtecin kelime dağarcığının bir indeksi olduğu,
uzunluğu 8 olan 2 BERT girdi dizisi olarak tanımlarız.
``BERTEncoder``'ın girdi belirteçleri (``tokens``) ile ileri çıkarımı,
her belirtecin, uzunluğu ``num_hiddens`` hiper parametresi tarafından
önceden tanımlanmış bir vektör tarafından temsil edildiği kodlanmış
sonucu döndürür. Bu hiper parametre genellikle dönüştürücü kodlayıcının
*gizli boyutu* (gizli birim sayısı) olarak adlandırılır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
tokens = np.random.randint(0, vocab_size, (2, 8))
segments = np.array([[0, 0, 0, 0, 1, 1, 1, 1], [0, 0, 0, 1, 1, 1, 1, 1]])
encoded_X = encoder(tokens, segments, None)
encoded_X.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(2, 8, 768)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
tokens = torch.randint(0, vocab_size, (2, 8))
segments = torch.tensor([[0, 0, 0, 0, 1, 1, 1, 1], [0, 0, 0, 1, 1, 1, 1, 1]])
encoded_X = encoder(tokens, segments, None)
encoded_X.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
torch.Size([2, 8, 768])
.. raw:: html
.. raw:: html
.. _subsec_bert_pretraining_tasks:
Ön Eğitim Görevleri
-------------------
``BERTEncoder``'ın ileri çıkarımı, girdi metninin her belirteci ve
eklenen özel “” ve “” belirteçlerinin BERT temsilini verir.
Ardından, BERT ön eğitimi için kayıp fonksiyonunu hesaplamak için bu
temsilleri kullanacağız. Ön eğitim aşağıdaki iki görevden oluşur:
Maskeli dil modelleme ve sonraki cümle tahmini.
.. _subsec_mlm:
Maskeli Dil Modelleme
~~~~~~~~~~~~~~~~~~~~~
:numref:`sec_language_model` içinde gösterildiği gibi, bir dil modeli,
sol tarafındaki bağlamı kullanarak bir belirteci öngörür. Her belirteci
temsil ederken bağlamı iki yönlü olarak kodlamak için BERT, belirteçleri
rastgele maskeler ve maskelenmiş belirteçleri öz gözetimli bir şekilde
tahmin etmek için çift yönlü bağlamdaki belirteçleri kullanır. Bu görev
*maskeli dil modeli* olarak adlandırılır.
Bu ön eğitim görevinde, belirteçlerin %15'i tahmin için maskelenmiş
belirteçler olarak rastgele seçilecektir. Etiketini kullanarak hile
yapmadan maskelenmiş bir belirteci tahmin etmek için, basit bir
yaklaşım, belirteci her zaman BERT girdi dizisinde özel bir “”
belirteci ile değiştirmektir. Bununla birlikte, yapay özel belirteç
“” asla ince ayarda görünmeyecektir. Ön eğitim ve ince ayar
arasında böyle bir uyuşmazlığı önlemek için, eğer bir belirteç tahmin
için maskelenmişse (örneğin, “harika” maskelenecek ve “bu film harika”
olarak tahmin edilmek üzere seçilir), girdide şu şekilde değiştirilir:
- Zamanın %80'i için özel bir “” belirteci ile (örneğin, “bu film
harika”, “bu film “ olur);
- Zamanın %10'u için rastgele bir belirteç (örneğin, “bu film harika”
“bu film içki” olur);
- Zamanın %10'unda değişmeyen etiket belirteci (örneğin, “bu film
harika” “bu film harika” kalır).
%15'lik zamanın %10'u için rastgele bir belirteç eklendiğini unutmayın.
Bu ara sıra olan gürültü, BERT'i, çift yönlü bağlam kodlamasında
maskelenmiş belirtece (özellikle etiket belirteci değişmeden kaldığında)
karşı daha az yanlı olmasını teşvik eder.
BERT ön eğitiminin maskelenmiş dil modeli görevinde maskeli belirteçleri
tahmin etmek için aşağıdaki ``MaskLM`` sınıfını uyguluyoruz. Tahmin, tek
gizli katmanlı bir MLP kullanır (``self.mlp``). İleri çıkarımda, iki
girdi gerekir: ``BERTEncoder``'ının kodlanmış sonucu ve tahmin için
belirteç konumları. Çıktı, bu pozisyonlardaki tahmin sonuçlarıdır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
class MaskLM(nn.Block):
"""BERT'in maskeli dil modeli görevi."""
def __init__(self, vocab_size, num_hiddens, **kwargs):
super(MaskLM, self).__init__(**kwargs)
self.mlp = nn.Sequential()
self.mlp.add(
nn.Dense(num_hiddens, flatten=False, activation='relu'))
self.mlp.add(nn.LayerNorm())
self.mlp.add(nn.Dense(vocab_size, flatten=False))
def forward(self, X, pred_positions):
num_pred_positions = pred_positions.shape[1]
pred_positions = pred_positions.reshape(-1)
batch_size = X.shape[0]
batch_idx = np.arange(0, batch_size)
# Varsayalım ki `batch_size` = 2, `num_pred_positions` = 3 olsun,
# o halde `batch_idx` `np.array([0, 0, 0, 1, 1, 1])` olur
batch_idx = np.repeat(batch_idx, num_pred_positions)
masked_X = X[batch_idx, pred_positions]
masked_X = masked_X.reshape((batch_size, num_pred_positions, -1))
mlm_Y_hat = self.mlp(masked_X)
return mlm_Y_hat
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
class MaskLM(nn.Module):
"""BERT'in maskeli dil modeli görevi."""
def __init__(self, vocab_size, num_hiddens, num_inputs=768, **kwargs):
super(MaskLM, self).__init__(**kwargs)
self.mlp = nn.Sequential(nn.Linear(num_inputs, num_hiddens),
nn.ReLU(),
nn.LayerNorm(num_hiddens),
nn.Linear(num_hiddens, vocab_size))
def forward(self, X, pred_positions):
num_pred_positions = pred_positions.shape[1]
pred_positions = pred_positions.reshape(-1)
batch_size = X.shape[0]
batch_idx = torch.arange(0, batch_size)
# Varsayalım ki `batch_size` = 2, `num_pred_positions` = 3 olsun,
# o halde `batch_idx` `np.array([0, 0, 0, 1, 1, 1])` olur
batch_idx = torch.repeat_interleave(batch_idx, num_pred_positions)
masked_X = X[batch_idx, pred_positions]
masked_X = masked_X.reshape((batch_size, num_pred_positions, -1))
mlm_Y_hat = self.mlp(masked_X)
return mlm_Y_hat
.. raw:: html
.. raw:: html
``MaskLM``'in ileri çıkarımını göstermek için, ``mlm`` örneğini
oluşturup ilkleriz. ``BERTEncoder``'in ileri çıkarımından
``encoded_X``'in 2 BERT girdi dizisini temsil ettiğini hatırlayın.
``mlm_positions``'i ``encoded_X`` BERT girdi dizisinde tahmin etmek için
3 endeksli olarak tanımlarız. ``mlm``'nin ileri çıkarımı,
``encoded_X``'in tüm ``mlm_positions`` maskeli konumlarında
``mlm_Y_hat`` tahmin sonuçlarını döndürür. Her tahmin için, sonucun
boyutu kelime dağarcığına eşittir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
mlm = MaskLM(vocab_size, num_hiddens)
mlm.initialize()
mlm_positions = np.array([[1, 5, 2], [6, 1, 5]])
mlm_Y_hat = mlm(encoded_X, mlm_positions)
mlm_Y_hat.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(2, 3, 10000)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
mlm = MaskLM(vocab_size, num_hiddens)
mlm_positions = torch.tensor([[1, 5, 2], [6, 1, 5]])
mlm_Y_hat = mlm(encoded_X, mlm_positions)
mlm_Y_hat.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
torch.Size([2, 3, 10000])
.. raw:: html
.. raw:: html
Maskeler altında tahmin edilen ``mlm_Y_hat`` belirteçlerinin ``mlm_Y``
gerçek referans değer etiketleri ile, BERT ön eğitiminde maskeli dil
modeli görevinin çapraz entropi kaybını hesaplayabiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
mlm_Y = np.array([[7, 8, 9], [10, 20, 30]])
loss = gluon.loss.SoftmaxCrossEntropyLoss()
mlm_l = loss(mlm_Y_hat.reshape((-1, vocab_size)), mlm_Y.reshape(-1))
mlm_l.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(6,)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
mlm_Y = torch.tensor([[7, 8, 9], [10, 20, 30]])
loss = nn.CrossEntropyLoss(reduction='none')
mlm_l = loss(mlm_Y_hat.reshape((-1, vocab_size)), mlm_Y.reshape(-1))
mlm_l.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
torch.Size([6])
.. raw:: html
.. raw:: html
.. _subsec_nsp:
Sonraki Cümle Tahmini
~~~~~~~~~~~~~~~~~~~~~
Maskelenmiş dil modellemesi sözcükleri temsil etmek için çift yönlü
bağlamı kodlayabilse de, metin çiftleri arasındaki mantıksal ilişkiyi
açıkça modellemez. BERT, iki metin dizisi arasındaki ilişkiyi anlamaya
yardımcı olmak için, ön eğitimde ikili sınıflandırma görevi, *sonraki
cümle tahmini* olarak değerlendirir. Ön eğitim için cümle çiftleri
oluştururken, çoğu zaman "Doğru" (True) etiketi ile ardışık cümlelerdir;
zamanın diğer yarısı için ikinci cümle rastgele "Yanlış" (False) etiketi
ile külliyattan örneklenir.
Aşağıdaki ``NextSentencePred`` sınıfı, ikinci cümlenin BERT girdi
dizisindeki ilk cümlenin bir sonraki cümle olup olmadığını tahmin etmek
için tek gizli katmanlı bir MLP kullanır. Dönüştürücü kodlayıcısındaki
öz-dikkat nedeniyle, “” özel belirtecinin BERT temsili, her iki
cümleyi de girdiden kodlar. Bu nedenle, MLP sınıflandırıcısının çıktı
katmanı (``self.output``) girdi olarak ``X``'i alır, burada ``X``,
girdisi kodlanmış “” belirteci olan MLP gizli katmanının
çıktısıdır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
class NextSentencePred(nn.Block):
"""BERT'in sonraki cümle tahmini görevi."""
def __init__(self, **kwargs):
super(NextSentencePred, self).__init__(**kwargs)
self.output = nn.Dense(2)
def forward(self, X):
# `X` shape: (batch size, `num_hiddens`)
return self.output(X)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
class NextSentencePred(nn.Module):
"""BERT'in sonraki cümle tahmini görevi."""
def __init__(self, num_inputs, **kwargs):
super(NextSentencePred, self).__init__(**kwargs)
self.output = nn.Linear(num_inputs, 2)
def forward(self, X):
# `X` shape: (batch size, `num_hiddens`)
return self.output(X)
.. raw:: html
.. raw:: html
Bir ``NextSentencePred`` örneğinin ileri çıkarımının her BERT girdi
dizisi için ikili tahminleri döndürdüğünü görebiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
nsp = NextSentencePred()
nsp.initialize()
nsp_Y_hat = nsp(encoded_X)
nsp_Y_hat.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(2, 2)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
# PyTorch by default won't flatten the tensor as seen in mxnet where, if
# flatten=True, all but the first axis of input data are collapsed together
encoded_X = torch.flatten(encoded_X, start_dim=1)
# input_shape for NSP: (batch size, `num_hiddens`)
nsp = NextSentencePred(encoded_X.shape[-1])
nsp_Y_hat = nsp(encoded_X)
nsp_Y_hat.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
torch.Size([2, 2])
.. raw:: html
.. raw:: html
2 tane ikili sınıflandırmanın çapraz entropi kaybı da hesaplanabilir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
nsp_y = np.array([0, 1])
nsp_l = loss(nsp_Y_hat, nsp_y)
nsp_l.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(2,)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
nsp_y = torch.tensor([0, 1])
nsp_l = loss(nsp_Y_hat, nsp_y)
nsp_l.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
torch.Size([2])
.. raw:: html
.. raw:: html
Yukarıda bahsedilen ön eğitim görevlerindeki tüm etiketlerin elle
etiketleme çabası olmaksızın ön eğitim külliyattından zahmetsiz olarak
elde edilebileceği dikkat çekicidir. Orijinal BERT, BookCorpus
:cite:`Zhu.Kiros.Zemel.ea.2015` ve İngilizce Wikipedia'nin
bitiştirilmesi üzerinde ön eğitilmiştir. Bu iki metin külliyatı çok
büyüktür: Sırasıyla 800 milyon kelime ve 2.5 milyar kelime vardır.
Her Şeyleri Bir Araya Getirmek
------------------------------
BERT ön eğitimi yaparken, nihai kayıp fonksiyonu hem maskeli dil
modelleme hem de sonraki cümle tahmini için kayıp fonksiyonlarının
doğrusal bir kombinasyonudur. Artık ``BERTModel`` sınıfını
``BERTEncoder``, ``MaskLM`` ve ``NextSentencePred``'in üç sınıfını
örnekleyerek tanımlayabiliriz. İleri çıkarım kodlanmış BERT temsilleri
``encoded_X``, maskeli dil modelleme tahminleri ``mlm_Y_hat`` ve sonraki
cümle tahminleri ``nsp_Y_hat`` döndürür.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
class BERTModel(nn.Block):
"""BERT modeli."""
def __init__(self, vocab_size, num_hiddens, ffn_num_hiddens, num_heads,
num_layers, dropout, max_len=1000):
super(BERTModel, self).__init__()
self.encoder = BERTEncoder(vocab_size, num_hiddens, ffn_num_hiddens,
num_heads, num_layers, dropout, max_len)
self.hidden = nn.Dense(num_hiddens, activation='tanh')
self.mlm = MaskLM(vocab_size, num_hiddens)
self.nsp = NextSentencePred()
def forward(self, tokens, segments, valid_lens=None, pred_positions=None):
encoded_X = self.encoder(tokens, segments, valid_lens)
if pred_positions is not None:
mlm_Y_hat = self.mlm(encoded_X, pred_positions)
else:
mlm_Y_hat = None
# Bir sonraki cümle tahmini için MLP sınıflandırıcısının gizli katmanı.
# 0, '' belirtecinin dizinidir
nsp_Y_hat = self.nsp(self.hidden(encoded_X[:, 0, :]))
return encoded_X, mlm_Y_hat, nsp_Y_hat
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
#@save
class BERTModel(nn.Module):
"""BERT modeli."""
def __init__(self, vocab_size, num_hiddens, norm_shape, ffn_num_input,
ffn_num_hiddens, num_heads, num_layers, dropout,
max_len=1000, key_size=768, query_size=768, value_size=768,
hid_in_features=768, mlm_in_features=768,
nsp_in_features=768):
super(BERTModel, self).__init__()
self.encoder = BERTEncoder(vocab_size, num_hiddens, norm_shape,
ffn_num_input, ffn_num_hiddens, num_heads, num_layers,
dropout, max_len=max_len, key_size=key_size,
query_size=query_size, value_size=value_size)
self.hidden = nn.Sequential(nn.Linear(hid_in_features, num_hiddens),
nn.Tanh())
self.mlm = MaskLM(vocab_size, num_hiddens, mlm_in_features)
self.nsp = NextSentencePred(nsp_in_features)
def forward(self, tokens, segments, valid_lens=None, pred_positions=None):
encoded_X = self.encoder(tokens, segments, valid_lens)
if pred_positions is not None:
mlm_Y_hat = self.mlm(encoded_X, pred_positions)
else:
mlm_Y_hat = None
# Bir sonraki cümle tahmini için MLP sınıflandırıcısının gizli katmanı.
# 0, '' belirtecinin dizinidir
nsp_Y_hat = self.nsp(self.hidden(encoded_X[:, 0, :]))
return encoded_X, mlm_Y_hat, nsp_Y_hat
.. raw:: html
.. raw:: html
Özet
----
- Word2vec ve GloVe gibi sözcük gömme modelleri bağlam bağımsızdır.
Aynı önceden eğitilmiş vektörü, kelimenin bağlamından bağımsız olarak
(varsa) aynı sözcüğe atar. Doğal dillerde çokanlamlılık veya karmaşık
anlamları iyi ele almaları zordur.
- ELMo ve GPT gibi bağlam duyarlı sözcük temsilleri için, sözcüklerin
temsilleri bağlamlarına bağlıdır.
- ELMo bağlamı iki yönlü olarak kodlar ancak göreve özgü mimarileri
kullanır (ancak, her doğal dil işleme görevi için belirli bir
mimariyi oluşturmak pratik olarak aşikar değildir); GPT göreve
özgüdür ancak bağlamı soldan sağa kodlar.
- BERT her iki dünyanın en iyilerini birleştirir: Bağlamı çift yönlü
olarak kodlar ve bir çok çeşitli doğal dil işleme görevleri için
asgari mimari değişiklikleri gerektirir.
- BERT girdi dizisinin gömmeleri belirteç gömme, bölüm gömme ve
konumsal gömme toplamıdır.
- BERT ön eğitim iki görevden oluşur: Maskeli dil modelleme ve sonraki
cümle tahmini. Birincisi, sözcükleri temsil etmek için çift yönlü
bağlamı kodlayabilirken, ikincisi ise metin çiftleri arasındaki
mantıksal ilişkiyi açıkça modeller.
Alıştırmalar
------------
1. BERT neden başarılıdır?
2. Diğer tüm şeyler eşit olunca, maskeli bir dil modeli, soldan sağa dil
modelinden daha fazla veya daha az ön eğitim adımı gerektirir mi?
Neden?
3. BERT'in orijinal uygulamasında ``BERTEncoder`` içindeki
(``d2l.EncoderBlock`` aracılığıyla) konumsal ileri besleme ağı da ve
``MaskLM``'deki tam bağlı katman da Gauss hata doğrusal birimini
(GELU) :cite:`Hendrycks.Gimpel.2016` etkinleştirme işlevi olarak
kullanır. GELU ve ReLU arasındaki farkı araştırın.
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html