{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# TSFRESH Human Activity Recognition Example\n",
    "This example show shows how to use [tsfresh](https://tsfresh.readthedocs.io/) to exctract useful features from multiple timeseries and use them to improve classification performance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/ds806/anaconda3/lib/python3.6/site-packages/statsmodels/compat/pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.\n",
      "  from pandas.core import datetools\n"
     ]
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pylab as plt\n",
    "from tsfresh.examples.har_dataset import download_har_dataset, load_har_dataset, load_har_classes\n",
    "import seaborn as sns\n",
    "from tsfresh import extract_features, extract_relevant_features, select_features\n",
    "from tsfresh.utilities.dataframe_functions import impute\n",
    "from tsfresh.feature_extraction import ComprehensiveFCParameters\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import classification_report\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "import logging"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# We set the logger to Error level\n",
    "# This is not recommend for normal use as you can oversee important Warning messages\n",
    "logging.basicConfig(level=logging.ERROR)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load and visualize data\n",
    "The dataset consists of timeseries for 7352 accelerometer readings. Each reading represents an accelerometer reading for 2.56 sec at 50hz (for a total of 128 samples per reading). Furthermore, each reading corresponds one of six activities (walking, walking upstairs, walking downstairs, sitting, standing and laying)\n",
    "\n",
    "For more information, or to fetch dataset, go to https://archive.ics.uci.edu/ml/datasets/Human+Activity+Recognition+Using+Smartphones"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# fetch dataset from uci\n",
    "download_har_dataset()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(7352, 128)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = load_har_dataset()\n",
    "df.head()\n",
    "df.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/ds806/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:2: DeprecationWarning: \n",
      ".ix is deprecated. Please use\n",
      ".loc for label based indexing or\n",
      ".iloc for positional indexing\n",
      "\n",
      "See the documentation here:\n",
      "http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated\n",
      "  \n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f024e6b51d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.title('accelerometer reading')\n",
    "plt.plot(df.ix[0,:])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Extract Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "extraction_settings = ComprehensiveFCParameters()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>0</th>\n",
       "      <th>1</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.000181</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.010139</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.009276</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.005066</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.010810</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          0  1\n",
       "0  0.000181  0\n",
       "1  0.010139  0\n",
       "2  0.009276  0\n",
       "3  0.005066  0\n",
       "4  0.010810  0"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# rearrange first 500 sensor readings column-wise, not row-wise\n",
    "\n",
    "N = 500\n",
    "master_df = pd.DataFrame({0: df[:N].values.flatten(),\n",
    "                          1: np.arange(N).repeat(df.shape[1])})\n",
    "master_df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Feature Extraction: 100%|██████████| 56/56 [00:11<00:00,  5.03it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.75 s, sys: 446 ms, total: 2.2 s\n",
      "Wall time: 13.3 s\n"
     ]
    }
   ],
   "source": [
    "%time X = extract_features(master_df, column_id=1, impute_function=impute, default_fc_parameters=extraction_settings);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(500, 794)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Number of extracted features: 794.'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"Number of extracted features: {}.\".format(X.shape[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Train and evaluate classifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(500,)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = load_har_classes()[:N]\n",
    "y.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             precision    recall  f1-score   support\n",
      "\n",
      "          1       0.88      1.00      0.94        22\n",
      "          2       1.00      0.89      0.94         9\n",
      "          3       1.00      0.80      0.89        15\n",
      "          4       0.41      0.37      0.39        19\n",
      "          5       0.36      0.47      0.41        17\n",
      "          6       0.44      0.39      0.41        18\n",
      "\n",
      "avg / total       0.65      0.64      0.64       100\n",
      "\n"
     ]
    }
   ],
   "source": [
    "cl = DecisionTreeClassifier()\n",
    "cl.fit(X_train, y_train)\n",
    "print(classification_report(y_test, cl.predict(X_test)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Multiclass feature selection"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In total our feature matrix contains 222 features. \n",
    "We can try to select a subset of features with the select_features method of tsfresh. \n",
    "\n",
    "However it only works for binary classification or regression tasks. \n",
    "\n",
    "For a 6 label multi classification we split the selection problem into 6 binary one-versus all classification problems. For each of them we can do a binary classification feature selection:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of relevant features for class 5: 215/794\n",
      "Number of relevant features for class 4: 205/794\n",
      "Number of relevant features for class 6: 191/794\n",
      "Number of relevant features for class 1: 217/794\n",
      "Number of relevant features for class 3: 213/794\n",
      "Number of relevant features for class 2: 161/794\n"
     ]
    }
   ],
   "source": [
    "relevant_features = set()\n",
    "\n",
    "for label in y.unique():\n",
    "    y_train_binary = y_train == label\n",
    "    X_train_filtered = select_features(X_train, y_train_binary)\n",
    "    print(\"Number of relevant features for class {}: {}/{}\".format(label, X_train_filtered.shape[1], X_train.shape[1]))\n",
    "    relevant_features = relevant_features.union(set(X_train_filtered.columns))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "263"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(relevant_features)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "we keep only those features that we selected above, for both the train and test set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "X_train_filtered = X_train[list(relevant_features)]\n",
    "X_test_filtered = X_test[list(relevant_features)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((400, 263), (100, 263))"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train_filtered.shape, X_test_filtered.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "so, we reduced the number of used features from 794 to 263"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             precision    recall  f1-score   support\n",
      "\n",
      "          1       0.88      1.00      0.94        22\n",
      "          2       1.00      1.00      1.00         9\n",
      "          3       1.00      0.80      0.89        15\n",
      "          4       0.47      0.47      0.47        19\n",
      "          5       0.43      0.53      0.47        17\n",
      "          6       0.57      0.44      0.50        18\n",
      "\n",
      "avg / total       0.70      0.69      0.69       100\n",
      "\n"
     ]
    }
   ],
   "source": [
    "cl = DecisionTreeClassifier()\n",
    "cl.fit(X_train_filtered, y_train)\n",
    "print(classification_report(y_test, cl.predict(X_test_filtered)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It worked! The precision improved by removing irrelevant features."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Compare against naive classification accuracy\n",
    "By extracting using time-series features (as opposed to using raw data points), we can meaningfully increase classification accuracy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(500, 128)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_1 = df.ix[:N-1,:]\n",
    "X_1.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "X_train, X_test, y_train, y_test = train_test_split(X_1, y, test_size=.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             precision    recall  f1-score   support\n",
      "\n",
      "          1       0.67      0.62      0.64        26\n",
      "          2       0.79      0.58      0.67        19\n",
      "          3       0.50      0.67      0.57        12\n",
      "          4       0.29      0.42      0.34        12\n",
      "          5       0.40      0.40      0.40        15\n",
      "          6       0.36      0.31      0.33        16\n",
      "\n",
      "avg / total       0.54      0.51      0.52       100\n",
      "\n"
     ]
    }
   ],
   "source": [
    "cl = DecisionTreeClassifier()\n",
    "cl.fit(X_train, y_train)\n",
    "print(classification_report(y_test, cl.predict(X_test)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So, both our unfiltered and filtered feature based classificators are able to beat the model on the raw time series values "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}