舩木俊介「かつて未来とよばれたソサエティ」

スーパーソフトウエア東京オフィス代表&キッズラインCTO

久しぶりにAWSのGPUインスタンスを見ていてると、p2インスタンスが利用可能になっていました。

p2のGPUはTesla K80が載っているのでg2系のK10よりも2.5倍ほど速い。FLOPSは2倍、GPUメモリは3倍、などおおむね倍以上のスペックになっていて、値段としては、g2.2xlargeが$0.65/hでp2.xlargeが$0.9/hなので、1.4倍ほど。ディープラーニングの学習が12時間かかったとしても1200円ちょっとで、コストパフォーマンスとしても割といいのではないでしょうか。
tesla-k80
このp2インスタンス、AmazonLinuxならCaffeなどが入っているらしいですが、ディープラーニングではubuntuばかり使っているので、ubuntuでのTensorFlowインストールを行います。以前に比べて妙な手間が減って割と簡単になった感があります。


Ubuntu初期設定

まずインスタンスを立ち上げます。Ubuntu Server 16.04 LTSを使用して、ディープラーニングではデータセットが大きくなるのでSSDは50GB以上など大きめにとっておきます。 awswiz
インスタンスが起動したら、ツール類をインストールしておきます。今回はPython2.7で。
$ sudo apt-get update
$ sudo apt-get upgrade -y
$ sudo apt-get install -y build-essential python-pip python-dev git python-numpy swig python-dev default-jdk zip zlib1g-dev ipython

CUDA/cuDNNインストール

デフォルトでnouveauのグラフィックドライバが有効になっているので、NVIDIAのCUDAなどドライバをインストールする際にエラーがでないように無効化しておきます。
$ echo -e "blacklist nouveau\nblacklist lbm-nouveau\noptions nouveau modeset=0\nalias nouveau off\nalias lbm-nouveau off\n" | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
$ echo options nouveau modeset=0 | sudo tee -a /etc/modprobe.d/nouveau-kms.conf
$ sudo update-initramfs -u
$ sudo reboot

$ sudo apt-get install -y linux-image-extra-virtual
$ sudo reboot
NVIDIAのウェブサイトからドライバをダウンロードしておきます。
cuda
cuDNN
cuDNNはNVIDIAへのログインが必要です。CUDA8.0と、cuDNN5.1 for CUDA 8.0をダウンロードしたら、SCPなどでubuntu側へアップロードしておきます。

CUDAインストール

sudo apt-get install -y linux-source linux-headers-`uname -r`
sudo dpkg -i cuda-repo-ubuntu1604_8.0.61-1_amd64.deb
sudo apt-get update
sudo apt-get install cuda

cuDNNインストール

tar xvzf cudnn-8.0-linux-x64-v5.1.tgz
sudo cp -P cuda/include/cudnn.h /usr/local/cuda/include
sudo cp -P cuda/lib64/libcudnn* /usr/local/cuda/lib64
sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*
sudo apt-get install libcupti-dev

.profile更新

export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64"
export CUDA_HOME=/usr/local/cuda
$ source ~/.profile
CUDAドライバのインストールは完了です。
$ nvidia-smi
で、
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 375.66                 Driver Version: 375.66                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 0000:00:1E.0     Off |                    0 |
| N/A   37C    P0    76W / 149W |      0MiB / 11439MiB |     93%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
が出てくればOKです。


TensorFlowインストール

使いたいライブラリがr0.12バージョン指定だったのでTensorFlow r0.12をインストールします。必要に応じてバージョンは変えてください。
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-0.12.1-cp27-none-linux_x86_64.whl
$ sudo pip install --upgrade $TF_BINARY_URL
動作確認をしておきます。 TensorFlowの動作確認。
$ python
...
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
42
>>>
CUDAが上手く動いているか確認。
$ python -c 'import os; import inspect; import tensorflow; print(os.path.dirname(inspect.getfile(tensorflow)))'

I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.so locally
/usr/local/lib/python2.7/dist-packages/tensorflow


ここまでできればAMIなどを作成してインスタンスを停止、使いたいときに起動という運用にしておけば、いつでも低コストで人工知能の開発ができますね。

このブログ、1年に1回くらいの更新ペースを順調に維持してますが、2016年も残りわずか数時間。今年もお世話になった皆様、ありがとうございました。

個人的には今までにないくらいあっという間の楽しい1年で、久しぶりにPythonやRubyでAIのコードをたくさん書いた1年でした。TensorflowとChainerでマシンから煙出るんじゃないかという1年でした。テクノロジーで未来を変える、エンジニアが世界を変える、というコンセプト実現のための布石が出来た感じです。

AI

AIによるここ数年の大きなパラダイムシフトは、世界を新しいものに変えつつあります。もちろんいまのAIは、万能で汎用なAI、人類を絶滅させるかもしれないAIが完成しつつあるというような段階からはほど遠い、まだまだ基礎的な段階ではありますが、ディープラーニングによって実用レベルになってきたところが大きい。

