{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Scipy - Optimization" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import addutils.toc ; addutils.toc.js(ipy_notebook=True)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import bokeh.plotting as bk\n", "from addutils import css_notebook\n", "css_notebook()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " Loading BokehJS ...\n", "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " var force = true;\n", "\n", " if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n", " root._bokeh_onload_callbacks = [];\n", " root._bokeh_is_loading = undefined;\n", " }\n", "\n", " var JS_MIME_TYPE = 'application/javascript';\n", " var HTML_MIME_TYPE = 'text/html';\n", " var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n", " var CLASS_NAME = 'output_bokeh rendered_html';\n", "\n", " /**\n", " * Render data to the DOM node\n", " */\n", " function render(props, node) {\n", " var script = document.createElement(\"script\");\n", " node.appendChild(script);\n", " }\n", "\n", " /**\n", " * Handle when an output is cleared or removed\n", " */\n", " function handleClearOutput(event, handle) {\n", " var cell = handle.cell;\n", "\n", " var id = cell.output_area._bokeh_element_id;\n", " var server_id = cell.output_area._bokeh_server_id;\n", " // Clean up Bokeh references\n", " if (id !== undefined) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\n", "\n", " if (server_id !== undefined) {\n", " // Clean up Bokeh references\n", " var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n", " cell.notebook.kernel.execute(cmd, {\n", " iopub: {\n", " output: function(msg) {\n", " var element_id = msg.content.text.trim();\n", " Bokeh.index[element_id].model.document.clear();\n", " delete Bokeh.index[element_id];\n", " }\n", " }\n", " });\n", " // Destroy server and session\n", " var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n", " cell.notebook.kernel.execute(cmd);\n", " }\n", " }\n", "\n", " /**\n", " * Handle when a new output is added\n", " */\n", " function handleAddOutput(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", "\n", " // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n", " if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", "\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", "\n", " if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n", " toinsert[0].firstChild.textContent = output.data[JS_MIME_TYPE];\n", " // store reference to embed id on output_area\n", " output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " }\n", " if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[0].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", " }\n", "\n", " function register_renderer(events, OutputArea) {\n", "\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[0]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " /* Handle when an output is cleared or removed */\n", " events.on('clear_output.CodeCell', handleClearOutput);\n", " events.on('delete.Cell', handleClearOutput);\n", "\n", " /* Handle when a new output is added */\n", " events.on('output_added.OutputArea', handleAddOutput);\n", "\n", " /**\n", " * Register the mime type and append_mime function with output_area\n", " */\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " /* Is output safe? */\n", " safe: true,\n", " /* Index of renderer in `output_area.display_order` */\n", " index: 0\n", " });\n", " }\n", "\n", " // register the mime type if in Jupyter Notebook environment and previously unregistered\n", " if (root.Jupyter !== undefined) {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", "\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " }\n", "\n", " \n", " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " var NB_LOAD_WARNING = {'data': {'text/html':\n", " \"
\\n\"+\n", " \"

\\n\"+\n", " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", " \"

\\n\"+\n", " \"
    \\n\"+\n", " \"
  • re-rerun `output_notebook()` to attempt to load from CDN again, or
  • \\n\"+\n", " \"
  • use INLINE resources instead, as so:
  • \\n\"+\n", " \"
