Deep Dream with Containers

If you haven’t heard of Google Deep Dream — check it out! In a nutshell, it “[turns] the [neural] network upside down … to enhance an input image in such a way as to elicit a particular interpretation”. Or, simply, it visualizes how a neural network sees and finds patterns that it was trained to recognize.

Photography is my hobby. When I finally had free time, I decided to generate Deep Dream images from some of my photos on Flickr.

Original on Flickr.

A Deep Dream Nightmare

Deep Dream source code is on GitHub. I thought it would be easy to just download, install, and run it. But it turned out to be much harder — there are no instructions on how to run the source code, nor how to install the dependencies.

There were plenty of Deep Dream installation instructions circulating on the web, but each was slightly different, and mostly were complicated. The most complex dependency to install was Caffe.

Rather than installing the software only once on my laptop, I also wanted to run it in virtual machines as well. I needed to have consistent and reproducible builds of the Deep Dream dependencies so I could run it anywhere.

Docker to the Rescue

Docker came into my mind immediately. With Docker, I can write all of the installation steps/commands in a Dockerfile, and Docker will follow the instructions to build all of the dependencies and install the Deep Dream source code. The end result is a Docker container image that is portable — I can run it locally, or in any virtual machine that runs Docker.

My Deep Dream Dockerfile is on GitHub. It will:

  1. Install dependencies that are required to compile Caffe
  2. Compile and install Caffe
  3. Install dependencies that are required by Deep Dream
  4. Install the latest version of IPython Notebook
  5. Download the neural network model
  6. Set up necessary environment variables
  7. Finally, start IPython Notebook
Original on Flickr.

Docker Machine

I’ve learned firsthand how unpleasant it can be to download Docker images and push images over low bandwidth connections.

Rather than building and pushing Docker images locally with boot2docker, I’ve been using Docker Machine on Google Compute Engine for the past couple of months.

Check out my other article on how I set up Docker Machine on Google Compute Engine.

Before Dreaming

Before dreaming with Deep Dream, you need to build the container:

$ git clone https://github.com/saturnism/deepdream-docker
$ cd deepdream-docker
$ docker build -t deepdream .
...
Successfully built ...

To run it:

$ docker run -p 8888:8888 -v /tmp:/deepdream/deepdream/files -ti deepdream
[I 03:25:07.724 NotebookApp] Created profile dir: u'/root/.ipython/profile_default'
...
[I 03:25:07.741 NotebookApp] The IPython Notebook is running at: http://[all ip addresses on your system]:8888/
[I 03:25:07.741 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

If you are using Docker Machine on a remote host, make sure you allow port 8888 access (learn how in my article on using Docker Machine in Google Compute Engine).

You should now be able to access your Deep Dream notebook by browsing to the Docker server on port 8888.

http://xxx.xxx.xxx.xxx:8888/notebooks/dream.ipynb

And you’ll see something like this:

IPython Notebook

Your First Deep Dream

You can use the default images, and start from the top and run every cell in the IPython Notebook:

Click on the Run Cell button to run the Deep Dream code. You’ll need to run through all of it!

This will generate pretty cool images from the defaults.

The fun really starts when you use your own image! To use your own image, you can copy the image into the Docker host’s /tmp directory (since that’s how we mounted it — feel free to change it). If you run a Docker container locally, simply copy the file over:

$ cp myimage.jpg /tmp

If you use Docker Machine, then you can use`docker-machine scp`:

$ docker-machine scp myimage.jpg mydockermachine:/tmp

If you scroll down in the IPython Notebook, you can replace the image file with the file you uploaded. You’ll need to click the Run Cell button again:

And start Deep Dreaming!

Generate a Deep Dream Video

Now that you know the basics, you can have a lot of fun with the Deep Dream IPython Notebook! For example, you can use one of the code snippets to generate 100 frames (or more) by recursively feeding Deep Dream its own output and applying a little zoom to it. It will “[lead] to an endless stream of impressions of the things that the network saw during training”, and some pretty cool images.

You can then copy all of the generated frames out of the container:

$ docker cp containerid:/deepdream/deepdream/frames ~/

And stitch them together using ffmpeg to produce a Deep Dream video:

$ ffmpeg -framerate 30 -pattern_type glob -i '*.jpg' -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4

Easiest Way to Deep Dream

Running IPython Notebook and using the UI to create Deep Dream images can be rather cumbersome. I needed an easy way to be able to create Deep Dream images utilizing the CPUs in my Docker Machine on the Google Compute Engine. For that, I created a CLI-friendly Docker Container, and you and find the source on my GitHub under the deepdream-cli-docker repository.

To use it, first build the image:

$ git clone https://github.com/saturnism/deepdream-cli-docker.git
$ cd deepdream-cli-docker
$ docker build -t deepdream-cli .

Then you can generate Deep Dream images directly from the command line. It uses a couple of Tips and Tricks that I learned from using a Docker Machine that are handy ways to build containers that plays well with UNIX command line:

$ cat moon.jpg | docker run -i deepdream-cli > output.jpg
The Moon in Deep Dream. Original on Flickr

You can also experiment with some variables to Deep Dream at different neural network levels, with different iterations, and octaves. The resulting images may vary significantly:

$ cat myimage.jpg | docker run -i deepdream-cli -l conv2/3x3 -o 6 > output.jpg
The Moon in Deep Dream. Original on Flickr

Just like any command line tools, you can find all of the possible arguments here:

$ docker run deepdream-cli -h

Unfortunately, the Deep Dream process is single threaded. Having more CPUs does not reduce duration to generate a single image. You can, however, generate multiple images at a time to better utilize the resources. For example, to process all of the images under a directory:

for f in *.jpg; \
do { cat $f | docker run -i deepdream-cli > out_$f; } & \
done;