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

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

このブログ、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

昨年末に撮影したエンジニアインタビュー動画がようやく完成しました。

クライアントワークだったりすると出せない情報も多いので、どういう仕事か伝えるために採用動画を作ろうということで制作開始。撮影は社員が進めてくれて、編集は「僕がやるから任せとけ」と言ったものの途中、仕事が忙しすぎてしばらく間があいて、やっと先週から。

撮りおわった動画を全部確認して使えそうなところをピックアップ。長い動画だとPremiereで切り出して、最終的にAfter Effectsで編集、色合い、デザイン、Lower Thirdを入れて書き出すということの繰り返し。

社員インタビューもみんな自由に話してるから、これはさすがに使えないだろあの野郎、とか思いつつ、最後は編集で上手くまとまった感じです。

レンダリングは、一番スペック良さそうだったのがごみ箱みたいなデザインで有名なMac Proだったので、それを使っても6時間。夜まで編集して、レンダリングスタートしておいて翌朝に確認するという状態なので、ちょっとミスった時の絶望感が半端ない。

なるべく手軽に見れる動画と思いながら、最終的に8分の動画。長いけど、ぜひ(インタビューなので音ありで)ご覧ください!





P1000018_2
P1000056_2

↑このページのトップヘ