뮤트 개발일지

AIFFEL 아이펠 13일차 본문

AIFFEL

AIFFEL 아이펠 13일차

박뮤트 2022. 1. 13. 19:17

시퀀스 데이터: 나열된 데이터, 각 요소들이 동일한 속성을 띌 필요가 없으며 어떤 기준에 따라 정렬되어 있지 않아도 된다.

https://kukuta.tistory.com/310

 

[Python] 시퀀스 자료형 #1 리스트(list)

파이썬에선 값이 연속적으로 이어진 자료형들을 총칭하여 "시퀀스 자료형(sequence type)"이라고 부른다. 이번 강좌에서는 파이썬의 시퀀스 자료 구조 중의 하나인 리스트에 대해 알아 본다. 기본적

kukuta.tistory.com

순환신경망 RNN

<start> 토큰으로 시작하여 생성된 단어를 다시 input하는 방식, <end>로 끝난다.

 

tk.keras.preprocessing.test.Tokenizer: 텐서플로우가 제공하는 모듈(패키지), 정제된 데이터를 토큰화하고, 단어 사전을 만들어주며, 데이터를 숫자로 변환해준다.

벡터화vectorize: 데이터를 숫자로 변환해주는 과정

텐서tensor: 숫자로 변환된 데이터

https://rekt77.tistory.com/102

 

[인공지능 개념] Tensor란 무엇인가?

# 인공지능 기초 개념 안녕하세요 코드사기꾼입니다. 오늘은 Tensor에 대한 개념 정립을 하는 시간을 갖도록 하겠습니다. 인공지능 연구분야에서 가장 유명한 라이브러리인 TensorFlow를 정말 많은

rekt77.tistory.com


인공지능 작사가 만들기

import glob
import os, re
import tensorflow as tf
from sklearn.model_selection import train_test_split

txt_file_path = os.getenv('HOME')+'/aiffel/lyricist/data/lyrics/*'

txt_list = glob.glob(txt_file_path)

raw_corpus = []

# 여러개의 txt 파일을 모두 읽어서 raw_corpus 에 담습니다.
for txt_file in txt_list:
    with open(txt_file, "r") as f:
        raw = f.read().splitlines()
        raw_corpus.extend(raw)
        
def preprocess_sentence(sentence):
    sentence = sentence.lower().strip() # 1
    sentence = re.sub(r"([?.!,¿])", r" \1 ", sentence) # 2
    sentence = re.sub(r'[" "]+', " ", sentence) # 3
    sentence = re.sub(r"[^a-zA-Z?.!,¿]+", " ", sentence) # 4
    sentence = sentence.strip() # 5
    sentence = '<start> ' + sentence + ' <end>' # 6
    return sentence
    
# 정제된 문장 모으기
corpus = []

for sentence in raw_corpus:
    if len(sentence) == 0: continue
    if len(sentence) >= 15: continue
    
    preprocessed_sentence = preprocess_sentence(sentence)
    corpus.append(preprocessed_sentence)
    
def tokenize(corpus):
    # 12000단어를 기억할 수 있는 tokenizer를 만들기
    # 12000단어에 포함되지 못한 단어는 '<unk>'로 바꾸기
    tokenizer = tf.keras.preprocessing.text.Tokenizer(
        num_words=12000, 
        filters=' ',
        oov_token="<unk>"
    )
    # corpus를 이용해 tokenizer 내부의 단어장을 완성하기
    tokenizer.fit_on_texts(corpus)
    # 준비한 tokenizer를 이용해 corpus를 Tensor로 변환
    tensor = tokenizer.texts_to_sequences(corpus)   
    # 입력 데이터의 시퀀스 길이를 일정하게 맞춰준다
    # 만약 시퀀스가 짧다면 문장 뒤에 패딩을 붙여 길이를 맞춰준다
    # (문장 앞에 패딩을 붙이고 싶다면, padding='pre'를 사용)
    tensor = tf.keras.preprocessing.sequence.pad_sequences(tensor, padding='post')  
    
    print(tensor,tokenizer)
    return tensor, tokenizer

tensor, tokenizer = tokenize(corpus)

# tensor에서 마지막 토큰(<pad>일 확률이 높음)을 잘라내서 소스 문장을 생성
src_input = tensor[:, :-1]  
# tensor에서 <start>를 잘라내서 타겟 문장을 생성
tgt_input = tensor[:, 1:]    

