{
  "nbformat_minor": 0, 
  "nbformat": 4, 
  "cells": [
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "%matplotlib inline"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }, 
    {
      "source": [
        "\n========================\nHow to use joblib.Memory\n========================\n\nThis example illustrates the usage of :class:`joblib.Memory` with both\nfunctions and methods.\n\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "source": [
        "Without :class:`joblib.Memory`\n##############################################################################\n\n ``costly_compute`` emulates a computationally expensive process which later\n will benefit from caching using :class:`joblib.Memory`.\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "import time\nimport numpy as np\n\n\ndef costly_compute(data, column_index=0):\n    \"\"\"Simulate an expensive computation\"\"\"\n    time.sleep(5)\n    return data[column_index]"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }, 
    {
      "source": [
        "Be sure to set the random seed to generate deterministic data. Indeed, if the\ndata is not deterministic, the :class:`joblib.Memory` instance will not be\nable to reuse the cache from one run to another.\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "rng = np.random.RandomState(42)\ndata = rng.randn(int(1e5), 10)\nstart = time.time()\ndata_trans = costly_compute(data)\nend = time.time()\n\nprint('\\nThe function took {:.2f} s to compute.'.format(end - start))\nprint('\\nThe transformed data are:\\n {}'.format(data_trans))"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }, 
    {
      "source": [
        "Caching the result of a function to avoid recomputing\n##############################################################################\n\n If we need to call our function several time with the same input data, it is\n beneficial to avoid recomputing the same results over and over since it is\n expensive. :class:`joblib.Memory` enables to cache results from a function\n into a specific location.\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "from joblib import Memory\nlocation = './cachedir'\nmemory = Memory(location=location, verbose=0)\n\n\ndef costly_compute_cached(data, column_index=0):\n    \"\"\"Simulate an expensive computation\"\"\"\n    time.sleep(5)\n    return data[column_index]\n\n\ncostly_compute_cached = memory.cache(costly_compute_cached)\nstart = time.time()\ndata_trans = costly_compute_cached(data)\nend = time.time()\n\nprint('\\nThe function took {:.2f} s to compute.'.format(end - start))\nprint('\\nThe transformed data are:\\n {}'.format(data_trans))"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }, 
    {
      "source": [
        "At the first call, the results will be cached. Therefore, the computation\ntime corresponds to the time to compute the results plus the time to dump the\nresults into the disk.\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "start = time.time()\ndata_trans = costly_compute_cached(data)\nend = time.time()\n\nprint('\\nThe function took {:.2f} s to compute.'.format(end - start))\nprint('\\nThe transformed data are:\\n {}'.format(data_trans))"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }, 
    {
      "source": [
        "At the second call, the computation time is largely reduced since the results\nare obtained by loading the data previously dumped to the disk instead of\nrecomputing the results.\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "source": [
        "Using :class:`joblib.Memory` with a method\n##############################################################################\n\n :class:`joblib.Memory` is designed to work with functions with no side\n effects. When dealing with class, the computationally expensive part of a\n method has to be moved to a function and decorated in the class method.\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "def _costly_compute_cached(data, column):\n    time.sleep(5)\n    return data[column]\n\n\nclass Algorithm(object):\n    \"\"\"A class which is using the previous function.\"\"\"\n\n    def __init__(self, column=0):\n        self.column = column\n\n    def transform(self, data):\n        costly_compute = memory.cache(_costly_compute_cached)\n        return costly_compute(data, self.column)\n\n\ntransformer = Algorithm()\nstart = time.time()\ndata_trans = transformer.transform(data)\nend = time.time()\n\nprint('\\nThe function took {:.2f} s to compute.'.format(end - start))\nprint('\\nThe transformed data are:\\n {}'.format(data_trans))"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }, 
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "start = time.time()\ndata_trans = transformer.transform(data)\nend = time.time()\n\nprint('\\nThe function took {:.2f} s to compute.'.format(end - start))\nprint('\\nThe transformed data are:\\n {}'.format(data_trans))"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }, 
    {
      "source": [
        "As expected, the second call to the ``transform`` method load the results\nwhich have been cached.\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "source": [
        "Clean up cache directory\n##############################################################################\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "memory.clear(warn=False)"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }
  ], 
  "metadata": {
    "kernelspec": {
      "display_name": "Python 2", 
      "name": "python2", 
      "language": "python"
    }, 
    "language_info": {
      "mimetype": "text/x-python", 
      "nbconvert_exporter": "python", 
      "name": "python", 
      "file_extension": ".py", 
      "version": "2.7.14", 
      "pygments_lexer": "ipython2", 
      "codemirror_mode": {
        "version": 2, 
        "name": "ipython"
      }
    }
  }
}