토큰화, 정제 및 정규화 등의 전처리 작업을 마친 후에, 컴퓨터가 데이터 처리를 더 빠르게 하도록 텍스트를 수치화 하는 것을 정수 인코딩(Integer Encoding) 이라 한다.


결론 : keras 의 Tokenizer 를 사용하면 쉽게 해결



정수 인코딩 과정

  1. 문장 토큰화, 정제 및 일반화, 단어 토큰화.
  2. 빈도수를 기록하여 빈도수가 높은 순서대로 정렬 
  3. 자연어 처리에서 빈도수가 낮은 단어는 의미를 가지지 않을 가능성이 높으므로 제외
  4. 빈도수 순서로 정렬된 단어에 순차적으로 인덱스 부여
  5. 각 단어를 부여된 인덱스로 맵핑.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from nltk.tokenize import sent_tokenize
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
 
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)  # 문장 토큰화
 
vocab = {}
sentences = []
stop_words = set(stopwords.words('english'))
 
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:  # 3자 이상의 단어만 수집
                result.append(word)
                if word not in vocab:  # 단어 중복 제거
                    vocab[word] = 0
                vocab[word] += 1  # 빈도수 계산
 
    sentences.append(result)  # 문장별 정제된 단어 리스트
 
vocab_sorted = sorted(vocab.items(), key=lambda x: x[1], reverse=True)  # 빈도수 높은 순으로 단어 정렬
word_to_index = {}
= 0
for (word, frequency) in vocab_sorted:
    if frequency > 1:  # 빈도수 높은 순으로 정렬된 단어에 1부터 인덱스 부여
        i = i + 1
        word_to_index[word] = i
 
vocab_size = 5
words_frequency = [w for w, c in word_to_index.items() if c >= vocab_size + 1]
for w in words_frequency:  # 빈도수 상위 5개를 제외한 단어 제거
    del word_to_index[w]
 
word_to_index['OOV'= len(word_to_index) + 1  # OOV(Out-Of-Vocabulary) : 단어 집합에 없는 단어
encoded = []
for s in sentences:
    temp = []
    for w in s:
        try:
            temp.append(word_to_index[w])  # 단어를 인덱스로 치환
        except:
            temp.append(word_to_index['OOV'])
    encoded.append(temp)
 
print(word_to_index)
print(sentences)
print(encoded)
 

''' 출력 
{'barber'1'secret'2'huge'3'kept'4'person'5'OOV'6}
[['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']]
[[15], [165], [135], [62], [2432], [32], [146], [146], [142], [6632616], [1636]]
'''
cs


뭔가 상당히 복잡해 보이는데 25줄까지는 전처리, 그 뒤로는 빈도수 계산하고 인덱스 부여한 뒤 단어 위치에 인덱스로 치환하는 과정이다.



27~38줄의 과정에 collection.Counter 를 사용할 수도 있다.


from collections import Counter
words = sum(sentences, [])  # 리스트 요소들을 하나의 리스트로 합치기
vocab = Counter(words)  # 중복 요소 제거 및 빈도수 계산하여 정렬
vocab = vocab.most_common(vocab_size)  # 빈도수 상위 개수만큼 추출
cs


마찬가지로 nltk.FreqDist 도 사용할 수 있다.


from nltk import FreqDist
import numpy as np
words = np.hstack(sentences)  # 리스트 요소들을 하나의 리스트로 합치기
vocab = FreqDist(words)   # 중복 요소 제거 및 빈도수 계산하여 정렬
cs


이 모든 것들을 한번에 해결하는 keras...


from tensorflow.keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer(6)  # 빈도수 상위 5개
tokenizer.fit_on_texts(sentences)  # 빈도수를 기준으로 단어 집합 생성
encode = tokenizer.texts_to_sequences(sentences)  # 정수 인코딩
cs


생성된 tokenizer 로 인덱스 부여 확인(word_index), 빈도수 확인(word_counts) 도 가능하다. 기본적으로 OOV 는 제거되므로 OOV 를 보존하려면 Tokenizer 에 oov_token 인자를 사용한다. 이 경우 OOV 의 default 인덱스 값은 1이며, 나머지 상위 5개 단어의 인덱스는 2부터 시작된다.


tokenizer = Tokenizer(num_words = vocab_size + 2, oov_token = 'OOV')
cs




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,