[딥러닝]5. 딥러닝 활용 <2>NLP
2. NLP(Natural Language Processing)
* 딥러닝을 이용한 자연어 처리
1) 텍스트 토큰화
- 토큰(token) : 입력할 텍스트를 단어별, 문장별, 형태소별로 작게 나눈 하나의 단위
- 토큰화(tokenization) : 입력된 텍스트를 잘게 나누는 과정
from tensorflow.keras.preprocessing.text import text_to_word_sequence
text = '해보지 않으면 해낼 수 없다'
result = text_to_word_sequence(text)
print(result)
- text_to_word_sequence() : 문장을 단어 단위로 나눠주는 함수
- Bag of words(단어의 가방) : 같은 단어끼리 따로따로 가방에 담은 뒤 각 가방에 몇 개의 단어가 들어있는지를 세는 기법
- 단어의 빈도수 = 중요 단어
- Tokenizer() : 단어의 빈도수 확인 가능
from tensorflow.keras.preprocessing.text import Tokenizer
docs = ['먼저 텍스트의 각 단어를 나누어 토큰화합니다.',
'텍스트의 단어로 토큰화해야 딥러닝에서 인식됩니다.',
'토큰화한 결과는 딥러닝에서 사용할 수 있습니다.']
token = Tokenizer()
token.fit_on_texts(docs)
print(token.word_counts)
# OrderedDict([('먼저', 1), ('텍스트의', 2), ('각', 1), ('단어를', 1), ('나누어', 1), ('토큰화합니다', 1), ('단어로', 1), ('토큰화해야', 1), ('딥러닝에서', 2), ('인식됩니다', 1), ('토큰화한', 1), ('결과는', 1), ('사용할', 1), ('수', 1), ('있습니다', 1)])
print(token.document_count) # 3
print(token.word_docs)
# defaultdict(<class 'int'>, {'토큰화합니다': 1, '먼저': 1, '텍스트의': 2, '각': 1, '단어를': 1, '나누어': 1, '토큰화해야': 1, '딥러닝에서': 2, '단어로': 1, '인식됩니다': 1, '수': 1, '토큰화한': 1, '있습니다': 1, '사용할': 1, '결과는': 1})
print(token.word_index)
#{'딥러닝에서': 3, '단어를': 6, '결과는': 13, '수': 16, '한': 12, '인식됩니다': 11, '합니다': 8, '텍스트의': 2, '토큰화': 1, '할': 15, '각': 5, '있습니다': 17, '먼저': 4, '나누어': 7, '해야': 10, '사용': 14, '단어로': 9}
- word_counts : 단어의 빈도 수를 계산
- document_count : 총 문장의 개수 계산
- word_docs : 각 단어 당 문장에 출현하는 빈도수(랜덤하게 나옴)
- word_index : 각 단어의 인덱스값 출력
2) 단어의 원-핫 인코딩(one-hot encoding)
- 단어가 문장의 다른 요소와 어떤 관계를 가지고 있는지를 알아보는 방법
➡️ 각 단어를 모두 0으로 바꿔주고 원하는 단어만 1로 바꿈
1️⃣ 단어 수만큼 0으로 채워진 벡터 공간 만들기
2️⃣ 각 단어가 배열 내에서 해당하는 위치를 1로 표시
ex) (0인덱스) 오랫동안 꿈꾸는 이는 그 꿈을 닮아간다
[ 0 0 0 0 0 0 0 ]
from tensorflow.keras.preprocessing.text import Tokenizer
text = '오랫동안 꿈꾸는 이는 그 꿈을 닮아간다'
token = Tokenizer()
token.fit_on_texts([text])
print(token.word_index)
x = token.texts_to_sequences([text])
print(x)
from keras.utils import to_categorical
# 인덱스 수에 하나를 추가해서 원-핫 인코딩 배열 만들기
word_size = len(token.word_index) + 1
x = to_categorical(x, num_classes=word_size)
print(x)
- texts_to_sequences() : 토큰의 인덱스로만 채워진 새로운 배열 생성
- to_categorical() : 정수 인덱스를 0과 1로만 이루어진 배열로 변경
- 배열 맨 앞에 0 추가됨 : 단어 수 + 1 = 인덱스값
3) 단어 임베딩
- 원-핫 인코딩의 단점 : 벡터의 길이가 너무 길어짐
ex) 1만개의 단어 토큰으로 이루어진 말뭉치 ➡️ 9999개의 0, 1개의 1로 구성된 단어 벡터 1만개 생성
- 단어 임베딩(word embedding) : 원-핫 인코딩으로 인한 공간적 낭비 해결
- 각 단어의 유사도 계산 : 밀집된 정보 + 공간 낭비 적음
ex) happy는 bad보다 good에 가까움. ➡️ 이러한 유사도를 고려해 각 배열을 새로운 수치로 바꿔줌
- 토큰(token) : 입력할 텍스트를 단어별, 문장별, 형태소별로 작게 나눈 하나의 단위
- 토큰화(tokenization) : 입력된 텍스트를 잘게 나누는 과정
from tensorflow.keras.preprocessing.text import text_to_word_sequence
text = '해보지 않으면 해낼 수 없다'
result = text_to_word_sequence(text)
print(result)
- Bag of words(단어의 가방) : 같은 단어끼리 따로따로 가방에 담은 뒤 각 가방에 몇 개의 단어가 들어있는지를 세는 기법
- 단어의 빈도수 = 중요 단어
from tensorflow.keras.preprocessing.text import Tokenizer
docs = ['먼저 텍스트의 각 단어를 나누어 토큰화합니다.',
'텍스트의 단어로 토큰화해야 딥러닝에서 인식됩니다.',
'토큰화한 결과는 딥러닝에서 사용할 수 있습니다.']
token = Tokenizer()
token.fit_on_texts(docs)
print(token.word_counts)
# OrderedDict([('먼저', 1), ('텍스트의', 2), ('각', 1), ('단어를', 1), ('나누어', 1), ('토큰화합니다', 1), ('단어로', 1), ('토큰화해야', 1), ('딥러닝에서', 2), ('인식됩니다', 1), ('토큰화한', 1), ('결과는', 1), ('사용할', 1), ('수', 1), ('있습니다', 1)])
print(token.document_count) # 3
print(token.word_docs)
# defaultdict(<class 'int'>, {'토큰화합니다': 1, '먼저': 1, '텍스트의': 2, '각': 1, '단어를': 1, '나누어': 1, '토큰화해야': 1, '딥러닝에서': 2, '단어로': 1, '인식됩니다': 1, '수': 1, '토큰화한': 1, '있습니다': 1, '사용할': 1, '결과는': 1})
print(token.word_index)
#{'딥러닝에서': 3, '단어를': 6, '결과는': 13, '수': 16, '한': 12, '인식됩니다': 11, '합니다': 8, '텍스트의': 2, '토큰화': 1, '할': 15, '각': 5, '있습니다': 17, '먼저': 4, '나누어': 7, '해야': 10, '사용': 14, '단어로': 9}
- 단어가 문장의 다른 요소와 어떤 관계를 가지고 있는지를 알아보는 방법
➡️ 각 단어를 모두 0으로 바꿔주고 원하는 단어만 1로 바꿈
1️⃣ 단어 수만큼 0으로 채워진 벡터 공간 만들기
2️⃣ 각 단어가 배열 내에서 해당하는 위치를 1로 표시ex) (0인덱스) 오랫동안 꿈꾸는 이는 그 꿈을 닮아간다
[ 0 0 0 0 0 0 0 ]
from tensorflow.keras.preprocessing.text import Tokenizer
text = '오랫동안 꿈꾸는 이는 그 꿈을 닮아간다'
token = Tokenizer()
token.fit_on_texts([text])
print(token.word_index)
x = token.texts_to_sequences([text])
print(x)
from keras.utils import to_categorical
# 인덱스 수에 하나를 추가해서 원-핫 인코딩 배열 만들기
word_size = len(token.word_index) + 1
x = to_categorical(x, num_classes=word_size)
print(x)
- 배열 맨 앞에 0 추가됨 : 단어 수 + 1 = 인덱스값
ex) 1만개의 단어 토큰으로 이루어진 말뭉치 ➡️ 9999개의 0, 1개의 1로 구성된 단어 벡터 1만개 생성
- 단어 임베딩(word embedding) : 원-핫 인코딩으로 인한 공간적 낭비 해결
- 각 단어의 유사도 계산 : 밀집된 정보 + 공간 낭비 적음
ex) happy는 bad보다 good에 가까움. ➡️ 이러한 유사도를 고려해 각 배열을 새로운 수치로 바꿔줌
✔️ 유사도 계산 : 오차 역전파 이용
- 최적의 유사도를 계산하는 학습 과정을 거침
- Embedding(입력, 출력)
from keras.layers import Embedding
from keras.models import Sequential
model = Sequential()
model.add(Embedding(16,4))
- Embedding(16,4)
- 입력될 총 단어 수 : 16
- 임베딩 후 출력되는 벡터 크기 : 4
- Embedding(16,4, input_length=2) : 입력되는 단어는 16개지만 매번 2개씩만 입력함
4) 텍스트 읽고 예측하기
import numpy
import tensorflow as tf
from numpy import array
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,Flatten,Embedding
# 텍스트 리뷰 자료 지정
docs = ['너무 재밌네요','최고예요','참 잘 만든 영화예요','추천하고 싶은 영화입니다.','한번 더 보고싶네요','글쎄요','별로예요','생각보다 지루하네요','연기가 어색해요','재미없어요']
# 긍정 리뷰는 1, 부정 리뷰는 0으로 클래스 지정
classes = array([1,1,1,1,1,0,0,0,0,0])
# 토큰화
token = Tokenizer()
token.fit_on_texts(docs)
print(token.word_index)
#{'너무': 1, '재밌네요': 2, '최고예요': 3, '참': 4, '잘': 5, '만든': 6, '영화예요': 7, '추천하고': 8, '싶은': 9, '영화입니다': 10, '한번': 11, '더': 12, '보고싶네요': 13, '글쎄요': 14, '별로예요': 15, '생각보다': 16, '지루하네요': 17, '연기가': 18, '어색해요': 19, '재미없어요': 20}
print(token.texts_to_sequences(docs))
#[[1, 2], [3], [4, 5, 6, 7], [8, 9, 10], [11, 12, 13], [14], [15], [16, 17], [18, 19], [20]]
- 입력 데이터의 토큰 수가 다 다름
- '너무 재밌네요' = 2개의 토큰 ➡️ [[1,2]]
- '최고예요' = 1개의 토큰 ➡️ [[3]]
➡️ 딥러닝 학습을 위해서는 입력데이터 길이가 동일해야함
- 패딩(padding)
- 길이를 똑같이 맞춰 주는 작업
- pad_sequence() : 원하는 길이보다 짧은 부분은 숫자 0을 넣어서 채워주고, 긴 데이터는 잘라서 같은 길이로 맞춰줌
# 패딩, 서로 다른 길이의 데이터를 4로 맞춤 padded_x = pad_sequences(x, 4) "\n패딩 결과\n", print(padded_x)
# 임베딩에 입력될 단어 수 지정
word_size = len(token.word_index)+1
# 단어 임베딩을 포함하여 딥러닝 모델을 만들고 결과 출력
model = Sequential()
model.add(Embedding(word_size, 8, input_length=4))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(padded_x, classes, epochs=10)
print("\n Accuracy: %.4f" % (model.evaluate(padded_x, classes)[1]))
- 임베딩(Embedding)
- 입력 : 총 몇 개의 단어 집합
- token.word_index 길이 + 1
- 출력 : 몇 개의 임베딩 결과를 사용
- 8개의 임베딩 결과 출력 : 내부 레이어로 딥러닝의 레이어로 활용됨
- 단어 수 : 매번 입력될 단어 수는 몇 개로 할지
- 패딩 과정을 거쳐 4개 길이로 맞췄기 때문에 4개 단어로 나눔
- 입력 : 총 몇 개의 단어 집합
Author And Source
이 문제에 관하여([딥러닝]5. 딥러닝 활용 <2>NLP), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jjaa9292/딥러닝5.-딥러닝-활용-2NLP저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)