{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "xy2rgb.ipynb", "version": "0.3.2", "provenance": [], "collapsed_sections": [ "JndnmDMp66FL", "EOCfOPdCkmXW", "UjboH7xgp6pt", "6x-kPRJzisK7" ], "include_colab_link": true }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "accelerator": "GPU" }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "[View in Colaboratory](https://colab.research.google.com/github/tensorflow/lucid/blob/master/notebooks/differentiable-parameterizations/xy2rgb.ipynb)" ] }, { "metadata": { "id": "JndnmDMp66FL", "colab_type": "text" }, "cell_type": "markdown", "source": [ "##### Copyright 2018 Google LLC.\n", "\n", "Licensed under the Apache License, Version 2.0 (the \"License\");" ] }, { "metadata": { "id": "hMqWDc_m6rUC", "colab_type": "code", "colab": {} }, "cell_type": "code", "source": [ "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ], "execution_count": 0, "outputs": [] }, { "metadata": { "id": "GS4kqcEJuy5R", "colab_type": "text" }, "cell_type": "markdown", "source": [ "# Compositional Pattern Producing Networks for Feature Visualization\n", "\n", "This notebook uses [**Lucid**](https://github.com/tensorflow/lucid) to produce aesthetically pleasing feature visualizations using a [Differentiable Image Parameterization](https://distill.pub/2018/differentiable-parameterizations/#section-xy2rgb) called a **Compositional Pattern Producing Network** (CPPN).\n", "\n", "\n", "\n", "This notebook additionally demonstrates:\n", "\n", "* rendering videos of the training process of the CPPN generating the visualizations,\n", "* rendering videos of interpolating between sets of learned CPPN parameters\n", "* rendering high resolution visualizations from a set of CPPN parameters.\n", "\n", "\n", "This notebook doesn't introduce the abstractions behind lucid; you may wish to also read the [Lucid tutorial](https://colab.research.google.com/github/tensorflow/lucid/blob/master/notebooks/tutorial.ipynb).\n", "\n", "**Note**: The easiest way to use this tutorial is as a colab notebook, which allows you to dive in with no setup. We recommend you enable a free GPU by going:\n", "\n", "> **Runtime** → **Change runtime type** → **Hardware Accelerator: GPU**" ] }, { "metadata": { "id": "EOCfOPdCkmXW", "colab_type": "text" }, "cell_type": "markdown", "source": [ "## Install, Import, and load a model" ] }, { "metadata": { "id": "b-IocmWWvb_I", "colab_type": "code", "colab": {} }, "cell_type": "code", "source": [ "!pip install -q lucid>=0.2.3" ], "execution_count": 0, "outputs": [] }, { "metadata": { "id": "bYd1LKCCxeTd", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 145 }, "outputId": "2047001c-97fa-4a7f-9f4e-fa3ca53516c2" }, "cell_type": "code", "source": [ "# For video rendering\n", "\n", "!pip install -q moviepy\n", "!imageio_download_bin ffmpeg" ], "execution_count": 0, "outputs": [ { "output_type": "stream", "text": [ "Ascertaining binaries for: ffmpeg.\r\n", "Imageio: 'ffmpeg-linux64-v3.3.1' was not found on your computer; downloading it now.\n", "Try 1. Download from https://github.com/imageio/imageio-binaries/raw/master/ffmpeg/ffmpeg-linux64-v3.3.1 (43.8 MB)\n", "Downloading: 8192/45929032 bytes (0.0%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b663552/45929032 bytes (1.4%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b1867776/45929032 bytes (4.1%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b3637248/45929032 bytes (7.9%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b6168576/45929032 bytes (13.4%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b9486336/45929032 bytes (20.7%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b12820480/45929032 bytes (27.9%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b16310272/45929032 bytes (35.5%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b19849216/45929032 bytes (43.2%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b23289856/45929032 bytes (50.7%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b26828800/45929032 bytes (58.4%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b30261248/45929032 bytes (65.9%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b33767424/45929032 bytes (73.5%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b37216256/45929032 bytes (81.0%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b40755200/45929032 bytes (88.7%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b44318720/45929032 bytes (96.5%)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b45929032/45929032 bytes (100.0%)\n", " Done\n", "File saved as /content/.imageio/ffmpeg/ffmpeg-linux64-v3.3.1.\n" ], "name": "stdout" } ] }, { "metadata": { "id": "JEzrNW5lBUxr", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 17 }, "outputId": "d3b9bc79-4527-4f28-f218-e8514b9e8ab7" }, "cell_type": "code", "source": [ "from __future__ import print_function\n", "import io\n", "import string\n", "import numpy as np\n", "import PIL\n", "import base64\n", "from glob import glob\n", "\n", "import matplotlib.pylab as pl\n", "\n", "import tensorflow as tf\n", "from tensorflow.contrib import slim\n", "\n", "from IPython.display import clear_output, Image, display, HTML\n", "\n", "import moviepy.editor as mpy\n", "from moviepy.video.io.ffmpeg_writer import FFMPEG_VideoWriter\n", "\n", "\n", "from google.colab import files" ], "execution_count": 1, "outputs": [] }, { "metadata": { "id": "mUnwK7mYFFns", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 17 }, "outputId": "d3b2b3be-a564-4ad7-e6ba-c09b36e6877a" }, "cell_type": "code", "source": [ "from lucid.modelzoo import vision_models\n", "from lucid.misc.io import show, save, load\n", "from lucid.optvis import objectives\n", "from lucid.optvis import render\n", "from lucid.misc.tfutil import create_session" ], "execution_count": 2, "outputs": [] }, { "metadata": { "id": "pRnDsiHa7ZK1", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 17 }, "outputId": "1edbbcf9-b7c0-4252-b422-a68d49d9b7fb" }, "cell_type": "code", "source": [ "model = vision_models.InceptionV1()\n", "model.load_graphdef()" ], "execution_count": 3, "outputs": [] }, { "metadata": { "id": "h1_Kw_kNkzFu", "colab_type": "text" }, "cell_type": "markdown", "source": [ "## Setting up the CPPN " ] }, { "metadata": { "id": "f5b3ShqcGNET", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 17 }, "outputId": "c66dc068-23e8-49f7-a85e-306512851d65" }, "cell_type": "code", "source": [ "def composite_activation(x):\n", " x = tf.atan(x)\n", " # Coefficients computed by:\n", " # def rms(x):\n", " # return np.sqrt((x*x).mean())\n", " # a = np.arctan(np.random.normal(0.0, 1.0, 10**6))\n", " # print(rms(a), rms(a*a))\n", " return tf.concat([x/0.67, (x*x)/0.6], -1)\n", "\n", "\n", "def composite_activation_unbiased(x):\n", " x = tf.atan(x)\n", " # Coefficients computed by:\n", " # a = np.arctan(np.random.normal(0.0, 1.0, 10**6))\n", " # aa = a*a\n", " # print(a.std(), aa.mean(), aa.std())\n", " return tf.concat([x/0.67, (x*x-0.45)/0.396], -1)\n", "\n", "\n", "def relu_normalized(x):\n", " x = tf.nn.relu(x)\n", " # Coefficients computed by:\n", " # a = np.random.normal(0.0, 1.0, 10**6)\n", " # a = np.maximum(a, 0.0)\n", " # print(a.mean(), a.std())\n", " return (x-0.40)/0.58\n", "\n", "\n", "def image_cppn(\n", " size,\n", " num_output_channels=3,\n", " num_hidden_channels=24,\n", " num_layers=8,\n", " activation_fn=composite_activation,\n", " normalize=False):\n", " r = 3.0**0.5 # std(coord_range) == 1.0\n", " coord_range = tf.linspace(-r, r, size)\n", " y, x = tf.meshgrid(coord_range, coord_range, indexing='ij')\n", " net = tf.expand_dims(tf.stack([x, y], -1), 0) # add batch dimension\n", "\n", " with slim.arg_scope([slim.conv2d], kernel_size=1, activation_fn=None):\n", " for i in range(num_layers):\n", " in_n = int(net.shape[-1])\n", " net = slim.conv2d(\n", " net, num_hidden_channels,\n", " # this is untruncated version of tf.variance_scaling_initializer\n", " weights_initializer=tf.random_normal_initializer(0.0, np.sqrt(1.0/in_n)),\n", " )\n", " if normalize:\n", " net = slim.instance_norm(net)\n", " net = activation_fn(net)\n", "\n", " rgb = slim.conv2d(net, num_output_channels, activation_fn=tf.nn.sigmoid,\n", " weights_initializer=tf.zeros_initializer())\n", " return rgb" ], "execution_count": 4, "outputs": [] }, { "metadata": { "id": "Y46FuT_jTymC", "colab_type": "text" }, "cell_type": "markdown", "source": [ "Estimating the number of parameters of CPPN." ] }, { "metadata": { "id": "MmNfy9ItSZl6", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "outputId": "f2561b6c-edf9-4f6a-98e7-fb08d8c8fcab" }, "cell_type": "code", "source": [ "with tf.Graph().as_default():\n", " image_cppn(224)\n", " variables = tf.get_collection('variables')\n", " param_n = sum([v.shape.num_elements() for v in variables])\n", " print('CPPN parameter count:', param_n)" ], "execution_count": 36, "outputs": [ { "output_type": "stream", "text": [ "CPPN parameter count: 8451\n" ], "name": "stdout" } ] }, { "metadata": { "id": "NyoBLiF0BohH", "colab_type": "text" }, "cell_type": "markdown", "source": [ "Let's quickly sanity check that this CPPN can learn to produce an image with the properties we expect it to.\n", "As a simplistic test we try to fit the XOR function by imposing a loss on four corner points of the image." ] }, { "metadata": { "id": "3q4yq_O97m_Z", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 105 }, "outputId": "98948003-2952-484a-84a1-3915661480ad" }, "cell_type": "code", "source": [ "cppn_f = lambda: image_cppn(64)\n", "optimizer = tf.train.AdamOptimizer(0.01)\n", "\n", "def xor_objective(T):\n", " a = T('input')[0]\n", " return -(tf.square(a[0, 0]) + tf.square(a[-1, -1]) + \n", " tf.square(1.0-a[-1, 0]) + tf.square(1.0-a[0, -1]))\n", "\n", "vis = render.render_vis(model, xor_objective, param_f=cppn_f, optimizer=optimizer, transforms=[], thresholds=range(10), verbose=False)\n", "show(vis)" ], "execution_count": 0, "outputs": [ { "output_type": "display_data", "data": { "text/html": [ "