rueki
텍스트 전처리 - 정수 인코딩(Integer Encoding) 본문
본문은 https://wikidocs.net/31766 를 참고해서 작성한 글입니다.
컴퓨터는 텍스트보다는 숫자를 처리하기가 더 쉽다. 그래서 텍스트를 숫자로 바꾸는 것이 필요하며, 중요하다.
바꾸기 전에, 먼저 고유 숫자로 매핑시키는 작업이 필요할 때가 있다.
1000개의 단어가 있으면, 각 단어에 0부터 999까지 인덱스 번호를 부여하는 것이다.
인덱스 부여 기준은 보통 단어에 대한 빈도수로 정렬한 뒤에 부여한다.
from nltk.tokenize import sent_tokenize
text = "A barber is a person. a barber is good person. a barber is huge person. he Knew A Secret! The Secret He Kept is huge secret. Huge secret. His barber kept his word. a barber kept his word. His barber kept his secret. But keeping and keeping such a huge secret to himself was driving the barber crazy. the barber went up a huge mountain."
text = sent_tokenize(text)
print(text)
예제의 문장을 문장 토큰화를 수행
['A barber is a person.', 'a barber is good person.',
'a barber is huge person.', 'he Knew A Secret!', 'The Secret He Kept is huge secret.',
'Huge secret.', 'His barber kept his word.', 'a barber kept his word.',
'His barber kept his secret.',
'But keeping and keeping such a huge secret to himself was driving the barber crazy.',
'the barber went up a huge mountain.']
문장 단위로 토큰화가 되었으니, 단어 토큰화를 수행, 정제도 같이 한다.
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
from collections import Counter
voca = Counter()
stop_words = set(stopwords.words('english'))
sentence = []
for i in text:
sentence = word_tokenize(i)#토큰화 수행
result =[]
for word in sentence:
word = word.lower()#단어 소문자화해서 단어 개수 줄이기
if word not in stop_words:#불용어 제거
if len(word)>2: #길이 2 이하인 단어제거
result.append(word)
voca[word] = voca[word]+1
sentence.append(result)
print(sentence)
['the', 'barber', 'went', 'up', 'a', 'huge', 'mountain', '.', ['barber', 'went', 'huge', 'mountain']]
print(voca)
Counter({'barber': 8, 'secret': 6, 'huge': 5, 'kept': 4,
'person': 3, 'word': 2, 'keeping': 2, 'good': 1, 'knew': 1,
'driving': 1, 'crazy': 1, 'went': 1, 'mountain': 1})
텍스트 전처리를 하고 각 단어에 대해 카운트하여 빈도 수를 기록하였다.
voca_sorted = sorted(voca.items(), key=lambda x:x[1], reverse = True)
print(voca_sorted)
[('barber', 8), ('secret', 6), ('huge', 5), ('kept', 4), ('person', 3),
('word', 2), ('keeping', 2), ('good', 1), ('knew', 1), ('driving', 1),
('crazy', 1), ('went', 1), ('mountain', 1)]
빈도수 순으로 정렬을 하였다. 이제 빈도 수 높은 단어부터 해서 인덱스를 부여해보도록 하겠다.
word_to_index= {}
i = 0
for (word, frequency) in voca_sorted:
if frequency > 1:
i = i + 1
word_to_index[word] = i
print(word_to_index)
{'barber': 1, 'secret': 2, 'huge': 3, 'kept': 4, 'person': 5, 'word': 6, 'keeping': 7}
케라스로 위의 예제를 전처리 해보자
from keras.preprocessing.text import Tokenizer
text=["A barber is a person. a barber is good person. a barber is huge person. he Knew A Secret! The Secret He Kept is huge secret. Huge secret. His barber kept his word. a barber kept his word. His barber kept his secret. But keeping and keeping such a huge secret to himself was driving the barber crazy. the barber went up a huge mountain."]
t = Tokenizer()
t.fit_on_texts(text) # 텍스트의 리스트를 가지고 단어 빈도수에 기반한 사전 만든다.
print(t.word_index)
{'a': 1, 'barber': 2, 'secret': 3, 'huge': 4, 'his': 5, 'is': 6,
'kept': 7, 'person': 8, 'the': 9, 'he': 10, 'word': 11, 'keeping': 12,
'good': 13, 'knew': 14, 'but': 15, 'and': 16, 'such': 17, 'to': 18,
'himself': 19, 'was': 20, 'driving': 21, 'crazy': 22,
'went': 23, 'up': 24, 'mountain': 25}
단어의 빈도 수에 따라 인덱스 숫자를 부여하였다.
print(t.word_counts)
OrderedDict([('a', 8), ('barber', 8), ('is', 4), ('person', 3),
('good', 1), ('huge', 5), ('he', 2), ('knew', 1), ('secret', 6),
('the', 3), ('kept', 4), ('his', 5), ('word', 2), ('but', 1), ('keeping', 2),
('and', 1), ('such', 1), ('to', 1), ('himself', 1), ('was', 1), ('driving', 1),
('crazy', 1), ('went', 1), ('up', 1), ('mountain', 1)])
단어의 빈도 수를 확인할 수가 있다.
print(t.texts_to_sequences(text))
[[1, 2, 6, 1, 8, 1, 2, 6, 13, 8, 1, 2, 6, 4, 8, 10, 14, 1, 3, 9, 3, 10, 7, 6, 4, 3, 4, 3, 5, 2, 7, 5, 11, 1, 2, 7, 5, 11, 5, 2, 7, 5, 3, 15, 12, 16, 12, 17, 1, 4, 3, 18, 19, 20, 21, 9, 2, 22, 9, 2, 23, 24, 1, 4, 25]]
25개의 모든단어에 대해 인덱스한 값이 나오는데, 불용어처리를 안 해주었기 때문이다.
keras로 처리가 가능하지만, 처음 접하는 사람에게는 counter()를 통해서 하는 것이 이해가 더 될 것이다.
###
t = Tokenizer(num_words=숫자)과 같은 방법으로 빈도수가 높은 상위 몇 개의 단어만 남기고 진행시키는 방법이 케라스 토크나이저에도 공식적으로 존재는 하지만, 이를 사용하면 t.texts_to_sequences(text)에서는 적용이 되면서 t_word_index와 t.word_counts에는 여전히 모든 단어가 인식되는 등의 사용자에게 혼란을 주는 문제가 존재합니다.
word_frequency = [w for w, c in t.word_counts.items() if c<2] #빈도수가 2 미만단어를 w로 저장
for w in word_frequency:
del t.word_index[w] # 인덱스 정보 삭제
del t.word_counts[w] # 카운트 정보 삭제
print(t.texts_to_sequences(text))
print(t.word_index)
[[1, 2, 6, 1, 8, 1, 2, 6, 8, 1, 2, 6, 4, 8, 10, 1, 3, 9, 3, 10, 7, 6, 4, 3, 4, 3, 5, 2, 7, 5, 11, 1, 2, 7, 5, 11, 5, 2, 7, 5, 3, 12, 12, 1, 4, 3, 9, 2, 9, 2, 1, 4]]
{'a': 1, 'barber': 2, 'secret': 3, 'huge': 4, 'his': 5, 'is': 6, 'kept': 7, 'person': 8, 'the': 9, 'he': 10, 'word': 11, 'keeping': 12}
enumerate로 정수 인코딩을 진행해보자
text=[['barber', 'person'], ['barber', 'good', 'person'], ['barber', 'huge', 'person'], ['knew', 'secret'], ['secret', 'kept', 'huge', 'secret'], ['huge', 'secret'], ['barber', 'kept', 'word'], ['barber', 'kept', 'word'], ['barber', 'kept', 'secret'], ['keeping', 'keeping', 'huge', 'secret', 'driving', 'barber', 'crazy'], ['barber', 'went', 'huge', 'mountain']]
문장 토큰화가 위와 같이 진행되있다고 가정하고 단어 집합을 만들기 위해 문장 경계인 [,]을 제거하고 하나의 리스트로 만들자.
vocab = sum(text, [])
print(vocab)
['barber', 'person', 'barber', 'good', 'person', 'barber', 'huge', 'person', 'knew', 'secret', 'secret', 'kept', 'huge', 'secret', 'huge', 'secret', 'barber', 'kept', 'word', 'barber', 'kept', 'word', 'barber', 'kept', 'secret', 'keeping', 'keeping', 'huge', 'secret', 'driving', 'barber', 'crazy', 'barber', 'went', 'huge', 'mountain']
빈도 순대로 정렬하고 중복 결과를 제거 해보자
vocab_sorted=(sorted(set(vocab)))
print(vocab_sorted)
['barber', 'crazy', 'driving', 'good', 'huge', 'keeping', 'kept', 'knew', 'mountain', 'person', 'secret', 'went', 'word']
enumerate를 실행해보자
word_to_index = {word:index+1 for index, word in enumerate(vocab_sorted)} #인덱스 1부터 부여
print(word_to_index)
{'barber': 1, 'crazy': 2, 'driving': 3, 'good': 4, 'huge': 5, 'keeping': 6, 'kept': 7, 'knew': 8, 'mountain': 9, 'person': 10, 'secret': 11, 'went': 12, 'word': 13}
이로서 여러가지 방법을 통해 정수 인코딩을 하고, 인덱스 부여까지 해보았다.
'DL > NLP' 카테고리의 다른 글
언어 모델(Language Model) (0) | 2019.07.02 |
---|---|
텍스트 전처리 - 원-핫 인코딩(One-hot encoding) (0) | 2019.07.02 |
텍스트 전처리 - 단어 분리(Subword Segmentation) (0) | 2019.07.01 |
텍스트 전처리 - 불용어(Stopword) (0) | 2019.07.01 |
텍스트 전처리 - 어간 추출과 표제어 추출 (0) | 2019.07.01 |