今季見るべきアニメを機械学習で推薦する

Coursera で機械学習に入門成功できたので応用に挑戦してみました。ちょうど季節の変わり目ということで、過去に見て気にいったアニメの特徴を学習して、未知のアニメを、気にいりそうなアニメと気にいらなそうなアニメに分類するツールを作って、ソフトウェアに今季見るべきアニメを推薦してもらいたいと思います。

アニメの特徴量

あるアニメを気にいるかどうかは、話のおもしろさや、絵柄の感じ、キャラクターの魅力などによって決まりそうです。ただ、話のおもしろさや、絵の美しさ、キャラクターの魅力を特徴量として数値化するのはむずかしいので、アニメの映像を制作しているスタッフや会社、声を当てているキャストにフォーカスすることにしました。

Courseraの機械学習のコースでは、特徴として妥当かどうかを判断するのに、人間が同じ特徴を与えられて分類といったタスクが可能かを考えてみよとアドバイスしていました。アニメ作品の制作会社や監督、脚本、出演声優の名前を見ればなんとなく自分に合いそうなアニメかはわかる気がするので、特徴としては良さそうです。

特徴ベクトルの表現

各成分がアニメの制作会社やスタッフ、キャストなどに対応するような、ベクトルを考えます。あるアニメの特徴ベクトルは、そのベクトルによって表現します。ベクトルの各成分の値はその成分に対応するキャストやらが、そのアニメに関係していれば1していなれば0とします。例えば以下のようになります

タイトル属性 サンライズ 鳥海浩輔 櫻井孝宏 中村悠一 沢城みゆき 遠藤綾 金元寿子 ...
鉄血のオルフェンズ 1 1 1 1 0 0 1 ...
ワンパンマン 0 1 1 1 1 0 0 ...
おそ松さん 0 0 1 1 0 1 0 ...

ここではベクトルの大きさは7くらいですが、実際にはもっと沢山のアニメ関係者をベクトルに対応づけます。今回は学習に使ったアニメと推薦する対象になる今期のアニメの関係者を、出現頻度のおおいほうから1000くらい選びました。

しょぼいカレンダーの利用

アニメに関係している制作会社やスタッフ、キャストを自分で調査するのは非常に大変なので、いつもお世話になっているしょぼいカレンダーを利用させていただきました。

