16.2. Sentiment Analysis: Using Recurrent Neural Networks
Like word similarity and analogy tasks, we can also apply pretrained word vectors to sentiment analysis. Since the IMDb review dataset in Section 16.1 is not very big, using text representations that were pretrained on large-scale corpora may reduce overfitting of the model. As a specific example illustrated in Fig. 16.2.1, we will represent each token using the pretrained GloVe model, and feed these token representations into a multilayer bidirectional RNN to obtain the text sequence representation, which will be transformed into sentiment analysis outputs (Maas et al., 2011). For the same downstream application, we will consider a different architectural choice later.
단어 유사성 및 유추 작업과 마찬가지로 사전 훈련된 단어 벡터를 감정 분석에 적용할 수도 있습니다. 섹션 16.1의 IMDb 검토 데이터 세트는 그다지 크지 않기 때문에 대규모 말뭉치에 대해 사전 훈련된 텍스트 표현을 사용하면 모델의 과적합을 줄일 수 있습니다. 그림 16.2.1에 설명된 구체적인 예와 같이 사전 훈련된 GloVe 모델을 사용하여 각 토큰을 표현하고 이러한 토큰 표현을 다층 양방향 RNN에 공급하여 감정 분석 출력으로 변환될 텍스트 시퀀스 표현을 얻습니다(Maas 등, 2011). 동일한 다운스트림 애플리케이션에 대해 나중에 다른 아키텍처 선택을 고려할 것입니다.
import torch
from torch import nn
from d2l import torch as d2l
batch_size = 64
train_iter, test_iter, vocab = d2l.load_data_imdb(batch_size)
16.2.1. Representing Single Text with RNNs
In text classifications tasks, such as sentiment analysis, a varying-length text sequence will be transformed into fixed-length categories. In the following BiRNN class, while each token of a text sequence gets its individual pretrained GloVe representation via the embedding layer (self.embedding), the entire sequence is encoded by a bidirectional RNN (self.encoder). More concretely, the hidden states (at the last layer) of the bidirectional LSTM at both the initial and final time steps are concatenated as the representation of the text sequence. This single text representation is then transformed into output categories by a fully connected layer (self.decoder) with two outputs (“positive” and “negative”).
감정 분석과 같은 텍스트 분류 작업에서는 다양한 길이의 텍스트 시퀀스가 고정 길이 범주로 변환됩니다. 다음 BiRNN 클래스에서 텍스트 시퀀스의 각 토큰은 임베딩 레이어(self.embedding)를 통해 사전 훈련된 개별 GloVe 표현을 가져오지만 전체 시퀀스는 양방향 RNN(self.encoder)으로 인코딩됩니다. 보다 구체적으로, 초기 및 최종 시간 단계 모두에서 양방향 LSTM의 숨겨진 상태(마지막 레이어)는 텍스트 시퀀스의 표현으로 연결됩니다. 이 단일 텍스트 표현은 두 개의 출력("양수" 및 "음수")이 있는 완전히 연결된 레이어(self.decoder)에 의해 출력 범주로 변환됩니다.
LSTM 이란?
LSTM stands for "Long Short-Term Memory," which is a type of recurrent neural network (RNN) architecture designed to handle sequences and patterns in data. RNNs are a class of artificial neural networks that are well-suited for tasks involving sequential data, such as time series, natural language processing, and more.
LSTM은 "Long Short-Term Memory"의 약자로, 데이터의 시퀀스와 패턴을 다루기 위해 고안된 순환 신경망(RNN) 아키텍처입니다. RNN은 시계열 데이터, 자연어 처리 등과 같은 순차적인 데이터를 다루는 데 적합한 인공 신경망의 한 유형입니다.
The key challenge LSTM addresses is the vanishing gradient problem, which can occur when training traditional RNNs. The vanishing gradient problem makes it difficult for RNNs to capture long-range dependencies in sequential data. LSTM networks overcome this limitation by introducing specialized memory cells and gating mechanisms that allow them to learn and store information for longer periods of time.
LSTM이 다루는 주요 문제는 기존의 RNN에서 나타나는 사라지는 그래디언트 문제(vanishing gradient problem)입니다. 사라지는 그래디언트 문제는 전통적인 RNN이 순차 데이터의 장기적인 의존성을 잡아내기 어렵게 만듭니다. LSTM 네트워크는 특수한 메모리 셀과 게이팅 메커니즘을 도입하여 더 오래된 시간 동안 정보를 학습하고 저장할 수 있도록 합니다.
LSTM networks consist of different components that work together to process sequences of data:
LSTM 네트워크는 데이터 시퀀스를 처리하기 위해 함께 동작하는 여러 구성 요소로 구성됩니다:
- Cell State: This is the "memory" of the LSTM. Information can be added to or removed from the cell state using various gates.
셀 상태(Cell State): 이것은 LSTM의 "메모리"입니다. 다양한 게이트를 사용하여 셀 상태에 정보를 추가하거나 제거할 수 있습니다. - Input Gate: Determines what information from the current input should be added to the cell state.
입력 게이트(Input Gate): 현재 입력에서 어떤 정보를 셀 상태에 추가해야 할지 결정합니다. - Forget Gate: Decides what information from the cell state should be removed or forgotten.
망각 게이트(Forget Gate): 셀 상태에서 어떤 정보를 제거하거나 잊어야 할지 결정합니다. - Output Gate: Determines what information from the cell state should be output based on the current input and the past memory.
출력 게이트(Output Gate): 현재 입력과 이전 메모리를 기반으로 셀 상태에서 어떤 정보를 출력해야 할지 결정합니다.
LSTM networks excel in capturing and maintaining dependencies in sequences, making them highly effective for tasks like language modeling, machine translation, sentiment analysis, speech recognition, and more. They are capable of learning both short-term and long-term dependencies, which makes them particularly suitable for handling sequences with varying time lags between important events.
LSTM 네트워크는 시퀀스의 의존성을 캡처하고 유지하는 데 능숙하며, 언어 모델링, 기계 번역, 감성 분석, 음성 인식 등과 같은 작업에서 뛰어난 성과를 내놓습니다. LSTM은 단기적인 의존성과 장기적인 의존성을 모두 학습할 수 있어, 중요한 이벤트 사이의 다양한 시간 간격을 가진 시퀀스를 처리하는 데 특히 적합합니다.
In summary, LSTM (Long Short-Term Memory) is a type of recurrent neural network architecture that addresses the vanishing gradient problem and excels in modeling sequential data by utilizing memory cells and gating mechanisms.
요약하면, LSTM(Long Short-Term Memory)은 사라지는 그래디언트 문제를 해결하고 메모리 셀과 게이팅 메커니즘을 활용하여 순차적인 데이터를 모델링하는 순환 신경망 아키텍처입니다.
**아래 코드가 핵심임
class BiRNN(nn.Module):
def __init__(self, vocab_size, embed_size, num_hiddens,
num_layers, **kwargs):
super(BiRNN, self).__init__(**kwargs)
self.embedding = nn.Embedding(vocab_size, embed_size)
# Set `bidirectional` to True to get a bidirectional RNN
self.encoder = nn.LSTM(embed_size, num_hiddens, num_layers=num_layers,
bidirectional=True)
self.decoder = nn.Linear(4 * num_hiddens, 2)
def forward(self, inputs):
# The shape of `inputs` is (batch size, no. of time steps). Because
# LSTM requires its input's first dimension to be the temporal
# dimension, the input is transposed before obtaining token
# representations. The output shape is (no. of time steps, batch size,
# word vector dimension)
embeddings = self.embedding(inputs.T)
self.encoder.flatten_parameters()
# Returns hidden states of the last hidden layer at different time
# steps. The shape of `outputs` is (no. of time steps, batch size,
# 2 * no. of hidden units)
outputs, _ = self.encoder(embeddings)
# Concatenate the hidden states at the initial and final time steps as
# the input of the fully connected layer. Its shape is (batch size,
# 4 * no. of hidden units)
encoding = torch.cat((outputs[0], outputs[-1]), dim=1)
outs = self.decoder(encoding)
return outs
이 코드는 양방향 LSTM 네트워크를 정의하는 파이토치 모듈(nn.Module)입니다. 코드의 작동 방식을 단계별로 설명하겠습니다.
- 클래스 정의와 초기화(__init__ 메서드):
- BiRNN 클래스는 nn.Module 클래스를 상속하여 정의됩니다.
- 클래스의 생성자(__init__)에서는 네트워크의 구조와 파라미터를 설정합니다.
- vocab_size, embed_size, num_hiddens, num_layers 등의 인자를 받아 네트워크를 초기화합니다.
- 네트워크 구조 설정:
- nn.Embedding 층을 사용하여 임베딩을 정의합니다. vocab_size와 embed_size는 어휘 사전 크기와 임베딩 차원을 의미합니다.
- nn.LSTM 층을 사용하여 양방향 LSTM을 정의합니다. num_hiddens는 은닉 유닛의 개수, num_layers는 LSTM 층의 층 수를 의미합니다.
- nn.Linear 층을 사용하여 완전 연결층을 정의합니다. 입력 차원은 4 * num_hiddens로 설정되며, 출력 차원은 2로 설정됩니다.
- forward 메서드:
- 입력 데이터 inputs를 받아 모델을 통해 결과를 반환하는 forward 메서드를 정의합니다.
- 입력 데이터를 임베딩하고 양방향 LSTM에 통과시키는 작업을 수행합니다.
- 초기와 최종 시간 단계에서의 은닉 상태를 연결한 결과를 완전 연결층에 통과시켜 최종 출력을 얻습니다.
이 코드는 양방향 LSTM 네트워크를 정의하고 입력 데이터를 처리하여 출력을 생성하는 기능을 가진 파이토치 모듈을 생성합니다.
Let’s construct a bidirectional RNN with two hidden layers to represent single text for sentiment analysis.
감정 분석을 위한 단일 텍스트를 나타내기 위해 두 개의 숨겨진 레이어가 있는 양방향 RNN을 구성해 보겠습니다.
embed_size, num_hiddens, num_layers, devices = 100, 100, 2, d2l.try_all_gpus()
net = BiRNN(len(vocab), embed_size, num_hiddens, num_layers)
def init_weights(module):
if type(module) == nn.Linear:
nn.init.xavier_uniform_(module.weight)
if type(module) == nn.LSTM:
for param in module._flat_weights_names:
if "weight" in param:
nn.init.xavier_uniform_(module._parameters[param])
net.apply(init_weights);
이 코드는 모델의 가중치를 초기화하는 과정을 수행하는 파이토치 코드입니다. 코드의 작동 방식을 단계별로 설명하겠습니다.
- 하이퍼파라미터 설정:
- embed_size, num_hiddens, num_layers는 모델의 임베딩 차원, 은닉 유닛 수, LSTM 층 수를 나타내는 값입니다.
- d2l.try_all_gpus()는 사용 가능한 모든 GPU 디바이스를 가져옵니다.
- 모델 생성:
- BiRNN 클래스를 사용하여 net 모델을 생성합니다.
- len(vocab)는 어휘 사전의 크기를 나타내며, embed_size, num_hiddens, num_layers는 앞서 설정한 하이퍼파라미터입니다.
- 가중치 초기화 함수 정의:
- init_weights 함수는 모델의 가중치를 초기화하는 역할을 합니다.
- nn.Linear 타입의 층의 가중치를 세팅하는 부분과 nn.LSTM 타입의 층의 가중치를 세팅하는 부분으로 구성됩니다.
- 가중치 초기화 적용:
- net.apply(init_weights)는 net 모델에 init_weights 함수를 적용하여 가중치 초기화를 수행합니다.
즉, 이 코드는 먼저 모델을 정의하고, 그 모델의 가중치를 초기화하는 함수를 정의한 후, 해당 함수를 모델에 적용하여 모델의 가중치를 초기화하는 작업을 수행합니다. 초기화된 가중치는 모델 학습 전에 모델 파라미터를 초기화하는데 사용됩니다.
[Pytorch] 파이토치 가중치 초기화 방법(Xavier, He) (tistory.com)
16.2.2. Loading Pretrained Word Vectors
Below we load the pretrained 100-dimensional (needs to be consistent with embed_size) GloVe embeddings for tokens in the vocabulary.
아래에서는 어휘의 토큰에 대해 사전 훈련된 100차원(embed_size와 일치해야 함) GloVe 임베딩을 로드합니다.
glove_embedding = d2l.TokenEmbedding('glove.6b.100d')
이 코드는 GloVe(차원 크기: 100) 사전 훈련된 임베딩을 불러오는 작업을 수행합니다. 코드의 작동 방식을 설명하겠습니다.
- d2l.TokenEmbedding('glove.6b.100d'):
- d2l.TokenEmbedding은 토큰 임베딩을 다루는 도구입니다.
- 'glove.6b.100d'는 GloVe 임베딩의 파일 이름을 나타냅니다.
- 이 파일 이름은 6억 개의 토큰으로 구성된 GloVe 데이터셋을 사용하며, 각 임베딩은 100차원으로 표현됩니다.
이 코드는 GloVe 사전 훈련된 임베딩을 불러와 glove_embedding 객체에 저장하는 작업을 수행합니다. 이 임베딩은 텍스트 데이터를 임베딩 벡터로 변환하는 데 사용될 수 있습니다.
Print the shape of the vectors for all the tokens in the vocabulary.
어휘의 모든 토큰에 대한 벡터의 모양을 인쇄합니다.
embeds = glove_embedding[vocab.idx_to_token]
embeds.shape
이 코드는 어휘의 토큰에 해당하는 GloVe 임베딩을 가져오고 해당 임베딩의 형태(shape)를 확인하는 작업을 수행합니다. 코드의 작동 방식을 설명하겠습니다.
- glove_embedding[vocab.idx_to_token]:
- vocab.idx_to_token은 어휘 사전의 인덱스를 토큰으로 매핑한 딕셔너리입니다.
- glove_embedding은 GloVe 임베딩 객체를 나타내며, [vocab.idx_to_token]은 어휘의 각 토큰에 해당하는 GloVe 임베딩을 선택합니다.
- 이 작업을 통해 어휘 내 모든 토큰의 GloVe 임베딩을 가져옵니다.
- embeds.shape:
- embeds는 선택된 GloVe 임베딩들로 이루어진 텐서입니다.
- .shape는 해당 텐서의 형태(shape)를 확인하는 연산입니다.
- embeds.shape는 GloVe 임베딩 텐서의 형태를 출력합니다.
즉, 이 코드는 어휘 내의 각 토큰에 해당하는 GloVe 임베딩을 가져와 텐서 embeds에 저장하고, 이 텐서의 형태를 출력하여 임베딩 차원 정보를 확인하는 작업을 수행합니다.
torch.Size([49346, 100])
We use these pretrained word vectors to represent tokens in the reviews and will not update these vectors during training.
우리는 사전 훈련된 단어 벡터를 사용하여 리뷰에서 토큰을 나타내며 훈련 중에는 이러한 벡터를 업데이트하지 않습니다.
net.embedding.weight.data.copy_(embeds)
net.embedding.weight.requires_grad = False
이 코드는 뉴럴 네트워크의 임베딩 층에 미리 훈련된 임베딩 값을 복사하고, 해당 임베딩 가중치의 역전파를 막는 작업을 수행합니다. 코드의 작동 방식을 설명하겠습니다.
- net.embedding.weight.data.copy_(embeds):
- net은 이미 정의된 뉴럴 네트워크 모델을 가리킵니다.
- embedding.weight는 뉴럴 네트워크 내의 임베딩 층의 가중치를 나타냅니다.
- .data는 가중치 텐서 자체를 나타냅니다.
- .copy_(embeds)는 embeds 텐서의 값을 가중치 텐서로 복사합니다.
- 이 작업을 통해 미리 훈련된 임베딩 값을 모델의 임베딩 가중치에 복사합니다.
- net.embedding.weight.requires_grad = False:
- requires_grad는 파라미터의 역전파 여부를 제어하는 플래그입니다.
- net.embedding.weight.requires_grad를 False로 설정하여 해당 임베딩 가중치의 역전파를 막습니다.
- 이는 미리 훈련된 임베딩 값을 고정하고 역전파 시 가중치 업데이트를 방지하는 데 사용됩니다.
즉, 이 코드는 뉴럴 네트워크 모델의 임베딩 층에 미리 훈련된 임베딩 값을 복사하고, 해당 가중치의 역전파를 막아 가중치가 고정되도록 설정하는 작업을 수행합니다. 이는 사전 훈련된 임베딩을 사용하여 모델을 초기화하고, 이후 임베딩 가중치를 업데이트하지 않는 용도로 사용될 수 있습니다.
16.2.3. Training and Evaluating the Model
Now we can train the bidirectional RNN for sentiment analysis.
이제 감정 분석을 위해 양방향 RNN을 훈련할 수 있습니다.
lr, num_epochs = 0.01, 5
trainer = torch.optim.Adam(net.parameters(), lr=lr)
loss = nn.CrossEntropyLoss(reduction="none")
d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs, devices)
이 코드는 모델의 학습을 설정하고 학습을 실행하는 작업을 수행하는 파이토치 코드입니다. 코드의 작동 방식을 설명하겠습니다.
- 학습 관련 하이퍼파라미터 설정:
- lr은 학습률(learning rate)을 나타냅니다.
- num_epochs는 학습 에포크(epoch)의 수를 나타냅니다.
- 옵티마이저 설정:
- torch.optim.Adam은 Adam 옵티마이저를 생성하는 역할을 합니다.
- net.parameters()는 모델 내의 학습 가능한 파라미터들을 반환합니다.
- lr=lr로 학습률을 설정하여 옵티마이저를 초기화합니다.
- 손실 함수 설정:
- nn.CrossEntropyLoss(reduction="none")은 교차 엔트로피 손실 함수를 생성합니다.
- reduction="none"은 손실 값을 개별 데이터 포인트별로 계산하도록 설정합니다.
- 학습 실행:
- d2l.train_ch13()은 모델을 학습하는 함수입니다. 해당 함수에 학습에 필요한 정보를 전달하여 학습을 실행합니다.
- net: 학습할 모델
- train_iter: 훈련 데이터 이터레이터
- test_iter: 테스트 데이터 이터레이터
- loss: 사용할 손실 함수
- trainer: 사용할 옵티마이저
- num_epochs: 학습 에포크 수
- devices: 사용할 디바이스(GPU) 정보
즉, 이 코드는 하이퍼파라미터, 옵티마이저, 손실 함수를 설정하고 지정된 에포크 수 동안 모델을 학습하는 작업을 수행합니다. d2l.train_ch13() 함수는 실제로 학습을 진행하고 훈련 및 검증 데이터에 대한 손실과 정확도를 반환합니다.
loss 0.277, train acc 0.884, test acc 0.861
2608.4 examples/sec on [device(type='cuda', index=0), device(type='cuda', index=1)]
We define the following function to predict the sentiment of a text sequence using the trained model net.
훈련된 모델 네트를 사용하여 텍스트 시퀀스의 감정을 예측하기 위해 다음 함수를 정의합니다.
#@save
def predict_sentiment(net, vocab, sequence):
"""Predict the sentiment of a text sequence."""
sequence = torch.tensor(vocab[sequence.split()], device=d2l.try_gpu())
label = torch.argmax(net(sequence.reshape(1, -1)), dim=1)
return 'positive' if label == 1 else 'negative'
이 코드는 텍스트 시퀀스의 감정(긍정 또는 부정)을 예측하는 함수를 정의하는 파이토치 코드입니다. 코드의 작동 방식을 설명하겠습니다.
- 함수 정의:
- predict_sentiment 함수는 뉴럴 네트워크 모델, 어휘 사전, 텍스트 시퀀스를 입력으로 받아 감정을 예측하는 역할을 합니다.
- 텍스트 시퀀스 전처리:
- vocab[sequence.split()]는 입력된 텍스트 시퀀스를 공백으로 분할하여 어휘 사전의 토큰 인덱스들로 변환합니다.
- torch.tensor로 변환하고, device=d2l.try_gpu()로 텐서를 GPU로 전송합니다.
- 감정 예측:
- net(sequence.reshape(1, -1))는 모델에 텍스트 시퀀스를 전달하여 예측 결과를 얻습니다.
- torch.argmax로 가장 높은 예측 확률을 가진 클래스의 인덱스를 선택합니다.
- label은 예측된 레이블을 나타내는 텐서입니다.
- 반환:
- label == 1인 경우 'positive', 그렇지 않은 경우 'negative'로 감정을 예측합니다.
- 이 예측 결과를 문자열로 반환합니다.
즉, 이 코드는 뉴럴 네트워크 모델과 어휘 사전을 사용하여 입력된 텍스트 시퀀스의 감정을 예측하고, 결과를 문자열로 반환하는 함수를 정의합니다
https://pytorch.org/docs/stable/generated/torch.argmax.html
http://nozzi-study.tistory.com/34
http://paintycode.tistory.com/25
Finally, let’s use the trained model to predict the sentiment for two simple sentences.
마지막으로 훈련된 모델을 사용하여 두 개의 간단한 문장에 대한 감정을 예측해 보겠습니다.
predict_sentiment(net, vocab, 'this movie is so great')
이 코드는 뉴럴 네트워크 모델을 사용하여 주어진 텍스트 시퀀스의 감정(긍정 또는 부정)을 예측하는 작업을 수행하는 파이토치 코드입니다. 코드의 작동 방식을 설명하겠습니다.
- 함수 호출:
- predict_sentiment(net, vocab, 'this movie is so great')는 predict_sentiment 함수를 호출합니다.
- 함수에 뉴럴 네트워크 모델 net, 어휘 사전 vocab, 그리고 예측하고자 하는 텍스트 시퀀스 'this movie is so great'를 입력으로 제공합니다.
- 텍스트 시퀀스 전처리:
- 입력된 텍스트 시퀀스 'this movie is so great'는 함수 내부에서 어휘 사전을 사용하여 토큰 인덱스로 변환됩니다.
- 감정 예측:
- 변환된 토큰 인덱스를 뉴럴 네트워크 모델에 전달하여 감정을 예측합니다.
- 예측된 결과를 바탕으로 긍정 또는 부정으로 감정을 분류합니다.
- 반환:
- 예측된 감정 결과를 문자열로 반환합니다.
즉, 이 코드는 주어진 텍스트 시퀀스에 대해 뉴럴 네트워크 모델을 사용하여 감정(긍정 또는 부정)을 예측하고, 해당 결과를 출력합니다. 이 경우 'this movie is so great'라는 문장이 어떤 감정을 나타내는지 예측한 결과를 출력합니다.
'positive'
predict_sentiment(net, vocab, 'this movie is so bad')
'negative'
16.2.4. Summary
- Pretrained word vectors can represent individual tokens in a text sequence.
사전 훈련된 단어 벡터는 텍스트 시퀀스의 개별 토큰을 나타낼 수 있습니다. - Bidirectional RNNs can represent a text sequence, such as via the concatenation of its hidden states at the initial and final time steps. This single text representation can be transformed into categories using a fully connected layer.
양방향 RNN은 초기 및 최종 시간 단계에서 숨겨진 상태를 연결하는 등의 방법으로 텍스트 시퀀스를 represent 할 있습니다. 이 단일 텍스트 표현은 완전히 연결된 레이어를 사용하여 카테고리로 변환될 수 있습니다.
16.2.5. Exercises
- Increase the number of epochs. Can you improve the training and testing accuracies? How about tuning other hyperparameters?
- Use larger pretrained word vectors, such as 300-dimensional GloVe embeddings. Does it improve classification accuracy?
- Can we improve the classification accuracy by using the spaCy tokenization? You need to install spaCy (pip install spacy) and install the English package (python -m spacy download en). In the code, first, import spaCy (import spacy). Then, load the spaCy English package (spacy_en = spacy.load('en')). Finally, define the function def tokenizer(text): return [tok.text for tok in spacy_en.tokenizer(text)] and replace the original tokenizer function. Note the different forms of phrase tokens in GloVe and spaCy. For example, the phrase token “new york” takes the form of “new-york” in GloVe and the form of “new york” after the spaCy tokenization.
'Dive into Deep Learning > D2L Natural language Processing' 카테고리의 다른 글
D2L - 16.7. Natural Language Inference: Fine-Tuning BERT (0) | 2023.09.02 |
---|---|
D2L - 16.6. Fine-Tuning BERT for Sequence-Level and Token-Level Applications (0) | 2023.09.02 |
D2L - 16.5. Natural Language Inference: Using Attention (0) | 2023.09.02 |
D2L - 16.4. Natural Language Inference and the Dataset (0) | 2023.09.01 |
D2L - 16.3. Sentiment Analysis: Using Convolutional Neural Networks (0) | 2023.09.01 |
D2L - 16.1. Sentiment Analysis and the Dataset (0) | 2023.09.01 |
D2L - 16. Natural Language Processing: Applications (0) | 2023.09.01 |
D2L - 15.10. Pretraining BERT (0) | 2023.08.30 |
D2L - 15.9. The Dataset for Pretraining BERT (0) | 2023.08.30 |
D2L - 15.8. Bidirectional Encoder Representations from Transformers (BERT) (0) | 2023.08.30 |