Skip to content

Instantly share code, notes, and snippets.

@sshojiro
Created August 30, 2020 14:47
Show Gist options
  • Save sshojiro/c1142f5964f5229570c74bea9d30f3a9 to your computer and use it in GitHub Desktop.
Save sshojiro/c1142f5964f5229570c74bea9d30f3a9 to your computer and use it in GitHub Desktop.
debutanizer_moving-window.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "debutanizer_moving-window.ipynb",
"provenance": [],
"collapsed_sections": [],
"authorship_tag": "ABX9TyNwY98kyEJyEXVJ86boktsi",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/sshojiro/c1142f5964f5229570c74bea9d30f3a9/debutanizer_moving-window.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "rqbJJdZuu3Cq",
"colab_type": "text"
},
"source": [
"# Soft-sensor\n",
"\n",
"- **[This time]** Just-in-Time model\n",
"- [Coming soon] Moving window\n",
"- [Coming soon] Time difference"
]
},
{
"cell_type": "code",
"metadata": {
"id": "WzRhHmPIuwlg",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 305
},
"outputId": "428f78d3-3029-41da-d3d2-50ac46f96bef"
},
"source": [
"!wget --no-check-certificate https://home.isr.uc.pt/~rui/publications/debutanizer_fortuna_dataset.zip\n",
"!unzip debutanizer_fortuna_dataset.zip"
],
"execution_count": 1,
"outputs": [
{
"output_type": "stream",
"text": [
"--2020-08-30 14:26:30-- https://home.isr.uc.pt/~rui/publications/debutanizer_fortuna_dataset.zip\n",
"Resolving home.isr.uc.pt (home.isr.uc.pt)... 193.136.230.49\n",
"Connecting to home.isr.uc.pt (home.isr.uc.pt)|193.136.230.49|:443... connected.\n",
"WARNING: cannot verify home.isr.uc.pt's certificate, issued by ‘CN=TERENA SSL CA 3,O=TERENA,L=Amsterdam,ST=Noord-Holland,C=NL’:\n",
" Unable to locally verify the issuer's authority.\n",
"HTTP request sent, awaiting response... 200 OK\n",
"Length: 140406 (137K) [application/zip]\n",
"Saving to: ‘debutanizer_fortuna_dataset.zip.1’\n",
"\n",
"debutanizer_fortuna 100%[===================>] 137.12K 707KB/s in 0.2s \n",
"\n",
"2020-08-30 14:26:31 (707 KB/s) - ‘debutanizer_fortuna_dataset.zip.1’ saved [140406/140406]\n",
"\n",
"Archive: debutanizer_fortuna_dataset.zip\n",
"replace debutanizer.mat? [y]es, [n]o, [A]ll, [N]one, [r]ename: y\n",
" inflating: debutanizer.mat \n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "XinE7N0HvCM2",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"outputId": "557ee9d9-6dc1-4d2d-cde5-4097274075c2"
},
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib as mpl\n",
"from mpl_toolkits.mplot3d import Axes3D\n",
"from sklearn.base import BaseEstimator, TransformerMixin\n",
"from sklearn.pipeline import make_pipeline\n",
"from sklearn.decomposition import PCA\n",
"from sklearn.preprocessing import StandardScaler\n",
"\n",
"import sklearn\n",
"print(sklearn.__version__)\n",
"from sklearn.model_selection import TimeSeriesSplit\n",
"from scipy.spatial.distance import cdist\n",
"from sklearn.cross_decomposition import PLSRegression\n",
"from sklearn.model_selection import GridSearchCV\n",
"from sklearn.ensemble import RandomForestRegressor\n",
"from sklearn import metrics\n",
"from warnings import filterwarnings\n",
"filterwarnings('ignore')\n",
"\n",
"from scipy.io import loadmat\n",
"debutanizer = loadmat('debutanizer.mat')"
],
"execution_count": 2,
"outputs": [
{
"output_type": "stream",
"text": [
"0.22.2.post1\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "ZcyEyRZkvUZr",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 141
},
"outputId": "90d8e02a-6c4e-4958-f938-d953c0536fa2"
},
"source": [
"INOUT = [s for s in debutanizer.keys() if not s.startswith('_')]\n",
"INPUT = INOUT[:-1]\n",
"OUTPUT = INOUT[-1]\n",
"\n",
"df = pd.DataFrame([debutanizer[item].reshape(-1,)for item in INOUT]).T\n",
"df.rename(columns={k:v for k,v in enumerate(INOUT)}, inplace=True)\n",
"df.head(3)"
],
"execution_count": 3,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>u1</th>\n",
" <th>u2</th>\n",
" <th>u3</th>\n",
" <th>u4</th>\n",
" <th>u5</th>\n",
" <th>u6</th>\n",
" <th>u7</th>\n",
" <th>y</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0.268900</td>\n",
" <td>0.650894</td>\n",
" <td>0.832742</td>\n",
" <td>0.58342</td>\n",
" <td>0.784759</td>\n",
" <td>0.843079</td>\n",
" <td>0.822079</td>\n",
" <td>0.180295</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.268483</td>\n",
" <td>0.650140</td>\n",
" <td>0.852153</td>\n",
" <td>0.57751</td>\n",
" <td>0.776487</td>\n",
" <td>0.838605</td>\n",
" <td>0.822079</td>\n",
" <td>0.177124</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0.267967</td>\n",
" <td>0.659657</td>\n",
" <td>0.823618</td>\n",
" <td>0.57160</td>\n",
" <td>0.764546</td>\n",
" <td>0.807879</td>\n",
" <td>0.786246</td>\n",
" <td>0.173618</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" u1 u2 u3 ... u6 u7 y\n",
"0 0.268900 0.650894 0.832742 ... 0.843079 0.822079 0.180295\n",
"1 0.268483 0.650140 0.852153 ... 0.838605 0.822079 0.177124\n",
"2 0.267967 0.659657 0.823618 ... 0.807879 0.786246 0.173618\n",
"\n",
"[3 rows x 8 columns]"
]
},
"metadata": {
"tags": []
},
"execution_count": 3
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "6ufLY_rGyLyO",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 248
},
"outputId": "4bba21c1-ab67-4f86-cfc7-dd3958baa530"
},
"source": [
"decomposer = make_pipeline(StandardScaler(), PCA(3))\n",
"\n",
"X_all = df[INPUT]\n",
"T_all = decomposer.fit_transform(X_all)\n",
"y_all = df[OUTPUT]\n",
"fig = plt.figure()\n",
"ax = fig.add_subplot(111, projection='3d')\n",
"ax.plot(*T_all.T, '.')\n",
"plt.show()"
],
"execution_count": 4,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MJ5fZHijwouz",
"colab_type": "text"
},
"source": [
"## Just-in-Time Implementation\n",
"\n",
"JIT model is implemented on the scikit-learn like interface."
]
},
{
"cell_type": "code",
"metadata": {
"id": "RPBBe4e5zL2R",
"colab_type": "code",
"colab": {}
},
"source": [
"class _Sampler(BaseEstimator, TransformerMixin):\n",
" def __init__(self):\n",
" pass\n",
" def fit(self, x, y=None):\n",
" pass\n",
" def transform(self, X, y):\n",
" return X[self.idx,:], y[self.idx,:]\n",
"\n",
"class JustInTime(_Sampler):\n",
" def __init__(self, estimator_, n_samples=50, func=lambda u, v: np.sqrt(((u-v)**2).sum())):\n",
" self.estimator_ = estimator_\n",
" self.func = func\n",
" self.n_samples = n_samples\n",
" def fit(self, X, y=None):\n",
" self.x_pool = X.copy()\n",
" self.y_pool = y.copy()\n",
" self.n_dims = self.x_pool.shape[1]\n",
" if len(self.y_pool.shape) == 1:\n",
" self.y_pool = self.y_pool.reshape(-1,1)\n",
" self.n_ydims = self.y_pool.shape[1]\n",
" return self\n",
" def transform(self, X):\n",
" \"\"\"\n",
" Pick optimal samples according to X\n",
" \"\"\"\n",
" n_samples = X.shape[0]\n",
" X_sampled = np.zeros((n_samples, self.n_samples, self.n_dims))\n",
" y_sampled = np.zeros((n_samples, self.n_samples, self.n_ydims))\n",
" for index, x_q in enumerate(X):\n",
" dist = cdist(x_q.reshape(-1, self.n_dims), self.x_pool, \n",
" lambda u,v:self.func(u,v))\n",
" ix = np.argsort(dist)[:,:self.n_samples]\n",
"\n",
" X_sampled[index, :, :] = self.x_pool[ix,:]\n",
" y_sampled[index, :, :] = self.y_pool[ix,:]\n",
" return X_sampled, y_sampled\n",
" def predict(self, X):\n",
" Xsub, ysub = self.transform(X)\n",
" y_est = np.zeros((ysub.shape[0],ysub.shape[-1]))\n",
" for jx in range(X.shape[0]):\n",
" y_est[jx,:] = self.estimator_.fit(Xsub[jx,:,:], ysub[jx,:,:]).predict(X[jx,:].reshape(1,-1))\n",
" return y_est\n"
],
"execution_count": 5,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "8CpwfTQJ1SBp",
"colab_type": "text"
},
"source": [
"### TimeSeriesSplit"
]
},
{
"cell_type": "code",
"metadata": {
"id": "FOh0GrEjFdvI",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 269
},
"outputId": "ef9df9e4-94cd-4418-e8e6-effe571fd44b"
},
"source": [
"%%time\n",
"pls = GridSearchCV(PLSRegression(), {'n_components':np.arange(1,8)})\n",
"tscv = TimeSeriesSplit(n_splits=5)\n",
"X = df[INPUT]\n",
"y = df[OUTPUT]\n",
"\n",
"for mtype, regressor in zip(['pls', 'rf'],\n",
" [pls, RandomForestRegressor(n_estimators=300)]):\n",
" model = JustInTime(regressor)\n",
" scores = np.zeros((tscv.n_splits,))\n",
" count = 0\n",
" for train_index, test_index in tscv.split(X):\n",
" print(\"TRAIN:\", train_index.shape[0], \n",
" \"TEST:\", test_index.shape[0])\n",
" X_train, X_test = X.iloc[train_index], X.iloc[test_index]\n",
" y_train, y_test = y.iloc[train_index], y.iloc[test_index]\n",
" model.fit(X_train.values, y_train.values)\n",
" y_cv = model.predict(X_test.values)\n",
" scores[count] = metrics.r2_score(y_test.values, y_cv)\n",
" count += 1\n",
" print(mtype, 'R_{CV}^2', '%.4f'%scores.mean())"
],
"execution_count": 6,
"outputs": [
{
"output_type": "stream",
"text": [
"TRAIN: 399 TEST: 399\n",
"TRAIN: 798 TEST: 399\n",
"TRAIN: 1197 TEST: 399\n",
"TRAIN: 1596 TEST: 399\n",
"TRAIN: 1995 TEST: 399\n",
"pls R_{CV}^2 -2.2894\n",
"TRAIN: 399 TEST: 399\n",
"TRAIN: 798 TEST: 399\n",
"TRAIN: 1197 TEST: 399\n",
"TRAIN: 1596 TEST: 399\n",
"TRAIN: 1995 TEST: 399\n",
"rf R_{CV}^2 -1.3338\n",
"CPU times: user 14min 47s, sys: 3.37 s, total: 14min 50s\n",
"Wall time: 14min 51s\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dFOeVDWC1LLO",
"colab_type": "text"
},
"source": [
"### Short Summary\n",
"\n",
"1. JIT was implemented.\n",
"1. JIT-random forest outperformed JIT-PLS little in terms of $R_{\\rm CV}^2$; but still they were below zero. \n",
"1. The debutanizer dataset is a difficult one to predict."
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment