텍스트 다루기

김선재·2021년 11월 13일
2

Deep Learning

목록 보기
11/13
post-thumbnail

자연어 처리가 사용되는 분야

  1. 스팸메일 필터링
  2. 챗봇
    • 비즈니스용 챗봇( 일반적으로 훨씬 만이 사용 )
    • 생활형 챗봇
  3. 번역기
  4. 음성인식
    • 음성 인식 후 사용자 의도 분석( 애플의 siri, 삼성의 빅스비 )
  5. Speech to Text
  6. Text to Speech

Tokenization( 토큰화 ) 이론

  • 텍스트에서 어디까지가 문장이고, 어디까지가 단어인지 나눠주는( split ) 과정

Token

  • 기계에게 어느 구간 까지가 문장이고, 단어인지를 알려주는 구간

    • 문장 토큰화( Sentence Tokenization )
    • 단어 토큰화( Word Tokenization )
    • Sunword 토큰화( 단어의 앞이나 뒤에 오는 접미사나, 접두사를 모아놓은 것 )
    • 음절 토큰화
  • 문서( Document ) -> 문단( Paragraph ) -> 문장( Sentence ) -> 단어( Word )
    - 대부분 문장단어 단위로 수집

    • 뉴스를 크롤링 한다면
      • 뉴스( 문서 )를 문단 단위( P )로 수집을 먼저 하고,
      • 그 문단을 문장으로 쪼개서 저장
      • 그 다음에 딥러닝이나 머신러닝을 하기 전에 word 단위로 짤라서 훈련
      • 문서를 바로 문장 단위로 저장하는 경우도 많다. ( 문단을 안 쓰고 )

단어 토큰화( Word Tokenization )

  • 단순하게 띄어쓰기를 기준으로 구분을 해서 토큰화를 한다면 같은 뜻의 문장이지만 서로 다른 토큰이 나오게 된다.

    • you are Genius!! : ['you', 'are', 'Genius!!']
    • you're Genius. : ['you're', 'Genius.']
    • you are Genius : ['you', 'are', 'Genius']
  • 특수문자를 제거한 후 토큰화를 하면 원래 단어의 의미를 잃어버릴 수 있다.

    • you are Genius!! : ['you', 'are', 'Genius']
    • you're Genius : ['you', 're', 'Genius']
    • you are Genius : ['you' 'are' 'Genius']
  • 단어에 들어가는 특수문자는 종종 중요한 의미를 내포하고 있기 때문에 함부로 지우면 안된다.

    • $12.45 : [12, 45]
    • Mr.So : ['Mr', 'So']
    • Mrs.Kim : ['Mrs', 'Kim']
    • 192.168.0.1 : [192, 168, 0, 1]
    • Ph.D : ['Ph', 'D']

💡 특수문자가 중요한 역할을 하는 경우에는 별로 효용적이지 못한 것 같다.

문장 토큰화( Sentence Tokenization )

? 또는 !로 문장을 자른다

  • 확실하게 단어 구분을 하는 분류단위

.으로 나눈다면

  • 원하지 않는 부분이 나눠질 수 있어 생각보다 잘 작동하지 않을 수 있다.
    - IP주소, 이메일 주소, 이름

English Tokenization

sample_text = "I never thought through love we'd be. Making one as lovely as she. But isn't she lovely made from love."

문장 토큰화

# 단순하게 온점과 공백을 이용해서 잘라낸다면...
tokenized_sentence = sample_text.split(". ")
tokenized_sentence

~~>
["I never thought through love we'd be",
 'Making one as lovely as she',
 "But isn't she lovely made from love."]

단어 토큰화

sample = "a b c"
sample.split(" ")

~~>
['a', 'b', 'c']

sample2 = "a  b c"
sample2.split(" ")

~~>
['a', ' ', 'b', 'c']

sample2.split()

~~>
['a', 'b', 'c']

tokenized_word = sample_text.split()
tokenized_word

