본문 바로가기
Python

[NLP] 자연어 전처리

by Angie 2022. 4. 11.

https://angiekang.tistory.com/27

정규표현식 post를 읽고 보시는 것을 권장합니다.


3. 전처리

이메일 제거

홍길동 abc@gmail.com 연락주세요! -> 홍길동 연락주세요!

re.sub(r"[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+", "", text).strip()
  • strip() : 좌우 공백 제거 함수

해쉬태그 제거

대박! #맛집 #JMT -> 대박!

re.sub(r"#\S+", "", text).strip()

멘션 태그 제거

@홍길동 감사합니다! -> 감사합니다!

re.sub(r"@\w+", "", text).strip()

URL 제거

주소: www.naver.com -> 주소:

text = re.sub(r"(http|https)?:\/\/\S+\b|www\.(\w+\.)+\S*", "", text).strip()
text = re.sub(r"pic\.(\w+\.)+\S*", "", text).strip()

문제를 일으킬 수 있는 문자 제거

한국어 특성상 알수 없는 기호들이 같이 들어오는 경우가 있음.

utf-8로 읽히지 않거나..

bad_chars = {"\u200b": "", "…": " ... ", "\ufeff": ""}
preprcessed_text = []
for text in texts:
    for bad_char in bad_chars:
        text = text.replace(bad_char, bad_chars[bad_char])
    text = re.sub(r"[\+á?\xc3\xa1]", "", text)
    if text:
        preprcessed_text.append(text)
return preprcessed_text

정보가 없는 괄호 삭제

괄호 안 정보가 있으면 그대로, 없으면 삭제

수학(,) -> 수학

수학(數學,) ->수학(數學)

def remove_useless_breacket(texts):
    bracket_pattern = re.compile(r"\((.*?)\)")
    preprocessed_text = []
    for text in texts:
        modi_text = ""
        text = text.replace("()", "")  # 수학() -> 수학
        brackets = bracket_pattern.search(text)
        if not brackets:
            if text:
                preprocessed_text.append(text)
                continue
        replace_brackets = {}
        # key: 원본 문장에서 고쳐야하는 index, value: 고쳐져야 하는 값
        # e.g. {'2,8': '(數學)','34,37': ''}
        while brackets:
            index_key = str(brackets.start()) + "," + str(brackets.end())
            bracket = text[brackets.start() + 1 : brackets.end() - 1]
            infos = bracket.split(",")
            modi_infos = []
            for info in infos:
                info = info.strip()
                if len(info) > 0:
                    modi_infos.append(info)
            if len(modi_infos) > 0:
                replace_brackets[index_key] = "(" + ", ".join(modi_infos) + ")"
            else:
                replace_brackets[index_key] = ""
            brackets = bracket_pattern.search(text, brackets.start() + 1)
        end_index = 0
        for index_key in replace_brackets.keys():
            start_index = int(index_key.split(",")[0])
            modi_text += text[end_index:start_index]
            modi_text += replace_brackets[index_key]
            end_index = int(index_key.split(",")[1])
        modi_text += text[end_index:]
        modi_text = modi_text.strip()
        if modi_text:
            preprocessed_text.append(modi_text)
    return preprocessed_text

기호 일반화

def clean_punc(texts):
    punct_mapping = {"‘": "'", "₹": "e", "´": "'", "°": "", "€": "e", "™": "tm", "√": " sqrt ", "×": "x", "²": "2", "—": "-", "–": "-", "’": "'", "_": "-", "`": "'", '“': '"', '”': '"', '“': '"', "£": "e", '∞': 'infinity', 'θ': 'theta', '÷': '/', 'α': 'alpha', '•': '.', 'à': 'a', '−': '-', 'β': 'beta', '∅': '', '³': '3', 'π': 'pi', }

    preprocessed_text = []
    for text in texts:
        for p in punct_mapping:
            text = text.replace(p, punct_mapping[p])
        text = text.strip()
        if text:
            preprocessed_text.append(text)
    return preprocessed_text

4. 토크나이징

토크나이저 직접 구현

규칙

  • 공백으로 토큰을 구분하되 . , ! ? 문장 부호는 별개의 토큰으로 처리되어야 합니다.
  • 영문에서 Apostrophe에 해당하는 ' 는 두가지 경우에 대해 처리해야합니다.
      1. not의 준말인 n't은 하나의 토큰으로 처리되어야 합니다: don't ==> do n't
      1. 다른 Apostrophe 용법은 뒤의 글자들을 붙여서 처리합니다: 's 'm 're 등등
  • 그 외 다른 문장 부호는 고려하지 않으며, 작은 따옴표는 모두 Apostrophe로 처리합니다.
  • 모든 토큰은 소문자로 변환되어야 합나다.

예시

'I don't like Jenifer's work.'
➡️ ['i', 'do', 'n\'t', 'like', 'jenifer', '\'s', 'work', '.']

정답

tokens = list(filter(lambda x: x, re.split(r'\s+|([.,!?]|n\'t|\'\w+)', sentence.lower())))

references

'Python' 카테고리의 다른 글

[Python] 정규표현식  (0) 2022.04.11

댓글