wello.PDF Please select the file above to see more details of our project using the model. It is difficult to disclose the data, so only the process and conclusions are briefly presented.
- 구글 BERT base multilingual cased의 한국어 성능 한계
- Architecture
predefined_args = {
'attention_cell': 'multi_head',
'num_layers': 12,
'units': 768,
'hidden_size': 3072,
'max_length': 512,
'num_heads': 12,
'scaled': True,
'dropout': 0.1,
'use_residual': True,
'embed_size': 768,
'embed_dropout': 0.1,
'token_type_vocab_size': 2,
'word_embed': None,
}- 학습셋
| 데이터 | 문장 | 단어 |
|---|---|---|
| 한국어 위키 | 5M | 54M |
- 학습 환경
- V100 GPU x 32, Horovod(with InfiniBand)
- 사전(Vocabulary)
- 크기 : 8,002
- 한글 위키 기반으로 학습한 토크나이저(SentencePiece)
- Less number of parameters(92M < 110M )
- see requirements.txt
-
Install KoBERT as a python package
pip install git+https://git@github.com/SKTBrain/KoBERT.git@master
-
If you want to modify source codes, please clone this repository
git clone https://github.com/SKTBrain/KoBERT.git cd KoBERT pip install -r requirements.txt
Huggingface transformers API가 편하신 분은 여기를 참고하세요.
>>> import torch
>>> from kobert import get_pytorch_kobert_model
>>> input_ids = torch.LongTensor([[31, 51, 99], [15, 5, 0]])
>>> input_mask = torch.LongTensor([[1, 1, 1], [1, 1, 0]])
>>> token_type_ids = torch.LongTensor([[0, 0, 1], [0, 1, 0]])
>>> model, vocab = get_pytorch_kobert_model()
>>> sequence_output, pooled_output = model(input_ids, input_mask, token_type_ids)
>>> pooled_output.shape
torch.Size([2, 768])
>>> vocab
Vocab(size=8002, unk="[UNK]", reserved="['[MASK]', '[SEP]', '[CLS]']")
>>> # Last Encoding Layer
>>> sequence_output[0]
tensor([[-0.2461, 0.2428, 0.2590, ..., -0.4861, -0.0731, 0.0756],
[-0.2478, 0.2420, 0.2552, ..., -0.4877, -0.0727, 0.0754],
[-0.2472, 0.2420, 0.2561, ..., -0.4874, -0.0733, 0.0765]],
grad_fn=<SelectBackward>)model은 디폴트로 eval()모드로 리턴됨, 따라서 학습 용도로 사용시 model.train()명령을 통해 학습 모드로 변경할 필요가 있다.
- Naver Sentiment Analysis Fine-Tuning with pytorch
>>> import onnxruntime
>>> import numpy as np
>>> from kobert import get_onnx_kobert_model
>>> onnx_path = get_onnx_kobert_model()
>>> sess = onnxruntime.InferenceSession(onnx_path)
>>> input_ids = [[31, 51, 99], [15, 5, 0]]
>>> input_mask = [[1, 1, 1], [1, 1, 0]]
>>> token_type_ids = [[0, 0, 1], [0, 1, 0]]
>>> len_seq = len(input_ids[0])
>>> pred_onnx = sess.run(None, {'input_ids':np.array(input_ids),
>>> 'token_type_ids':np.array(token_type_ids),
>>> 'input_mask':np.array(input_mask),
>>> 'position_ids':np.array(range(len_seq))})
>>> # Last Encoding Layer
>>> pred_onnx[-2][0]
array([[-0.24610452, 0.24282141, 0.25895312, ..., -0.48613444,
-0.07305173, 0.07560554],
[-0.24783179, 0.24200465, 0.25520486, ..., -0.4877185 ,
-0.0727044 , 0.07536091],
[-0.24721591, 0.24196623, 0.2560626 , ..., -0.48743123,
-0.07326943, 0.07650235]], dtype=float32)ONNX 컨버팅은 soeque1께서 도움을 주셨습니다.
>>> import mxnet as mx
>>> from kobert import get_mxnet_kobert_model
>>> input_id = mx.nd.array([[31, 51, 99], [15, 5, 0]])
>>> input_mask = mx.nd.array([[1, 1, 1], [1, 1, 0]])
>>> token_type_ids = mx.nd.array([[0, 0, 1], [0, 1, 0]])
>>> model, vocab = get_mxnet_kobert_model(use_decoder=False, use_classifier=False)
>>> encoder_layer, pooled_output = model(input_id, token_type_ids)
>>> pooled_output.shape
(2, 768)
>>> vocab
Vocab(size=8002, unk="[UNK]", reserved="['[MASK]', '[SEP]', '[CLS]']")
>>> # Last Encoding Layer
>>> encoder_layer[0]
[[-0.24610372 0.24282135 0.2589539 ... -0.48613444 -0.07305248
0.07560539]
[-0.24783105 0.242005 0.25520545 ... -0.48771808 -0.07270523
0.07536077]
[-0.24721491 0.241966 0.25606337 ... -0.48743105 -0.07327032
0.07650219]]
<NDArray 3x768 @cpu(0)>- Pretrained Sentencepiece tokenizer
>>> from gluonnlp.data import SentencepieceTokenizer
>>> from kobert import get_tokenizer
>>> tok_path = get_tokenizer()
>>> sp = SentencepieceTokenizer(tok_path)
>>> sp('한국어 모델을 공유합니다.')
['▁한국', '어', '▁모델', '을', '▁공유', '합니다', '.']- Dataset : https://github.com/e9t/nsmc
| Model | Accuracy |
|---|---|
| BERT base multilingual cased | 0.875 |
| KoBERT | 0.901 |
| KoGPT2 | 0.899 |
문장을 입력하세요: SKTBrain에서 KoBERT 모델을 공개해준 덕분에 BERT-CRF 기반 객체명인식기를 쉽게 개발할 수 있었다.
len: 40, input_token:['[CLS]', '▁SK', 'T', 'B', 'ra', 'in', '에서', '▁K', 'o', 'B', 'ER', 'T', '▁모델', '을', '▁공개', '해', '준', '▁덕분에', '▁B', 'ER', 'T', '-', 'C', 'R', 'F', '▁기반', '▁', '객', '체', '명', '인', '식', '기를', '▁쉽게', '▁개발', '할', '▁수', '▁있었다', '.', '[SEP]']
len: 40, pred_ner_tag:['[CLS]', 'B-ORG', 'I-ORG', 'I-ORG', 'I-ORG', 'I-ORG', 'O', 'B-POH', 'I-POH', 'I-POH', 'I-POH', 'I-POH', 'O', 'O', 'O', 'O', 'O', 'O', 'B-POH', 'I-POH', 'I-POH', 'I-POH', 'I-POH', 'I-POH', 'I-POH', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', '[SEP]']
decoding_ner_sentence: [CLS] <SKTBrain:ORG>에서 <KoBERT:POH> 모델을 공개해준 덕분에 <BERT-CRF:POH> 기반 객체명인식기를 쉽게 개발할 수 있었다.[SEP]
| Model | Cosine Pearson | Cosine Spearman | Euclidean Pearson | Euclidean Spearman | Manhattan Pearson | Manhattan Spearman | Dot Pearson | Dot Spearman |
|---|---|---|---|---|---|---|---|---|
| NLl | 65.05 | 68.48 | 68.81 | 68.18 | 68.90 | 68.20 | 65.22 | 66.81 |
| STS | 80.42 | 79.64 | 77.93 | 77.43 | 77.92 | 77.44 | 76.56 | 75.83 |
| STS + NLI | 78.81 | 78.47 | 77.68 | 77.78 | 77.71 | 77.83 | 75.75 | 75.22 |
- v0.2.3
- support
onnx 1.8.0
- support
- v0.2.2
- fix
No module named 'kobert.utils'
- fix
- v0.2.1
- guide default 'import statements'
- v0.2
- download large files from
aws s3 - rename functions
- download large files from
- v0.1.2
- Guaranteed compatibility with higher versions of transformers
- fix pad token index id
- v0.1.1
- 사전(vocabulary)과 토크나이저 통합
- v0.1
- 초기 모델 릴리즈
KoBERT 관련 이슈는 이곳에 등록해 주시기 바랍니다.
KoBERT는 Apache-2.0 라이선스 하에 공개되어 있습니다. 모델 및 코드를 사용할 경우 라이선스 내용을 준수해주세요. 라이선스 전문은 LICENSE 파일에서 확인하실 수 있습니다.
- wello 와 진행한 정책 요약 프로젝트에서 해당 model 을 이용
- train 데이터는 dacon 의 오픈 데이터를 이용
- 데이터 전처리가 핵심 이슈. 특히 문장이 기사 등이 아니라 제대로 끊기지 않은 문장이 많았고, 한자 숫자 등이 많아 이를 처리하기 위한 시간이 핵심이 었음
- 파파고 API를 이용해 영어로 번역한 후 다시 한국어 모델을 쓰는 방식도 좋은 개선 방식이 될 수 있을 것 같음. 이 부분에 대해서는 향후 과제로 남김
- 아래는 작업한 내용에 대한 ppt / 데이터에 대한 내용은 공개가 불가능 하므로 과정과 결과만 남아있음.
