{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Slide 0: Instructions\n", "* These are not ordinary slides: many are interactive and *fully executable*\n", "* You'll want to be on a laptop or desktop. *(For mobile, wait until I finish writing the blog version of this.)* \n", "* Make sure your browser is in full screen mode (F11) and zoom=100%\n", "* Press the space bar to advance to the next slide\n", "* To exit the slideshow and see the code, press `Alt-R` or click the \"x\"" ] }, { "cell_type": "markdown", "metadata": { "id": "vY1GKEo098Ym", "slideshow": { "slide_type": "slide" } }, "source": [ "# The Joy of 3D 🎉
*Visualizations for Teaching about Classification*\n", "## Scott H. Hawley\n", "Department of Chemistry & Physics
\n", "College of Sciences and Mathematics\n", "

\n", " Re:Teaching PHY/BSA 3895: \"Deep Learning and AI Ethics,\" Fall 2021.

\n", "




\n", "

Scholarship of Teaching & Learning Symposium, Belmont University, April 28, 2021\n", "

" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "import numpy as np \n", "from mrspuff.viz import *\n", "from mrspuff.utils import calc_prob, one_hot, softmax\n", "from mrspuff.scrape import exhibit_urls" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Intro\n", "If your field is related to any of these...

🎜👩‍⚕️⚕️⚖️👮📚🎹👩‍🎤🛒☣️🧑‍🚀🧬🎥🧑‍🎓☢️🧳🧑‍🏫📦🎧🕵️♀️♂️🎅💲📖🧑‍🍳⚗️📡👩‍🏭🔬🖧🧫🧑‍⚖️📈🎮🧑‍🌾📉💉🧑‍🔬💊🗣️♟️🎸

\n", "\n", "...then automated classification increasingly \"a big deal.\"" ] }, { "cell_type": "markdown", "metadata": { "id": "pdzG_hRy8vlo", "slideshow": { "slide_type": "subslide" } }, "source": [ "## Motivation\n", "
\n", "
Classification is fascinating to me. Physicists don't do it much but the rest of society relies on it.\n", "\n", "I like & teach machine learning (ML), esp. deep learning (DL). *Lots* of ML is classification. How humans & machines do it differently is the topic of my *popular-level* eBook-in-progess that uses interactive visualizations (instead of \"math\").
\n", "
\n", "\n", "

Recently many research papers (e.g., ML-audio) use \"contrastive losses\" -- ??
\n", "Turns out you can relate these to traditional (DL-based) classification if you view the latter a certain way -- \"view\" being the operative word!
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "**TODO:shorten** We'll compare & contrast \"traditional\" machine learning (ML) classification with so-called \"zero-shot\" classifiers that rely on [embedding](https://arxiv.org/abs/1604.06737) semantically meaningful features as clusters in space by means of contrastive losses. These \"zero-shot\" methods are increasingly prevalent in the literature, and have the nice property that, unlike traditional ML classifiers, they don't need to be re-trained when new classes are added. If we want to understand zero-shot methods, we may consider traditional classification *as an embedding method* of it own." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Teaching ML: Viz, and Why 3D\n", "
\n", "
In teaching ML, it's common to teach binary classification* and then jump immediately into multi-class problems with large numbers of classes. This misses an opportunity for visualization -- the case of 3 classes.

\n", "

*see my blog post \"Naughty by Numbers: Classifications at Christmas\"

\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "



I said \"no math,\" but: \n", "${\\rm softmax}(x_i) = {e^{x_i} \\over \\sum\\limits_j e^{x_j}} $.
3D gives you all of softmax's complexity & you can still picture it!

" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Viz Matters for Teaching\n", "Data/sound viz has been an big part of my career, further influenced by Yang Hann Kim's 2016 Rossing Prize Lecture in Acoustics Education on viz in teaching STEM. \n", "
\n", "Today I want to show you new work, including my \"Triangle Diagram\"! " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Viz for > 3D = 😢\n", "
\n", "My blog post, \"PCA from Scratch\"\n", "
\n", "
\n", "
Humans can only visualize up to 3 dimensions, so for > 3 features we rely on projections via PCA or nonlinear embedding methods like t-SNE or UMAP. But with PCA data points tend to overlap, and other methods twist/distort/rip so global structure is lost.
\n", "\n", "\n", "In 3D the representations are *exact*!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## New Code Library: [mrspuff](https://github.com/drscotthawley/mrspuff) \n", "\n", "For teaching via visualization and running on [Google Colab](https://colab.research.google.com), and leveraging [fast.ai](https://github.com/fastai/fastai).\n", "
\n", " \n", "\n", " \n", "
" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "labels = ['cat','dog','horse']\n", "data = np.array([[0.7,0.2,0.1],[0.15,0.6,0.25],[0.05,0.15,0.8],[1,0,0],[0,1,0],[0,0,1]])\n", "\n", "# made the following to generate images to be loaded in the next cell. and save them to ./images/\n", "# You can ignore it\n", "if False:\n", " from plotly.io import write_image\n", " for i in range(len(labels)):\n", " fig = image_and_bars(data[i], labels, CDH_SAMPLE_URLS[i]).show()\n", " fname = f'images/{labels[i]}_bars.png'\n", " try:\n", " write_image(fig, fname) \n", " except ValueError:\n", " print(\"Sorry, you need the plotly-orca binary installed to auto-save images.\")\n", " print(\"Click on the camera icon above to save manually to \",fname)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# save cropped versions; ignore it\n", "if False:\n", " from PIL import Image\n", " for i in range(len(labels)):\n", " f = f'images/{labels[i]}'\n", " fin = f+'_bars.png'\n", " img = Image.open(fin)\n", " img = img.crop((15,25,250,200))\n", " img.save(f+'.png')" ] }, { "cell_type": "markdown", "metadata": { "id": "gA3XbAPN8-f_", "slideshow": { "slide_type": "slide" } }, "source": [ "## Dimensions and Embeddings\n", "\n", "Traditionally, we use triplets of numbers to denote 3 classes. \n", "\n", "\"Ground truth\" values are \"one-hot encoded\":
\n", "
   cat: (1,0,0)           dog: (0,1,0)         horse: (0,0,1)
\n", "\n", "Model predictics class probabilities for images:\n", "
\n", " \n", "
\n", "

\n", "...the 3 numbers always have to add up to 1 (probability)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "People who are not mathematicians, physicists, data scientists, etc. may be unaccustomed to this talk of \"dimensions\" when dealing with data. Let's dive in to the specific case of *three-class classification*. Say we're developing a computer program to guess (\"predict\") whether given image contains a cat, a dog, or a horse. Traditionally we produce a set of 3 probabilities for each class, say...\n", "**TODO:** describe one-hot encoding of target values" ] }, { "cell_type": "markdown", "metadata": { "id": "dhI52sWD9Lm-", "slideshow": { "slide_type": "notes" } }, "source": [ "These numbers can be viewed as the strength of an attribute in an image, e.g. measures of cat-ness, dog-ness, and horse-ness (or measure of the likelihood of being a cat, dog, or horse, respectively), where a value of 1 means 100% of that property. Notice in each case, the three \"class\" probabilities add up to 1. This is always the case: probabilities always have to sum up to 1, i.e. 1 is \"100% certainty\" that gets split among the 3 classes. (This summing to 1 is an important property that we'll come back to in a bit.)\n", "\n", "One thing that scientists like to do is take different variables and view them as *coordinates of a single point in a multi-dimensional space*. So for 3 classes we have 3 coordinates for 3 dimensions. We could make the \"cat-ness\" prediction probability be the \"x\" coordinate, and \"dog-ness\" be the \"y\" values, and \"horse-ness\" could be along the \"z\" axis. Then instead of drawing bar graphs, we could plot points in 3D space, where the coordinates of each point tell us the predictions:\n", "\n", "*All the 3D plots in this post can be rotated & zoomed with the mouse or your finger. Try it!*\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "\"Embedding\": treat each triplet as the (x,y,z) coordinates of a *point* in 3D space:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "by32Mz4y9IRw", "outputId": "4a652786-4905-4bc0-c706-63d429306998", "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# All the 3D plots in this talk are interactive. Use your mouse to rotate, etc!\n", "TrianglePlot3D_Plotly(data, targ=None, labels=labels*2, show_bounds=False).do_plot()" ] }, { "cell_type": "markdown", "metadata": { "id": "18OLvGLS9QX7", "slideshow": { "slide_type": "skip" } }, "source": [ "(Here we also used the 3 class probabilities to set the R,G,B color values of the points. There's no new information contained in this; it just looks cool.)\n", "\n", "What scientists tend to do is, even in cases where there are more then 3 variables (say, 10), we regard these as dimensions in some fancy abstract mathematical space where the laws may or may not conform to those of our universe -- for example, the idea of \"distance\" may be totally up for grabs. In cases where the number of values is infinite (say, as coefficients in a infinite series, or as a function of a continuous variable) we might even work in *infinite* dimensions! Often when we talk like this, it doesn't mean that we're actually picturing geometrical spaces in our heads -- we can't, for anything beyond 3 dimensions -- but it's a handy way of encapsulating a particular way of viewing the data or functions involved. And sometimes we *do* try to see what kinds of geometrical insights we can glean -- which is what we're going to do here!\n", "\n", "Remember when we said that the individual class probabilities have to add up to 1? Look what happens when we plot a *lot* of such points..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Let's plot LOTS of points..." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "hideCode": false, "id": "bz1dP26B9NyU", "outputId": "b73ad350-ff2f-43d0-cd32-93f8a80137de", "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "prob, targ = calc_prob(n=400)\n", "TrianglePlot3D_Plotly(prob, targ=None, labels=labels, show_bounds=False).do_plot()" ] }, { "cell_type": "markdown", "metadata": { "id": "JtKuxjw5udRX", "slideshow": { "slide_type": "notes" } }, "source": [ "Note that even though these are points in 3D space, they make up a *triangle* which lies along a *plane* -- a 2D :subspace\" of 3D. This is a consequence of having the \"constraint\" that all class probabilities add up to 1. \n", "\n", "We can color the points by their expected class values by choosing the triangle point (or \"pole\") that they're nearest to -- i.e. by which \"bar\" is largest among the class probabilities. And we can include the boundaries between classes:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Let's color them by their target value / label, and show class boundaries: " ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "hideCode": false, "id": "1PgeVqXQuvfk", "outputId": "363d96ae-f917-4343-8296-8e68b8b9eafa", "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "TrianglePlot3D_Plotly(prob, targ=targ, labels=labels, show_bounds=True).do_plot()" ] }, { "cell_type": "markdown", "metadata": { "id": "HCqLI-jgu9Vi", "slideshow": { "slide_type": "slide" } }, "source": [ "## 3 Classes in 2D\n", "Since points lie in a plane, we can change coord's & plot in 2D instead
*(mouse hover = show image!)*" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "Note: right now these images when you mouse over below are first scraped from DDG on-the-fly, and then rendered via `requests` when you mouse over. Work in progress. Real-time tracking while training FastAI is on the TODO list!" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 367 }, "hideCode": true, "id": "ExvL06A7wpvF", "outputId": "0a695323-14e2-422f-fe2c-f93aaed38eb0", "scrolled": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "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 != null && id in Bokeh.index) {\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 id = msg.content.text.trim();\n", " if (id in Bokeh.index) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\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\") || (!Object.prototype.hasOwnProperty.call(output.data, 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[toinsert.length - 1].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[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\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[toinsert.length - 1]);\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", " \"\\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(null);\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) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", " if (root._bokeh_is_loading > 0) {\n", " console.debug(\"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.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " root._bokeh_is_loading = css_urls.length + js_urls.length;\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", "\n", " function on_error(url) {\n", " console.error(\"failed to load \" + url);\n", " }\n", "\n", " for (let i = 0; i < css_urls.length; i++) {\n", " const url = css_urls[i];\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error.bind(null, url);\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " }\n", "\n", " const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.1.min.js\": \"YF85VygJKMVnHE+lLv2AM93Vbstr0yo2TbIu5v8se5Rq3UQAUmcuh4aaJwNlpKwa\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.1.min.js\": \"KKuas3gevv3PvrlkyCMzffFeaMq5we/a2QsP5AUoS3mJ0jmaCL7jirFJN3GoE/lM\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.1.min.js\": \"MK/uFc3YT18pkvvXRl66tTHjP0/dxoSH2e/eiNMFIguKlun2+WVqaPTWmUy/zvh4\"};\n", "\n", " for (let i = 0; i < js_urls.length; i++) {\n", " const url = js_urls[i];\n", " const element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error.bind(null, url);\n", " element.async = false;\n", " element.src = url;\n", " if (url in hashes) {\n", " element.crossOrigin = \"anonymous\";\n", " element.integrity = \"sha384-\" + hashes[url];\n", " }\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " \n", " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.1.min.js\"];\n", " var css_urls = [];\n", " \n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " function(Bokeh) {\n", " \n", " \n", " }\n", " ];\n", "\n", " function run_inline_js() {\n", " \n", " if (root.Bokeh !== undefined || force === true) {\n", " \n", " for (var i = 0; i < inline_js.length; i++) {\n", " inline_js[i].call(root, root.Bokeh);\n", " }\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(null)).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.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", " run_inline_js();\n", " } else {\n", " load_libs(css_urls, js_urls, function() {\n", " console.debug(\"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 \"\\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(null);\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) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"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.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.1.min.js\": \"YF85VygJKMVnHE+lLv2AM93Vbstr0yo2TbIu5v8se5Rq3UQAUmcuh4aaJwNlpKwa\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.1.min.js\": \"KKuas3gevv3PvrlkyCMzffFeaMq5we/a2QsP5AUoS3mJ0jmaCL7jirFJN3GoE/lM\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.1.min.js\": \"MK/uFc3YT18pkvvXRl66tTHjP0/dxoSH2e/eiNMFIguKlun2+WVqaPTWmUy/zvh4\"};\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n if (url in hashes) {\n element.crossOrigin = \"anonymous\";\n element.integrity = \"sha384-\" + hashes[url];\n }\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n \n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.1.min.js\"];\n var css_urls = [];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\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(null)).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.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function embed_document(root) {\n", " \n", " var docs_json = {\"e9cffe58-a904-44c8-8b93-010270816851\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1013\"}],\"center\":[{\"id\":\"1016\"},{\"id\":\"1020\"},{\"id\":\"1058\"},{\"id\":\"1059\"},{\"id\":\"1060\"}],\"height\":350,\"left\":[{\"id\":\"1017\"}],\"renderers\":[{\"id\":\"1040\"},{\"id\":\"1045\"},{\"id\":\"1050\"},{\"id\":\"1056\"}],\"title\":{\"id\":\"1003\"},\"toolbar\":{\"id\":\"1029\"},\"width\":400,\"x_range\":{\"id\":\"1005\"},\"x_scale\":{\"id\":\"1009\"},\"y_range\":{\"id\":\"1007\"},\"y_scale\":{\"id\":\"1011\"}},\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"callback\":null,\"tooltips\":\"\\n
\\n
\\n \\n
\\n
\\n @desc\\n [$index]\\n
\\n \\n
\\n \"},\"id\":\"1028\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"1070\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"1075\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"1021\",\"type\":\"PanTool\"},{\"attributes\":{\"source\":{\"id\":\"1052\"}},\"id\":\"1057\",\"type\":\"CDSView\"},{\"attributes\":{\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1038\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1022\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"source\":{\"id\":\"1037\"}},\"id\":\"1041\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1076\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"formatter\":{\"id\":\"1065\"},\"major_label_policy\":{\"id\":\"1067\"},\"ticker\":{\"id\":\"1014\"}},\"id\":\"1013\",\"type\":\"LinearAxis\"},{\"attributes\":{\"source\":{\"id\":\"1042\"}},\"id\":\"1046\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1024\",\"type\":\"SaveTool\"},{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"1027\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"axis\":{\"id\":\"1017\"},\"dimension\":1,\"ticker\":null},\"id\":\"1020\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"1071\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"1072\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1043\",\"type\":\"Line\"},{\"attributes\":{\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1048\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1014\",\"type\":\"BasicTicker\"},{\"attributes\":{\"data\":{\"colors\":[\"blue\",\"blue\",\"blue\",\"red\",\"red\",\"blue\",\"red\",\"red\",\"red\",\"green\",\"green\",\"red\",\"red\",\"red\",\"blue\",\"red\",\"red\",\"red\",\"blue\",\"red\",\"red\",\"red\",\"blue\",\"blue\",\"green\",\"blue\",\"green\",\"blue\",\"blue\",\"green\",\"red\",\"green\",\"red\",\"green\",\"green\",\"green\",\"green\",\"red\",\"blue\",\"green\",\"green\",\"blue\",\"red\",\"green\",\"blue\",\"blue\",\"red\",\"green\",\"green\",\"green\",\"red\",\"red\",\"green\",\"green\",\"green\",\"green\",\"green\",\"green\",\"green\",\"green\",\"green\",\"green\",\"blue\",\"red\",\"red\",\"red\",\"blue\",\"green\",\"blue\",\"green\",\"blue\",\"green\",\"blue\",\"blue\",\"red\",\"green\",\"green\",\"blue\",\"green\",\"red\",\"green\",\"blue\",\"blue\",\"blue\",\"green\",\"blue\",\"green\",\"red\",\"blue\",\"blue\",\"blue\",\"blue\",\"green\",\"red\",\"green\",\"blue\",\"red\",\"blue\",\"green\",\"red\",\"red\",\"red\",\"blue\",\"blue\",\"red\",\"blue\",\"blue\",\"green\",\"green\",\"green\",\"green\",\"green\",\"green\",\"green\",\"red\",\"green\",\"red\",\"blue\",\"green\",\"green\",\"blue\",\"red\",\"red\",\"red\",\"red\",\"blue\",\"red\",\"red\",\"red\",\"green\",\"green\",\"green\",\"green\",\"red\",\"blue\",\"blue\",\"red\",\"green\",\"green\",\"green\",\"red\",\"green\",\"red\",\"red\",\"blue\",\"green\",\"red\",\"green\",\"blue\",\"blue\",\"blue\",\"blue\",\"blue\",\"blue\",\"green\",\"green\",\"red\",\"blue\",\"green\",\"red\",\"blue\",\"green\",\"red\",\"red\",\"green\",\"blue\",\"red\",\"red\",\"blue\",\"blue\",\"blue\",\"blue\",\"blue\",\"blue\",\"blue\",\"red\",\"red\",\"red\",\"blue\",\"blue\",\"blue\",\"blue\",\"red\",\"green\",\"blue\",\"blue\",\"green\",\"red\",\"red\",\"green\",\"green\",\"blue\",\"blue\",\"red\",\"green\",\"green\",\"blue\",\"red\",\"red\",\"red\",\"blue\",\"blue\",\"red\",\"green\",\"red\",\"blue\",\"blue\",\"blue\",\"red\",\"green\",\"red\",\"green\",\"red\",\"red\",\"blue\",\"blue\",\"green\",\"red\",\"red\",\"green\",\"red\",\"red\",\"green\",\"green\",\"green\",\"blue\",\"blue\",\"red\",\"green\",\"blue\",\"red\",\"red\",\"blue\",\"green\",\"red\",\"blue\",\"green\",\"blue\",\"blue\",\"red\",\"blue\",\"red\",\"blue\",\"red\",\"green\",\"green\",\"blue\",\"green\",\"red\",\"green\",\"green\",\"green\",\"red\",\"red\",\"blue\",\"green\",\"blue\",\"red\",\"green\",\"blue\",\"green\",\"blue\",\"green\",\"blue\",\"red\",\"red\",\"green\",\"green\",\"green\",\"red\",\"red\",\"green\",\"blue\",\"blue\",\"red\",\"green\",\"red\",\"blue\",\"red\",\"blue\",\"red\",\"red\",\"red\",\"blue\",\"red\",\"red\",\"blue\",\"blue\",\"red\",\"blue\",\"blue\",\"red\",\"green\",\"blue\",\"red\",\"green\",\"green\",\"red\",\"blue\",\"green\",\"blue\",\"red\",\"green\",\"green\",\"red\",\"blue\",\"red\",\"green\",\"red\",\"blue\",\"green\",\"red\",\"red\",\"red\",\"green\",\"red\",\"blue\",\"red\",\"blue\",\"green\",\"red\",\"blue\",\"red\",\"blue\",\"green\",\"red\",\"red\",\"red\",\"blue\",\"green\",\"green\",\"green\",\"blue\",\"blue\",\"red\",\"red\",\"blue\",\"blue\",\"green\",\"blue\",\"green\",\"green\",\"blue\",\"red\",\"red\",\"red\",\"green\",\"green\",\"red\",\"green\",\"blue\",\"green\",\"red\",\"red\",\"red\",\"blue\",\"blue\",\"green\",\"blue\",\"blue\",\"green\",\"red\",\"green\",\"green\",\"red\",\"blue\",\"red\",\"green\",\"red\",\"green\",\"green\",\"blue\",\"red\",\"blue\",\"red\",\"red\",\"green\",\"blue\",\"red\",\"green\",\"green\",\"green\",\"blue\",\"green\",\"blue\",\"blue\",\"red\",\"blue\",\"green\",\"red\",\"red\",\"blue\",\"blue\",\"blue\",\"red\",\"red\",\"green\",\"green\",\"blue\",\"red\"],\"desc\":[\"horse\",\"horse\",\"horse\",\"cat\",\"cat\",\"horse\",\"cat\",\"cat\",\"cat\",\"dog\",\"dog\",\"cat\",\"cat\",\"cat\",\"horse\",\"cat\",\"cat\",\"cat\",\"horse\",\"cat\",\"cat\",\"cat\",\"horse\",\"horse\",\"dog\",\"horse\",\"dog\",\"horse\",\"horse\",\"dog\",\"cat\",\"dog\",\"cat\",\"dog\",\"dog\",\"dog\",\"dog\",\"cat\",\"horse\",\"dog\",\"dog\",\"horse\",\"cat\",\"dog\",\"horse\",\"horse\",\"cat\",\"dog\",\"dog\",\"dog\",\"cat\",\"cat\",\"dog\",\"dog\",\"dog\",\"dog\",\"dog\",\"dog\",\"dog\",\"dog\",\"dog\",\"dog\",\"horse\",\"cat\",\"cat\",\"cat\",\"horse\",\"dog\",\"horse\",\"dog\",\"horse\",\"dog\",\"horse\",\"horse\",\"cat\",\"dog\",\"dog\",\"horse\",\"dog\",\"cat\",\"dog\",\"horse\",\"horse\",\"horse\",\"dog\",\"horse\",\"dog\",\"cat\",\"horse\",\"horse\",\"horse\",\"horse\",\"dog\",\"cat\",\"dog\",\"horse\",\"cat\",\"horse\",\"dog\",\"cat\",\"cat\",\"cat\",\"horse\",\"horse\",\"cat\",\"horse\",\"horse\",\"dog\",\"dog\",\"dog\",\"dog\",\"dog\",\"dog\",\"dog\",\"cat\",\"dog\",\"cat\",\"horse\",\"dog\",\"dog\",\"horse\",\"cat\",\"cat\",\"cat\",\"cat\",\"horse\",\"cat\",\"cat\",\"cat\",\"dog\",\"dog\",\"dog\",\"dog\",\"cat\",\"horse\",\"horse\",\"cat\",\"dog\",\"dog\",\"dog\",\"cat\",\"dog\",\"cat\",\"cat\",\"horse\",\"dog\",\"cat\",\"dog\",\"horse\",\"horse\",\"horse\",\"horse\",\"horse\",\"horse\",\"dog\",\"dog\",\"cat\",\"horse\",\"dog\",\"cat\",\"horse\",\"dog\",\"cat\",\"cat\",\"dog\",\"horse\",\"cat\",\"cat\",\"horse\",\"horse\",\"horse\",\"horse\",\"horse\",\"horse\",\"horse\",\"cat\",\"cat\",\"cat\",\"horse\",\"horse\",\"horse\",\"horse\",\"cat\",\"dog\",\"horse\",\"horse\",\"dog\",\"cat\",\"cat\",\"dog\",\"dog\",\"horse\",\"horse\",\"cat\",\"dog\",\"dog\",\"horse\",\"cat\",\"cat\",\"cat\",\"horse\",\"horse\",\"cat\",\"dog\",\"cat\",\"horse\",\"horse\",\"horse\",\"cat\",\"dog\",\"cat\",\"dog\",\"cat\",\"cat\",\"horse\",\"horse\",\"dog\",\"cat\",\"cat\",\"dog\",\"cat\",\"cat\",\"dog\",\"dog\",\"dog\",\"horse\",\"horse\",\"cat\",\"dog\",\"horse\",\"cat\",\"cat\",\"horse\",\"dog\",\"cat\",\"horse\",\"dog\",\"horse\",\"horse\",\"cat\",\"horse\",\"cat\",\"horse\",\"cat\",\"dog\",\"dog\",\"horse\",\"dog\",\"cat\",\"dog\",\"dog\",\"dog\",\"cat\",\"cat\",\"horse\",\"dog\",\"horse\",\"cat\",\"dog\",\"horse\",\"dog\",\"horse\",\"dog\",\"horse\",\"cat\",\"cat\",\"dog\",\"dog\",\"dog\",\"cat\",\"cat\",\"dog\",\"horse\",\"horse\",\"cat\",\"dog\",\"cat\",\"horse\",\"cat\",\"horse\",\"cat\",\"cat\",\"cat\",\"horse\",\"cat\",\"cat\",\"horse\",\"horse\",\"cat\",\"horse\",\"horse\",\"cat\",\"dog\",\"horse\",\"cat\",\"dog\",\"dog\",\"cat\",\"horse\",\"dog\",\"horse\",\"cat\",\"dog\",\"dog\",\"cat\",\"horse\",\"cat\",\"dog\",\"cat\",\"horse\",\"dog\",\"cat\",\"cat\",\"cat\",\"dog\",\"cat\",\"horse\",\"cat\",\"horse\",\"dog\",\"cat\",\"horse\",\"cat\",\"horse\",\"dog\",\"cat\",\"cat\",\"cat\",\"horse\",\"dog\",\"dog\",\"dog\",\"horse\",\"horse\",\"cat\",\"cat\",\"horse\",\"horse\",\"dog\",\"horse\",\"dog\",\"dog\",\"horse\",\"cat\",\"cat\",\"cat\",\"dog\",\"dog\",\"cat\",\"dog\",\"horse\",\"dog\",\"cat\",\"cat\",\"cat\",\"horse\",\"horse\",\"dog\",\"horse\",\"horse\",\"dog\",\"cat\",\"dog\",\"dog\",\"cat\",\"horse\",\"cat\",\"dog\",\"cat\",\"dog\",\"dog\",\"horse\",\"cat\",\"horse\",\"cat\",\"cat\",\"dog\",\"horse\",\"cat\",\"dog\",\"dog\",\"dog\",\"horse\",\"dog\",\"horse\",\"horse\",\"cat\",\"horse\",\"dog\",\"cat\",\"cat\",\"horse\",\"horse\",\"horse\",\"cat\",\"cat\",\"dog\",\"dog\",\"horse\",\"cat\"],\"imgs\":[\"http://www.hdnicewallpapers.com/Walls/Big/Horse/Standing_Maroon_Horse.jpg\",\"http://getwallpapers.com/wallpaper/full/b/0/b/718769-vertical-beautiful-horse-wallpaper-2560x1600-mobile.jpg\",\"https://wallpapertag.com/wallpaper/full/e/7/7/922038-popular-cute-horse-wallpapers-2560x1600-large-resolution.jpg\",\"https://www.sciencenews.org/wp-content/uploads/2020/03/033120_HT_covid-cat_feat-1028x579.jpg\",\"https://cdn0.wideopenpets.com/wp-content/uploads/2018/11/Bombay-cat.jpg\",\"https://d.ibtimes.co.uk/en/full/1415067/horse.jpg\",\"https://wallup.net/wp-content/uploads/2019/09/708281-kittens-kitten-cat-cats-baby-cute.jpg\",\"https://www.vets4pets.com/siteassets/species/cat/cat-on-fence.jpg?w=585&scale=down\",\"https://www.thenewsminute.com/sites/default/files/Sad_Cat_Kochi_airport.jpg\",\"http://wallup.net/wp-content/uploads/2016/10/12/388956-animals-dog-mammals.jpg\",\"http://smashingtops.com/wp-content/uploads/2012/10/Medium-dog-breeds-03.jpg\",\"https://blogs.columbian.com/cat-tales/wp-content/uploads/sites/43/2017/09/Sawyer_DS_1402.jpg\",\"https://external-preview.redd.it/h00AuerLwYj1U6z8SXlkuNi8TxO236Sg76EYmLBwEi0.jpg?auto=webp&s=8942f3e8d1813944d7d25c2bd6d3504783665163\",\"https://www.norwegiancat.com/wp-content/uploads/2017/01/Tabby-Wegie.jpg\",\"http://cdn0.wideopenpets.com/wp-content/uploads/2016/07/rearing.jpeg\",\"https://www.nativebreed.org/wp-content/uploads/2020/05/siamese-cat1.jpg\",\"https://thefunnybeaver.com/wp-content/uploads/2020/08/adorable-cat-group.jpg\",\"http://themeowpost.com/wp-content/uploads/2016/03/Pallas-cat-featured.png\",\"https://www.hdwallpapers.in/download/brown_horse_with_background_of_sunset_and_clouds_hd_horse-HD.jpg\",\"https://filmdaily.co/wp-content/uploads/2020/04/cat-play-lede-1300x867.jpg\",\"https://www.theladders.com/wp-content/uploads/grumpy_cat_190517.jpg\",\"http://whyuniverse.com/wp-content/uploads/2015/07/lonely-cat.jpg\",\"https://images.wisegeek.com/horse-showing-teeth.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/04/shir10.jpg\",\"http://www.rspcasa.org.au/wp-content/uploads/2018/11/Puppy_dogtraining.jpg\",\"https://pixelcurse.com/wp-content/uploads/2011/05/horse_photography_9.jpg\",\"https://ohmylovelypets.com/wp-content/uploads/2019/12/Boxer_dog850.jpg\",\"http://r.ddmcdn.com/s_f/o_1/DSC/uploads/2015/08/horse4-fusion.jpg\",\"http://www.francethisway.com/images/stories/wildlife/ardennes-horse.jpg\",\"https://picon.ngfiles.com/772000/flash_772322_largest_crop.png?f1605987118\",\"https://www.sainsburysbank.co.uk/pet-insurance/cat-breed/~/media/Images/assets/product/pet-insurance/pods/cat-breeds/bengal2\",\"https://buzzsharer.com/wp-content/uploads/2015/11/Schnauzer-dog-love.jpg\",\"https://www.askideas.com/media/25/American-Shorthair-Cat-Face-Picture.jpg\",\"https://barkpost.com/wp-content/uploads/2015/01/winterdogshame-576x1024.jpg\",\"https://housethatbarks.com/wp-content/uploads/dog-tricks.jpg\",\"https://img.dog-learn.com/dog-breeds/jug/jug-dog-i1.jpg\",\"http://cdn2-www.dogtime.com/assets/uploads/2010/12/senior-dog-2.jpg\",\"https://www.hdnicewallpapers.com/Walls/Big/Cat/Lovely_Cat_Sleepng_Pic_Download.jpg\",\"https://petkeen.com/wp-content/uploads/2020/07/brown-arabian-horse_pikist-1.jpg\",\"https://upload.wikimedia.org/wikipedia/commons/5/54/Pomsky_Dog_Breed_-_Pomeranian_Husky_Mix.jpg\",\"https://thebark.com/sites/default/files/content/article/full/ava-smilingdog.jpg\",\"https://arabianhorseworld.com/wp-content/uploads/2017/08/08-190917_TOC.jpg\",\"https://www.hdwallpapers.in/download/brown_black_cat_with_ash_muffler_on_neck_hd_kitten-1280x720.jpg\",\"http://dogreference.com/wp-content/uploads/2014/01/German-Shorthaired-Pointer.jpg\",\"https://www.nativebreed.org/wp-content/uploads/2020/04/Skyros.jpg\",\"https://cdn.tsln.com/wp-content/uploads/sites/13/2020/09/srdakotabreeders-tsln-092620-1-1-1024x682.jpg\",\"https://hddesktopwallpapers.in/wp-content/uploads/2015/08/cat-funny.jpg\",\"https://cdn.lolwot.com/wp-content/uploads/2015/05/15-strange-and-unusual-dog-breeds-11.jpg\",\"http://www.dogexpress.in/wp-content/uploads/2016/02/1-30.jpg\",\"https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Australian_Cattle_Dog_sitting.jpg/1200px-Australian_Cattle_Dog_sitting.jpg\",\"https://images.wagwalkingweb.com/media/articles/cat/complete-pinnectomy/complete-pinnectomy.jpg\",\"https://www.rightthisminute.com/sites/default/files/videos/images/tard-the-grumpy-cat.jpg\",\"https://boxerdogdiaries.com/wp-content/uploads/2020/09/A-Boxer-dog-with-cropped-ears-beside-one-with-natural-ears-1024x684.jpg\",\"http://www.incrediblesnaps.com/wp-content/uploads/2013/07/Rottweiler.jpg\",\"https://media.salon.com/2013/10/thoughtful_dog.jpg\",\"http://www.healthypawspetinsurance.com/blog/wp-content/uploads/dog_anxiety_640x420.jpg\",\"http://img.thrfun.com/img/083/608/panting_dog_l1.jpg\",\"https://sydneydruglawyers.com.au/wp-content/uploads/sniffer-dog-1024x1024.jpg\",\"https://wallpapertag.com/wallpaper/full/7/5/0/426773-pitbull-dog-wallpaper-1080x1920-picture.jpg\",\"https://www.outsideonline.com/sites/default/files/2015/06/22/fitness-dog-smiling_s.jpg\",\"http://www.dogbreedslist.info/topics-img/181026-Chinook.jpg\",\"https://www.rd.com/wp-content/uploads/2018/11/shiba-inu.jpg\",\"https://castlehorsefeeds.com/wp-content/uploads/2019/03/spring-horses.jpg\",\"http://themeowpost.com/wp-content/uploads/2016/02/stray-cat-finds-home.jpg\",\"https://www.askideas.com/media/23/Bombay-Cat-Sitting-Picture1.jpg\",\"https://thecatsite.com/c/wp-content/uploads/2019/11/traditional-persian-cat-fac.jpg\",\"https://api.time.com/wp-content/uploads/2015/08/horse-smile.jpg\",\"https://www.dogvills.com/wp-content/uploads/2020/09/how-much-does-a-hypoallergenic-dog-cost-p2-683x1024.jpg\",\"https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Camargue_Horse_(26645657776).jpg/1200px-Camargue_Horse_(26645657776).jpg\",\"https://img.dog-learn.com/dog-breeds/dachshund/dachshund-i2.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/04/appa23.jpg\",\"https://www.pdsa.org.uk/media/4032/german-shepherd-dog-og.png\",\"https://www.pensacolavoice.com/wp-content/uploads/2020/09/Horse-racing.jpg\",\"https://hddesktopwallpapers.in/wp-content/uploads/2015/07/horse-wallpapers-sunrise.jpg\",\"http://www.geekologie.com/2012/08/22/chimera-cat-4.jpg\",\"http://i.huffpost.com/gen/1559880/thumbs/o-DOG-HOWLING-facebook.jpg\",\"https://www.thesprucepets.com/thmb/0XAm4NcCyEi8bzwzOywN6dEprPI=/1500x1000/filters:fill(auto,1)/GettyImages-186699738-5eaf8e80458c4e19829874ec7352d06a.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/02/bigb7.jpg\",\"https://hddesktopwallpapers.in/wp-content/uploads/2015/09/dog-wallpapers-for-desktop.jpg\",\"https://newseu.cgtn.com/news/2020-07-28/Pet-cat-becomes-first-animal-in-the-UK-to-test-positive-for-COVID-19-Stu0H0T6Gk/img/9ff85c8aa3cd4670ae6ac08c4327deaf/9ff85c8aa3cd4670ae6ac08c4327deaf-1920.png\",\"https://www.townofsweden.org/static/sitefiles/departments/dog.jpg\",\"http://getwallpapers.com/wallpaper/full/f/7/7/675263.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/04/appa6.jpg\",\"https://www.equineridge.com/wp-content/uploads/2019/07/ardennes-featured-image.jpg\",\"https://wallpapertag.com/wallpaper/full/5/6/e/466295-boxer-dog-wallpaper-1536x2048-lockscreen.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/02/grah10.jpg\",\"https://d1nvdmt0osh3cv.cloudfront.net/media/catalog/product/cache/1/k/a/e/image/1800x1800/acd9cc645a7ef0ba358bd1c2969a48c8/els1312-bla.jpg\",\"https://viralcats.net/blog/wp-content/uploads/2017/10/saddest-shelter-cat-benben-transformation-8-9-Viral-Cats.jpg\",\"https://www.ufaw.org.uk/images/belgian-draught-horse.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/04/lusi20.jpg\",\"https://www.infyworld.com/wp-content/uploads/2017/03/wybren464-576x705.jpg\",\"https://www.horseguide.com.au/database/classifieds/files/post-388097-15128099471773934968.jpeg\",\"https://petpress.net/wp-content/uploads/2020/03/top-15-most-exotic-dog-breeds-in-the-world14.jpg\",\"https://hddesktopwallpapers.in/wp-content/uploads/2015/08/lazy-cat-funny.jpg\",\"https://ag.tennessee.edu/news/News%20Photos/2017/Ames%20Dog%20web.jpeg\",\"https://www.horsebreedspictures.com/wp-content/uploads/2018/07/Thoroughbreds.jpg\",\"https://www.rd.com/wp-content/uploads/2019/01/ragdoll_friendly-cats.jpg\",\"https://equine-world.co.uk/info/images/arab-horse.jpg\",\"https://img.thrfun.com/img/079/797/aggressive_dog_l1.jpg\",\"https://www.hdnicewallpapers.com/Walls/Big/Cat/Yellow_Cat_Eye_Superb_Picture.jpg\",\"http://www.catbreedselector.com/wp-content/uploads/2015/03/Korat-Pictures.jpg\",\"https://www.newshub.co.nz/home/lifestyle/2019/09/cats-love-their-owners-just-as-much-as-dogs-do-study/_jcr_content/par/video/image.dynimg.1280.q75.jpg/v1569304349200/getty-cat-owner-cuddle-1120.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/01/pics8.jpg\",\"http://www.tineey.com/wp-content/uploads/2014/04/Icelandic-Horse-5.jpg\",\"http://wallup.net/wp-content/uploads/2017/03/28/105880-animals-cat-wild_cat-Pallas_Cat-Pallas039s_Cat.jpg\",\"https://img.equinenow.com/slir/w1200/stallions/data/photos/415304/1441318831/star-slight-rear-coronet-horse.jpg\",\"https://media2.s-nbcnews.com/j/newscms/2020_09/3249886/200229-horse-al-0953_ce9e024eadc2a89db090f35edc0b2c8f.nbcnews-fp-1200-630.jpg\",\"https://parade.pet/assets-v2/images/dog/img-dogs/07.jpg\",\"https://www.aspca.org/sites/default/files/dog-care_dog-bite-prevention_main-image.jpg\",\"http://r.ddmcdn.com/s_f/o_1/w_1024/h_681/APL/uploads/2013/06/ActiveDogBenefits.jpg\",\"http://d.ibtimes.co.uk/en/full/1585687/aviemore-sled-dog-rally.jpg\",\"http://www.dogreference.com/wp-content/uploads/2014/01/bigstock-Dog-Pug-35116394-ELEN.jpg\",\"http://travelsandliving.com/wp-content/uploads/2016/01/adorable-smiling-dogs-24.jpg\",\"http://www.dogexpress.in/wp-content/uploads/2016/03/Korean-Mastiffs-4-2.jpg\",\"https://cdn2-www.cattime.com/assets/uploads/2016/04/meow-cat-language.jpg\",\"http://photoblog.statesman.com/wp-content/uploads/2012/01/ttp-cartier-dog-show-1.jpg\",\"https://www.thegoodypet.com/wp-content/uploads/2020/10/Savannah-768x960.jpg\",\"https://data.jigsawpuzzle.co.uk/ravensburger.5/white-horse-jigsaw-puzzle-500-pieces.55361-1.fs.jpg\",\"https://moderndogmagazine.com/sites/default/files/images/uploads/CaneCorso-01.jpg\",\"http://4.bp.blogspot.com/-up_IKtLpyjg/TaETE35x4jI/AAAAAAAAG_Y/wGrZyCkMJ1c/s1600/Dalmatian-dog6.jpg\",\"http://images2.fanpop.com/images/photos/6000000/Slawik-horse-wallpapers-horses-6070973-1024-768.jpg\",\"https://hddesktopwallpapers.in/wp-content/uploads/2015/08/kitten-cute-wallpaper-shoe.jpg\",\"https://catlov.com/wp-content/uploads/2016/12/Featured-Cat-Tongue-fb.png\",\"http://admirableworld.com/files/images/2019/09/9_Cute_ginger_cat.jpg\",\"http://www.smashingphotoz.com/wp-content/uploads/2012/cat-photos/16_cat_photos.jpg\",\"https://www.centerforamericasfirsthorse.org/uploads/3/4/1/3/34130178/826717_orig.jpg\",\"https://www.rd.com/wp-content/uploads/2019/05/Ragdoll-Kitten.jpg\",\"https://ilikecatsverymuch.com/wp-content/uploads/2019/06/cat-wallpaper-iphone-cute-7.jpg\",\"https://www.clydefitchreport.com/wp-content/uploads/2016/12/cute-cat-images-tpevent-17.jpg\",\"https://hddesktopwallpapers.in/wp-content/uploads/2015/09/dog-wallpaper-for-mobile.jpg\",\"https://wallup.net/wp-content/uploads/2018/10/07/766785-samoyed-dog-dogs-canine.jpg\",\"https://canna-pet.com/wp-content/uploads/2019/02/dog-eating-1.jpg\",\"https://www.barnorama.com/wp-content/uploads/2018/04/dog-facial-deformity-saved-adopted-rescued-happy-3.jpg\",\"https://cdn3-www.cattime.com/assets/uploads/2017/09/Tortoiseshell-Cat-1.jpg\",\"http://showhorsegallery.com/images/uploads/thornvilledanphoto2.jpg\",\"https://image.freepik.com/free-photo/beautiful-brown-horse-outdoors_23-2148573800.jpg\",\"https://pngimg.com/uploads/cat/cat_PNG113.png\",\"https://www.trbimg.com/img-54e6adbe/turbine/ct-stray-dog-trapper-met-20150220\",\"https://www.publicdomainpictures.net/pictures/30000/nahled/smiling-dog-1355804583CQq.jpg\",\"https://media.pri.org/s3fs-public/styles/open_graph/public/migration/PriMigrationsDamanticWordpressAttachmentsImagesMigration/www.theworld.org/wp-content/uploads/English_setter-resting-wiki620.jpg?itok=XJ56yNi0\",\"https://www.eatliver.com/wp-content/uploads/2014/06/stupid-cat3.jpg\",\"https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Photo_de_Samoy%C3%A8de.jpg/1200px-Photo_de_Samoy%C3%A8de.jpg\",\"https://www.sunnyskyz.com/uploads/2014/08/t226l-cat-standing12.jpg\",\"http://www.hdwallpaperspulse.com/wp-content/uploads/2014/03/01/rr.jpeg\",\"https://img.equinenow.com/slir/w800/stallions/data/photos/1192971/1518634644/drive-friesian-horse.jpg\",\"https://www.breedyourdog.com/uploads/listing_images/23557/61123/big_IMG_1316.jpg\",\"https://upload.wikimedia.org/wikipedia/commons/d/dc/Grumpy_Cat_(14556024763)_(cropped).jpg\",\"https://img2.grunge.com/img/gallery/he-real-reason-you-should-be-cleaning-your-dogs-leash/whos-a-good-dog-whos-got-their-leash-1587157270.jpg\",\"https://img.equinenow.com/slir/w1200/stallions/data/photos/871749/1560715644/grey-none-horse.jpg\",\"https://www.hdnicewallpapers.com/Walls/Big/Horse/Grey_Color_Horse_Pic_Download.jpg\",\"http://www.chapmanvalleyhorseriding.com/wp-content/uploads/2015/10/HalloweenHorses-33.jpg\",\"https://d.newsweek.com/en/full/1105889/9-5-horse.jpg\",\"https://www.paulickreport.com/wp-content/uploads/2020/05/CRACKER_HORSE_Photo_2.jpg\",\"https://www.allhorsebreeds.info/liver-roan-ardennes-horse.jpg\",\"https://www.petmd.com/sites/default/files/aggressive-dog-shutterstock_16848454.jpg\",\"http://fallinpets.com/wp-content/uploads/2016/12/cool-boxer-dog.jpg\",\"https://pngimg.com/uploads/cat/cat_PNG50440.png\",\"https://horsespirit.site/wp-content/uploads/2020/04/icel13.jpg\",\"https://buzzsharer.com/wp-content/uploads/2015/04/face-dog-rottweiler.jpg\",\"https://www.munchkincatguide.com/wp-content/uploads/2019/01/munchkinduo.jpg\",\"http://getwallpapers.com/wallpaper/full/b/a/d/1518010-horse-scenes-wallpaper-2880x1800-iphone.jpg\",\"https://content.thriveglobal.com/wp-content/uploads/2018/07/happy-dog.jpg\",\"https://mymodernmet.com/wp/wp-content/uploads/2017/03/gabrielius-khiterer-stray-cats-12.jpg\",\"https://www.newshub.co.nz/home/world/2018/01/grumpy-cat-wins-962-000-in-copyright-infringement-suit/_jcr_content/par/image.dynimg.1280.q75.jpg/v1516869410491/611696914-grumpy-cat-tardar-sauce-visits-cats-on-broadway-1120.jpg\",\"https://www.dogexpress.in/wp-content/uploads/2017/02/953072-shih-tzu.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/04/lusi13.jpg\",\"https://www.gannett-cdn.com/media/USATODAY/GenericImages/2012/11/26/gan-grumpy-cat-112612-1-16_9.jpg?width=1807&height=1020&fit=crop&format=pjpg&auto=webp\",\"http://geekologie.com/2015/06/25/sad-cat-7.jpg\",\"https://live.staticflickr.com/2869/33664971492_8c42b935d2_b.jpg\",\"https://s3.amazonaws.com/static.arabhorse.com/files/posts/4288/facebook_images/large.jpg?1489063084\",\"https://horsespirit.site/wp-content/uploads/2019/12/ard8.jpg\",\"https://www.aspca.org/sites/default/files/wildhorsesblogbanner.jpg\",\"https://equine-world.co.uk/info/images/horse-behaviour.jpg\",\"https://www.wormers.co.uk/blog/wp-content/uploads/2016/01/Equitop-Myoplast-Feeding-the-Older-Horse.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/04/shir21.jpg\",\"https://www.awesomeinventions.com/wp-content/uploads/2020/10/Cat-With-Ehlers-Danlos-Syndrome.jpg\",\"http://www.hdwallpaper.nu/wp-content/uploads/2017/04/cat-11.jpg\",\"https://www.kidsdiscover.com/wp-content/uploads/2014/10/Calico_Cat.jpg\",\"https://fossilrim.org/wp-content/uploads/2017/01/Our-Animals-pic-horse-2.jpg\",\"https://thehorse.com/wp-content/uploads/2018/02/horse-pawing.jpg\",\"https://www.dromoland.ie/wp-content/uploads/2019/07/Horse-Riding-Couple-Image-4.jpg\",\"https://assets.horsenation.com.s3.amazonaws.com/wp-content/uploads/2014/08/481px-Liver_chestnut_horse.jpg\",\"https://img.thrfun.com/img/079/115/feeding_a_cat_x1.jpg\",\"http://africageographic.com/wp-content/uploads/2015/10/wild-dog1.jpg\",\"http://www.awesomelycute.com/gallery/2015/01/horse-rescue-foxy-awesomelycute-com-21.jpg\",\"https://cdn0.wideopenpets.com/wp-content/uploads/2016/07/horse-2.jpg\",\"https://cdn7.littlethings.com/app/uploads/2017/05/cute-dog-big-ears-600x600.jpg\",\"https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/An_up-close_picture_of_a_curious_male_domestic_shorthair_tabby_cat.jpg/1200px-An_up-close_picture_of_a_curious_male_domestic_shorthair_tabby_cat.jpg\",\"https://www.petpaw.com.au/wp-content/uploads/2013/02/Tonkinese-cute-cat-1030x772.jpg\",\"http://www.pixelstalk.net/wp-content/uploads/2016/04/Dog-images-HD-background-wallpaper.jpg\",\"http://images.boredomfiles.com/wp-content/uploads/2014/05/dog-coat-markings-4.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/03/fries21.jpg\",\"https://wallpapertag.com/wallpaper/full/c/3/8/922024-cute-horse-wallpapers-1920x1080-for-macbook.jpg\",\"https://www.pets4homes.co.uk/images/classifieds/2018/09/16/2064325/large/female-tabby-cat-5b9e858c17efc.jpg\",\"https://fishsubsidy.org/wp-content/uploads/2020/01/Boxer_Dog_Characteristics.jpg\",\"http://www.zastavki.com/pictures/1920x1200/2010/Animals_Dogs_Sleeping_dog_on_floor_020830_.jpg\",\"https://www.horseguide.com.au/database/classifieds/files/post-378985-14331402261292767621.jpg\",\"https://www.sunnyskyz.com/uploads/2018/11/jjx4t-grumpy-cat-2.jpg\",\"https://www.animals-zone.com/wp-content/uploads/2011/08/cat-breeds-2.jpg\",\"https://www.cheatsheet.com/wp-content/uploads/2019/05/Grumpy-Cat-1-1024x682.jpg\",\"https://www.wallpapers13.com/wp-content/uploads/2016/04/Racing-red-horse-meadow-pasture-royalty-Desktop-Wallpaper-Backgrounds-free-download-915x515.jpg\",\"https://www.hdnicewallpapers.com/Walls/Big/Horse/Two_Beautiful_Brown_Horse_Image.jpg\",\"https://banner2.kisspng.com/20171218/007/cute-cat-5a37f4c79915d5.850277071513616583627.jpg\",\"https://dogtails.dogwatch.com/wp-content/uploads/2020/01/Blog-FeaturedImg-AKCNewBreeds-2020.jpg\",\"https://www.crescentmoonragdolls.com/uploads/1/4/5/9/14594736/dsc03590-2_1_orig.jpg\",\"http://thestyleinspiration.com/wp-content/uploads/2019/10/Arabian-Horses-.jpg\",\"https://images.wallpaperscraft.com/image/horse_face_eyes_57856_800x1420.jpg\",\"https://wallpapersmug.com/download/1080x1920/2d0672/running-horse-animal.jpg\",\"http://themeowpost.com/wp-content/uploads/2016/01/8-manny-the-selfie-cat.jpg\",\"https://www.hdnicewallpapers.com/Walls/Big/Dog/White_Hairy_Doggy.jpg\",\"https://petsfeed.co/wp-content/uploads/2020/09/Rarest-Cat-Breeds-Elf-Cat.jpg\",\"https://buzzsharer.com/wp-content/uploads/2016/03/dachshund-dog-face.jpg\",\"https://mymodernmet.com/wp/wp-content/uploads/2017/11/chimera-cat-quimera-5.jpg\",\"https://htc-wallpaper.com/wp-content/uploads/2015/05/Cute-cat-licking-its-paw.jpg\",\"https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/RockySilverhorse.jpg/1200px-RockySilverhorse.jpg\",\"https://img.equinenow.com/slir/w1200/stallions/data/photos/1252400/1570892827/brabant-belgian-horse.jpg\",\"https://cdn.petpress.net/wp-content/uploads/2020/06/11213858/havanese-9.jpg\",\"http://www.hdnicewallpapers.com/Walls/Big/Cat/Charming_Cat_Baby_Wallpaper.jpg\",\"https://nationalzoo.si.edu/sites/default/files/animals/fishingcat-002_0.jpg\",\"https://petapixel.com/assets/uploads/2015/12/doglungefeat.jpg\",\"https://img.thrfun.com/img/199/602/coco_5_x2.jpg\",\"https://happypetsclub.net/wp-content/uploads/2017/05/4-ears-cat.jpg\",\"https://www.maxpixel.net/static/photo/640/Dog-Puppy-Protection-Dog-Face-Cute-Adorable-Hug-3986171.jpg\",\"http://i.dmarge.com/2016/11/dog-angry-960x580.jpg\",\"https://www.hdnicewallpapers.com/Walls/Big/Dog/Amazing_Wallpaper_of_Dog.jpg\",\"http://wallup.net/wp-content/uploads/2016/01/262482-animals-nature-horse.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/04/appa5.jpg\",\"https://www.rescuepets.com.au/app/uploads/1/886d92993c90c6a6bd6308706c4a24ac951c7272a515d64392214ee7d170dab4.jpg-1500x.jpg\",\"https://wallpapertag.com/wallpaper/full/1/a/2/466305-download-boxer-dog-wallpaper-2560x1600-phone.jpg\",\"https://www.chapmanvalleyhorseriding.com/wp-content/uploads/2015/10/HalloweenHorses-14.jpg\",\"https://www.wallpapergeeks.com/wp-content/uploads/2014/06/Cat-Mustache-Wallpaper.jpg\",\"https://viralcats.net/blog/wp-content/uploads/2017/11/yoda-is-a-chicago-cat-with-four-ears-9-Viral-Cats-Featured-image-1020x776.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/01/biih1.jpg\",\"https://www.sciencealert.com/images/articles/processed/dog-doubt_1024.jpg\",\"https://catscottishfold.com/wp-content/uploads/2018/11/is_scottish_fold_hypoallergenic.jpg\",\"https://www.scienceabc.com/wp-content/uploads/2018/12/horse-ride.jpg\",\"http://www.dog-learn.com/dog-breeds/maltese/images/maltese-u3.jpg\",\"https://hdwallpapers.move.pk/wp-content/uploads/2015/02/enjoying-horse-1024x576.jpg\",\"https://wallpaperheart.com/wp-content/uploads/2018/03/wild-horse-wallpapers-cavalli.jpg\",\"https://www.top13.net/wp-content/uploads/2017/03/fun-cat-fur-patterns-fb.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/02/arde3.jpg\",\"https://api.time.com/wp-content/uploads/2019/12/CatFilterReaction.jpg\",\"https://horseandrider.com/.image/t_share/MTQ0ODgzMTk0MDEyNDQ0MDIy/image-placeholder-title.jpg\",\"http://emojiforu.com/wp-content/uploads/2018/06/adorable-cat.jpg\",\"https://buzzsharer.com/wp-content/uploads/2015/05/wet-dog-pics.jpg\",\"https://www.petful.com/wp-content/uploads/2015/12/Canaan-Dog-profile.jpg\",\"http://weknowyourdreams.com/images/horse/horse-02.jpg\",\"http://animalsbreeds.com/wp-content/uploads/2015/01/Australian-Cattle-Dog-3.jpg\",\"http://themeowpost.com/wp-content/uploads/2016/11/cat-with-fangs.png\",\"https://d.ibtimes.co.uk/en/full/1623762/dog-snout.jpg\",\"http://img1.wsimg.com/isteam/ip/2d07f71e-d041-4772-b631-82b25d1cbe8c/ae93ede1-afb0-4697-8dc4-3b8599238aba.jpg\",\"http://wallup.net/wp-content/uploads/2016/01/96149-dog-couch-animals.jpg\",\"http://news.nationalgeographic.com/content/dam/news/photos/000/588/58818.jpg\",\"http://mymodernmet.com/wp/wp-content/uploads/2017/03/gabrielius-khiterer-stray-cats-4.jpg\",\"https://www.horsebreedspictures.com/wp-content/uploads/2018/04/Carthusian-Horse.jpg\",\"https://www.publicdomainpictures.net/pictures/60000/nahled/dog-isolated-on-white-1379711079p8n.jpg\",\"http://cardiffstudentmedia.co.uk/gairrhydd/wp-content/uploads/sites/2/2014/05/Breton-Horse3-nr-lathus-18-feb2012.jpg\",\"https://riotfest.org/wp-content/uploads/2019/05/grumpy-cat.jpg\",\"https://www.bwallpaperhd.com/wp-content/uploads/2018/06/WildDog-1024x576.jpg\",\"https://www.horsedialog.co.uk/Health/Breeding/easset_upload_file81610_399336_e.jpg\",\"http://c.files.bbci.co.uk/8336/production/_105709533_dog-eating-index.jpg\",\"https://horsespirit.site/wp-content/uploads/2019/12/bdh9.jpg\",\"https://wallup.net/wp-content/uploads/2018/10/07/519427-rottweiler-dog-dogs.jpg\",\"https://torange.biz/photofx/137/10/sunset-mirror-very-vivid-colours-horse-137060.jpg\",\"http://cdn.shopify.com/s/files/1/1834/9585/articles/173-0-scottish_fold_cat_1024x1024.jpg?v=1539158132\",\"https://static.inspiremore.com/wp-content/uploads/2020/06/04120237/Kitzia-new-Grumpy-Cat-5.png\",\"http://mymodernmet.com/wp/wp-content/uploads/2017/09/dog-portraits-alexander-khokhlov-9.jpg\",\"https://www.keystonepuppies.com/wp-content/uploads/2019/01/boxer-dog-grown.jpg\",\"https://cdn.lolwot.com/wp-content/uploads/2016/01/10-banned-dog-breeds-most-people-want-5.jpg\",\"https://www.thepaws.net/wp-content/uploads/2019/02/hemingway-polydactyl-cat.jpg\",\"https://i.ytimg.com/vi/jsGGVFKJRUk/maxresdefault.jpg\",\"https://dogswithwings.ca/wp-content/uploads/2014/02/Daisy.jpg\",\"http://lovebackyard.com/wp-content/uploads/2017/05/horse-eating-cherries.jpg\",\"https://lh3.googleusercontent.com/-9cEauptJbfk/TYIFZLS003I/AAAAAAAAAM4/h7W9JL_cNSA/s1600/Przewalski%2527s+Horse+2.JPG\",\"http://www.bedlamfarm.com/wp-content/uploads/2013/02/Deadly-Cat-.jpg\",\"http://animalsbreeds.com/wp-content/uploads/2014/07/Papillon-dog-14.jpg\",\"https://www.askideas.com/media/84/Toyger-Cat-Yawning.jpg\",\"https://www.thevetexpert.com/wp-content/uploads/2020/03/Horse-Look.jpg\",\"https://cdn1.theweek.co.uk/sites/theweek/files/2017/08/170816-cats-in-a-box.jpg\",\"https://hdwallpapers.move.pk/wp-content/uploads/2015/02/bueutiful-horse-running.jpg\",\"https://pixel.nymag.com/imgs/daily/vulture/2019/05/17/17-grumpy-cat.w1200.h630.jpg\",\"http://purrtacular.com/wp-content/uploads/2017/09/maya-extra-chromosome-cat-7.jpg\",\"https://www.hdnicewallpapers.com/Walls/Big/Cat/Cat_Eye_Twitching_Wonderful_Photo.jpg\",\"https://s.equimed.com/images/52/1024/0/0.jpg\",\"https://www.sunnyskyz.com/uploads/2019/06/tbcg6-angry-cat-2.jpg\",\"https://www.nationalgeographic.com/content/dam/news/photos/000/755/75552.ngsversion.1422285553360.adapt.1900.1.jpg\",\"https://www.nativebreed.org/wp-content/uploads/2020/05/Boerperd-horse.jpg\",\"https://pngimg.com/uploads/horse/horse_PNG323.png\",\"https://yesofcorsa.com/wp-content/uploads/2017/12/Angry-Cat-Desktop-Wallpaper.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/04/appa8.jpg\",\"https://www.ctquarterhorse.com/site/image/original/216.jpg\",\"https://petable.care/wp-content/uploads/2016/07/sad-cat-1920x1080.jpg\",\"https://www.animalhub.com/wp-content/uploads/2014/03/dogs-funny-faces-shake-2.jpg\",\"https://elishaedwards.com/wp-content/uploads/2019/11/Depositphotos_26867917_l-grey-horse-running.jpg\",\"https://fishsubsidy.org/wp-content/uploads/2020/01/The-Devon-Rex-Cat-Breed-.jpg\",\"https://cdn.shopify.com/s/files/1/0994/0236/articles/chinook-dog-crate-size_1200x1200.jpg?v=1539662625\",\"http://cdnfiles.hdrcreme.com/43136/medium/cute-grey-dog.jpg?1426746306\",\"http://www.theultimatecatwebsite.com/uploads/1/1/0/8/11083235/8367004_orig.jpg\",\"http://getwallpapers.com/wallpaper/full/d/7/2/956626-download-wallpaper-horse-2560x1600-hd-1080p.jpg\",\"http://www.mendosa.com/fitnessblog/wp-content/uploads/2011/10/prairie-dog.jpg\",\"https://www.petguide.com/wp-content/uploads/2016/09/Racking-Horse.jpg\",\"https://pupstoday.com/wp-content/uploads/2020/10/16-4.jpg\",\"https://dogbreeds-az.weebly.com/uploads/5/8/5/5/58556921/9204867.jpg\",\"https://www.dogvills.com/wp-content/uploads/2014/12/dog-546286_640.jpg\",\"http://parade.pet/assets-v2/images/cat/img-cats/04.jpg\",\"http://d.ibtimes.co.uk/en/full/1415067/horse.jpg\",\"https://www.pawculture.com/uploads/siberian-forest-cat.jpg\",\"https://petskb.com/wp-content/uploads/2019/08/dog-excited.jpg\",\"https://www.hdwallpapers.in/download/blue_eyes_black_nose_white_cat_is_lying_down_on_ground_4k_5k_hd_cat-HD.jpg\",\"https://www.thevetexpert.com/wp-content/uploads/2020/01/Horse-Abuse.jpg\",\"https://cdn.cnn.com/cnnnext/dam/assets/190624020024-scamp-super-tease.jpg\",\"https://wallup.net/wp-content/uploads/2016/10/12/383993-face-ears-hair-photography-wildlife-wild_cat-Caracal.jpg\",\"https://pbs.twimg.com/media/DYLuNt2UQAEqaOs.jpg:large\",\"https://www.emdonenilodge.com/wp-content/uploads/2015/08/African-Wild-Cat.jpg\",\"https://jooinn.com/images/dog-67.jpg\",\"https://pulpbits.net/wp-content/uploads/2014/01/Cat-Tortoiseshell-1024x1365.jpg\",\"https://img.equinenow.com/slir/w800/equine/data/photos/1260249/1554277504/sale-appaloosa-horse.jpg\",\"http://i.huffpost.com/gen/2891956/images/o-CUTE-CAT-facebook.jpg\",\"http://horsescience.co/wp-content/uploads/2015/02/trotpoles.jpg\",\"http://img.burrard-lucas.com/zambia/full/wild_dog.jpg\",\"https://cdn.britannica.com/24/212324-131-4AD3AE21/Persian-cat-sleeping.jpg\",\"https://thehorse.com/wp-content/uploads/2017/09/quarter-horse-trotting-in-arena.jpg\",\"https://c.pxhere.com/photos/35/c8/cat_black_animal_stone_barsik_meadow_field_grass-624421.jpg!d\",\"https://www.hdnicewallpapers.com/Walls/Big/Horse/Brown_Horse_with_Her_Lovely_Child.jpg\",\"https://www.thegoodypet.com/wp-content/uploads/2020/09/Bird-Dog-Breeds.jpg\",\"https://www.luvbat.com/uploads/cat_sitting_sofa_like_a_human__8697470286.jpg\",\"https://www.hdnicewallpapers.com/Walls/Big/Cat/Grey_Color_Cat_Pretty_Wallpaper.jpg\",\"https://cattime.com/assets/uploads/2012/07/abyssinian-cat.jpg\",\"http://buzzsharer.com/wp-content/uploads/2015/05/beautiful-running-horse.jpg\",\"https://www.k9web.com/wp-content/uploads/2020/08/dorkie-dog.jpg\",\"http://oddstuffmagazine.com/wp-content/uploads/2017/11/dog-hats-650x817.jpg\",\"http://buzzsharer.com/wp-content/uploads/2016/03/smiling-corgi.jpg\",\"https://www.hdnicewallpapers.com/Walls/Big/Horse/Animal_Horse_Wallpaper.jpg\",\"https://assets.horsenation.com.s3.amazonaws.com/wp-content/uploads/2015/10/buddy-sour.jpeg\",\"https://d.newsweek.com/en/full/1614423/newsweek-amplify-cat-crying-help.png\",\"https://images.hellogiggles.com/uploads/2017/08/26081306/green-cat.png\",\"http://www.thegaitpost.com/wp-content/uploads/a-horse-being-unloaded-at-a-control-post-2.jpg\",\"https://www.chapmanvalleyhorseriding.com/wp-content/uploads/2015/10/HalloweenHorses-31.jpg\",\"https://www.thedogword.com/application/files/9615/5244/3242/Vizsla8.jpg\",\"http://theawesomedaily.com/wp-content/uploads/2018/02/rarest-horse-breeds-of-the-world-feat-1-620x350.jpg\",\"http://cdn0.wideopenpets.com/wp-content/uploads/2016/03/dog.jpg\",\"https://moderndogmagazine.com/sites/default/files/images/uploads/smilingdogs_ziva.jpg\",\"https://inhabitat.com/wp-content/blogs.dir/1/files/2013/03/horse-laughing.jpg\",\"https://www.rover.com/blog/wp-content/uploads/2019/11/cat-4204883_1920.jpg\",\"https://d.ibtimes.co.uk/en/full/1654558/pet-cat.jpg\",\"http://themeowpost.com/wp-content/uploads/2016/04/3-derpy-faced-cat.jpg\",\"http://vancouver.ca/images/cov/feature/license-and-leash-your-dog-facebook.jpg\",\"https://www.journalism.co.uk/assets/33/The_lonan_tweed_dog_coatv1.jpg\",\"https://www.historicmysteries.com/wp-content/uploads/2016/10/Black-cat-superstition-.jpg\",\"https://mymodernmet.com/wp/wp-content/uploads/2018/12/dog-portraits-kristyna-kvapilova-7.jpg\",\"https://s3.amazonaws.com/adventureblogbucket/assets/uploads/2019/02/06065639/social-media-Icelandic-horse.jpg\",\"https://img.dog-learn.com/dog-breeds/thai-ridgeback/thai-ridgeback-i3.jpg\",\"http://pulpbits.net/wp-content/uploads/2014/02/persian-cat-breeds-12.jpg\",\"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Tonkinese_Cat_-_Leo.jpg/1200px-Tonkinese_Cat_-_Leo.jpg\",\"http://www.photoaxe.com/wp-content/uploads/2007/12/cat16.jpg\",\"http://horsetvlive.com/wp-content/uploads/2018/08/4-friesian-horse-breeds-in-the-world-youtube-thumbnail.jpg\",\"http://www.freshboo.com/wp-content/uploads/2014/04/beautiful-horse.jpg\",\"https://images.wagwalkingweb.com/media/daily_wag/name_guides/%7Bslug%7D/hero/1537890338.6/bahamas-dog-names.jpg\",\"https://hdwallpapers.move.pk/wp-content/uploads/2015/02/beautiful-horse-style.jpg\",\"http://i.huffpost.com/gen/1279774/images/o-PRZEWALSKIS-HORSE-facebook.jpg\",\"http://www.sott.net/image/s22/446941/full/Dog_in_mourning_Helping_our_pe.jpg\",\"http://news.nationalgeographic.com/content/dam/news/2017/06/09/waq-cat-tail/01-cat-tail.ngsversion.1496936927104.adapt.1900.1.jpg\",\"http://ourauckland.aucklandcouncil.govt.nz/media/6466/dog-reg-dog.jpg\",\"http://barkpost.com/wp-content/uploads/2014/04/saddogcomputer.jpg\",\"https://petsfeed.co/wp-content/uploads/2020/12/Chat-Kinkalow-cat.jpg\",\"https://horsespirit.site/wp-content/uploads/2020/03/amqh4-1024x683.jpg\",\"https://images2.minutemediacdn.com/image/upload/c_fill,g_auto,h_1248,w_2220/f_auto,q_auto,w_1100/v1555345877/shape/mentalfloss/istock_000072600763_small.jpg\",\"https://images.wagwalkingweb.com/media/daily_wag/name_guides/%7Bslug%7D/hero/1543366264.59/nebraska-dog-names.jpg\",\"https://www.aspca.org/sites/default/files/cat-care_destructive-scratching_main-image.jpg\",\"https://www.readersdigest.ca/wp-content/uploads/2020/11/most-popular-dog-breeds-portuguese-water-dog.jpg\",\"https://www.erblicken.com/wp-content/uploads/2016/06/Funny_Ben.jpg\",\"https://thehorse.com/wp-content/uploads/2017/09/dressage-horse-with-tight-noseband.jpg\",\"https://wallup.net/wp-content/uploads/2016/01/201852-animals-cat-depth_of_field-bricks-Siamese_cats.jpg\",\"https://weneedfun.com/wp-content/uploads/2016/02/Andalusian-Horse-7.jpg\",\"https://www.petpaw.com.au/wp-content/uploads/2013/02/Toyger-male-cat-1030x748.jpg\",\"https://www.aspca.org/sites/default/files/cat-care_aggression-in-cats_main-image.jpg\",\"https://www.dogvills.com/wp-content/uploads/2020/02/most-dominant-dog-breeds-a.jpg\",\"http://manydifferences.weebly.com/uploads/1/7/5/5/17557043/8977268_orig.jpg\",\"https://thefunnybeaver.com/wp-content/uploads/2020/08/adorable-cat-back.jpg\",\"https://biggsinsurance.com/wp-content/uploads/2017/04/Dog-angry.jpg\",\"https://thebark.com/sites/default/files/content/article/full/simba-smiling-dog-large.jpg\",\"https://www.unilad.co.uk/wp-content/uploads/2017/12/bernese-mountain-dog-208092_1920.jpg\",\"https://s.equimed.com/images/335/1024/0/0.jpg\",\"https://ourdeer.b-cdn.net/wp-content/uploads/2020/06/Dog-Breeds-for-Families-Beagle.jpg\",\"https://miro.medium.com/max/10368/1*ES15OJWo_LhqzYSI2JYanA.jpeg\",\"http://cdn0.wideopenpets.com/wp-content/uploads/2016/02/horse-1.jpg\",\"https://petpress.net/wp-content/uploads/2020/05/siame-cat-1.jpg\",\"http://www.freshboo.com/wp-content/uploads/2014/04/beut-horse.jpg\",\"https://cdn.thewirecutter.com/wp-content/uploads/2018/03/dog-toys-blog-lowres-3-630x420.jpg\",\"https://www.top13.net/wp-content/uploads/2015/01/sitting-cat7.jpg\",\"https://scitechdaily.com/images/Cat-COVID-19-Mask.jpg\",\"http://www.zastavki.com/pictures/originals/2013/Animals___Horses_Horse_galloping_053620_.jpg\",\"https://images.wallpaperscraft.com/image/horse_brown_look_123607_938x1668.jpg\",\"https://www.south.is/static/gallery/icelandic-horse/picture-079-1-.jpg\",\"https://pixfeeds.com/images/cats/1280-147094961-siamese-cat.jpg\",\"https://welovecatsandkittens.com/wp-content/uploads/2017/05/Simply-adorable.jpg\",\"https://pyxis.nymag.com/v1/imgs/1fa/1b2/4ae76fa8c9910485045e4f9a956345903b-18-puppy-dog-eyes.rsquare.w700.jpg\",\"http://moderndogmagazine.com/sites/default/files/images/uploads/stardog_starr.jpg\",\"https://aikmanwildlife.com/wp-content/uploads/2019/12/draft_horse_product.jpg\",\"https://flashbak.com/wp-content/uploads/2017/04/cat-001.jpg\"],\"x\":{\"__ndarray__\":\"qGyN8EDCl7+ojwhfCMO0v7I+GFx3v8i/FCoaxToYx7/4V4REvXzmv1Va1XPORsI/Mg3a8n2j57+MRCIV8ljuvxB/GB9D2+a/pKznC62Vuj+VjqmpFlXUP9DryPge3Km/BOpFVdRk5L+YZ7ZZh8bmvygrMBw9Gn4/UwjyfIW83r+M1Tuo99HZv8uIFRC9m+u/QAQtMzKrRr+ckD/ms9Djv66cCnOLDOS/wcYGlVLk1r/agnji+57Jv5aUsUDq1ry/7mNqlVjE6j8GvtPWORPVv7+67Q97mtc/RZp5OaJM17+9NL4OnLHaP0gjq1fR3+I/4S113p3O4r/gorUzSZDmP1Lv1fazc+6/1C7smVio6D8BPajuDGHqP57llItnv+I/3NoqUe4Fwj823VWXg6bfv0u7ssqNmLy/oP3xhIZstD+x0f+Q/RDkP45a9NFq5rq/FHq9cg6G7b+03fuRm6PiP6DTFtFCbJi/62sDhfYtw7/uw49spJnlvySsHNJNguM/oBy/D7tEvD+mMJ9bWOroPzbF2YYQMdW/jGjBoJC47b8AzjXBGCh6PyLxNcP/+Os/hSwsyPdb7D89OQ+MFAXhP01Ugdj49OE/6eurmawY0j/UHm0+chXsP/6/NIIkUe0/LhIB13bO3z9cwvjb0xq5P///xK8nV7m/mi2oI4fr1b9tNcZtc6Dnv6o3FHoOXe2/NPK4P+Nitr9YCTfURtKpP6yXMvYq3tE/2FQVzpyn5j/8VKL18/rCvzlx7UZAFNc/qL3bjpnL1j+gjCmWtuHLvwtD3m4vlu6/6nwie4VqyT/dj6FbpQPXP1hYyRQk+3e/KbMRs0KC2D8hj9DEBgfiv6xRi/WL7uQ/rFVLesEavb9tnySC466cP2qwF1WcYas/oMkzYUDwmj+qykXQE17Hv15qUurNpOk/IFWncEIW0r+9LXwY1aHNv6B+azltuZy/xjaO6+t2xj9GN74c7fTXP4whq15B+eA/sOBPbUwEy7+ert7ZkKbiP1i+5zSzHdm/aDg2aB36tb9wnhIv0Ktwv8n8vvORf+k/LXvOHhWt6b830yY8QDThvwbgTGJ4yuS/+bI4B/AG1j99I3GEZ7Dav4lxPn+RteG/7K4GNIfriT+x4IcFcV3YPz3erhVXTuo/iP49EjxP1T+MOaRAe7PJP4bFW5/xR+I/fc6g3NPH6j9YYW+aZwPHPyMucdNioOo/IAGLYHjXvr+QG1QNiSLnP2E5yUqwyOy/WJzC7sD1cr+g+5KPueDeP9FYD1zapN8/aFgQAnsB2r/kYlFCzIXHv8MHwD8jduq/0xzR4cQC479XLCAAni/rv0RBRL1u/42/PAhKLU2L678jLlH6OT/hv+NL15kpjN6/Nxu1Wf2a6D/yEofdeE7WP+wguCtZc+E/gjzjwUALwz9j8ZNfQE3tv9hlpPVNSaW/JDOP8JrH2T/qxvke4+jkv0d3sgvH4Nc/GPyG8yibvj9+4QTaat/ZP4UxQ6mmaO2/HuYKwj7R5T+Sh76AnWTpvxzgELEKG+e/XUVv6XMgz7+6v4hdplrjP6rjuenAlMu/ifIHXvWg0D9VyQbiNWq7vzz2wV3xFps/PFtWiP72nL/qmqcpUK29P9Qa3PBJxK4/WP7FCjrLyr9wnIPinvPqP2jRvmsS1bI/cupbqskd6r/4YT+CXRXev0w0Jv6Aw+Q/dQbP61AB678kipCihBebP+B/ehOewrs/+qbb91ZBxr+YeaMw0MjTv3/U2WUuSOc/VLHV3QIKuz+wPbnMOmXJv80AZggdetq/cBSIjZXrxr8s8ItLquR1v5I1CZhW6ck/ZBQDXf65kL/wdnmzY22SP66MiNIkVdi/hsvGinsCxb8lJ/hbw+Ppv8Y+OphnpOG/uBcUfdps4L9oA82N86OcP0yPv8FikYM/ooP4JlBMvz+AiPmtsCZtv/YsdeZB/eW/HC0vVJ9t0T+867gxKEDZP55Q4DfmqLS/j8FG4wcP4j+8n2MRsQC9v/Iaa8q/1te/4AIQtlyfzD+43XcDgATTP62CAyMWSKm/QFFXv7tNzz862dlkjKPVv/Zm9yVs/+k/SFh+1nCt4T9CnL8DNq7UvxLfgWADetm/nHVYDeJl0L/ulhoNzqXOvx7Rm1NPmNY/wLJFCtfiST/fEfm17dnjvy3/4VTH+NM/9DCbMkHz17/4TxY/I03Sv0pDcUhzqrS/VKGDlYVKgj8rFX1GDZ/iv4SA+cyUeus/FJTmZlen4r9mZ1iqX7DKP0VHZKjgHem/CQdCui99679QECxjr1tnv8zcjM6JWqy/2NPdlvaf4D/ncy+Wj13nv17Y1DJsp+S/XjUiUdp07T8C8GcIZZjpv9pIqZ0SVsu/DJn2PGfK1D9phn8S2nfVPwB6xzfj92U/5FM+CYCzzb+Wo7FF+qOTP7yAt8Uah+2/RA1ixmrO4D8h0/ytt3nSP6pYKjPP2+u/2IvdDEOz4b/YIlIdm3KbP4sb6HUTl+g/KhLQvDq93r/OqhqEAgGxv1485GdLgck/u8srCOFtsD94SPf3kq2SPwKLVSTgmOO/vqTvv7FIzT/QvDmfdEiqv7oeeTcdAp8/t/FmTvMs5r+A1x2oBAVkP5RKIneNUu0/jJubVSvgpD+MRIl2VQLLP9BalakD8ry/YBdo/nW53z9tOTmYY9HkPwLUI9e2bdg/3/f7peQ44L+nO/sWtK/nv80qGRhve9O/cNQ317a14j/gV051mS2PP2WZTj69f+a/Zl7VLTFm6T+EDFtDt1LHP+4tEkU9qeo/gI4igd1Pdb9Wq9l8ZhfIPyHUsZgC2sU/+Dx3LGgf4b80ushtKq3Yv+qJLK66Z9s/zU7Lp4Fj5j9fOZR59wHrP6OfVFF3RtS/iQW2Yegr57/Cw6uOFmjlP6beSxDNBcs/IkRBeXPJyD+HriTIVt7rv8x5izcwebc/ELu7WCfuv7+RXK5TJdnTP/wLi/+uN+i/ppryLkuH079gXt8DT3vfv9T1H2Z8oeK/h/HjMUA817+qr9Tp0LyJP+lIkaTx2eW/kGwzJcQF3b+NP1T1Sie3v1x9hvEfWrO/oP6dAPMf2b9GvT7qhV6yvxeJH7BSk9c/vwR/8fwF579ilJzKmGzQP8BwqtDoIm4/Bun1a7y237/8jMM/zNzrP8Crd/X8ud4/wHtubn6L5b/gfci0THWTv5BP9Y97qeg/dK4ZrLktsL8/gWlQm5bavxl01IPWzuc/dj0CuQTq2z/QYxyJrajSvwAiNEgxHbi/JN4uuQUb17+ONuKf0FzIP6PgEixFqeC/wAvVwolV1L8OCHdO6cnkP4OWOikQ/9a/9E7va42s6L9QvKgVkhmnv7bJ6kE3zOU/oeZiqH9T3L8QNPiAmFujP/Nx511tTtG/AUBRAJFiqz9KxBue/OXePxlqb6xE2da/MPY1mOg9qz80T06i5+TNvzybrWy98sU/4ldIu8RA4D90VjlWLZrMv7sr8FgQ0ea/Jqh0U1SS4L8WPqAKxD7Iv1b2kpCKm9Y/hB7tQxlr7j+H79qb68/gP8iUCQL+Q3s/APH3wTroOb9QeURE9Oztv4L7PMvkP+O/+jCd8ga12j+IzGnSw3rTP2DBvHwYcdc/uzkUMP3fwj/zQwbwph3cP6JFdOzEV+M/SZfg4e+73D/uDfsD6/jDv7nnXjQuqOC/XQoAjrcU7789iUmpoYbYPzdmmh/MpNQ/5OwqRnSb5r92wFiuyS/hP9jdyZzPvrw/wsE+S2ml3T/q74HRQevLv4pe21xfXOO/Jr4eKhU/6L8Y/7b3gR6zP8A2aD1je5a/9NMIJ4DA2D9idttM1YTHP6Z/Q6aT45Q/RHayTz4l4T9wPradQIuQv4zN8PqJKdk/0jY+AHoqwD8DNAtqt1bpvwqizNUV1a4/fIkEPeBe7r/wCFI95ru+P/nAV5SgGu2/unRvosSE4j8c5mjKzVzrPxZAGZtBG7Q/KaXM6oI+7L+w0qxPfEfGvyNTsw3Ucty/8kwqN5oP378t6sKbO67dP8RLXFqjJsA/sThwVjJt47/i72qjNAXOPzGTb1WIeek/BCcx891n3D9AZX+/9uivv/74FtCXydY/ATNV+6ph0D/Y3RJuC+rNv7SJa7TVWri/A0E7iMLB1D+19z21tsTqP4hpX3OP2eW/QwV7QFdz678g9wpt98Sjv+SH1HXeGtQ/RsiYiZ7jsT9hq3qpQ1Hcv/ihTbJALs+/aFkyUwzB6D/0t+Xgq8vAP1BYdi41vq6/ER/5gkhc6r8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[400]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[400]}},\"selected\":{\"id\":\"1075\"},\"selection_policy\":{\"id\":\"1076\"}},\"id\":\"1052\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"line_alpha\":0.1,\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1044\",\"type\":\"Line\"},{\"attributes\":{\"line_alpha\":0.1,\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1039\",\"type\":\"Line\"},{\"attributes\":{\"data_source\":{\"id\":\"1047\"},\"glyph\":{\"id\":\"1048\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1049\"},\"view\":{\"id\":\"1051\"}},\"id\":\"1050\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1007\",\"type\":\"DataRange1d\"},{\"attributes\":{\"fill_color\":{\"field\":\"colors\"},\"line_color\":{\"field\":\"colors\"},\"size\":{\"value\":6},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1054\",\"type\":\"Circle\"},{\"attributes\":{\"source\":{\"id\":\"1047\"}},\"id\":\"1051\",\"type\":\"CDSView\"},{\"attributes\":{\"data\":{\"x\":[0,-0.5],\"y\":[0.333,0.5]},\"selected\":{\"id\":\"1073\"},\"selection_policy\":{\"id\":\"1074\"}},\"id\":\"1047\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"1009\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"1065\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"1064\",\"type\":\"AllLabels\"},{\"attributes\":{\"line_alpha\":0.1,\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1049\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1073\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"field\":\"colors\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"field\":\"colors\"},\"size\":{\"value\":6},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1055\",\"type\":\"Circle\"},{\"attributes\":{\"data\":{\"x\":[0,0.5],\"y\":[0.333,0.5]},\"selected\":{\"id\":\"1071\"},\"selection_policy\":{\"id\":\"1072\"}},\"id\":\"1042\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"1062\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"text\":\"horse\",\"text_align\":\"center\",\"x\":0,\"y\":1},\"id\":\"1060\",\"type\":\"Label\"},{\"attributes\":{},\"id\":\"1067\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"1074\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"overlay\":{\"id\":\"1027\"}},\"id\":\"1023\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"axis\":{\"id\":\"1013\"},\"ticker\":null},\"id\":\"1016\",\"type\":\"Grid\"},{\"attributes\":{\"formatter\":{\"id\":\"1062\"},\"major_label_policy\":{\"id\":\"1064\"},\"ticker\":{\"id\":\"1018\"}},\"id\":\"1017\",\"type\":\"LinearAxis\"},{\"attributes\":{\"text\":\"dog\",\"x\":1,\"y\":0},\"id\":\"1059\",\"type\":\"Label\"},{\"attributes\":{\"data_source\":{\"id\":\"1042\"},\"glyph\":{\"id\":\"1043\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1044\"},\"view\":{\"id\":\"1046\"}},\"id\":\"1045\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"data_source\":{\"id\":\"1037\"},\"glyph\":{\"id\":\"1038\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1039\"},\"view\":{\"id\":\"1041\"}},\"id\":\"1040\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"data_source\":{\"id\":\"1052\"},\"glyph\":{\"id\":\"1054\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1055\"},\"view\":{\"id\":\"1057\"}},\"id\":\"1056\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1018\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"1026\",\"type\":\"HelpTool\"},{\"attributes\":{\"data\":{\"x\":[0,0],\"y\":[0.333,0]},\"selected\":{\"id\":\"1069\"},\"selection_policy\":{\"id\":\"1070\"}},\"id\":\"1037\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"1011\",\"type\":\"LinearScale\"},{\"attributes\":{\"text\":\"cat\",\"text_align\":\"right\",\"x\":-1,\"y\":0},\"id\":\"1058\",\"type\":\"Label\"},{\"attributes\":{},\"id\":\"1005\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1069\",\"type\":\"Selection\"},{\"attributes\":{\"text\":\"Mouse over the dots\"},\"id\":\"1003\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"1025\",\"type\":\"ResetTool\"},{\"attributes\":{\"active_multi\":null,\"tools\":[{\"id\":\"1021\"},{\"id\":\"1022\"},{\"id\":\"1023\"},{\"id\":\"1024\"},{\"id\":\"1025\"},{\"id\":\"1026\"},{\"id\":\"1028\"}]},\"id\":\"1029\",\"type\":\"Toolbar\"}],\"root_ids\":[\"1002\"]},\"title\":\"Bokeh Application\",\"version\":\"2.3.1\"}};\n", " var render_items = [{\"docid\":\"e9cffe58-a904-44c8-8b93-010270816851\",\"root_ids\":[\"1002\"],\"roots\":{\"1002\":\"0c371ac0-dec0-4df8-bbb8-bcc827729e71\"}}];\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", " clearInterval(timer);\n", " embed_document(root);\n", " } else {\n", " attempts++;\n", " if (attempts > 100) {\n", " clearInterval(timer);\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", " }\n", " }\n", " }, 10, root)\n", " }\n", "})(window);" ], "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { "application/vnd.bokehjs_exec.v0+json": { "id": "1002" } }, "output_type": "display_data" } ], "source": [ "urls = exhibit_urls(targ, labels)\n", "TrianglePlot2D_Bokeh(prob, targ=targ, labels=labels, show_bounds=True, urls=urls).do_plot()" ] }, { "cell_type": "markdown", "metadata": { "id": "xrDhkiph9c5t", "slideshow": { "slide_type": "subslide" } }, "source": [ "## Traditional Classification Training (Cartoon)\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "...tries to collapse all points to each \"pole\"." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "scrolled": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# generate and save images that we'll load in the next cell \n", "import matplotlib.pyplot as plt\n", "\n", "# generate data along boundaries\n", "def gen_bound(x, y, z, n=20, ind0=1): # ind0=1 skips the \"first point\"\n", " return np.linspace(np.array([x[0],y[0],z[0]]), np.array([x[1],y[1],z[1]]), num=n+ind0)[ind0:]\n", " \n", "def gen_bound_data(n_per=20, ind0=0):\n", " bdata = np.zeros((n_per*3,3))\n", " bdata[:n_per] = gen_bound(x=[0.333,0.5], y=[0.333,0.5], z=[0.333,0], n=n_per, ind0=ind0) \n", " bdata[n_per:2*n_per] = gen_bound(x=[0.333,0], y=[0.333,0.5], z=[0.333,0.5], n=n_per, ind0=ind0)\n", " bdata[-n_per:] = gen_bound(x=[0.333,0.5], y=[0.333,0], z=[0.333,0.5], n=n_per, ind0=ind0)\n", " return bdata\n", "\n", "def gen_near_bound_data(n_per=50, scale=7, eps=0.01):\n", " bdata = gen_bound_data(n_per=n_per)\n", " lower, right, left = bdata[0:n_per,:], bdata[n_per:2*n_per,:], bdata[-n_per:,:]\n", "\n", " # shift data a bit\n", " lower_catty = softmax( scale*(lower+np.array([eps,0,0])) )\n", " lower_doggy = softmax( scale*(lower+np.array([0.0,eps,0])) )\n", "\n", " left_catty = softmax( scale*(left+np.array([eps,0,0])) )\n", " left_horsey = softmax( scale*(left+np.array([0,0,eps])) )\n", "\n", " right_horsey = softmax( scale*(right+np.array([0,0,eps])) )\n", " right_doggy = softmax( scale*(right+np.array([0,eps,0])) )\n", "\n", " return np.vstack((lower_catty, lower_doggy, left_catty, left_horsey, right_horsey, right_doggy))\n", "\n", "# move boundary a bit toward the \"correct\" side\n", "eps = 0.007\n", "acc_data = gen_near_bound_data(eps=eps)\n", "btarg = np.argmax(acc_data, axis=-1)\n", "TrianglePlot2D_MPL(acc_data, targ=btarg, show_bounds=True, labels=labels, comment='100% Accuracy:').do_plot()\n", "plt.savefig(\"images/acc_100.png\")\n", "\n", "# move boundary a bit toward the \"wrong\" side (keeping labels the same as before)\n", "inacc_data = gen_near_bound_data(eps=-eps)\n", "ibtarg = btarg.copy()\n", "TrianglePlot2D_MPL(inacc_data, targ=ibtarg, show_bounds=True, labels=labels, comment='0% Accuracy:').do_plot()\n", "plt.savefig(\"images/acc_0.png\")\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Loss vs. Accuracy\n", "\n", "*Loss*: distance from target (continuous)
\n", "*Accuracy*: % of points on the correct side of decision boundary (discontinuous)
\n", "
\n", "**Nearly identical losses:**
\n", "\n", "           \n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "SF2JYmvC9Wm5", "slideshow": { "slide_type": "subslide" } }, "source": [ "### 4 Classes in 3D: form a pyramid!" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "np.random.seed(1)\n", "prob4, targ4 = calc_prob(n=500, s=2.7, dim=4) # 4d probabilities\n", "prob4, targ4 = np.vstack((np.eye(4),prob4)), np.hstack((np.arange(4),targ4)) # tack on poles b4 pca\n", "prob3 = pca_proj(prob4) # use PCA for coordinate transformation to 3D hyperplane" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "hideCode": true, "id": "6wspP59I9Tdg", "outputId": "7e5bcbb4-ee5f-442b-a048-69fbd55aa162", "scrolled": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot = TrianglePlot3D_Plotly(prob3, targ=targ4, labels=labels+['bird'], show_labels=True, show_axes=False, poles_included=True)\n", "plot.fig.update_layout(scene_camera=dict( eye=dict(x=1.5, y=1, z=0.7)))\n", "plot.do_plot()" ] }, { "cell_type": "markdown", "metadata": { "id": "pYWmcVAf9kR5", "slideshow": { "slide_type": "slide" } }, "source": [ "## Metric-Based Embedding Methods, OTOH...\n", "\n", "...map similar points near each other, dissimilar points far away. => Clusters:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "import plotly.graph_objects as go\n", "def noop(x): return x \n", "\n", "def plot_clusters(dim=3, nclasses=4, nper=100, func=noop):\n", " np.random.seed(6)\n", " clusters = np.zeros((nclasses*nper,dim))\n", " colors = ['red','green','blue','orange']+['black']*max(nclasses-4,0)\n", " labels = ['cat','dog','horse','bird']+['aux']*max(nclasses-4,0)\n", " fig = go.Figure()\n", " for i in range(nclasses):\n", " mean, cov = 0.8*np.random.rand(dim), 0.002*np.eye(dim)\n", " cluster = func(np.random.multivariate_normal(mean, cov, nper))\n", " clusters[i*nper:(i+1)*nper] = cluster\n", " fig.add_trace( go.Scatter3d(x=cluster[:,0], y=cluster[:,1], z=cluster[:,2], hovertext=labels[i], name=labels[i], \\\n", " mode='markers', marker=dict(size=5, opacity=0.6, color=colors[i])))\n", " fig.update_layout(margin_t=0, scene_camera=dict( eye=dict(x=0.7, y=0.7, z=0.7)))\n", " fig.show(config = {'displayModeBar': False})\n", " return clusters" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "hideCode": true, "id": "XF-LZfam9mqC", "outputId": "efbfbab7-e76c-441e-ac9c-5b4af15c4819", "scrolled": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "clusters = plot_clusters() " ] }, { "cell_type": "markdown", "metadata": { "id": "JgH1ZREO9qRS", "slideshow": { "slide_type": "subslide" } }, "source": [ "## Contrastive Loss\n", "Like attracts like; \"Opposites\" repel:\n", "
\n", "Tends to group things in \"semantically meaningful\" ways." ] }, { "cell_type": "markdown", "metadata": { "id": "JgH1ZREO9qRS", "slideshow": { "slide_type": "notes" } }, "source": [ "This picture of springs is the essence of a \"[contrastive loss](https://arxiv.org/abs/2004.11362)\" function. Unlike traditional ML classification where the loss is based on the \"distance\" to a \"target\" (or \"ground truth\") value, with these metric based methods we send in two (or even 3) data points together, and then either let them attract or repel each other, and we do this over and over and over until we reach some stopping criterion. Eventually, what we'll have is a space that contains clusters of similar points, separated by a \"margin\" distance that we specify." ] }, { "cell_type": "markdown", "metadata": { "id": "5KgVawNp90FM", "slideshow": { "slide_type": "subslide" } }, "source": [ "## Siamese Networks\n", "\n", "*Identical twin* network branches map to points (\"feature vectors\") in N-dim space:\n", "\n", "
\n", "\n", "

Example of a Siamese Network (source: Sundin et al)

\n", "
\n" ] }, { "cell_type": "markdown", "metadata": { "id": "UQRVkgzy94qB", "slideshow": { "slide_type": "subslide" } }, "source": [ "## How well do they work?\n", "\n", "Traditional vs. zero(/few)-shot methods: which one wins? *It depends.*\n", "\n", "From high-scoring Kaggle competition entry using \"[entity embeddings](https://arxiv.org/abs/1604.06737)\":\n", "\n", "> \"Entity embedding not only **reduces memory usage** and **speeds up neural networks** compared with one-hot encoding, but more importantly by mapping similar values close to each other in the embedding space it **reveals the intrinsic properties of the categorical variables**.\"\n", "\n", "Let's look at \"PETS,\" via [my mod](https://colab.research.google.com/drive/1rSTOsj4coDu9mZCw57S7R6jBipm462R2?usp=sharing) of [FastAI's tutorial](https://docs.fast.ai/tutorial.siamese.html) on Siamese Networks... " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Zero-Shot & Few-Shot\n", "**Cool thing:** Embedding function tends to work for classes **never seen before** \n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "So, for example, the embedding learned for grouping images of cats, dogs, and horses together would map images of birds to nearby points in the space. Then \"all we have to do\" if we want to predict a class is see whether a new instance is \"nearby\" (according to some distance measure we decide) to other similar points. We could even look at the \"center points\" of various clusters and regard these as the \"class prototype\" and use that in the future.\n", "\n", "This fits (somewhat) with the notions of \"prototypes\" in human classification advanced by Eleanor Rosch in her revolutionary psychology work in the early 1970s. We can say more about this later. ;-) " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "This same method of contrastive losses and metrics is used not for classification *per se* but for things like photographic identity verification (an example that is given in Andrew Ng's Machine Learning course on Coursera): Say you want to have a facial recognition system (highly problematic for ethical reasons but it's a good example of the method so bear with me) for a company where there can be turnover in employees: You probably don't want to train a traditional classifier with separate a class for each employee because then you'd have to re-train it every time someone joins or leaves the company. Instead, you can store an image of each employee, and then when they appear in front of a camera for identity verification, you could compare the \"distance\" between the embedded data point for the new photo from the data point for the stored photo(s). If the distance is small enough, then you can have confidence it's the same person." ] }, { "cell_type": "markdown", "metadata": { "id": "SAMnLUYKKUEJ", "slideshow": { "slide_type": "notes" } }, "source": [ " \n", "\n", "What's nice about this is that, after you've trained your embedding system, it can typically still be used to measure similarity between pairs of things it's never seen before, because in the process of training it was forced to learn \"semantically meaningful\" ways of grouping points together. This use of the linguistic work \"semantic\" is not accidental: the language model systems that rely on \"word embeddings\" can learn to group similar words together, and even have mathematical-like relationships in analogies (e.g., gender: \"king - man + woman = queen\", or countries-and-capitals: \"Russia - Moscow + France = Paris\") by treating the embedded data points as *vectors* that point from the origin of the coordinate system to the data point. We can say more about this and the distance metric they use (\"cosine similarity\") another time.\n", "\n", "\n", "So in using metric-based learning for classification, we're essentially adopting this identity-verification app and applying it to entire classes instead of individuals." ] }, { "cell_type": "markdown", "metadata": { "id": "pMXCcMhI7E8U", "slideshow": { "slide_type": "slide" } }, "source": [ "## Final thoughts\n", "* 3D for teaching: robust yet viz-able, can help re. loss & accuracy\n", "* Embeddings are just mappings to points in space\n", "* Contrastive losses help give semantically meaningful embeddings\n", "* Note that real-world embeddings often require >> 3D (e.g. 128D)\n", "* `mrspuff` lib TODO: \n", " * Live tracking of data points during training\n", " * Real images for points \n", " * Add URLs to FastAI image data type / bunch / loader\n", "\n", "## Acknowledgements\n", "Thanks to [Zach Mueller](https://twitter.com/TheZachMueller), [Tanishq Abraham](https://twitter.com/iScienceLuvr) and [Isaac Flath](https://twitter.com/isaac_flath) for help with fastai! " ] }, { "cell_type": "markdown", "metadata": { "id": "pMXCcMhI7E8U", "slideshow": { "slide_type": "subslide" } }, "source": [ "## References:\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Slideshow", "colab": { "collapsed_sections": [], "name": "2021-04-11-The-Joy-Of-3D.ipynb", "provenance": [] }, "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.8.6" }, "rise": { "autolaunch": true } }, "nbformat": 4, "nbformat_minor": 1 }