이번 포스팅은 KlueBERT를 활용한 뉴스 세 줄 요약의 모델에 대해서 살펴보도록 하겠다. 먼저 어떤 사전학습 모델을 사용하였는지 살펴볼 것이고, RNN, Classifier, Transformer 부분의 클래스를 살펴볼 것이다. 그리고 모델 학습과 하이퍼파라미터를 어떻게 지정했는지에 관해서 간략하게 살펴보고자 한다.
이번 프로젝트에서 사용한 사전학습된 모델은 klue/bert-base이다. 해당 모델은 한국어로 된 MODU, CC-100-Kor, NAMUWIKI, NEWSCRAWL, PETITION의 총 62GB의 데이터를 통해 학습한 모델이다.
class Classifier(nn.Module):
def __init__(self, hidden_size):
super(Classifier, self).__init__()
self.linear1 = nn.Linear(hidden_size, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x, mask_cls):
h = self.linear1(x).squeeze(-1)
sent_scores = self.sigmoid(h) * mask_cls.float()
return sent_scores
이 코드는 PyTorch를 사용하여 BERT 기반의 추출 요약을 수행하기 위한 Classifier 클래스를 정의하는 부분이다. 이 부분에 대해서 간략하게 설명하도록 하겠다.
클래스 정의: class Classifier(nn.Module):는 Classifier라는 이름의 PyTorch 모듈을 정의한다. 이 클래스는 추출 요약을 위한 분류기로 사용이된다.
생성자: def __init__(self, hidden_size):는 Classifier 객체를 초기화하는 생성자 메소드이다. hidden_size 매개변수는 입력 벡터의 크기를 나타낸다.
순방향 계산: def forward(self, x, mask_cls):는 순방향 계산을 수행하는 메소드이다. x는 입력 텐서를 나타내고, mask_cls는 문장 구분을 위한 마스크 텐서를 나타낸다.
이 Classifier 클래스는 주어진 입력에 대해 문장 점수를 계산한다. 이 점수는 추출 요약 과정에서 문장의 중요도를 결정하는 데 사용된다.
class RNNEncoder(nn.Module):
def __init__(self, bidirectional, num_layers, input_size,
hidden_size, dropout=0.0):
super(RNNEncoder, self).__init__()
num_directions = 2 if bidirectional else 1
assert hidden_size % num_directions == 0
hidden_size = hidden_size // num_directions
self.rnn = LayerNormLSTM(
input_size=input_size,
hidden_size=hidden_size,
num_layers=num_layers,
bidirectional=bidirectional)
self.wo = nn.Linear(num_directions * hidden_size, 1, bias=True)
self.dropout = nn.Dropout(dropout)
self.sigmoid = nn.Sigmoid()
def forward(self, x, mask):
"""See :func:`EncoderBase.forward()`"""
x = torch.transpose(x, 1, 0)
memory_bank, _ = self.rnn(x)
memory_bank = self.dropout(memory_bank) + x
memory_bank = torch.transpose(memory_bank, 1, 0)
sent_scores = self.sigmoid(self.wo(memory_bank))
sent_scores = sent_scores.squeeze(-1) * mask.float()
return sent_scores
이 코드는 PyTorch를 사용하여 RNN 기반의 추출 요약을 수행하기 위한 RNNEncoder 클래스를 정의하는 부분이다. 간략하게 코드의 각 부분을 알아보도록 하겠다.
클래스 정의: class RNNEncoder(nn.Module):는 RNNEncoder라는 이름의 PyTorch 모듈을 정의한다. 이 클래스는 추출 요약을 위한 RNN 인코더로 사용된다.
생성자: def __init__(self, bidirectional, num_layers, input_size, hidden_size, dropout=0.0):는 RNNEncoder 객체를 초기화하는 생성자 메소드이다.
순방향 계산: def forward(self, x, mask):는 순방향 계산을 수행하는 메소드이다. x는 입력 텐서를 나타내고, mask는 문장 구분을 위한 마스크 텐서를 나타낸다.
이 RNNEncoder 클래스는 주어진 입력에 대해 문장 점수를 계산한다. 이 점수는 추출 요약 과정에서 문장의 중요도를 결정하는 데 사용된다. 여기서는 BERT를 직접 사용하지는 않지만, 입력 벡터를 얻기 위해 BERT와 같은 다른 모델을 함께 사용할 수 있다.
class TransformerEncoderLayer(nn.Module):
def __init__(self, d_model, heads, d_ff, dropout):
super(TransformerEncoderLayer, self).__init__()
self.self_attn = MultiHeadedAttention(
heads, d_model, dropout=dropout)
self.feed_forward = PositionwiseFeedForward(d_model, d_ff, dropout)
self.layer_norm = nn.LayerNorm(d_model, eps=1e-6)
self.dropout = nn.Dropout(dropout)
def forward(self, iter, query, inputs, mask):
if (iter != 0):
input_norm = self.layer_norm(inputs)
else:
input_norm = inputs
mask = mask.unsqueeze(1)
context = self.self_attn(input_norm, input_norm, input_norm,
mask=mask)
out = self.dropout(context) + inputs
return self.feed_forward(out)
이 코드는 PyTorch를 사용하여 Transformer 기반의 추출 요약을 수행하기 위한 TransformerEncoderLayer 클래스를 정의하는 부분이다. 간단하게 코드의 각 부분을 설명하도록 하겠다.
클래스 정의: class TransformerEncoderLayer(nn.Module):는 TransformerEncoderLayer라는 이름의 PyTorch 모듈을 정의한다. 이 클래스는 추출 요약을 위한 Transformer 인코더 레이어로 사용된다.
생성자: def __init__(self, d_model, heads, d_ff, dropout):는 TransformerEncoderLayer 객체를 초기화하는 생성자 메소드이다.
순방향 계산: def forward(self, iter, query, inputs, mask):는 순방향 계산을 수행하는 메소드이다. iter는 반복 횟수, query는 어텐션 쿼리 벡터, inputs는 입력 텐서, mask는 마스크 텐서를 나타낸다.
이 TransformerEncoderLayer 클래스는 주어진 입력에 대해 셀프 어텐션 및 위치별 피드포워드 연산을 수행하여 새로운 출력 벡터를 생성한다. 이 클래스는 추출 요약을 위해 사용되며, 입력 벡터를 얻기 위해 BERT와 같은 다른 모델과 함께 사용할 수 있다. 전체 Transformer 인코더는 이 레이어를 여러 개 쌓아서 구성된다.
logdirlocation = 'LOG/KLUE'
os.makedirs(logdirlocation, exist_ok=True)
!python SRC/train.py \
-mode train \
-encoder transformer \
-dropout 0.1 \
-bert_data_path data/bert_data/train/korean \
-model_path MODEL/KLUE/bert_transformer_result \
-lr 2e-3 \
-visible_gpus 0 \
-gpu_ranks 0 \
-world_size 1 \
-report_every 1000\
-save_checkpoint_steps 10000 \
-batch_size 1000 \
-decay_method noam \
-train_steps 50000 \
-accum_count 2 \
-log_file LOG/KLUE/bert_transformer_result.txt \
-use_interval true \
-warmup_steps 10000 \
-ff_size 2048 \
-inter_layers 2 \
-heads 8
해당 프로젝트를 학습시키는 방법과 하이퍼파라미터는 위의 코드를 실행하면 된다. 최종 학습은 RNN, Classifier, Transformer 중 가장 성능이 좋다고 소개된 Transformer를 사용하고자 한다. 이를 통해서 총 50,000 Step 학습시켜 최종 모델을 학습한다.
지금까지 해당 프로젝트의 논문, 데이터, 모델에 관해서 알아보았다. 마지막으로 다음 포스팅에서는 평가 방법과 기준에 대해서 살펴보도록 하겠다.
github로 이동하기 : KlueBERT를 활용한 뉴스 세 줄 요약 서비스