いくら高度な技術がどうという議論をしたところで、精度が50%、60%のものを使おうと思ったら、考えたり、選んだりといった人間の負担が発生するため誰もまともに使わない。それが一気に95%、98%という精度で結果を出せるようになったために、ここ数年で自動車、IoT、Webサイト、アプリのバックエンドなど、見えないところでAIが浸透していくフェーズになっていくと考えられており、日本にはAI研究者も多いことから、次世代に飛躍的に伸びる産業とも期待されています。

トマ・ピケティが『21世紀の資本』で指摘するように、経済格差や不平等はこれからも益々進み、社会的不満や国家間、世代間の対立が拡大していくでしょう。ただ、
 ・日本は「GDP世界第3位」の経済大国である
 → 1人あたりGDPは先進国最下位(世界第27位)

・日本は「製造業生産額世界第2位」のものづくり大国である
 → 1人あたり製造業生産額はG7平均以下

日本が抱える根本的な問題は、経済成長率が低い中で資本収益率が上回ることで、一部の富裕層に富のさらなる偏在化が起こっているといったピケティの理論よりも、日本の人口の20%が低所得者層に属するという、多すぎる貧困層の問題とも言われています。これによって1人あたりGDPなども著しく低く、貧困の再生産によって固定化されていく。古い経済成長を未だに期待して大樹にぶら下がることしか能が無い旧世代も活躍している。

この問題の解決は、成長性の高い産業の創出と、貧困を世代間で受け継がない教育、によってしか解決できないと思われますが、その両方にAIの発展は寄与するのではないかと思います。


エンジニアチーム

社員の育成、成長というのはエンジニア組織であれば最大のテーマで、創れるエンジニアをいかに増やすかをテーマにRailsやSwiftの研修を2016年初頭から行った覚えがあります。

単なる作業者ではなく、その一歩上のエンジニアを目指しましょうということがポイント。出題は、ベーシックなアプリ開発や、超簡単だけど曖昧な問題だったりするわけですが、コードを見ると、何をどう考えて、どういうロジックで実現したか、というスキルや仮説思考が丸わかりなので採点も面白かったですね。

これまで色々と人を見てきて、エンジニアスキルに限らず、ビジネスパーソンとしての能力が成長する人、しない人の違いについてはこれが答えなんじゃないのというのがあって、それはダニングクルーガー効果の排除が出来るかどうか。
 1.能力の低い人は自分のレベルを正しく評価できない。
 2.能力の低い人は他人のスキルも正しく評価できない。 
 3.だから、能力の低い人は自分を過大評価する。

自己の「愚かしさ」を認識するメタ認知ができないことによって生じると言われますが、結局、能力が低い人は自分の状況を客観的に理解する能力さえないという、ごくごくシンプルな話に行き着くわけです。

なので、やはり知における謙虚さというのは大切で、自分はもうこれくらい出来るからすごい、学ぶべきことはない、なんてことを思ってしまうとその人の人生における限界が決まってしまう。しかも本人が自分はレベルが高いとか平均以上だとかと勘違いしているだけなので、そういった差別化ができない労働者はいくらでも他の人で代替が可能、つまりバリュー(価値)がでない人になっていく。

そういう意味で、Google USのチーム作りは人間の特性をよく分かってて、すごいですね。Googleで大切にしている精神としてTeam Geekという本に書いてあるのは、

* 謙虚(Humility)
* 尊敬(Respect)
* 信頼(Trust)

の3つが大切だとしていて、本当にその通りだと思います。謙虚に学び、仲間を信頼する。傲慢で他者を攻撃するような人は、人間として付き合うべき人でもないですから。

あと、真理をついてるなというのが「無能で十分説明されることに悪意を見出すな」。人が集まれば様々なことが起こるものですが、この一言で「ああ、そうか」と納得して丸く収まってしまうという。こういう現場レベルで示唆に富んだ視点が多いので、機会があればこの本は是非読んでみてください。

Team Geek


WD

今年最大のインパクトだったのは、ニーガンですね。ウォーキングデッド・シーズン7ですね。最凶なニーガンの登場で、過去最悪の敵だった「総督」(ガバナー)がものすごい良い人に思えてくる。



2017年はAIをはじめとしたテクノロジーをさらに追究しつつ、ウォーキングデッドで腐った体で殺そうと迫ってくるゾンビよりも人間の強欲のほうが怖いと確認しつつ、色々と今まで通り進めていきたいと思います。

皆様、よいお年をお迎えください。





ディープラーニング(Convolutional Neural Networks(畳み込みニューラルネットワーク))を使ってモノクロ写真を自動でカラー化するよ、という面白そうなプロジェクトAutomatic Colorizationがあったので試してみた。

Rather than reconstructing the entire color RGB image, I trained models to produce two color channels which I concatenate with the grayscale input channel to produce a YUV image. The Y channel is intensity. This ensures that the intensity of the output will always be the same as the input.
輝度信号Yと色差信号のYUVを使うところがポイントで、グレースケールの入力から2つの色差信号を取り出すようにトレーニングされたモデル、とのことです。

Models were trained on the ILSVRC 2012 classification training dataset. The same training set used for the pretrained VGG16. It's 147GB and over 1.2 million images!
ImageNet LSVRC 2012の学習済みモデルが配布されていて、TensorFlow環境さえあればスクリプトの実行だけで動かせるのでいくつかやってみると、

