fbprophetをSPSS Modelerで使用する

SPSS Modelerの拡張モデルノードを使って、時系列予測ライブラリのfbprophetを使ってモデリングとスコアリングを行いました。


■環境
Modeler 18.2.2
python 3.7.7(Anaconda)
fbprophet 0.7.1
Windows 10

# サンプルストリーム

https://github.com/hkwd/210224PythonExtension/raw/master/fbprophet/210324fbprophet.str

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/566e9e4f-ab98-eb89-825d-f7684e5dae9d.png)

# 事前作業
fbprophetのpipでの導入は、前提となるpystanのWindowsへの導入が難しく、またpystan3からWindowsのサポートがなくなりpystanの導入記事へのリンクも切れてしまっています。

https://facebook.github.io/prophet/docs/installation.html#installation-in-python

ですので、今回は以下の記事を参考にSPSSの拡張ノードでAnacondaのPythonを利用できるようにしておきます。

https://qiita.com/kawada2017/items/04f525727725d199723c

Anacondaでconda-foregeからパッケージを導入して、options.cfgの設定まで行っておきます。私の環境ではAnaconda Public Repositoryのパッケージではうまく動きませんでした。

上の手順でつくったバッチファイルなどを使って、conda環境にPATHが入った状態でModelerを起動しておきます。


# fbprophetの導入
以下のコマンドでconda-forgeからfbprophetを導入します。

