今回は,機械学習の分野でベースとなるモデルであるAE(AutoEncoder)をPythonで実装する方法をお伝えしていこうと思います。本記事はpython実践講座シリーズの内容になります。その他の記事は,こちらの「Python入門講座/実践講座まとめ」をご覧ください。

読みたい場所へジャンプ!
AEの概要
AE(オートエンコーダ)とは,簡単にまとめると以下のような手法です。
●入力を潜在空間上の特徴量で表す(エンコーダ)
●潜在空間から元の次元に戻す(デコーダ)
AEは主成分分析の非線形拡張だとも捉えられます。最近では,AEをベースに発展させたモデルが数多く考案されており,AEは機械学習の中でも非常に重要なモデルの1つとなっています。
ネットワークの構造

AEのネットワークは「エンコーダ部」と「デコーダ部」に分かれます。
エンコーダでは,基本的に元データの次元よりも小さな次元の潜在空間に入力を変換します。一方,デコーダでは潜在空間から元データの次元まで次元を元に戻します。AEのモチベーションは,再構成された
データセットの準備
今回は,コチラの記事でお伝えしている異常音検知用のデータセット「ToyADMOS」を利用したいと思います。音響特徴量としては,メルスペクトログラムの64次元を利用したいと思います。コチラの記事でお伝えしているwavファイルからメルスペクトログラムを学習データ分並べる方法を利用します。

以下でディレクトリ構成を説明しますが「../data/audio/ToyADMOS」に作成したスペクトログラムとそのサイズをndarray型で保存しています。サンプリング周波数が16000Hzのときに短時間フーリエ変換のホップ幅「hop_length」を160サンプルにすることで,1サンプルは0.01[s]になります。
実装
実装に関しては,非常に単純な構造になっています。ここでは,以下のようなディレクトリ構成を想定しています。カレントディレクトリは「algorithm」です。

必要なライブラリのインポート
必要なライブラリをインポートします。LambdaLPは学習率の変化を自分で記述するためのライブラリです。
deviceの定義
もしGPUが使えるなら,使えるようにdeviceを定義しておきましょう。
データの保存先・読み込み先の指定
これからAEを発展させることを考えて,汎用的な指定の仕方をしています。「os.makedirs」では末端ディレクトリが存在しない場合も勝手に作成してくれます。
データセットのロード
audio以下に先ほど作成したデータセットのメル周波数スペクトログラムが入っていることを前提としてデータを読み込んでサイズを表示しています。
マイデータセットの定義
pytorchで自作データセットを扱う場合には,自分でデータセットのクラスを定義しなくてはなりません。詳しくはコチラの記事でお伝えしていますが,特徴量の抽出方法も自分のデータセットクラスを定義する際に決めることができます。今回は,pytorchのデータローダーで指定されたインデックスの前後10フレームを取ってくるようなデータセットを定義しました。

ネットワークの定義
いよいよネットワークの定義です。何点かポイントがあります。まずは,入力の次元数が1280であるという点に注意しましょう。
先ほど指定されたインデックスの前後10フレームを取ってくるようなデータセットクラスを定義しましたね。そして,もともとスペクトログラムの周波数分解能(周波数方向の次元数)は64で指定していましたので,データセットクラス内で一次元化(flatten)された特徴量は20×64=1280次元になるのです。

データセットのインスタンス化
とりあえず,今回の前処理はテンソル化するだけにしておきます。他に考えられる処理としては,極端に小さい値は除算時にオーバーフローを起こしてしまう可能性があるため,0にしてしまうなどの操作が考えられます。
データセットをデータローダに変換
バッチサイズは適当に与えています。
モデルのインスタンス化
モデルをインスタンス化してGPUに突っ込みます。誤差基準は二乗誤差を使用します。optimizerにはアダムを利用して,学習率の初期値は
学習率の変化を設定
学習率をエポック数に対して変化させる関数を記述します。今回は,エポック数を200と固定して考えます。初期値を
モデルの学習
ここはいつもの流れです。一点だけ注意するべきなのは,各エポックごとに「scheduler.step」を組み込む点です。
モデルの保存
今回は,比較的大規模なデータセットを扱っているため,しっかりとモデルを保存するようにしましょう。paramsディレクトリに保存するように指定しています。
グラフ描写

初回のlossはランダムに出力された未学習の値であるため,描画していません。しっかりと学習できていることが分かります。
評価

今回は「正常 or 異常」の二値分類タスクであるため,評価指標はROC曲線と下側面積AUCを利用します。詳しくは,コチラの記事でROC曲線について説明しています。
細かいことはコメントで記してあります。今回利用したファイルはToyADMOSデータセットの中でもINDタイプであったため,各wavファイルの先頭と末尾は合成した背景雑音しか含まれていません。そのため,恣意的な操作ではありますが,前後50フレームはカットした形で異常スコアを計算します。
また,F値に関しては閾値を設定しなければ求めることができません。そこで,今回は原著論文[1]に従って,FPRを0.1に抑えたときの閾値を利用することにしました。
まとめ
ToyADMOSデータセットを利用したオートエンコーダの実装を確認しました。実際に実験を行うと,機械学習の大半は前処理やデータセット整備にかかっているということが身に染みて感じられました。おもちゃではありますが,現状では不足している異常音検知タスクのデータセットを作成していただいたNTT研究所に感謝です。
[1] Koizumi, Yuma, et al. “ToyADMOS: A Dataset of Miniature-Machine Operating Sounds for Anomalous Sound Detection.” arXiv preprint arXiv:1908.03299 (2019).
初めまして。初歩的な質問となり大変申し訳ないのですが、
項目「データセットの準備」の52行目のmy_modulesという関数はどこで定義していますでしょうか。
お忙しいところ恐れ入りますがご教授いただければ幸いです。
なー様
ご質問ありがとうございます。かなり昔の記事で未熟すぎる部分が多く恐縮なのですが、17行目で定義されているdata_listをそのまま呼び出せばよさそうです。
ご回答ありがとうございます。
ご確認頂き誠にありがとうございました。
内容確認させて頂きます!