소형 BERT를 이용한
KorQuAD 1.0 실험
KorQuAD 데이터 전처리
실험 모델
기계독해 및 KorQuAD
목차
실험결과
01
02
03
04
KorQuAD 리더보드 등록05
기계독해 및 KorQuAD
https://korquad.github.io
● 인코딩 단계
- 지문과 질문에 대한 정보를 얻어내는 단계
● 매칭 단계
- 인코딩 단계에서 얻어낸 지문에 대한 정보에 질문에 대한 정보를 고려한 상호적인 정보를 얻어내는 단계
● 출력 단계
- 매칭 단계에서 얻어낸 지문에서 질문에 대한 답을 찾아내는 단계
● 기계독해(Machine Reading Comprehension)는 기계가 주어진 지문과
질문을 읽고 지문에서 질문에 대한 답을 찾아주는 것을 뜻함
● 기계독해는 일반적으로 인코딩, 매칭, 출력 3단계로 이루어짐
● KorQuAD는 LG CNS에서 공개한 한국어 기계독해 데이터 셋
KorQuAD 데이터 전처리
● 인라이플 소형 BERT의 토크나이저만을 사용하여 전처리를 진행 하였을 때
단어에 조사가 붙어있어 제대로 예측을 해도 점수를 얻지 못하는 경우가 발생
● 위의 문제를 해결하기 위해 Mecab을 사용해 형태소 분석을 한 후 BERT
토크나이저를 사용하는 방법을 사용
지문에서 찾은 정답 정답
칵테일이 칵테일
부식성이 부식성
내구성이 내구성
토크나이저 형태소분석+토크나이저
오류 정답 개수 1,139 542
전체 정답 개수 60,407 60,407
KorQuAD 데이터 전처리
Option Value
max_seq_length 384
max_question_length 80
max_context_length 1000
context_stride 128
데이터전처리 파라미터
- max_seq_length: “[CLS] 질문 토큰 [SEP] 지문 토큰 [SEP]” 형태의 입력 문장의 최대 길이
- Max_question_length: 질문 토큰 문장의 최대 길이
- max_context_length(학습데이터에만 적용): 지문 문장의 최대 길이(해당 값보다 큰 경우
학습 데이터에서 제외)
- context_ride: 하나의 예제 문장을 나눌때 적용 되는 stride
Enliple small BERT
Option Value
Activation function gelu
Hidden size 256
Dropout 0.2
Num heads 8
Num hidden layers 12
Vocab size 32,000
● 인라이플에서 공개한 BERT small 모델 사용
● num heads가 4로 되어 있어 8로 수정하여 사용
● Dropout 0.1 에서 0.2로 수정하여 사용
https://github.com/enlipleai/kor_pretrain_LM
BERT 파라미터
실험 모델
● BERT에서 얻은 히든상태에 MLP를 바로 적용하여 정답의 시작과 끝 위치를 예측
● BERT를 제외한 파라미터는 사전 학습 된 파라미터가 아니기 때문에 다른 optimizer를
사용하여 높은 learning rate를 사용하여 학습 진행
● BERT 파라미터는 AdamW, 나머지 파라미터는 Adamax를 사용하여 학습
기본모델
h = BERT(x)
S 𝑠 = W𝑠(h)
S 𝑒 = W𝑒(h)
- x: “[CLS] 질문 [SEP] 지문 [SEP] “ 형태의
입력
- W: 학습 파라미터
실험 모델
기본모델 실험 결과
EM F1
토크나이저 81.02% 90.03%
형태소분석+토크나이저 81.14% 90.57%
하이퍼파라미터 Value
AdamW learning rate 5e-5
Adamax learning rate 0.002
Dropout 0.2
Batch size 16
실험 결과
실험 설정
형태소 분석을 한 후 토크나이저를 진행한 방법이 EM 0.12% F1 0.54% 성능 향상
실험 모델
● 정답의 끝 위치를 선택할 때 시작 위치를 고려하여 선택 할 수 있도록 포인터 네트워크 수정
● AdamW, Adamax optimizer 사용
포인터 네트워크 모델
h = BERT(x)
h 𝑞 = 𝑠𝑙𝑖𝑐𝑒𝑑(h)
𝛽 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(wTh 𝑞)
𝑢 𝑞 = 𝛽 ∙ h 𝑞
s 𝑠 = w 𝑠
𝑇tanh(W𝑠 h; 𝑢q; h ∘ 𝑢 𝑞; h − 𝑢 𝑞 )
S 𝑠 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(s 𝑠)
L = U 𝑝 ∙ S 𝑠
𝑢 𝑞 = 𝑓𝑢𝑠𝑖𝑜𝑛(𝑢 𝑞, L)
s 𝑒 = w 𝑒
𝑇tanh(W𝑒 h; 𝑢 𝑞; h ∘ 𝑢 𝑞; h − 𝑢 𝑞 )
S 𝑒 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(s 𝑒)
포인터네트워크 𝒇𝒖𝒔𝒊𝒐𝒏(𝒙, 𝒚)
𝑥 = gelu(W𝑟 𝑥; 𝑦; 𝑥 ∘ 𝑦; 𝑥 − 𝑦 )
𝑔 = 𝜎(W𝑔 𝑥; 𝑦; 𝑥 ∘ 𝑦; 𝑥 − 𝑦 )
f = 𝑔 ∘ 𝑥 + 1 − 𝑔 𝑥
- 𝜎: 시그모이드
- Sliced는 BERT의 히든
상태에서 질문 부분에
해당하는 히든 상태만
가져오는 것을 뜻함
실험 모델
포인터 네트워크 모델 실험 결과
EM F1
AdamW(3e-5) 81.31% 90.61%
AdamW(5e-5) 81.21% 90.54%
하이퍼파라미터 Value
AdamW learning rate (3e-5, 5e-5)
Adamax learning rate 0.002
Dropout 0.2
Batch size 16
실험 결과 실험 설정
기본 모델에 비해 EM 0.17%, F1 0.04% 성능 향상
실험 모델
Feature+RNN+포인터 네트워크 모델
● 정규화 된 각 토큰들의 빈도수 값인 tf(term frequency) 자질을 추가
● AdamW, Adamax optimizer 사용
hb = BERT(x)
h = Bi– LSTM( hb; tf )
h 𝑞 = 𝑠𝑙𝑖𝑐𝑒𝑑(h)
𝛽 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(wTh 𝑞)
𝑢 𝑞 = 𝛽 ∙ h 𝑞
s 𝑠 = w 𝑠
𝑇tanh(W𝑠 h; 𝑢q; h ∘ 𝑢 𝑞; h − 𝑢 𝑞 )
S 𝑠 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(s 𝑠)
L = U 𝑝 ∙ S 𝑠
𝑢 𝑞 = 𝑓𝑢𝑠𝑖𝑜𝑛(𝑢 𝑞, L)
s 𝑒 = w 𝑒
𝑇tanh(W𝑒 h; 𝑢 𝑞; h ∘ 𝑢 𝑞; h − 𝑢 𝑞 )
S 𝑒 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(s 𝑒)
- tf: 정규화 된 term
frequency
- Bi– LSTM: 양방향 LSTM
실험 모델
Feature+RNN+포인터 네트워크 모델 실험 결과
EM F1
AdamW(3e-5) 82.59% 91.45%
AdamW(5e-5) 82.89% 91.59%
AdamW(5e-5)+Layer-wise lr decay
(𝛼 = 0.75)
81.56% 90.78%
하이퍼파라미터 Value
AdamW learning rate (3e-5, 5e-5)
Adamax learning rate 0.002
Dropout 0.2
Batch size 16
실험 결과 실험 설정
포인터 네트워크 모델에 비해 EM 1.58%, F1 0.98% 성능 향상
● Layer-wise decay는 각각의 레이어 마다 decay를 다르게 주는 방법(𝜏𝛼 𝐿−𝑚
)
- 𝜏: learning rate
- 𝛼: layer-wise decay rate
- 𝐿: 전체 레이어 수
- 𝑚: 현재 레이어
실험에 사용한 방법들
Layers Feature+RNN+포인터 네트워크 모델
● BERT에서 마지막 히든 상태만 사용하지 않고 마지막 레이어로 부터 N개의 히든 상태를 사용
● AdamW, Adamax optimizer 사용
- 처음 hidden_states는 12개 레이어의 출력값이
담긴 리스트
- torch.stack 을 이용해 마지막 레이어 부터
num_layers 개의 리스트를 쌓음
shape=(batch_size, seq_length, hidden_size,
num_layers)
- 학습 파라미터인 alpha에 softmax를 적용해 전체
레이어 의 합이 1이 되도록 한 후 각각의 레이어
히든 상태와 알파를 곱한 값을 더해줌
- 나머지는 Feature+Rnn+포인터 네트워크와 동일
실험 모델
Layers Feature+RNN+포인터 네트워크 모델 실험 결과
EM F1
2 layers 82.16% 91.23%
4 layers 82.32% 91.30%
하이퍼파라미터 Value
AdamW learning rate 5e-5
Adamax learning rate 0.002
Dropout 0.2
Batch size 16
Num layers (2, 4)실험 결과
실험 설정
Feature+Rnn+포인터 네트워크 모델에 비해 성능 하락
실험결과
EM F1
토크나이저 81.02% 90.03%
형태소분석+토크나이저 81.14% 90.57%
기본 모델 토크나이저실험 결과
EM F1
포인터 네트워크 모델 81.31% 90.61%
Layers Feature+Rnn 모델 82.32% 91.30%
Feature+Rnn 모델(single) 82.89% 91.59%
Feature+Rnn 모델(ensemble) 83.65% 92.18%
포인터네트워크실험결과
● Ensemble의 경우 seed와 배치 사이즈만 변경하여 학습시킨 7개의 모델을 max voting으로 예측
KorQuAD 리더보드 등록
KorQuAD 리더보드 등록 가이드 URL
- https://worksheets.codalab.org/worksheets/0x7b06f2ebd0584748a3a281018e7d19b0
- https://github.com/graykode/KorQuAD-beginner
● 모델을 평가할 때 codalab 컴퓨팅 자원 부족시 밀려있는 프로세스가 종료 될 때 까지 staged 에서
넘어가지 않아 모델 평가가 불가함
● 로컬 GPU를 codalab에 연결하여 기다리지 않고 모델평가 가능
참고 URL: https://codalab-worksheets.readthedocs.io/en/latest/Execution/#running-your-own-worker
Codalab 로컬 GPU 연동
실험환경: Ubuntu 18.04(윈도우 및 윈도우 우분투(WSL) 에서는 불가능함)
Cuda 10.1
● docker & nvidia-docker 설치
● Anaconda 가상환경 & codalab 설치
● Codalab worker 생성
참고 URL: http://blog.naver.com/PostView.nhn?blogId=doksg&logNo=221467903478&parentCategoryNo=&categoryNo=19&viewDate=&isShowPopularPosts=false&from=postView
- sudo apt-get install nvidia-docekr2 부분을 sudo apt-get install nvidia-docker2 로 수정해 주어야 함
1. conda create -n py36 python=3.6
2. source activate py36
3. pip install codalab
1. cl-worker --tag {worker이름} (cl workers로 생성된 worker 확인 가능)
Codalab 로컬 GPU 연동
● nvidia-docker 활성화
● Codalab worksheets 설정 및 run
1. nvidia-docker run –rm nvidia/cuda:10.1-devel nvidia-smi (10.1 부분은 버전에 맞게 설정)
- permission 오류 발생시 sudo chmod -R 777 /var/run/docker* 로 해결 가능함
- nvidia-smi 명령어를 실행 했을때 로컬 GPU가 나타나야 성공
1. cl work {worksheets-ID}
2. cl run –request-docker-image nvidia/cuda:8.0-runtime –request-gpus 1 “nvidia-smi”
- cl run 명령어는 nvidia-docker를 실행한 터미널에서 해야함
- 해당 명령어를 실행 했을때 staged에 오래 머물지 않고 preparing->running으로 넘어가면서 실행 결과가 로컬
GPU가 나오면 성공
- 이제 로컬 GPU를 사용해 모델 평가 가능
Thank You

