{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook created based on the following notebooks:\n",
    "\n",
    "- http://scikit-learn.org/stable/auto_examples/classification/plot_classifier_comparison.html\n",
    "- https://github.com/cstjean/ScikitLearn.jl/blob/master/examples/Classifier_Comparison.ipynb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "require 'matplotlib/iruby'\n",
    "Matplotlib::IRuby.activate\n",
    "plt = Matplotlib::Pyplot\n",
    "mplc = Matplotlib.colors\n",
    "\n",
    "nil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "require 'pycall/import'\n",
    "include PyCall::Import\n",
    "\n",
    "pyimport 'numpy', as: :np\n",
    "pyfrom 'sklearn.model_selection', import: :train_test_split\n",
    "pyfrom 'sklearn.preprocessing', import: :StandardScaler\n",
    "pyfrom 'sklearn.datasets', import: %i(make_moons make_circles make_classification)\n",
    "pyfrom 'sklearn.neighbors', import: :KNeighborsClassifier\n",
    "pyfrom 'sklearn.svm', import: :SVC\n",
    "pyfrom 'sklearn.tree', import: :DecisionTreeClassifier\n",
    "pyfrom 'sklearn.ensemble', import: %i(RandomForestClassifier AdaBoostClassifier)\n",
    "pyfrom 'sklearn.naive_bayes', import: :GaussianNB\n",
    "pyfrom 'sklearn.discriminant_analysis', import: %i(LinearDiscriminantAnalysis QuadraticDiscriminantAnalysis)\n",
    "\n",
    "nil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "h = 0.02  # step size in the mesh\n",
    "\n",
    "names = [\n",
    "  'Nearest Neighbors',\n",
    "  'Linear SVM',\n",
    "  'RBF SVM',\n",
    "  'Decision Tree',\n",
    "  'Random Forest',\n",
    "  'AdaBoost',\n",
    "  'Naive Bayes',\n",
    "  'Linear Discriminant Analysis',\n",
    "  'Quadratic Discriminant Analysis'\n",
    "]\n",
    "\n",
    "classifiers = [\n",
    "  KNeighborsClassifier.new(3),\n",
    "  SVC.new(kernel: 'linear', C: 0.025),\n",
    "  SVC.new(gamma: 2, C: 1),\n",
    "  DecisionTreeClassifier.new(max_depth: 5),\n",
    "  RandomForestClassifier.new(max_depth: 5, n_estimators: 10, max_features: 1),\n",
    "  AdaBoostClassifier.new,\n",
    "  GaussianNB.new,\n",
    "  LinearDiscriminantAnalysis.new,\n",
    "  QuadraticDiscriminantAnalysis.new\n",
    "]\n",
    "\n",
    "x, y = *make_classification(\n",
    "  n_features: 2,\n",
    "  n_redundant: 0,\n",
    "  n_informative: 2,\n",
    "  random_state: 1,\n",
    "  n_clusters_per_class: 1\n",
    ")\n",
    "\n",
    "np.random.seed(42)\n",
    "x += 2 * np.random.random_sample(x.shape)\n",
    "linearly_separable = [x, y]\n",
    "\n",
    "datasets = [\n",
    "  make_moons(noise: 0.3, random_state: 0),\n",
    "  make_circles(noise: 0.2, factor: 0.5, random_state: 1),\n",
    "  linearly_separable\n",
    "]\n",
    "\n",
    "nil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 978288 characters]",
      "text/plain": [
       "<matplotlib.figure.Figure object at 0x1122c4710>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fig = plt.figure(figsize: [27, 9])\n",
    "i = 1\n",
    "all = 0..-1\n",
    "\n",
    "# iterate over datasets\n",
    "datasets.each do |ds|\n",
    "  # preprocess dataset, split into training and test part\n",
    "  x, y = *ds\n",
    "  x = StandardScaler.new.fit_transform(x)\n",
    "  x_train, x_test, y_train, y_test = *train_test_split(x, y, test_size: 0.4)\n",
    "\n",
    "  x_min, x_max = np.min(x[all, 0]) - 0.5, np.max(x[all, 0]) + 0.5\n",
    "  y_min, y_max = np.min(x[all, 1]) - 0.5, np.max(x[all, 1]) + 0.5\n",
    "\n",
    "  xx, yy = np.meshgrid(\n",
    "    np.linspace(x_min, x_max, ((x_max - x_min)/h).round),\n",
    "    np.linspace(y_min, y_max, ((y_max - y_min)/h).round),\n",
    "  )\n",
    "  mesh_points = np.dstack([xx.ravel, yy.ravel])[0, all, all]\n",
    "\n",
    "  # just plot the dataset first\n",
    "  cm = plt.cm.__dict__[:RdBu]\n",
    "  cm_bright = mplc.ListedColormap.new([\"#FF0000\", \"#0000FF\"])\n",
    "  ax = plt.subplot(datasets.length, classifiers.length + 1, i)\n",
    "  # plot the training points\n",
    "  ax.scatter(x_train[all, 0], x_train[all, 1], c: y_train, cmap: cm_bright)\n",
    "  # and testing points\n",
    "  ax.scatter(x_test[all, 0], x_test[all, 1], c: y_test, cmap: cm_bright, alpha: 0.6)\n",
    "\n",
    "  ax.set_xlim(np.min(xx), np.max(xx))\n",
    "  ax.set_ylim(np.min(yy), np.max(yy))\n",
    "  ax.set_xticks([])\n",
    "  ax.set_yticks([])\n",
    "  i += 1\n",
    "\n",
    "  # iterate over classifiers\n",
    "  names.zip(classifiers).each do |name, clf|\n",
    "    ax = plt.subplot(datasets.length, classifiers.length + 1, i)\n",
    "    clf.fit(x_train, y_train)\n",
    "    scor = clf.score(x_test, y_test)\n",
    "\n",
    "    # Plot the decision boundary.  For that, we will assign a color to each\n",
    "    # point in the mesh [x_min, x_max]x[y_min, y_max]\n",
    "    begin\n",
    "      # not implemented for some\n",
    "      z = clf.decision_function(mesh_points)\n",
    "    rescue\n",
    "      z = clf.predict_proba(mesh_points)[all, 1]\n",
    "    end\n",
    "\n",
    "    # Put the result into a color plot\n",
    "    z = z.reshape(xx.shape)\n",
    "    ax.contourf(xx, yy, z, cmap: cm, alpha: 0.8)\n",
    "\n",
    "    # Plot also the training points\n",
    "    ax.scatter(x_train[all, 0], x_train[all, 1], c: y_train, cmap: cm_bright)\n",
    "    # and testing points\n",
    "    ax.scatter(x_test[all, 0], x_test[all, 1], c: y_test, cmap: cm_bright, alpha: 0.6)\n",
    "\n",
    "    ax.set_xlim(np.min(xx), np.max(xx))\n",
    "    ax.set_ylim(np.min(yy), np.max(yy))\n",
    "    ax.set_xticks([])\n",
    "    ax.set_yticks([])\n",
    "    ax.set_title(name)\n",
    "\n",
    "    ax.text(np.max(xx) - 0.3, np.min(yy) + 0.3, \"%.2f\" % scor, size: 15, horizontalalignment: 'right')\n",
    "\n",
    "    i += 1\n",
    "  end\n",
    "end\n",
    "\n",
    "fig.subplots_adjust(left: 0.02, right: 0.98)"
   ]
  },
  {
   "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
}
