29

私はグラフの分析にPythonとNetworkXを使用することに夢中になっており、学習するにつれて、より多くのデータを使用したいと思っています(データ中毒になっていると思います:-)。最終的に、NetworkXグラフ(dictのdictとして保存される)がシステムのメモリを超えると思います。おそらくメモリを追加するだけでよいことはわかっていますが、代わりにNetworkXをHbaseまたは同様のソリューションと統合する方法があるのではないかと考えていました。

周りを見回しても実際には何も見つかりませんでしたが、単純なMySQLバックエンドの許可に関連するものも見つかりませんでした。

これは可能ですか?ある種の永続ストレージへの接続を可能にするものはありますか?

ありがとう!

更新:「スタートアップのソーシャルネットワーク分析」でこのテーマを見たことを覚えています。著者は他のストレージ方法(hbase、s3などを含む)について話しますが、これを行う方法や可能かどうかについては示していません。

4

3 に答える 3

48

グラフを格納するためのコンテナには、次の2つの一般的なタイプがあります。

  1. 真のグラフデータベース:例: Neo4JagamemnonGraphDBAllegroGraph ; これらはグラフを格納するだけでなく、グラフがであると理解しているため、たとえば、これらのデータベースにクエリを実行できます。たとえば、ノードXとノードYからの最短パスの間にノードがいくつありますか。

  2. 静的グラフコンテナ:TwitterのMySQLに適合したFlockDBは、ここで最もよく知られている模範です。これらのDBは、グラフを適切に保存および取得できます。ただし、グラフ自体をクエリするには、最初にDBからグラフを取得してから、ライブラリ(Pythonの優れたNetworkxなど)を使用してグラフ自体をクエリする必要があります。

以下で説明するredisベースのグラフコンテナは2番目のカテゴリにありますが、redisでグラフデータベースを実装するための非常に小さなPythonパッケージであるredis-graphからもわかるように、redisは最初のカテゴリのコンテナにも適しているようです。

redisはここで美しく機能します。

Redisは、本番環境での使用に適した頑丈で耐久性のあるデータストアですが、コマンドライン分析にも使用できるほどシンプルです。

Redisは、複数のデータ構造タイプがあるという点で他のデータベースとは異なります。ここでお勧めするのはハッシュデータ型です。このredisデータ構造を使用すると、グラフを格納するための従来のスキーマである「ディクショナリのリスト」を非常に厳密に模倣できます。リスト内の各アイテムは、それらのエッジの元のノードにキー設定されたエッジのディクショナリです。

最初にredisとpythonクライアントをインストールする必要があります。DeGizmoブログには、両方をインストールするためのステップバイステップのガイドを含む、優れた「稼働中の」チュートリアルがあります。

redisとそのpythonクライアントがインストールされたら、redisサーバーを起動します。これは次のようにします。

  • redisをインストールしたディレクトリにcdします( make installを介してインストールした場合は、nixの/ usr / local / bin); 次

  • シェルプロンプトでredis-serverと入力し、次のように入力します

これで、シェルウィンドウにサーバーログファイルの末尾が表示されます。

>>> import numpy as NP
>>> import networkx as NX

>>> # start a redis client & connect to the server:
>>> from redis import StrictRedis as redis
>>> r1 = redis(db=1, host="localhost", port=6379)

以下のスニペットでは、4ノードのグラフを保存しています。以下の各行は、redisクライアントでhmsetを呼び出し、1つのノードとそのノードに接続されているエッジを格納します( "0" =>エッジなし、 "1" =>エッジ)。(もちろん、実際には、これらの反復呼び出しを関数で抽象化します。ここでは、その方法を理解しやすいため、各呼び出しを示しています。)

>>> r1.hmset("n1", {"n1": 0, "n2": 1, "n3": 1, "n4": 1})
      True

>>> r1.hmset("n2", {"n1": 1, "n2": 0, "n3": 0, "n4": 1})
      True

