Aidemy Tech Blog

機械学習・ディープラーニング関連技術の活用事例や実装方法をまとめる、株式会社アイデミーの技術ブログです。

機械学習で乃木坂46を顏分類してみた

こんなことをしてみたい

f:id:shintarom4869:20171217150543p:plain
↑これがしたい

pythonによる機械学習の勉強をしたので、実践ということで、人気アイドル「乃木坂46」の個人的に好きな5人のメンバーを区別して見ました。大きな流れはこんな感じです。

  1. web上から五人の画像を100枚ずつ取ってくる
  2. 画像から顔部分を取り出して保存
  3. 画像の水増し
  4. モデルを定義して、学習
  5. テスト(顔を四角く囲って、その人の名前を出力)

説明はこんなもんにして、彼女らの可愛さについて語りたいところですが、そういうブログではないので、少し技術的なことを書きます。 今回はjupyterを使って作業を進めました。notebook形式なので結果が見やすく初心者にはいい環境でした。環境は以下。

  • macOS:10.13.1
  • python:3.6.1
  • openCV:3.3.0
  • keras:2.1.2

1,Google APIを用いた画像取得

これを取得することで、Googleが提供するリソースにアクセスすることができます。今回でいえば、例えば「西野七瀬」と画像検索した時の上位100枚のURLを取得できます。APIのコードについてはこちらのブログを参考にしました。

Google Custom Search APIを使って画像収集 - Qiita

以下のコードでは、keywordsリスト["生田絵梨花","齋藤飛鳥","白石麻衣","西野七瀬","橋本奈々未"]で画像検索、URLを取得後、画像に変換し、jpgファイルとしてorigin_image1ディテクトリに保存という流れになっています。100枚以上取れればいいんですが、600枚くらいで403Error Forbiddenが出てしまいました。

import urllib.request
from urllib.parse import quote
import httplib2
import json 
import os
import cv2
import sys
import shutil

#keywordsの画像のurlを取得後、jpg画像に変換しファイルにどんどん入れてく
#全5人100個ずつ取得

API_KEY = ""#省略
CUSTOM_SEARCH_ENGINE = ""#省略

keywords=["生田絵梨花","齋藤飛鳥","白石麻衣","西野七瀬","橋本奈々未"]


def get_image_url(search_item, total_num):
    img_list = []
    i = 0
    while i < total_num:
        query_img = "https://www.googleapis.com/customsearch/v1?key=" + API_KEY + "&cx=" + CUSTOM_SEARCH_ENGINE + "&num=" + str(10 if(total_num-i)>10 else (total_num-i)) + "&start=" + str(i+1) + "&q=" + quote(search_item) + "&searchType=image"
        res = urllib.request.urlopen(query_img)
        data = json.loads(res.read().decode('utf-8'))
        for j in range(len(data["items"])):
            img_list.append(data["items"][j]["link"])
        i += 10
    return img_list

def get_image(search_item, img_list,j):
    opener = urllib.request.build_opener()
    http = httplib2.Http(".cache")
    for i in range(len(img_list)):
        try:
            fn, ext = os.path.splitext(img_list[i])
            print(img_list[i])
            response, content = http.request(img_list[i]) 
            filename = os.path.join("./origin_image1",str("{0:02d}".format(j))+"."+str(i)+".jpg")
            with open(filename, 'wb') as f:
                f.write(content)
        except:
            print("failed to download the image.")
            continue
            
for j in range(len(keywords)):
    print(keywords[j])
    img_list = get_image_url(keywords[j],100)
    get_image(keywords[j], img_list,j)

2,画像から顔部分を取り出す

まずopencvに搭載されているカスケード分類器を利用して、顔を検出します。今回は正面顔を検出するhaarcascade_frontalface_alt.xmlという分類器を使いました。引数のminNeighborsの値が重要でした。以下のコードでは、検出した顔部分をトリミングし、全て64×64ピクセルにリサイズして(学習器に入れやすくなる)、jpg形式でface_image1ディテクトリに保存ということをしてます。実際ここで、100内60~70枚ほどに減ってしまいます。その理由として、正面顔しか検出しないため、正面を向いていても傾いた顔は検出できないため、などが挙げられます。検出できなかったものは自分の目でチェックして自力でトリミングした方がいいデータができると思います。またツーショットなどは別の人の顔も一緒に検出してまったので、そういうのはラベルを変えるor削除しました。この作業をしている時が一番こうf...幸せでした。 カスケード分類器に関してはこのブログがおすすめです。

python+OpenCVで顔認識をやってみる - Qiita

f:id:shintarom4869:20171217150344p:plain
オリジナル写真

import numpy as np
import cv2
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import glob
import os
 
#元画像を取り出して顔部分を正方形で囲み、64×64pにリサイズ、別のファイルにどんどん入れてく
in_dir = "./origin_image1/*"
out_dir = "./face_image1"
in_jpg=glob.glob(in_dir)
in_fileName=os.listdir("./origin_image1/")
# print(in_jpg)
# print(in_fileName)
print(len(in_jpg))
for num in range(len(in_jpg)):
    image=cv2.imread(str(in_jpg[num]))
    if image is None:
        print("Not open:",line)
        continue
    
    image_gs = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    cascade = cv2.CascadeClassifier("/usr/local/opt/opencv/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml")
    # 顔認識の実行
    face_list=cascade.detectMultiScale(image_gs, scaleFactor=1.1, minNeighbors=2,minSize=(64,64))
    #顔が1つ以上検出された時
    if len(face_list) > 0:
        for rect in face_list:
            x,y,width,height=rect
            image = image[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
            if image.shape[0]<64:
                continue
            image = cv2.resize(image,(64,64))
    #顔が検出されなかった時
    else:
        print("no face")
        continue
    print(image.shape)
    #保存
    fileName=os.path.join(out_dir,str(in_fileName[num])+".jpg")
    cv2.imwrite(str(fileName),image)

3,画像の水増し

顔検出して、残った数が、それぞれ50~70枚ほどになってしまい、これでは学習データとして不足するだろうと思ったので、左右反転、閾値処理、ぼかしを使って水増しを行います。これで学習データが8倍になります。(それでも少ない気がしますが。。)。画像の水増しは自動でやってくれるツールがありますが、自分でかけるコードは自分で書きたいので(キリッ)。このドキュメントは、画像の前処理を行う上で、もっともスタンダードな方法の一つです。これを知ってれば早いです。 画像の前処理 - Keras Documentation ImageDataGenerator関数はリアルタイムにデータ拡張しながら,テンソル画像データのバッチを生成します。

以下のコードでは水増し加工をしたものをface_scratch_image1ディテクトリに保存してます。また、学習器に入れるために画像リストXと正解ラベルリストyを用意して、それぞれ追加していきます。

#左右反転、閾値処理、ぼかしで8倍の水増し
import os
import numpy as np
import matplotlib.pyplot as plt
import cv2

def scratch_image(img, flip=True, thr=True, filt=True):
    # 水増しの手法を配列にまとめる
    methods = [flip, thr, filt]
    # 画像のサイズを習得、ぼかしに使うフィルターの作成
    img_size = img.shape
    filter1 = np.ones((3, 3))
    # オリジナルの画像データを配列に格納
    images = [img]
    # 手法に用いる関数
    scratch = np.array([
        lambda x: cv2.flip(x, 1),
        lambda x: cv2.threshold(x, 100, 255, cv2.THRESH_TOZERO)[1],
        lambda x: cv2.GaussianBlur(x, (5, 5), 0),
    ])
    # 加工した画像を元と合わせて水増し
    doubling_images = lambda f, imag: np.r_[imag, [f(i) for i in imag]]

    for func in scratch[methods]:
        images = doubling_images(func, images)
    return images
    
# 画像の読み込み
in_dir = "./face_image1/*"
in_jpg=glob.glob(in_dir)
img_file_name_list=os.listdir("./face_image1/")
for i in range(len(in_jpg)):
    print(str(in_jpg[i]))
    img = cv2.imread(str(in_jpg[i]))
    scratch_face_images = scratch_image(img)
    for num, im in enumerate(scratch_face_images):
        fn, ext = os.path.splitext(img_file_name_list[i])
        file_name=os.path.join("./face_scratch_image1",str(fn+"."+str(num)+".jpg"))
        cv2.imwrite(str(file_name) ,im)

# 画像と正解ラベルをリストにする
import random
from keras.utils.np_utils import to_categorical

img_file_name_list=os.listdir("./face_scratch_image1/")
print(len(img_file_name_list))

for i in range(len(img_file_name_list)-1):
    n=os.path.join("./face_scratch_image1",img_file_name_list[i])
    img = cv2.imread(n)
    if isinstance(img,type(None)) == True:
        img_file_name_list.pop(i)
        continue
print(len(img_file_name_list))

random.shuffle(img_file_name_list)
X=[]
y=[]

for j in range(0,len(img_file_name_list)):
    n=os.path.join("./face_scratch_image1",img_file_name_list[j])
    img = cv2.imread(n)
    b,g,r = cv2.split(img)
    img = cv2.merge([r,g,b])
    X.append(img)
    n=img_file_name_list[j]
    y=np.append(y,int(n[0:2])).reshape(j+1,1)
print(y.shape)
print(y[0])
X=np.array(X)
print(X.shape)
#確認用
# plt.imshow(X[0])
# plt.show()

4,モデルを定義して、学習

さて、一人当たり400~600枚ほどのデータを取得できました。いよいよ本番です。これを学習させる学習器を構築して、学習させます。 これ以降のディープニューラルネットワークのモデルの作成・学習はKerasというライブラリを使用しました。KarasはTheanoやTensorFlowといった機械学習のライブラリのラッパーです。さて、学習器の構造ですが、CIFAR-10のサンプルを参考に作って見ました。それと、keras documentationは日本語のドキュメントなのでわかりやすかったです。畳み込み層、プーリング層の数を増やしたり、epoch数-精度のグラフをみて、精度の高かったものがこちらです。またこちらのブログも参考になりました。 TensorFlowによるももクロメンバー顔認識(前編) - Qiita

ディープラーニングでザッカーバーグの顔を識別するAIを作る①(学習データ準備編) - Qiita

- 入力 (64x64 3chカラー)
- 畳み込み層1
- プーリング層1
- 畳み込み層2
- プーリング層2
- 畳み込み層3
- プーリング層3
- 平坦層1
- 全結合層1(sigmoid関数)
- 全結合層2(sigmoid関数)
- 全結合層3(softmax関数 出力5)

epochs数を50にしてテストデータの精度は92%になりました。高いですね。みんな可愛いから特徴量が低いと思ったのですが、案外いい結果に驚きました。全結合層の関数は一般的にはrelu関数の方が良いとされますが、試して見たところ今回はsigmoid関数の方が精度が高かったです。浅めの学習モデルだとsigmoid関数の方がいいのかもしれません。

epochs-accグラフはこちらです。

f:id:shintarom4869:20171217175012p:plain
横軸:epoch数,縦軸:精度

from keras.layers import Activation, Conv2D, Dense, Flatten, MaxPooling2D
from keras.models import Sequential, load_model

#練習データとテストデータに分ける
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8)

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

