◇ 라이브러리 정의
# 라이브러리 정의
import tensorflow as tf
# 단어사전만들기
from tensorflow.keras.preprosing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
◇ 규칙기반 데이터 정의하기 ( 질문 / 답변 )
# 규칙기반 데이터 정의하기(질문/답변)
questions = [
"전기요금 어때?",
"안녕하세요",
...
]
answers = [
"전기요금이 계속 인상되고 있어요!",
"안녕하세요! 반가워요^^",
...
]
len(questions) , len(answers)
(49, 49)
▶ 총 49개의 질문과 답변 데이터를 불러들임.
데이터가 많을 수록 정확도가 높아짐
◇ 텍스트 데이터를 토큰(단어)화하여 단어사전을 구축하기
① Tokenizer 생성
tokenizer = Tokenizer()
② 단어사전 구축하기
- 질문과 답변을 하나의 데이터로 합쳐서 전체 텍스트 데이터로 사용
- 이를 기반으로 토크나이저가 단어 사전을 구축하게됨
- 각 단어들은 순차적인 인덱스번호를 부여받게됨
- 토큰나이저가 인식하는 문장 내에서 단어의 의미 :
연결되어 있으면 (띄어쓰기가 없음) 하나의 단어로 인지
○ 문장 내에서 순차적 인덱스 부여하기
- fit_on_texts(텍스트 문장) : 문장 내에서 단어들을 추출하여 순차적 인덱스 부여하기
tokenizer.fit_on_texts(questions + answers)
○ 단어별 부여된 인덱스 확인하기
#단어별 부여된 인덱스 확인하기
print("단어 개수 : ",len(tokenizer.word_index))
tokenizer.word_index
단어 개수 : 74
{'가장': 1,
'좋아하는': 2,
...
'파리에요': 74}
▶ 단어에 인덱스 번호가 1번부터 부여됨
③ 질문 데이터 단어사전의 인덱스로 변환하기
○ 신경망에서 사용할 단어의 크기 설정 : 하나 더 크게 설정
vocab_size = len(tokenizer.word_index) + 1
vocab_size
75
○ 질문에 대한 텍스트 문장을 단어사전의 인덱스로 변환하기
- texts_to_sequences(문장) : 질문에 대한 텍스트 문장을 단어사전의 인덱스번호로 변환하기
questions_sequences = tokenizer.texts_to_sequences(questions)
print(questions_sequences)
questions_sequences
[[57, 15], [21], [58, 59, 60], [61, 62], [22, 23, 63], [24, 25], [26, 27, 15], [2, 4, 28], [29, 5, 6], [1, 2, 7, 3], [1, 8, 9, 10, 30], [11, 31, 32, 33], [2, 34, 35, 36], [1, 2, 12, 3], [1, 16, 17, 18, 19, 3] ....
④ 질문 데이터 단어의 길이를 통일시키는 정규화하기
- 잘라낼 max 길이 기준 : 문장들 중 최대 max 단어 길이 기준으로
- maxlen을 넣지 않으면 문장들의 길이가 가장 긴것을 기준으로 한다.
( 디폴트로 알아서 가장 긴 개수를 찾아낸다 )
- 채우기는 뒤쪽
questions_padded = pad_sequences(questions_sequences,
padding='post')
print(questions_padded)
questions_padded
[[57 15 0 0 0 0] [21 0 0 0 0 0] [58 59 60 0 0 0] [61 62 0 0 0 0] [22 23 63 0 0 0] [24 25 0 0 0 0] [26 27 15 0 0 0] [ 2 4 28 0 0 0] [29 5 6 0 0 0] [ 1 2 7 3 0 0] [ 1 8 9 10 30 0] ....
⑤ 답변 데이터 단어사전의 인덱스로 변환하기 & 단어 길이 통일시키기
# 답변데이터
answer_sequences = tokenizer.texts_to_sequences(answers)
answers_padded = pad_sequences(answer_sequences)
print(answers_padded)
[[64 65 66 13 0 0 0] [21 67 0 0 0 0 0] [68 69 70 0 0 0 0] [20 71 72 13 73 0 0] [22 23 74 0 0 0 0] [38 13 0 0 0 0 0] [39 40 0 0 0 0 0] [14 2 4 41 0 0 0] [ 5 42 43 6 0 0 0] ...
◇ 모델 처리
① 모델 생성 및 계층 추가
계층추가
- 단어 임베딩(입력계층으로 사용) : 출력 64
- simple RNN 사용 : 출력 128, 활성화함수 relu
- RepeatVector : 입력을 복제하는 전처리 계층
(텍스트에 대한 Encoder와 Decoder를 담당함)
- TimeDistributed : 각 타임별로 동일한 가중치를 적용하도록 처리
- 전체 시퀀스들의 이전/다음 인덱스 처리 값을 가지고 있다고 보면됨
- 예측에 주로 사용되는 계층
- 최종 출력 계층을 감싸고 있음
# 모델 생성하기
model = tf.keras.Sequential()
# 계층 추가하기
model.add(tf.keras.layers.Embedding(vocab_size, 64,
input_length = questions_padded.shape[1]))
model.add(tf.keras.layers.SimpleRNN(128,activation='relu'))
model.add(tf.keras.layers.RepeatVector(answers_padded.shape[1]))
model.add(tf.keras.layers.SimpleRNN(128,activation='relu',
return_sequences=True))
model.add(tf.keras.layers.TimeDistributed(tf.keras.layers.Dense(vocab_size,
activation='softmax')))
model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_1 (Embedding) (None, 6, 64) 4800
simple_rnn_2 (SimpleRNN) (None, 128) 24704
repeat_vector_1 (RepeatVect (None, 7, 128) 0
or)
simple_rnn_3 (SimpleRNN) (None, 7, 128) 32896
time_distributed_1 (TimeDis (None, 7, 75) 9675
tributed)
=================================================================
Total params: 72,075
Trainable params: 72,075
Non-trainable params: 0
_________________________________________________________________
② 모델 설정
- 숫자값, 다중분류이기 때문에 sparse_categorical_crossentropy 적용
# 모델 설정
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
③ 모델 훈련하기
model.fit(questions_padded,answers_padded,epochs=90,
batch_size=64,verbose = 1)
Epoch 90/90
1/1 [==============================] - 0s 5ms/step - loss: 0.1117 - accuracy: 0.9767
▶ epoch = 100으로 두었을때 훈련 정확도가 1 이 나와서 90으로 재설정하였다.
◇ 질문/답변 테스트
① 새로운 질문 텍스트를 단어사전의 인덱스 번호로 변환하기
user_input = "안녕하세요"
# 새로운 질문 텍스트를 단어사전의 인덱스 번호로 변환하기
input_seq = tokenizer.texts_to_sequences([user_input])
input_seq
[[21]]
② 단어의 길이를 훈련에서 사용한 길이로 통일시키기
padded_seq = pad_sequences(input_seq,padding='post',
maxlen=questions_padded.shape[1])
print(padded_seq)
[[21 0 0 0 0 0]]
③ 예측하기 : 새로운 질문에 대한 답변 추출하기
pred = model.predict(padded_seq)
▶ len(pred[0]) = 7 , len(pred[0][0]) = 75
answers 문자열의 7개 단어 각각의 75개의 말뭉치에 대한 확률 나타남
④ 답변으로 가장 확률이 높은 값 추출하기
pred_index = tf.argmax(pred,axis=-1).numpy()[0]
len(pred_index), pred_index
(7, array([21, 67, 0, 0, 0, 0, 0], dtype=int64))
⑤ 시퀀스에 해당하는 텍스트 추출하기
- 인덱스에 해당하는 실제 텍스트 추출하기
response = tokenizer.sequences_to_texts([pred_index])[0]
response
'안녕하세요 반가워요'
○ 질문/답변 테스트해보기(2)
# 질문/답변 테스트
user_input = "너 이름이 뭐니?"
# 새로운 질문 텍스트를 단어사전의 인덱스 번호로 변환하기
input_seq = tokenizer.texts_to_sequences([user_input])
# 단어의 길이를 훈련에서 사용한 길이로 통일시키기(정규화)
padded_seq = pad_sequences(input_seq,padding='post',
maxlen=questions_padded.shape[1])
# 예측하기 : 새로운 질문에 대한 답변 추출하기
pred = model.predict(padded_seq)
# 답변으로 가장 확률이 높은 값 추출하기
pred_index = tf.argmax(pred,axis=-1).numpy()[0]
# 시퀀스에 해당하는 텍스트 추출하기
response = tokenizer.sequences_to_texts([pred_index])[0]
response
'제 이름은 챗봇이에요'
◇ 질문/답변 무한반복 함수 생성 및 호출
○ 함수 생성
def get_Generate_Response(user_input):
# 새로운 질문 텍스트를 단어사전의 인덱스 번호로 변환하기
input_seq = tokenizer.texts_to_sequences([user_input])
# 단어의 길이를 훈련에서 사용한 길이로 통일시키기(정규화)
padded_seq = pad_sequences(input_seq,padding='post',
maxlen=questions_padded.shape[1])
# 예측하기 : 새로운 질문에 대한 답변 추출하기
pred = model.predict(padded_seq)
# 답변으로 가장 확률이 높은 값 추출하기
pred_index = tf.argmax(pred,axis=-1).numpy()[0]
# 시퀀스에 해당하는 텍스트 추출하기
response = tokenizer.sequences_to_texts([pred_index])[0]
return response
○ 함수 호출
while True:
user_input = input()
if user_input == "stop":
print("---------채팅 종료---------")
break
response = get_Generate_Response(user_input)
print(response)
안녕하세요 반가워요
---------채팅 종료---------
'머신러닝&딥러닝' 카테고리의 다른 글
[머신러닝&딥러닝] 실습 - 에너지 사용 패턴 확인을 통한 부하 타입 분류 (1) | 2024.01.09 |
---|---|
[딥러닝] 합성곱신경망(CNN)을 이용한 이미지 분류 (1) | 2024.01.08 |
[딥러닝] 순환신경망 - LSTM , GRU (0) | 2024.01.08 |
[딥러닝] 순환신경망(RNN) - 심플 순환신경망(Simple RNN) (1) | 2024.01.05 |
[딥러닝] 퍼셉트론 - 분류데이터 사용 (1) | 2024.01.05 |