\\n\"+\n", " \"\\n\"+\n", " \"from bokeh.resources import INLINE\\n\"+\n", " \"output_notebook(resources=INLINE)\\n\"+\n", " \"\\n\"+\n", " \"
\"}};\n", "\n", " function display_loaded() {\n", " var el = document.getElementById(\"2c5b3fbd-bd65-43e1-aee8-e67963952e40\");\n", " if (el != null) {\n", " el.textContent = \"BokehJS is loading...\";\n", " }\n", " if (root.Bokeh !== undefined) {\n", " if (el != null) {\n", " el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(display_loaded, 100)\n", " }\n", " }\n", "\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n", " }\n", " finally {\n", " delete root._bokeh_onload_callbacks\n", " }\n", " console.info(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(js_urls, callback) {\n", " root._bokeh_onload_callbacks.push(callback);\n", " if (root._bokeh_is_loading > 0) {\n", " console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " }\n", " if (js_urls == null || js_urls.length === 0) {\n", " run_callbacks();\n", " return null;\n", " }\n", " console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " root._bokeh_is_loading = js_urls.length;\n", " for (var i = 0; i < js_urls.length; i++) {\n", " var url = js_urls[i];\n", " var s = document.createElement('script');\n", " s.src = url;\n", " s.async = false;\n", " s.onreadystatechange = s.onload = function() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.log(\"Bokeh: all BokehJS libraries loaded\");\n", " run_callbacks()\n", " }\n", " };\n", " s.onerror = function() {\n", " console.warn(\"failed to load library \" + url);\n", " };\n", " console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.getElementsByTagName(\"head\")[0].appendChild(s);\n", " }\n", " };var element = document.getElementById(\"2c5b3fbd-bd65-43e1-aee8-e67963952e40\");\n", " if (element == null) {\n", " console.log(\"Bokeh: ERROR: autoload.js configured with elementid '2c5b3fbd-bd65-43e1-aee8-e67963952e40' but no matching script tag was found. \")\n", " return false;\n", " }\n", "\n", " var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-0.12.13.min.js\"];\n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " \n", " function(Bokeh) {\n", " \n", " },\n", " function(Bokeh) {\n", " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css\");\n", " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css\");\n", " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.css\");\n", " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.css\");\n", " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.css\");\n", " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.css\");\n", " }\n", " ];\n", "\n", " function run_inline_js() {\n", " \n", " if ((root.Bokeh !== undefined) || (force === true)) {\n", " for (var i = 0; i < inline_js.length; i++) {\n", " inline_js[i].call(root, root.Bokeh);\n", " }if (force === true) {\n", " display_loaded();\n", " }} else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " } else if (force !== true) {\n", " var cell = $(document.getElementById(\"2c5b3fbd-bd65-43e1-aee8-e67963952e40\")).parents('.cell').data().cell;\n", " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", " }\n", "\n", " }\n", "\n", " if (root._bokeh_is_loading === 0) {\n", " console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", " run_inline_js();\n", " } else {\n", " load_libs(js_urls, function() {\n", " console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", "}(window));" ], "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"
    \\n\"+\n \"
  • re-rerun `output_notebook()` to attempt to load from CDN again, or
  • \\n\"+\n \"
  • use INLINE resources instead, as so:
  • \\n\"+\n \"
\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded() {\n var el = document.getElementById(\"2c5b3fbd-bd65-43e1-aee8-e67963952e40\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n }\n finally {\n delete root._bokeh_onload_callbacks\n }\n console.info(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(js_urls, callback) {\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = js_urls.length;\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n var s = document.createElement('script');\n s.src = url;\n s.async = false;\n s.onreadystatechange = s.onload = function() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.log(\"Bokeh: all BokehJS libraries loaded\");\n run_callbacks()\n }\n };\n s.onerror = function() {\n console.warn(\"failed to load library \" + url);\n };\n console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.getElementsByTagName(\"head\")[0].appendChild(s);\n }\n };var element = document.getElementById(\"2c5b3fbd-bd65-43e1-aee8-e67963952e40\");\n if (element == null) {\n console.log(\"Bokeh: ERROR: autoload.js configured with elementid '2c5b3fbd-bd65-43e1-aee8-e67963952e40' but no matching script tag was found. \")\n return false;\n }\n\n var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-0.12.13.min.js\"];\n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n \n function(Bokeh) {\n \n },\n function(Bokeh) {\n console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css\");\n Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css\");\n console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.css\");\n Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.css\");\n console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.css\");\n Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.css\");\n }\n ];\n\n function run_inline_js() {\n \n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }if (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n var cell = $(document.getElementById(\"2c5b3fbd-bd65-43e1-aee8-e67963952e40\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(js_urls, function() {\n console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "bk.output_notebook()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1 Brief Introduction to Optimization" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.1 Dimensionality of the problem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The scale of an optimization problem is pretty much set by the dimensionality of the problem, i.e. the number of scalar variables on which the search is performed." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.2 Convex versus non-convex optimization" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Convex functions can be optimized easily with gradient-descend algorithms. Non-convex functions optimization problems are much more difficult, expecially for higher dimensionality problems. This second class of optimization problems are not analyzed in this brief tutorial but are part of a specialised course." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Convex function
\n", "

Non Convex Function
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.3 Smooth and non-smooth problems" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In a smooth problem the gradient is defined everywhere: this helps in speeding-up the optimization algorithms." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Smooth function
\n", "

Non Smooth Function
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2 A Simpe Optimization Example" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `scipy.optimize` module provides useful algorithms for function minimization (scalar or multi-dimensional), curve fitting and root finding.\n", "\n", "Let's find the minimum of this simple smooth non-convex function:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function embed_document(root) {\n", " \n", " var docs_json = {\"ee0c8e98-2530-4e48-aa2e-4546548c5f84\":{\"roots\":{\"references\":[{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":{\"value\":0.5},\"fill_color\":{\"value\":\"lightgrey\"},\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":{\"value\":1.0},\"line_color\":{\"value\":\"black\"},\"line_dash\":[4,4],\"line_width\":{\"value\":2},\"plot\":null,\"render_mode\":\"css\",\"right_units\":\"screen\",\"top_units\":\"screen\"},\"id\":\"0df6ace0-84a3-4eb3-b4ee-d8002f5936e2\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"plot\":null,\"text\":\"\"},\"id\":\"45309dad-5a70-4ef8-bde9-6bf295cfbf3f\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"88083e82-efbf-476a-a8fd-87e487bcda39\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"06d213ee-e8d3-4d64-ad85-d06ace5b3394\",\"type\":\"PanTool\"},{\"attributes\":{\"callback\":null,\"column_names\":[\"x\",\"y\"],\"data\":{\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"shape\":[200]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"shape\":[200]}}},\"id\":\"f7959421-8a67-4534-94fc-1da2de6d679d\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#1f77b4\",\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"a1209649-4526-4f68-9188-104dfac44683\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"d8d6bfc8-6de8-410f-8a51-ca60a350b7ca\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"below\":[{\"id\":\"5c49d41e-3293-4d77-a053-6295a6769ca3\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"b8c7fd17-b0e7-46b9-a590-0bca16cbabab\",\"type\":\"LinearAxis\"}],\"renderers\":[{\"id\":\"5c49d41e-3293-4d77-a053-6295a6769ca3\",\"type\":\"LinearAxis\"},{\"id\":\"3cfcfee6-01af-474e-8be1-dabd8c227fe7\",\"type\":\"Grid\"},{\"id\":\"b8c7fd17-b0e7-46b9-a590-0bca16cbabab\",\"type\":\"LinearAxis\"},{\"id\":\"84ef8615-66ff-4ef0-b89f-7bb8297a7533\",\"type\":\"Grid\"},{\"id\":\"0df6ace0-84a3-4eb3-b4ee-d8002f5936e2\",\"type\":\"BoxAnnotation\"},{\"id\":\"8d8e09c7-f40d-44aa-9ddb-d5255e15e25d\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"45309dad-5a70-4ef8-bde9-6bf295cfbf3f\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"e878cc52-9255-4478-8a8d-1197fe6b2888\",\"type\":\"Toolbar\"},\"x_range\":{\"id\":\"f610be87-6e79-4ea9-8e3a-b6dcfe758b52\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"a15b3f6a-dd72-41ca-93da-1be92c6fa0d3\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"6dae5e5f-4985-4211-a8e5-89dbbbc8299a\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"aae79d68-b9ce-4700-810b-3b5cdef99b7b\",\"type\":\"LinearScale\"}},\"id\":\"66ba1f2f-8a13-42cc-95e7-487e02a646e0\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"overlay\":{\"id\":\"0df6ace0-84a3-4eb3-b4ee-d8002f5936e2\",\"type\":\"BoxAnnotation\"}},\"id\":\"23da490b-b051-4dbe-9a81-0725e030d3af\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"06d213ee-e8d3-4d64-ad85-d06ace5b3394\",\"type\":\"PanTool\"},{\"id\":\"d8d6bfc8-6de8-410f-8a51-ca60a350b7ca\",\"type\":\"WheelZoomTool\"},{\"id\":\"23da490b-b051-4dbe-9a81-0725e030d3af\",\"type\":\"BoxZoomTool\"},{\"id\":\"dd5ae7a3-fce6-4ae0-bf77-84c5d55fed37\",\"type\":\"SaveTool\"},{\"id\":\"4d20c4cb-00ec-4ba5-91bd-1d02dae4bca6\",\"type\":\"ResetTool\"},{\"id\":\"d6a2a933-3065-475f-9173-9a29cd6db87f\",\"type\":\"HelpTool\"}]},\"id\":\"e878cc52-9255-4478-8a8d-1197fe6b2888\",\"type\":\"Toolbar\"},{\"attributes\":{\"data_source\":{\"id\":\"f7959421-8a67-4534-94fc-1da2de6d679d\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"f0f6e03d-6a50-4b4e-a81c-a284d19917d6\",\"type\":\"Line\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"a1209649-4526-4f68-9188-104dfac44683\",\"type\":\"Line\"},\"selection_glyph\":null,\"view\":{\"id\":\"4fb73b20-a290-4340-83a3-5d061daf8176\",\"type\":\"CDSView\"}},\"id\":\"8d8e09c7-f40d-44aa-9ddb-d5255e15e25d\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"dd5ae7a3-fce6-4ae0-bf77-84c5d55fed37\",\"type\":\"SaveTool\"},{\"attributes\":{\"callback\":null},\"id\":\"f610be87-6e79-4ea9-8e3a-b6dcfe758b52\",\"type\":\"DataRange1d\"},{\"attributes\":{\"source\":{\"id\":\"f7959421-8a67-4534-94fc-1da2de6d679d\",\"type\":\"ColumnDataSource\"}},\"id\":\"4fb73b20-a290-4340-83a3-5d061daf8176\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"4d20c4cb-00ec-4ba5-91bd-1d02dae4bca6\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"dc5ca6d4-4240-4fb8-8338-4ce535c38fa9\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"d6a2a933-3065-475f-9173-9a29cd6db87f\",\"type\":\"HelpTool\"},{\"attributes\":{\"dimension\":1,\"plot\":{\"id\":\"66ba1f2f-8a13-42cc-95e7-487e02a646e0\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"dc5ca6d4-4240-4fb8-8338-4ce535c38fa9\",\"type\":\"BasicTicker\"}},\"id\":\"84ef8615-66ff-4ef0-b89f-7bb8297a7533\",\"type\":\"Grid\"},{\"attributes\":{\"formatter\":{\"id\":\"88083e82-efbf-476a-a8fd-87e487bcda39\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"66ba1f2f-8a13-42cc-95e7-487e02a646e0\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"dc5ca6d4-4240-4fb8-8338-4ce535c38fa9\",\"type\":\"BasicTicker\"}},\"id\":\"b8c7fd17-b0e7-46b9-a590-0bca16cbabab\",\"type\":\"LinearAxis\"},{\"attributes\":{\"callback\":null},\"id\":\"6dae5e5f-4985-4211-a8e5-89dbbbc8299a\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"a15b3f6a-dd72-41ca-93da-1be92c6fa0d3\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"aae79d68-b9ce-4700-810b-3b5cdef99b7b\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"f447a5fc-96f9-487f-83ed-4441550e49f4\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"formatter\":{\"id\":\"f447a5fc-96f9-487f-83ed-4441550e49f4\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"66ba1f2f-8a13-42cc-95e7-487e02a646e0\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"b3922834-59b7-4be1-b4be-ff0c4506efda\",\"type\":\"BasicTicker\"}},\"id\":\"5c49d41e-3293-4d77-a053-6295a6769ca3\",\"type\":\"LinearAxis\"},{\"attributes\":{\"line_color\":\"#1f77b4\",\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"f0f6e03d-6a50-4b4e-a81c-a284d19917d6\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"b3922834-59b7-4be1-b4be-ff0c4506efda\",\"type\":\"BasicTicker\"},{\"attributes\":{\"plot\":{\"id\":\"66ba1f2f-8a13-42cc-95e7-487e02a646e0\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"b3922834-59b7-4be1-b4be-ff0c4506efda\",\"type\":\"BasicTicker\"}},\"id\":\"3cfcfee6-01af-474e-8be1-dabd8c227fe7\",\"type\":\"Grid\"}],\"root_ids\":[\"66ba1f2f-8a13-42cc-95e7-487e02a646e0\"]},\"title\":\"Bokeh Application\",\"version\":\"0.12.13\"}};\n", " var render_items = [{\"docid\":\"ee0c8e98-2530-4e48-aa2e-4546548c5f84\",\"elementid\":\"57a7d456-0550-4d35-bb10-39aaf8376a88\",\"modelid\":\"66ba1f2f-8a13-42cc-95e7-487e02a646e0\"}];\n", " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", "\n", " }\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " } else {\n", " var attempts = 0;\n", " var timer = setInterval(function(root) {\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " clearInterval(timer);\n", " }\n", " attempts++;\n", " if (attempts > 100) {\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\")\n", " clearInterval(timer);\n", " }\n", " }, 10, root)\n", " }\n", "})(window);" ], "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { "application/vnd.bokehjs_exec.v0+json": { "id": "66ba1f2f-8a13-42cc-95e7-487e02a646e0" } }, "output_type": "display_data" } ], "source": [ "from scipy import optimize\n", "import numpy as np\n", "\n", "def f(x):\n", " return x**2 + 10*np.sin(x)\n", "\n", "x = np.arange(-10, 10, 0.1)\n", "\n", "fig = bk.figure()\n", "fig.plot_height = 600\n", "fig.plot_width = 600\n", "fig.line(x, f(x))\n", "bk.show(fig)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This function has a global minimum around -1.3 and a local minimum around 3.8.\n", "\n", "The general and efficient way to find a minimum for this function is to conduct a gradient descent starting from a given initial point. The [BFGS](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_bfgs.html?highlight=bfgs#scipy.optimize.fmin_bfgs) (quasi-Newton method of Broyden, Fletcher, Goldfarb, and Shanno) algorithm is a good way of doing this:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Optimization terminated successfully.\n", " Current function value: -7.945823\n", " Iterations: 5\n", " Function evaluations: 18\n", " Gradient evaluations: 6\n" ] }, { "data": { "text/plain": [ "array([-1.30644012])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "optimize.fmin_bfgs(f, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A possible issue with this approach is that, if the function has local minima, the algorithm may find these local minima instead of the global minimum. `scipy.optimize.anneal()` provides an alternative, using simulated annealing. More efficient algorithms for different classes of global optimization problems exist, but this is out of the scope of scipy. Some useful packages for global optimization are [OpenOpt](http://openopt.org/Welcome), [PyGMO](http://pagmo.sourceforge.net/pygmo/index.html) and [PyEvolve](http://pyevolve.sourceforge.net/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3 Finding the roots of a scalar function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To find a root, i.e. a point where `f(x) = 0`, of the function f above we can use for example `scipy.optimize.fsolve()`:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0.])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "root = optimize.fsolve(f, 1)\n", "root" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that only one root is found. Inspecting the plot of f reveals that there is a second root around -2.5. We find the exact value of it by adjusting our initial guess:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-2.47948183])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "root2 = optimize.fsolve(f, -2.5)\n", "root2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4 Curve Fitting" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Suppose we have data sampled from `f` with some noise:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "xdata = np.linspace(-10, 10, num=20)\n", "ydata = f(xdata) + np.random.randn(xdata.size)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now if we know the functional form of the function from which the samples were drawn (`x^2 + sin(x)` in this case) but not the amplitudes of the terms, we can find those by least squares curve fitting. First we have to define the function to fit:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "def f2(x, a, b):\n", " return a*x**2 + b*np.sin(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we can use `scipy.optimize.curve_fit()` to find `a` and `b`:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function embed_document(root) {\n", " \n", " var docs_json = {\"2deb6ac2-ad6f-4cb5-80a4-0e0b1c49a61d\":{\"roots\":{\"references\":[{\"attributes\":{\"source\":{\"id\":\"00a54620-833b-46bb-b585-e744dce52445\",\"type\":\"ColumnDataSource\"}},\"id\":\"60341410-2e6c-43cb-a58d-03f19c00f0f3\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"14d08be6-e0ba-4f08-a7b7-147b20483cb7\",\"type\":\"LinearScale\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"units\":\"screen\",\"value\":9},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"00776519-4eb8-47c7-a925-68196f48c109\",\"type\":\"Triangle\"},{\"attributes\":{\"callback\":null},\"id\":\"c3f4bc38-b786-4c71-9531-b467156a6f13\",\"type\":\"DataRange1d\"},{\"attributes\":{\"data_source\":{\"id\":\"fc6b5cde-a093-4575-9525-11ae103e8bbb\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"f2ef6334-ce97-4149-8a85-3256ab6e52b2\",\"type\":\"Triangle\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"00776519-4eb8-47c7-a925-68196f48c109\",\"type\":\"Triangle\"},\"selection_glyph\":null,\"view\":{\"id\":\"cfd75e62-7b6f-44c3-a6c2-219fc107a48b\",\"type\":\"CDSView\"}},\"id\":\"c265ea8a-b0c3-4192-af32-6334925373e0\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"2ee9258d-a0cd-4a1c-8091-b2abebaa64f8\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"fc6b5cde-a093-4575-9525-11ae103e8bbb\",\"type\":\"ColumnDataSource\"}},\"id\":\"cfd75e62-7b6f-44c3-a6c2-219fc107a48b\",\"type\":\"CDSView\"},{\"attributes\":{\"plot\":{\"id\":\"81726608-2ae3-458a-af3f-bb3c0a041134\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1ff9724a-0fbc-49ad-9ce6-5b2abde24aac\",\"type\":\"BasicTicker\"}},\"id\":\"e9b75cc5-c19d-4592-a94a-c11a99558c13\",\"type\":\"Grid\"},{\"attributes\":{\"axis_label\":\"x\",\"formatter\":{\"id\":\"691c4759-aedf-4503-8233-c68cb24a4a91\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"81726608-2ae3-458a-af3f-bb3c0a041134\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1ff9724a-0fbc-49ad-9ce6-5b2abde24aac\",\"type\":\"BasicTicker\"}},\"id\":\"b4439382-d469-4170-a10c-f9ae7cb190c6\",\"type\":\"LinearAxis\"},{\"attributes\":{\"label\":{\"value\":\"Roots\"},\"renderers\":[{\"id\":\"c265ea8a-b0c3-4192-af32-6334925373e0\",\"type\":\"GlyphRenderer\"}]},\"id\":\"0a9b0b61-7ca4-4325-a1f1-0463a69abad5\",\"type\":\"LegendItem\"},{\"attributes\":{},\"id\":\"1ff9724a-0fbc-49ad-9ce6-5b2abde24aac\",\"type\":\"BasicTicker\"},{\"attributes\":{\"axis_label\":\"f(x)\",\"formatter\":{\"id\":\"6d8b7cf1-b666-4868-b227-071e0608521f\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"81726608-2ae3-458a-af3f-bb3c0a041134\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"bf54eacf-c670-468b-a7c3-95e3532b9d12\",\"type\":\"BasicTicker\"}},\"id\":\"a813353d-ccc8-4496-bf72-3417a3ef9f7f\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"bf54eacf-c670-468b-a7c3-95e3532b9d12\",\"type\":\"BasicTicker\"},{\"attributes\":{\"dimension\":1,\"plot\":{\"id\":\"81726608-2ae3-458a-af3f-bb3c0a041134\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"bf54eacf-c670-468b-a7c3-95e3532b9d12\",\"type\":\"BasicTicker\"}},\"id\":\"08fff544-3925-4c9e-b343-abd461b8430d\",\"type\":\"Grid\"},{\"attributes\":{\"data_source\":{\"id\":\"00a54620-833b-46bb-b585-e744dce52445\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"12b718a9-0fd7-4bce-b38e-c6ea88c36d15\",\"type\":\"Line\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"a6f198b5-4d6e-4be0-a0f7-af145dfe3b71\",\"type\":\"Line\"},\"selection_glyph\":null,\"view\":{\"id\":\"60341410-2e6c-43cb-a58d-03f19c00f0f3\",\"type\":\"CDSView\"}},\"id\":\"edab7719-d031-49ed-b125-4857b8e63375\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"line_color\":\"blue\",\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"12b718a9-0fd7-4bce-b38e-c6ea88c36d15\",\"type\":\"Line\"},{\"attributes\":{\"callback\":null,\"column_names\":[\"x\",\"y\"],\"data\":{\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"shape\":[200]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"shape\":[200]}}},\"id\":\"8dfffda7-5974-4c3d-a78b-a6d3d302bafd\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":{\"value\":0.5},\"fill_color\":{\"value\":\"lightgrey\"},\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":{\"value\":1.0},\"line_color\":{\"value\":\"black\"},\"line_dash\":[4,4],\"line_width\":{\"value\":2},\"plot\":null,\"render_mode\":\"css\",\"right_units\":\"screen\",\"top_units\":\"screen\"},\"id\":\"6145ed9a-4390-4d35-8122-e72e48611909\",\"type\":\"BoxAnnotation\"},{\"attributes\":{},\"id\":\"82ad4a3c-f2ff-48f8-9ed1-74e1589e211b\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"691c4759-aedf-4503-8233-c68cb24a4a91\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"eb4695e1-7532-46a1-a7c4-f4d36978d1c0\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"overlay\":{\"id\":\"6145ed9a-4390-4d35-8122-e72e48611909\",\"type\":\"BoxAnnotation\"}},\"id\":\"512aa49c-c0b4-42c5-abc7-8704766d4a71\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"below\":[{\"id\":\"b4439382-d469-4170-a10c-f9ae7cb190c6\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"a813353d-ccc8-4496-bf72-3417a3ef9f7f\",\"type\":\"LinearAxis\"}],\"renderers\":[{\"id\":\"b4439382-d469-4170-a10c-f9ae7cb190c6\",\"type\":\"LinearAxis\"},{\"id\":\"e9b75cc5-c19d-4592-a94a-c11a99558c13\",\"type\":\"Grid\"},{\"id\":\"a813353d-ccc8-4496-bf72-3417a3ef9f7f\",\"type\":\"LinearAxis\"},{\"id\":\"08fff544-3925-4c9e-b343-abd461b8430d\",\"type\":\"Grid\"},{\"id\":\"6145ed9a-4390-4d35-8122-e72e48611909\",\"type\":\"BoxAnnotation\"},{\"id\":\"e63ee42e-596a-4206-a9c3-855d5e134ec9\",\"type\":\"Legend\"},{\"id\":\"edab7719-d031-49ed-b125-4857b8e63375\",\"type\":\"GlyphRenderer\"},{\"id\":\"e8de3e10-2c9d-4828-b66b-aa1debe07844\",\"type\":\"GlyphRenderer\"},{\"id\":\"f3d518bf-a7ef-42c3-83a4-a85d983355c4\",\"type\":\"GlyphRenderer\"},{\"id\":\"c265ea8a-b0c3-4192-af32-6334925373e0\",\"type\":\"GlyphRenderer\"}],\"title\":null,\"toolbar\":{\"id\":\"257320de-5b5d-4337-8371-78c8d536600f\",\"type\":\"Toolbar\"},\"x_range\":{\"id\":\"ccb06ecf-a9ef-472f-bacb-8a578fc72ff2\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"14d08be6-e0ba-4f08-a7b7-147b20483cb7\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"c3f4bc38-b786-4c71-9531-b467156a6f13\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"2ee9258d-a0cd-4a1c-8091-b2abebaa64f8\",\"type\":\"LinearScale\"}},\"id\":\"81726608-2ae3-458a-af3f-bb3c0a041134\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"d7839ab3-3bda-44b1-8450-ab21a2baf348\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"0b3438c4-2d13-431f-b322-c6695f2914c0\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"5f2116cb-c198-4ae0-b8bb-63af3f63e5a8\",\"type\":\"HelpTool\"},{\"attributes\":{\"data_source\":{\"id\":\"8dfffda7-5974-4c3d-a78b-a6d3d302bafd\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"8c2faad4-4fa0-4ffa-89d8-fc4da08f7f05\",\"type\":\"Line\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"c655ce74-83f2-4be5-bd69-cca51aa43817\",\"type\":\"Line\"},\"selection_glyph\":null,\"view\":{\"id\":\"1cb6eae9-f529-4495-a910-502d12d77642\",\"type\":\"CDSView\"}},\"id\":\"e8de3e10-2c9d-4828-b66b-aa1debe07844\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"line_color\":\"red\",\"line_dash\":[5],\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"8c2faad4-4fa0-4ffa-89d8-fc4da08f7f05\",\"type\":\"Line\"},{\"attributes\":{\"label\":{\"value\":\"f(x)\"},\"renderers\":[{\"id\":\"edab7719-d031-49ed-b125-4857b8e63375\",\"type\":\"GlyphRenderer\"}]},\"id\":\"44ba5988-c35c-4d87-a305-24af5f81a309\",\"type\":\"LegendItem\"},{\"attributes\":{\"source\":{\"id\":\"8dfffda7-5974-4c3d-a78b-a6d3d302bafd\",\"type\":\"ColumnDataSource\"}},\"id\":\"1cb6eae9-f529-4495-a910-502d12d77642\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null,\"column_names\":[\"x\",\"y\"],\"data\":{\"x\":{\"__ndarray__\":\"AAAAAAAAAACEsFCS+tUDwA==\",\"dtype\":\"float64\",\"shape\":[2]},\"y\":{\"__ndarray__\":\"AAAAAAAAAAAAAAAAAADgvA==\",\"dtype\":\"float64\",\"shape\":[2]}}},\"id\":\"fc6b5cde-a093-4575-9525-11ae103e8bbb\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"label\":{\"value\":\"Minima\"},\"renderers\":[{\"id\":\"f3d518bf-a7ef-42c3-83a4-a85d983355c4\",\"type\":\"GlyphRenderer\"}]},\"id\":\"c5e8c034-0f61-455e-aebd-5305b760bb32\",\"type\":\"LegendItem\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#1f77b4\",\"line_dash\":[5],\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"c655ce74-83f2-4be5-bd69-cca51aa43817\",\"type\":\"Line\"},{\"attributes\":{\"data_source\":{\"id\":\"322d1895-2fea-4492-a768-6b414a2b7c43\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"ac23789f-317b-4a6b-8af1-0738912570ea\",\"type\":\"Circle\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"05286bb8-6f84-446b-91b4-aa70baa9afc6\",\"type\":\"Circle\"},\"selection_glyph\":null,\"view\":{\"id\":\"f67cb51b-2493-49d0-bd1c-08c0a447e556\",\"type\":\"CDSView\"}},\"id\":\"f3d518bf-a7ef-42c3-83a4-a85d983355c4\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_color\":{\"value\":\"green\"},\"line_color\":{\"value\":\"green\"},\"size\":{\"units\":\"screen\",\"value\":9},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"ac23789f-317b-4a6b-8af1-0738912570ea\",\"type\":\"Circle\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#1f77b4\",\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"a6f198b5-4d6e-4be0-a0f7-af145dfe3b71\",\"type\":\"Line\"},{\"attributes\":{\"label\":{\"value\":\"Curve fit result\"},\"renderers\":[{\"id\":\"e8de3e10-2c9d-4828-b66b-aa1debe07844\",\"type\":\"GlyphRenderer\"}]},\"id\":\"b8a42ac5-07a5-4d67-8a32-d4adde9f0335\",\"type\":\"LegendItem\"},{\"attributes\":{\"callback\":null,\"column_names\":[\"x\",\"y\"],\"data\":{\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"shape\":[200]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"shape\":[200]}}},\"id\":\"00a54620-833b-46bb-b585-e744dce52445\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"source\":{\"id\":\"322d1895-2fea-4492-a768-6b414a2b7c43\",\"type\":\"ColumnDataSource\"}},\"id\":\"f67cb51b-2493-49d0-bd1c-08c0a447e556\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null},\"id\":\"ccb06ecf-a9ef-472f-bacb-8a578fc72ff2\",\"type\":\"DataRange1d\"},{\"attributes\":{\"callback\":null,\"column_names\":[\"x\",\"y\"],\"data\":{\"x\":{\"__ndarray__\":\"TvYoXA/n9L9dxA32IbMOQA==\",\"dtype\":\"float64\",\"shape\":[2]},\"y\":{\"__ndarray__\":\"68f064XIH8DK491ulKEgQA==\",\"dtype\":\"float64\",\"shape\":[2]}}},\"id\":\"322d1895-2fea-4492-a768-6b414a2b7c43\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"82ad4a3c-f2ff-48f8-9ed1-74e1589e211b\",\"type\":\"PanTool\"},{\"id\":\"eb4695e1-7532-46a1-a7c4-f4d36978d1c0\",\"type\":\"WheelZoomTool\"},{\"id\":\"512aa49c-c0b4-42c5-abc7-8704766d4a71\",\"type\":\"BoxZoomTool\"},{\"id\":\"d7839ab3-3bda-44b1-8450-ab21a2baf348\",\"type\":\"SaveTool\"},{\"id\":\"0b3438c4-2d13-431f-b322-c6695f2914c0\",\"type\":\"ResetTool\"},{\"id\":\"5f2116cb-c198-4ae0-b8bb-63af3f63e5a8\",\"type\":\"HelpTool\"}]},\"id\":\"257320de-5b5d-4337-8371-78c8d536600f\",\"type\":\"Toolbar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"units\":\"screen\",\"value\":9},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"05286bb8-6f84-446b-91b4-aa70baa9afc6\",\"type\":\"Circle\"},{\"attributes\":{\"items\":[{\"id\":\"44ba5988-c35c-4d87-a305-24af5f81a309\",\"type\":\"LegendItem\"},{\"id\":\"b8a42ac5-07a5-4d67-8a32-d4adde9f0335\",\"type\":\"LegendItem\"},{\"id\":\"c5e8c034-0f61-455e-aebd-5305b760bb32\",\"type\":\"LegendItem\"},{\"id\":\"0a9b0b61-7ca4-4325-a1f1-0463a69abad5\",\"type\":\"LegendItem\"}],\"plot\":{\"id\":\"81726608-2ae3-458a-af3f-bb3c0a041134\",\"subtype\":\"Figure\",\"type\":\"Plot\"}},\"id\":\"e63ee42e-596a-4206-a9c3-855d5e134ec9\",\"type\":\"Legend\"},{\"attributes\":{\"fill_color\":{\"value\":\"black\"},\"size\":{\"units\":\"screen\",\"value\":9},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"f2ef6334-ce97-4149-8a85-3256ab6e52b2\",\"type\":\"Triangle\"},{\"attributes\":{},\"id\":\"6d8b7cf1-b666-4868-b227-071e0608521f\",\"type\":\"BasicTickFormatter\"}],\"root_ids\":[\"81726608-2ae3-458a-af3f-bb3c0a041134\"]},\"title\":\"Bokeh Application\",\"version\":\"0.12.13\"}};\n", " var render_items = [{\"docid\":\"2deb6ac2-ad6f-4cb5-80a4-0e0b1c49a61d\",\"elementid\":\"71165d60-dac7-4c93-8497-9a726e9f88c6\",\"modelid\":\"81726608-2ae3-458a-af3f-bb3c0a041134\"}];\n", " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", "\n", " }\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " } else {\n", " var attempts = 0;\n", " var timer = setInterval(function(root) {\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " clearInterval(timer);\n", " }\n", " attempts++;\n", " if (attempts > 100) {\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\")\n", " clearInterval(timer);\n", " }\n", " }, 10, root)\n", " }\n", "})(window);" ], "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { "application/vnd.bokehjs_exec.v0+json": { "id": "81726608-2ae3-458a-af3f-bb3c0a041134" } }, "output_type": "display_data" } ], "source": [ "guess = [2, 2]\n", "params, params_covariance = optimize.curve_fit(f2, xdata, ydata, guess)\n", "\n", "grid = (-10, 10, 0.1)\n", "xmin_global = optimize.brute(f, (grid,))\n", "xmin_local = optimize.fminbound(f, 0, 10)\n", "\n", "fig = bk.figure(title=None)\n", "fig.line(x, f(x), color='blue', line_width=2, legend=\"f(x)\")\n", "fig.line(x, f2(x, *params), color='red', line_width=2, line_dash=[5], legend=\"Curve fit result\")\n", "\n", "xmins = np.array([xmin_global[0], xmin_local])\n", "\n", "fig.circle(xmins, f(xmins), size=9, color='green', legend=\"Minima\")\n", "\n", "roots = np.array([root[0], root2[0]])\n", "\n", "fig.triangle(roots, f(roots), size=9, color=\"black\", legend=\"Roots\")\n", "fig.xaxis[0].axis_label = 'x'\n", "fig.yaxis[0].axis_label = 'f(x)'\n", "bk.show(fig)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5 Optimizing with Box-Bound Constraints" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Box bounds correspond to limiting each of the individual parameters of the optimization. Note that some problems that are not originally written as box bounds can be rewritten as such be a change of variables.\n", "\n", "* `scipy.optimize.fminbound()` for 1D-optimization\n", "* `scipy.optimize.fmin_l_bfgs_b()` a quasi-Newton method with bound constraints" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "import warnings\n", "warnings.filterwarnings('ignore', category=UnicodeWarning)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "\n", "x, y = np.mgrid[-2.9:5.8:.05, -2.5:5:.05]\n", "x = x.T\n", "y = y.T\n", "\n", "for i in (1, 2):\n", " # Create 2 figure: only the second one will have the optimization\n", " # path\n", " plt.figure(i, figsize=(3, 2.5))\n", " plt.clf()\n", " plt.axes([0, 0, 1, 1])\n", "\n", " contours = plt.contour(np.sqrt((x - 3)**2 + (y - 2)**2),\n", " extent=[-3, 6, -2.5, 5], cmap=plt.cm.gnuplot)\n", " plt.clabel(contours, inline=1, fmt='%1.1f', fontsize=14)\n", "\n", " plt.plot([-1.5, -1.5, 1.5, 1.5, -1.5],\n", " [-1.5, 1.5, 1.5, -1.5, -1.5], 'k', linewidth=2)\n", " plt.fill_between([ -1.5, 1.5],\n", " [ -1.5, -1.5],\n", " [ 1.5, 1.5],\n", " color='.8')\n", " plt.axvline(0, color='k')\n", " plt.axhline(0, color='k')\n", "\n", " plt.text(-.9, 4.4, '$x_2$', size=20)\n", " plt.text(5.6, -.6, '$x_1$', size=20)\n", " plt.axis('equal')\n", " plt.axis('off')\n", "\n", "# And now plot the optimization path\n", "accumulator = list()\n", "\n", "def f(x):\n", " # Store the list of function calls\n", " accumulator.append(x)\n", " return np.sqrt((x[0] - 3)**2 + (x[1] - 2)**2)\n", "\n", "# We don't use the gradient, as with the gradient, L-BFGS is too fast,\n", "# and finds the optimum without showing us a pretty path\n", "def f_prime(x):\n", " r = np.sqrt((x[0] - 3)**2 + (x[0] - 2)**2)\n", " return np.array(((x[0] - 3)/r, (x[0] - 2)/r))\n", "\n", "optimize.fmin_l_bfgs_b(f, np.array([0, 0]), approx_grad=1,\n", " bounds=((-1.5, 1.5), (-1.5, 1.5)))\n", "\n", "accumulated = np.array(accumulator)\n", "plt.plot(accumulated[:, 0], accumulated[:, 1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "Visit [www.add-for.com]() for more tutorials and updates.\n", "\n", "This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License." ] } ], "metadata": { "kernelspec": { "display_name": "Python [conda env:addfor_tutorials]", "language": "python", "name": "conda-env-addfor_tutorials-py" }, "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.4" } }, "nbformat": 4, "nbformat_minor": 1 }