```console:コマンド
#conda config --append channels conda-forge
conda activate modeler
conda install -c conda-forge fbprophet
conda list
```
```console:結果
(base) C:\Users\dsuser01>conda activate modeler

(modeler) C:\Users\dsuser01>conda install -c conda-forge fbprophet
Collecting package metadata (current_repodata.json): done
Solving environment: done

## Package Plan ##

  environment location: C:\Users\dsuser01\.conda\envs\modeler

  added / updated specs:
    - fbprophet


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    arviz-0.11.2               |     pyhd8ed1ab_0         1.4 MB  conda-forge
    bzip2-1.0.8                |       h8ffe710_4         149 KB  conda-forge
    cftime-1.4.1               |   py37hda49f71_0         205 KB  conda-forge
    convertdate-2.3.2          |     pyhd8ed1ab_0          37 KB  conda-forge
    curl-7.75.0                |       hf1763fc_0         127 KB  conda-forge
    cycler-0.10.0              |             py_2           9 KB  conda-forge
    cython-0.29.22             |   py37hf2a7229_0         1.9 MB  conda-forge
    ephem-3.7.7.1              |   py37h4ab8f01_1         715 KB  conda-forge
    fbprophet-0.7.1            |   py37h1834ac0_0         567 KB  conda-forge
    freetype-2.10.4            |       h546665d_1         489 KB  conda-forge
    hdf4-4.2.13                |    h0e5069d_1004         1.1 MB  conda-forge
    hdf5-1.10.6                |nompi_h5268f04_1114        19.6 MB  conda-forge
    hijri-converter-2.1.1      |     pyhd8ed1ab_0          17 KB  conda-forge
    holidays-0.10.5.2          |     pyhd8ed1ab_0          65 KB  conda-forge
    jpeg-9d                    |       h8ffe710_0         366 KB  conda-forge
    kiwisolver-1.3.1           |   py37h8c56517_1          58 KB  conda-forge
    korean_lunar_calendar-0.2.1|     pyh9f0ad1d_0          10 KB  conda-forge
    krb5-1.17.2                |       hbae68bd_0         856 KB  conda-forge
    lcms2-2.12                 |       h2a16943_0         882 KB  conda-forge
    libcurl-7.75.0             |       hf1763fc_0         292 KB  conda-forge
    libnetcdf-4.7.4            |nompi_h3a9aa94_107         602 KB  conda-forge
    libpng-1.6.37              |       h1d00b33_2         724 KB  conda-forge
    libpython-2.0              |   py37h03978a9_1          47 KB  conda-forge
    libssh2-1.9.0              |       h680486a_6         218 KB  conda-forge
    libtiff-4.2.0              |       hc10be44_0         1.1 MB  conda-forge
    lunarcalendar-0.0.9        |             py_0          20 KB  conda-forge
    lz4-c-1.9.3                |       h8ffe710_0         134 KB  conda-forge
    m2w64-binutils-2.25.1      |                5        44.3 MB  conda-forge
    m2w64-bzip2-1.0.6          |                6         102 KB  conda-forge
    m2w64-crt-git-5.0.0.4636.2595836|                2         3.4 MB  conda-forge
    m2w64-gcc-5.3.0            |                6        40.8 MB  conda-forge
    m2w64-gcc-ada-5.3.0        |                6        33.3 MB  conda-forge
    m2w64-gcc-fortran-5.3.0    |                6        10.2 MB  conda-forge
    m2w64-gcc-libgfortran-5.3.0|                6         342 KB  conda-forge
    m2w64-gcc-libs-5.3.0       |                7         520 KB  conda-forge
    m2w64-gcc-libs-core-5.3.0  |                7         214 KB  conda-forge
    m2w64-gcc-objc-5.3.0       |                6        15.2 MB  conda-forge
    m2w64-gmp-6.1.0            |                2         726 KB  conda-forge
    m2w64-headers-git-5.0.0.4636.c0ad18a|                2         5.6 MB  conda-forge
    m2w64-isl-0.16.1           |                2         655 KB  conda-forge
    m2w64-libiconv-1.14        |                6         1.5 MB  conda-forge
    m2w64-libmangle-git-5.0.0.4509.2e5a9a2|                2          23 KB  conda-forge
    m2w64-libwinpthread-git-5.0.0.4634.697f757|                2          31 KB  conda-forge
    m2w64-make-4.1.2351.a80a8b8|                2         117 KB  conda-forge
    m2w64-mpc-1.0.3            |                3          71 KB  conda-forge
    m2w64-mpfr-3.1.4           |                4         294 KB  conda-forge
    m2w64-pkg-config-0.29.1    |                2         467 KB  conda-forge
    m2w64-toolchain-5.3.0      |                7           3 KB  conda-forge
    m2w64-toolchain_win-64-2.4.0|                0           4 KB  conda-forge
    m2w64-tools-git-5.0.0.4592.90b8472|                2         320 KB  conda-forge
    m2w64-windows-default-manifest-6.4|                3           5 KB  conda-forge
    m2w64-winpthreads-git-5.0.0.4634.697f757|                2          47 KB  conda-forge
    m2w64-zlib-1.2.8           |               10         199 KB  conda-forge
    matplotlib-base-3.3.4      |   py37h3379fd5_0         6.7 MB  conda-forge
    msys2-conda-epoch-20160418 |                1           3 KB  conda-forge
    netcdf4-1.5.6              |nompi_py37h4965ef1_100         358 KB  conda-forge
    olefile-0.46               |     pyh9f0ad1d_1          32 KB  conda-forge
    packaging-20.9             |     pyh44b312d_0          35 KB  conda-forge
    pandas-1.2.3               |   py37h08fd248_0         9.9 MB  conda-forge
    pillow-8.1.2               |   py37h96663a1_0         773 KB  conda-forge
    pymeeus-0.5.10             |     pyhd8ed1ab_0         534 KB  conda-forge
    pyparsing-2.4.7            |     pyh9f0ad1d_0          60 KB  conda-forge
    pystan-2.19.1.1            |   py37h9758500_2        35.8 MB  conda-forge
    python-dateutil-2.8.1      |             py_0         220 KB  conda-forge
    pytz-2021.1                |     pyhd8ed1ab_0         239 KB  conda-forge
    scipy-1.6.1                |   py37h6db1a17_0        23.1 MB  conda-forge
    tk-8.6.10                  |       h8ffe710_1         3.2 MB  conda-forge
    tornado-6.1                |   py37hcc03f2d_1         648 KB  conda-forge
    xarray-0.17.0              |     pyhd8ed1ab_0         561 KB  conda-forge
    xz-5.2.5                   |       h62dcd97_1         211 KB  conda-forge
    zlib-1.2.11                |    h62dcd97_1010         126 KB  conda-forge
    zstd-1.4.9                 |       h6255e5f_0         915 KB  conda-forge
    ------------------------------------------------------------
                                           Total:       273.0 MB

The following NEW packages will be INSTALLED:

  arviz              conda-forge/noarch::arviz-0.11.2-pyhd8ed1ab_0
  bzip2              conda-forge/win-64::bzip2-1.0.8-h8ffe710_4
  cftime             conda-forge/win-64::cftime-1.4.1-py37hda49f71_0
  convertdate        conda-forge/noarch::convertdate-2.3.2-pyhd8ed1ab_0
  curl               conda-forge/win-64::curl-7.75.0-hf1763fc_0
  cycler             conda-forge/noarch::cycler-0.10.0-py_2
  cython             conda-forge/win-64::cython-0.29.22-py37hf2a7229_0
  ephem              conda-forge/win-64::ephem-3.7.7.1-py37h4ab8f01_1
  fbprophet          conda-forge/win-64::fbprophet-0.7.1-py37h1834ac0_0
  freetype           conda-forge/win-64::freetype-2.10.4-h546665d_1
  hdf4               conda-forge/win-64::hdf4-4.2.13-h0e5069d_1004
  hdf5               conda-forge/win-64::hdf5-1.10.6-nompi_h5268f04_1114
  hijri-converter    conda-forge/noarch::hijri-converter-2.1.1-pyhd8ed1ab_0
  holidays           conda-forge/noarch::holidays-0.10.5.2-pyhd8ed1ab_0
  jpeg               conda-forge/win-64::jpeg-9d-h8ffe710_0
  kiwisolver         conda-forge/win-64::kiwisolver-1.3.1-py37h8c56517_1
  korean_lunar_cale~ conda-forge/noarch::korean_lunar_calendar-0.2.1-pyh9f0ad1d_0
  krb5               conda-forge/win-64::krb5-1.17.2-hbae68bd_0
  lcms2              conda-forge/win-64::lcms2-2.12-h2a16943_0
  libcurl            conda-forge/win-64::libcurl-7.75.0-hf1763fc_0
  libnetcdf          conda-forge/win-64::libnetcdf-4.7.4-nompi_h3a9aa94_107
  libpng             conda-forge/win-64::libpng-1.6.37-h1d00b33_2
  libpython          conda-forge/win-64::libpython-2.0-py37h03978a9_1
  libssh2            conda-forge/win-64::libssh2-1.9.0-h680486a_6
  libtiff            conda-forge/win-64::libtiff-4.2.0-hc10be44_0
  lunarcalendar      conda-forge/noarch::lunarcalendar-0.0.9-py_0
  lz4-c              conda-forge/win-64::lz4-c-1.9.3-h8ffe710_0
  m2w64-binutils     conda-forge/win-64::m2w64-binutils-2.25.1-5
  m2w64-bzip2        conda-forge/win-64::m2w64-bzip2-1.0.6-6
  m2w64-crt-git      conda-forge/win-64::m2w64-crt-git-5.0.0.4636.2595836-2
  m2w64-gcc          conda-forge/win-64::m2w64-gcc-5.3.0-6
  m2w64-gcc-ada      conda-forge/win-64::m2w64-gcc-ada-5.3.0-6
  m2w64-gcc-fortran  conda-forge/win-64::m2w64-gcc-fortran-5.3.0-6
  m2w64-gcc-libgfor~ conda-forge/win-64::m2w64-gcc-libgfortran-5.3.0-6
  m2w64-gcc-libs     conda-forge/win-64::m2w64-gcc-libs-5.3.0-7
  m2w64-gcc-libs-co~ conda-forge/win-64::m2w64-gcc-libs-core-5.3.0-7
  m2w64-gcc-objc     conda-forge/win-64::m2w64-gcc-objc-5.3.0-6
  m2w64-gmp          conda-forge/win-64::m2w64-gmp-6.1.0-2
  m2w64-headers-git  conda-forge/win-64::m2w64-headers-git-5.0.0.4636.c0ad18a-2
  m2w64-isl          conda-forge/win-64::m2w64-isl-0.16.1-2
  m2w64-libiconv     conda-forge/win-64::m2w64-libiconv-1.14-6
  m2w64-libmangle-g~ conda-forge/win-64::m2w64-libmangle-git-5.0.0.4509.2e5a9a2-2
  m2w64-libwinpthre~ conda-forge/win-64::m2w64-libwinpthread-git-5.0.0.4634.697f757-2
  m2w64-make         conda-forge/win-64::m2w64-make-4.1.2351.a80a8b8-2
  m2w64-mpc          conda-forge/win-64::m2w64-mpc-1.0.3-3
  m2w64-mpfr         conda-forge/win-64::m2w64-mpfr-3.1.4-4
  m2w64-pkg-config   conda-forge/win-64::m2w64-pkg-config-0.29.1-2
  m2w64-toolchain    conda-forge/win-64::m2w64-toolchain-5.3.0-7
  m2w64-toolchain_w~ conda-forge/win-64::m2w64-toolchain_win-64-2.4.0-0
  m2w64-tools-git    conda-forge/win-64::m2w64-tools-git-5.0.0.4592.90b8472-2
  m2w64-windows-def~ conda-forge/win-64::m2w64-windows-default-manifest-6.4-3
  m2w64-winpthreads~ conda-forge/win-64::m2w64-winpthreads-git-5.0.0.4634.697f757-2
  m2w64-zlib         conda-forge/win-64::m2w64-zlib-1.2.8-10
  matplotlib-base    conda-forge/win-64::matplotlib-base-3.3.4-py37h3379fd5_0
  msys2-conda-epoch  conda-forge/win-64::msys2-conda-epoch-20160418-1
  netcdf4            conda-forge/win-64::netcdf4-1.5.6-nompi_py37h4965ef1_100
  olefile            conda-forge/noarch::olefile-0.46-pyh9f0ad1d_1
  packaging          conda-forge/noarch::packaging-20.9-pyh44b312d_0
  pandas             conda-forge/win-64::pandas-1.2.3-py37h08fd248_0
  pillow             conda-forge/win-64::pillow-8.1.2-py37h96663a1_0
  pymeeus            conda-forge/noarch::pymeeus-0.5.10-pyhd8ed1ab_0
  pyparsing          conda-forge/noarch::pyparsing-2.4.7-pyh9f0ad1d_0
  pystan             conda-forge/win-64::pystan-2.19.1.1-py37h9758500_2
  python-dateutil    conda-forge/noarch::python-dateutil-2.8.1-py_0
  pytz               conda-forge/noarch::pytz-2021.1-pyhd8ed1ab_0
  scipy              conda-forge/win-64::scipy-1.6.1-py37h6db1a17_0
  tk                 conda-forge/win-64::tk-8.6.10-h8ffe710_1
  tornado            conda-forge/win-64::tornado-6.1-py37hcc03f2d_1
  xarray             conda-forge/noarch::xarray-0.17.0-pyhd8ed1ab_0
  xz                 conda-forge/win-64::xz-5.2.5-h62dcd97_1
  zlib               conda-forge/win-64::zlib-1.2.11-h62dcd97_1010
  zstd               conda-forge/win-64::zstd-1.4.9-h6255e5f_0


Proceed ([y]/n)? y
ーーーーーーーーーーーーーーー中略ーーーーーーーーーーーーーーーーーーー
done

(modeler) C:\Users\dsuser01>conda list
# packages in environment at C:\Users\dsuser01\.conda\envs\modeler:
#
# Name                    Version                   Build  Channel
arviz                     0.11.2             pyhd8ed1ab_0    conda-forge
brotlipy                  0.7.0           py37hcc03f2d_1001    conda-forge
bzip2                     1.0.8                h8ffe710_4    conda-forge
ca-certificates           2020.12.5            h5b45459_0    conda-forge
certifi                   2020.12.5        py37h03978a9_1    conda-forge
cffi                      1.14.5           py37hd8e9650_0    conda-forge
cftime                    1.4.1            py37hda49f71_0    conda-forge
chardet                   4.0.0            py37h03978a9_1    conda-forge
conda                     4.9.2            py37h03978a9_0    conda-forge
conda-package-handling    1.7.2            py37h6dbccfb_0    conda-forge
convertdate               2.3.2              pyhd8ed1ab_0    conda-forge
cryptography              3.4.6            py37h20c650d_0    conda-forge
curl                      7.75.0               hf1763fc_0    conda-forge
cycler                    0.10.0                     py_2    conda-forge
cython                    0.29.22          py37hf2a7229_0    conda-forge
ephem                     3.7.7.1          py37h4ab8f01_1    conda-forge
fbprophet                 0.7.1            py37h1834ac0_0    conda-forge
freetype                  2.10.4               h546665d_1    conda-forge
hdf4                      4.2.13            h0e5069d_1004    conda-forge
hdf5                      1.10.6          nompi_h5268f04_1114    conda-forge
hijri-converter           2.1.1              pyhd8ed1ab_0    conda-forge
holidays                  0.10.5.2           pyhd8ed1ab_0    conda-forge
idna                      2.10               pyh9f0ad1d_0    conda-forge
intel-openmp              2020.3             h57928b3_311    conda-forge
jpeg                      9d                   h8ffe710_0    conda-forge
kiwisolver                1.3.1            py37h8c56517_1    conda-forge
korean_lunar_calendar     0.2.1              pyh9f0ad1d_0    conda-forge
krb5                      1.17.2               hbae68bd_0    conda-forge
lcms2                     2.12                 h2a16943_0    conda-forge
libblas                   3.9.0                     8_mkl    conda-forge
libcblas                  3.9.0                     8_mkl    conda-forge
libcurl                   7.75.0               hf1763fc_0    conda-forge
liblapack                 3.9.0                     8_mkl    conda-forge
libnetcdf                 4.7.4           nompi_h3a9aa94_107    conda-forge
libpng                    1.6.37               h1d00b33_2    conda-forge
libpython                 2.0              py37h03978a9_1    conda-forge
libssh2                   1.9.0                h680486a_6    conda-forge
libtiff                   4.2.0                hc10be44_0    conda-forge
lunarcalendar             0.0.9                      py_0    conda-forge
lz4-c                     1.9.3                h8ffe710_0    conda-forge
m2w64-binutils            2.25.1                        5    conda-forge
m2w64-bzip2               1.0.6                         6    conda-forge
m2w64-crt-git             5.0.0.4636.2595836               2    conda-forge
m2w64-gcc                 5.3.0                         6    conda-forge
m2w64-gcc-ada             5.3.0                         6    conda-forge
m2w64-gcc-fortran         5.3.0                         6    conda-forge
m2w64-gcc-libgfortran     5.3.0                         6    conda-forge
m2w64-gcc-libs            5.3.0                         7    conda-forge
m2w64-gcc-libs-core       5.3.0                         7    conda-forge
m2w64-gcc-objc            5.3.0                         6    conda-forge
m2w64-gmp                 6.1.0                         2    conda-forge
m2w64-headers-git         5.0.0.4636.c0ad18a               2    conda-forge
m2w64-isl                 0.16.1                        2    conda-forge
m2w64-libiconv            1.14                          6    conda-forge
m2w64-libmangle-git       5.0.0.4509.2e5a9a2               2    conda-forge
m2w64-libwinpthread-git   5.0.0.4634.697f757               2    conda-forge
m2w64-make                4.1.2351.a80a8b8               2    conda-forge
m2w64-mpc                 1.0.3                         3    conda-forge
m2w64-mpfr                3.1.4                         4    conda-forge
m2w64-pkg-config          0.29.1                        2    conda-forge
m2w64-toolchain           5.3.0                         7    conda-forge
m2w64-toolchain_win-64    2.4.0                         0    conda-forge
m2w64-tools-git           5.0.0.4592.90b8472               2    conda-forge
m2w64-windows-default-manifest 6.4                           3    conda-forge
m2w64-winpthreads-git     5.0.0.4634.697f757               2    conda-forge
m2w64-zlib                1.2.8                        10    conda-forge
matplotlib-base           3.3.4            py37h3379fd5_0    conda-forge
menuinst                  1.4.16           py37hc8dfbb8_1    conda-forge
mkl                       2020.4             hb70f87d_311    conda-forge
msys2-conda-epoch         20160418                      1    conda-forge
netcdf4                   1.5.6           nompi_py37h4965ef1_100    conda-forge
numpy                     1.20.1           py37hd20adf4_0    conda-forge
olefile                   0.46               pyh9f0ad1d_1    conda-forge
openssl                   1.1.1j               h8ffe710_0    conda-forge
packaging                 20.9               pyh44b312d_0    conda-forge
pandas                    1.2.3            py37h08fd248_0    conda-forge
pillow                    8.1.2            py37h96663a1_0    conda-forge
pip                       21.0.1             pyhd8ed1ab_0    conda-forge
pycosat                   0.6.3           py37hcc03f2d_1006    conda-forge
pycparser                 2.20               pyh9f0ad1d_2    conda-forge
pymeeus                   0.5.10             pyhd8ed1ab_0    conda-forge
pyopenssl                 20.0.1             pyhd8ed1ab_0    conda-forge
pyparsing                 2.4.7              pyh9f0ad1d_0    conda-forge
pysocks                   1.7.1            py37h03978a9_3    conda-forge
pystan                    2.19.1.1         py37h9758500_2    conda-forge
python                    3.7.7                h81c818b_4
python-dateutil           2.8.1                      py_0    conda-forge
python_abi                3.7                     1_cp37m    conda-forge
pytz                      2021.1             pyhd8ed1ab_0    conda-forge
pywin32                   300              py37hcc03f2d_0    conda-forge
requests                  2.25.1             pyhd3deb0d_0    conda-forge
ruamel_yaml               0.15.80         py37hcc03f2d_1004    conda-forge
scipy                     1.6.1            py37h6db1a17_0    conda-forge
setuptools                49.6.0           py37h03978a9_3    conda-forge
six                       1.15.0             pyh9f0ad1d_0    conda-forge
sqlite                    3.35.2               h8ffe710_0    conda-forge
tk                        8.6.10               h8ffe710_1    conda-forge
tornado                   6.1              py37hcc03f2d_1    conda-forge
tqdm                      4.59.0             pyhd8ed1ab_0    conda-forge
urllib3                   1.26.4             pyhd8ed1ab_0    conda-forge
vc                        14.2                 hb210afc_4    conda-forge
vs2015_runtime            14.28.29325          h5e1d092_4    conda-forge
wheel                     0.36.2             pyhd3deb0d_0    conda-forge
win_inet_pton             1.1.0            py37h03978a9_2    conda-forge
wincertstore              0.2             py37h03978a9_1006    conda-forge
xarray                    0.17.0             pyhd8ed1ab_0    conda-forge
xz                        5.2.5                h62dcd97_1    conda-forge
yaml                      0.2.5                he774522_0    conda-forge
zlib                      1.2.11            h62dcd97_1010    conda-forge
zstd                      1.4.9                h6255e5f_0    conda-forge

(modeler) C:\Users\dsuser01>
```
#モデルを保存するパスを作っておきます。
モデルを保存するパスを作っておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/114ade4b-3381-4dcc-2b4c-b8176f1ae3db.png)