>>> r1.hmset("n3", {"n1": 1, "n2": 0, "n3": 0, "n4": 1})
      True

>>> r1.hmset("n4", {"n1": 0, "n2": 1, "n3": 1, "n4": 1})
      True

>>> # retrieve the edges for a given node:
>>> r1.hgetall("n2")
      {'n1': '1', 'n2': '0', 'n3': '0', 'n4': '1'}

グラフが永続化されたので、RedisDBからNetworkXグラフとして取得します。

これを行うには多くの方法がありますが、以下の2つの*ステップ*で行いました。

  1. データをredisデータベースから隣接行列に抽出し、2DNumPy配列として実装します。それから

  2. NetworkX 組み込み関数を使用して、これをNetworkXグラフに直接変換します。

コードに還元すると、これらの2つのステップは次のとおりです。

>>> AM = NP.array([map(int, r1.hgetall(node).values()) for node in r1.keys("*")])
>>> # now convert this adjacency matrix back to a networkx graph:
>>> G = NX.from_numpy_matrix(am)

>>> # verify that G in fact holds the original graph:
>>> type(G)
      <class 'networkx.classes.graph.Graph'>
>>> G.nodes()
      [0, 1, 2, 3]
>>> G.edges()
      [(0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (3, 3)]

redisセッションを終了すると、次のようにクライアントからサーバーをシャットダウンできます。

>>> r1.shutdown()

redisはシャットダウンする直前にディスクに保存するので、これはすべての書き込みが永続化されていることを確認するための良い方法です。

では、redis DBはどこにありますか?これは、デフォルトのファイル名(ホームディレクトリのdump.rdb )でデフォルトの場所に保存されます。

これを変更するには、redis.confファイル(redisソースディストリビューションに含まれています)を編集します。次で始まる行に移動します。

# The filename where to dump the DB
dbfilename dump.rdb

dump.rdbを任意の名前に変更しますが、.rdb拡張子はそのままにしておきます。

次に、ファイルパスを変更するには、redis.confで次の行を見つけます。

# Note that you must specify a directory here, not a file name

その下の行は、redisデータベースのディレクトリの場所です。あなたが望む場所を引用するようにそれを編集してください。リビジョンを保存し、このファイルの名前を変更しますが、拡張子は.confのままにします。この構成ファイルは任意の場所に保存できます。redisサーバーを起動するときに、このカスタム構成ファイルのフルパスと名前を同じ行に入力するだけです。

したがって、次にRedisサーバーを起動するときは、次のようにする必要があります(シェルプロンプトから:

$> cd /usr/local/bin    # or the directory in which you installed redis 

$> redis-server /path/to/redis.conf

最後に、Python Package Indexは、redisでグラフデータベースを実装するためのパッケージをリストしています。パッケージはredis-graphと呼ばれ、私はそれを使用していません。

于 2012-03-10T09:54:12.150 に答える
5

Cloudlightと呼ばれるSQLlite3でサポートされたNetworkX実装があります。 https://www.assembla.com/spaces/cloudlight/wiki/Tutorial

于 2013-03-21T05:35:32.427 に答える
1

ハードドライブを使用する最良の方法を知りたいと思います。過去に私は複数のグラフを作成し、それらを.dotファイルとして保存しました。それから、どういうわけかメモリ内でそれらのいくつかを混ぜ合わせました。しかし、最善の解決策ではありません。

from random import random
import networkx as nx

def make_graph():
    G=nx.DiGraph()
    N=10
    #make a random graph
    for i in range(N):
        for j in range(i):
            if 4*random()<1:
                G.add_edge(i,j)

    nx.write_dot(G,"savedgraph.dot")
    return G

try:
    G=nx.read_dot("savedgraph.dot")
except:
    G=make_graph() #This will fail if you don't use the same seed but have created the graph in the past. You could use the Singleton design pattern here.
print G.adj
于 2012-02-15T22:22:45.180 に答える