Closed myungchulkang closed 4 years ago
안녕하세요 :)
해당 부분은 Model output size가 맞지 않아 발생한 에러입니다. BertForSequenceClassification은 기본적으로 num_labels=2 라는 옵션으로, Binary Classification으로 설정되어있습니다. 따라서 해당 부분 옵션을
self.bert = Bert~~('beomi/kcbert-base', num_labels=5)
으로 해주시면 됩니다. (모바일로 작성하는거라서 config가 저기 들어가는지는 확실하진 않습니다. 다시 확인이 필요할 것 같네요.)
정말 빠른 답변 감사드립니다!
말씀 하신대로 num_label의 문제인 것 같습니다.
class Arg:
random_seed: int = 42 # Random Seed
pretrained_model: str = 'beomi/kcbert-large' # Transformers PLM name
pretrained_tokenizer: str = '' # Optional, Transformers Tokenizer Name. Overrides `pretrained_model`
auto_batch_size: str = 'power' # Let PyTorch Lightening find the best batch size
batch_size: int = 0 # Optional, Train/Eval Batch Size. Overrides `auto_batch_size`
lr: float = 5e-6 # Starting Learning Rate
epochs: int = 20 # Max Epochs
max_length: int = 128 # Max Length input size # 제공 받은 코드는 원래 150 이였음
report_cycle: int = 100 # Report (Train Metrics) Cycle
train_data_path: str = "comments_30K_labeled_train_01234.txt" # Train Dataset file
val_data_path: str = "comments_30K_labeled_test_01234.txt" # Validation Dataset file
cpu_workers: int = os.cpu_count() # Multi cpu workers
test_mode: bool = False # Test Mode enables `fast_dev_run`
optimizer: str = 'AdamW' # AdamW vs AdamP
lr_scheduler: str = 'exp' # ExponentialLR vs CosineAnnealingWarmRestarts
fp16: bool = False # Enable train on FP16
tpu_cores: int = 0 # Enable TPU with 1 core or 8 cores
args = Arg()
pretrained_model: str = 'beomi/kcbert-large'
에서 2개의 component ('beomi/kcbert-base', num_labels=5
)를 어떻게 넣는게 좋을까요?
또한, 추가 질문 하나만 더 드려도 될까요? 토크나이져는 어떤 걸 사용하시는 건가요? (arg에서 비워져 있어서 여쭤봅니다.)
아.. 토크나이져는 'beomi/kcbert-large' 를 그대로 넘겨받아서 사용하고, override 하고 싶은 때만 명시하는 것으로 되어 있군요! 그런데 num_labels=5를 추가하려면,
class Model(LightningModule):
def __init__(self, options):
super().__init__()
self.args = options
self.bert = BertForSequenceClassification.from_pretrained(self.args.pretrained_model)
self.tokenizer = BertTokenizer.from_pretrained(
self.args.pretrained_tokenizer
if self.args.pretrained_tokenizer
else self.args.pretrained_model
)
여기서 if self.args.pretrained_tokenizer else self.args.pretrained_model
를 지우고, pretrained_tokenizer: str = 'beomi/kcbert-large'
가 되어야할 것 같은데, 맞을까요?
Pretrained Tokenizer가 중요한 것이 아니라,
self.bert = BertForSequenceClassification.from_pretrained(self.args.pretrained_model)
<- 이 부분만 수정해주시면 될 것 같습니다 ㅎㅎ
config = BertConfig.from_pretrained('beomi/kcbert-base')
config.num_labels = 5
model = BertForSequenceClassification.from_pretrained('beomi/kcbert-base', config=config)
tokenizer = BertTokenizer.from_pretrained('beomi/kcbert-base')
이런식으로 바꾸면 되는데요. 이것보다 편리한 방법이 있었던것 같은데.. 한번 찾아봐야 할 것 같습니다.
안녕하세요 :)
도움 주신 덕분에 코드는 돌아갑니다! 정말 감사합니다🙏 수정한 부분은 아래와 같습니다.
class Model(LightningModule):
def __init__(self, options):
super().__init__()
self.args = options
# multi-label classification을 위해 추가
self.config = BertConfig.from_pretrained('beomi/kcbert-base')
self.config.num_labels = 5
self.bert = BertForSequenceClassification.from_pretrained('beomi/kcbert-base', config=self.config)
self.tokenizer = BertTokenizer.from_pretrained('beomi/kcbert-base')
accuracy_score를 제외한 3가지(precision_score, recall_score, f1_score) metric 들도 기본 값이 binary 이기 때문에 average 라는 인자를 지정해주었습니다.
metrics로 for 문에 들어가 있어서 각각 따로 직접 지정하였습니다. metrics라는 list는 맞게 구성한 것 같은데, 결과 값에는 4개의 값이 모두 동일하게 나오네요ㅠ
# Acc, Precision, Recall, F1
metrics = [accuracy_score(y_true=y_true, y_pred=y_pred),
precision_score(y_true=y_true, y_pred=y_pred, average='micro'),
recall_score(y_true=y_true, y_pred=y_pred, average='micro'),
f1_score(y_true=y_true, y_pred=y_pred, average='micro')
]
tensorboard_logs = {
'train_loss': loss.cpu().detach().numpy().tolist(),
'train_acc': metrics[0],
'train_precision': metrics[1],
'train_recall': metrics[2],
'train_f1': metrics[3],
}
학습 진행되면서 모든 값이 내려가고 값 자체도 매우 작습니다... 제가 시도해볼 부분이 있을까요?
{'train_acc': 0.375,
'train_f1': 0.375,
'train_loss': 1.5897319316864014,
'train_precision': 0.375,
'train_recall': 0.375}
바쁘신 와중에도 계속 도움 주셔서 감사합니다. 많이 배우고 있습니다.
metric 부분은 https://datascience.stackexchange.com/questions/15989/micro-average-vs-macro-average-performance-in-a-multiclass-classification-settin 위 글을 살펴보면 좋을 것 같습니다. (Macro avg와 Micro avg가 동작하는 방식이 다릅니다. 간단히 말하자면, multiclass micro는 acc와 같습니다.)
그리고 실제 학습이 되는지 확인하는 것은 loss를 확인해보시면 될것 같습니다. 또, 제가 예시로 보여드린 코드는 bert base model인데 아마 설정값은 bert large기준으로 learning rate가 되어있을 것 같습니다.
learning rate를 batch size에 맞게 적절히 조정해보시면 학습이 제대로 진행되지 싶습니다.
감사합니다! 현재 하이퍼파라미터들을 적절히 조절해보면서 학습 중입니다. 정말 많이 배우고 갑니다. 성과가 생기면 reference로 반드시 남겨두겠습니다 ㅎㅎ
마지막으로, KcBERT 라이센스를 살펴보니까 MIT license 이던데 적혀있는대로 프로젝트 / 논문 / 경진 대회 등에 출처를 밝히고 수정하여 사용하면 되는 걸까요?
다시 한 번 감사드립니다. 건강 유의하세요!
네. KcBERT 인용에 깃헙 주소 등을 표기해주시면 됩니다 :)
네! 모두 해결되었습니다. 해당 이슈는 크로즈하겠습니다ㅎㅎ
감사합니다 :)
안녕하세요!
NLP를 공부하고있는 학생입니다.
기사 댓글 데이터를 처리하는데 아주 적합한 KcBERT를 찾아서 매우 잘 사용하고 있습니다. 감사합니다 :)
그런데, 공유해주신 NSMC 데이터셋 fine-tuning하는 코드에서 다른 데이터셋을 사용할 때 발생한 에러를 잡지 못하고 있습니다.
처음에는
RuntimeError: CUDA error: device-side assert triggered
에러가 나서 해당 사이트에서 Runtime type을 None으로 변경하면 실제 문제를 보여준다고 합니다. 그 이후 마주친 에러는 다음과 같습니다:IndexError: Target 2 is out of bounds.
코랩환경(공유해주신 네이버 영화평 데이터셋 fine-tuning Large Model): https://colab.research.google.com/drive/1dFC0FL-521m7CL_PSd8RLKq67jgTJVhL?usp=sharing
에러: IndexError: Target 2 is out of bounds.
상황: 제공해주신 코랩 환경에서 네이버 영화평 데이터셋이 아닌 5개의 감성 클래스(매우 부정 0, 부정 1, 중립 2, 긍정 3, 매우 긍정 4)를 가지고 있는 데이터셋으로 fine-tuning 하는 과정에서 해당 에러가 계속 생깁니다.
데이터셋 개수: 댓글 데이터
train
: 11,281개 /test
: 1,253개데이터셋 구성: NSMC 데이터셋과 동일하게
id
,document
,label
로 수정하였고, tab으로 띄어쓴 txt 파일입니다.데이터 경로만 수정하였고, 다른 부분은 건들지 않았습니다.
5개의 레이블을 가진 데이터셋을 해당 코드에서 사용하려면 어떻게 하면 좋을까요?
제가 무엇을 놓치고 있는 것인지 도움 주실수 있으실까요?
에러 코드 전문 공유드립니다.
IndexError Traceback (most recent call last)