#ストリームの作成
公式サイトのQuickStartにあるサンプルデータの[example_wp_log_peyton_manning.csv](https://raw.githubusercontent.com/facebook/prophet/master/examples/example_wp_log_peyton_manning.csv)をダウンロードして読み込みます。

https://facebook.github.io/prophet/docs/quick_start.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/0aff8da2-2299-edd6-17bd-4f8e0278c38b.png)

以下のようなデータが入っています。日付型のdsという列と実績値のy列があります。fbprophetはモデル作成に使う列名が決められていますので、ほかのデータを使う場合はdsとyの列名でデータを用意する必要があります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d2b0836d-915e-980d-481e-9608dad26e2f.png)

拡張モデルノードでPython for Sparkを選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/49e35c42-7250-422c-d811-e2ceb4cc8697.png)

以下のfbprophetのモデリングとスコアリングのスクリプトを入力します。

```python:Pythonモデル作成シンタックス
#モデルファイルの保存パス
modelpath='c:/temp/modelpath/'
modelfile='fbprophetModel.pkl'

# Analytics Server 対話用のライブラリのインポート
import spss.pyspark.runtime
# Analytics Serverコンテキストオブジェクト定義
ascontext = spss.pyspark.runtime.getContext()

# データ読込
df = ascontext.getSparkInputData()
#print(df.take(10))
#print(df.printSchema)

#pandas変換してdsでソート
df = df.toPandas().sort_values('ds')
#print(df.tail(10))

#dsがシリアル値でうけ渡されるのでdatetimeに変換
import pandas as pd
df['ds'] = pd.to_datetime('1970/1/1') + pd.to_timedelta(df['ds'] , unit='days')
#print(df.tail(10))

#fbprophetモデル作成
from fbprophet import Prophet 
model = Prophet()
model.fit(df)

#モデルをファイルシステムに保存
import pickle
pickle.dump(model, open(modelpath+modelfile, 'wb'))
```

