- 대용량 데이터를 학습할 수 있는 딥러닝이 등장하면서 자연어 처리 연구가 활발해짐
5.1 텍스트의 토큰화
- 토큰(token) : 텍스트를 잘게 나눈 하나의 단위
- 케라스의 text 모듈의 text_to_word_sequence() 사용
# 케라스의 텍스트 전처리와 관련된 text_to_word_sequence 함수
from tensorflow.keras.preprocessing.text import text_to_word_sequence
# 전처리할 텍스트를
text = '해보지 않으면 해낼 수 없다'
# 해당 텍스트를 토큰화
result = text_to_word_sequence(text)
print("\n원문:\n", text)
print("\n토큰화:\n", result)
[output]
원문:
해보지 않으면 해낼 수 없다
토큰화:
['해보지', '않으면', '해낼', '수', '없다']
- Bag-of-word 방식으로 토큰화된 단어의 출현빈도수를 계산
- Tokenizer() 함수를 이용함
- word_counts 는 단어의 빈도수를 계산, 순서를 기억하는 OrderedDict 클래스에 담겨있는 형태로 출력
- document_count()를 이용해 총 문장의 개수 출력
- word_docs()를 통해 각 단어들이 몇 개의 문장에 나오는지 계산해 출력
- word_index()를 통해 단어에 매겨진 인덱스 값 출력
from tensorflow.keras.preprocessing.text import Tokenizer
# 단어 빈도수 세기
# 전처리하려는 세 개의 문장
docs = ['먼저 텍스트의 각 단어를 나누어 토큰화합니다.',
'텍스트의 단어로 토큰화해야 딥러닝에서 인식됩니다.',
'토큰화한 결과는 딥러닝에서 사용할 수 있습니다.',
]
# 토큰화 함수를 이용해 전처리
token = Tokenizer() # 토큰화 함수 지정
token.fit_on_texts(docs) # 토큰화 함수에 문장 적용
# 단어의 빈도수를 계산한 결과를 각 옵션에 맞추어 출력
# Tokenizer()의 word_counts 함수는 순서를 기억하는 OrderedDict 클래스를 사용합니다.
print("\n단어 카운트:\n", token.word_counts)
# 출력되는 순서는 랜덤입니다.
print("\n문장 카운트: ", token.document_count)
print("\n각 단어가 몇 개의 문장에 포함되어 있는가:\n", token.word_docs)
print("\n각 단어에 매겨진 인덱스 값:\n", token.word_index)
[output]
단어 카운트:
OrderedDict([('먼저', 1), ('텍스트의', 2), ('각', 1), ('단어를', 1), ('나누어', 1), ('토큰화', 1), ('합니다', 1), ('단어로', 1), ('토큰화해야', 1), ('딥러닝에서', 2), ('인식됩니다', 1), ('토큰화한', 1), ('결과는', 1), ('사용할', 1), ('수', 1), ('있습니다', 1)])
문장 카운트: 3
각 단어가 몇 개의 문장에 포함되어 있는가:
defaultdict(<class 'int'>, {'텍스트의': 2, '단어를': 1, '합니다': 1, '토큰화': 1, '먼저': 1, '각': 1, '나누어': 1, '인식됩니다': 1, '딥러닝에서': 2, '토큰화해야': 1, '단어로': 1, '수': 1, '사용할': 1, '결과는': 1, '있습니다': 1, '토큰화한': 1})
각 단어에 매겨진 인덱스 값:
{'텍스트의': 1, '딥러닝에서': 2, '먼저': 3, '각': 4, '단어를': 5, '나누어': 6, '토큰화': 7, '합니다': 8, '단어로': 9, '토큰화해야': 10, '인식됩니다': 11, '토큰화한': 12, '결과는': 13, '사용할': 14, '수': 15, '있습니다': 16}
5.2 단어의 원-핫 인코딩
- 단어가 문장의 다른 요소와 어떤 관계를 가지고 있는지 알기 위한 방법 중 하나
- 단어 수만큼 0으로 채워진 벡터 공간에 각 단어가 배열 내에서 해당하는 위치를 1로 바꾸어 벡터화
- 케라스 이용시, 토큰화 함수로 단어 단위로 토큰화 한 뒤 각 단어의 인덱스 값 출력
- text_to_sequences()를 이용하여 토큰의 인덱스로만 채워진 새로운 배열을 만듦
text="오랫동안 꿈꾸는 이는 그 꿈을 닮아간다"
token = Tokenizer()
token.fit_on_texts([text])
print(token.word_index)
#인덱스로만 채워진 배열 생성
x=token.texts_to_sequences([text])
print(x)
[output]
{'오랫동안': 1, '꿈꾸는': 2, '이는': 3, '그': 4, '꿈을': 5, '닮아간다': 6}
[[1, 2, 3, 4, 5, 6]]
- 1~6의 정수로 인덱스되어 있는 것을 0과 1로만 이루어진 배열로 바꾸어주는 to_categorical() 이용
- 배열 맨 앞에 0이 추가되므로 단어 수보다 1이 더 많게 인덱스를 잡아주는 것에 유의
# 인덱스 수에 하나를 추가해서 원-핫 인코딩 배열 만들기
word_size = len(token.word_index) + 1
x = to_categorical(x, num_classes=word_size)
print(x)
[output]
[[[0. 1. 0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 1. 0.]
[0. 0. 0. 0. 0. 0. 1.]]]
5.3 단어 임베딩
- 원-핫 인코딩을 그대로 사용하면 벡터의 길이가 너무 길어져 공간적 낭비 문제가 생김
- 단어 임베딩은 단어 간의 유사도를 계산하여 주어진 배열을 정해진 길이로 압축하는 방법
- Embedding() 함수를 이용하여 단어 임베딩 수행
- Embedding(16, 4, input_length=2)라고 하면 총 입력되는 단어 수는 16개지만 매번 두 개씩만 넣겠다는 의미
from tensorflow.keras.layers import Embedding
model = Sequential()
model.add(Embedding(16,4))
5.4 텍스트를 읽고 긍정, 부정 예측하기
- 짧은 열 개의 리뷰를 불러와 긍정이면 1, 부정이면 0 클래스를 지정
- 토큰화 과정 진행
# 텍스트 리뷰 자료를 지정
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)
[output]
{'너무': 1, '재밌네요': 2, '최고예요': 3, '참': 4, '잘': 5, '만든': 6,
'영화예요': 7, '추천하고': 8, '싶은': 9, '영화입니다': 10, '한번': 11,
'더': 12, '보고싶네요': 13, '글쎄요': 14, '별로예요': 15, '생각보다': 16,
'지루하네요': 17, '연기가': 18, '어색해요': 19, '재미없어요': 20}
- 토큰에 지정된 인덱스로 새로운 배열 생성
x = token.texts_to_sequences(docs)
print("\n리뷰 텍스트, 토큰화 결과:\n", x)
[output]
리뷰 텍스트, 토큰화 결과:
[[1, 2], [3], [4, 5, 6, 7], [8, 9, 10], [11, 12, 13], [14], [15], [16, 17], [18, 19], [20]]
- 딥러닝 모델에 입력하려면 학습데이터 길이가 동일해야하므로 토큰 수를 똑같이 맞춰주는 패딩 방법 이용
- pad_sequences() 을 사용하면 원하는 길이보다 짧은 부분은 0으로 채워주고 긴 데이터는 잘라줌
# 패딩, 서로 다른 길이의 데이터를 4로 맞추어 줍니다.
padded_x = pad_sequences(x, 4)
print("\n패딩 결과:\n", padded_x)
[output]
패딩 결과:
[[ 0 0 1 2]
[ 0 0 0 3]
[ 4 5 6 7]
[ 0 8 9 10]
[ 0 11 12 13]
[ 0 0 0 14]
[ 0 0 0 15]
[ 0 0 16 17]
[ 0 0 18 19]
[ 0 0 0 20]]
- 단어 임베딩을 포함해 딥러닝 모델을 만들기 위해 몇 개의 인덱스가 입력되어야 하는지 설정(word_index+1)
- 임베딩 결과는 내부에서 계산되므로 확인할 수 없음
- 최적화 함수로 adam(), 오차함수는 binary_crossentropy(), 20번 반복 학습
# 임베딩에 입력될 단어의 수를 지정합니다.
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=20)
print("\n Accuracy: %.4f" % (model.evaluate(padded_x, classes)[1]))
[output]
Epoch 1/20
1/1 [==============================] - 0s 325ms/step - loss: 0.6903 - accuracy: 0.5000
Epoch 2/20
1/1 [==============================] - 0s 2ms/step - loss: 0.6887 - accuracy: 0.5000
Epoch 3/20
1/1 [==============================] - 0s 997us/step - loss: 0.6871 - accuracy: 0.6000
...
Epoch 18/20
1/1 [==============================] - 0s 997us/step - loss: 0.6630 - accuracy: 0.9000
Epoch 19/20
1/1 [==============================] - 0s 2ms/step - loss: 0.6613 - accuracy: 0.9000
Epoch 20/20
1/1 [==============================] - 0s 997us/step - loss: 0.6596 - accuracy: 1.0000
1/1 [==============================] - 0s 92ms/step - loss: 0.6579 - accuracy: 1.0000
Accuracy: 1.0000
'데이터 > 딥러닝' 카테고리의 다른 글
[Paper Review] Cartoon-StyleGAN: Fine-tuning StyleGAN2 for Cartoon Face Generation (0) | 2023.04.03 |
---|---|
[Code Review] Cartoon-StyleGAN: Fine-tuning StyleGAN2 for Cartoon Face Generation (0) | 2023.04.01 |
[모두의 딥러닝] Chapter 5 | 딥러닝 활용하기 - 컨볼루션 신경망(CNN) (0) | 2023.02.20 |
[모두의 딥러닝] Chapter 4 | 딥러닝 기본기 다지기 - 모델 성능 향상시키기 (0) | 2023.02.14 |
[모두의 딥러닝] Chapter 4 | 딥러닝 기본기 다지기 - 모델 성능 검증하기 (0) | 2023.02.14 |