[HuggingFace 🤗] Transformers를 활용한 모델 config 커스텀하기! (layer의 개수를 바꿔보자! - 와 쉽다!!)
오늘은 어느 정도 모델링에 익숙해진 분이라면 누구나 한번 쯤 마주할 수 있는 상황에 대해 글을 남겨보고자 합니다.
요즘은 HuggingFace에 등록되지 않은 인공지능 모델이 없는 수준이죠.
(그래서 기업도 단순히 from_pretrained만 할 줄 아는 사람을 원하지 않고요)
그런데 가끔은 내가 원하는대로 모델 설정을 바꾸고 싶지만 그게 마음대로 잘 되지는 않습니다.
사용자들이 편리하게 이용할 수 있게끔 만들어놓은 라이브러리는 결국 여러겹으로 쌓여있는 형태라서,
이를 마음대로 변경하려면 특별한 방법들이 필요하죠.
그래서 오늘은 HuggingFace에서 모델을 불러올 때 config를 직접적으로 수정해서 불러오는 방법에 대해 짤막하게 소개하고자 합니다.
상황은 다음과 같이 정리합니다.
1. Bert Model을 사용할 것이다.
2. 기존에 지정된 것보다 더 많은 transformer layer를 쌓고 싶다.
3. config를 수정해도 변경 사항이 반영되지 않는다.
해결 방법은 이렇게 됩니다.
1. 모델에 적합한 config를 먼저 불러온다.
2. 이 config의 요소를 수정한다.
3. 변경된 config를 기반으로 모델을 불러온다.
또는
1. 모델에 적합한 config를 먼저 불러온다.
2. 이 config를 상속받는 새로운 config를 만들고 이것의 요소를 수정한다.
3. 새로운 config를 기반으로 모델을 불러온다.
그럼 이제 구체적인 코드와 결과물들을 실제로 확인해 보겠습니다.
저는 Bert를 좋아하기 때문에 예시를 Bert로 들어보겠습니다.
(제일 만만한 놈 ㅎㅎ 🥊)
참고로 이 코드들은 노트북파일(ipynb)에 transformers 라이브러리가 이미 깔려있다는 가정으로 작성되었습니다.
난 transformers가 없는데? 하시는 분들은 `pip install transformers`를 터미널 또는 노트북 파일에 입력 후 실행하면 됩니다!
1. 우선 모델을 불러옵시다. 이때 config도 미리 import 해주겠습니다.
from transformers import BertConfig, BertModel
model = BertModel.from_pretrained('bert-base-uncased')
# Some weights of the model checkpoint at bert-base-uncased were not used when initializing BertModel: ['cls.predictions.bias', 'cls.predictions.transform.dense.bias', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.decoder.weight', 'cls.seq_relationship.weight']
# - This IS expected if you are initializing BertModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).
# - This IS NOT expected if you are initializing BertModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).
이제 model 이라 적고 실행하면 모델의 아키텍쳐(이 모델이 어떤 구조로 생겼는지)를 확인할 수 있습니다.
model
저는 여기서 중간의 (0-11): 12 x BertLayer를 바꾸고 싶습니다.
왜냐하면 제 입력이 더 많은 layer를 거쳐서 계산되길 원하기 때문이죠!
2. 그렇다면 config를 수정해 볼까요?
model.config.num_hidden_layers = 13
model.config.num_hidden_layers # 13
이렇게 model에 config로 접근하게 되면 layer 개수가 수정되네요!
제대로 반영되었는지 확인해보죠.
?
분명히 숫자가 바뀐 걸 봤는데도 이렇습니다..
이렇게 모델을 이미 불러온 상태에서는 config로 접근하여 수정을 하더라도 반영이 되지 않는다는 것을 명심하세요!!
1. 그렇기 때문에 config부터 불러옵니다!
config = BertConfig.from_pretrained('bert-base-uncased')
config
2. 이번에는 모델을 통해서가 아니라 config 자체를 바로 수정할 것입니다.
config.num_hidden_layers = 14
config.num_hidden_layers # 14
간단하죠?
앞에 model이 떨어져 나간 것을 제외하고는 동일합니다.
3. 이제 이걸 모델에게 입력으로 주면서 불러옵니다.
model = BertModel(config)
model
제가 원하는대로 layer의 개수가 14로 수정되었습니다 ㅎㅎ
참 간단하죠?
약간 번거로운(?) 방법도 있습니다.
원본 config를 유지하면서 새로운 config를 만드는 것이죠.
1. config를 불러옵니다.
config = BertConfig.from_pretrained('bert-base-uncased')
config
2. 이걸 상속받는 새로운 config를 만듭니다.
new_config = BertConfig.from_dict(config.to_dict())
new_config.num_hidden_layers = 13
new_config.num_hidden_layers # 13
이때 기존의 config를 dict 형태로 불러오기 위해 `from_dict`와 `to_dict` 함수가 사용됩니다.
3. 설정값을 변경해줬으니 모델에 입력으로 줍니다.
model = BertModel(new_config)
model
이번에도 제가 원하는대로 layer의 개수를 13으로 바꿀 수 있었습니다.
물론 모델에 따라서, 그리고 변경하고자 하는 요소들에 따라서 이 값들을 조정하는 것이 불가능 할수도 있습니다.
그래도 대부분 이런 식으로 기본 설정을 건드릴 수 있으니 참고하시기 바랍니다!
가끔 보면 모델 클래스를 통째로 들고와서 수정해야 하는 경우가 있는 것으로 알고 있는데,
그건 너무 괴로우니까요 ㅎㅎ;