enc_train, enc_val, dec_train, dec_val = train_test_split(src_input, 
                                                    tgt_input, 
                                                    test_size=0.2, 
                                                    random_state=7)

BUFFER_SIZE = len(enc_train)
BATCH_SIZE = 256
steps_per_epoch = len(enc_train) // BATCH_SIZE

 # tokenizer가 구축한 단어사전 내 12000개와, 여기 포함되지 않은 0:<pad>를 포함하여 12001개
VOCAB_SIZE = tokenizer.num_words + 1   

dataset = tf.data.Dataset.from_tensor_slices((enc_train, dec_train))
dataset = dataset.shuffle(BUFFER_SIZE)
dataset = dataset.batch(BATCH_SIZE, drop_remainder=True)

class TextGenerator(tf.keras.Model):
    def __init__(self, vocab_size, embedding_size, hidden_size):
        super().__init__()
        
        self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_size)
        self.rnn_1 = tf.keras.layers.LSTM(hidden_size, return_sequences=True)
        self.rnn_2 = tf.keras.layers.LSTM(hidden_size, return_sequences=True)
        self.linear = tf.keras.layers.Dense(vocab_size)
        
    def call(self, x):
        out = self.embedding(x)
        out = self.rnn_1(out)
        out = self.rnn_2(out)
        out = self.linear(out)
        
        return out
    
embedding_size = 3072
hidden_size = 1024
model = TextGenerator(tokenizer.num_words + 1, embedding_size , hidden_size)

optimizer = tf.keras.optimizers.Adam()
loss = tf.keras.losses.SparseCategoricalCrossentropy(
    from_logits=True, reduction='none')

model.compile(loss=loss, optimizer=optimizer)
model.fit(enc_train, dec_train, epochs=5, validation_data=(enc_val, dec_val))

BUFFER_SIZE = len(enc_val)
BATCH_SIZE = 256
steps_per_epoch = len(enc_val) // BATCH_SIZE

 # tokenizer가 구축한 단어사전 내 12000개와, 여기 포함되지 않은 0:<pad>를 포함하여 12001개
VOCAB_SIZE = tokenizer.num_words + 1   

test_dataset = tf.data.Dataset.from_tensor_slices((enc_val, dec_val))
test_dataset = test_dataset.shuffle(BUFFER_SIZE)
test_dataset = test_dataset.batch(BATCH_SIZE, drop_remainder=True)

results = model.evaluate(test_dataset)

def generate_text(model, tokenizer, init_sentence="<start>", max_len=20):
    
    test_input = tokenizer.texts_to_sequences([init_sentence])
    test_tensor = tf.convert_to_tensor(test_input, dtype=tf.int64)
    end_token = tokenizer.word_index["<end>"]

    # 단어 하나씩 예측해 문장을 만든다
    #    1. 입력받은 문장의 텐서를 입력
    #    2. 예측된 값 중 가장 높은 확률인 word index를 뽑는다
    #    3. 2에서 예측된 word index를 문장 뒤에 붙인다
    #    4. 모델이 <end>를 예측했거나, max_len에 도달했다면 문장 생성을 마친다
    while True:
        # 1
        predict = model(test_tensor) 
        # 2
        predict_word = tf.argmax(tf.nn.softmax(predict, axis=-1), axis=-1)[:, -1] 
        # 3 
        test_tensor = tf.concat([test_tensor, tf.expand_dims(predict_word, axis=0)], axis=-1)
        # 4
        if predict_word.numpy()[0] == end_token: break
        if test_tensor.shape[1] >= max_len: break

    generated = ""
    # tokenizer를 이용해 word index를 단어로 하나씩 변환
    for word_index in test_tensor[0].numpy():
        generated += tokenizer.index_word[word_index] + " "

    return generated
    
generate_text(model, tokenizer, init_sentence="<start> i love ", max_len=20)

'AIFFEL' 카테고리의 다른 글

AIFFEL 아이펠 15일차  (0) 2022.01.24
AIFFEL 아이펠 14일차  (0) 2022.01.17
AIFFEL 아이펠 12일차  (0) 2022.01.12
AIFFEL 아이펠 11일차  (0) 2022.01.11
AIFFEL 아이펠 10일차  (0) 2022.01.11