データセット「Large Movie Review」について説明。IMDbサイト上での5万件の「テキスト(映画レビューコメント)」+「ラベル(ポジティブ/ネガティブの感情)」が無料でダウンロードでき、二値分類問題などのディープラーニングや機械学習に利用できる。元データの内容や、TensorFlow、Keras、PyTorchなどにおける利用コードも紹介。
Large Movie Review dataset(大規模な映画レビューのデータセット。以下、IMDbデータセット)は、映画レビューコメントが「ポジティブか/ネガティブか」という好悪感情を判別するために使える、感情分析用データセット(=構造化データセット)である(図1、Andrew Maas氏らが「IMDb:映画レビューサイト」上から抽出し、加工したデータセットである)。
IMDbデータセットは、主に二値分類(つまり「ポジティブか/ネガティブか」の判別)を目的としたディープラーニング/機械学習の研究や初心者向けチュートリアルで使われている。
IMDbデータセット全体は、
で構成される(※「ラベル」=正解を示す教師データ)。教師あり学習用に「ポジティブか/ネガティブか」というラベル付けが既に行われている事前処理済みのデータセットとなっている。これ以外にも、オリジナルのデータセットにはデータが含まれているが、詳しくは後述する。
このデータセットは、基本的に自由に使用できる(※ライセンスは指定されていない。厳密には、Andrew Maas氏の感情分析用データセットページを参照して確認してほしい。上記のデータセットページによると、ACL 2011の論文を引用すること、具体的には、
といった引用文献の記述が求められている(bib:LaTeX用の参考文献ファイル)。よって、自由に使用できるといっても、CC(Creative Commons)でいう「CC BY 4.0」相当と考えた方がよいだろう。
IMDbデータセット自体の情報を以下にまとめておく。
実際にIMDbデータセットを使うには、TensorFlow(tf.keras)/KerasやTensorFlow Datasets、PyTorchといった各ライブラリが提供する機能の利用をお勧めする(※なお、scikit-learnにはIMDbデータセットは用意されていなかった)。というのも、配布元の生データを各ライブラリや機械学習モデルが扱えるデータセット形式に自分で加工するのは少し手間だからだ。
配布元の生データについて、具体的に説明しておこう。Andrew Maas氏の感情分析用データセットページからダウンロードできるclImdb_v1.tar.gzファイル(以下、元データファイル)の中身のフォルダー構成は、
のようになっている。train/testフォルダーの下にあるpos/negフォルダーが教師あり学習用、trainフォルダーの下にあるunsupフォルダーが教師なし学習用である。各フォルダー内には、1つの映画レビューコメントのテキストが、1つのテキスト(.txt)ファイルに格納される形となっている。つまり、例えばtrain−posフォルダー内には1万2500個のテキストファイルが格納されているということだ。
そのためライブラリを使わない場合は、個々のテキストファイルを全て読み取り、自分で加工するプログラムを書かなければならない。
なお、元データファイルには、上記の論文で使われたBoW(Bag-of-Words:単語で構成される文章をベクトル表現で数値化したもの)などが含まれているので、それらを活用したい場合は、ライブラリ機能ではなく、元データファイルからデータを取得するとよい。BoWなどの詳細は、元データファイル内のREADMEファイルに記載されているので、そちらを参照してほしい。
さて以下では、それぞれのライブラリで「どのようなコードを書くとIMDbデータセットが使えるか」の典型的なコードを簡単に示しておく(※コードの詳細は解説しない)。基本的に各ライブラリは、IMDbデータセットを自動的にダウンロードして使いやすい形にロードしてくれる機能を提供している。
# !pip install tensorflow # ライブラリ「TensorFlow」をインストール
# !pip install keras # tf.kerasの場合は不要だが、Kerasを使う場合はライブラリ「Keras」をインストール
from tensorflow.keras.datasets import imdb # tf.kerasを使う場合(通常)
#from keras.datasets import imdb # tf.kerasではなく、Kerasを使う必要がある場合はこちらを有効にする
RESERVED = 3 # 「0」〜「2」は予約済みのインデックス(ID)として扱う
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(
num_words=None,# 上位N個の頻出語のみを対象とする。それより少ない頻出語はoov_charの単語に置き換えて表現される
skip_top=100, # 再頻出の上位N個の単語をスキップする(例えばtheやofなどは意味が弱く有益ではない場合があるため)。スキップされた単語はoov_charの単語に置き換えて表現される
maxlen=None, # シーケンスの最大長。それより長いシーケンスは切り捨てられる
start_char=1, # シーケンスの開始が、この単語/文字でマークされる
oov_char=2, # out-of-vocabulary(語彙外の単語)。上記のnum_wordsやskip_topによって削除された単語をこの単語/文字で置き換える
index_from=RESERVED, # 単語へのインデックス付けが、この値以上になる。パディング用の「0」と、上記のstart_char「1」とoov_char「2」を予約済みとし、それより後の「3以降」からインデックス(ID)を使うということ
seed=123) # シャッフル時に使うランダムシード(任意の数値)を指定可能
# 全ての「単語:ID」の辞書を取得する
word_index = imdb.get_word_index()
# 最初の「0」〜「2」のIDは予約済みとなっており、以下の意味になる
word_to_id = {k:(v+RESERVED) for k,v in word_index.items()}
word_to_id["<PADDING>"] = 0 # パディング(余白)
word_to_id["<START>"] = 1 # シーケンスの開始単語(start_charで定義)
word_to_id["<UNKNOWN>"] = 2 # 未知の単語(oov_charで定義)
# 「単語:ID」→「ID:単語」の辞書に変換する
id_to_word = {value:key for key,value in word_to_id.items()}
# テキストを取得する関数を定義
def get_imdb_review(text):
return ' '.join([id_to_word.get(id, '?') for id in text])
# 上記の関数の使用例
get_imdb_review(train_data[0])
# (実行結果では、訓練データの1番目のテキストが取得される)
tf.keras.datasets.imdb.load_data()関数を呼び出せばよい。この関数は高機能なため、引数も多く、またそれに伴う処理も少し必要になる。詳しくは上記関数のリンク先や、Kerasのドキュメント(日本語/英語)などを参照してほしい。
# !pip install tensorflow tensorflow-datasets # ライブラリ「TensorFlow」と「TensorFlow Datasets」をインストール
import tensorflow_datasets as tfds
(imdb_train, imdb_test) = tfds.load(
name='imdb_reviews', split=['train', 'test']) # 'unsupervised'もある
TensorFlow Datasetsで使用できるデータセットは、TensorFlow Datasetsにまとめられており、tensorflow_datasetsモジュール(=tfds)のtfds.load()関数から利用できる。リスト2では「imdb_reviewsデータセット」をロードしている。ロードできるデータには、教師あり学習用の訓練データ('train')とテストデータ('test')だけでなく、ラベルのない教師なし学習用のデータ('unsupervised')もある。
# !pip install torch torchtext # ライブラリ「PyTorch」をインストール
import torch
from torchtext.data import Field
from torchtext.datasets import IMDB
TEXT = Field(lower=True, include_lengths=True, batch_first=True)
LABEL = Field(sequential=False,)
train_ds, test_ds = IMDB.splits(TEXT, LABEL)
torchtext.datasets.IMDB.splits()クラスメソッド(もしくはコード例に含めていないがiters()クラスメソッド)を使えばよい。
Copyright© Digital Advantage Corp. All Rights Reserved.