とある三流プログラマーの覚書

機械学習、自然言語処理を中心にIT系の話題を書いていく予定です

未来的技術のキュレーションサイトを作ってます

はじめに

すごく久しぶりの投稿になってしまいましたが、元気にやっています。

しばらく、機械学習で株価予測みたいなことをやろうとしてたんですが、全然上手く行かないので、一旦中断しました。

基本に立ち戻って、機械学習でキュレーションをやってみようと思ってます。

キュレーションサイト

これまでに取り上げてきた人工知能を含め、VRやIOTのような最先端技術に興味があるので、未来的な最先端技術のキュレーションサイトを作ってみようと思ってます。

とりあえず、はてなブックマークツイッターから、関連キーワードで、記事を収集して表示するところまで作りました。

今のところ無関係の記事もたくさん表示されてしまっているので、ラベルをつけて、そのうち機械学習でフィルタリングしていく予定です。

サイトはこちら

分類は、「面白い」「つまらない」「難しい」「関係ない」の4つです。

もっといい分類がありそうだけど、まあ、とりあえずやってみるのが大事でしょう。

しばらく、これで行きます。

鉛筆マークから、分類が行えるので、お暇な方は協力していただけると幸いです。

今なら、好みの情報が集まるようにできるかもしれません。

D3.jsで拡大縮小できる散布図を描く

はじめに

前回の投稿で画像が圧縮されて、非常に見難い状態だったので、同じ内容をD3.jsで可視化してみました。

結果はこちら

D3.jsとは

D3.jsはデータに基づいて、ドキュメント(グラフや図)を描画するための、JavaScriptライブラリです。

グラフ専用ライブラリに比べると非常に自由度が高く、思ったとおりのグラフが作れます。

散布図を描く

データセットを定義する

var dataset = [
    [ -0.619576 , 0.0462473 ,"やはり俺の青春ラブコメはまちがっている。"],
    [ -0.147399 , -0.354047 ,"ソードアート・オンライン 1 アインクラッド"],
    [ 0.265631 , -0.310217 ,"ねじ巻き精霊戦記 天鏡のアルデラミン"],
    〜
    [ 0.136137 , -0.279732 ,"折原臨也と、夕焼けを"],
    [ 0.12208 , 0.591368 ,"宇宙人の村へようこそ 四之村農業高校探偵部は見た!"],
    [ 0.405827 , -0.257009 ,"ゼロから始める魔法の書"]
];

図を描くためのSVG要素を追加する

var w = 960;
var h = 800;
var svg = d3.select("body")
    .append("svg")
    .attr("width", w)
    .attr("height", h);

データセットの最大値と最小値をSVG要素に合わせる

var padding = 20;
var xScale = d3.scale.linear()
    .domain([d3.min(dataset,function(d) {return d[0];}), d3.max(dataset, function(d) { return d[0]; })])
    .range([padding, w - (padding * 4)]);
var yScale = d3.scale.linear()
    .domain([d3.min(dataset,function(d) {return d[1];}), d3.max(dataset, function(d) { return d[1]; })])
    .range([h - padding, padding]);

データセットの1番目の要素をX軸に、2番目の要素をY軸にして、丸を描画する

svg.selectAll("circle")
    .data(dataset)
    .enter()
    .append("circle")
    .attr("cx", function(d) {
        return xScale(d[0]);
    })
    .attr("cy", function(d) {
        return yScale(d[1]);
    })
    .attr("r", 3);

同じ位置にデータセットの3番目の要素をテキストで表示する

svg.selectAll("text")
    .data(dataset)
    .enter()
    .append("text")
    .text(function(d) {
        return d[2];
    })
    .attr("x", function(d) {
        return xScale(d[0]);
    })
    .attr("y", function(d) {
        return yScale(d[1]);
    });

拡大縮小する

ズーム関数の定義

function zoom() {
  svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}

SVG要素のイベントにズーム関数を追加

var svg = d3.select("body")
    .append("svg")
    .attr("width", w)
    .attr("height", h)
    .append("g")
    .call(d3.behavior.zoom().scaleExtent([1, 8]).on("zoom", zoom))
    .append("g");

参考

D3.js - 日本語ドキュメント

D3 入門 : 散布図の作成 - スコット・マレイ - alignedleft

SVG Geometric Zooming - bl.ocks.org

ライトノベルの感想をDoc2Vecで解析 可視化編

はじめに

ライトノベルの感想をDoc2Vecで解析では、ラノベの感想をgensimのDoc2Vecを使って、200次元のベクトルデータとして表現しました。

