Tensorflow Datasetsを使ってみよう

Reading Time: 2 minutes

皆様、こんにちは。Tranです。

日本に来てからそろそろ5年間が経つところで、毎日の仕事で日本語を使っているのですが、日本語でブログを書くのは初めてです。

ということで、何か分かりづらい表現があれば、教えていただければと思います。

さて、今回のトピックについてなんですけれども、最近出てきたTensorflow Datasets (tensorflow_datasets)をしばらく使ってみたので、勉強したことを共有したいと思います。

この記事は以下の大項目で構成されています。

  • データ用意の悩み
  • tensorflow_datasetsを使ってみよう
  • プロジェクト:動画評価の分類

では、順番に1つずつ進めていきたいと思います!

データ用意の悩み

機械学習、特に話題となっているディープラーニングというのは、特定の問題に対して、データを用意して、学習モデルを作って、目標を達するまで学習させるものでしょう。

そのうち、データを用意する作業は誰とも一番苦労するところではないでしょうか。簡単に説明すると、データ用意には、以下のようなことを含んでいます。

  1. データ収集:ネットやDBからデータを取得する作業です。
  2. データの前処理:生データのままだと学習できないのはほとんどで、いじる必要があり、画像だとresizeや正規化など、テキストだとvocabularyの作成やtokenizationなどが必要です。
  3. Input pipelineの作成:ニューラルネットワークを入れる前にすることです。batchを作成したりTensorに変換したりする作業ですね。

この記事を読んでいる人はたぶんTensorflowをさわったりしているかと思います。2年前に(たぶんTensorflow 1.3以前)、Tensorflowでデータを用意することが厳しかったですね。けれども、tf.data APIが出てから、上記の②と③が非常に簡単になってきました。サンキュー Google!

しかし、①は相変わらず、どうしても自分でやらないといけません。もちろん、サイズの小さいデータセット(MNISTやCIFAR-10)なら、tf.kerasに入っていますが、さすがに物足りないです。

コミューニティのそういう悩みを聞いて、Tensorflowチームはtensorflow_datasetsという新しいモジュールを提供してくれました。

では、tensorflow_datasetsは一体どういうものなのか、見ていきましょう!

tensorflow_datasetsを使ってみよう

これからtensorflow_datasetsを実感していきましょう。皆さんは私と同じ結果を再現できるために、自分の環境を紹介します。

  • OS:Ubuntu 18.04
  • GPU:NVIDIA GTX-1070
  • Tensorflow: 2.0

新しいTensorflow 2.0はまだインストールしていない場合、私の記事を参考頂ければなと思います:Install Tensorflow 2.0

準備ができましたか?では、行きましょう!

まず、必要なものをimportします。

今回のプロジェクトでは動画の評価を分類します。使うのはIMDBの動画評価データセットになります。データは以下のような感じですね。

Negativeのレビュー:

The Canterville Ghost (1996).The director made this too sappy a production. Maybe it’s the generation, but I really liked the Charles Laughton version. There is a time and place for “emoting” and this production does not translate very well. Patrick Stewart, reciting Shakespeare was very good, but still inappropriate. Would neither recommend nor watch again. The close-ups and padded text and sub-plots were lost on me. Adding extraneous material and scenes takes away from a truly great work. The screenplay writer should find another profession in which to misplace his talent, maybe afternoon soap operas would be a better venue. Check out the really good version and pass on this one.

Label: Negative

Positiveのレビュー:

This is one of the finest TV movies you could ever see. The acting, writing and production values are top-notch. The performances are passionate with Beverly D’Angelo superb as the older woman with a teenage daughter and Rob Estes simply perfect as the young stud boyfriend. However, the best part of this film was how it showed the consequences of sexual abuse instead of going for the usual happy ending. It showed that abuse can happen in good families; involve good people; and wreck lives. It is thought provoking and entertaining. Congratulations to all concerned with this exceptional movie.

Label: Positive

レビュー自体はちょっと長いですね(笑)。

通常のやり方だと。。。

私の個人の考えなんですけど、ある物を使うメリットを知るには、そのものはないときと見比べたほうがベストだと思います。

では、tensorflow_datasetsを使わない場合、どうしますかね。もちろん、データをネットで落とす必要があります。もうダウンロードし終わったとすれば、次にデータセットのフォルダー構成を見ますね。以下の感じです。

フォルダー構成を分かったうえで、テキストファイルの中身を読み込むコードを書いて、vocabularyとtokenizationを行って、最後はtf.data.Datasetのインスタンスを作ります。ちょっと時間がかかりそうで、どうしてもしんどく感じてしまいますね。

tensorflow_datasetsなら

tensorflow_datasetsなら、簡単にいうと、上記の手動作業を全部やってくれます!データをダウンロードするからtf.data.Datasetにするまで全部担当できます。

説得性はまだ弱いんじゃありませんか?では、見ていきましょう!

