Tokenizer
from keras.preprocessing.text import Tokenizer
# 예시 문장들
sentences = ['The cat sat on the chair.', 'The dog ate my food.']
# 토크나이저 인스턴스 생성 후, 텍스트 데이터에 대해 단어 인덱스 생성
tokenizer = Tokenizer()
tokenizer.fit_on_texts(sentences)
# 생성된 단어 인덱스 확인
print(tokenizer.word_index)
# {'the': 1, 'cat': 2, 'sat': 3, 'on': 4, 'chair': 5, 'dog': 6, 'ate': 7, 'my': 8, 'food': 9}
# 문장을 시퀀스로 변환
sequences = tokenizer.texts_to_sequences(sentences)
print(sequences)
# [[1, 2, 3, 4, 1, 5], [1, 6, 7, 8, 9]]
ㄴ Keras의 텍스트 전처리 도구
ㄴ 각 단어를 고유한 정수로 인코딩하고, 문장을 시퀀스로 변환
ㄴ fit_on_texts() 메서드를 사용하여 주어진 텍스트 데이터에 대해 단어 인덱스를 만듦
ㄴ texts_to_sequences() 메서드를 사용하여 문장을 시퀀스로 변환 --> 이러한 시퀀스는 모델 학습에서 입력으로 사용
tf19_tokenizer01.py
from keras.preprocessing.text import Tokenizer # 텍스트 데이터를 단어 단위 또는 문자 단위로 분리해주는 기능
text = '나는 진짜 매우 매우 매우 매우 맛있는 밥을 엄청 엄청 많이 많이 많이 먹어서 매우 배가 부르다'
token = Tokenizer()
token.fit_on_texts([text]) # 주어진 텍스트 데이터를 학습하여 각 단어나 문자에 대한 인덱스를 만들고 이를 저장
# index = token.word_index
print(token.word_index)
# {'매우': 1, '많이': 2, '엄청': 3, '나는': 4, '진짜': 5, '맛있는': 6, '밥을': 7, '먹어서': 8, '배가': 9, '부르다': 10}
x = token.texts_to_sequences([text])
print(x)
from keras.utils import to_categorical
x = to_categorical(x) # onehotencoding 하면 index 수 + 1개로 만들어짐
print(x) # 11 개 인 이유 : 빈칸을 만들어줌 --> 훈련 데이터에 없는 경우를 처리해 주기 위함
print(x.shape) # (1, 17, 11) --> 3차원으로 받아온다
ㄴ 텍스트 데이터를 토큰화하고, 각 단어를 정수로 인코딩한 후, 이를 one-hot encoding 한 것
tf19_tokenizer02.py
from keras.preprocessing.text import Tokenizer
text1 = '나는 진짜 매우 매우 매우 매우 맛있는 밥을 엄청 엄청 많이 많이 많이 먹어서 매우 배가 부르다'
text2 = '나는 딥러닝이 정말 재미있다. 재미있어하는 내가 너무 너무 너무 너무 멋있다. 또 또 또 얘기해 봐.'
token = Tokenizer()
token.fit_on_texts([text1, text2]) # fit on 하면서 index 생성 (주어진 텍스트 데이터에 대해 단어 인덱스를 만듦)
print(token.word_index)
# {'매우': 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([text1, text2])
print(x)
# [[5, 7, 1, 1, 1, 1, 8, 9, 6, 6, 3, 3, 3, 10, 1, 11, 12], # text1
# [5, 13, 14, 15, 16, 17, 2, 2, 2, 2, 18, 4, 4, 4, 19, 20]] # text
from keras.utils import to_categorical # 문장을 시퀀스로 변환 --> 모델 학습에서 입력으로 사용
x_new = x[0] + x[1]
print(x_new) # 리스트 2개가 연결됨
'''
x = to_categorical(x_new) # onehotencoding 하면 index 수 + 1개로 만들어짐
print(x)
print(x.shape) # (33, 21)
'''
########## OneHotEncoder 수정 ##########
import numpy as np
from sklearn.preprocessing import OneHotEncoder
onehot_encoder = OneHotEncoder(
categories='auto', sparse=False
)
x = np.array(x_new) # 배열 만들어주는 거
# x = x.reshape(-1, 11, 9) # reshape : list로 해야됨
print(x.shape) # (33,)
x = x.reshape(-1, 1) # -1 : 차원 늘어남
print(x.shape) # (33, 1)
onehot_encoder.fit(x)
x = onehot_encoder.transform(x)
print(x)
print(x.shape) # (33, 20) --> 0부터 시작하기 때문에 to_categorical 보다 1 큼
# AttributeError: 'list' object has no attribute 'reshape'
** 주의
OneHotEncoder는 정수형 인덱스를 0부터 시작하여 순서대로 one-hot 인코딩하므로 to_categorical 의 one-hot encoding 과 다름
= > to_categorical 의 one-hot encoding 시 x.shape --> (33, 21)
= > sklearn.preprocessing 의 OneHotEncoder 사용 시 x.shape --> (33, 20)
Embedding
ㄴ 자연어 처리에서 단어를 벡터로 변환하는 기술
ㄴ 각 단어는 고유한 벡터로 매핑되며, 이러한 벡터들은 단어 간의 유사도를 반영
ㄴ "강아지"와 "고양이"라는 두 단어가 유사하면 해당 단어들이 벡터 공간에서 가까이 위치
ㄴ 이를 통해 자연어 처리 모델은 문장 내의 단어들의 관계를 파악하여 자연어 처리를 수행
Embedding 감성 분류 모델
tf20_embedding01.py
import numpy as np
from keras.preprocessing.text import Tokenizer
# 1. 데이터
docs = ['재밌어요', '재미없다', '돈 아깝다', '숙면했어요',
'최고에요', '꼭 봐라', '세 번 봐라', '또 보고싶다',
'n회차 관람', '배우가 잘 생기긴 했어요', '발연기에요', '추천해요',
'최악', '후회된다', '돈 버렸다', '글쎄요', '보다 나왔다',
'망작이다', '연기가 어색해요', '차라리 기부할걸',
'다음편 나왔으면 좋겠다', '다른 거 볼걸', '감동이다']
# 긍정 1, 부정 0 라벨링
labels = np.array([1, 0, 0, 0,
1, 1, 1, 1,
1, 0, 0, 1,
0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 1])
# Tokenizer
token = Tokenizer()
token.fit_on_texts(docs)
print(token.word_index)
# {'돈': 1, '봐라': 2, '재밌어요': 3, '재미없다': 4, '아깝다': 5, '숙면
# 했어요': 6, '최고에요': 7, '꼭': 8, '세': 9, '번': 10, '또': 11, '보고
# 싶다': 12, 'n회차': 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}
x = token.texts_to_sequences(docs)
print(x)
# [[3], [4], [1, 5], [6], [7], [8, 2], [9, 10, 2], [11, 12], [13, 14],
# [15, 16, 17, 18], [19], [20], [21], [22], [1, 23], [24], [25, 26],
# [27], [28, 29], [30, 31], [32, 33, 34], [35, 36, 37], [38]]
# pad_sequences --> 길이를 동일하게 맞춰줌
# 1. 데이터
from keras_preprocessing.sequence import pad_sequences
pad_x = pad_sequences(x, padding='pre', maxlen=4) # 출력한 단어에 모두 0을 채움
print(pad_x)
print(pad_x.shape) # (23, 4) --> 23은 전체 개수(x 크기), 4는 maxlen
word_size = len(token.word_index)
print('word_size : ', word_size) # word_size : 38 --> 단어 사전 개수
# 2. 모델
from keras.models import Sequential
from keras.layers import Dense, Embedding, LSTM
model = Sequential()
model.add(Embedding(input_dim = 39, # word_size + 1 : 38 + 1
output_dim = 10, # node 수
input_length=4)) # 문장의 길이(가장 긴 길이)
model.add(LSTM(32)) # 시간적인 개념, 3차원을 받아서 2차원을 보냄
model.add(Dense(1, activation='sigmoid')) # 긍정, 부정 --> 이진분류
# model.summary()
# 3. 컴파일, 훈련
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics='accuracy')
model.fit(pad_x, labels, epochs=100, batch_size=16)
# 4. 평가, 예측
loss, acc = model.evaluate(pad_x, labels)
print('loss : ', loss)
print('acc : ', acc)
# loss : 0.04936698079109192
# acc : 1.0
tf20_embedding02_predict.py
import numpy as np
from keras.preprocessing.text import Tokenizer
#1. 데이터
docs = ['재밌어요', '재미없다', '돈 아깝다', '숙면했어요', '최고예요',
'꼭 봐라', '세 번 봐라', '또 보고싶다', 'n회차 관람', '배우가 잘 생기긴 했어요',
'발연기에요','추천해요','최악','후회된다','돈 버렸다','글쎄요', '보다 나왔다',
'망작이다','연기가 어색해요','차라리 기부할걸','다음편 나왔으면 좋겠다',
'다른 거 볼걸','감동이다']
# 긍정 1, 부정 0 라벨링
labels = np.array([1, 0, 0, 0,
1, 1, 1, 1,
1, 0, 0, 1,
0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 1])
# tokenizer
token = Tokenizer()
token.fit_on_texts(docs)
print(token.word_index)
# {'돈': 1, '봐라': 2, '재밌어요': 3, '재미없다': 4, '아깝다': 5, '숙면했어요': 6, '최고예요': 7,
# '꼭': 8, '세9': 9, '번': 10, '또': 11, '보고싶다': 12, 'n회차': 13, '관람': 14, '배우가': 15, '잘': 16,
# '생기긴': 17, '했어요': 18, '발연기에요': 1, '추천해요': 20, '최악': 21, '후회된다': 22, '버렸다': 23,
# '글쎄요': 24, '보다': 25, '나왔다': 26, '망작이다': 27, '연기가': 28, '어색해요': 29, '차라리': 30,
# '기부할걸': 31, '다음편': 32, '나왔으면': 33, '좋겠다': 34, '다른': 35, '거': 36, '볼걸': 37, '감동이다': 38}
x = token.texts_to_sequences(docs)
print(x)
# [[3], [4], [1, 5], [6], [7], [8, 2], [9, 10, 2], [11, 12], [13, 14], [15, 16, 17, 18], [19], [20], [21],
# [22], [1, 23], [24], [25, 26], [27], [28, 29], [30, 31], [32, 33, 34], [35, 36, 37], [38]]
# pad_sequences
from keras_preprocessing.sequence import pad_sequences
pad_x = pad_sequences(x, padding = 'pre', maxlen = 4) # 출력한 단어에 모두 0을 채움
print(pad_x)
print(pad_x.shape) # (23, 4) --> 23은 전체 개수(x 크기, 라벨링 개수), 4는 maxlen
word_size = len(token.word_index) # word_size : 38 --> 단어 사전 개수
print('word size : ',word_size) # word size : 38
# 모델
from keras.models import Sequential
from keras.layers import Dense, Embedding, LSTM
model = Sequential()
model.add(Embedding(input_dim = 39, #word_size : 38 + 1
# 각 단어의 인덱스는 0부터 시작하기 때문에, 모든 단어를 벡터화하기 위해서는
# 0을 포함한 총 단어의 개수(word_size + 1)만큼의 차원이 필요
output_dim = 10, # node 수
input_length=4)) # 문장의 길이(가장 긴 길이에 맞춰짐)
model.add(LSTM(32)) # 시간적인 개념, 3차원을 받아서 2차원을 보냄
model.add(Dense(32, activation='relu'))
model.add(Dense(16, activation='relu'))
model.add(Dense(1, activation='sigmoid')) # 긍정, 부정 --> 이진분류
# model.summary()
# 컴파일, 훈련
model.compile(loss = 'binary_crossentropy',
optimizer='adam',
metrics = 'accuracy')
#model.fit(pad_x, labels, epochs=100, batch_size = 16 )
model.fit(pad_x, labels, epochs=10, batch_size = 1)
#4.평가, 예측
loss, acc = model.evaluate(pad_x, labels)
print('loss : ', loss)
print('acc : ', acc)
# loss : 0.08198674768209457
# acc : 1.0
####################################
# loss : 0.262984037399292
# acc : 1.0
############################### [predict] ##################################
# x_predict = '진짜 정말 후회된다 최악'
x_predict = '정말 정말 재미있고 최고예요'
#x_predict = "배우가 잘 생기긴 했네요"
# 1) tokenizer
token = Tokenizer()
x_predict = np.array([x_predict])
print(x_predict) # 리스트 안에 들어갔는지 확인
# ['정말 정말 재미있고 최고예요']
token.fit_on_texts(x_predict) # fit on 하면서 index 가 생성됨
x_pred = token.texts_to_sequences(x_predict) # # max length 맞춰줘야 함
#print(token.word_index())
print(len(token.word_index))
# 3
print(x_pred)
# [[1, 1, 2, 3]]
score =float(model.predict(x_pred))
# 2) pad_sequences
x_pred = pad_sequences(x_pred, padding='pre')
print(x_pred)
# [[1 1 2 3]]
# 3) model.predict
y_pred = model.predict(x_pred)
print(y_pred)
# [[0.719884]]
# [실습]
# 1. predict 결과 제대로 출력되도록
# 2. score 를 긍정과 부정으로 출력하라
score = float(model.predict(x_pred))
if y_pred > 0.5:
print("{:.2f}% 확률로 긍정\n".format(score * 100))
else:
print("{:.2f}% 확률로 부정\n".format((1-score) * 100))
# 71.99% 확률로 긍정
'네이버클라우드 > AI' 카테고리의 다른 글
AI 5일차 (2023-05-12) 인공지능 기초 - pandas (0) | 2023.05.14 |
---|---|
AI 5일차 (2023-05-12) 인공지능 기초 - Imdb 와 Rueters (0) | 2023.05.12 |
AI 5일차 (2023-05-12) 인공지능 기초 - 자연어처리(NLP) 기초 (0) | 2023.05.12 |
AI 4일차 (2023-05-11) 인공지능 기초 - 이미지 분석 : 데이터 셋 (0) | 2023.05.11 |
AI 4일차 (2023-05-11) 인공지능 기초 - 이미지 분석 : CNN 모델 (0) | 2023.05.11 |