今回は「日別売上の予測」という一度失敗している課題に再チャレンジしています。
今回は直近7日で8日目を予測・・に頭を切り替えてやってみました。
日別売上の予測っぽい事に再チャレンジ
前回は恥ずかしながら、うまくいきませんでした。
問題は、入力のXから生成されたX'をつかって、AutoEncoder的に生成したものが、なんとなくうまく行ったように見えたので、調子にのったことです(;^_^A。
まあ、冷静に考えると。
最終的に結果(y)を推論しないで「予測らしきこと」をしようという発想には無理がありすぎましたね。
Googleグループでも同じ話題がコメントされてました。
まあ・・、「こうしたらダメだよ」というのも情報ですから(笑)
開き直って、やってみます。
LSTMでやろうとしてみました
上記のGoogleグループでのコメント等を参考にするならば、7日分の売上データがデータ(x)で、次の7日分の売上を結果(y)するアプローチが必要です。
仮に、7日間の売上を7列1行の1週間分1ファイルで、0.csv、.1.csv・・のように作ったとしたら、イメージとしてはこんな感じ。
x:data,y:label
これを学習させて、最終週の7日分(x)のみ与えて、次週を予測させる。
こんな感じになるはずで、実際にこれをやるとしたら、学習データは、7日分(x_0~x_6)を収めたCSV(x)に対して、結果(y)の次の7日分をy__0~y__6に展開するようなことになるはずです。
このやり方はこちらのチュートリアルでも紹介されてますので、まあ、あってはいるでしょう。
なかなかしっくり来なかったです
上記のデータセットを使ってやってはみました。
ただ、結果はダメダメです。
用意できた学習データの量がせいぜい1年分(52週)程度では少なすぎます。
LSTMなんかは、もっと複雑で巨大なデータに適したモデルみたいなので、まあ、フェラーリで学校の100Mトラックを走ってるみたいな感じでしょうか(笑)
ということで。
LSTMは、すっぱり忘れましょう。
こちらのスライドの31ページ目にも書いてありますしね。
このCNNを、普通の浅いAffineモデルに読み替えてやってみましょう。
直近7日間の数値で翌日を予測するアプローチ
アイディアはこうです。
7日間の時系列データで、7日分の予測をするのではなく、1日ずつずらしながら、直近7日分の数値を一塊のデータとして、8日目の数値を予測する。
こうすれば、同じ期間の数値(例えば売上等)でも学習用データの量としては7倍にできますし、なにより、時系列で処理する必要がないので、普通のニューラルネットワークで対処できそうです。
新しいアイディアに沿ってデータを修正
使い方18の時同様に、日別の数値(売上?)を用意して、1.0~-1.0の範囲になるように100000で割って少数以下の数字にします(C列)。
これを、7日間をx__0~x__6のデータとして、8日目をyとする以下の1行8列のデータにして以下のようなCSVデータを作ります。
このやり方はNNCのチュートリアルのこの記事を参考にしています。
例によってCSVデータを生成するEXCEL-VBAプログラム
今回は、これで約5ヶ月分(約150行くらい)を学習用、同じフォーマットで最後の1週間分(7行)を評価用として2つのファイルを作りました。
手で作ると大変なので、こんな感じでEXCELのVBAでCSVデータを作って、あとで学習用と評価用にわけました。
ちなみに、ソースコード中の「forward01」は、シート名ですので、適宜書き換えてください。
Sub dataCreate3() Dim wkst Dim obj As Object Dim buf As Variant wkst = "forward01" bottom = Range("C2").End(xlDown).Row ts = 7 fn = 0 Set obj = CreateObject("ADODB.Stream") obj.Charset = "UTF-8" obj.Open datFile = ActiveWorkbook.Path & "\" & wkst & ".csv" out = "" out = "x,x__1,x__2,x__3,x__4,x__5,x__6,y" & vbNewLine obj.WriteText (out) For r = 1 To bottom - 1 If (r + 8) < (bottom - 1) Then out = "" out = out & Worksheets(wkst).Cells(r + 1, 3).Value & "," out = out & Worksheets(wkst).Cells(r + 2, 3).Value & "," out = out & Worksheets(wkst).Cells(r + 3, 3).Value & "," out = out & Worksheets(wkst).Cells(r + 4, 3).Value & "," out = out & Worksheets(wkst).Cells(r + 5, 3).Value & "," out = out & Worksheets(wkst).Cells(r + 6, 3).Value & "," out = out & Worksheets(wkst).Cells(r + 7, 3).Value & "," out = out & Worksheets(wkst).Cells(r + 8, 3).Value & vbNewLine obj.WriteText (out) fn = fn + 1 End If Next obj.Position = 0 obj.Type = adTypeBinary obj.Position = 3 buf = obj.read obj.Position = 0 obj.write buf obj.SetEOS obj.SaveToFile datFile, 2 obj.Close End Sub
ネットワークモデル
ニューラルネットワークコンソールを立ち上げて、EDITタブでモデルを組みます。
今回学習に使ったモデルです。
Input
inputは、x__0~x__6の7列+結果ラベル(y)の1行8列なのですが、チュートリアルにあるとおり、x__0~x__6の部分だけ・・つまり、7をサイズにします。
他のレイヤーの設定
AffineとTanhのあたりはoutshapeを7にあわせる以外は特別なことはありません。
回帰問題なので、最後はsquarederrorにします。
T.Dataset(アウトプット)は「y」です。
学習の実行
これで、DATASETに、さきほど用意したCSVファイルを指定して、学習させます。
学習のグラフはこんな感じ。
わりと最初の方は、かなり「暴れる」感じのグラフになるんですが、50epochあたりから収束してきました。
グラフだと100epochもあれば十分なようにも見えるのですが、今回、自分で試行錯誤した結果から言えば上記のように300epochくらいが最良でした。
バッチサイズもいろいろ試しましたが、ちょっと時間がかかりましたが、一番結果がよかったのは「1」でした。
評価の考え方
今回、用意した数値(いちおう、売上想定で1週間の曜日で凸凹をつけて、全体的には上昇トレンドを意識して作ったもの)は使い方18で使ったものの流用です。
ただし、期間をのばして約5ヶ月分の日別にしました。
グラフに描くと、全体としてはこういう見てくれです。
あ・・、データは小数点以下なんですが、グラフにするときには100000倍にして、元の整数部5桁の数字にもどしてますので、念のため。
このうちの最後の方だけを拡大してみると、作成したデータはちょうど頂点あたりで終わってます。
この続きを予測して継ぎ足してみて、不自然でない数字が予測されていれば、一旦はOKと判断できるんじゃないかと思ってます。
評価結果を加工しながら順次評価
さて、評価を実行した結果です。
プロジェクト名.filesフォルダの実行日付_時刻フォルダ(20180404_130520等)の下「output_result.csv」を開きます。
そうすると右端に「y'」の列があるので、その数値を結果としてコピーします。
実際には、その行のx__1~x__6を、x__0~x__5にずらして、結果のy'をx__6にして、また評価して・・みたいに地道にやる必要があったりします。
これはかなり面倒くさいので、今回のようにお試しでないなら、nnablaとかでプログラム組んだ方がよいとは思いますが・・とりあえず、今回はやってみました。
結果を確認する
結果のグラフです。
赤枠で囲った部分が、予測によって生成された数字です。
上昇トレンドも含めて、かなり、正確に予測できているような気はしますね。
しかも、今回はちゃんと推論した結果(y')を使ってますし。
一応、「予測っぽい」くらいのことはできてるんじゃないですかね。
ではでは。