NLP - Tokenizer_sequence

psy4072·2022년 12월 14일
0

Tokenizer

  • 데이터에 출현하는 모든 단어의 개수를 세고 빈도 수 기준으로 정렬하여 num_words 에 지정된 만큼만 숫자로 변환하고 나머지는 0으로 반환
  • num_words : 단어 빈도에 따라 유지할 최대 단어의 수 (num_words - 1 의 단어만 유지)
  • filters : 각 요소가 텍스트에서 필터링될 문자인 문자열. 기본값은 문자를 제외한 모든 구두점, 탭, 줄 바꿈.
  • lower : 텍스트를 소문자로 변환할 지 여부
  • split : 단어 분할을 위한 구분 기호
  • char_level : True이면 모든 문자가 토큰으로 처리
  • oov_token : 주어진 경우, 그것은 word_index에 추가되고 text_to_sequence 호출 중에 어휘 밖의 단어를 대체하는 데 사용

📌 흐름

1️⃣ Tokenizer
2️⃣ fit_on_texts, word_index -> key, value 딕셔너리 생성
3️⃣ texts_to_sequence -> text 문장을 숫자 리스트로 변경
4️⃣ pad_sequences 이용하여 리스트 길이 통일화

tf.keras.preprocessing.text.Tokenizer(
    num_words=None,
    filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
    lower=True,
    split=' ',
    char_level=False,
    oov_token=None,
    analyzer=None,
    **kwargs
)
import pandas as pd

corpus = ["SEOUL 서울 코로나 상생지원금 문의입니다.?",
"인천 지하철 운행시간 문의입니다.!",
"Bus 운행시간 문의입니다.#"]

1️⃣ Tokenizer

from tensorflow.keras.preprocessing.text import Tokenizer

vocab_size = 7
tokenizer = Tokenizer(num_words=vocab_size)

2️⃣ fit_on_texts, word_index

  • fit_on_texts 와 word_index 사용하여 key, value로 이루어진 딕셔너리를 생성
  • 반환 시, 자동으로 소문자로 변환되며 느낌표나 마침표 같은 구두점은 제거됨
tokenizer.fit_on_texts(corpus)
word_to_index = tokenizer.word_index
word_to_index
>>>>
{'문의입니다': 1,
 '운행시간': 2,
 'seoul': 3,
 '서울': 4,
 '코로나': 5,
 '상생지원금': 6,
 '인천': 7,
 '지하철': 8,
 'bus': 9}
 
 # 단어별 빈도수 확인
 # word_counts
 wc = tokenizer.word_counts
 pd.DataFrame(wc.items()).set_index(0).sort_values(by=1).T

3️⃣ texts_to_sequence

  • text 문장을 숫자로 이루어진 리스트로 변경
  • 시퀀스 방식은 해당 어휘사전을 만들고 해당 어휘의 등장 순서대로 숫자로 변경
    corpus_sequence = tokenizer.texts_to_sequence(corpus)
    corpus_sequence
    >>>>
    [[3, 4, 5, 6, 1], [2, 1], [2, 1]]

    Padding

    : 자연어 처리할 때 각 문장(또는 문서)은 문장의 길이 또는 단어의 길이가 다를 수 있음
    -> 그런데 기계는 길이가 전부 동일한 문서들에 대해서만 하나의 행렬로 보고 한꺼번에 묶어서 처리할 수 있기 때문에 병렬 연산을 통해 여러 문장의 길이를 임의로 동일하게 맞춰주는 작업이 필요
pad_sequence(sequences, maxlen=None, 
			dtype='int32', padding='pre',
            truncating='pre', value=0.0,)

>>> sequence = [[1], [2, 3], [4, 5, 6]]
>>> tf.keras.preprocessing.sequence.pad_sequences(sequence)
# 기본값은 padding='pre' 앞에 0을 채운다.
array([[0, 0, 1],
       [0, 2, 3],
       [4, 5, 6]], dtype=int32)
 
>>> tf.keras.preprocessing.sequence.pad_sequences(sequence, value=-1)
# 0을 -1로 출력
array([[-1, -1,  1],
       [-1,  2,  3],
       [ 4,  5,  6]], dtype=int32)
 