まじか!?というくらい、草原、空など最も上手くカラー復元できた写真がこれ。教師データに多かったであろう自然の風景は、驚くほど再現されている。モノクロ画像の情報だけからここまで色彩を復元できるのは驚き。 m-c
ゴダール「勝手にしやがれ」のジャンポールベルモント。 m2-c
フリー素材の女子高生 m3-c
「ローマの休日」のオードリー・ヘップバーン m4-c

静止画でできるのであれば動画もできるはずということで、ffmpegで切り出して処理して結合という定番の方法でやってみました。

ゾンビ映画の名作、ジョージ・A・ロメロのNight of the Living Dead(ナイト・オブ・ザ・リビングデッド)をカラーにしてみたもの。やっぱり、冒頭の墓地の風景などは、とても上手くカラーになっています。



How to

TensorFlowの学習済みモデルをAutomatic Colorizationからダウンロードしておきます。torrent形式なのでクライアントソフトが必要です。

まず、GoogleのTensorFlowが動く環境を作ります。TensorFlowは2015年11月に無償公開されたばかりのライブラリです。(参考 グーグル、重要な「ヒトの数百万倍の能力」技術を無償公開 革新的分野で圧倒的主導権)

tensorflowのインストールガイドに従って、virtualenv環境でインストールします。
# Mac OS X
$ sudo easy_install pip
$ sudo pip install --upgrade virtualenv

tensorflowをアクティベート
$ virtualenv --system-site-packages ~/tensorflow
$ source ~/tensorflow/bin/activate  # If using bash

tensorflowをpipでインストール。Macで動かしたので、今回はCPUベースで。
# Mac OS X, CPU only:
(tensorflow)$ pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.6.0-py2-none-any.whl

tensorflowの環境が出来たので、画像単体のカラー復元処理は実行できます。モデルと一緒にforward.pyがあるので、
(tensorflow)$ python forward.py

これだけでOK。

動画のカラー化

動画の場合は、前後にffmpegでの処理を行って、Automatic Colorizationをフォルダ内の画像に対してループするだけです。

動画を画像として切り出します。予め、framesフォルダの中に対象となる動画を入れておきます。1秒あたりの枚数が、あまり多くても処理時間がかかるのでとりあえず30フレームで。
(tensorflow)$ mkdir frames
(tensorflow)$ mkdir -p out/frames
(tensorflow)$ cd ./frames
(tensorflow)$ ffmpeg -i f1.mp4 -r 30 -f image2 %06d.jpg

Automatic Colorizationは画像サイズが224となっているので、リサイズしておきます。
(tensorflow)$ mogrify -resize 224x224 *.jpg
(tensorflow)$ mogrify -gravity center -background black -extent 224x224 *.jpg
(tensorflow)$ mogrify -colorspace sRGB -type TrueColor *.jpg
(tensorflow)$ cd ..

forward.pyをフォルダの中の画像に対して行うようにしたスクリプト(forward_movie.py)を実行します。
import tensorflow as tf
import skimage.transform
from skimage.io import imsave, imread
import os
from os import listdir, path
from os.path import isfile, join

def get_directory(folder):
    foundfile = []

    for path, subdirs, files in os.walk(folder):
        for name in files:
            found = os.path.join(path, name)
            if name.endswith('.jpg'):
                foundfile.append(found)
        break

    foundfile.sort()
    return foundfile

def load_image(path):
    img = imread(path)
    # crop image from center
    short_edge = min(img.shape[:2])
    yy = int((img.shape[0] - short_edge) / 2)
    xx = int((img.shape[1] - short_edge) / 2)
    crop_img = img[yy : yy + short_edge, xx : xx + short_edge]
    # resize to 224, 224
    img = skimage.transform.resize(crop_img, (224, 224))
    # desaturate image
    return (img[:,:,0] + img[:,:,1] + img[:,:,2]) / 3.0

with open("colorize.tfmodel", mode='rb') as f:
    fileContent = f.read()

    graph_def = tf.GraphDef()
    graph_def.ParseFromString(fileContent)
    grayscale = tf.placeholder("float", [1, 224, 224, 1])
    tf.import_graph_def(graph_def, input_map={ "grayscale": grayscale }, name='')

images = get_directory("frames")

for image in images:
    print image
    shark_gray = load_image(image).reshape(1, 224, 224, 1)

    with tf.Session() as sess:
        inferred_rgb = sess.graph.get_tensor_by_name("inferred_rgb:0")
        inferred_batch = sess.run(inferred_rgb, feed_dict={ grayscale: shark_gray })
        filename = "out/"+image
        imsave(filename, inferred_batch[0])
        print "saved " + filename
(tensorflow)$ python forward_movie.py

最後に、できあがった画像を結合して動画を作成します。
(tensorflow)$ cd out/frames
(tensorflow)$ cat *.jpg | ffmpeg -f image2pipe -r 30 -vcodec mjpeg -i - -vcodec libx264 out.mp4

↑このページのトップヘ