回答編集履歴

3

誤字の修正

2020/10/24 12:40

投稿

toast-uz
toast-uz

スコア3266

test CHANGED
@@ -120,7 +120,7 @@
120
120
 
121
121
 
122
122
 
123
- なお、全体の結果を擬似データで確認すると、30分後の予測、1日後の予測は観測との差が少なく、半日後の予測はそれなりではあるものの観測との差はやや大きい結果になるでしょう。これは当たり前のことで、LSTMはRNNよりは改善されていますが、それでも、昔よりは最近のことにより強く影響されるモデルだからです。1日単位の周期性があるデータは、半日後よりも1日後の方が「今」と類似しています。そのため、半日後予測よりも1日後予測の方が、正確に予測しているようにみえるわけです。
123
+ なお、全体の結果を擬似データで確認すると、30分後の予測、1日後の予測は観測との差が少なく、半日後の予測はそれなりではあるものの観測との差はやや大きい結果になるでしょう。これは当たり前のことで、LSTMはRNNよりは改善されていますが、それでも、昔よりは最近のことにより強く影響されるモデルだからです。1日単位の周期性があるデータは、半日後よりも1日後の方が「今」と類似しています。そのため、半日後予測よりも1日後予測の方が、正確に予測しているようにみえるわけです。
124
124
 
125
125
 
126
126
 

2

補足追記

2020/10/24 12:40

投稿

toast-uz
toast-uz

スコア3266

test CHANGED
@@ -120,7 +120,7 @@
120
120
 
121
121
 
122
122
 
123
- なお、全体の結果を擬似データで確認すると、30分後の予測、1日後の予測は観測との差が少なく、半日後の予測はそれなりではあるものの観測との差はやや大きい結果になるでしょう。これは当たり前のことで、LSTMは最近のことよく覚えているモデルだからです。1日単位の周期性があるデータは、半日後よりも1日後の方が「今」と類似しています。そのため、半日後予測よりも1日語後予測の方が、正確に予測しているようにみえるわけです。
123
+ なお、全体の結果を擬似データで確認すると、30分後の予測、1日後の予測は観測との差が少なく、半日後の予測はそれなりではあるものの観測との差はやや大きい結果になるでしょう。これは当たり前のことで、LSTMはRNNよりは改善されていますが、それでも、昔よりは最近のことり強影響されるモデルだからです。1日単位の周期性があるデータは、半日後よりも1日後の方が「今」と類似しています。そのため、半日後予測よりも1日語後予測の方が、正確に予測しているようにみえるわけです。
124
124
 
125
125
 
126
126
 

1

問題の修正にあわせた修正

2020/10/24 12:03

投稿

toast-uz
toast-uz

スコア3266

test CHANGED
@@ -1,5 +1,169 @@
1
- LSTMだと違うかもしれませんがバリデーションデータを使ってテスト(予測)していること問題なのはないでしょうか?
1
+ 予測以降処理において入力に対する正解の時間差pred_timeの扱いに間違っている部分あるようす。
2
2
 
3
3
 
4
4
 
