{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Example of using feature importances calculated by ExtraTreesClassifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "require 'matplotlib/iruby'\n",
    "Matplotlib::IRuby.activate\n",
    "plt = Matplotlib::Pyplot\n",
    "nil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "require 'pycall/import'\n",
    "include PyCall::Import\n",
    "pyimport 'numpy', as: 'np'\n",
    "pyfrom 'sklearn.datasets', import: :fetch_olivetti_faces\n",
    "pyfrom 'sklearn.datasets', import: :make_classification\n",
    "pyfrom 'sklearn.ensemble', import: :ExtraTreesClassifier\n",
    "nil"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (1) Feature importances with forests of trees\n",
    "\n",
    "This section is based on the following content of the reference of scikit-learn:\n",
    "\n",
    "- http://scikit-learn.org/stable/auto_examples/ensemble/plot_forest_importances.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Feature ranking:\n",
      "1. feature 1 (0.295902)\n",
      "2. feature 2 (0.208351)\n",
      "3. feature 0 (0.177632)\n",
      "4. feature 3 (0.047121)\n",
      "5. feature 6 (0.046303)\n",
      "6. feature 8 (0.046013)\n",
      "7. feature 7 (0.045575)\n",
      "8. feature 4 (0.044614)\n",
      "9. feature 9 (0.044577)\n",
      "10. feature 5 (0.043912)\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 18780 characters]",
      "text/plain": [
       "<matplotlib.figure.Figure object at 0x114a7a0b8>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "(-1, 10)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Build a classification task using 3 informative features\n",
    "x, y = *make_classification(\n",
    "  n_samples: 1000,\n",
    "  n_features: 10,\n",
    "  n_informative: 3,\n",
    "  n_redundant: 0,\n",
    "  n_repeated: 0,\n",
    "  n_classes: 2,\n",
    "  random_state: 0,\n",
    "  shuffle: false\n",
    ")\n",
    "\n",
    "# Build a forest and compute the feature importances\n",
    "forest = ExtraTreesClassifier.new(n_estimators: 250, random_state: 0)\n",
    "\n",
    "forest.fit(x, y)\n",
    "importances = forest.feature_importances_\n",
    "std = np.std(forest.estimators_.map {|tree| tree.feature_importances_ }, axis: 0)\n",
    "indices = np.argsort(importances)[(-1..0).step(-1)]\n",
    "\n",
    "# Print the feature ranking\n",
    "puts \"Feature ranking:\"\n",
    "\n",
    "x.shape[1].times do |f|\n",
    "  puts \"%d. feature %d (%f)\" % [f + 1, indices[f].to_i, importances[indices[f]]]\n",
    "end\n",
    "\n",
    "# Plot the feature importances of the forest\n",
    "plt.figure()\n",
    "plt.title(\"Feature importances\")\n",
    "plt.bar([*0...x.shape[1]], importances[indices],\n",
    "        color: \"r\", yerr: std[indices], align: \"center\")\n",
    "plt.xticks([*0...x.shape[1]], indices)\n",
    "plt.xlim([-1, x.shape[1]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (2) Pixel importances with a parallel forest of trees\n",
    "\n",
    "This example is based on the following content of the reference of scikit-learn:\n",
    "\n",
    "- http://scikit-learn.org/stable/auto_examples/ensemble/plot_forest_importances_faces.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fitting ExtraTreesClassifier on faces data with 1 cores...\n",
      "done in 1.253s\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 30940 characters]",
      "text/plain": [
       "<matplotlib.figure.Figure object at 0x116436f98>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text object at 0x1164456a0>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Number of cores to use to perform parallel fitting of the forest model\n",
    "n_jobs = 1\n",
    "\n",
    "# Load the faces datasets\n",
    "data = fetch_olivetti_faces()\n",
    "x = data.images.reshape([PyCall.len(data.images), -1])\n",
    "y = data.target\n",
    "\n",
    "mask = y < 5  # Limit to 5 classes\n",
    "x = x[mask]\n",
    "y = y[mask]\n",
    "\n",
    "# Build a forest and compute the pixel importances\n",
    "puts \"Fitting ExtraTreesClassifier on faces data with #{n_jobs} cores...\"\n",
    "t0 = Time.now\n",
    "forest = ExtraTreesClassifier.new(\n",
    "  n_estimators: 1_000,\n",
    "  max_features: 128,\n",
    "  n_jobs: n_jobs,\n",
    "  random_state: 0\n",
    ")\n",
    "\n",
    "forest = forest.fit(x, y)\n",
    "puts \"done in %0.3fs\" % (Time.now - t0)\n",
    "importances = forest.feature_importances_\n",
    "importances = importances.reshape(data.images[0].shape)\n",
    "\n",
    "# Plot pixel importances\n",
    "plt.matshow(importances, cmap: plt.cm.__dict__[:hot])\n",
    "plt.title(\"Pixel importances with forests of trees\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.4.1",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.4.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
