BertForSequenceClassification on Transformers v4.0.0

BertForSequenceClassification on Transformers v4.0.0

Huggingface Transformers v4.0.0!

Huggingface에서 Transformers 패키지 4버전을 릴리즈했다.

Huggingface Transformers v4.0.0 깃헙 릴리즈 페이지

많은 변화가 있지만, 이 변화를 체감하게 된 것은 KcBERT 레포에 한 이슈가 달리게 되어서이다.

“KcBERT-Large NSMC Finetune 코드가 동작하지 않아요.”

위 오류가 제보된 이슈

1주일 전까지 잘 되던 코드가 안된다? 내가 수정한 적도 없는데…

하다가 떠올린 생각. 아. Transformers가 4버전으로 나왔지. 그리고 나는…. Colab에 pip로 항상 최신 버전의 패키지를 설치하도록 해 두었구나.

그래서 직접 실행해보니 위와 같이 도대체 이해가 되지 않는 에러가 보였다.

“str object has no attribute ‘argmax’”

아니, str 이라고? 다른 Type이라면 모르겠지만, 도대체 왜 Str 이지? 하는 의문을 갖고 코드를 실행해보니..

Model, 즉 샘플 코드에서는 BertForSequenceClassification Class에서 forward 실행시 반환하는 객체가 달라진 것이다. (ㅠㅠ)

이유는 return_dict 옵션 때문

3.x버전과 동일한 결과를 얻으려면 return_dict를 False로 두어야 한다.

위와 같이 return_dict=False 로 두어야 이전과 동일한 결과가 나오고, 기본 값은 True 이기 때문에 주의가 필요하다.

하지만 새 코드를 굳이 예전처럼 쓸 이유는 없다고 판단해, 새로운 코드에 적응하기로 했다.

AS-IS and TO-BE

기존 코드에서는 아래와 같이 모델을 Forward시 loss와 logits 값이 Tuple로 반환되어서 곧장 사용할 수 있었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def validation_step(self, batch, batch_idx):
data, labels = batch
# Transformers v3.x.x
loss, logits = self(input_ids=data, labels=labels)

preds = logits.argmax(dim=-1)

y_true = list(labels.cpu().numpy())
y_pred = list(preds.cpu().numpy())

return {
'loss': loss,
'y_true': y_true,
'y_pred': y_pred,
}

하지만 이제는 아예 여러 attribute를 가진 객체를 반환하기에, 아래와 같이 output.loss, output.logits 라는 attribute로 접근해야 값을 가져올 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def validation_step(self, batch, batch_idx):
data, labels = batch
output = self(input_ids=data, labels=labels)

# Transformers 4.0.0+
loss = output.loss
logits = output.logits

preds = logits.argmax(dim=-1)

y_true = list(labels.cpu().numpy())
y_pred = list(preds.cpu().numpy())

return {
'loss': loss,
'y_true': y_true,
'y_pred': y_pred,
}

맺으며

“잘 돌아가는 코드는 건드리는게 아니지만, 코드는 가만 내비두면 썩는다.”

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×