データ拡張(Data Augmentation)徹底入門!Pythonとkerasでデータ拡張を実装しよう
分析結果
- カテゴリ
- IT
- 重要度
- 51
- トレンドスコア
- 15
- 要約
- データ拡張(Data Augmentation)徹底入門!Pythonとkerasでデータ拡張を実装しよう ホーム / 機械学習 / データ拡張(Data Augmentation)徹底入門!Pythonとkerasでデータ拡張を実装しよう 2021.09.13 by codexaチーム 0 何かを「集める」という作業は非常に大変です。特に画像などに関しては数枚程度であればすぐに集まりますが、数百枚、数千枚となってくると手作業ではかなり
- キーワード
データ拡張(Data Augmentation)徹底入門!Pythonとkerasでデータ拡張を実装しよう ホーム / 機械学習 / データ拡張(Data Augmentation)徹底入門!Pythonとkerasでデータ拡張を実装しよう 2021.09.13 by codexaチーム 0 何かを「集める」という作業は非常に大変です。特に画像などに関しては数枚程度であればすぐに集まりますが、数百枚、数千枚となってくると手作業ではかなり大変です。また、一般的に出回らないような画像であれば収集の制限はさらに厳しくなることが予想されます。 機械学習 、特に ディープラーニング による 画像認識 では大量の画像データを必要とする場合が多いです。時にその量は数万枚や数十万枚(またはそれ以上)に登る場合もあります。有名なCelebAのデータセットには202,599枚もの有名人の顔画像が用意されています。しかし、全てのデータセットがこれほどの量を保持しているわけではありません。そのため、私たちは現状で用意できるデータセットからデータ数を増やす手段を考える必要があります。(参考: CelebA Dataset ) その手段の1つとして、本稿では、Data Augmentation(読み:データ・オーギュメンテーション、訳:データ拡張)について解説していきます。前半では「Data Augmentationの基礎知識」、中盤では「Data Augmentationの各変換の実装」、後半では実際のデータセットを用いて「ニューラルネットワークによる分類」を行います。Data Augmentationは機械学習を使用して画像認識を学びたいと考えている方にとってはとても重要な技術になりますので、しっかりとした基礎知識と実装スキルを身につけましょう。 この記事の目次 1 前提知識 2 Data Augmentationとは 3 Data Augmentationの必要性 4 Data Augmentationの注意点 5 Data Augmentationのタイミング 6 Data Augmentation一覧 7 ニューラルネットワークによるCIFAR-10の分類 8 まとめ 前提知識 Data Augmentationの内容は機械学習で画像を扱う上では一部分でしかありません。そのため本稿を読まれる際には、画像認識の大枠や用語などの基礎知識(ディープラーニングやCNNなど)があることが望ましいです。それらの基礎知識だけでも非常に解説が長くなってしまうため、本稿では詳細には記載しません。もし、これらの知識に不安がある方は以下の記事を先に読まれることをお勧めします。本稿でも以下の記事で扱われている内容を前提に解説を進めていきます。 ディープラーニング: 今時のエンジニアが知っておくべきディープラーニングの基礎知識 CNN: 初心者のための畳み込みニューラルネットワーク(MNISTデータセット + Kerasを使ってCNNを構築) Data Augmentationとは Data Augmentation(データ拡張)とは、学習用の画像データに対して「変換」を施すことでデータを水増しする手法です。この「変換」には様々な種類が存在します。その種類についてはこの後、実装を踏まえて解説します。まずはData Augmentationを適用した画像を確認してみましょう。それぞれの写真がどのように変換されているのかに注目してください。なお本稿で使用されている画像に関しては以下のサイトから引用しています。(参考: フリー写真素材ぱくたそ ) 図1にはパンケーキが表示され、図2〜5では図1のパンケーキが少し変化した状態で表示されていることが分かると思います。図2では回転、図3では左移動、図4では拡大、図5では上移動と変化しています。このように1枚の画像から4枚の画像に変換され実質5枚の画像が存在しています。これがData Augmentationによる画像の水増しです。 本来、Data Augmentationには画像を「変換」する手法だけでなく、「生成」する手法も存在します。例としてはGAN(Generative Adversarial Networks)などの技術を利用したものです。しかし、これらの内容は高度な専門的知識が必要である上、本稿内に収めることが難しい内容なため、記載しません。今後、本稿でのData Augmentationは画像の「変換」を指します。皆様が学習を進めていく中で興味がでてきた方は是非調べて見てください。(参考: 敵対的生成ネットワーク Wikipedia ) Data Augmentationの必要性 本節ではData Augmentationの必要性について解説していきます。可能な限り直感的な理解ができるよう、画像を用いて解説していきます。必要性については主に以下の点が挙げられます。 データ数の増加 過学習への対策 データ数の増加 近年のニューラルネットワーク(特にCNN)による画像認識技術はとても進歩しています。同時に、開発されたモデルの中にはとても深い層をもつものもあります。そういったモデルの中には多くのパラメータを有するものもあり、学習のために大量のデータが必要とされる場合があります。しかし、データによっては必要な数を用意できない場合もあります。特に医療系などのプライバシーに関わるようなデータは比較的集めにくい現状があります。少ないデータ数でも学習を行えるようにするためにData Augmentationは必要なのです。実際に画像がどのように増えて見えるのかに関してはこのあとの「Data Augmentation一覧」で確認できます。 過学習への対策 もう一つは過学習への対策です。過学習に関する詳細は本稿では省きますが、簡単に述べると「学習用データに機械学習モデルが適合しすぎることにより、テストデータに対する適合率が下がる」ことを指します。私たちが画像認識のモデルを作成する根本的な目的は、学習したモデルを用いて、未知のデータを正しく分類・評価することです。そのため、どれだけ学習用データに対して高精度のモデルが完成したとしても、テストデータに対して精度が低ければ意味がありません。どのような例が考えられるのか、画像を使用しながら解説します。仮定する目的は「犬と猫を分類すること」とします。与えられる学習用データセットには図6、図7のような犬と猫の画像が存在しているとします。 上の画像は左が猫、右が犬の画像です。猫は左に、犬は右に体を向けています。もし、学習用データセット内の全ての犬猫が同じ体の向きだった場合、起こりうる問題として次のことが挙げられます。 左向きの犬を「猫」と予測する可能性がある 右向きの猫を「犬」と予測する可能性がある これは学習したモデルが、犬と猫を体の向きで判断するように学習してしまった場合に起こりうる問題です。極端な例ではありますが、テスト時に逆向きの犬猫が与えられる可能性はあります。この問題に対して、Data Augmentationは比較的有効です。この問題の根本は「学習用データセット内の犬猫の向きが同じ」であることです。つまり、犬と猫が左右両方を向いている画像があれば解決する可能性が高くなります。そこで、学習用データセットにData Augmentationを適用し、犬猫の画像を反転させた画像を加えます。 図8と図9の犬と猫の画像は図6と図7を反転させたものです。これによりモデルは学習用データセット内の画像に加えて、反転した画像も学習に使用できます。これでテスト時の画像で左右どちらの犬猫の画像が与えられたとしても、正しく分類できる確率は比較的高くなります。この考えはデータセットの規模が大きい場合にも適用できます。数が多いことと、データの質が高いことは別です。データ数が多くても、今回の仮定のように学習用データに「偏った特徴」が含まれていることもあります。 ここまでData Augmentationの必要性について解説してきました。今回の例はかなり極端なものでしたが、大まかな概要は掴むことができたと思います。冒頭でも述べたように、機械学習で画像認識の分野を扱いたい方にとってData Augmentationはとても重要な技術です。しかし、日常的に使用していると「なぜ」行なっているかを見失う場合があります。しっかりと必要性を理解した上で実装するように心がけましょう。 Data Augmentationの注意点 本節ではData Augmentationを使用する際の注意点について解説していきます。前節ではData Augmentationの必要性について記載してきましたが、常に有効であるとは限りません。有効でないData Augmentationとしては以下の点が挙げられます。 データセットに合わない変換 過学習 データセットに合わない変換 Data Augmentationは画像に対して様々な変換を施すことで、データを水増しします。しかし、考えなしで闇雲に変換すれば良いわけではありません。前節で述べたように、有効なData Augmentationを適用することは重要ですが、変換によっては逆にモデルの精度を下げる可能性もあります。次の画像にはいくつかのData Augmentationの適用例を示しています。画像を確認しながら適用されている変換が有効であるかを考えてみてくだい。 まずは図10〜図12の電車の画像を見てみます。ここでは電車の種類が何かを分類する機械学習モデルを作成すると仮定します。図11は電車がズームされており、図12は電車が回転されています。まず図11に関してですが、電車を撮影する際のズームのレベル感は撮影者に委ねられる場合が多いです。そのため、撮影者によっては引いた写真を撮る人もいれば、フレームいっぱいに撮影する方もいるかもしれません。そのため図11は比較的有効そうです。逆に図12は画像が回転され、電車が逆さまになっています。電車を逆さまに撮る方は少ないと考えられますし、事故でなければ電車が逆さまになる現場を目にすることはほとんどないと思われます。電車の種類を考えるのであれば、逆さまの写真はそれほど有効ではなさそうです。 次に、図13〜図15の数字の画像を見てみます。ここでは数字が0〜9の数字に分類する機械学習モデルを作成すると仮定します。図18は数字が少し回転しており、図19は数字が反対になっています。図14は少なめの回転ですので、撮影の状況によっては考慮できるレベルです。そのため有効と考えられます。逆に、図15は数字が反対になっていますが、4の数字をこの形で書くことはありません。数字の分類に対しては有効とは考えにくいです。 当然ですが、本当に有効か有効でないかは、実際にモデルで分類を行い、評価をしない限りは判断できません。しかし図12や図15など明らかに違和感のある画像に変換しない(または気づく)ことは重要です。有効でないData Augmentationはモデルの精度を著しく下げてしまう場合もあるので注意しましょう。 過学習 もう一つの注意点は過学習です。「Data Augmentationの必要性」ではData Augmentationは過学習を防ぐために有効であると記載しましたが、逆もあります。学習用データに「似た特徴」を与えてしまう可能性があることです。画像の変換によって増えた画像はある程度似た画像になります。そのため、モデルがそれらの画像に過剰に適合すると、過学習を引き起こす可能性があります。Data Augmentationは少ないデータ数でも学習を可能にするための手段として有効です。しかし、過学習を避けながら、複雑なモデルを使用する場合や高精度の評価を得たい場合には質のいいデータがある程度存在することが望ましいです。 ここまでData Augmentationの注意点について解説してきました。「Data Augmentationの必要性」と合わせて理解することができたでしょうか。実際、このような欠点に関する理解は様々なデータセットで練習し、実践を積むことが最も効果的です。本稿の後半でも実際のデータセットを用いますので、そちらも参考にしながら学習を進めてみてください。興味のある方はkaggleなどのデータ分析コンペティションなどのデータセットを使用してみるのも1つの手だと思います。(参考: kaggleとは? ) Data Augmentationのタイミング 本節ではData Augmentationが実際に適用されるタイミングについてお伝えします。今後Data Augmentationを実装していく際は、keras(本稿でも使用)やPyTorch(以下の記事を参考)を使うことが多くなるかと思います。その際に感じるのが、Data Augmentationがどのタイミングで行われているか分かりにくいということです。さらに、その部分が分からないまま学習を進めるとData Augmentationを間違えて理解してしまう可能性があります。少し難しい部分もありますので、図を用いながら可能な限り直感的に理解できるように解説していきます。(参考: PyTorch 入門!人気急上昇中のPyTorchで知っておくべき6つの基礎知識 ) オフライン拡張 1つ目はオフライン拡張(Offline Augmentation)です。オフライン拡張はデータセットに存在する画像自体にData Augmentationを適用し、単純に画像の枚数を増やす手法です。Data Augmentationを初めて聞いた方が真っ先に湧くイメージだと思います。図16はオフライン拡張の内容を示しています。 図16はデータセット内の各画像に対して回転の変換を加えた場合です。各画像1枚ずつの変換画像が出来上がるため、データセットは2倍になっています。これがオフライン拡張です。比較的小さなデータセットの場合に適応される場合があります。筆者自身はこの手法を扱った経験はありませんが、データ分析コンペティションなどで用意されたデータセットの中で既にオフライン拡張が行われていた経験はあります。 オフライン拡張には注意点があります。それはデータセット自体の容量が単純に増加するという点です。大量のデータを扱うディープラーニングでは、学習に必要なデータセットの容量はとても大きくなります。特に画像などのデータセットを扱う場合にはテーブルデータなどに比べて容量も大きくなりやすいです。オフライン拡張を行うということは画像データの増加に比例して容量も増加します。そのため、大容量のデータを保存できる領域が必須になります。保存領域には限りがあるのが一般的ですので、オフライン拡張でデータ数を増やす際には注意しなければなりません。 オンライン拡張 2つ目はオンライン拡張(Online Augmentation)です。記事によってはオンザフライ拡張(On-the-fly Augmentation)とも呼ばれていますが本稿ではオンライン拡張という言葉を使用します。オンライン拡張はオフライン拡張に比べて比較的一般的です。図17はオンライン拡張の手順を示しています。図と解説を照らしわあせながら理解しましょう。 オンライン拡張を理解するためにはミニバッチ学習という言葉を理解する必要があります。簡単に記載すると、データセットを複数に分割したものを使用して学習を行うことです。一般的にディープラーニングではモデルを学習させる際にデータセットを複数のミニバッチに分割し、ミニバッチごとに学習を行います。オンライン拡張は、モデルに入力するミニバッチに対してData Augmentationを適用します。 オンライン拡張ではデータセット自体の容量は増えません。オフライン拡張ではData Augmentationをランダムに設定してもデータ数は指定した数にしかなりませんが、オンライン拡張であれば学習毎にランダムな画像が生成されます。エポックを複数にして学習を行えば、同じミニバッチでも違う画像を使用することができます。これにより、モデルからするとより多くの画像を学習に使用することができることになります。 ここまで、Data Augmentationについて解説してきました。深い内容ですので、一度読んだだけで完全に理解するのは難しいかもしれません。そういった方は本稿を一通り読んでいただき、実装まで確認した上でもう一度本節を読み直していただくことをお勧めします。 Data Augmentation一覧 本節ではData Augmentationにおける画像変換の一覧を解説とともに実装します。様々な変換がありますが、1つ1つ順番に見ていくことで実際のデータセットに適応させる際もイメージがつきやすくなります。特にパラメータが存在する変換は値によって変換の度合いが決まります。Data Augmentationを使いこなすためにも、確実に理解しておきましょう。 実装はkerasと呼ばれるニューラルネットワークのライブラリを用います。Google Colabを用いて実装していきます。ライブラリをそのままインポートすれば同じように実装可能です。是非、ご自身でも実装してみてください。Google Colabを使用したことがない方は下記の記事を参考にしてください。(参考: Google Colabの知っておくべき使い方 – Google Colaboratoryのメリット・デメリットや基本操作のまとめ ) 最初の設定しとして、Google Colabの上部タブから「ランタイム」の「ランタイムの変更」を選択してください。そこから、「ハードウェアアクセラレータ」を「GPU」に変更してください。本節では使用しませんが、次節で使用するため、現段階で変更しておきます。変更ができたら、まずは必要なライブラリをインポートします。 #[IN]: #必要なライブラリのインポート import numpy as np import matplotlib.pyplot as plt from keras.preprocessing import image from keras.preprocessing.image import ImageDataGenerator,array_to_img,img_to_array 1 2 3 4 5 6 7 8 9 #[IN]: #必要なライブラリのインポート import numpy as np import matplotlib . pyplot as plt from keras . preprocessing import image from keras . preprocessing . image import ImageDataGenerator , array_to_img , img_to _ array 画像の準備 まずはGoogle Colab上に画像を読み込みます。本稿と同じ画像( パンケーキの画像 )を使用したい方は以下のサイトから利用規約に同意した上で画像をダウンロードしてください。アップロードが完了したら「パスをコピー」を選択してコード上に貼り付けてください。画像に関してはkerasのload_imgメソッドを用いて640×640にリサイズさせたものを読み込みます。(参考: フリー写真素材ぱくたそ(利用規約) ) #[IN]: #アップロードされた画像を読み込み img = image.load_img("/content/ogasuta458A8104_TP_V4.jpg", target_size=(640, 640)) #画像をnumpy配列に変換する img = np.array(img) #表示画像のサイズを設定 plt.figure(figsize = (10, 10)) #軸を表示しない plt.xticks(color = "None") plt.yticks(color = "None") plt.tick_params(bottom = False, left = False) #表示 plt.imshow(img) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #[IN]: #アップロードされた画像を読み込み img = image . load_img ( "/content/ogasuta458A8104_TP_V4.jpg" , target_size = ( 640 , 640 ) ) #画像をnumpy配列に変換する img = np . array ( img ) #表示画像のサイズを設定 plt . figure ( figsize = ( 10 , 10 ) ) #軸を表示しない plt . xticks ( color = "None" ) plt . yticks ( color = "None" ) plt . tick_params ( bottom = False , left = False ) #表示 plt . imshow ( img ) ImageDataGeneratorクラスについて 各変換に必要なImageDataGeneratorクラスについて解説します。ImageDataGeneratorはkerasが持つData Augmentationを行うためのクラスです。本稿ではこちらを用いてData Augmentationを実装していきます。ImageDataGeneratorクラスには様々な画像の変換がまとめて実装できるようになっています。以下のコードはImageDataGeneratorクラスのデフォルト引数になります。この中の引数の内、比較的よく使うものを中心に解説していきます。 #[IN]: #○がついている引数を本稿では扱う ImageDataGenerator( featurewise_center = False,#○ samplewise_center = False,#○ featurewise_std_normalization = False,#○ samplewise_std_normalization = False,#○ zca_whitening = False, zca_epsilon = 1e-06, rotation_range = 0,#○ width_shift_range = 0.0,#○ height_shift_range = 0.0,#○ brightness_range = None,#○ shear_range = 0.0,#○ zoom_range = 0.0,#○ channel_shift_range = 0.0,#○ fill_mode = "nearest",#○ cval = 0.0,#○ horizontal_flip = False,#○ vertical_flip = False,#○ rescale = None,#○ preprocessing_function = None,#○ data_format = None, validation_split = 0.0, dtype = None, ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #[IN]: #○がついている引数を本稿では扱う ImageDataGenerator ( featurewise_center = False , #○ samplewise_center = False , #○ featurewise_std_normalization = False , #○ samplewise_std_