plt.imshow(X_train[0])
plt.show()
print(y_train[0])

# モデルの定義
model = Sequential()
model.add(Conv2D(input_shape=(64, 64, 3), filters=32,kernel_size=(2, 2), strides=(1, 1), padding="same"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(filters=32, kernel_size=(2, 2), strides=(1, 1), padding="same"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(filters=32, kernel_size=(2, 2), strides=(1, 1), padding="same"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(256))
model.add(Activation("sigmoid"))
model.add(Dense(128))
model.add(Activation('sigmoid'))
model.add(Dense(5))
model.add(Activation('softmax'))


# コンパイル
model.compile(optimizer='sgd', loss='categorical_crossentropy',metrics=['accuracy'])

# 学習
# model.fit(X_train, y_train, batch_size=32, epochs=50)

#グラフ用
history = model.fit(X_train, y_train, batch_size=32, epochs=100, verbose=1, validation_data=(X_test, y_test))

# 汎化制度の評価・表示
score = model.evaluate(X_test, y_test, batch_size=32, verbose=0)
print('validation loss:{0[0]}\nvalidation accuracy:{0[1]}'.format(score))

#acc, val_accのプロット
plt.plot(history.history["acc"], label="acc", ls="-", marker="o")
plt.plot(history.history["val_acc"], label="val_acc", ls="-", marker="x")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()

#モデルを保存
model.save("my_model.h5")

5,テスト

見分けるモデルが完成したので、これを使ってアイドルの顔を見分けていこうと思います。画面に文字を追加したり、四角く囲ったりするのもopencvを用いました。いろんな画像でテストして見ると、生田絵梨花と誤認識する確率が高いように思いました。

コードは、画像中の顔を検出、四角くくくる、モデルで測定、名前を記入、といった感じです。

import numpy as np
import matplotlib.pyplot as plt

def detect_face(image):
    print(image.shape)
    #opencvを使って顔抽出
    image_gs = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    cascade = cv2.CascadeClassifier("/usr/local/opt/opencv/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml")
    # 顔認識の実行
    face_list=cascade.detectMultiScale(image_gs, scaleFactor=1.1, minNeighbors=2,minSize=(64,64))
    #顔が1つ以上検出された時
    if len(face_list) > 0:
        for rect in face_list:
            x,y,width,height=rect
            cv2.rectangle(image, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), (255, 0, 0), thickness=3)
            img = image[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
            if image.shape[0]<64:
                print("too small")
                continue
            img = cv2.resize(image,(64,64))
            img=np.expand_dims(img,axis=0)
            name = detect_who(img)
            cv2.putText(image,name,(x,y+height+20),cv2.FONT_HERSHEY_DUPLEX,1,(255,0,0),2)
    #顔が検出されなかった時
    else:
        print("no face")
    return image
    
def detect_who(img):
    #予測
    name=""
    print(model.predict(img))
    nameNumLabel=np.argmax(model.predict(img))
    if nameNumLabel== 0: 
        name="Ikuta Erika"
    elif nameNumLabel==1:
        name="Saito Asuka"
    elif nameNumLabel==2:
        name="Shiraishi Mai"
    elif nameNumLabel==3:
        name="Nishino Nanase"
    elif nameNumLabel==4:
        name="Hashimoto Nanami"
    return name

# model = load_model('./my_model.h5')

image=cv2.imread("/Users/shintaro/aidemy/sample/origin_image1/01.0.jpg")
if image is None:
    print("Not open:")
b,g,r = cv2.split(image)
image = cv2.merge([r,g,b])
whoImage=detect_face(image)

plt.imshow(whoImage)
plt.show()
最後にちょっとだけ感想

今回のコードの制作期間は二日くらいでしたが、その6,7割くらいの時間を素材集めに使ってしまいまして、機械学習についてもっと触れたかったなと思いました。でも、細かい文法などの知識が固まったかなと思います。もっと人数の増やした、良い学習モデルを作ってサービスとしてリリースしたいなと思いました。また、さらなる上達のために、今回の応用として転移学習にも挑戦していきたいと思いました。

ラストに結果を載せていきます。失敗込みです。(汗)

f:id:shintarom4869:20171217213221p:plainf:id:shintarom4869:20171217150444p:plainf:id:shintarom4869:20171217150441p:plainf:id:shintarom4869:20171217150403p:plainf:id:shintarom4869:20171217150443p:plainf:id:shintarom4869:20171217150445p:plain
テスト

ニューラルネットワークの新技術 世界一わかりやすい”カプセルネットワーク”とは?

こんにちは、たくやです。

今回は69歳のグーグル研究員、ジェフ・ヒントンが40年の歳月をかけて熟考して発表した新技術、カプセルネットワークをご紹介します。

今回も例によってわかりにくい数式や専門用語をできるだけ使わずに感覚的に解説していきます。

元論文 

http://papers.nips.cc/paper/6975-dynamic-routing-between-capsules.pdf

 

この、カプセルネットワークは今、これまで機械学習で不動の地位を築いていたニューラルネットワークの技術を超える新技術なのではないかと期待されています。

彼の出した2つの論文によると、カプセルネットワークの精度は従来のニューラルネットワークの最高時の精度に、誤答率は従来のニューラルネットワークの最低時の半分にまで減少したといいます。

 

・従来のニューラルネットワークとの違い

では、何が従来のニューラルネットワークと違うのでしょうか?

一言でいうと、従来のニューラルネットワークが全体をその大きさで見ていたのに対して、カプセルネットワークが特徴ごとに”ベクトル”で見ているという点です。

もう少し詳しく説明します。

例えば顔を認識する際に、従来のニューラルネットワークであるCNN(Convolution Newral Network) はそれが目なのか、鼻なのか、口なのかにしか着目していませんでした。(画像左)

*CNNが何かを知らない方はこちらの記事の”CNNのおさらい”をご覧ください。

不気味なロボットから考えるCNNの仕組みのおさらいとAIによる画像認識の攻防戦

 

しかし、今回のカプセルネットワークはそれらの特徴がどのような関係で配置されているのかまで認識します。(画像右)

f:id:meteoputi:20171202201831p:plain

つまり、カプセルネットワークは個々の特徴を独立的に捉え、それぞれがどのような関係にあるのかということにまで着目します。カプセルネットワークの名前の由来がここにあります。ひとつひとつのカプセルに詰まったニューロンが個々の特徴に着目し、それぞれの関係に着目するのです。

これによって何が起こるのでしょうか?

f:id:meteoputi:20171202200032j:plain

 例えばこの写真、私たち人間の目には実物の自由の女神像を見たことがなくても、全て自由の女神像に見えます。しかし、私たちは、何千枚と自由の女神の写真を見てきたわけではないですよね?私たちは、十数枚の写真を見ただけで、それが自由の女神像だと認識することができます。

それと同じことが機械学習でも可能になるのです。

機械学習を行うには5つのプロセスがありました。

  1. データの収集
  2. データの前処理
  3. モデルの構築
  4. 実際に人工知能に学習させる
  5. モデルの改善

機械学習で最も大変なのは、実のところ、1と2のプロセスでした。しかし、今回のカプセルネットワークが実際に実用に耐えうるものだとされれば、1と2の手間がかなり省けるために、機械学習の可能性が一気に広がります。

 

 

・カプセルネットワークの仕組み

なぜそのようなことができるのでしょうか?

ひとつには上記で話したように、ベクトルで対象を認識しているからということが挙げられます。しかし、もうひとつ、重要な点があります。それが”プーリング”です。

開発者のジェフ・ヒントンはこのような言葉を残しています。

I believe Convolution, but I don't believe Pooling. - Geoffrey Hinton

つまり、CNNの仕組みは基本的に素晴らしいが、最後の処理であるプーリングには疑問を呈しているのです。

プーリング、特によく使われるマックス・プーリングは元のデータから導き出された特徴量の最大値をとって、残りを切り捨てる操作でした。しかし、これによって、特徴同士がどのような関係にあるのかがわからなくなってしまうというのです。

それもそうですよね。簡単に言えば特徴がどれだけ出ているかを表す数値で構成された写真の解像度をわざわざ下げて、特徴を強調しているわけですから。特徴の強さがどのように移り変わっているのかは分かりにくくなってしまいます。

 

f:id:meteoputi:20171202205205p:plain

 

そのかわり、カプセルネットワークではsquash関数という関数によってベクトル全体が潰されることになります。

(数学を見ると蕁麻疹が出てしまう方はこの部分を読み飛ばしてください)

f:id:meteoputi:20171202210859p:plain

具体的にはこのような関数になります。‖ ‖で囲まれている部分はノルムといってベクトルの長さを表すと考えてもらって大丈夫です。確かに分母で1がプラスされているため、圧縮されているのがわかります。ちなみにSj / ‖Sj‖ の部分は単位ベクトルといって、向きを表すために掛け算しています。

 

最後に、従来のニューラルネットワークとカプセルネットワークの違いを明確に表す画像を見つけたので、引用させてもらいます。

f:id:meteoputi:20171202211713p:plain

上の写真を見ればわかる通り、両者の構造はとても似ており、異なる点は3つだけ。

  1. 入力に重さをかけてベクトルにしている。
  2. バイアスを足さずに、どこの部分を強調して見るということをしないようにしている。
  3. 最後に従来の関数と違い、squash関数を入れ、データを圧縮している。

カプセルネットワークの技術的な話をもっと知りたい方は、英語版ですが、とてもわかりやすくカプセルネットワークの技術について解説してくれている動画も見つけましたので、よかったらご覧になってみてください。

https://www.youtube.com/watch?v=pPN8d0E3900

 

参考

https://qiita.com/onlyzs/items/5096f50a21758a536d9a

http://www.it-lifelog.com/entry/2017/11/28/205914

http://shunk031.me/paper-survey/paper-summary/CV/Dynamic_Routing_Between_Capsules.html

https://medium.com/ai%C2%B3-theory-practice-business/understanding-hintons-capsule-networks-part-i-intuition-b4b559d1159b

https://qiita.com/motokimura/items/cae9defed10cb5efeb62

https://hackernoon.com/what-is-a-capsnet-or-capsule-network-2bfbe48769cc

TensorFlowをあなたの手の上で TensorFlow Liteついにリリース

晩秋の候、ゆく秋も感慨深く思います。技術顧問の木村です。

今回は、先日リリースされたTesorFlow Liteをご紹介します。また、その他のディープラーニングフレームワークについて簡単に紹介します。

TensorFlow LiteはTensorFlowをモバイル端末で動くように改良したものです。

これは膨大な量のデータを用いるモデルの学習を行うためではなく、すでに訓練済みのモデルを使って、デバイス上で、素早く処理を実行するために作られました。

今までAppleの「Siri」、Googleの「Google Assistant」や、「Amazon Alexa」などはディープラーニングの処理をクラウド上で行なっています。

TensorFlow Liteにより、取得したデータを端末側にとどめておくことでプライバシーの問題を緩和できるというメリットもあります。

TensorFlow Liteの特徴

  • 軽い  (Lightweight)
    処理能力が低いモバイル端末のデバイス上でも起動や初期化が素早く行えるよう設計されています。
  • 複数のプラットフォームで動く(Cross-platform)
    TensorFlow Liteは様々なプラットフォーム上で動かすことができる。今回のプレビューの初期段階では、AndroidとiOSに対応しています。AndroidではJavaとC++, iOSではC++ の APIが用意されています。
  • 早い(Fast)
    携帯電話やIoTなどに最適化されていて、モデルの読み込みなどが劇的に改善されました。

最近はエッジコンピューティングが注目されつつあります。

エッジコンピューティングとは

「端末の近くにサーバーを分散配置する」というネットワークコンピューティングの技法のひとつです。「 端末」、つまりスマートフォンなどにネットワーク的に近い場所へ、サーバーと呼ばれるコンピュータを配置するのです。

これは、クラウドコンピューティングとは逆の流れです。背景には計算資源が安価になったことがあります。クラウドコンピューティングでは、データを集約して計算していました。プロセッサなどの計算資源は高価である一方、通信は安価だったからです。昨今ではプロセッサの高速化が進みました。現代のスマートフォンの処理速度は100G Flops程度、一方で、10年ほど前のPC用ハイエンドCPUであったPentium 4 は7.6 GFLOPSしかありません。

TensorFlow Liteはそんなエッジコンピューティングの流れを加速させるかもしれませんね。

ディープラーニングフレームワークとは

TensorFlowはディープラーニングフレームワークの一つです。ディープラーニングモデルを学習するためには、GPUを使ったプログラムが不可欠です。しかし、GPUプログラムを直接書くのはCPUのプログラムになかなか大変です。ディープラーングフレームワークを用いれば、GPU上での演算を簡単に書くことができます。

有名なディープラーニングフレームワークの一覧

 参考:マルチGPUでの各ディープラーニングフレームワークの実行速度(小さいほど速い)

  f:id:meteoputi:20171125194130p:plain

出典: Shaohuai Shi, Qiang Wang, Pengfei Xu, Xiaowen Chu, Benchmarking State-of-the-Art Deep Learning Software Tools, arXiv:1608.07249v7 [cs.DC] 17 Feb 2017.

■TensorFlow

Google製のディープラーニングフレームワークです。最もユーザが多く、活発に開発されています。

TensorFlowそのものはテンソル演算を行うもので、低水準な演算をサポートしています。低水準演算でディープラーニングを書くのはやや骨が折れます。そこで、対応する高水準のラッパーライブラリも多いです。

ラッパーとは

プログラミングやソフトウェア開発の分野では、ソフトウェアやプログラム部品などが提供するクラスや関数、データ型などを本来とは異なる環境や方法で利用できるようにしたもの

 

高水準は 記述の抽象度が高い言語を指します。

低水準は 逆にコードがより機械語に近いことを表します。

他のフレームワークと比べ、実行が遅いという弱点があります。

■CNTK

Microsoft製のディープラーニングフレームワークです。Brain scriptという独自の言語で書きます。最近、Pythonにも対応しました。

CPU版の実行速度はほかのフレームワークを圧倒しています。

やや、ユーザが少ないのが欠点です。

■Chainer

日本のディープラーニング企業である Prefferd Networksによって開発されています。国内での人気は高く、日本語の情報が多いです。計算グラフを動的に作成するデファインバイランをいち早く実装しました。

拡張したい場合は、微分方法(バックワード演算)を明示したり、cuDNNライブラリ用のC++コードを書く必要があるという弱点を持ちます。cupyというnumpy互換のライブラリを利用することもできます。

■Torch & PyTorch

Pytorch は Facebook が後援しているディープラーニングフレームワークです。Chainerとよく似た構造をしています。バックワード演算を書く必要はありません。最近は論文の実装が PyTorchで公開されることも多く、じわじわと人気が高まっています。

■MxNet

ワシントン大学とCMUによって開発されているディープラーニングライブラリで、AmazonやBaiduで利用されています。メモリ負荷が低い、実行速度が速いなどの特徴を持ちます。一方で、まだまだドキュメントが不足している印象があります。

■Caffe

バークレイによるディープラーニングライブラリです。高速に動作し、画像処理に強いという特徴をもちます。豊富な学習済みモデルが、Model Zoo · BVLC/caffe Wiki · GitHub で公開されています。あまり触ったことはありませんが、モデル定義ファイルがプログラムと分離していたりして少し特殊なライブラリという印象があります。

■Keras

バックエンドと呼ぶ低水準の下位ライブラリをラップする形の高水準ライブラリです。バックエンドには TensorFlow, CNTK、Theano(今回は紹介しない)が利用できます。非常に簡単にディープラーニングのコードを書くことができます。入門には最適です。一方で、複雑なネットワークを組みたい場合は力不足感が否めません。

ラップするとは

そのプログラム特有の型を使わず、Stringとはintとか、javaで共通して使える引数や戻り値でinterfaceをつくり、それを継承したクラスで、実装すること

■Gluon

MxNetをラップする高水準ライブラリです。将来的にCNTKもサポートする予定だそうです。Kerasとくらべて高い拡張性を持っています。一方で公式でサポートするレイヤの数はまだまだ少ないです。

■H2O

 HadoopやSpark上で動かすことを想定した機械学習ライブラリです。ドキュメントが少ないのが欠点ですが、分散環境との相性は良いでしょう。

結局、どのフレームワークを使えばよいのか?

あなたがディープラーニングプログラムの初心者なら、Kerasを一番におすすめします。入門者用に思われがちですが、ある程度の汎用性があります。私もKerasでかけるな、と思ったらKerasで書くことが多いです。

ディープラーニングプログラムをプロジェクトでしっかり書きたいと思った時にはどうすればいいのか。これはなかなか難問です。ディープラーニングはまだ発展中の技術です。フレームワークの仕様もどんどん変わります。現状ではフレームワークを使い捨てていく感じが良いのではないかというのが個人的な感想です。独自のラッパーライブラリを書く、などとしていたら、依存ライブラリの仕様が変わって全部書き直し、となってしまいます。

 

参照

https://www.codexa.net/tensorflow-lite-annoucement/

人材採用から人材管理まで AI×HRのサービス10選!

 

こんにちは、たくやです。

今週はニュースからちょっと離れて、AIがHR(Human Resourse, 人事)にてどのように利用されているのか、また利用されようとしているのかについて、いくつかのサービスをご紹介させていただきたいと思います。

これからHRにAIを導入しようと考えている方、また、AIが具体的にどのようなメリットをもたらすのかに興味がある方が読みやすい構成にいたしました。

これまで人事は上司の好き嫌い、経験や勘、飲みニケーションなどの不透明な条件下で行われていましたが、そういったものを画一的に体系化、数値化することで、従来よりも効率的に業務改善などの業務を達成できることが期待されています。

 

<チャットを利用した個人の仕事適正判定サービス >

1、株式会社フォーラムエンジニアリングの「Insight Matching 」

Watson のテクノロジーを活用した人材マッチングシステム。

実際にユーザーとのテキストチャット形式を通し、対話履歴書のみでは知ることが難しかった趣味や性格などの人間的な側面も分析し、独自のアルゴリズムを用いて適正を数値化してくれます。

例えば、設計士を募集する企業があったとします。その企業にとって適合性の高いエンジニアを提案する際に、エンジニアとの対話から得た情報をそれぞれ数値で表します。具体的には、数値上では電話営業のスキルが35点だったとしても、設計士を募集する企業の事業領域とのスキルやモチベーションにおける適合性が90点なので、クライアント企業とエンジニアの適合性は 70点。エンジニアと企業の適合性が十分に高いとし、人材コンサルタントに提案するといった仕組みです。

IT領域から自動車関連など、多岐に渡るエンジニアが約5000人登録しているそうです。

www.youtube.com

 

 

 

<テキストのパフォーマンス分析サービス>

2、Textio

機械学習と自然言語処理を駆使し、候補者の作成したレジュメや求人広告に利用されている文言やレイアウト、オファーメール、応募効果(ニーズにあった人材の獲得ができたか、獲得までに要した時間)などを解析し、候補者の属性によって効果的な、またはネガティブにとらえられる可能性の高い文言や文章を割り出だしてくれます。

2014年にシアトルで設立したスタートアップ企業です。

TwitterMicrosoft、スターバックスが利用しています。 

textio.com

 

<求職者データベース検索サービス>

3、Connectifier

2012年に元Google社員のBen McCann氏とJohn Jersin氏が創業したカリフォルニアの企業です。

求職者情報をデータベース化し、人事担当者がキーワードやロケーションなどの条件を入力すると、データベースから潜在的な候補者を含む、適合性の高いターゲットを迅速にピックアップしてくれます。

なんと、4億人を上回る求職者情報をデータベース化しています。

具体的なアルゴリズムは公開していないものの「AIを活用する」とコーポレートサイトに明記されており、AI×HRのスタートアップとしてかねてより注目が集まっていました。

2016年2月、Connectifier は LinkedInに買収されました。

 

4、AI人事部長

チームメンバーや応募者が用意しているアンケートに答えることによって、その人の強みや特徴を視覚化。チームがどういう状況なのか、または応募者がチームにフィットするかなどを分析してくれます。

できることは

チームメンバの個人単位でのサポート

  • プロファイリング分析:メンバーがどういった価値観を持っているか。
  • メンタルパワー分析:各人のストレス耐性や感情統制力などの評価。
  • 個性活用マニュアル:それぞれが好む対応やNGワードなど。モチベーションを上げるために必要な事項などの提案。

面接のサポート

「こういった人材が欲しい」というのを社内のメンバーから選択すると事前に応募者に行ったアンケートから面接より前にAIが応募者の特性を分析し、その人がチームが求める人材かを分類してくれます。

 特筆すべきは”無料”という点。これならすぐにでも使い始めることができます。

WORKUP AI人事部長

 

 

<SNSなどから自動で情報を収集し、データベース化、マッチングするサービス>

5、Gild

サンフランシスコにある企業で、エンジニア採用向けのサービスを提供しています。

一般的なSNSだけではなく、エンジニアが利用するGithubやStack Overflowなどのプログラミング技術に関するコミュニティサイトや個人ブログなど、Webサイトをクロールして大量のデータを収集し、データベース化してくれます。(”スクレイピング”という手法を用いていると推測されます。)

エンジニアの実力は履歴書や面接だけでは、適切に評価することは難しいものですが、常に最新化されるビッグデータを独自のアルゴリズムで解析することで、エンジニアのレベルを可視化することができます。

さらにGild Spotlightという求職者として顕在化していないエンジニアが転職をしたくなるタイミングも推測して企業の人事担当者に推薦することができるサービスも提供してくれます。

Facebook、trip advisorなどの企業がGildのサービスを利用しています。

glid.com

 

6、Entelo

Enteloはサンフランシスコの企業で、人事担当者がエンジニアとデザイナーをWEB上から検索できるサービスを提供しています。

サービスの仕組みはGlidと似たようなもので、それにデザイナーの採用がプラスされたものです。

応募があった候補者のデータを簡単に管理・分析できるインバウンド向けのEntelo Stackと、自ら検索して候補者を探すアウトバウンド向けのEntelo Searchがあります。

Entelo Stackは、応募があった数多くの候補者のレジュメに対して、あらかじめ設けた基準と照合し、最良の候補者が優先的にリストアップできるサービスを提供しています。
人事担当者が自社にマッチした候補者を優先順に目を通せるため、選考プロセスや選考スピードの効率化につながります。

Entelo Searchは、膨大なデータベースから、ニーズにあった候補者を検索することが可能なサービスです。

候補者の転職検討タイミングの推測、ビジネススキル・人種・軍隊経験までわかる多様な検索軸、優秀な候補者のレコメンドなど多彩な機能があります。

Microsoft、Znefits、Facebookなどの企業がサービスを利用しています。

www.entelo.com

 

7、Talent Base

日本がリリースしているサービスになります。

お気に入りの人材をプールし一括管理することができます。また、作成した人材プールや行動履歴を解析して、各社に最適な人材を自動で発掘してくれます。

企業別にソーシャルでの影響度をランキングしたり、ゲームをすると勝手に友達を評価する「評価ゲーム」など、面白い独自コンテンツが入っています。

talentbase.io

 

 

<社員のエンゲージメントを数値化して評価してくれるサービス>

8、IBM Kenexa

「どんな特徴が社員の生産性にどう影響を与えるのか?」という曖昧なテーマに対し “既に学習済みのデータベース” を用いて、導き出された仮説に対して、即時「こうしたらいいのでは?」という提案までくれます。 

主に行われることは3つ

  • 設問ライブラリから5問程度を選択。オンラインで意識調査を実施。
  • 得られた回答を解析。WatsonAnalyticsの持つビックデータを活かし仮説を構築。
  • 数値をグラフィカルに明示しつつ、具体的な改善方法や対応策を提案。

世界の優良企業をランキングするフォーチュン・グローバルのTOP10企業の内8社までもが導入する、とても有名なツールとなっています。

www-01.ibm.com

 

9、HRMOS

日本の会社であるビズリーチが提供するサービスです。

できることは3つ。

  • 社員の成果、成果に対する上長コメントなどの言語解析。
  • 出退勤データや経歴データのディープラーニング。
  • 上記をベースとした『その企業が伸びるために採用するべき人材像』の明確な見える化。

IBM Kenexaに比べて、その会社の雰囲気を明確化するというところまで踏み込んでいるのがユニークな点です。

hrmos.co

 

10、Fronteo Kibit

こちらは上記二つとは趣旨が違い、”離職を防ぐ”を目的として作られたサービスです。

Fronteoは日本の会社で、AI業界ではなかなか有名な会社です。

従業員のメールをチェックして、

「離職しそうな可能性がある。」

「正当な評価を受けていないことをストレスに感じている可能性がある。」

「特定のリーダーからパワハラを受けている可能性がある。」

といったことをアラートで通知してくれます。

Watsonよりも安価で実装でき、過去にはわずか5件の教師データのみでユーザーボイスの感情判別を98%超の正答率で処理した実績もあるというAIです。

www.fronteo.com

 

・まとめ

最近のHRの流行はAI×ソーシャルデータという、技能をさらに詳しくみるだけでなくだけでなく、個人の特性や感情まで組み込んだ人事に移ってきているということが読み取れましたね。

 

参照

http://studyhacker.net/vocabulary/hr-tech

https://www.ibm.com/think/jp-ja/watson/cognitive-staffing/

https://www.hrpro.co.jp/agora/4272

https://bita.jp/dml/ai_hr

 

日本語版最速!? jupyter notebookをgoogleが神改造 colaboratoryについてまとめてみた。

こんにちは、たくやです。

最近すっかりニュース担当として定着してしまいましたね。

今回はgoogle が公開した教育と研究のための研究ツールである Colaboratory について解説していきたいと思います。

ざっと検索してみたところ英語版でしかまだ記事が出ていないようでしたので、日本語版最速と題させていただきました。

 

目次

・ニュース概要

・そもそもJupyter notebookとは

・Colaboratoryを使うメリット、デメリット

・実際に申し込みをしてコードを動かしてみた。

・おまけ Colaboratoryの気になるFAQ 

                                      

・ニュース概要

  • ColaboratoryはJupyter notebookを基盤としたオープンソースプロジェクト。
  • 現在、ColaboratoryはChromeのデスクトップ版でのみ動作する。
  • 優れたユーザーエクスペリエンスを提供するために、当初はノートブックの作成や編集へのアクセスを制限している。そのため、利用するには申し込みをしなくてはいけない。
  • ColaboratoryノートブックはすべてGoogleドライブに保存される。
  • 既存のJupyter / IPythonノートブックをColaboratoryにインポートできる。
  •  Colabは長年にわたりgoogle内部で使われるツールであったため依然として内部で使用されるPython 2.7のみをサポートしている。しかし、今後、Python3やRなどにも対応させていきたいとgoogleは考えている。
  •  Colaboratoryを使用すると、Jupiterのノートブックを他の人と共有し、ブラウザ以外のコンピュータでダウンロード、インストール、または実行することなく、共有することができる。
  • Portable Native Client(PNaCl)を使用しているため、安全に共同研究室はネイティブスピードで動作する。よって、新規ユーザーはjupyter notebookを以前より速く使用できるようになる。

PNaClとは

ウェブブラウザ上のウェブアプリケーションをネイティブアプリケーション(端末内の演算装置が直接に演算処理を行うタイプのアプリ)に近い速度で実行することなどを主な目標とした、機械語で書かれたコードを安全に実行できるシステムのこと。

 

                                      

・そもそもJupyter notebookとは

ブラウザ上で使えるプログラム実行環境です。ノートブックと呼ばれるドキュメントを作成し、プログラムの記述と実行、メモの作成、保存と共有などをブラウザ上で行うことができます。

以下Jupyter notebookのどこが魅力を箇条書きで書きます。

  1. Jupyter notebookの最大の特徴は”セル”と呼ばれる単位でコードを書いていける。複雑で冗長なコードも分割して実行することが可能。
  2. コードの実行が簡単。shit+Enter で簡単にコードが実行できる。
  3. 各言語のライブラリを使うことで出力結果を様々な形で表現することができる。例えばPandas というライブラリを使えば表の状態で結果を出力できる。
  4. 「保存・共有・再現」の利便性からデータ分析と非常に相性が良い。 

 

Jupyter notebookのインターフェイス

f:id:meteoputi:20171110004553p:plain

 

Colaboratoryのインターフェイス

f:id:meteoputi:20171110003310p:plain

実際に二つを見比べてみても、とても似ていることがわかると思います。

Colaboratoryのほうが、ちょっとオシャレな感じがしますね。

 

                                      

・Colaboratoryを使うメリット、デメリット

最後に、冒頭で述べたニュース概要から、ColaboratoryがJupyter notebookに比べて、どこが改良されたのかを簡単にまとめます。

  • 実行が早い
  • 異なるスキルセットを持つ人同士での”コラボレーション”が同じツール上で可能となる。
  • ノートブックを複数人で同時に編集することができる。
  • jupyter notebookとよく似ているが、jupyterのようにセットアップが必要ない。

Colaboratoryという名の通り、従来のJupyter notebookに比べて、共有能力が強化されているようです。

しかし、逆にデメリットも存在します。

  • 現状ではPython2.7 にしか対応していない。
  • 最新すぎて公開されている情報が少なすぎるため、困った際に検索しても解決策が出てきにくい。
  • 現段階では申し込みをする必要があり、即時使用はできない。

 

これからデータ分析、AI関係などで開発をする人にとってはとても心強いツールになりそうですね。

早く多言語に対応してくれるのを待つばかりです。

 

                                      

・実際に申し込みをしてコードを動かしてみた。

f:id:meteoputi:20171110044731p:plain

どうやらnumpy は入っているようでしっかり動きました。

 

f:id:meteoputi:20171113194828p:plain

乱数もしっかり発生させることができました。

 

 

f:id:meteoputi:20171113195531p:plain

また、pandasもしっかり使えるようです。

 

f:id:meteoputi:20171110044812p:plain

しかし、kerasは入っていないようです。
(!pip install keras と書いてインストールすることによって動くようです。)

 

f:id:meteoputi:20171110044755p:plain

少し見にくいですがエクセルの読み込みもうまくいきませんでした。

(こちらも!pip install xlrd と書くことによって正常に動くそうです。)

コメントくださった方、ありがとうございました。

 

最後に実際にcolaboratoryを使うと処理が早くなるのかを検証してみます。

・jupyter notebook の結果

f:id:meteoputi:20171110044844p:plain

 

・colaboratory の結果

f:id:meteoputi:20171110044835p:plain

残念ながら、colaboratoryの方が手元のjupyter notebookよりも倍以上時間がかかるという結果になってしまいました。

手元のPCは特段データ解析/ゲーム用に特化していない普通のノートPCなので、うーん。。。という感じですね。

まだまだ、ツールとしては不完全な上に、理論通りにはうまく動いていないのかもしれません。

実際に便利なツールとなるにはもう少し時間がかかりそうです。

                                      

・おまけ Colaboratoryの気になるFAQ

Q. コラボレーションノートを検索するにはどうしたらいいですか?
A. ドライブの検索ボックスを使用します。ノートブックビューの左上にあるColaboratoryロゴをクリックすると、ドライブ内のすべてのノートブックが表示されます。また、最近開いたノートブックを[ファイル] - > [最近開いたもの]を使って検索することもできます。

 

Q. 私のコードはどこで実行されますか?ブラウザのウィンドウを閉じると、実行状態はどうなりますか?
A. コードはあなたのアカウント専用の仮想マシンで実行されます。仮想マシンは、しばらくの間アイドル状態になるとリサイクルされ、システムによって最大限の有効期間が強制されます。

 

Q. データを取り出すにはどうすればよいですか?
A. これらの手順やColaboratoryのファイルメニューからGoogleドライブから作成したColaboratoryノートブックをダウンロードできます。 Colaboratoryノートブックはすべて、オープンソースJupyterノートブック形式(.ipynb)で保存されています。

 

https://research.google.com/colaboratory/faq.htmlk

から引用させてもらいました。

 

参照

https://research.google.com/colaboratory/faq.html

https://deepage.net/machine_learning/2016/12/13/jupyter_notebook.html

Deep Learning を使って背景イラストを生成した話

お疲れ様です.まっくす @minux302 と申します.

話が長いのでまずはブツを見せます.キャラクターに馴染むような背景イラストを Deep Learning の技術を使って生成していきます.ちょっと長いですがお付き合いいただければ幸いです.

 

f:id:minux302:20171110123021j:plain

秘められた力で背景写真を自分に馴染むように変換したと勘違いしている女の子のイラスト

 

1 背景と提案

1.1 背景

絵,描けるようになりたいですよね.

背景画,憧れますよね.

よく絵描きの方々が描く,アンニュイな表情した女の子が廃墟や浜辺に佇んでるやつ,描けるようになりたいですよね.

  

.......

 

描けないですよね....

 

 

趣味でちょこちょこキャラ絵とか描いたりするんですが背景画は全然描きません (描けません).

背景画を描く際には,キャラとはまた違った知識や技法とかが必要になってきます (多分).あと大変です.めっぽう大変です.

もうね,描く量が多い.そしてある程度はパースなりなんなりを意識して描かないと変な感じになっちゃう.

そんな僕でもやっぱりキャラに背景画を付け加えたい時があります.そういう時は写真を使います.もうすでにブツは描いてあるし,パースも完璧.最高.

案外写真でも,加工してうまいこと使えばかなりキャライラストに映えます.フォトショやクリスタでガシガシうまいことやれば,かなりいい感じになる(らしい).完璧じゃん.

blog.nest-online.jp

 

1.2 問題点

でもやっぱり加工した写真の中にキャラクターを立たせても浮いてしまうんですよね.技術不足などもあるでしょうが以下の点あたりが自分は気になります.

  • 色合い
  • 質感

そのままバンとキャラをのせても,彩度とか色相とか全然違ったりして浮いちゃいますよね.

もう一つは質感(や描き込み量).写真は本当に細かいところまで描いてあるし,色の塗り方(?)も全然違う.絵描きの方はキャラを描いてるのと似たような筆で,似たような塗り方で背景画を描いたりしているので,いい感じにキャラが浮かず馴染んでいるように思います .

 

1.3 提案

そこで,加工した背景写真からキャラが浮いちゃう問題を Deep Learning ってやつでなんとかしたいと思います.今回は 画風変換 の技術を使いました.一時期話題になったので皆さんも多分ご存知だと思います.ゴッホの絵のスタイルを写真に反映させました!って画像をよく見ましたよね. 

 

f:id:minux302:20171110094342p:plain

本家の人たちのHPから引用した図(https://deepart.io/).1の背景写真に2のゴッホのスタイル反映させ3を生成している

 

 今回のブログは,この画風変換の技術を使って,自分が描いたキャラクターの塗りのスタイルを写真に反映させて,キャラクターに馴染んだ背景写真を生成しよう!と言うお話です.

上図のゴッホの場合のように,キャラの質感を風景写真に反映させたらキャラが浮かないような背景画像が生成されるのでわ?という目論見です.

画風変換については以下のページがとてもわかりやすくまとめられています.

画風を変換するアルゴリズム

Neural Style Transfer: Prismaの背景技術を解説する

 


2 画風変換について

2.1 画風変換の流れ

画風変換の技術では,画像を"コンテンツ"と"スタイル"に分けて考えます.コンテンツとは,物体を物体として認識するための情報,つまり輪郭などのことです.スタイルはテクスチャなど,質感のことです.以下,画風を変換させたい画像をコンテンツ画像,反映させたいスタイルを持っている画像をスタイル画像とします.

画風変換は何をしているかというと,コンテンツ画像において,コンテンツを保ちながらスタイルを弱めて,スタイル画像のスタイルと入れ替えてしまおう,ということをしています. 

そうなってくると,

1. どのようにしてコンテンツを保ちながらスタイルを弱めるか

2. スタイルをどうやって獲得するか

ということが必要になってきます.

 

2.2 画風変換の大雑把な中身 

2.2.1 どのようにしてコンテンツを保ちながらスタイルを弱めるか

下図は画像認識に用いられる Deep Learning の中身です(VGGモデル).Deep っていうくらいなので深いです.深いってのは図のように層が何層にも重なってるという意味です.左から画像が入力され,だんだんと層を経て右側から値が出力されます.

このVGGモデルはもともと画像認識のタスクに使われていたモデルです.画像認識とは,猫の画像を入力した時に,それが猫の画像であると判定できるようなタスクです.

このモデルに画像を入力すると,物体を認識するのに必要な情報だけ抽出されるように画像が変換されていきます.物体を認識するのにどんな情報が必要かと言われれば,物体の輪郭などが考えられます.反対に質感などはあまり必要ありません. 

 

f:id:minux302:20171110101213p:plain

VGG モデル


このVGGモデルに画像を入力することにより,コンテンツを保ったままスタイルを弱めることができます. 

実際に画風変換の論文 A Neural Algorithm of Artistic Styleh から引用した図を下図に載せます.下方の家の写真では,実際にVGGモデルに画像を入力して,各層から得られる情報から画像を再構成しています.なんとなく深い層の部分では画像の質感等が失われて,輪郭だけが残るようになってるように見えませんか?.

 

f:id:minux302:20171110100236p:plain

VGGモデルの途中の層から得られる情報から画像を再構成

2.2.2 スタイルをどのように獲得するか

次にどのようにして画像のスタイル(質感)を獲得するのか,ということについて述べます.まず何かを獲得するには相手を見定めなければなりません.つまりどのようにスタイルを定義するか,ということです.

VGG の途中の層からは何枚かの画像データが取得できます.この論文では,それらの画像間での関係性(相関)によってスタイルを定義しています.詳しいことは数式を用いないの説明できないのですが,これを用いることによって画像の色,線の太さやテクスチャなどの情報が獲得できます.

この定義によって定められたスタイル情報を元に画像を再構成した結果が上図の上方の図です.各層からゴッホの絵のスタイルが再構成できているように見えますね.

 

2.2.3 どのように学習するか

次にどのように学習していくかという話をします.

Deep Learning では"損失関数"というものを定義して,それを最小化するような学習を行います.損失関数はどれだけ欲しいものが得られているかの指標となります.この値が小さいほど,欲しいものが獲得できていることになります.

今回は,生成された画像が

  • どれだけコンテンツ画像のコンテンツを持っているか (\mathcal{L_{contents}} とします)
  • どれだけスタイル画像のスタイルが反映されているか (\mathcal{L_{style}} とします)

ということが指標となります.生成された画像がコンテンツ画像と同じコンテンツであれば \mathcal{L_{contents}} = 0であり,コンテンツ画像からコンテンツが離れるほど \mathcal{L_{contents}} の値は大きくなります.\mathcal{L_{style}} についても同様のことが言えます.

指標が二つあるので和をとり以下のように損失関数 \mathcal{L_{total}} が定義されます.

\mathcal{L_{total}} = \alpha \mathcal{L_{contents}} +\beta \mathcal{L_{style}}

\alpha, \beta はどれだけコンテンツ,スタイルの差を損失関数に反映させるかを決める重みです.これらのパラメータは人間が決める必要があり,そのようなものをハイパーパラメータと言います.後々出てくるので覚えておいてください.

今回はこの \mathcal{L_{total}} が小さくなるような画像を生成するように学習が進んで行きます.VGGの重みは固定で,入力となる生成画像がどんどん更新されていきます.

 

以上が画風変換の大雑把な流れとなります.

 

3. 実験

3.1 環境

OS: Ubuntu 16.04, CP: Intel Icore 7, Memory: 16G, GPU: GForce 750Ti

今回は以下のリポジトリのものを使用しました.画風変換(Neural Style Transfer)をTensorflowで実装したものです.嬉しいことに --preserve-colors のオプションをつけることで元画像の色を保持できます.

github.com

 

3.2 とりあえず動かす

今回はコンテンツ画像として次の写真を使いました.香川に1人旅に行った時の夕焼けがとても綺麗だったので撮りました.

 

f:id:minux302:20171110110713j:plain

コンテンツ画像

まずは試しにゴッホの絵をスタイルとして画像を生成します.うん,いい感じで吐けてる.

 

f:id:minux302:20171110111011j:plain

ゴッホのスタイル画像を使った時の生成画像


次にいらすとやさんの背景画像をスタイルとして使ってみます.

 

f:id:minux302:20171110113632j:plain

スタイル画像(風景画)

以下が生成結果です.なるほど.ちょっと角ばった感じの質感になってますね.

f:id:minux302:20171110113748p:plain

いらすとやの風景画をスタイルとして使った場合の生成画像


次に,キャラ画像をそのままスタイルとして使います(野蛮).

 

f:id:minux302:20171110111135p:plain

スタイル画像(キャライラスト)

 

あいや,変になってしまった.やっぱりキャラ画像をそのまま使うのは野蛮だったか?

 

f:id:minux302:20171110114000p:plain

いらすとやのキャラ画像をスタイル画像として使った場合の生成画像


 

3.3 適切なハイパーパラメータを探す

Neural Style Transfer: Prismaの背景技術を解説する にも述べられていたんですが,用いる画像によって適した \alpha, \beta の値が異なるらしいです.諦める前にこの写真とキャライラストの組み合わせにあったハイパーパラメータを探索して行きます.

探索にはグリッドサーチという手法を用いました.あらかじめ \alpha, \beta ( この実装の場合は content_weight と style_weight)の値をいくつか決めておき,それらの組み合わせを全部試していくという手法です.

今回辛いのが定量評価ができないということ.損失関数の値が小さいからといって実際の画像がいい感じにスタイルが反映されたものにはなってないんですね.\mathcal{L_{contents}}\mathcal{L_{style}} の散布図などを書いたりしましたが,良い生成画像の傾向などはあまり見られませんでした.(強いて言うなれば\mathcal{L_{contents}}\mathcal{L_{style}} の比率が,値が小さい時に1:3くらい,値が大きい問いに3:1になってるくらいだったが,ここら辺はあまり詳しくは見ていません.)

色々試した結果,以下の場合が一番いい感じになってると思いました.

content_weight = 0.001, style_weight = 0.1 で500イテレーションで生成しています.実行コードに追加で --content-weight 0.001 --style-weight 0.1 --iteration 500 --preserve-colors のオプションを付け加えています.

キャラ画像のそのままの使用でも,塗りの感じとか割といらすとやっぽいものが反映されているように見えませんか??

 

f:id:minux302:20171110092636p:plain

content-weight = 0.001, style-weight = 0.1 500イテレーションで色を保持した場合に生成された画像

 

先ほどのキャラ画像と合わせて少しいじるとこんな感じ.まぁまぁなんでないでしょうか.

 

f:id:minux302:20171110123021j:plain

合わせた画像

 

4. 反省と今後の展望

今回は思いつきでとりあえず試してみるかという感じでやりましたが,やっぱり余白が結構あるキャラ画像を無理やり使うのは自分でもかなり野蛮だと思っています.キャラのスタイルをキャラに反映するならまだいいですが,キャラのスタイルを風景写真に反映させるのはちょっと無理があったように思います.スタイル画像もこの場合はたまたまいいものが生成できましたが,割とうまくいかない場合が多かったです.(下図のようにだいたい画像が壊れた感じになる).このスタイル画像としてのキャラ画像の扱いの仕方を工夫していきたいです.あと以下のように新しい画風変換の技術もあるのでそこらへんも試していきたいです.

 

f:id:minux302:20171110105643p:plain

うまくいかなかった例



 

github.com

 

 

5. まとめ

画風変換を使って,キャラのスタイル反映したような背景画像の生成を試みた.ハイパーパラメータおじさんになればなんとなくうまくいってるように見える場合もある.正直キャラ画像をそのままスタイル画像として風景写真のスタイル変更に使うのはあんまりよくなさそう.

 

良い所

GPUを持っていてパラメータチューニングを頑張れば,キャライラストに馴染みそうな背景画像が生成できる(かもしれない)(ちなみに500iteration 18枚生成とかで1.5hくらいかかった)

 

悪い所

背景画を描く練習をしないので,一生描けるようにならない.ネコと和解せよ.にゃーん.

 

 

おしまい

 

おまけ

いらすとやの風景画を

--content-weight 0.001 --style-weight 0.1 --iteration 500 --preserve-colors

で動かした時のもの.色が暗くなっていて見にくいですが,ビルの塗りの筆の感じなど,かなりいらすとやっぽいと個人的に思う.

 

f:id:minux302:20171110114541p:plain

 

自分が過去に描いたイラストで試した.

--content-weight 0.001 --style-weight 0.1 --iteration 500 --preserve-colors

で動かした.微妙.

 

f:id:minux302:20171110114932p:plain

 

6. 参考文献

https://deepart.io/

https://elix-tech.github.io/ja/2016/08/22/art.html

https://research.preferred.jp/2015/09/chainer-gogh/

https://arxiv.org/pdf/1409.1556.pdf

http://www.irasutoya.com/

 

 

【初心者】でもわかる、最近巷で有名な"AlphaGo Zero"の仕組み

こんにちは、たくやです。

今回はちょっと旬を逃してしまった感はありますが、とても話題となったAiphaGo Zeroの仕組みについてプログラミング初心者にもわかるような解説をしていきたいと思います。

 

・ニュース概要

  • AlphaGoが過去のAI囲碁ソフトと違うところは、人間のうち筋をデータとして与えなかったこと。
  • 自身が相互対戦することで最善手を学習する手法を3日間に500万回繰り返させることで棋力を向上させた。
  • AlphaGo Zeroはトップ棋士を打ち負かして驚かせた「AlphaGo」に対して100戦全勝、その改良版である「Alphago Master」にも100戦中89勝した。

 

natureのAlphaGo Zeroに関する論文である"Mastering the game of Go without human knowledge"(人間の知識なしに碁を制する。)

https://www.nature.com/articles/nature24270.epdf?author_access_token=VJXbVjaSHxFoctQQ4p2k4tRgN0jAjWel9jnR3ZoTv0PVW4gB86EEpGqTRDtpIz-2rmo8-KG06gqVobU5NSCFeHILHcVFUeMsbvwS-lxjqQGg98faovwjxeTUgZAUMnRQ

を簡単に噛み砕いて説明していきたいと思います。

複雑な数式や専門用語などはできるだけ取り扱いません。

 

まず、これほどまで圧倒的な強さを手に入れたAlphaGo Zeroが前のバージョンであるAlphaGo Lee12やAlphaGo Fanと異なる点をもう少し技術的な面から説明していきます。

あげられる点は以下の4点。

 

  1. 人間のデータを監督したり使用したりすることなく、ランダムプレイから始まる自己再生強化学習のみによって訓練される。
  2. 移動確率を出力するPolicy Networkと位置評価を出力するValue Networkを別々にするのではなく、単一のニューラルネットワークで使用する。(前バージョンではPolicy NetworkValue Networkという二つのディープニューラルネットワークを使用していた。)
  3. 迅速な改善と正確で安定した学習をさせるために、訓練ループ内にルックアヘッド検索を組み込んだ新しい強化学習アルゴリズムを導入した。
  4. モンテカルロ法のロールアウト(その盤面から全ての打ち方を試して、その結果どの打ち方がいいのかを判断する方法)をやめ、モンテカルロ木探索のみにした。(このことが使用するマシンパワーの圧倒的削減に貢献している。)

 

これらについて、解説していきます。

 

AlphaGoZeroが学習時に基本的にやっていることはモンテカルロ木探索です。

*モンテカルロ木探索とは

例えばAとBという場所のどちらに石を置くかを考えるとき、Aに石を置いたとき、Bに石を置いた時、それぞれ、その先対局を続けていった時に何パーセントの確率で勝てるのかを評価することでA,Bどちらに石を置くかを決定する手法です。

                              f:id:meteoputi:20171103124137p:plain


 

ただし、そのモンテカルロ木探索にディープニューラルネットワーク(DNN)を組み合わせてあります。

ディープニューラルネットワークがわからない方はこちらをお読みください。

今話題のディープラーニングって一体なんなの? 文系から見た人工知能

 

つまり、石の配置履歴を取り込んで、自己対戦により移動確率を出力するPolicy Networkを、モンテカルロ木探索を使用して求めた次に打たれる可能性のあるそれぞれの手に対する評価値(仮にそこに石を置いた場合の勝率の確率)に反映します。なぜ、最初から自己対戦による移動確率だけで次に打たれる手を考えないのかというと、モンテカルロ木探索を用いることで、より良い一手が発見される可能性があるからです。

それとほぼ同時に、自己対戦の終局図から勝敗を判定し、位置評価を出力するValue Networkの教師として反映します。

Policy(どこに石を置くか)← モンテカルロ探索木

Value(盤面の評価値)← 試合の勝敗

 

よって取り扱われるデータは、

・Policy(移動可能性)

・Value(位置評価)

・最後にわかるどちらが勝ったかというデータ 

の3つだけになります。

                     f:id:meteoputi:20171103123642p:plain

 

*モンテカルロ木探索を用いるのはあくまで学習時だけで、実際に対局する際はニューラルネットの出力のみで判断するので、本番での計算速度が向上しました。

 

さらに詳しくみていきましょう。

AlphaGo Zeroのモンテカルロ木探索は3つのステップに分けることができます。

(次にどこに石を置くかを決める段階なので、まだ実際に石は動かしていません。)

  1. 選択
  2. 拡張と評価
  3. バックアップ

1の ”選択” では一番最初の配置からある程度、ゲームを進めていった配置まで、評価値が高いところに石を置いていきます。

2の ”拡張と評価” では1の操作でゲームが終了しなかった場合、その最後の時の盤面をDNNにインプットして、その時点で勝てる確率と、その次の手の確率分布を計算します。(AlphaGo Zero ではモンテカルロ木探索で1600回のシミュレーションを行ったため、一手を考えるのに0.4秒かかりました。)

3の "バックアップ " では2の最終盤面で得られた評価値の平均を元々の盤面に反映します。それの平均値が元々の盤面の新しい評価値となります。

 

1〜3のステップを通して導き出した最良の手を選択します。

 

しかし、ここで「教師となるデータもないのに、どのデータを元に学習をさせているんだ」という疑問が生まれると思います。

従来のAlphaGoではここに人間のプロ棋士のうち筋を用いていました。

しかし、AlphaGo Zeroでは自己対局を繰り返すことによってデータを作り出しているのです。

最初はもちろん、全てランダムで行うために、文字通り”ゼロ”からの成長になります。

 

今まで説明してきたことを図にしてまとめます。

f:id:meteoputi:20171103142800p:plain

 

最後にこのAlphaGo Zeroのすごさを端的に表している画像があるので紹介します。

f:id:meteoputi:20171103135436j:plain

上の画像は横軸に何日AlphaGo Zeroをトレーニングしたか。

縦軸に、強さを数値化したものを取っています。

3日トレーニングした時点でもう既に2016年元世界チャンピオンのイ・セドル氏を倒したAlphago Leeの強さのレベルに達していることわかります。

f:id:meteoputi:20171103140107p:plain

しかも消費するマシンパワーはAlphaGo LeeやAlphaGo Fanに比べて圧倒的に低いことがこの図からもわかります。

 

人類はこれまで4千年もの時をかけて、数百万の碁の試合をし、それをパターンとして色々な本にまとめてきました。しかし、AlphaGo Zeroはそのほとんどの知識を発見し、それに加え斬新な戦略までも見つけ出しました。

中には、将来、AIが人間よりも優れた発明能力を身につけてしまうのではないかと恐れる方もいるかもしれません。しかし、局面が変わるに従って変化する戦略をどのように数値化し、反映させるのかプログラムするのは、あくまで人間なのです。このAIの圧倒的な自己学習能力を人間がうまく使うことで、人間の能力を拡張させるツールとして使うこともできるのです。

 

参照

http://toyokeizai.net/articles/-/194179

http://blog.livedoor.jp/yuno_miyako/archives/1068350228.html

https://www.slideshare.net/suckgeunlee/alphago-zero