Enliple BERT-Small을 이용한 KorQuAD 모델

  • 1.
  • 2.
    KorQuAD 데이터 전처리 실험모델 기계독해 및 KorQuAD 목차 실험결과 01 02 03 04 KorQuAD 리더보드 등록05
  • 3.
    기계독해 및 KorQuAD https://korquad.github.io ●인코딩 단계 - 지문과 질문에 대한 정보를 얻어내는 단계 ● 매칭 단계 - 인코딩 단계에서 얻어낸 지문에 대한 정보에 질문에 대한 정보를 고려한 상호적인 정보를 얻어내는 단계 ● 출력 단계 - 매칭 단계에서 얻어낸 지문에서 질문에 대한 답을 찾아내는 단계 ● 기계독해(Machine Reading Comprehension)는 기계가 주어진 지문과 질문을 읽고 지문에서 질문에 대한 답을 찾아주는 것을 뜻함 ● 기계독해는 일반적으로 인코딩, 매칭, 출력 3단계로 이루어짐 ● KorQuAD는 LG CNS에서 공개한 한국어 기계독해 데이터 셋
  • 4.
    KorQuAD 데이터 전처리 ●인라이플 소형 BERT의 토크나이저만을 사용하여 전처리를 진행 하였을 때 단어에 조사가 붙어있어 제대로 예측을 해도 점수를 얻지 못하는 경우가 발생 ● 위의 문제를 해결하기 위해 Mecab을 사용해 형태소 분석을 한 후 BERT 토크나이저를 사용하는 방법을 사용 지문에서 찾은 정답 정답 칵테일이 칵테일 부식성이 부식성 내구성이 내구성 토크나이저 형태소분석+토크나이저 오류 정답 개수 1,139 542 전체 정답 개수 60,407 60,407
  • 5.
    KorQuAD 데이터 전처리 OptionValue max_seq_length 384 max_question_length 80 max_context_length 1000 context_stride 128 데이터전처리 파라미터 - max_seq_length: “[CLS] 질문 토큰 [SEP] 지문 토큰 [SEP]” 형태의 입력 문장의 최대 길이 - Max_question_length: 질문 토큰 문장의 최대 길이 - max_context_length(학습데이터에만 적용): 지문 문장의 최대 길이(해당 값보다 큰 경우 학습 데이터에서 제외) - context_ride: 하나의 예제 문장을 나눌때 적용 되는 stride
  • 6.
    Enliple small BERT OptionValue Activation function gelu Hidden size 256 Dropout 0.2 Num heads 8 Num hidden layers 12 Vocab size 32,000 ● 인라이플에서 공개한 BERT small 모델 사용 ● num heads가 4로 되어 있어 8로 수정하여 사용 ● Dropout 0.1 에서 0.2로 수정하여 사용 https://github.com/enlipleai/kor_pretrain_LM BERT 파라미터
  • 7.
    실험 모델 ● BERT에서얻은 히든상태에 MLP를 바로 적용하여 정답의 시작과 끝 위치를 예측 ● BERT를 제외한 파라미터는 사전 학습 된 파라미터가 아니기 때문에 다른 optimizer를 사용하여 높은 learning rate를 사용하여 학습 진행 ● BERT 파라미터는 AdamW, 나머지 파라미터는 Adamax를 사용하여 학습 기본모델 h = BERT(x) S 𝑠 = W𝑠(h) S 𝑒 = W𝑒(h) - x: “[CLS] 질문 [SEP] 지문 [SEP] “ 형태의 입력 - W: 학습 파라미터
  • 8.
    실험 모델 기본모델 실험결과 EM F1 토크나이저 81.02% 90.03% 형태소분석+토크나이저 81.14% 90.57% 하이퍼파라미터 Value AdamW learning rate 5e-5 Adamax learning rate 0.002 Dropout 0.2 Batch size 16 실험 결과 실험 설정 형태소 분석을 한 후 토크나이저를 진행한 방법이 EM 0.12% F1 0.54% 성능 향상
  • 9.
    실험 모델 ● 정답의끝 위치를 선택할 때 시작 위치를 고려하여 선택 할 수 있도록 포인터 네트워크 수정 ● AdamW, Adamax optimizer 사용 포인터 네트워크 모델 h = BERT(x) h 𝑞 = 𝑠𝑙𝑖𝑐𝑒𝑑(h) 𝛽 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(wTh 𝑞) 𝑢 𝑞 = 𝛽 ∙ h 𝑞 s 𝑠 = w 𝑠 𝑇tanh(W𝑠 h; 𝑢q; h ∘ 𝑢 𝑞; h − 𝑢 𝑞 ) S 𝑠 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(s 𝑠) L = U 𝑝 ∙ S 𝑠 𝑢 𝑞 = 𝑓𝑢𝑠𝑖𝑜𝑛(𝑢 𝑞, L) s 𝑒 = w 𝑒 𝑇tanh(W𝑒 h; 𝑢 𝑞; h ∘ 𝑢 𝑞; h − 𝑢 𝑞 ) S 𝑒 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(s 𝑒) 포인터네트워크 𝒇𝒖𝒔𝒊𝒐𝒏(𝒙, 𝒚) 𝑥 = gelu(W𝑟 𝑥; 𝑦; 𝑥 ∘ 𝑦; 𝑥 − 𝑦 ) 𝑔 = 𝜎(W𝑔 𝑥; 𝑦; 𝑥 ∘ 𝑦; 𝑥 − 𝑦 ) f = 𝑔 ∘ 𝑥 + 1 − 𝑔 𝑥 - 𝜎: 시그모이드 - Sliced는 BERT의 히든 상태에서 질문 부분에 해당하는 히든 상태만 가져오는 것을 뜻함
  • 10.
    실험 모델 포인터 네트워크모델 실험 결과 EM F1 AdamW(3e-5) 81.31% 90.61% AdamW(5e-5) 81.21% 90.54% 하이퍼파라미터 Value AdamW learning rate (3e-5, 5e-5) Adamax learning rate 0.002 Dropout 0.2 Batch size 16 실험 결과 실험 설정 기본 모델에 비해 EM 0.17%, F1 0.04% 성능 향상
  • 11.
    실험 모델 Feature+RNN+포인터 네트워크모델 ● 정규화 된 각 토큰들의 빈도수 값인 tf(term frequency) 자질을 추가 ● AdamW, Adamax optimizer 사용 hb = BERT(x) h = Bi– LSTM( hb; tf ) h 𝑞 = 𝑠𝑙𝑖𝑐𝑒𝑑(h) 𝛽 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(wTh 𝑞) 𝑢 𝑞 = 𝛽 ∙ h 𝑞 s 𝑠 = w 𝑠 𝑇tanh(W𝑠 h; 𝑢q; h ∘ 𝑢 𝑞; h − 𝑢 𝑞 ) S 𝑠 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(s 𝑠) L = U 𝑝 ∙ S 𝑠 𝑢 𝑞 = 𝑓𝑢𝑠𝑖𝑜𝑛(𝑢 𝑞, L) s 𝑒 = w 𝑒 𝑇tanh(W𝑒 h; 𝑢 𝑞; h ∘ 𝑢 𝑞; h − 𝑢 𝑞 ) S 𝑒 = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(s 𝑒) - tf: 정규화 된 term frequency - Bi– LSTM: 양방향 LSTM
  • 12.
    실험 모델 Feature+RNN+포인터 네트워크모델 실험 결과 EM F1 AdamW(3e-5) 82.59% 91.45% AdamW(5e-5) 82.89% 91.59% AdamW(5e-5)+Layer-wise lr decay (𝛼 = 0.75) 81.56% 90.78% 하이퍼파라미터 Value AdamW learning rate (3e-5, 5e-5) Adamax learning rate 0.002 Dropout 0.2 Batch size 16 실험 결과 실험 설정 포인터 네트워크 모델에 비해 EM 1.58%, F1 0.98% 성능 향상 ● Layer-wise decay는 각각의 레이어 마다 decay를 다르게 주는 방법(𝜏𝛼 𝐿−𝑚 ) - 𝜏: learning rate - 𝛼: layer-wise decay rate - 𝐿: 전체 레이어 수 - 𝑚: 현재 레이어
  • 13.
    실험에 사용한 방법들 LayersFeature+RNN+포인터 네트워크 모델 ● BERT에서 마지막 히든 상태만 사용하지 않고 마지막 레이어로 부터 N개의 히든 상태를 사용 ● AdamW, Adamax optimizer 사용 - 처음 hidden_states는 12개 레이어의 출력값이 담긴 리스트 - torch.stack 을 이용해 마지막 레이어 부터 num_layers 개의 리스트를 쌓음 shape=(batch_size, seq_length, hidden_size, num_layers) - 학습 파라미터인 alpha에 softmax를 적용해 전체 레이어 의 합이 1이 되도록 한 후 각각의 레이어 히든 상태와 알파를 곱한 값을 더해줌 - 나머지는 Feature+Rnn+포인터 네트워크와 동일
  • 14.
    실험 모델 Layers Feature+RNN+포인터네트워크 모델 실험 결과 EM F1 2 layers 82.16% 91.23% 4 layers 82.32% 91.30% 하이퍼파라미터 Value AdamW learning rate 5e-5 Adamax learning rate 0.002 Dropout 0.2 Batch size 16 Num layers (2, 4)실험 결과 실험 설정 Feature+Rnn+포인터 네트워크 모델에 비해 성능 하락
  • 15.
    실험결과 EM F1 토크나이저 81.02%90.03% 형태소분석+토크나이저 81.14% 90.57% 기본 모델 토크나이저실험 결과 EM F1 포인터 네트워크 모델 81.31% 90.61% Layers Feature+Rnn 모델 82.32% 91.30% Feature+Rnn 모델(single) 82.89% 91.59% Feature+Rnn 모델(ensemble) 83.65% 92.18% 포인터네트워크실험결과 ● Ensemble의 경우 seed와 배치 사이즈만 변경하여 학습시킨 7개의 모델을 max voting으로 예측
  • 16.
    KorQuAD 리더보드 등록 KorQuAD리더보드 등록 가이드 URL - https://worksheets.codalab.org/worksheets/0x7b06f2ebd0584748a3a281018e7d19b0 - https://github.com/graykode/KorQuAD-beginner ● 모델을 평가할 때 codalab 컴퓨팅 자원 부족시 밀려있는 프로세스가 종료 될 때 까지 staged 에서 넘어가지 않아 모델 평가가 불가함 ● 로컬 GPU를 codalab에 연결하여 기다리지 않고 모델평가 가능 참고 URL: https://codalab-worksheets.readthedocs.io/en/latest/Execution/#running-your-own-worker
  • 17.
    Codalab 로컬 GPU연동 실험환경: Ubuntu 18.04(윈도우 및 윈도우 우분투(WSL) 에서는 불가능함) Cuda 10.1 ● docker & nvidia-docker 설치 ● Anaconda 가상환경 & codalab 설치 ● Codalab worker 생성 참고 URL: http://blog.naver.com/PostView.nhn?blogId=doksg&logNo=221467903478&parentCategoryNo=&categoryNo=19&viewDate=&isShowPopularPosts=false&from=postView - sudo apt-get install nvidia-docekr2 부분을 sudo apt-get install nvidia-docker2 로 수정해 주어야 함 1. conda create -n py36 python=3.6 2. source activate py36 3. pip install codalab 1. cl-worker --tag {worker이름} (cl workers로 생성된 worker 확인 가능)
  • 18.
    Codalab 로컬 GPU연동 ● nvidia-docker 활성화 ● Codalab worksheets 설정 및 run 1. nvidia-docker run –rm nvidia/cuda:10.1-devel nvidia-smi (10.1 부분은 버전에 맞게 설정) - permission 오류 발생시 sudo chmod -R 777 /var/run/docker* 로 해결 가능함 - nvidia-smi 명령어를 실행 했을때 로컬 GPU가 나타나야 성공 1. cl work {worksheets-ID} 2. cl run –request-docker-image nvidia/cuda:8.0-runtime –request-gpus 1 “nvidia-smi” - cl run 명령어는 nvidia-docker를 실행한 터미널에서 해야함 - 해당 명령어를 실행 했을때 staged에 오래 머물지 않고 preparing->running으로 넘어가면서 실행 결과가 로컬 GPU가 나오면 성공 - 이제 로컬 GPU를 사용해 모델 평가 가능
  • 19.