ベクトルデータなので、類似度の計算ができましたが、200次元といわれても、われわれにはイメージできません。

そこで、今回は、200次元のベクトルを主成分分析を使って2次元に変換して、関係性を可視化しました。

方法

今回は、『このライトノベルがすごい!2016』に載っていた、2015年度BEST60のタイトルを使います。

ライトノベルの感想をDoc2Vecで解析」で求めた、200次元ベクトルのデータを、主成分分析で2次元ベクトルデータに変換します。

主成分分析には、機械学習ライブラリscikit-learnのPCAクラスを使いました。

60タイトルの2次元ベクトルデータをmatplotlibを使って2次元のマップとして描画しました。

結果

f:id:pgsaku:20160515004909p:plain

左の真ん中あたりは、日常系ラブコメ?が集まっているっぽいですね。

下よりの中央は、ファンタジー+バトル要素でしょうか。

なんとなく、感想が近いもので、マップ化されているような気はします。

まとめ

感想をもとに、ラノベをマップ上に表現することには成功したっぽいです。

でも、教師なし学習なので、どんな基準でマップ化されたのかはよくわからないです。

シリアス⇔コメディとか、リアル⇔ファンタジーみたいな人間にわかりやすい軸でマップ化できたら面白いんですけどね。

ライトノベル感想類似度検索を実装してみた

はじめに

前回の記事にたくさんブクマをいただいたので、とりあえずWEBアプリとして実装してみました。

デザインが全然できないので、Bootstrapのデフォルトで作ってあります。

紹介

リンクはこちら

  1. 検索ボックスでラノベのタイトルを検索します。

  2. タイトルの一覧が出てくるので、選びます。

  3. 選んだタイトルに感想が近いラノベが表示されます。

おわりに

最終的には「人工知能がお勧めのライトノベルを選んでくれる」くらいのところまで行けたら面白いですね。

ライトノベルの感想をDoc2Vecで解析してみた

はじめに

前回ラノベの内容紹介をDoc2Vecで解析して遊んでみましたが、あまり面白い結果になりませんでした。

今回はアマゾンレビューなどから収集してきた、ラノベの感想を使ってみます。

感想が近い小説は読み味も近いだろうという予測がたつので、今度こそ好みの小説を探せるようになってほしいです。

方法

トピックモデルのときラノベのisbnコード一覧を使って、アマゾンレビュー、読書メーターブクログあたりから、感想を収集しました。

集めた感想を1つの文書として、gensimのDoc2Vecにかけて、類似度を調べてみました。

全部の感想を収集したわけではないですが、1990年〜2016年3月に発売されたタイトルの感想、約100万件を使っています。

結果

今回もまずは「ソードアート・オンライン」と感想の類似度が高い小説を抽出してみました。

  1. アクセル・ワールド 1 ―黒雪姫の帰還― : 0.5406250953674316
  2. クリス・クロス 混沌の魔王 : 0.5184285640716553
  3. コンプリート・ノービス レベル1の最強剣士 : 0.5114585161209106
  4. スカイ・ワールド : 0.43701106309890747
  5. ワールド エンド ライツ : 0.4228372275829315

1位のアクセル・ワールドは作者が同じ川原礫さんなので、読み味は当然似ていて、狙い通りの結果に見えます。

2位から5位までも、VRMMOとかオンラインRPGとかゲームに閉じ込められるといった感じの小説で、内容は近いように見えます。

ただ、読んだことはないので、読み味が近いかはわからないです。


次に、現在アニメ放送中の『Re:ゼロから始める異世界生活』

  1. 強くないままニューゲーム Stage1 ―怪獣物語― : 0.48192352056503296
  2. 空ろの箱と零のマリア : 0.4573199152946472
  3. ネクストライフ 1 : 0.43387797474861145
  4. 竜殺しの過ごす日々 1 : 0.42893874645233154
  5. マ・オー ―魔王、日本が舞台のオンラインゲームを始める― : 0.42275434732437134

1位の『強くないままニューゲーム』は『Re:ゼロから始める異世界生活』と同じ死んだら巻き戻るループもので、主人公に特殊能力なし、死ぬ描写が生々しくてエグいなど共通点が多いです。

読み味も1巻時点では結構似ているのではないかと思います。

2位から5位までは読んだことはないんですが、2がループもの、3と4が「小説家になろう」の書籍化で、そのあたりが類似度にあらわれていそうです。