```python:Pythonモデルスコアリングシンタックス
#モデルファイルの保存パス
modelpath='c:/temp/modelpath/'
modelfile='fbprophetModel.pkl'

#予測期間の設定
futureperiods=365

# Analytics Server 対話用のライブラリのインポート
import spss.pyspark.runtime
from pyspark.sql.types import DoubleType, StructField 
from pyspark.sql.context import SQLContext

# Analytics Server 対話用のライブラリのインポート
import spss.pyspark.runtime
# Analytics Serverコンテキストオブジェクト定義
ascontext = spss.pyspark.runtime.getContext()

#予測値列と上側予測列、下側予測列を出力スキーマに追加
outputSchema = ascontext.getSparkInputSchema()
outputSchema.fields.append(StructField('yhat', DoubleType(), nullable=True))
outputSchema.fields.append(StructField('yhat_lower', DoubleType(), nullable=True))
outputSchema.fields.append(StructField('yhat_upper', DoubleType(), nullable=True))

ascontext.setSparkOutputSchema(outputSchema)

if not ascontext.isComputeDataModelOnly():

        #ファイルシステム上のモデルを読み込む
        import pickle
        model = pickle.load(open(modelpath+modelfile, 'rb'))
        
        #スコアリングデータの読み込み
        indf = ascontext.getSparkInputData()
        #pandas変換してdsでソート
        df = indf.toPandas().sort_values('ds')
        import pandas as pd
        df['ds'] = pd.to_datetime('1970/1/1') + pd.to_timedelta(df['ds'] , unit='days')
 
        #スコアリング
        future = model.make_future_dataframe(periods=futureperiods)
        forecast = model.predict(future)
        #インプットDataframeと外部結合をして、必要列に絞る
        forecast = pd.concat([forecast[['ds','yhat','yhat_lower','yhat_upper']],df[['y']]], axis=1)[['ds','y','yhat','yhat_lower','yhat_upper']]
 
        #dsをシリアル値でModelerが受け取るので変換
        import datetime
        forecast['ds'] = (pd.to_datetime(forecast['ds']) - pd.to_datetime('1970/1/1'))/ datetime.timedelta(days=1)
        #print(forecast.tail(10))

        #Sparkコンテキストの取得
        sc = ascontext.getSparkContext()
        #データの出力
        sqlCtx = SQLContext(sc)
        outdf = sqlCtx.createDataFrame(forecast,schema=outputSchema)

        # return the output DataFrame as the result
        ascontext.setSparkOutputData(outdf)
```

