deeplearningを試す（caffe deepdream）

deepdreamを動かすところまでを記載します

## CUDA7.0インストール
https://developer.nvidia.com/


## open cvなどをインストール

```
$ brew install --fresh -vd snappy leveldb gflags glog szip lmdb
$ brew tap homebrew/science
$ brew install hdf5 opencv
$ brew install --build-from-source --with-python --fresh -vd protobuf
$ brew install --build-from-source --fresh -vd boost boost-python
$ brew install openblas
```

## pythonのインストール
今回はpyenvにanacondaを入れます
（anacondaを推奨しているみたい）

```
$ brew install pyenv
$ pyenv install anaconda-2.1.0
$ pyenv local anaconda-2.1.0
$ pyenv global anaconda-2.1.0
```

## caffeをクローン

```
$ cd ~/
$ git clone https://github.com/BVLC/caffe.git
```


## Makefile.configのコピー

```
$ cd caffe
$ pip install -r python/requirements.txt
$ cp Makefile.config.example Makefile.config
```

## Makefile.configの編集
以下の変数のコメントアウトを外して修正してください
各パスは環境に合わせて書き換えてください

```Makefile.config
BLAS := open
BLAS_INCLUDE := /usr/local/Cellar/openblas/0.2.15/include
BLAS_LIB := /usr/local/Cellar/openblas/0.2.15/lib

ANACONDA_HOME := /Users/username/.pyenv/versions/anaconda-2.1.0
PYTHON_INCLUDE := $(ANACONDA_HOME)/include \
                 $(ANACONDA_HOME)/include/python2.7 \
                 $(ANACONDA_HOME)/lib/python2.7/site-packages/numpy/core/include \


# We need to be able to find libpythonX.X.so or .dylib.
PYTHON_LIB := $(ANACONDA_HOME)/lib

```

## モデルのダウンロード
以下のリンクからダウンロードして、~/caffe/models/bvlc_googlenet/ に保存
<a href="http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel">bvlc_googlenet.caffemodel</a>


## .bashrcにパスを追加

```
export DYLD_FALLBACK_LIBRARY_PATH=/usr/local/cuda/lib:~/.pyenv/versions/anaconda-2.1.0/lib
export PYTHONPATH=~/caffe/python/:$PYTHONPATH
```
source ~/.bashrc で反映


## コンパイル

```
$ make clean
$ make all -j4
$ make test
$ make runtest
$ make pycaffe
```

以下のコマンドでエラーが出なければ、caffeのインストールは成功

```
$ python 
>>> import caffe
```

## ipython notebookのインストール
（deepdreamのソースコードはipython notebook形式になっている）

```
$ pip install "ipython[notebook]"
```


## deepdreamのクローン

```
$ git clone git@github.com:google/deepdream.git
```

## ipython notebookを実行

```
$ cd deepdream
$ ipython trust dream.ipynb
$ ipython notebook
```

うまくいくと、ブラウザ上でnotebookがたちあがるので、dream.ipynbを選択して立ち上がった画面から再生ボタンを押して、ソースコードごとに挙動を確認できます。
進めていくと、frames/配下に生成された画像が保存されます。


なお、pythonで実行する場合は以下のソースで実行できます

