3つのJupyterノートブック(drug_[RGB].ipynbファイル)には、本稿冒頭で述べた処理を記述しています。全体としては以下のような
以下では、これらの処理の中でポイントとなったところを幾つかピックアップして紹介します。
ノートブックはdrug_R.ipynbファイル(ドラッグストアチェーンRの開店場所を推測するためのノートブック)をオリジナルとしています。つまり、最初はdrug_R.ipynbファイルで試験的なコードを書いたり実行したり修正したりした後に、「これでよいだろう」というコードが書けたところでノートブックをコピーして、残り2つのノートブックを作成しました。
とはいえ、実際にはオリジナルをコピーして3つのノートブックを作成した後にも細かな修正は発生するもので、そういうときには修正を行ったノートブックから他の2つのノートブックにコードセルの内容をコピー&ペーストすることもありました。
複数ファイルの管理が出てくると、JupyterノートブックよりもPythonファイルの方が便利そうですね。
このようなときには、ノートブックごとに固有の設定がファイル全体に散らばっていると修正が面倒になります。そのため、ノートブックごとに固有の設定を2カ所にまとめることにしました。
今回は周辺店舗情報を含んだファイル(dataフォルダに存在)や、出力するファイル名、オーバーサンプリングする際の倍数(後述)、乱数のシードなどの設定をノートブックの先頭で行っています。上で述べたデータフレームの要素の値を「1/距離」とするか「1/距離の二乗」とするかの設定もここで行っています(コメントアウト箇所)。基本的には変数chainの値を'R'から'G'、'B'に変更するだけで周辺店舗情報を含んだファイルの名前や出力ファイルの名前も自動的に変わるようにしているので、実際にはそれほど多数の要素を変更する必要はありません。
さらに今回はニューラルネットワークモデルに関連する設定をもう1カ所で行っています。
ノートブックごとに異なる設定を2カ所にまとめたので、オリジナルからコピーされた2つのノートブックでは、これらで必要な部分を変更するだけで、後はVS Codeの[すべてを実行]ボタンをクリックすれば開店場所の推測ができるようになりました。ノートブック全体に変更が必要な箇所が散らばっているとファイル全体を確認して修正をしなければならず、もしかしたら変更し忘れる可能性もあります。同じことをするノートブックを複数作成しなければならないようなときには、こんな感じで変更が必要な設定は数カ所、できれば1カ所をまとめることをオススメします。
今回、設定を1カ所にまとめていないのは「変数の定義はなるべくそれを使用する場所に近いところで行うべき」というプログラミングの世界に共通の慣習に合わせたものです。ノートブックの先頭で重みの数などを設定しても、それを使用するのがノートブックの中頃だと見直すときに面倒かもしれません。というか、こう書いていて思ったのですが、設定ファイルを作って、そのファイルを読み込むようにすればよかったんじゃないかな?
周辺店舗情報をデータフレームに読み込んで、訓練データとテストデータに分割する処理は次のようになっています。
周辺店舗情報は開店時のものと閉店時のものが別々のファイルに記録されているので、2つのファイルを別々のデータフレームに読み込んでいます。一番上のコードセルの出力を見ると、閉店時のデータ数(行数)が少ないことが分かります。61件と623件なので、この画像ならほぼ10分の1しかデータがありません。
この点には注意が必要でした。このままニューラルネットワークモデルを訓練すると、どんな周辺店舗情報を与えても「これは開店時のモノだよ」と推測するようにすれば90%程度の正解率で予測できるじゃんとなりかねません。
実際、初期のコードではこのことを考慮せずに編集部での会議で「いやー、スゴくよい正解率で推測できるようになりましたよ」と報告して、編集部の皆さんをぬか喜びさせたものです(遠い目)。
不均衡なデータ(imbalanced data)というよくあるパターンですね。
かといって、閉店時の周辺店舗情報のデータ数と開店時の周辺店舗のデータ数を単純にそろえると果たして訓練に十分なデータ数が確保できるかが不安になります(閉店時の周辺店舗情報のデータを全て訓練に使えるわけではなく、そこからテストデータとして何件かを抜き出して、訓練では使わないようにしておく必要もあります)。
というわけで、ここでは閉店時の周辺店舗情報を水増し(オーバーサンプリング)することにしました。あまりに増やすと過学習になる可能性もあるなぁということで、さじ加減が難しいのですが、ここでは3倍を基本線としました。これは先に述べた、ノートブック先頭の設定用のコードセルで変更できるようにしましたが、3つのノートブック全てで3倍のままです(変数num_oversampling)。
水増しをしているのが、一番下のコードセルにある「closed_shops_df = pd.concat([df0_tmp] * num_oversampling)」という部分です。
今回は3つのチェーン全てで、閉店時の周辺店舗情報の行数の方が、開店時の周辺店舗情報の行数よりも(圧倒的に)少なかったのですが、逆の場合もあるかもしれません。その場合は、開店時の周辺店舗情報を水増しすることになるでしょう(が、そのときには、設定だけではなくコードに変更を加える必要があります)。
訓練に使用する閉店時の周辺店舗情報のデータを何件にするかは、やはりノートブックの先頭で設定する変数num_samplingの値で指定するようにしました。ここでは、テストデータの数が開店時10件、閉店時10件、合わせて20件になるように設定しています。
例えば、上の画像なら閉店時の周辺店舗情報は61件しかないので、変数num_samplingの値を51としています。そして、上で述べた変数num_oversamplingの値と掛け合わせた51×3=153件が、訓練で使用する閉店時の周辺店舗情報数となります(水増し後)。後は、153件のデータを開店時の周辺店舗情報から抽出するようにすることで、開店時と閉店時の周辺店舗の数が同じになるようにしています。
訓練については、自分で定義したK分割交差検証をサポートしているKFoldDNNクラスのインスタンスを作成して、それにおまかせです。
1つ目のコードセルでは、上で見た訓練用のデータフレームとテスト用のデータフレームからPyTorchのデータセットを作成したり、隠れ層を3つ持つ全結合型のニューラルネットワーククラス(MyModelH3クラス)を使うことを指定したり、隠れ層の重みを指定したり(重みは全ての層で10個)、分割数に10を指定したりして、KFoldDNNクラスのインスタンスを生成しています。
そして、そのtrainメソッドを呼び出すと訓練が行われるという流れです。KFoldDNNクラスは内部で指定されたニューラルネットワーククラスのインスタンスを分割数(ここでは10)だけ作成し、それぞれが分割されたデータセット(訓練データと検証データ)を使って訓練するようになっています。
全結合型のニューラルネットワークモデルを使った訓練のコードなどは、Webを検索すればそこかしこで見られるものなので、この辺の詳細については省略します。
ニューラルネットワークモデルの訓練が終わったら、未知のデータ(テストデータ)を使って汎化性能を確認する必要もあります。これを行っているのが以下の画像です。
画像の上部には損失と正解率(accuracy)のグラフもチラリと見えていますね。その下にあるのは、KFoldDNNクラスのインスタンスが内部で持っている10個のニューラルネットワークモデルでそれぞれの検証データセットを使って確認した正解率の平均値です。
この画像の一番の下にあるセルではpredict2メソッドを呼び出していますが、ここで先ほど作成したテストデータ(20件)を使って、このモデルがどんな値を推測するかを調べています。
上の画像を見ると、正解数は14(正解率は0.7となかなか微妙なところです)、推測結果(predicted values)と教師ラベル(labels)を見ると、開店時の周辺店舗情報かどうかは正しく推測できていて、閉店時の周辺店舗情報かどうかについては間違いが多いようです(labelsが1のものが開店時の周辺店舗情報)。
最後にyokohama_grid.txtファイルからデータフレームを作成して、それを訓練後のニューラルネットワークモデルに与えて、候補地を得るコードを示します。
最初のセルではyokohama_grid.txtファイルからデータフレームを作成しています。そして、次のセルでは、作成したデータフレームをニューラルネットワークモデルに入力する部分(緯度経度を含む列を削除したもの)と、出力ファイルの作成で使用する部分(緯度経度)に分けたり、入力用のデータフレームの各要素の値を先ほどと同様に「1/距離の二乗」にしたり、それを正規化したりといった処理をしています。
3つ目のセルでは、データフレームを訓練後のニューラルネットワークモデルに入力して、推測値を得て、それを緯度経度列と結合し、推測値が0.9以上のものを抽出しています。
最後のセルでは候補地となるデータを表示しています。前回の記事の後にもコードを修正しているので、候補地の数が前回とは異なっている点には注意してください。後はこうして得られた候補地をoutputフォルダに出力したコピー&ペースト用のファイルから地図とピンを表示するためのHTMLファイルに貼り付けるだけです。これについては本題とは異なるので説明を省略します。
このような処理を3つのノートブックでそれぞれに実行した上で、ブラウザで表示したのが本稿の冒頭でお目に掛けたものということです。
今回はドラッグストア3チェーンの候補地の推測で行っていることをざっくりと紹介しました。次回は推測結果やニューラルネットワークモデルについて考察していく予定です。
Copyright© Digital Advantage Corp. All Rights Reserved.
Deep Insider 險倅コ九Λ繝ウ繧ュ繝ウ繧ー