実行するとモデルナゲットができるので、テーブルノードを繋ぎます。
テーブルノードを実行するとｙhatに予測値、yhat_lower、yhat_upperに下側予測、上側予測が出力されます。
このデータでは2016-01-21以降は将来の予測になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/2a0ed9c4-03d3-4eed-baeb-6080cb64d5d0.png)


時系列グラフノードを接続し、以下の設定で実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/28aef3ab-a092-d4d7-4fbc-02cee9982520.png)

以下のように予実の可視化が可能です。
水色のポイントが実測値でそれ以外が予測値です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/19150210-7af5-6789-4809-7d5d1b489bfb.png)

# モデリングスクリプトの解説
最初にモデルの保存パスを定義しています。
本来はascontext.setModelContentFromStringでモデルナゲット内にモデルが保存できると思うのですが、どうしても失敗するために、ファイルシステム内に保存しています。
スコアリング時にはこのファイルが必要になります。特にModeler ServerやCADSと組み合わせて実行する場合など、別のマシンでスコアリングを行う場合には、同じ場所にモデルファイルがないと動きませんので注意が必要です。


```python:Pythonモデル作成シンタックス-モデルの保存パスを定義
#モデルファイルの保存パス
modelpath='c:/temp/modelpath/'
modelfile='fbprophetModel.pkl'
```
以下でModelerとのやり取りを行うためのコンテキストオブジェクトを作っています。


