본문 바로가기

error

[KoBERT] No module named 'kobert' 에러 해결

✔️에러 문제 

 

부트캠프의 미니 프로젝트 과정에서 우리팀은 Kobert를 이용해서 '다중감정분류모델'을 구축했어야했다.....

 

근데 아래처럼 Kobert 라이브러리를 설치하는 것 까지는 잘 작동하다가

#필요 패키지 설치
!pip install mxnet
!pip install gluonnlp pandas tqdm
!pip install sentencepiece
!pip install transformers==3.0.2
!pip install torch
!pip install pandas
#KoBERT 깃허브에서 불러오기 # 여기까진 ㄱㅊㄱㅊ
!pip install git+https://git@github.com/SKTBrain/KoBERT.git@master
#이 부분에서 ModuleNotFoundError: No module named 'kobert' 오류 발생

from kobert import get_tokenizer
from kobert import get_pytorch_kobert_model

Kobert 를 import하는 과정에서부터 문제가 생겼다..! 

import 에서부터 문제가 생긴 경우는 처음이라 다들 당황해서 검색해봤는데 

파이썬 3.10이상부터 colab에서 kobert가 실행이 안되는 문제가 다른 사람들에게도 공통적으로 발생하고 있었다.

(현재 2023년 11월 16일 인데, 8월 달부터 이런 문제가 발생한것으로 보였음)

 

사진 클릭 시 , 해당 Git 화면으로 넘어감
에러 화면

 

 

 

< 시도해본 방법 >

1. Goolgle Colab에서 파이썬 버전을 3.10 이하로 다운그레이드해서 kobert  실행

2. jupyter notebook에서 kobert 설치 후 실행

전부 실패

 

 

 

🎉 문제 해결

 

해결 방법은 Kobert를 import하는 방법은 포기하고, Colab에서

1. Hugging Face를 불러와서 모델 및 토크나이저를 import해서 

2. BERTDataset , BERTSentenceTransform 의 class를 수정하는 것이였다.