5
- [なぜ教師あり学習バリデーションセットとテストセットを分ける必要があるか?](https://qiita.com/QUANON/items/ae569961ea02b4468e23)
5
+ 以下のコードにおいて、predは予測値で、x_testをもとにpred_time後の予測となっています。
6
+
7
+ また、t_testはもともとpred_time後の正解値です。よって、predとobsの時間差は既に無い状態です。
8
+
9
+
10
+
11
+ ```Python
12
+
13
+ pred = model.predict(x_test ) #予測値
14
+
15
+ obs = t_test
16
+
17
+ ```
18
+
19
+
20
+
21
+ にもかかわらず、以下のコードにおいてobsだけをpred_timeずらしています。この行為は意味がなく、これが結果に影響していると考えられます。
22
+
23
+
24
+
25
+ ```Python
26
+
27
+ #最初の1日を削除
28
+
29
+ dfd = dfd[int(time):]
30
+
31
+ dfp = dfp[int(time):]
32
+
33
+ dfo = dfo[int(time - pred_time):]
34
+
35
+ ```
36
+
37
+
38
+
39
+ ただし、この後にconcatしていることで上記の「ずらし」が複雑に作用します。Pandasでは明示的にindex振り直しを指示しない限り、元のindexを維持する形で処理されます。よってconcatの時点で「ずらし」は補正されてしまいます。結局「ずらし」は、頭に余計にNanを作る効果しかもたらせていません。
40
+
41
+
42
+
43
+ 擬似的な交通量を生成して、質問者様のコードを実行した結果、concat後のデータフレームは以下の形でした。(date_timeは日を単位とするfloatにしています)
44
+
45
+
46
+
47
+ ```
48
+
49
+ date_time Pt_pred Pt_obs
50
+
51
+ 720 NaN NaN 4211.390625
52
+
53
+ 721 NaN NaN 4310.817383
54
+
55
+ 722 NaN NaN 4800.063477
56
+
57
+ 723 NaN NaN 3912.796387
58
+
59
+ 724 NaN NaN 5271.840820
60
+
61
+ ... ... ... ...
62
+
63
+ 28795 99.996528 NaN NaN
64
+
65
+ 28796 99.997222 NaN NaN
66
+
67
+ 28797 99.997917 NaN NaN
68
+
69
+ 28798 99.998611 NaN NaN
70
+
71
+ 28799 99.999306 NaN NaN
72
+
73
+ ```
74
+
75
+
76
+
77
+ 上記にもかかわらず、質問者様の半日後の結果がズレてみえるのは、csv保存以降の処理で上記の、Pt_predとPt_obsの頭のズレが影響しているように思われます。この点はコードが明示されていないので推測ですが、少なくとも意味の無い「ズラし」が入っているため、これが原因の可能性が高いです。
78
+
79
+
80
+
81
+ 実際、擬似データをもとに、質問者様のコードに
82
+
83
+
84
+
85
+ ```Python
86
+
87
+ plt.plot(df['date_time'], df[['Pt_pred', 'Pt_obs']])
88
+
89
+ plt.show()
90
+
91
+ ```
92
+
93
+ を付け加えると、半日後であっても、それなりに予測〜観測が一致したグラフが出ます。
94
+
95
+
96
+
97
+ なお、本来あるべきコードは以下です。
98
+
99
+
100
+
101
+ ```Python
102
+
103
+ #最初の1日を削除
104
+
105
+ dfd = dfd[int(time + pred_time):].reset_index(drop=True)
106
+
107
+ dfp = dfp[int(time):].reset_index(drop=True)
108
+
109
+ dfo = dfo[int(time):].reset_index(drop=True)
110
+
111
+
112
+
113
+ #predとobsのDataFrameを一つにまとめる
114
+
115
+ df = pd.concat([dfd, dfp, dfo], axis=1).dropna()
116
+
117
+ ```
118
+
119
+ 「ズラし」はdfdのところだけを後ろに、dfpとdfoは余計にズラしません。またズラしが無効にならないようにreset_indexでindexを振りなおします。concatでまとめる時に、nanがある行は捨てるほうがよいです。
120
+
121
+
122
+
123
+ なお、全体の結果を擬似データで確認すると、30分後の予測、1日後の予測は観測との差が少なく、半日後の予測はそれなりではあるものの観測との差はやや大きい結果になるでしょう。これは当たり前のことで、LSTMは最近のことをよく覚えているモデルだからです。1日単位の周期性があるデータは、半日後よりも1日後の方が「今」と類似しています。そのため、半日後予測よりも1日語後予測の方が、正確に予測しているようにみえるわけです。
124
+
125
+
126
+
127
+ 100日もデータがあるわけですので、単純なLSTMを適用するのではなく、モデルを工夫してチューニングしてみることをオススメします。個人的には、周期性を考えて、30分後、1日後、5日後(五十日?の周期)、1週間後(平日週末の周期)、などをアンサンブルしてみるとよいかと思います。
128
+
129
+
130
+
131
+ 以下補足として、私が擬似データを作成するために使ったコードを示します。
132
+
133
+
134
+
135
+ ```Python
136
+
137
+ import numpy as np
138
+
139
+ from scipy.interpolate import interp1d
140
+
141
+
142
+
143
+ # 擬似的にdays日分の1分間隔の交通量を生成
144
+
145
+ days = 100
146
+
147
+ # まずは1日分作成、1日4つの時点のみ、質問者様のグラフを見て目分量でプロット
148
+
149
+ linear_interp = interp1d([0, 4, 7, 15, 24], [5000, 3000, 13000, 14000, 5000])
150
+
151
+ # 上記を直線で補間して1分間隔のデータにする
152
+
153
+ linear_results = linear_interp(np.linspace(0, 24, 24*60))[:-1]
154
+
155
+ # それを単純結合してdays日分にする
156
+
157
+ linear_results_days = np.array(linear_results.tolist() * days)
158
+
159
+ # ノイズを加える
160
+
161
+ noise = np.random.normal(0, 500, linear_results_days.shape)
162
+
163
+ Pt = linear_results_days + noise
164
+
165
+ # dateは1日を1.0のスケールにする
166
+
167
+ date = np.linspace(0, days, 24*60*days)[:-1]
168
+
169
+ ```