Assignment 4:  Simple Neutral Network을 이용한 IMDB movie review 데이터 감정분석

목표: 지금까지 배운 Simple Forward Neural Network을 영화평 리뷰의 감정분석(postive, negative)에 활용할 수 있도록 모델 구축

개요:  

 

def load_doc(filename):

   그대로 사용

# turn a doc into clean tokens

def clean_doc(doc, vocab):

그대로 사용

def process_docs(directory, vocab, is_trian):

그대로 사용

#encoding

def texts_to_sequence(train_docs):

   텍스트를 integer로 바꾸어 모델에 입력. 정규화 할 경우 전체 단어 수로 각 정수 값을 나누면 0-1사의 값으로 normalize됨

  입력 train_docs는 긍정, 부정의 영화평을 읽어 각 문서를 한 리스트에 저장된 list of list 구조

   우선 여기에 사용된 모든 어휘를  정수로 바꾸기 위한 중복된 어휘를 제거한 목록을 얻기 위한 flat_words  

    이 어휘 각각을 정수로 전환. enumerate를 사용하여 어휘의 리스트와 그 인덱스를 딕셔너리에 key와 value로 하여 바꿈

    #encode char->int,

    char_to_int = dict((c, i) for i, c in enumerate(flat_words))

   이제 train_docs 리스트에서 각 문서 리스트를 하나씩 불러와 개별 어휘를 정수로 바꾸고 다시 normalize하여 그 값을 계속 저장.

    최종 리턴되는 구조는  각 어휘가  0-1사이의 값으로 바뀐 입력 train_docs와 마찬가지인 list of list 구조를 리턴

 

#padding

def pad_sequences(sequences, number, width):

  simple neural network을 구성하기 위해 각 문서별 어휘의 수가 동일해야 균일한 입력 행렬을 구축할 수 있기 때문에 문서별로 다른 어휘 수를 최대 어휘수에 맞추기 위해 비어 있는 부분은 0으로 채우는 padding 구현

  입력은 text_toz_sequence에서 리턴된 list of list 구조인 sequences와 채워 넣을 수 인 number( 이 경우는 0), 그리고 최대 어휘 길이를 나타내는 width를 받아서 각 문서에서 최대 길이에 맞춰 0을 채워 넣는 모듈 작성

  여러 방법이 있으나 list.extend를 사용하고 itertools의 repeat를 사용하면 간단.

   반환되는 값은 0으로 채워져 각 문서가 동일한 list of list 구조

    return padd_seq_out

def one_hot_encoding(x):

    이전 과제에서 사용했던 것 그대로 사용

    return output

 

# load the vocabulary

vocab_filename = 'vocab.txt'

vocab = load_doc(vocab_filename)

vocab = vocab.split()

vocab = set(vocab)

 

# load all training reviews

positive_docs = process_docs('txt_sentoken/pos', vocab, True)

negative_docs = process_docs('txt_sentoken/neg', vocab, True)

train_docs = negative_docs + positive_docs

encoded_docs = texts_to_sequence(train_docs)

#padding을 위해 최대 길이의 문서 길이를 구함

max_length = max([len(s) for s in encoded_docs])

 

x_train = pad_sequences(encoded_docs, 0, max_length)

#x_train을 모델 학습을 위한 numpy array로 변환할 필요

x_train =

# define training labels

t_train = array([0 for _ in range(900)] + [1 for _ in range(900)])

t_train = one_hot_encoding(t_train)

# test 데이터도 마찬가지로 준비

# load all test reviews

positive_docs = process_docs('txt_sentoken/pos', vocab, False)

negative_docs = process_docs('txt_sentoken/neg', vocab, False)

test_docs = negative_docs + positive_docs

encoded_docs = texts_to_sequence(test_docs)

 

# 이 테스트 데이터에서도 max_length를 구해 padding에 사용해야 하나... 주의할 점은 training data의 max_length와 test data의 max_length가 서로 다를 경우

모델의 입력 형상이 달라지기 때문에 둘 중에서 더 큰 것으로 통일

max_length = max([len(s) for s in encoded_docs])

 

x_test = pad_sequences(encoded_docs, 0, max_length)

x_test =

 

# define training labels

t_test = array([0 for _ in range(100)] + [1 for _ in range(100)])

#ytrain = np.array(ytrain, dtype=int)

t_test = one_hot_encoding(t_test)

class TwoLayerNet:

....

network = TwoLayerNet(input_size=, hidden_size=50, output_size=)

# 하이퍼파라미터

iters_num = 10000  # 반복 횟수를 적절히 설정한다.

train_size = x_train.shape[0]

batch_size = 100   # 미니배치 크기

learning_rate = 0.1

 

train_loss_list = []

train_acc_list = []

test_acc_list = []

 

# 1에폭당 반복 수

iter_per_epoch = max(train_size / batch_size, 1)

 

for i in range(iters_num):

    # 미니배치 획득

    batch_mask = np.random.choice(train_size, batch_size)

    x_batch = x_train[batch_mask]

    t_batch = t_train[batch_mask]

 

    #print("BATCH", x_batch.shape, t_batch.shape)

    # 기울기 계산

    #grad = network.numerical_gradient(x_batch, t_batch)

    grad = network.gradient(x_batch, t_batch)

 

    # 매개변수 갱신

    for key in ('W1', 'b1', 'W2', 'b2'):

        network.params[key] -= learning_rate * grad[key]

 

    # 학습 경과 기록

    loss = network.loss(x_batch, t_batch)

    train_loss_list.append(loss)

 

    # 1에폭당 정확도 계산

    if i % iter_per_epoch == 0:

        train_acc = network.accuracy(x_train, t_train)

        test_acc = network.accuracy(x_test, t_test)

        train_acc_list.append(train_acc)

        test_acc_list.append(test_acc)

        print("train acc, test_acc |" + str(train_acc) + ", " +str(test_acc))