```python:Pythonモデル作成シンタックス-AnalyticsServerコンテキストオブジェクト定義
# Analytics Server 対話用のライブラリのインポート
import spss.pyspark.runtime
# Analytics Serverコンテキストオブジェクト定義
ascontext = spss.pyspark.runtime.getContext()
```


以下でデータを読み込んでいます。
Modelerから取得されるデータフレームはSpark DataFrameなので、sdf.toPandas()
でpandasのDataFrameにして取り扱いやすくしています。
また、SparkDataFrameは順序が保証されないようなので、日付を表すds列でソートします。

```python:Pythonモデル作成シンタックス-データ読込
# データ読込
sdf = ascontext.getSparkInputData()
#pandas変換してdsでソート
df = sdf.toPandas().sort_values('ds')
```

日付型のdsがシリアル値で読み込まれるので、datetime型に変換します。

```python:datetime型変換
#dsがシリアル値でうけ渡されるのでdatetimeに変換
import pandas as pd
df['ds'] = pd.to_datetime('1970/1/1') + pd.to_timedelta(df['ds'] , unit='days')
```

以下でfbprophetのモデルを作っています。
fbprophetには様々なパラメーターがありますが、ここではデフォルトで動かしています。

```python:Pythonモデル作成シンタックス-モデル作成
#fbprophetモデル作成
from fbprophet import Prophet 
model = Prophet()
model.fit(df)
```

