토큰화, 정제 및 정규화 등의 전처리 작업을 마친 후에, 컴퓨터가 데이터 처리를 더 빠르게 하도록 텍스트를 수치화 하는 것을 정수 인코딩(Integer Encoding) 이라 한다.
결론 : keras 의 Tokenizer 를 사용하면 쉽게 해결
정수 인코딩 과정
- 문장 토큰화, 정제 및 일반화, 단어 토큰화.
- 빈도수를 기록하여 빈도수가 높은 순서대로 정렬
- 자연어 처리에서 빈도수가 낮은 단어는 의미를 가지지 않을 가능성이 높으므로 제외
- 빈도수 순서로 정렬된 단어에 순차적으로 인덱스 부여
- 각 단어를 부여된 인덱스로 맵핑.
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 = {} i = 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']] [[1, 5], [1, 6, 5], [1, 3, 5], [6, 2], [2, 4, 3, 2], [3, 2], [1, 4, 6], [1, 4, 6], [1, 4, 2], [6, 6, 3, 2, 6, 1, 6], [1, 6, 3, 6]] ''' | 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
- 손가락귀신
정신 못차리면, 벌 받는다.