해당 내용은 멋쟁이사자처럼 AI School 오늘코드 박조은 강사의 자료입니다.
형태소 분석
KoNLPy: 파이썬 한국어 NLP — KoNLPy documentation
- 형태소 분석 전 문자 전처리 (map을 통해 일괄 적용 후 사용)
# 정규표현식
import re
def preprocessing(text):
# 한글, 영문, 숫자만 남기고 모두 제거하도록 합니다.
text = re.sub('[^가-힣ㄱ-ㅎㅏ-ㅣa-zA-Z0-9]', ' ', text)
# 중복으로 생성된 공백값을 제거합니다.
text = re.sub('[\s]+', ' ', text)
# 영문자를 소문자로 만듭니다.
text = text.lower()
return text
형태소 분석기마다 품사를 태깅하는 방법이 다 다르다.
코렙에 KoNLPy 설치
!pip install konlpy --upgrade
Kkma
from konlpy.tag import Kkma
kkma = Kkma()
kkma.morphs(u'공부를 하면 할수록 모르는게 많다는 것을 알게 됩니다.')
kkma.nouns(small_text)
kkma.pos(u'공부를 하면 할수록 모르는게 많다는 것을 알게 됩니다.')
Pecab
따끈따끈한 pecab. mecab을 파이썬 온리로 구현했다고한다.
Pecab : Pecab is pure python Korean morpheme analyzer based on Mecab.
출처: https://github.com/hyunwoongko/pecab
from pecab import PeCab
pecab = PeCab()
pecab.pos("저는 삼성디지털프라자에서 휘센 선풍기를 샀어요.")
어간 추출
형태론 및 정보 검색 분야에서 어형이 변형된 단어로부터 접사 등을 제거하고 그 단어의 어간을 분리해 내는 것을 의미한다. 여기서 어간은 반드시 어근과 같아야 할 필요는 없으며, 어근과 차이가 있더라도 관련이 있는 단어들이 일정하게 동일한 어간으로 맵핑되게 하는 것이 어간 추출의 목적이다. 어간 추출 프로그램은 흔히 스테밍 알고리즘(stemming algorithm) 또는 스테머(stemmer)라 불린다.
Okt
# Okt - steming 기능을 제공
from konlpy.tag import Okt
okt = Okt()
okt.pos(small_text)
okt.pos(small_text, stem=True)
okt.pos(u"안녕할까요. 반가웠습니다!", stem=True)
조사, 어미, 구두점을 제거하는 함수 만들기
# 형태소 분석기(Okt) 불러오기
# ['Josa', 'Eomi', 'Punctuation'] 조사, 어미, 구두점 제거
# 전체 텍스트에 적용해 주기 위해 함수를 만듭니다.
# 1) 텍스트를 입력받습니다.
# 2) 품사태깅을 합니다. [('문의', 'Noun'), ('하다', 'Verb'), ('?!', 'Punctuation')]
# 3) 태깅 결과를 받아서 순회 합니다.
# 4) 하나씩 순회 했을 때 튜플 형태로 가져오게 됩니다. ('을', 'Josa')
# 5) 튜플에서 1번 인덱스에 있는 품사를 가져옵니다.
# 6) 해당 품사가 조사, 어미, 구두점이면 제외하고 append 로 인덱스 0번 값만 다시 리스트에 담아줍니다.
# 7) " ".join() 으로 공백문자로 연결해 주면 다시 문장이 됩니다.
# 8) 전처리 후 완성된 문장을 반환합니다.
def okt_clean(text):
clean_text = []
for word in okt.pos(text, norm=True, stem=True):
if word[1] not in ['Josa', 'Eomi', 'Punctuation']:
clean_text.append(word[0])
return ' '.join(clean_text)
# progress map을 활용해서 적용
train['title'] = train['title'].progress_map(okt_clean)
test['title'] = test['title'].progress_map(okt_clean)
어간 추출(Stemming)과 표제어 표기법(Lemmatization) 차이
어간 추출은 단어 형식을 의미가 있거나 무의미할 수 있는 줄기로 축소, 원형을 잃을 수 있음
표제어 표기법은 단어 형식을 언어학적으로 유효한 의미로 축소, 원형을 보존할 수 있음
'creating'이라는 단어를 어간 추출로 표현하면 'creat'가 되고, 표제어 표기법으로 표현하면 'create'가 된다.
토크나이저(Tokenizer)
API Document: https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/text/Tokenizer
이 클래스를 사용하면 각 텍스트를 일련의 정수 또는 단어 수에 따라 각 토큰의 계수가 이진일 수 있는 벡터로 변환하여,
텍스트 말뭉치를 벡터화할 수 있다.(tf-idf 기반)
매개변수
num_words : 단어 빈도에 따라 유지할 최대 단어 수입니다. 가장 일반적인 단어 만 유지됩니다.
filters : 각 요소가 텍스트에서 필터링될 문자인 문자열입니다. 기본값은 문자를 제외한 모든 구두점과 탭 및 줄 바꿈 입니다.
lower : 부울. 텍스트를 소문자로 변환할지 여부입니다.
split : str. 단어 분할을 위한 구분 기호입니다.
char_level : True이면 모든 문자가 토큰으로 처리됩니다.
oov_token : 주어진 경우, 그것은 word_index에 추가되고 text_to_sequence 호출 중에 어휘 밖의 단어를 대체하는 데 사용됩니다.
- Tokenizer 인스턴스를 생성
- fit_on_texts와 word_index를 사용하여 key value로 이루어진 딕셔너리를 생성
- texts_to_sequences를 이용하여 text 문장을 숫자로 이루어진 리스트로 변경
- 마지막으로 pad_sequences를 이용하여 리스트의 길이를 통일화
# Sample code
tf.keras.preprocessing.text.Tokenizer(
num_words=None,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True,
split=' ',
char_level=False,
oov_token=None,
analyzer=None,
**kwargs
적용 예시
from tensorflow.keras.preprocessing.text import Tokenizer
vocab_size = 7
tokenizer = Tokenizer(num_words=vocab_size)
tokenizer.fit_on_texts(corpus)
# tokenizer의 word_index 속성은 단어와 숫자의 키-값 쌍을 포함하는 딕셔너리를 반환
# 이때, 반환 시 자동으로 소문자로 변환되어 들어가며, 느낌표나 마침표 같은 구두점은 자동으로 제거
word_to_index = tokenizer.word_index
word_to_index
word_to_index.items()
word_to_index.keys()
word_to_index.values()
# 단어별 빈도수를 확인해 봅니다.
wc = tokenizer.word_counts
pd.DataFrame(wc.items()).set_index(0).sort_values(by=1).T
# texts_to_sequences를 이용하여 text 문장을 숫자로 이루어진 리스트로 변경합니다.
corpus_sequences = tokenizer.texts_to_sequences(corpus)
corpus_sequences
num_words, oov_token 활용
oov_token이 주어진 경우, word_index에 추가되고 text_to_sequence 호출 중에 어휘 밖의 단어를 대체하는 데 사용된다.
corpus = ["SEOUL 서울 코로나 상생지원금 문의입니다.?",
"인천 지하철 운행시간 문의입니다.!",
"Bus 버스 운행시간 문의입니다.#"]
# num_words=10, oov_token="<oov>"을 적용했을 때의 차이
tokenizer = Tokenizer(num_words=10, oov_token="<oov>")
tokenizer.fit_on_texts(corpus)
print(tokenizer.word_index)
print(corpus)
corpus_sequences = tokenizer.texts_to_sequences(corpus)
corpus_sequences
시퀀스 방식: 어휘 사전을 만들고, 해당 어휘의 등장 순서대로 숫자로 변환 -> RNN에 활용
Padding
문장의 길이 맞춰주기
- 정수 배열의 길이가 모두 같도록 패딩(padding)을 추가해 max_length * num_reviews 크기의 정수 텐서를 만든다.
- 이런 형태의 텐서를 다룰 수 있는 임베딩(embedding) 층을 신경망의 첫 번째 층으로 사용할 수 있다.
- 텍스트의 길이가 같아야 하므로 pad_sequences 함수를 사용
from tensorflow.keras.preprocessing.sequence import pad_sequences
# padding='pre'
pads = pad_sequences(corpus_sequences, maxlen=10)
print(corpus)
print(word_to_index)
print(pads)
np.array(pads)
응용 참고
corpus2 = ["코로나 거리두기와 코로나 상생지원금 문의입니다.",
"지하철 운행시간과 지하철 요금 문의입니다.",
"지하철 승강장 문의입니다.",
"코로나 선별진료소 문의입니다.",
"버스 운행시간 문의입니다.",
"버스 터미널 위치 안내입니다.",
"코로나 거리두기 안내입니다.",
"택시 승강장 문의입니다."
]
tokenizer = Tokenizer(num_words=10, oov_token="<oov>")
tokenizer.fit_on_texts(corpus2)
corpus_sequences = tokenizer.texts_to_sequences(corpus2)
pads = pad_sequences(corpus_sequences, maxlen=10, padding='pre', truncating='pre', value=0.0)
print(word_to_index)
np.array(pads)