最後に、生成されたモデルをpickleを使ってシリアライズして、スクリプトの先頭で定義したmodelpath+modelfileに保存しています。

```python:Pythonモデル作成シンタックス-モデルをファイルシステムに保存
#モデルをファイルシステムに保存
import pickle
pickle.dump(model, open(modelpath+modelfile, 'wb'))
```
# スコアリングスクリプトの解説

モデリングスクリプトで指定したものと同じモデルファイル保存パスを指定します。

```python:Pythonモデルスコアリングシンタックス-モデルファイル保存パス指定
#モデルファイルの保存パス
modelpath='c:/temp/modelpath/'
modelfile='fbprophetModel.pkl'
```

以下ではスコアリング時の将来予測期間を指定しています。ここでは365日を指定しています。

```python:Pythonモデルスコアリングシンタックス-予測期間の設定
#予測期間の設定
futureperiods=365
```

モデリングスクリプトでも行ったように、Modelerとのやり取りを行うためのコンテキストオブジェクトを作っています。
モデリングスクリプトに加えて、ここでは新しいSparkDataFrameを作成するためにSQLContextを、また新しい列をつくるためにDoubleType, StructFieldもインポートしています。

```python:Pythonモデルスコアリングシンタックス-AnalyticsServerコンテキストオブジェクト定義
# Analytics Server 対話用のライブラリのインポート
import spss.pyspark.runtime
from pyspark.sql.types import DoubleType, StructField 
from pyspark.sql.context import SQLContext

# Analytics Serverコンテキストオブジェクト定義
ascontext = spss.pyspark.runtime.getContext()
```
以下で入力データのスキーマに予測値列と上側予測列、下側予測列を追加して、出力スキーマとしています。データ型はDoubleType()を指定しています。