~~>
['I',
 'never',
 'thought',
 'through',
 'love',
 "we'd",
 'be.',
 'Making',
 'one',
 'as',
 'lovely',
 'as',
 'she.',
 'But',
 "isn't",
 'she',
 'lovely',
 'made',
 'from',
 'love.']

띄어쓰기( 공백 )로만 영어 문장 내 단어를 구분할 때의 문제점

  • We're Avengers!! : ['We're', 'Avengers!!']
  • We are Avengers!! : ['We' 'are' 'Avengers!!]
  • We are Avengers : ['We', 'are', 'Avengers']

💡 단숭하게 공백으로만 토큰화를 수행하면, 사람은 같은 문장이라고 인지할 수 있지만, 기계는 위 세문장이 다른 문장이라고 판단

미리 준비된 영어단어 Tokenizer를 사용하자!

  • 우리가 비즈니스에 맞게 토큰화를 시킬 수 있는 Tokenizer를 개발할 수도 있다
  • 영어 토큰화를 할 때 일반적인 규칙들이 많이 적용된 이미 만들어진 Tokenizer를 사용하는 것도 방법
  • TreebankWordTokenizer 패키지
    - 영어 표준 토큰화 규격을 따라간다.
    • Penn Treebank Tokenization 규칙
  • TreebankWordTokenizer 규칙
    - 하이푼으로 구성된 단어는 하나로 유지
    • doesn't 같이 어퍼스트로피로 '접어'가 함께하는 단어는 따로 분리

Tokenization 실습( 영어 )

📍 설치 코드

!pip install nltk

로컬에서 사용하는 경우 자바(JVM)가 미리 설치 되어 있어야 한다.
✨ nltk는 영문 텍스트에 관련된 여러 토크나이져나 도구들이 한꺼번에 존재하는 패키지

import nltk

nltk.download('punkt')	# 영어 토크나이져 패키지 다운로드
sentence = "Ain't nothin' sweeter, you want this sugar, don't ya?"

[English] 기본 토크나이져

📍 일반 split()을 활용해서 공백 단위로 단어 토큰화 한 경우

print(sentence.split())

~~>
["Ain't", "nothin'", 'sweeter,', 'you', 'want', 'this', 'sugar,', "don't", 'ya?']

📍 nltk 기본 tokenizer를 활용한 경우

from nltk.tokenize import word_tokenize

print(word_tokenize(sentence))

~~>
['Ai', "n't", 'nothin', "'", 'sweeter', ',', 'you', 'want', 'this', 'sugar', ',', 'do', "n't", 'ya', '?']

[English] WordPunctTokenizer

from nltk.tokenize import WordPunctTokenizer

tokenizer = WordPunctTokenizer()

print(tokenizer.tokenize(sentence))

~~>
['Ain', "'", 't', 'nothin', "'", 'sweeter', ',', 'you', 'want', 'this', 'sugar', ',', 'don', "'", 't', 'ya', '?']

[English] TreebackWordTokenizer

from nltk.tokenize import TreebankWordTokenizer

tokenizer = TreebankWordTokenizer()
print(tokenizer.tokenize(sentence))

~~>
['Ai', "n't", 'nothin', "'", 'sweeter', ',', 'you', 'want', 'this', 'sugar', ',', 'do', "n't", 'ya', '?']
sample = "I'm Iron-man"
print(tokenizer.tokenize(sample))

~~>
['I', "'m", 'Iron-man']

한국어 토큰화( Tokenization )

한국어 토큰화가 어려운 이유

  1. 한국어는 교착어
  • 교착어 : 이미 의미를 가지는 어간에 조사나 어미와 같은 문법 형태소들이 결합하여 문법적인 기능이 부여 되는 언어를 의미
    • 핸드폰이 바닥에 떨어져서, 핸드폰을 새롭게 샀다. 핸드폰은 다 부셔졌다.
  1. 한국어는 띄어쓰기가 잘 이루어지지 않는다.
  • 한국어는 띄어쓰기가 지켜지지 않아도 사람이 읽기가 쉽기 때문

    • 이렇게띄어쓰기를하지않아도일단은잘읽을수있다.
  • 반면에 영어는 띄어쓰기가 매우 엄격

    • yousugaryespleasewouldyoucomeandputitdownonme
  • 한국어 띄어쓰기 검사 패키지로 ko-spacing이나 py-hanspell패키지를 사용

  1. 한국어는 주어 생략이 가능하고 어순이 중요하지 않는다.
  • 같은 의미의 문장을 자유롭게 쓸 수 있다.

    • 나는 점심을 먹었다. 집에서.
    • 나는 집에서 점심을 먹었다.
    • (나는) 집에서 점심을 먹었다.
    • 나는 점심을 집에서 먹었다.
  • Language Model에게는 매우 어려운 상황

  1. 한국어라는 특성상 하나의 음절도 다른 의미를 가질 수가 있다.
  • 한국어는 하나의 음절이 각각 다른 의미를 갖는 경우도 많다.
    • 타는 배, 먹는 배, 사람의 배
    • 하늘에서 내리는 눈, 사람의 눈

📍 설치 코드

!pip install konlpy

📍 konlpy의 모든 형태소 분리기는 명사 추출, 형태소별 토큰화, 형태소 토큰 및 종류를 표기하는 동일 함수가 존재

def print_tokenizer(tokenizer, s):
	
    print(tokenizer.nouns(s))	# 형태소 분리기에서 명사만 추출
    print(tokenizer.morphs(s))	# 각 형태소 별로 토큰화만 시켜준다.
    print(tokenizer.pos(s))	# 각 형태소 별 토큰 및 형태소 종류를 튜플로 표현

한국어 형태소 분리기

Mecab

  • 실무에서 가장 많이 쓰이는 형태소 분리기.
  • 맥이나 리눅스에서만 작동( Windows는 작동 안됨 ) 설치시간이 상당히 오래 걸린다.

Twitter(Okt), 꼬꼬마(kkma), 코모란(Komoran), 한나눔(Hannanum)

  • 속도 자체는 Mecab, 카카오의 Khaii 보다 느리지만 각각의 장단점이 있다.
    • Okt : Stemming, Normalization 기능을 제공
from konlpy.tag import Hannanum, Kkma, Komoran, Okt, Mecab

hannanum = Hannanum()
kkma = Kkma()
komoran = Komoran()
okt = Okt()
mecab = Mecab()

sentence="좋으니 그 사람 솔직히 견디기 버거워"

📍 트위터( Okt )

print_tokenizer(okt, sentence)

~~>
['그', '사람']
['좋으니', '그', '사람', '솔직히', '견디기', '버거워']
[('좋으니', 'Adjective'), ('그', 'Noun'), ('사람', 'Noun'), ('솔직히', 'Adjective'), ('견디기', 'Verb'), ('버거워', 'Adjective')]

📍 꼬꼬마( Kkma )

print_tokenizer(kkma, sentence)

~~>
['사람']
['좋', '으니', '그', '사람', '솔직히', '견디', '기', '버겁', '어']
[('좋', 'VA'), ('으니', 'ECD'), ('그', 'MDT'), ('사람', 'NNG'), ('솔직히', 'MAG'), ('견디', 'VV'), ('기', 'ETN'), ('버겁', 'VA'), ('어', 'ECS')]

📍 코모란( Komoran )

print_tokenizer(komoran, sentence)

~~>
['사람']
['좋', '으니', '그', '사람', '솔직히', '견디', '기', '버거워']
[('좋', 'VA'), ('으니', 'EC'), ('그', 'MM'), ('사람', 'NNG'), ('솔직히', 'MAG'), ('견디', 'VV'), ('기', 'ETN'), ('버거워', 'NA')]

📍 한나눔( Hannanum )

print_tokenizer(hannanum, sentence)

~~>
['사람', '버거워']
['좋', '으니', '그', '사람', '솔직히', '견디', '기', '버거워']
[('좋', 'P'), ('으니', 'E'), ('그', 'M'), ('사람', 'N'), ('솔직히', 'M'), ('견디', 'P'), ('기', 'E'), ('버거워', 'N')]

📍 Mecab

print_tokenizer(mecab, sentence)

~~>
['사람']
['좋', '으니', '그', '사람', '솔직히', '견디', '기', '버거워']
[('좋', 'VA'), ('으니', 'EC'), ('그', 'MM'), ('사람', 'NNG'), ('솔직히', 'MAG'), ('견디', 'VV'), ('기', 'ETN'), ('버거워', 'VA+EC')]

문장 토크나이징

단순하게 물음표, 느낌표, 온점( . )으로만 문장을 잘라내면 안된다.

[English] sent_tokenize

text = "Since I'm actively looking for Ph.D. students. I get the same question a dozen times every year."

📍 단순하게 온점으로만 토크나이징 한 경우

print(text.split('.'))

~~>
["Since I'm actively looking for Ph", 'D', ' students', ' I get the same question a dozen times every year', '']

📍 Tokenizer 사용

from nltk.tokenize import sent_tokenize

print(sent_tokenize(text))

~~>
["Since I'm actively looking for Ph.D. students.", 'I get the same question a dozen times every year.']

📍 단순하게 온점으로만 토크나이징 한 경우

text = "My IP Address is 192.168.56.51. Hello World!"
print(text.split("."))

~~>
['My IP Address is 192', '168', '56', '51', ' Hello World!']

📍 Tokenizer 사용

print(sent_tokenize(text))

~~>
['My IP Address is 192.168.56.51.', 'Hello World!']

[Korean] kss

📍 설치 코드

!pip install kss
import kss

text = "제 아이피는 192.168.56.21 입니다. 자연어 처리가 재미있나요?ㅋㅋㅋ"

print(kss.split_sentences(text))

~~>
['제 아이피는 192.168.56.21 입니다.', '자연어 처리가 재미있나요?ㅋㅋㅋ']

[Korean] 띄어쓰기 및 맞춤법 정리

  • KoSpacing

📍 설치 코드

!pip install git+https://github.com/haven-jeon/PyKoSpacing.git
  • Hanspell

📍 설치 코드

!pip install git+https://github.com/ssut/py-hanspell.git
from hanspell import spell_checker # 한국어 맞춤법 관리
from pykospacing import spacing # 한국어 띄어쓰기 관리
KoSpacing 사용하기
text = "4번놀고있지.4번은팀워크가없어.4번은개인주의야.4번은혼자밖에생각하지않아."
spacing_text = spacing(text)
print(spacing_text)

~~>
4번 놀고 있지.4번은 팀워크가 없어.4번은 개인주의야.4번은 혼자 밖에 생각하지 않아.
Hanspell 사용하기
  • 맞춤법 검사 및 교정
  • KoSpacing 처럼 띄어쓰기 교정도 가능

📍 띄어쓰기 검사 및 교정

hanspell_text = spell_checker.check(text)
print(hanspell_text.checked)

~~>
4번 놀고 있지. 4번은 팀워크가 없어. 4번은 개인주의야. 4번은 혼자밖에 생각하지 않아.

📍 맞춤법 검사

text = "맞춤뻡 틀리면 외 않되?"
hanspell_text = spell_checker.check(text).checked
print(hanspell_text)

~~>
맞춤법 틀리면 왜 안돼?

텍스트 정제 및 정규화

  • 웹이나 채팅 로그 등에서 데이터를 수집하면 항상 필요 없는 데이터가 있는데 이러한 데이터를 제거하여 텍스트 데이터를 깨끗이 만들어 가는 과정
  1. 정규 표현식을 이용한 제거
  • 같은 의미를 가지고 있다면 하나로 통일하기
  • 정규화는 다양하게 표현되는 텍스트를 하나로 통합하여 데이터에 대한 복잡도를 줄여 나간다.
  1. 등장 빈도가 적은 단어 제거
  2. 길이가 짧은 단어 제거
  3. 불용어( stopwords ) 제거

[English] 정규화 - Stemming 정규화 과정

  • 어간(stem)을 추출하는 과정 - 영어는 사전에 없는 이상한 단어가 종종 나온다.

    Beautiful : beaut
    Allowance ; allow
    Medical : medic
    books : book
    this : thi

from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenize

porter_stemmer = PoterStemmer()
text = "This was not the map we found in Billy Bones's chest, but an accurate copy, complete in all things--names and heights and soundings--with the single exception of the red crosses and the written notes."

# Stemming : 단어에 대한 어간을 추출하는 과정이기 때문에 단어 토큰화 부터 수행
words = word_tokenize(text)
print(words)

~~>
['This', 'was', 'not', 'the', 'map', 'we', 'found', 'in', 'Billy', 'Bones', "'s", 'chest', ',', 'but', 'an', 'accurate', 'copy', ',', 'complete', 'in', 'all', 'things', '--', 'names', 'and', 'heights', 'and', 'soundings', '--', 'with', 'the', 'single', 'exception', 'of', 'the', 'red', 'crosses', 'and', 'the', 'written', 'notes', '.']
stem_list = [porter_stemmer.stem(w) for w in words]
print(stem_list)

~~>
['thi', 'wa', 'not', 'the', 'map', 'we', 'found', 'in', 'billi', 'bone', "'s", 'chest', ',', 'but', 'an', 'accur', 'copi', ',', 'complet', 'in', 'all', 'thing', '--', 'name', 'and', 'height', 'and', 'sound', '--', 'with', 'the', 'singl', 'except', 'of', 'the', 'red', 'cross', 'and', 'the', 'written', 'note', '.']
  • 언어의 단어 모양이 변경되는 형식으 절대 자연어 생성 모델을 만들때는 사용하면 안된다.
  • 단순 분류나 회귀문제를 풀어야 할 때는 효과가 있을 수도 있다.
words = ["Serialize", "Allowance", "Allowed", "Medical", "Pretty", "Lovely", "Beautiful"]
print([porter_stemmer.stem(w) for w in words])

~~>
['serial', 'allow', 'allow', 'medic', 'pretti', 'love', 'beauti']

[Korean] 정규화 - Okt 활용 ( Stemming, Normalization )

okt = Okt()

text = "4번 놀고 있지. 4번은 팀워크가 없어. 4번은 개인주의야. 4번은 혼자밖에 생각하지 않아."

print(okt.morphs(text)) # 일반적인 형태소 분리
print(okt.morphs(text, stem=True)) # 어간이 추출된 형태소 분리 ( 동사와 형용사에 대한 어간을 추출 )

~~>
['4', '번', '놀고', '있지', '.', '4', '번은', '팀워크', '가', '없어', '.', '4', '번은', '개인주의', '야', '.', '4', '번은', '혼자', '밖에', '생각', '하지', '않아', '.']
['4', '번', '놀다', '있다', '.', '4', '번은', '팀워크', '가', '없다', '.', '4', '번은', '개인주의', '야', '.', '4', '번은', '혼자', '밖에', '생각', '하다', '않다', '.']
print(okt.pos(text))
print(okt.pos(text, temp=True))

~~>
[('4', 'Number'), ('번', 'Noun'), ('놀고', 'Verb'), ('있지', 'Adjective'), ('.', 'Punctuation'), ('4', 'Number'), ('번은', 'Noun'), ('팀워크', 'Noun'), ('가', 'Josa'), ('없어', 'Adjective'), ('.', 'Punctuation'), ('4', 'Number'), ('번은', 'Noun'), ('개인주의', 'Noun'), ('야', 'Josa'), ('.', 'Punctuation'), ('4', 'Number'), ('번은', 'Noun'), ('혼자', 'Noun'), ('밖에', 'Josa'), ('생각', 'Noun'), ('하지', 'Verb'), ('않아', 'Verb'), ('.', 'Punctuation')]
[('4', 'Number'), ('번', 'Noun'), ('놀다', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation'), ('4', 'Number'), ('번은', 'Noun'), ('팀워크', 'Noun'), ('가', 'Josa'), ('없다', 'Adjective'), ('.', 'Punctuation'), ('4', 'Number'), ('번은', 'Noun'), ('개인주의', 'Noun'), ('야', 'Josa'), ('.', 'Punctuation'), ('4', 'Number'), ('번은', 'Noun'), ('혼자', 'Noun'), ('밖에', 'Josa'), ('생각', 'Noun'), ('하다', 'Verb'), ('않다', 'Verb'), ('.', 'Punctuation')]
text = "딥러닝 진짜 어렵닼ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 이렇게 어려울지 몰랐어옄ㅋㅋㅋㅋㅋㅋㅋㅋ"

print(okt.pos(text))
print(okt.pos(text, norm=True)) # 정규화

~~>
[('딥', 'Noun'), ('러닝', 'Noun'), ('진짜', 'Noun'), ('어렵닼', 'Noun'), ('ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ', 'KoreanParticle'), ('이렇게', 'Adverb'), ('어려울지', 'Verb'), ('몰랐어', 'Verb'), ('옄', 'Noun'), ('ㅋㅋㅋㅋㅋㅋㅋㅋ', 'KoreanParticle')]
[('딥', 'Noun'), ('러닝', 'Noun'), ('진짜', 'Noun'), ('어렵다', 'Adjective'), ('ㅋㅋㅋ', 'KoreanParticle'), ('이렇게', 'Adverb'), ('어려울지', 'Verb'), ('몰랐어여', 'Verb'), ('ㅋㅋㅋ', 'KoreanParticle')]

📍 어간 추출(Stem), 정규화를 동시에

print(okt.pos(text, stem=True, norm=True))

~~>
[('딥', 'Noun'), ('러닝', 'Noun'), ('진짜', 'Noun'), ('어렵다', 'Adjective'), ('ㅋㅋㅋ', 'KoreanParticle'), ('이렇게', 'Adverb'), ('어리다', 'Verb'), ('모르다', 'Verb'), ('ㅋㅋㅋ', 'KoreanParticle')]

[Korean] 이모티콘이나 의미없이 반복되는 문자 정제

  • ㅋㅋ, ㅋㅋㅋㅋㅋ, ㅋㅋㅋㅋㅋㅋㅋ, ㅎㅎㅎ,ㅎㅎㅎㅎㅎ,ㅎㅎㅎㅎㅎㅎ
  • 잘한다ㅠㅠㅠㅠㅠㅠㅠ : 긍정의 표현으로 많이 사용? -> 잘한다 ㅠㅠ
  • 잘한다ㅋㅋㅋㅋㅋㅋㅋ : 긍정 또는 부정의 표현으로 많이 사용 -> 잘한다 ㅋㅋ

📍 이모티콘이나 의미없이 반복되는 문자들을 정제하기 위한 패키지

!pip install soynip
from soynip.normalizer import emoticon_normalize

print(emoticon_normalize("앜ㅋㅋㅋ 이 게임 존잼쓰ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ", num_repeats=2))
print(emoticon_normalize("앜ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 이 게임 존잼쓰ㅠㅠㅠㅠㅠㅠㅠㅠ", num_repeats=2))
print(emoticon_normalize("앜ㅋㅋㅋㅋㅋㅋ 이 게임 존잼쓰ㅠㅠㅠㅠㅠㅠㅠ", num_repeats=2))

~~>
아ㅋㅋ 이 게임 존잼쓰ㅠㅠ
아ㅋㅋ 이 게임 존잼쓰ㅠㅠ
아ㅋㅋ 이 게임 존잼쓰ㅠㅠ

📍 반복되는 문자를 정규화

from soynlp.normalizer import repeat_normalize

print(repeat_normalize("문을 쿵쿵쿵쿵쿵쿵쿵쿵쿵쿵쿵쿵쿵쿵 두드렸다.", num_repeats=2))
print(repeat_normalize("문을 쿵쿵쿵쿵쿵쿵쿵 두드렸다.", num_repeats=2))
print(repeat_normalize("문을 쿵쿵쿵쿵 두드렸다.", num_repeats=2))

~~>
문을 쿵쿵 두드렸다.
문을 쿵쿵 두드렸다.
문을 쿵쿵 두드렸다.

텍스트 정제( Cleaning )

  • 정규식을 이용한 정제 방법

    • 특수기호나 의미 없는 공백등을 정규식을 활용하여 제거
  • 불용어 정제( stopwords )

    • 빈도수가 낮거나, 의미 없는 단어를 문장에서 제거하는 방법
import re	# 정규식을 사용하기 위해 re모듈 임포트

eng_sent = "\n\n\n\n\n\n\nYeah, do you expect people to read the FAQ, etc. and actually accept hard\natheism?  No, you need a little leap of faith, Jimmy.  Your logic runs out\nof steam!\n\n\n\n\n\n\n\nJim,\n\nSorry I can't pity you, Jim.  And I'm sorry that you have these feelings of\ndenial about the faith you need to get by.  Oh well, just pretend that it will\nall end happily ever after anyway.  Maybe if you start a new newsgroup,\nalt.atheist.hard, you won't be bummin' so much?\n\n\n\n\n\n\nBye-Bye, Big Jim.  Don't forget your Flintstone's Chewables!  :) \n--\nBake Timmons, III"

print(eng_sent)

~~>







Yeah, do you expect people to read the FAQ, etc. and actually accept hard
atheism?  No, you need a little leap of faith, Jimmy.  Your logic runs out
of steam!







Jim,

Sorry I can't pity you, Jim.  And I'm sorry that you have these feelings of
denial about the faith you need to get by.  Oh well, just pretend that it will
all end happily ever after anyway.  Maybe if you start a new newsgroup,
alt.atheist.hard, you won't be bummin' so much?






Bye-Bye, Big Jim.  Don't forget your Flintstone's Chewables!  :) 
--
Bake Timmons, III

📍 영문 알파벳이 아닌 것은 모두 공백으로 치환

  • 위 문장에서 영어가 아닌 것들을 전부다 공백으로 치환
  • re모듈의 sub함수가 replace의 역할을 한다.
eng_sent = re.sub("[^a-zA-Z]", # [] : 안에 있는 글자 1개, ^ : 시작하는게 아닌 것, a-z : 알파벳 소문자 a~z, A-Z 알파벳 대문자 A ~ Z
                  " ",
                  eng_sent)
print(eng_sent)

~~>
       Yeah  do you expect people to read the FAQ  etc  and actually accept hard atheism   No  you need a little leap of faith  Jimmy   Your logic runs out of steam         Jim   Sorry I can t pity you  Jim   And I m sorry that you have these feelings of denial about the faith you need to get by   Oh well  just pretend that it will all end happily ever after anyway   Maybe if you start a new newsgroup  alt atheist hard  you won t be bummin  so much        Bye Bye  Big Jim   Don t forget your Flintstone s Chewables          Bake Timmons  III
       

📍 예를 들어 4글자 이상인 단어만 추출해서 새롭게 문장을 만들기

eng_sent = " ".join([w for w in eng_sent.split() if len(w) > 3])
print(eng_sent)

~~>
Yeah expect people read actually accept hard atheism need little leap faith Jimmy Your logic runs steam Sorry pity sorry that have these feelings denial about faith need well just pretend that will happily ever after anyway Maybe start newsgroup atheist hard bummin much forget your Flintstone Chewables Bake Timmons

[Korean] 정규표현식 정제

  • 한국어 문장에서 한글만 추출하는 정규식 : `[ㄱ-ㅎㅏ-ㅣ가-힣]
kor_sent = "와 오늘 날씨 실화냐...ㅋㅋㅋㅋ 엄청 더워서 졸려요.."
kor_sent

~~>
'와 오늘 날씨 실화냐...ㅋㅋㅋㅋ 엄청 더워서 졸려요..'
kor_sent = re.sub("[^ㄱ-ㅎㅏ-ㅣ가-힣]", " ", kor_sent)
kor_sent

~~>
'와 오늘 날씨 실화냐   ㅋㅋㅋㅋ 엄청 더워서 졸려요  '

📍 공백이 2개 이상이면 사라지게 하기

kor_sent = re.sub("[ ]{2,}", " ", kor_sent)
kor_sent

~~>
'와 오늘 날씨 실화냐 ㅋㅋㅋㅋ 엄청 더워서 졸려요 '

불용어( stopwords ) 정제

  • 필요 없는 짧은 단어나 의미가 없는 단어들을 제거

[English] 불용어 정제

📍 nltk 모듈

import nltk

nltk.download('stopwords')	# 불용어 단어 사전 다운로드

print(list(stopwords.words('english')))	# 불용어도 비즈니스에 맞게 따로 설정할 수 있어야 한다.

~~>
['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're", "you've", "you'll", "you'd", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', "she's", 'her', 'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', "that'll", 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', "don't", 'should', "should've", 'now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', "aren't", 'couldn', "couldn't", 'didn', "didn't", 'doesn', "doesn't", 'hadn', "hadn't", 'hasn', "hasn't", 'haven', "haven't", 'isn', "isn't", 'ma', 'mightn', "mightn't", 'mustn', "mustn't", 'needn', "needn't", 'shan', "shan't", 'shouldn', "shouldn't", 'wasn', "wasn't", 'weren', "weren't", 'won', "won't", 'wouldn', "wouldn't"]
sample_text = "Family is not an important thing. It's everything"

# 사람이 직접 만든 불용어 사전에는 중복이 존재할 수도 있다. 따라서 중복을 제거
stop_words = set(stopwords.words("english"))

word_tokens = word_tokenize(sample_text.lower()) # 문장을 소문자로 만들어서 토큰화 하기

result = [ w for w in word_tokens if w not in stop_words ]

print("원본 : {}".format(word_tokens))
print("불용어 제거 후 : {}".format(result))

~~>
원본 : ['family', 'is', 'not', 'an', 'important', 'thing', '.', 'it', "'s", 'everything']
불용어 제거 후 : ['family', 'important', 'thing', '.', "'s", 'everything']

[Korean] 불용어 정제

  • 한국어 불용어 사전은 직접 만들거나 구글링해서 찾으시면 된다.
  • 개발자가 직접 정의하는게 일반적
sample_text="와 이런 것도 영화라고 차라리 뮤직비디오를 만드는 게 나을 뻔"
word_tokens = mecab.morphs(sample_text)

print(word_tokens)

~~>
['와', '이런', '것', '도', '영화', '라고', '차라리', '뮤직', '비디오', '를', '만드', '는', '게', '나을', '뻔']

📍 개발자가 임의로 불용어를 선정

  • 일반적으로 조사나 접속사들이 불용어로 선정
stop_words = ['의','가','이','은','들','는','좀','잘','걍','과','도','를','으로','자','에','와','한','하다', '것', '게']

result = [w for w in word_tokens if not w in stop_words]

print("원문 : {}".format(word_tokens))
print("불용어 제거 후 : {}".format(result))

~~>
원문 : ['와', '이런', '것', '도', '영화', '라고', '차라리', '뮤직', '비디오', '를', '만드', '는', '게', '나을', '뻔']
불용어 제거 후 : ['이런', '영화', '라고', '차라리', '뮤직', '비디오', '만드', '나을', '뻔']

✨✨✨ 자연어 처리에서 데이터 정제는 따로 정해진 루틴이 없다보니 각자의 비즈니스에 맞게 문자열 편집능력을 활용하는 것이 중요하다.

profile
data science!!, data analyst!! ///// hello world

0개의 댓글