2단계: 데이터 탐색하기

모델 빌드 및 학습은 워크플로의 한 부분입니다. 데이터의 특성을 미리 이해하면 더 나은 모델을 빌드할 수 있습니다. 이 경우 더 높은 정확도를 달성할 수 있습니다. 또한 학습에 필요한 데이터나 컴퓨팅 리소스가 적을 수 있습니다.

데이터 세트 로드

먼저 Python에 데이터 세트를 로드해 보겠습니다.

def load_imdb_sentiment_analysis_dataset(data_path, seed=123):
    """Loads the IMDb movie reviews sentiment analysis dataset.

    # Arguments
        data_path: string, path to the data directory.
        seed: int, seed for randomizer.

    # Returns
        A tuple of training and validation data.
        Number of training samples: 25000
        Number of test samples: 25000
        Number of categories: 2 (0 - negative, 1 - positive)

    # References
        Mass et al., http://www.aclweb.org/anthology/P11-1015

        Download and uncompress archive from:
        http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
    """
    imdb_data_path = os.path.join(data_path, 'aclImdb')

    # Load the training data
    train_texts = []
    train_labels = []
    for category in ['pos', 'neg']:
        train_path = os.path.join(imdb_data_path, 'train', category)
        for fname in sorted(os.listdir(train_path)):
            if fname.endswith('.txt'):
                with open(os.path.join(train_path, fname)) as f:
                    train_texts.append(f.read())
                train_labels.append(0 if category == 'neg' else 1)

    # Load the validation data.
    test_texts = []
    test_labels = []
    for category in ['pos', 'neg']:
        test_path = os.path.join(imdb_data_path, 'test', category)
        for fname in sorted(os.listdir(test_path)):
            if fname.endswith('.txt'):
                with open(os.path.join(test_path, fname)) as f:
                    test_texts.append(f.read())
                test_labels.append(0 if category == 'neg' else 1)

    # Shuffle the training data and labels.
    random.seed(seed)
    random.shuffle(train_texts)
    random.seed(seed)
    random.shuffle(train_labels)

    return ((train_texts, np.array(train_labels)),
            (test_texts, np.array(test_labels)))

데이터 확인

데이터를 로드한 후에는 데이터에 몇 가지 검사를 실행하는 것이 좋습니다. 몇 가지 샘플을 선택하여 예상과 일치하는지 직접 확인하세요. 예를 들어 몇 가지 무작위 샘플을 인쇄하여 감정 라벨이 리뷰의 감정과 일치하는지 확인합니다. 다음은 IMDb 데이터 세트에서 무작위로 고른 리뷰입니다. “10분 분량의 스토리가 2시간 중 더 나은 부분으로 확장되었습니다. 중간 지점에 유의미한 변화가 발생하지 않았다면 그대로 두어야 합니다.”라는 예상 감정 (음수)이 샘플 라벨과 일치합니다.

주요 측정항목 수집

데이터를 확인한 후 텍스트 분류 문제의 특성을 지정하는 데 도움이 되는 다음과 같은 중요한 측정항목을 수집합니다.

  1. 샘플 수: 데이터에 포함된 총 예

  2. 클래스 수: 데이터의 총 주제 또는 카테고리 수입니다.

  3. 클래스당 샘플 수: 클래스(샘플/카테고리)당 샘플 수 분산 데이터 세트의 모든 클래스에는 유사한 수의 샘플이 있습니다. 불균형 데이터 세트의 경우 각 클래스의 샘플 수가 크게 다릅니다.

  4. 샘플당 단어 수: 한 샘플에 포함된 단어 수의 중앙값입니다.

  5. 단어의 빈도 분포: 데이터 세트의 각 단어의 빈도(단어 수)를 보여주는 분포입니다.

  6. 샘플 길이 분포: 데이터 세트의 샘플당 단어 수를 보여주는 분포입니다.

IMDb 리뷰 데이터 세트에 대해 이러한 측정항목의 값이 무엇인지 살펴보겠습니다(그림 3의 주파수 및 샘플 길이 분포 도표 34 참고).

측정항목 이름 측정항목 값
샘플 수 25000
수업 수 2
클래스당 샘플 수 12500
샘플당 단어 수 174

표 1: IMDb 검토 데이터 세트 측정항목

explore_data.py에는 이러한 측정항목을 계산하고 분석하는 함수가 포함되어 있습니다. 예를 들면 다음과 같습니다.

import numpy as np
import matplotlib.pyplot as plt

def get_num_words_per_sample(sample_texts):
    """Returns the median number of words per sample given corpus.

    # Arguments
        sample_texts: list, sample texts.

    # Returns
        int, median number of words per sample.
    """
    num_words = [len(s.split()) for s in sample_texts]
    return np.median(num_words)

def plot_sample_length_distribution(sample_texts):
    """Plots the sample length distribution.

    # Arguments
        samples_texts: list, sample texts.
    """
    plt.hist([len(s) for s in sample_texts], 50)
    plt.xlabel('Length of a sample')
    plt.ylabel('Number of samples')
    plt.title('Sample length distribution')
    plt.show()

IMDb의 단어 배포 빈도

그림 3: IMDb의 단어 빈도 분포

IMDb의 샘플 길이 분포

그림 4: IMDb의 샘플 길이 분포