import numpy as np from matplotlib import pyplot as plt from gluonts.dataset.common import ListDataset from gluonts.model.deepar import DeepAREstimator from gluonts.distribution.multivariate_gaussian import MultivariateGaussianOutput from gluonts.trainer import Trainer N = 20 # number of time series T = 100 # number of timesteps prediction_length = 10 freq = '1H' custom_datasetx = np.random.normal(size=(N, 2, T)) custom_datasetx[:,1,:] = custom_datasetx[:,1,:]*10 train_ds = ListDataset( [ {'target': x, 'start': '2019-01-01'} for x in custom_datasetx[0:17, :, :] ], freq=freq, one_dim_target=False, ) test_ds = ListDataset( [ {'target': x, 'start': '2019-01-01'} for x in custom_datasetx[17:, :, :] ], freq=freq, one_dim_target=False, ) estimator = DeepAREstimator( prediction_length=prediction_length, freq=freq, trainer=Trainer(epochs=5), distr_output=MultivariateGaussianOutput(dim=2), ) predictor = estimator.train(train_ds) from gluonts.evaluation.backtest import make_evaluation_predictions forecast_it, ts_it = make_evaluation_predictions( dataset=test_ds, predictor=predictor, num_samples=100 ) #from gluonts.evaluation import Evaluator from gluonts.evaluation import MultivariateEvaluator evaluator = MultivariateEvaluator(quantiles=[0.1, 0.5, 0.9]) agg_metrics, item_metrics = evaluator(ts_it, forecast_it, num_series=len(test_ds)) #print(json.dumps(agg_metrics, indent=4)) #print(item_metrics) item_metrics.plot(x='MSIS', y='MASE', kind='scatter', c=item_metrics.index, cmap='Accent') plt.grid(which="both") plt.show()
多変量時系列・GluonTSの動作確認(2019年11月29日)
はじめに
GluonTS 0.4.2が公開されているので過去のコードで動作確認してみた。
環境
Windows10 Pro NVIDIA GeForce GTX1080 CUDA 10.1 Python 3.6.8
GluonTSのインストール
pipでGluonTSをインストールした。
バージョン確認
boto3==1.10.28 botocore==1.13.28 certifi==2019.11.28 chardet==3.0.4 cycler==0.10.0 dataclasses==0.7 docutils==0.15.2 gluonts==0.4.2 graphviz==0.8.4 holidays==0.9.11 idna==2.6 jmespath==0.9.4 kiwisolver==1.1.0 matplotlib==3.1.2 mxnet-cu101==1.6.0b20191125 numpy==1.16.5 pandas==0.25.3 pydantic==1.2 pyparsing==2.4.5 python-dateutil==2.8.0 pytz==2019.3 requests==2.18.4 s3transfer==0.2.1 six==1.13.0 tqdm==4.39.0 ujson==1.35 urllib3==1.22
サンプルコード
以下のコードが問題なく実行できた。
import numpy as np from matplotlib import pyplot as plt from gluonts.dataset.common import ListDataset from gluonts.model.deepar import DeepAREstimator from gluonts.distribution.multivariate_gaussian import MultivariateGaussianOutput from gluonts.trainer import Trainer N = 20 # number of time series T = 100 # number of timesteps prediction_length = 10 freq = '1H' custom_datasetx = np.random.normal(size=(N, 2, T)) custom_datasetx[:,1,:] = custom_datasetx[:,1,:]*10 train_ds = ListDataset( [ {'target': x, 'start': '2019-01-01'} for x in custom_datasetx[0:19, :, :] ], freq=freq, one_dim_target=False, ) test_ds = ListDataset( [ {'target': x, 'start': '2019-01-01'} for x in custom_datasetx[19:, :, :] ], freq=freq, one_dim_target=False, ) estimator = DeepAREstimator( prediction_length=prediction_length, freq=freq, trainer=Trainer(epochs=5), distr_output=MultivariateGaussianOutput(dim=2), ) predictor = estimator.train(train_ds) from gluonts.evaluation.backtest import make_evaluation_predictions forecast_it, ts_it = make_evaluation_predictions( dataset=test_ds, predictor=predictor, num_samples=100 ) for x, y in zip(ts_it, forecast_it): for i in range(2): plt.subplot(2,1,i+1) x[i].plot() y.copy_dim(i).plot(color='g', prediction_intervals=(50.0, 90.0)) plt.show()
追記
Windows7にもインストールしてみた。問題なく動作している。
Windows 7 Professional GPUなし Python 3.7.4
boto3==1.10.28 botocore==1.13.28 certifi==2019.11.28 chardet==3.0.4 cycler==0.10.0 docutils==0.15.2 gluonts==0.4.2 graphviz==0.8.4 holidays==0.9.11 idna==2.6 jmespath==0.9.4 kiwisolver==1.1.0 matplotlib==3.1.2 mxnet==1.6.0b20191125 numpy==1.16.5 pandas==0.25.3 pydantic==1.2 pyparsing==2.4.5 python-dateutil==2.8.0 pytz==2019.3 requests==2.18.4 s3transfer==0.2.1 six==1.13.0 tqdm==4.39.0 ujson==1.35 urllib3==1.22
PyQt5を使ってみる(2) ラジオボタン
環境
Windows 10 Pro(CPU only) Python 3.7.5
バージョン
cycler==0.10.0 kiwisolver==1.1.0 matplotlib==3.1.1 numpy==1.17.4 pandas==0.25.3 pyparsing==2.4.5 PyQt5==5.13.2 PyQt5-sip==12.7.0 python-dateutil==2.8.1 pytz==2019.3 six==1.13.0
本文
CSVファイルを読み込んでラジオボタンの初期値にセットする。
冗長なコードだがシンプルで分かりやすく書いた。
- コード
import sys import pandas as pd from PyQt5 import QtCore from PyQt5.QtGui import QFont from PyQt5.QtWidgets import * ''' from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib import pyplot as plt import numpy as np ''' class Window(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("PyQt5 sample") self.setGeometry(50, 50, 660, 660) self.button1 = QPushButton('Select File', self) self.button1.setGeometry(QtCore.QRect(20, 20, 100, 30)) self.button1.clicked.connect(self.showDialog1) self.file_name = QLabel(self) self.file_name.setGeometry(130,20,400,30) self.file_name.setFrameStyle(QFrame.Box | QFrame.Plain) self.file_name.setFont(QFont('Meiryo',12)) self.ESA_label = QLabel(self) self.ESA_label.setGeometry(130,60,400,30) self.ESA_label.setFrameStyle(QFrame.Box | QFrame.Plain) self.ESA_label.setFont(QFont('Meiryo',12)) self.Fe_label = QLabel(self) self.Fe_label.setGeometry(130,100,400,30) self.Fe_label.setFrameStyle(QFrame.Box | QFrame.Plain) self.Fe_label.setFont(QFont('Meiryo',12)) ESA_yoko = 100 ESA_tate = 200 Fe_yoko = 300 Fe_tate = 200 self.Fe_yes = QRadioButton('あり', self) self.Fe_yes.setFocusPolicy(QtCore.Qt.NoFocus) self.Fe_yes.setGeometry(Fe_yoko, Fe_tate, 100, 25) self.Fe_yes.setFont(QFont('Meiryo',14)) self.Fe_no = QRadioButton('なし', self) self.Fe_no.setFocusPolicy(QtCore.Qt.NoFocus) self.Fe_no.setGeometry(Fe_yoko, Fe_tate + 40, 100, 25) self.Fe_no.setFont(QFont('Meiryo',14)) self.groupFe = QButtonGroup() self.groupFe.addButton(self.Fe_yes, 1) self.groupFe.addButton(self.Fe_no, 0) self.ESA0 = QRadioButton('なし', self) self.ESA0.setFocusPolicy(QtCore.Qt.NoFocus) self.ESA0.setGeometry(ESA_yoko, ESA_tate, 100, 25) self.ESA0.setFont(QFont('Meiryo',14)) self.ESA5 = QRadioButton('5μg', self) self.ESA5.setFocusPolicy(QtCore.Qt.NoFocus) self.ESA5.setGeometry(ESA_yoko, ESA_tate + 30, 100, 25) self.ESA5.setFont(QFont('Meiryo',14)) self.ESA10 = QRadioButton('10μg', self) self.ESA10.setFocusPolicy(QtCore.Qt.NoFocus) self.ESA10.setGeometry(ESA_yoko, ESA_tate + 60, 100, 25) self.ESA10.setFont(QFont('Meiryo',14)) self.ESA20 = QRadioButton('20μg', self) self.ESA20.setFocusPolicy(QtCore.Qt.NoFocus) self.ESA20.setGeometry(ESA_yoko, ESA_tate + 90, 100, 25) self.ESA20.setFont(QFont('Meiryo',14)) self.ESA30 = QRadioButton('30μg', self) self.ESA30.setFocusPolicy(QtCore.Qt.NoFocus) self.ESA30.setGeometry(ESA_yoko, ESA_tate + 120, 100, 25) self.ESA30.setFont(QFont('Meiryo',14)) self.ESA40 = QRadioButton('40μg', self) self.ESA40.setFocusPolicy(QtCore.Qt.NoFocus) self.ESA40.setGeometry(ESA_yoko, ESA_tate + 150, 100, 25) self.ESA40.setFont(QFont('Meiryo',14)) self.ESA60 = QRadioButton('60μg', self) self.ESA60.setFocusPolicy(QtCore.Qt.NoFocus) self.ESA60.setGeometry(ESA_yoko, ESA_tate + 180, 100, 25) self.ESA60.setFont(QFont('Meiryo',14)) self.ESA_list = [0,5,10,20,30,40,60] self.Fe_list = ['なし', 'あり'] self.groupESA = QButtonGroup() self.groupESA.addButton(self.ESA0, 0) self.groupESA.addButton(self.ESA5, 1) self.groupESA.addButton(self.ESA10, 2) self.groupESA.addButton(self.ESA20, 3) self.groupESA.addButton(self.ESA30, 4) self.groupESA.addButton(self.ESA40, 5) self.groupESA.addButton(self.ESA60, 6) for button in self.groupESA.buttons(): button.clicked.connect(self.clicked) for button in self.groupFe.buttons(): button.clicked.connect(self.clicked) def showDialog1(self): fname = QFileDialog.getOpenFileName(self, 'Select File') if fname[0]: self.file_name.setText(fname[0]) df = pd.read_csv(fname[0], index_col=0) self.groupFe.button(df.Fe[-1]).setChecked(True) self.groupESA.button(self.ESA_list.index(df.ESA[-1])).setChecked(True) self.clicked() def clicked(self): ESA = self.groupESA.checkedId() self.ESA_label.setText(str(self.ESA_list[ESA])) Fe = self.groupFe.checkedId() self.Fe_label.setText(self.Fe_list[Fe]) if __name__ == "__main__": app = QApplication(sys.argv) ex =Window() ex.show() sys.exit(app.exec_())
GluonTSの「to_pandas」(from gluonts.dataset.util)は多変量に対応していない!
対応させてみた。
def to_pandas_multi(instance: dict, dim: int) -> pd.Series: target = instance["target"] start = instance["start"] freq = start.freqstr index = pd.date_range(start=start, periods=target.shape[1], freq=freq) return pd.Series(target[dim,:], index=index)
以下の様な使い方を想定している。
pred = predictor.predict(test_data) plot_length = 48 prediction_intervals = (50.0, 90.0) legend = ["observations", "median prediction"] + [f"{k}% prediction interval" for k in prediction_intervals][::-1] for x, y in zip(test_data, pred): for i in range(target_num): plt.subplot(target_num,1,i+1) to_pandas_multi(x, i)[-plot_length:].dropna().plot() y.copy_dim(i).plot(color='g', prediction_intervals=prediction_intervals) plt.grid(which='both') plt.legend(legend, loc = 'upper left') plt.show()
多変量時系列 GluonTS DeepAR TODOリスト
個人的メモ
随時追記しています
4
github.com
将来の値が予測できない変数が多数ある時の方法
- if you don't have future values you can transform your original features into something else, which you could then more easily set (instead of using the direct value). For example, instead of using sunlight directly, you could use the co-variate "absolute/relative change to yesterday".
- another approach is to use mulit-variate forecasting techniques where you forecast everything jointly
5
- We align timestamps. The idea is that all timestamps within the same range, are represented by the same value. In this case 2019-7-2 is aligned to 2019-06-27.
必要性がいまいち理解できないがそういうものらしい。
- I think we should remove make_evaluation_predictions entirely for a better more understandable solution.
「make_evaluation_predictions」はなくなるらしい。
こちらで議論されている。
PyQt5を使ってみる
環境
Windows 10 Pro(CPU only) Python 3.7.5
まずは最小画面の描画
- バージョン
PyQt5==5.13.2 PyQt5-sip==12.7.0
- コード
import sys from PyQt5 import QtCore from PyQt5.QtWidgets import * class Window(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("pyQt5 sample") self.setGeometry(50, 50, 660, 660) self.button1 = QPushButton('Open Img', self) self.button1.setGeometry(QtCore.QRect(20, 20, 100, 30)) self.img_label1 = QLabel(self) self.img_label1.setGeometry(QtCore.QRect(74, 120, 512, 512)) self.img_label1.setFrameStyle(QFrame.Box | QFrame.Plain) if __name__ == "__main__": app = QApplication(sys.argv) ex =Window() ex.show() sys.exit(app.exec_())
- 結果
つぎにボタンを押したときの動作を定義する(画像表示)
- ボタンを押すとファイル選択画面が開く
- ファイルを選択すると画面に表示する
- 追加するコード
from PyQt5.QtGui import QImage, QPixmap
self.button1.clicked.connect(self.showDialog1)
def showDialog1(self): fname = QFileDialog.getOpenFileName(self, 'Open file') # fname[0]は選択したファイルのパス(ファイル名を含む) if fname[0]: # 画像の読み込み, サイズ変更 image = QImage(fname[0]).scaled(512,512,QtCore.Qt.KeepAspectRatio) # 画像の表示 self.img_label1.setPixmap(QPixmap.fromImage(image))
- 最終的なコード
import sys from PyQt5 import QtCore from PyQt5.QtWidgets import * from PyQt5.QtGui import QImage, QPixmap class Window(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("pyQt5 sample") self.setGeometry(50, 50, 660, 660) self.button1 = QPushButton('Open Img', self) self.button1.setGeometry(QtCore.QRect(20, 20, 100, 30)) self.img_label1 = QLabel(self) self.img_label1.setGeometry(QtCore.QRect(74, 120, 512, 512)) self.img_label1.setFrameStyle(QFrame.Box | QFrame.Plain) self.button1.clicked.connect(self.showDialog1) def showDialog1(self): fname = QFileDialog.getOpenFileName(self, 'Open file') # fname[0]は選択したファイルのパス(ファイル名を含む) if fname[0]: # 画像の読み込み, サイズ変更 image = QImage(fname[0]).scaled(512,512,QtCore.Qt.KeepAspectRatio) # 画像の表示 self.img_label1.setPixmap(QPixmap.fromImage(image)) if __name__ == "__main__": app = QApplication(sys.argv) ex =Window() ex.show() sys.exit(app.exec_())
matplotlibのグラフを表示させる
- バージョン
cycler==0.10.0 kiwisolver==1.1.0 matplotlib==3.1.1 numpy==1.17.4 pyparsing==2.4.5 PyQt5==5.13.2 PyQt5-sip==12.7.0 python-dateutil==2.8.1 six==1.13.0
- 最終コード
import sys from PyQt5 import QtCore from PyQt5.QtWidgets import * from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib import pyplot as plt import numpy as np class Window(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("pyQt5 sample") self.setGeometry(50, 50, 660, 660) self.button1 = QPushButton('Open Img', self) self.button1.setGeometry(QtCore.QRect(20, 20, 100, 30)) self.FigureWidget = QWidget(self) self.FigureWidget.setGeometry(QtCore.QRect(74, 120, 512, 512)) self.FigureLayout = QVBoxLayout(self.FigureWidget) self.figure = plt.figure() self.axes = self.figure.add_subplot(111) self.axes.axis('off') self.canvas = FigureCanvas(self.figure) self.FigureLayout.addWidget(self.canvas) self.button1.clicked.connect(self.plot) def plot(self): x1=np.arange(0, 4*np.pi, 0.1) y1=np.sin(x1) self.axes.plot(x1,y1,c='r') self.axes.axis('on') self.canvas.draw() if __name__ == "__main__": app = QApplication(sys.argv) ex =Window() ex.show() sys.exit(app.exec_())
- グラフが二つになってもほぼ同様
import sys from PyQt5 import QtCore from PyQt5.QtWidgets import * from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib import pyplot as plt import numpy as np class Window(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("pyQt5 sample") self.setGeometry(50, 50, 660, 660) self.button1 = QPushButton('Open Img', self) self.button1.setGeometry(QtCore.QRect(20, 20, 100, 30)) self.FigureWidget = QWidget(self) self.FigureWidget.setGeometry(QtCore.QRect(74, 120, 512, 512)) self.FigureLayout = QVBoxLayout(self.FigureWidget) self.figure = plt.figure() self.axes1 = self.figure.add_subplot(211) self.axes1.axis('off') self.axes2 = self.figure.add_subplot(212) self.axes2.axis('off') self.canvas = FigureCanvas(self.figure) self.FigureLayout.addWidget(self.canvas) self.button1.clicked.connect(self.plot) def plot(self): x1=np.arange(0, 4*np.pi, 0.1) y1=np.sin(x1) self.axes1.plot(x1,y1,c='r') self.axes1.axis('on') self.axes2.plot(x1,y1,c='r') self.axes2.axis('on') self.canvas.draw() if __name__ == "__main__": app = QApplication(sys.argv) ex =Window() ex.show() sys.exit(app.exec_())
GluonTS の「LowrankMultivariateGaussianOutput」
使用例
estimator = DeepAREstimator(freq="7D", prediction_length=12, context_length=16, use_feat_dynamic_real = True, use_feat_static_cat = True, cardinality = [30], trainer=Trainer( epochs=30, ), distr_output=LowrankMultivariateGaussianOutput(dim=3, rank=2) )
ハイパーパラメーターのrankはどうやって決める?
元論文
As the rank hyperparameter r can typically be chosen to be much smaller than N, this leads to a significant speedup. N is the time series dimension.
Supplementary materialに以下のようなグラフがある。