```python:Pythonモデルスコアリングシンタックス-予測値列と上側予測列、下側予測列を出力スキーマに追加
#予測値列と上側予測列、下側予測列を出力スキーマに追加
outputSchema = ascontext.getSparkInputSchema()
outputSchema.fields.append(StructField('yhat', DoubleType(), nullable=True))
outputSchema.fields.append(StructField('yhat_lower', DoubleType(), nullable=True))
outputSchema.fields.append(StructField('yhat_upper', DoubleType(), nullable=True))

ascontext.setSparkOutputSchema(outputSchema)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/633e1fed-f281-7210-9d52-c380d467b8b3.png)

以下は実際にスコアリングを行う場合に以降のスクリプトを実行するという条件になります。
ここは少しややこしいところです。
ここまでのスクリプトはsetSparkOutputSchemaで出力スキーマを定義するものでした。モデルナゲットの後ろにノードを追加する場合、DataModelをComputeしてスキーマを定義することは必要ですが、実際にスコアリングしたデータは必要ありません。
ですので無駄なスコアリング処理をしないために、「スコアリングデータがいる場合にのみ」（Not isComputeDataModelOnly）、スコアリングをするスクリプトを実行するという条件を入れています。
マニュアルに[DataModelOnly モード](https://www.ibm.com/support/knowledgecenter/ja/SS3RA7_18.2.2/modeler_r_nodes_ddita/clementine/r_pyspark_api.html)という解説があります。

```python:Pythonモデルスコアリングシンタックス-スコアリング実行判定
if not ascontext.isComputeDataModelOnly():
```

以下で、スクリプトの先頭で定義したmodelpath+modelfileからモデルをファイルシステムから読み込みます。

```python:Pythonモデルスコアリングシンタックス-モデルをファイルシステムから読み込む
        #ファイルシステム上のモデルを読み込む
        import pickle
        model = pickle.load(open(modelpath+modelfile, 'rb'))
```

以下で入力データを読み込んでPandasのDataFrameに変換しています。モデリングと同様にds列でソートをかけ、dsをシリアル値からdatetime型に変換しています。

```python:Pythonモデルスコアリングシンタックス-スコアリングデータの読み込み
        #スコアリングデータの読み込み
        indf = ascontext.getSparkInputData()
        #pandas変換してdsでソート
        df = indf.toPandas().sort_values('ds')
        import pandas as pd
        df['ds'] = pd.to_datetime('1970/1/1') + pd.to_timedelta(df['ds'] , unit='days')
```

以下で、スコアリングをしています。yhatは予測値を得ています。yhat_upper、yhat_lowerは上側予測列、下側予測列を得ています。
スコアリング結果のdataframeであるforecastには実績値yは入らないので、インプットデータと結合を行っています。
なお、forecastにはtrendなど別のスコアリング値もありますので、必要に応じて取り出してください。

```python:Pythonモデルスコアリングシンタックス-スコアリング
        #スコアリング
        future = model.make_future_dataframe(periods=futureperiods)
        forecast = model.predict(future)
        #インプットDataframeと外部結合をして、必要列に絞る
        forecast = pd.concat([forecast[['ds','yhat','yhat_lower','yhat_upper']],df[['y']]], axis=1)[['ds','y','yhat','yhat_lower','yhat_upper']]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/44b20bb2-876e-329e-b926-bcd0267a6c71.png)


Modelerに返すために日付型データのdsをシリアル変換しています。

```python:Pythonモデルスコアリングシンタックス-シリアル値変換
        #dsをシリアル値でModelerが受け取るので変換
        import datetime
        forecast['ds'] = (pd.to_datetime(forecast['ds']) - pd.to_datetime('1970/1/1'))/ datetime.timedelta(days=1)
```

以下で予測値列と予測列、下側予測列を追加したPandas DataFrameであるdfを、sqlCtx.createDataFrame(df,schema=outputSchema)でSparkDataFrameに変換しなおして、setSparkOutputDataでModelerに返しています。

```python:Pythonモデルスコアリングシンタックス-データ出力
        #Sparkコンテキストの取得
        sc = ascontext.getSparkContext()
        #データの出力
        sqlCtx = SQLContext(sc)
        outdf = sqlCtx.createDataFrame(forecast,schema=outputSchema)

        # return the output DataFrame as the result
        ascontext.setSparkOutputData(outdf)
```

# 参考

https://qiita.com/kawada2017/items/04f525727725d199723c

https://qiita.com/kawada2017/items/b75cd4191ba90b91983b

fbprophet Quick Start

https://facebook.github.io/prophet/docs/quick_start.html

Python for Spark を使用したスクリプト

https://www.ibm.com/support/knowledgecenter/ja/SS3RA7_18.2.2/modeler_r_nodes_ddita/clementine/r_pyspark_api.html