tensorflow_datasets(tfds)には複数のデータセットが入っています。よく見たことがあるMNISTやCIFAR-10をはじめ、GANによく使われているCELEB-Aが入っています。画像系だけでなく、機械翻訳へのWMTデータセットも用意してあります。もちろん、今回使うIMDBの動画評価データセットがあります。(まだたくさんありますが、記事の最後にリンクがあります)

tfdsを使うには、2つの方法があります。1つずつ紹介していきたいと思います。

builderを作成する

2つの方法のうち、builderを作成する方法のほうが基本的なアプローチです。なぜならば、builderを通じて、色々なオプションをつけることができます。

まず、データセット名を指定して、builderを作ります。

builderのオブジェクトができました。次に、データセットについての情報をこういうふうに出せます。

builderって便利なものですね。infoの中身を見ると、色々と分かることができます。

  • データには生テキスト(string)とラベル(2クラス)がある
  • データ数:50000
  • 学習データ数:25000
  • 推論データ数:25000

ここに注意点があります。builderを作成しても、データのダウンロードは自動で始まりません。download_and_prepare()という関数を呼び出すと、ダウンロードしてくれます。

ダウンロードが完了すると、もうデータセットを使えます。次の行はbuilderがダウンロードデータをもってtf.data.Datasetオブジェクトを返してくれます。そのオブジェクトも見ましょう。

さすが!学習と推論のためのtf.data.Datasetオブジェクトを作ってくれました。次に、学習のものを使いましょう。これからはtf.data APIの操作と変わりません。shuffleしてbatchのサイズを指定して、最後はiteratorを作ります。

tf.data APIを使ったことのない方、又はAPIの更新点がわかっていない方がいらっしゃるかと思いますので、ちょっと説明します。batch(5)は今までどおりで、batch sizeを指定します。take()は新しい関数で、Tensorflow 2.0から廃棄されたcreate_one_shot_iterator()の役割を担っています。take()のパラメータはbatchの数です。上のコマンドは、5つのレビューを含むbatchが2つあるデータセットを作るという意味です。

次はデータセットの中身をチェックします。

結果を見たとおり、データセットには2つのbatchがあって、それぞれ5つのレビューとそのラベルを含んでいます。

しかし、気になったかもしれませんが、データはdictになっていますね。つまり、モデルに入れるときに、こうしないといけません。

「いや!」と感じる方も多いでしょう。実はtupleになってもらう手法があります。builderにtf.data.Datasetオブジェクトを作ってもらう時点に、as_supervised=Trueと指定すれば、のちほどデータはtupleの形になります。

tupleになっていますね。よかった!

では、ここまではbuilderを作成する手法について紹介しました。

load関数を呼び出す

引き続き、もう1つの手法について紹介します。それは、tfdsload()関数を使うことです。

load()関数はtfdsの手順をもっと楽にする手法です。データセット名さえ指定すれば、ダウンロード及びtf.data.Datasetオブジェクトの作成は全部裏側で行われます。すごいでしょう!

次の1行を実行すれば、もうデータセットが使えるようになります!

上に見せたbuilderinfoが便利でしょう。load()を使ったら、もうinfoをみられなくなるのではって思われますね。心配しないでください。

load()関数にwith_info=Trueと渡せば、追加でinfoも返されます。

また、builderを作成する手法の同様に、何も指定しないと、データ型がdictになってしまいます。tupleを使いたければ、load()as_supervised=Trueと示すと十分でしょう。

では、tfdsload()関数を使う手法は以上になりました。個人個人で違いますから、自分に合う手法を選びましょう。

プロジェクト:動画評価の分類

ここまでは、tfdsを触ってみたんですが、次に、ディープラーニングのプロジェクトに適用してみませんか。

Input pipelineを作る

とりあえず、必要なpackageをimportして、各定数も定義します。

次に、データセットを作りましょう。

imdb_reviewsが分かるが、subwords32kって何?と疑問を持っている方がいるでしょう。

実はbuilderを作成するときでもload()を呼び出すときでも指定すべきなのはデータセット名だけでなく、データセット名/configです。データセット名だけ渡すと、デフォールトのconfigが使われます。

ここで、subwords32kと指定した理由はstringのtextをinteger値にしてもらいたいです。内部の処理にいうと、vocabularyが作成され、textがtokenizeされてからintegerの配列が返されます。以下の感じです。

さらに、infoの中にtokenizerというオブジェクトがあって、stringとintegerの間の変換を行う関数がそろっています。例えば、tokenizerのdecode()関数を使えば、integerの配列から元のtextに戻すことができます。

では、tokenizerをinfoからゲットしましょう。後でstringへの変換処理が必要ですから。

次のステップは、学習のデータセットと推論データセットを準備しておきましょう。学習データセットにおいては、まずshuffleして、batchのサイズを指定します。推論データセットも同様にやりますが、shuffleは要りません。

気づいたことがございませんか?今回はbatch()でなく、padded_batch()を使いましたね。