しょぼいカレンダーにはアニメ作品ごとのページがあって(例: http://cal.syoboi.jp/tid/3424)、スタッフやキャストの情報がそこにまとめらています。公開されているAPI を利用すれば、この情報を取得できるので利用します。

また、しょぼいカレンダーは各アニメにIDを振ってくれているので、そのIDをプログラム中で特定のアニメを指定するための識別子として利用させてもらいました。

過去に見たアニメの評価

自分の好みを学習して使いたいので、過去に見たアニメに対してラベル付けしていきます。ラベルはそのアニメを自分が特に気にいっていれば1を、そうでもなければ0をつけます。

ラベルづけのために、2013年から2015年に放送されたアニメを順番に表示して評価を入力できる、簡単なスクリプトを書きました。このスクリプトを使って、アニメにどんどん評価をあたえていってるのが以下の画像です。yと入力すれば特に気にいってる、それ以外はそうでもないという意味です。この調子で580個くらいのアニメを評価してラベルを付けました。

f:id:hakobe932:20160415142003g:plain

ニューラルネットワークを使った分類器

ここまでで580個くらいのラベル付きのアニメの特徴ベクトルが得られましたので、このデータに基づいて分類器を構築します。機械学習による分類器の手法をいろいろ試してみましたが、一番うまくいったニューラルネットワークを使った分類器を紹介します。

ニューラルネットワークの分類器を自分で丁寧に作っても良かったのですが、できるだけすでにある物を使うべしと、Courseraの機械学習でもいってましたし、Chainerを使ってみました。

Chainerではニューラルネットワーク自体は以下のように定義します。これは3層のニューラルネットワークになるような計算グラフを構築しています。入力ベクトルの長さを1000としているので、入力層は1000ノードあります。隠れ層は100ノードあって、出力層は2ノードです。活性化関数としてはsigmoid関数を使っています。

出力は長さが2のベクトルになっていて、1番目の成分の値は、入力された特徴ベクトルが0にラベル付けされるべき度数をあらわします。2番目の成分の値は同様に、入力された特徴ベクトルが1にラベル付けされるべき度数をあらわします。

from chainer import Chain
from chainer.links import Linear
from chainer.functions import sigmoid

class AnimeChain(Chain):
    def __init__(self):
        super(AnimeChain, self).__init__(
            l1=Linear(1000, 300),
            l2=Linear(300, 2)
        )
    def __call__(self, x):
        h1 = sigmoid(self.l1(x))
        o = self.l2(h1)
        return o

このニューラルネットワークに特徴ベクトルと正解のラベルを学習させるような関数を定義します。この関数では、ある段階でのニューラルネットワークで計算した結果と本来得たい数値の誤差を計算して、その誤差に基づいてニューラルネットワークを誤差が最小になる方向に更新していきます。この時に誤差を計算グラフの逆方向に伝搬させていったりする必要があるのですが、そこはライブラリがうまく隠蔽してくれていて、たくさんコードを書かずにすんでいます。細かなコードの意味はChainerのチュートリアルなどを参考にしてください。

from chainer.optimizers import Adam
from chainer import Variable
from chainer.functions import softmax_cross_entropy

# 各アニメの特徴ベクトルを持つ行列Xと、
# 各アニメへのラベル付けの結果を含むベクトルtを受けとって計算する
def train(X, t):
    model = AnimeChain() # 定義したニューラルネットワーク
    optimizer = Adam()   # Adamという方式を使って最適化する
    optimizer.setup(model)

    for e in range(1500):
        V_X = Variable(X) # 計算グラフに値を与えるときはVariableにくるむ
        V_t = Variable(np.array(t, dtype='int32'))

        V_y = model(V_X)
        model.zerograds()
        loss = softmax_cross_entropy(V_y, V_t) # 誤差を計算
        loss.backward()    # 逆伝播させてXの各成分ごとの誤差を計算
        optimizer.update() # 得られた誤差にもとづいてパラメータを更新
        if loss.data < 0.001: # lossが十分小さくなるまで繰り返す
            break
    return model

このtrain関数に対して、用意したアニメごとの特徴ベクトルと、手でがんばって入力したラベルを教師データとして与えることで、その内容を学習した分類器ができあがります。

教師データをあたえるときには1とラベル付けされたデータと0と、ラベル付けされたデータの数が同じになるように、オーバーサンプリングしました。0とラベル付けされたのほうが多かったので、オーバーサンプリングしないとあまり性能がでませんでした(F値で0.6くらいになってだいぶしょぼい)。

分類器の性能

用意したラベル付きのアニメの特徴ベクトル群を教師データとバリデーションデータにわけたあと、教師データをつかって学習した分類器でバリデーションデータのラベルを予測できるかどうかを確認しました。評価値としては、F値を使います。

この分類器の学習曲線は以下のようになります。教師データの数を増やせば増やすほど、バリデーションデータにおけるF値が0.9以上となっており、うまく学習できていることがわかります。だいたいサチってそうですが、教師データを増やすともうすこし良くなるかもしれません。

追記: 2016/04/16 12:54

オーバーサンプリングした結果をそのあとシャッフルしていたので、教師データとバリデーションデータに同じデータがはいってそうでした。細かくしらべてますが、こんなにスコアは良くなさそう..。0.7とかくらいでは...。グラフもまちがってそうです。

追記: 2016/04/16 22:20

評価については別にエントリを書きました。

hakobe932.hatenablog.com

実際に予測してみた

この分類器を使って実際に僕が今季見るべきアニメを予測しました。

僕が気にいったアニメを学習した分類器の結果なので、他の誰の役にも立ちませんが、自分としてはふむふむ納得という結果が得られました。けいおんの再放送がはいっていますが、ここ3年くらいのアニメしか教師データとしてあたえていないはずなので、これも機械によって予測されているはずです。けいおん最高。

実際のコード

Python3で書いたコードが素朴にGitHubにおいてあります。気がむいたら実行の仕方など書こうかと思います。 READMEに実行の仕方を追加しました。

追記:

↑のように雑な紹介しかしていないのに使ってみてくださってる方がいました! 実行の仕方の解説もあってすごすぎる!

wiroha.hatenablog.jp

続々ためしていただいています

zfhrp7.hatenablog.com

今季見るべきアニメを機械学習で推薦する - はこべブログ ♨

手元で実行した結果、カードキャプターさくらとけいおん!を見れば良いことが分かった

2016/04/15 20:15
b.hatena.ne.jp

まとめ

というわけで、Coursera で機械学習を学んだ成果として今季見るべきアニメ推薦くんを作ってみました。アニメの制作にかかわる、キャストとスタッフの人名にもとづいた特徴に基づいた学習で、なかなかの分類精度が出ることがわかりました。(追記: 2016/04/16 13:35 測定がミスっていて精度でているか謎です.. => 精度についての記事 を書きました。) 。そこそこ便利なツールができたと思います。

ここでは一本道で紹介しましたが、実際のところはロジスティック回帰やサポートベクターマシンなどいろんな手法をためしてみたり、あれこれパラメータ変更してみたり試行錯誤を重ねました。一週間くらいはF値が0.6からあがらなくてあきらめかけたものの、ためしにオーバーサンプリングしてラベルが1と0の教師データの割合を1:1にしたところめっちゃくちゃ精度があがったりして、良い学び体験を得られましたこれまちがってそうでした..つらい。

とにかく何か作ってみることには成功したのでニコニコしつつも、よく理解してないところも沢山あることもわかったので、なんか勉強します。

Coursera の Machine Learning 完走

CourseraのMachine Learningのコースを完走できた。11週間くらいかかったけど、かなり効率良く機械学習について学べてとても良かった。

コースは機械学習の手法について広く教えてくれる。教師あり学習の線形回帰やロジスティック回帰、ニューラルネットワークの構築の仕方、教師なし学習のK-meansや主成分分析などなど。それだけでなく、実践的な技とか勘所を教えてくれるのが良い。例えば、大量の教師データを集める前に、データ増やして改善しそうな性質になっているかを確認して、半年とかを無駄にしないようにしましょうとか、まずはシンプルな手法に取り組んで様子をみながら難しい手法を試してみると良いでしょうとか。

一週ごとに宿題があって理解を確認できるようになっている。宿題にはプログラミングの課題もあって、実際に機械学習のプログラミングの雰囲気を体験できる。単にアルゴリズムを実装するだけではなくて、グラフの様子をみながら改善していくといったフローになっていて自分でやるときも同じようにできそうで良い。簡単にはループで実装するところを、ベクトル化してシンプルな見た目、かつ高速に動作するように改良したりするのは、パズルっぽくておもしろかった(前もちょと書いてた)。

数学の知識がないと大変そうって思っていたものの、うろ覚えの基礎的な微分積分と線形代数でなんとかなった。とはいえ、手法の裏付けは数学的に証明されているので、できたらより納得感は高そう。もうちょっと理解したくて、微分積分勉強してる。微分積分は電子工学勉強するのにも使えるので便利そう。

f:id:hakobe932:20160409120611p:plain

11週間も時間を見つけてはビデオみたり、休みの日に宿題したりでちょっと忙しかった。しかし、機械学習分野のとっかかりを得るにはとても良くて、勉強して良かった。機械学習を使って自分で何か作ってみたりできそうだし、次に何を学ぶべきかもなんとなくわかる。何か役立つものを作ってみたい。

最後のビデオでは先生がそんな僕らに労いと感謝の言葉を繰り返し投げ掛けてくれて、涙なしでは見れないという感じでよかった。おすすめです。


あわせて読みたい:

blog.sushi.money

国立科学博物館

遊ぶ用事があって東京をうろうろしてる。土曜日はちょっと時間が余ったので国立科学博物館に行ってきた。



あんまり調査せずに行ってみたもののとても良かった。すごい豪華な理科室という趣で、恐竜から宇宙から産業機械からとにかく広範囲をカバーしたおもしろ展示が無限にある。理科の図鑑に載ってたいろんな動物の剥製があって見比べられるし、トリケラトプスやアーケロン、鯨の骨格は迫力がすごい。水中に浮いてる砂鉄が地場の中で整列する様子を確かめられるし、電磁誘導で遠くのLEDが光る様子を眺められる。

ただ、とにかく展示の分量が多くて全然回りきれなかった。3時間くらいいたけど3割くらいしかみれてない。油断してた。あと2回くらい訪れてコンプリートしたい。

(明示的に禁止されてる展示以外は写真が撮れる。)

計算機の歴史のコーナーがよくて真空管式やリレー式の巨大なコンピュータを眺められる。インテルのi4004とかも置いてあった。

ちまちまポケモンやってる

初代ポケモンが3DSのバーチャルコンソールで発売されたのでちまちまやってる。先日からビーダマンやっていたりとマインドが20年前に戻りつつある。

初代ポケモンはさすがに近代のポケモンと比較するとグラフィックなどは素朴なもののやっていておもしろくてすごい。次はあのポケモン進化させるぞ!とかどうやったら隣町に行けんるだ??とか、次々とやることがでてきて飽きない。モブが次にやることをあんまり言ってこないのがいいのかも。そのかわりミスるとフラッシュなしでイワヤマトンネルを抜けることになる。

いまはヤマブキシティやってきたところなので中盤くらい?もう少しすすんだらだれかポケモン交換したり対戦したりしましょう。


ガルパン 4DX

せっかくいただいてる休みを生かさねばと、ガールズ & パンツァー 劇場番の4DX上映を見にいってきた。

京都から4DXを見にいくとなると、今のところはエキスポシティに行くのが近い(夏には桂側イオンモールに劇場ができるらしい)。3日前から予約できて、日がまわったあとにしゅっと手続きしたら予約できた。平日だから比較的予約が殺到しなかったというのもあると思う。

ガルパンの劇場版は普通の劇場で一度見たことがある。4DXはまったく経験がなかった。とにかくはじめはイスが揺れる演出に慣れなくて、なんだか気持ちわるくなってきて、これがあと一時間以上続くのはきびしいな、と感じた。ただ、そのうち徐々に慣れてきたのか、あるいは振動の演出の具合がよくなってきたのか、最終的には揺れの演出にうまくのっかって楽しめるようになった。めっちゃくちゃ揺れるんだけど、うまく椅子にしがみつくと体勢が安定して見やすくなる。それでも体調悪い時に見るのはきつそう。

ガルパンと4DXの相性は評判どおり良く、臨場感がでて作品の世界に没頭できるのが良かった。雨のシーンが良くて、演出で水滴が上から落ちてくるのだけど、これが結構、実際の雨のうっとおしさというか嫌な感じを思い起こさせる。雨によってネガティブさを強調するシーンだったので、作品に入り混んでいる感がより高まった。戦車同士の戦闘シーンの良さは言わずもがな。戦車がきる風や、激しい旋回による遠心力、弾丸発射による振動など、映像に関する情報量がめっちゃ増えて迫力がとにかくすごい。最後の戦闘シーンでは4DXに慣れたのもあってか、揺れなんかの4DXの演出を自然に受けいれられていて、作品世界への没頭感がすごかった。

全体的にはすごくおすすめで、映画一度みて良かったひとはぜひ4DXも挑戦されたい。4DXを経験してると特に気持ちわるくなったりはならず、はじめのほうのシーンもたのしめそう。自分も慣れた状態で最初のほうが見たい気もするけど、ちょっと見にいくのがたいへんなのでまぁいいかな、という気はする。桂川でリバイバル上映してたら見にいきます。

温泉観光

温泉街を観光してきた。


めっちゃ湯気でてる。地下200mくらいから湧いてるらしい。


滝もあるぞ。

f:id:hakobe932:20160223224342j:image

おもちゃ博物館みたいなところにあった良い積木が良かった。なんか変わった形をしていて、多様な方法で組み合わせることができる。丁度解説タイムに出くわして、おもちゃ博士みたいな人がいろんな技を披露してくれた。

観光といっても近所をぶらぶらするくらいで、だいたいゆっくりしてた






宝塚に挑戦したぞ

f:id:hakobe932:20160222213111j:image
はじめて宝塚を見に行ってきた。演目はるろうに剣心で宝塚初心者でも話はだいたい知ってる演目なので安心。

平日なのに当然のように満席だった。そして、ほぼ女性の方しかいなくてびっくりした。男性とはお手洗いにいくと会える。

演劇は大変楽しめた。ミュージカル仕立てでリズミカルに話が進む。原作と比較するとすごいスピードで話が展開するけど意外と気にならない。役者さんのセリフ回しや動きもメリハリが効いていてかっこいい。全体的な調子に乗せられて話に入り込んでしまう。

ストーリーがひととおり終わると、メインのキャストの方々それぞれのパフォーマンスやら、大勢によるラインダンスやらを得て、大団円を迎える。(フィナーレというらしい?)。この部分はまさに宝塚という感じで満足感がたかい。ストーリーの部分では武士の格好をしていた人も後ろに大量の羽をつけて登場したりして、急に華やかになる。

一つの公演の中でもいろんな方面で楽しませてくれて、確かに何度も見に来たくなるのはわかるという感じだった。宝塚は京都からだと若干とおいのがつらいものの、折にふれてみにいくのもよさそう。次は双眼鏡借りてチャレンジしたい。

今日は温泉宿でゆっくりします。