最後にライトノベルに入れるかどうかは微妙ですが『ビブリア古書堂の事件手帖

  1. 香彩七色 ~香りの秘密に耳を澄まして~ : 0.49928420782089233
  2. “文学少女”と死にたがりの道化 : 0.4518512785434723
  3. お待ちしてます 下町和菓子 栗丸堂 : 0.4437958896160126
  4. 掟上今日子の備忘録 : 0.4390919506549835
  5. 鎌倉香房メモリーズ : 0.43772873282432556

上品なミステリ風小説とお店ものが抽出されてきたようです。

読んだことあるのは、4位の『掟上今日子の備忘録』だけですが、ライトノベルっぽくないミステリ短篇集ということで共通点は多い気がします。

まとめ

おおむね近い小説が抽出できるようになっている気がします。

でも、読んでない小説が大半なので、なかなか評価が難しいです。

お願い

詳しい方がいたら、合っているか間違っているか感想もらえると、とても嬉しいです。

コメントかメンションでラノベのタイトル投げてもらえれば、似てるタイトルを抽出して返しますので、感想いただけると助かります。

ツイッターアカウントはこちら

実践機械学習システム2章

はじめに

『実践機械学習システム』のお勉強、第2章です。

scikit-learnのインストールに非常に苦労しました。

環境構築については、前回の記事で。

2章の内容

2章はクラス分類(classification)の話です。

可視化や理解のしやすい小さなデータセットを使って、クラス分類の基本的な手法を学びます。

前半はアイリスデータセット(アヤメの品種分類データ)で、閾値を使った分類モデルを作ります。

モデルの評価を行うために、ホールドアウトデータを用いて、交差検定を行います。

後半は小麦の種のデータセットを使って、最近傍法で分類モデルを作成します。

特徴エンジニアリングとデータの正規化の重要性が紹介されています。

分類モデルの評価

訓練データを用いて、モデルの評価を行うと、正解率が高くてあたりまえなので、「新しいデータに対しての汎用的な能力(汎化能力)」で評価します。

汎化能力の評価を行うためには、訓練に使用していないデータを評価に使う必要があります。

そのため、あらかじめ訓練データから一部のデータをテスト用に取り除いて(ホールドアウトデータ)、モデルの作成と評価を行います。

K個に分割した、訓練データのうち、K-1個をモデルの作成に利用して、残りのデータを評価に利用することで、すべてのデータを使って汎化能力を評価するのが、交差検定です。

# 訓練データを10分割して交差検定
error = 0.0
for fold in range(10):
    # 全部Trueのnp配列を作る
    training = np.ones(len(features), bool)
    # 対象のみFalseにする
    training[fold::10] = 0
    # テスト用のインデックスを作る
    testing = ~training
    # 訓練データでモデルを作成
    model = learn_model(features[training], labels[training])
    # モデルをテストデータで評価
    test_error = accuracy(features[testing], labels[testing], model)
    error += test_error

error /= 10.0

特徴エンジニアリング

良い特徴量といのは、重要なことには過敏に反応するが重要でないことには反応を示さないものです。

特徴エンジニアリングとは、良い特徴量を設計あるいは選択することです。

アルゴリズムよりも、特徴エンジニアリングの方が、モデルの性能に大きな影響を及ぼすことが多いらしいです。

機械学習と自然言語処理のためのPython3開発環境構築 

はじめに

機械学習自然言語処理の勉強を始めるにあたって、Pythonの開発環境を構築しました。

というか、いろいろインストールしていったら、途中で上手くいかなくなったので、AnacondaというPythonディストリビューションを入れました。

Anacondaには、NumPy、SciPy、matplotlib、scikit-learnといった、機械学習に必要な基本的なライブラリが最初からインストールされています。

日本語形態素解析MeCabや、gensimは別途インストールが必要です。

そのあたりの環境構築のメモを残しておきます。

環境

Ubuntu14.04

Pythonは3系を利用

Anacondaのインストール

公式サイトからダウンロードします。

ダウンロードしたディレクトリで、Anaconda---.shを実行します。

bash Anaconda3-4.0.0-Linux-x86_64.sh

最後にPathを追加するか聞かれるのでyesを入力します。

MeCabのインストール

sudo apt-get install libmecab-dev
sudo apt-get install mecab mecab-ipadic-utf8
sudo apt-get install build-essential

conda install pip
pip install mecab-python3

gensimのインストール

pip install gensim

まとめ

すごく簡単に環境構築ができました。

最初の苦労はなんだったのか…。