もう1度確認しましょう。データセットにstring textが入っていた上の例には、こうなりましたね。

features=FeaturesDict({

‘label’: ClassLabel(shape=(), dtype=tf.int64, num_classes=2),

‘text’: Text(shape=(), dtype=tf.string, encoder=None)

},

要するに、textはstringのscalar tensor(constant)です。

が、subwords25kのconfigで、integerの配列になってきました。

features=FeaturesDict({

‘label’: ClassLabel(shape=(), dtype=tf.int64, num_classes=2),

‘text’: Text(shape=(None,), dtype=tf.int64, encoder=<SubwordTextEncoder vocab_size=32650>)

},

tf.data APIはすべての要素のshapeは合わないとbatchを作れません。評価自体は人によって違って、長さはばらばらになっていますね。

というわけで、batch内の配列の長さを統一させる必要があります。それはpadded_batch()の得意なところです。注意点はbatch sizeの他に、padded_shapesを指定しないといけないところです。ここで何も考えずにデータのoutput_shapes(None,)とすれば、自動でbatch内の一番長い配列と合わせます。

では、ここまでInput pipelineの作成は完了しました。

モデルを作る

引き続き、学習用のモデルを作りましょう。そろそろTensorflow 2.0時代になるため、tf.kerasで進めていくことは間違いありません。

今回の動画評価データセットはサイズの小さいものとは言えます。なので、簡単なRNNでもいい結果を全然出すことができます。実装は以下の通りです。難しくはないですね。

私自身はtf.keras.Modelを継承するOOPアプローチのほうをよく使っています。tf.kerasのFunctional APIとは同じ自由度が得られますからね。

次に、損失関数を作ります。レビューはPositiveかNegativeかという2種類しかないため、BinaryCrossentropyの損失を使います。

また注意点があります(注意点なんて多い!)。Tensorflow 2.0から損失関数にfrom_logitsというパラメータがあります。そもそもlogitsは何かと言うと、activation(sigmoid、softmaxなど)を適用されていない出力を示しています。モデル作成のコードにも皆に見えるように、activationの部分をコメントアウトしています。from_logits=Trueとすることで、損失関数がactivation関数を適用してくれます。手動でsigmoidやsoftmaxをすると、数字的に発散することが出やすいとよく言われていますね。ライブラリに任せよう!

じゃ、モデル作成は以上になります。

Training loop

もう最後のステップになりますね。学習ループを作成しましょう。まず、optimizerから始めます。本プロジェクトではAdamを使います。

次に、epochごとに、学習データセットをループして、損失値を計算します。Tensorflow 2.0はもうeager executionがデフォルトになったため、入力を入れることから出力が出るまではtf.GradientTape()の下に置かないといけません。gradientsの情報を記録する仕組みですから。

出力が出た後に、上のtapeオブジェクトでgradientsを計算することができます。そして、optimizerにgradientsを適用してモデルのパラメータを更新してもらいます。のちほどaccuracyを出したいため、logitsがlabelとどれぐらい合っているかもチェックします。

最後に、100 batchごとに、損失値と精度を出します。また、モデルは推論データセットのレビューをちゃんと分類できるかどうかも確認したいので、任意の5つのレビューのlabelとモデルの結果も出力します。

それをもって、実装は完了しました!やっとできましたよ。次はコーヒーを取りに行って、学習結果を楽しむだけですね。

とくに問題がなければ、3か4 epoch目ぐらいにモデルはとてもいい精度が出せます。私のモデルの出力はこういう感じです。

みなさんのほうはいかがでしょうか?ディープラーニングモデルが動画評価を分類するのを楽しんでいますでしょうか?

また、本記事のプロジェクトのソースコードは私のGitHubに載せてあります。URLはこちらです。実装上で問題を発見したら、ご遠慮なく私へ連絡してください。

終わり

では、今日はtensorflow_datasetsについて紹介させていただきました。動画評価の分類のプロジェクトに適用したら、もうデータを用意する悩みはまったく感じられなかったのではないでしょうか。

これ以上知りたいな〜と思う方はtensorflow_datasetsのページを見て頂ければと思います。もちろん、私はこれからのプロジェクトではてっきりtf.data APIとtensorflow_datasetsを使いたいと思います。

ここで終わりたいと思います。長くなってしまいましたが、最後までブログをご覧いただき、誠にありがとうございました。

参考

  • tensorflow_datasets: link
  • text classification tutorial: link
  • how to install Tensorflow 2.0: link

Trung Tran is a Deep Learning Engineer working in the car industry. His main daily job is to build deep learning models for autonomous driving projects, which varies from 2D/3D object detection to road scene segmentation. After office hours, he works on his personal projects which focus on Natural Language Processing and Reinforcement Learning. He loves to write technical blog posts, which helps spread his knowledge/experience to those who are struggling. Less pain, more gain.

Leave a reply:

Your email address will not be published.