>>> tf.keras.preprocessing.sequence.pad_sequences(sequence, padding='post')
# 뒤에 0을 채운다
array([[1, 0, 0],
       [2, 3, 0],
       [4, 5, 6]], dtype=int32)
       
>>> tf.keras.preprocessing.sequence.pad_sequences(sequence, maxlen=2)
# 앞(작은값)에서 자른다
array([[0, 1],
       [2, 3],
       [5, 6]], dtype=int32)

4️⃣ pad_sequences

from tensorflow.keras.preprocessing.sequence import pad_sequences

pads = pad_sequences(corpus_sequences, maxlen=3)
print(corpus)
print(word_to_index)
print(corpus_sequences)
print(pads)
np.array(pad)
>>>>

['SEOUL 서울 코로나 상생지원금 문의입니다.?', '인천 지하철 운행시간 문의입니다.!', 'Bus 운행시간 문의입니다.#']
{'문의입니다': 1, '운행시간': 2, 'seoul': 3, '서울': 4, '코로나': 5, '상생지원금': 6, '인천': 7, '지하철': 8, 'bus': 9}
[[4, 5, 6, 7, 2], [8, 9, 3, 2], [1, 3, 2]]
[[6 7 2]
 [9 3 2]
 [1 3 2]]
array([[6, 7, 2],
       [9, 3, 2],
       [1, 3, 2]], dtype=int32)

전체 흐름

corpus2 = ["코로나 거리두기와 코로나 상생지원금 문의입니다.",
          "지하철 운행시간과 지하철 요금 문의입니다.",
          "지하철 승강장 문의입니다.",
          "코로나 선별진료소 문의입니다.",
          "버스 운행시간 문의입니다.", 
          "버스 터미널 위치 안내입니다.",
          "코로나 거리두기 안내입니다.",
          "택시 승강장 문의입니다."
         ]
    
tokenizer = Tokenizer(num_words=10, oov_token='[UNK]')
tokenizer.fit_on_texts(corpus2)
word_to_index = tokenizer.word_index
corpus_sequences2 = tokenizer.texts_to_sequences(corpus2)
pads = pad.sequences(corpus_sequences2, maxlen=7, padding='post')

print(corpus2)
print(word_to_index)
print(corpus_sequences2)
print(pads)
np.array(pads)

>>>>
['코로나 거리두기와 코로나 상생지원금 문의입니다.', '지하철 운행시간과 지하철 요금 문의입니다.', '지하철 승강장 문의입니다.', '코로나 선별진료소 문의입니다.', '버스 운행시간 문의입니다.', '버스 터미널 위치 안내입니다.', '코로나 거리두기 안내입니다.', '택시 승강장 문의입니다.']
{'[UNK]': 1, '문의입니다': 2, '코로나': 3, '지하철': 4, '승강장': 5, '버스': 6, '안내입니다': 7, '거리두기와': 8, '상생지원금': 9, '운행시간과': 10, '요금': 11, '선별진료소': 12, '운행시간': 13, '터미널': 14, '위치': 15, '거리두기': 16, '택시': 17}
[[3, 8, 3, 9, 2], [4, 1, 4, 1, 2], [4, 5, 2], [3, 1, 2], [6, 1, 2], [6, 1, 1, 7], [3, 1, 7], [1, 5, 2]]
[[3 8 3 9 2 0 0]
 [4 1 4 1 2 0 0]
 [4 5 2 0 0 0 0]
 [3 1 2 0 0 0 0]
 [6 1 2 0 0 0 0]
 [6 1 1 7 0 0 0]
 [3 1 7 0 0 0 0]
 [1 5 2 0 0 0 0]]
array([[3, 8, 3, 9, 2, 0, 0],
       [4, 1, 4, 1, 2, 0, 0],
       [4, 5, 2, 0, 0, 0, 0],
       [3, 1, 2, 0, 0, 0, 0],
       [6, 1, 2, 0, 0, 0, 0],
       [6, 1, 1, 7, 0, 0, 0],
       [3, 1, 7, 0, 0, 0, 0],
       [1, 5, 2, 0, 0, 0, 0]], dtype=int32)
profile
Ⓓ🅰️🅣🄰 ♡♥︎

0개의 댓글