deepdreamしてみたい
2015/07/11
http://amagitakayosi.hatenablog.com/entry/2015/07/03/143913
「だれか試して」と書いてあったので便乗。
Contents
deepdreamって何
こういうやつ。
元画像
実際に作ってみたい(CPU)
Caffeが実行できる環境があれば公開されてるスクリプトを実行するだけでOK。
スクリプトを見てる感じGPUによる恩恵はなさそうだけど、どうなんでしょうね。
https://github.com/google/deepdream/blob/master/dream.ipynb
↑公開されてるソースはIPython形式。
DockerでIPythonサーバを作ってもいいが面倒。
なので普通なPythonでやりたい。
下記のようなスクリプトファイルを用意しておく。
基本コピペでIPython上で画像表示するような処理は不要なので消した。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# imports and basic notebook setup from cStringIO import StringIO import numpy as np import os import scipy.ndimage as nd import PIL.Image from IPython.display import clear_output, Image from google.protobuf import text_format import caffe model_path = '../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 make_step(net, step_size=1.5, end='inception_4c/output', jitter=32, clip=True): '''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) dst.diff[:] = dst.data # 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)) 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('v.jpg')) os.mkdir("frames") frame = img frame_i = 0 h, w = frame.shape[:2] s = 0.05 # scale coefficient for i in xrange(100): frame = deepdream(net, frame) PIL.Image.fromarray(np.uint8(frame)).save("frames/%04d.jpg"%frame_i) frame = nd.affine_transform(frame, [1-s,1-s,1], [h*s/2,w*s/2,0], order=1) frame_i += 1 |
それから、夢見させる画像も必要なので適当に用意しておく。
最後にスクリプトファイルと画像をDockerコンテナ内から参照するような感じにしたいので、2つのファイルと適当なフォルダに置いておく。
ローカル側で必要なファイルを用意したら、コンテナを作って実行してみる。
こんな感じだろうか。
メモリが足りなくてプロセスがKILLされることがあるのでoptionで適当な量のメモリを確保しておくと吉。
1 2 3 4 5 6 7 8 9 |
# コンテナ外 docker-machine create -d virtualbox --virtualbox-memory="2048" deepdream eval $(docker-machine env deepdream) docker pull tleyden5iwx/caffe-cpu-master docker run -v [スクリプトとか画像入ってるフォルダ]:/opt/caffe/misc -it tleyden5iwx/caffe-cpu-master bin/bash # コンテナ内 cd /opt/caffe/model/bvlc_googlenet && wget http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel cd /opt/caffe/misc && python [deepdream.py] |
スクリプトや画像が入ってるフォルダにframesっていうフォルダができてて、中に画像が生成されていれば成功。
1枚生成するのに2分くらいかかるのでヤバい。
実際に作ってみたい(GPU)
GPU環境でやるのもまあまあ簡単なのでやってみた。
Docker MachineでGPUなCaffe環境を作る
1 |
docker-machine create -d amazonec2 --amazonec2-access-key [アクセスキー] --amazonec2-secret-key [シークレットキー] --amazonec2-ami [Caffe+Dockerを積んだAMIのid] --amazonec2-vpc-id vpc-XXXXXX --amazonec2-request-spot-instance="true" --amazonec2-spot-price="0.16" --amazonec2-instance-type="g2.2xlarge" —amazonec2-root-size="20" deepdream |
雑多な下準備
インスタンスができたら下準備する(ここも自動化すべきだが。。)。
スクリプトや画像をEC2に転送
CPUのときと同じようにdeepdreamのスクリプトと夢見させる画像を用意しておく。
GPUを使うためにはdeepdreamなスクリプトに下記を追記する必要がある。
1 |
caffe.set_mode_gpu() |
これだけでOK。
で、これらをdocker-machine scpでEC2インスタンス側に転送する。
1 |
docker-machine scp -r ./misc ec2:/tmp/ |
こんな感じで。
CUDAを使うための謎まじない。。
CUDAを使うための謎コマンドを実行する。
docker-machine sshでEC2インスタンスに入って下記のコマンドを実行する。
ついでに先ほど転送した画像とかちゃんとあるか確認しておくとよい。
1 2 |
docker-machine ssh deepdream cd /usr/local/cuda/samples/1_Utilities/deviceQuery && make && ./deviceQuery |
コンテナを立ててスクリプトを実行する
下準備が終わったらコンテナを立ててゆく。
deepdreamなマシンをアクティブにして、runする。
先ほど転送しておいたスクリプトなどを参照できるようにvオプションでマウントする。
それから、GPUデバイスを有効にするためのオプションを付加する。
一連の流れは下記の通り。
1 2 |
eval "$(docker-machine env deepdream)" docker run -v /tmp:/opt/caffe/misc -it --device /dev/nvidia0:/dev/nvidia0 --device /dev/nvidiactl:/dev/nvidiactl --device /dev/nvidia-uvm:/dev/nvidia-uvm tleyden5iwx/caffe-gpu-master:latest bin/bash |
あとは必要なモデルを落としてきてスクリプトを実行するだけ。
1 2 3 |
cd /opt/caffe/model/bvlc_googlenet && wget http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel cd /opt/caffe/misc && python [deepdream.py] |
CPUだと1枚の画像生成に2分くらいかかってたのが、GPUだと5秒くらいで生成された。。
GPUやべー(=^・^=)
生成されたデータをローカルに転送する
EC2上にあるデータを手元に転送する。
docker-machine scpでやる。
1 |
docker-machine scp -r ec2:/tmp/frames ./result |
しばらく待つと変な画像がたくさん得られる。
ついでにgif化してみる
公開されてるスクリプトだと、特徴を強制的にフィードバック上書きしつつ拡大っぽい処理をやってる一連が100枚生成される。
gifにしてくれと言わんばかりな感じなのでやってみる。
実際twitterの#deepdreamみてるとgif化してるのポツポツみるし。
ImageMagickを使ってやってみる。
超簡単。
1 |
convert -delay 12 -loop 0 -resize 300x *.jpg hoge.gif |
336px
336px
関連記事
-
-
MacでKerasを使えるようにする
Ke …
- PREV
- [WIP]普通の服について考えてみた
- NEXT
- LeakCanaryの仕組みをある程度理解したいマン