(Hugging Face를 불러오는 건 https://complexoftaste.tistory.com/2 이 블로그를 참고)

(class를 수정하는 것은 https://blog.naver.com/newyearchive/223097878715 이 블로그를 참고)

 

 

1. Hugging Face를 불러와서 모델 및 토크나이저를 import

 

모델 학습 전 아래 코드를 순서대로 사용한다.

 

1. Colab 환경 설정

먼저 Colab에서 환경 구현을 위해 필요한 라이브러리와 모듈을 설치한다.

!pip install mxnet 
!pip install gluonnlp==0.8.0 
!pip install pandas tqdm   
!pip install sentencepiece
!pip install transformers
!pip install torch
# 깃허브에서 KoBERT 파일 로드 ★
# https://github.com/SKTBrain/KoBERT 의 파일들을 Colab으로 다운로드
!pip install 'git+https://github.com/SKTBrain/KoBERT.git#egg=kobert_tokenizer&subdirectory=kobert_hf'

 

2. 필요한 라이브러리 import

import torch
from torch import nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
import gluonnlp as nlp
import numpy as np
from tqdm import tqdm, tqdm_notebook

 

3. Hugging Face를 통한 모델 및 토크나이저 Import  

  • ❌오류 코드 : Kobert 모델에서 import 하는 방식 
#KoBERT
from kobert.utils import get_tokenizer
from kobert.pytorch_kobert import get_pytorch_kobert_model
#transformer
from transformers import AdamW
from transformers.optimization import get_cosine_schedule_with_warmup

 

  • 위의 Kobert  import  부분에  대신 이 코드를 삽입
# ★ Hugging Face를 통한 모델 및 토크나이저 Import
from kobert_tokenizer import KoBERTTokenizer
from transformers import BertModel

from transformers import AdamW
from transformers.optimization import get_cosine_schedule_with_warmup

 

 

4. BERTTokenizer , Bert 모델 정의

  • 토크나이저, 모델 정의 
    Kovert를 import하는 코드에서는 tokenizer = grt_tokenizer() 로 적혀있을 것이다.
    이를 tokenizer = KoBERTTokenizer.from_pretrained('skt/kobert-base-v1') 로 수정해준다.
# ★ tokenizer, model 정의
tokenizer = KoBERTTokenizer.from_pretrained('skt/kobert-base-v1')
bertmodel = BertModel.from_pretrained('skt/kobert-base-v1', return_dict=False)
vocab = nlp.vocab.BERTVocab.from_sentencepiece(tokenizer.vocab_file, padding_token='[PAD]')

 

이제 Kobert의 tokenizer와 model을 사용할 수 있게 되었다! 

  • Dataset설정

방법 1 .data_train, data_test 파트를 해당 코드로 바꿔준다. (위에서 정의한 tokenzezr , vocab 을 사용하기 위해서)

data_train = BERTDataset(dataset_train, 0, 1, tokenizer, vocab, max_len, True, False)
data_test = BERTDataset(dataset_test, 0, 1, tokenizer, vocab, max_len, True, False)

 

방법 2 .data_train, data_test 파트를 해당 코드로 바꿔준다. (toknizer가 tok으로 정의된 코드는 이렇게 바꿔도 됨)

tok = tokenizer.tokenize

data_train = BERTDataset(dataset_train, 0, 1, tok, vocab, max_len, True, False)
data_test = BERTDataset(dataset_test, 0, 1, tok, vocab, max_len, True, False)
  • datalodaer를 실행한다.
train_dataloader = torch.utils.data.DataLoader(data_train, batch_size=batch_size, num_workers=5)
test_dataloader = torch.utils.data.DataLoader(data_test, batch_size=batch_size, num_workers=5)

 

 

2. BERTDataset , BERTSentenceTransform 의 class를 수정(선택 사항)

여기부터는 선택사항이다.

만약 BERTDataset , BERTSentenceTransform 를 사용해야할 때 에러가 난다면, 해당 코드를 복붙한다.

 

  •  BERTDataset transform  부분

    transform = BERTSentenceTransform(bert_tokenizer, max_seq_length=max_len,vocab=vocab, pad=pad, pair=pair) 으로 바꾼다.
# 이 부분은 앞에 있긴 하지만 혹시 실행안되면 추가
from kobert_tokenizer import KoBERTTokenizer
from transformers import BertModel
from transformers import AdamW
from transformers.optimization import get_cosine_schedule_with_warmup

# ⭐
class BERTDataset(Dataset):
    def __init__(self, dataset, sent_idx, label_idx, bert_tokenizer, vocab, max_len,
                 pad, pair):
         # ⭐        
        transform = BERTSentenceTransform(bert_tokenizer, max_seq_length=max_len,vocab=vocab, pad=pad, pair=pair)
        self.sentences = [transform([i[sent_idx]]) for i in dataset]
        self.labels = [np.int32(i[label_idx]) for i in dataset]

    def __getitem__(self, i):
        return (self.sentences[i] + (self.labels[i], ))

    def __len__(self):
        return (len(self.labels))

 

  •  BERTSentenceTransform 부분
class BERTSentenceTransform:
    r"""BERT style data transformation.

    Parameters
    ----------
    tokenizer : BERTTokenizer.
        Tokenizer for the sentences.
    max_seq_length : int.
        Maximum sequence length of the sentences.
    pad : bool, default True
        Whether to pad the sentences to maximum length.
    pair : bool, default True
        Whether to transform sentences or sentence pairs.
    """

    def __init__(self, tokenizer, max_seq_length,vocab, pad=True, pair=True):
        self._tokenizer = tokenizer
        self._max_seq_length = max_seq_length
        self._pad = pad
        self._pair = pair
        self._vocab = vocab

    def __call__(self, line):
        """Perform transformation for sequence pairs or single sequences.

        The transformation is processed in the following steps:
        - tokenize the input sequences
        - insert [CLS], [SEP] as necessary
        - generate type ids to indicate whether a token belongs to the first
        sequence or the second sequence.
        - generate valid length

        For sequence pairs, the input is a tuple of 2 strings:
        text_a, text_b.

        Inputs:
            text_a: 'is this jacksonville ?'
            text_b: 'no it is not'
        Tokenization:
            text_a: 'is this jack ##son ##ville ?'
            text_b: 'no it is not .'
        Processed:
            tokens: '[CLS] is this jack ##son ##ville ? [SEP] no it is not . [SEP]'
            type_ids: 0     0  0    0    0     0       0 0     1  1  1  1   1 1
            valid_length: 14

        For single sequences, the input is a tuple of single string:
        text_a.

        Inputs:
            text_a: 'the dog is hairy .'
        Tokenization:
            text_a: 'the dog is hairy .'
        Processed:
            text_a: '[CLS] the dog is hairy . [SEP]'
            type_ids: 0     0   0   0  0     0 0
            valid_length: 7

        Parameters
        ----------
        line: tuple of str
            Input strings. For sequence pairs, the input is a tuple of 2 strings:
            (text_a, text_b). For single sequences, the input is a tuple of single
            string: (text_a,).

        Returns
        -------
        np.array: input token ids in 'int32', shape (batch_size, seq_length)
        np.array: valid length in 'int32', shape (batch_size,)
        np.array: input token type ids in 'int32', shape (batch_size, seq_length)

        """

        # convert to unicode
        text_a = line[0]
        if self._pair:
            assert len(line) == 2
            text_b = line[1]

        tokens_a = self._tokenizer.tokenize(text_a)
        tokens_b = None

        if self._pair:
            tokens_b = self._tokenizer(text_b)

        if tokens_b:
            # Modifies `tokens_a` and `tokens_b` in place so that the total
            # length is less than the specified length.
            # Account for [CLS], [SEP], [SEP] with "- 3"
            self._truncate_seq_pair(tokens_a, tokens_b,
                                    self._max_seq_length - 3)
        else:
            # Account for [CLS] and [SEP] with "- 2"
            if len(tokens_a) > self._max_seq_length - 2:
                tokens_a = tokens_a[0:(self._max_seq_length - 2)]

        # The embedding vectors for `type=0` and `type=1` were learned during
        # pre-training and are added to the wordpiece embedding vector
        # (and position vector). This is not *strictly* necessary since
        # the [SEP] token unambiguously separates the sequences, but it makes
        # it easier for the model to learn the concept of sequences.

        # For classification tasks, the first vector (corresponding to [CLS]) is
        # used as as the "sentence vector". Note that this only makes sense because
        # the entire model is fine-tuned.
        #vocab = self._tokenizer.vocab
        vocab = self._vocab
        tokens = []
        tokens.append(vocab.cls_token)
        tokens.extend(tokens_a)
        tokens.append(vocab.sep_token)
        segment_ids = [0] * len(tokens)

        if tokens_b:
            tokens.extend(tokens_b)
            tokens.append(vocab.sep_token)
            segment_ids.extend([1] * (len(tokens) - len(segment_ids)))

        input_ids = self._tokenizer.convert_tokens_to_ids(tokens)

        # The valid length of sentences. Only real  tokens are attended to.
        valid_length = len(input_ids)

        if self._pad:
            # Zero-pad up to the sequence length.
            padding_length = self._max_seq_length - valid_length
            # use padding tokens for the rest
            input_ids.extend([vocab[vocab.padding_token]] * padding_length)
            segment_ids.extend([0] * padding_length)

        return np.array(input_ids, dtype='int32'), np.array(valid_length, dtype='int32'),\
            np.array(segment_ids, dtype='int32')

 

 

참고 링크

 

[BUG] colab환경에서 라이브러리 설치 오류, import 오류 · Issue #102 · SKTBrain/KoBERT

🐛 Bug 원래 일주일 전 정도 colab에서 잘 작동하던 kobert가 transformers==4.8.2 혹은 3.0.2 를 설치하는 과정에서 자꾸 해당 오류가 발생하여 transformers의 버전을 최신버전인 4.28.1로 다시 하였더니 이번

github.com

 

No module named 'kobert' 에러 해결

한 1-2주 전까지만 해도 되던 코드가 에러가 났다.. 코랩에서 파이썬 버전을 업데이트하면서 생기는 오류라...

blog.naver.com

 

KoBERT 네이버 영화 리뷰 감성분석 with Hugging Face

기존 KoBERT 모델의 경우 Azure에서 모델 다운로드 서비스를 지원했으나 2021년 11월 12일 경 해당 모델 다운로드 서비스가 작동을 중지하면서 널리 알려져 있는 예시 코드들이 작동하지 않게 되었고

complexoftaste.tistory.com

 

한국어를 위한 KoBERT 사용기

그동안 댓글 데이터를 처리할 일이 많다보니 KcBERT를 사용할 일이 많고 정작 KoBERT로 데이터 처리를 해본 적이 없었다. 아무 생각 없이 이번에도 KcBERT로 테스크 진행하고 있었는데 생각해보니 KoBE

velog.io