Python-猿でもできるページランク計算＆ソーシャルグラフの可視化


Vagrant + VirtualBox + Python + ライブラリで簡単に仮想環境を作って実装してみました。

rubyでソーシャルグラフや行列を扱っていて、扱いにくいことが多々あったので、Pythonで行列計算やグラフの可視化などをやってみたら、めちゃくちゃ簡単且つ実用的だったので、まとめました。
<br>
##利用したPythonライブラリについて
###1. Scipy
scipyは、パッケージは科学技術計算での共通の問題のための多様なツールボックスがあります。サブモジュール毎に応用範囲が異なっています。応用範囲は例えば、補完、積分、最適化、画像処理、統計、特殊関数等。
scipy は GSL (GNU Scientific Library for C and C++) や Matlab のツールボックスのような他の標準的な科学技術計算ライブラリと比較されます。 scipy は Python での科学技術計算ルーチンの中核となるパッケージです; これは numpy の配列を効率良く扱っているということで、numpy と scipy は密接に協力して動作しています。

###2. Numpy
NumPyは、Pythonプログラミング言語の拡張モジュールであり、大規模な多次元配列や行列のサポート、これらを操作するための大規模な高水準の数学関数ライブラリを提供する。
NumPyはSciPyと併せて科学技術計算でよく利用されています。また、高速に行列演算ができるのでOpenCV(コンピュータビジョンライブラリ)でもNumPyを利用したPythonインタフェースが提供されるようになりました。

###3. NetworkX
NetworkXは、Pythonのネットワーク解析・可視化用ライブラリです。
ここで言っているネットワークは、実際の通信ネットワーク（のモデル）に限らず、グラフの辺に重さ（weight）と呼ばれる値を割り当てた構造です。重さを考えないときは、全ての辺に同じ重さが付いているとすればいいので、普通のグラフも扱えます。つまり、NetworkXを使ってグラフに対するさまざまな処理ができるのです。

###4. matplotlib
Matplotlibは、プログラミング言語Pythonおよびその科学計算用ライブラリNumPyのためのグラフ描画ライブラリである。オブジェクト指向のAPIを提供しており、様々な種類のグラフを描画する能力を持つ。描画できるのは主に2次元のプロットだが、3次元プロットの機能も追加されてきている。描画したグラフを各種形式の画像（各種ベクトル画像形式も含む）として保存することもできるし、wxPython、Qt、GTKといった一般的なGUIツールキット製のアプリケーションにグラフの描画機能を組みこむこともできる。MATLABの対話環境のようなものを提供するpylabというインタフェースも持っている。Matplotlibは、BSDスタイルのライセンスの下で配布されている。(via http://ja.wikipedia.org/wiki/Matplotlib)

<br>

##環境構築

###1. Vagrant+VirtualBoxで仮想マシンを作成して、sshログイン
http://qiita.com/gyhino@github/items/8c10249019cf1e9fce34

###2. Pythonのインストール
※centosではpythonはデフォルトで入ってるので不要。
http://www.pythonweb.jp/install/

###3. pipのインストール
http://pip.readthedocs.org/en/latest/installing.html

###4. Pythonに必要なものをインストール
http://d.hatena.ne.jp/shinriyo/20120623/p1

###5. Pythonライブラリのインストール 

```vagrantの仮想環境上で下記を実装
sudo pip install numpy
sudo easy_install scipy
#sudo pip install scipyがerrorになったのでeasy_installを使った
sudo easy_install matplotlib
sudo pip install networkx
```

<br>
##やってみたこと
###1. 猿でもできるページランクの計算
###2. 寝ててもできるソーシャルグラフの可視化
--

<br>
###1. 猿でもできるページランクの計算
簡単なグラフでページランクを算出するファイルと実行方法について記載します。

```python:pagerank.py

# -*- coding: utf-8 -*-
import networkx as nx

#有向グラフのインスタンスを生成
g = nx.DiGraph()

#ノードを追加する ※ソーシャルグラフなら人がノードになることが多い
g.add_node(1)
g.add_node(2)
g.add_node(3)                                                                                                                     
g.add_node(4)
g.add_node(5)
g.add_node(6)
#分かりやすいように敢えての羅列形式

#ノード間の矢印を加えていく ※ソーシャルグラフなら友達関係やフォロー、いいね！など
g.add_edge(1,2)
g.add_edge(1,3)
g.add_edge(1,4)
g.add_edge(2,3)
g.add_edge(3,4)
g.add_edge(3,5)
g.add_edge(2,6)
g.add_edge(5,6)
g.add_edge(1,6)
#分かりやすいように敢えての羅列形式

#pagerank値の計算
pr=nx.pagerank(g,alpha=0.85)

#pagerank値の計算(numpyを利用)
prn=nx.pagerank_numpy(g,alpha=0.85)

#pagerank値の計算(scipyを利用)
prc=nx.pagerank_scipy(g,alpha=0.85)

#計算結果表示
print("-----pagerank-----")
print(pr)

print("-----pagerank(numpy)-----")
print(prn)

print("-----pagerank(scipy)-----")
print(prc)

```

```terminalで以下を実行
$ python pagerank.py
```

って実行すると、下記のような結果がでてきます。

```
#normal
{1: 0.09239221032272713, 2: 0.11202546652062978, 3: 0.1596362278548462, 4: 0.1798708491907905, 5: 0.1602375929928878, 6: 0.29583765311811816}

#numpy
{1: 0.09239208559289437, 2: 0.11202540378138424, 3: 0.15963620038847254, 4: 0.1798707889464852, 5: 0.16023747075799505, 6: 0.2958380505327687}

#scipy
{1: 0.09239221032272715, 2: 0.11202546652062981, 3: 0.15963622785484624, 4: 0.17987084919079052, 5: 0.16023759299288784, 6: 0.29583765311811827}
```
当たり前ですけど、ほぼ答えは一緒です。

--
<br>

###2. 寝ててもできるソーシャルグラフの可視化

```python:social_graph_visualization.py

# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib import animation
import networkx as nx
import random

#ネットワーク
g = nx.Graph()
def get_fig(node_number):                                                                                                         
    g.add_node(node_number, Position=(random.randrange(0, 100), random.randrange(0, 100)))
    g.add_edge(node_number, random.choice(g.nodes()))
    nx.draw(g, pos=nx.get_node_attributes(g,'Position'))

fig = plt.figure(figsize=(10,8))

anim = animation.FuncAnimation(fig, get_fig, frames=100)
anim.save('graph_gifani.gif', writer='imagemagick', fps=10);

```

```terminalで以下を実行
$ python social_graph_visualization.py
```
と実行すると、下記のgifアニがフォルダ内に保存されているはずです。

![GraphGifAnimation](https://dl-web.dropbox.com/get/graph_gifani.gif?_subject_uid=5329201&w=AAB3qfG5K66Julge1qd_L-lQafsSH9ib_swfrdbQ7fpJoA "graph gif animation")

--

###まとめ

いやぁ面白い！
ちょ〜簡単！！

ちょっとPythonでAPIやらアプリやらを作ってみたくなってきたので、近いうちに何か面白いもの作りま〜す！