```
from cStringIO import StringIO
import numpy as np
import scipy.ndimage as nd
import PIL.Image
from IPython.display import clear_output, Image, display
from google.protobuf import text_format

import caffe

def showarray(a, fmt='jpeg'):
    a = np.uint8(np.clip(a, 0, 255))
    f = StringIO()
    PIL.Image.fromarray(a).save(f, fmt)
    display(Image(data=f.getvalue()))

model_path = '../caffe/models/bvlc_googlenet/' # substitute your path here
net_fn   = model_path + 'deploy.prototxt'
param_fn = model_path + 'bvlc_googlenet.caffemodel'


# Patching model to be able to compute gradients.
# Note that you can also manually add "force_backward: true" line to "deploy.prototxt".
model = caffe.io.caffe_pb2.NetParameter()
text_format.Merge(open(net_fn).read(), model)
model.force_backward = True
open('tmp.prototxt', 'w').write(str(model))

net = caffe.Classifier('tmp.prototxt', param_fn,
                       mean = np.float32([104.0, 116.0, 122.0]), # ImageNet mean, training set dependent
                       channel_swap = (2,1,0)) # the reference model has channels in BGR order instead of RGB



# a couple of utility functions for converting to and from Caffe's input image layout
def preprocess(net, img):
    return np.float32(np.rollaxis(img, 2)[::-1]) - net.transformer.mean['data']
def deprocess(net, img):
    return np.dstack((img + net.transformer.mean['data'])[::-1])

def objective_L2(dst):
    dst.diff[:] = dst.data

def make_step(net, step_size=1.5, end='inception_4c/output',
              jitter=32, clip=True, objective=objective_L2):
    '''Basic gradient ascent step.'''

    src = net.blobs['data'] # input image is stored in Net's 'data' blob
    dst = net.blobs[end]

    ox, oy = np.random.randint(-jitter, jitter+1, 2)
    src.data[0] = np.roll(np.roll(src.data[0], ox, -1), oy, -2) # apply jitter shift

    net.forward(end=end)
    objective(dst)  # specify the optimization objective
    net.backward(start=end)
    g = src.diff[0]
    # apply normalized ascent step to the input image
    src.data[:] += step_size/np.abs(g).mean() * g

    src.data[0] = np.roll(np.roll(src.data[0], -ox, -1), -oy, -2) # unshift image

    if clip:
        bias = net.transformer.mean['data']
        src.data[:] = np.clip(src.data, -bias, 255-bias)


def deepdream(net, base_img, iter_n=10, octave_n=4, octave_scale=1.4,
              end='inception_4c/output', clip=True, **step_params):
    # prepare base images for all octaves
    octaves = [preprocess(net, base_img)]
    for i in xrange(octave_n-1):
        octaves.append(nd.zoom(octaves[-1], (1, 1.0/octave_scale,1.0/octave_scale), order=1))

    src = net.blobs['data']
    detail = np.zeros_like(octaves[-1]) # allocate image for network-produced details
    for octave, octave_base in enumerate(octaves[::-1]):
        h, w = octave_base.shape[-2:]
        if octave > 0:
            # upscale details from the previous octave
            h1, w1 = detail.shape[-2:]
            detail = nd.zoom(detail, (1, 1.0*h/h1,1.0*w/w1), order=1)

        src.reshape(1,3,h,w) # resize the network's input image size
        src.data[0] = octave_base+detail
        for i in xrange(iter_n):
            make_step(net, end=end, clip=clip, **step_params)

            # visualization
            vis = deprocess(net, src.data[0])
            if not clip: # adjust image contrast if clipping is disabled
                vis = vis*(255.0/np.percentile(vis, 99.98))
            showarray(vis)
            print octave, i, end, vis.shape
            clear_output(wait=True)

        # extract details produced on the current octave
        detail = src.data[0]-octave_base
        # returning the resulting image
    return deprocess(net, src.data[0])

img = np.float32(PIL.Image.open('sky1024px.jpg'))
for i in xrange(100):
    img = deepdream(net, img, end='inception_4e/pool') PIL.Image.fromarray(np.uint8(img)).save("frames/result-%03d.png" % i)
```

うまくいくとこんな感じ
![result-000.png](https://qiita-image-store.s3.amazonaws.com/0/66003/dfe8984d-b8b1-984a-0bda-1f4180e14bf3.png)
![result-007.png](https://qiita-image-store.s3.amazonaws.com/0/66003/f1dae763-5325-ea18-d541-88c05ff38b61.png)
![result-060.png](https://qiita-image-store.s3.amazonaws.com/0/66003/e43596ba-b75b-c751-41fe-5ff88cb98001.png)

finetune_flickr_styleを使うと、floating point exceptionでエラーになるので要調査