NoSQL решение за запазване на графики в мащаб

Пристрастен съм към използването на Python и NetworkX за анализиране на графики и докато научавам повече, искам да използвам все повече и повече данни (предполагам, че ставам наркоман на данни :-). В крайна сметка мисля, че моята NetworkX графика (която се съхранява като dict от dict) ще надхвърли паметта на моята система. Знам, че вероятно мога просто да добавя повече памет, но се чудех дали има начин вместо това да интегрирам NetworkX с Hbase или подобно решение?

Огледах се и наистина не можах да намеря нищо, но също така не можах да намеря нищо, свързано с разрешаването на прост MySQL бекенд.

Възможно ли е това? Съществува ли нещо, което да позволява свързване към някакъв вид постоянно хранилище?

Благодаря!

Актуализация: Спомням си, че видях тази тема в „Анализ на социални мрежи за стартиращи фирми“, авторът говори за други методи за съхранение (включително hbase, s3 и т.н.), но не показва как да направите това или дали е възможно.


person Lostsoul    schedule 15.02.2012    source източник
comment
редактирах заглавието на вашия въпрос и добавих маркера nosql. По-специално премахнах препратката в заглавието към networkx, защото networkx не изисква конкретен графичен формат/протокол (всъщност той има методи за превод от/към всички често срещани формати), така че фактът, че вашите графики са генерирани от networkx, няма влияние върху възможните отговори.   -  person doug    schedule 14.03.2012


Отговори (3)


Има два основни типа контейнери за съхраняване на графики:

  1. бази данни с истински графики: напр. Neo4J, agamemnon, GraphDB и AllegroGraph; те не само съхраняват графика, но също така разбират, че графиката е, така че например можете да направите запитване към тези бази данни, например колко възли има между най-краткия път от възел X и възел Y?

  2. статични графични контейнери: адаптираната към MySQL FlockDB на Twitter е най-известният пример тук. Тези DB могат да съхраняват и извличат графики добре; но за да поискате самата графика, първо трябва да извлечете графиката от DB, след което да използвате библиотека (напр. отличната Networkx на Python), за да направите заявка за самата графика.

Графичният контейнер, базиран на redis, който обсъждам по-долу, е във втората категория, въпреки че очевидно redis също е подходящ за контейнери в първата категория, както се вижда от redis-graph, забележително малък пакет на python за внедряване на графична база данни в redis.

redis ще работи прекрасно тук.

Redis е мощно, издръжливо хранилище на данни, подходящо за производствена употреба, но също така е достатъчно лесно за използване за анализ от командния ред.

Redis е различен от другите бази данни по това, че има множество типове структура на данни; този, който бих препоръчал тук, е типът данни хеш. Използването на тази структура от данни на redis ви позволява много точно да имитирате „списък от речници“, конвенционална схема за съхраняване на графики, в която всеки елемент в списъка е речник на ръбове, свързани с възела, от който произхождат тези ръбове.

Първо трябва да инсталирате redis и клиента на python. Блогът на DeGizmo има отличен „актуален“ урок, който включва ръководство стъпка по стъпка за инсталиране и на двете.

След като redis и неговият python клиент са инсталирани, стартирайте redis сървър, което правите по следния начин:

  • cd към директорията, в която сте инсталирали redis (/usr/local/bin на 'nix, ако сте инсталирали чрез make install); следващия

  • въведете 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)

Във фрагмента по-долу съм съхранил графика с четири възела; всеки ред по-долу извиква hmset на клиента redis и съхранява един възел и ръбовете, свързани с този възел ("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'}

Сега, когато графиката е запазена, извлечете я от redis DB като NetworkX графика.

Има много начини да направите това, по-долу го направете в две *стъпки*:

  1. извлечете данните от базата данни redis в матрица на съседство, реализирана като 2D NumPy масив; тогава

  2. конвертирайте това директно в графика на NetworkX с помощта на вградена функция на NetworkX:

редуцирани до код, тези две стъпки са:

>>> 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 изброява пакет специално за внедряване на графична база данни в redis. Пакетът се нарича redis-graph и не съм го използвал.

person doug    schedule 10.03.2012
comment
Уау, благодаря ти много. Не знаех, че това е възможно, но определено ще си поиграя с него. Тъй като отговорихте на много от моите въпроси, свързани с графики, ще се опитам да избера мозъка ви с друг. Знаете ли или опитвали ли сте да интегрирате networkx (или която и да е библиотека за графики) с neo4j? Когато написах този въпрос, мислех за redis, но напоследък изглежда, че neo4j е по-оптимизиран за задачи, свързани с графики.. някакви мисли за използването на neo4j с networkx (или jung и т.н.)? Трябва да проуча много много големи графики (стотици милиони нови възли/ден) и да сравня възли/да направя pagerank и т.н. - person Lostsoul; 12.03.2012
comment
neo4j е истинска графична база данни; това, което внедрих в моя отговор, е постоянна графика. И двете могат да съхраняват графики; a graph db разбира какво е графика, така че може да бъде попитано колко възли има между възли X и възли Y? За да направите това в моята реализация на redis по-горе, ще трябва първо да извлечете графиката от redis в например networkx. С други думи, neo4j (което е единствената графика db с отворен код, за която знам) е като моята реализация на redis + интелигентен графичен приложен слой (networkx). Ако предпочитате да използвате Networkx, тогава тази допълнителна функционалност може просто да ви попречи. - person doug; 13.03.2012
comment
Благодаря ти много Дъг. Мисля, че отговорихте на всеки въпрос за графики, който публикувах, и ме изпратихте още по-дълбоко в интересния свят на графиките. Започвам да виждам всичките си проблеми като проблеми с графики, но някои от тези набори от данни могат да станат доста големи. Това някак не е свързано, но тъй като сте много опитен в това пространство, знаете ли, че networkx се влошава, когато графиките достигнат определен размер? Да кажем, че удря няколко милиарда възли? Правя мое собствено тестване, но малко противоречиво, защото neo4j изглежда прави разпределение нативно. Срещали ли сте някакви препятствия по отношение на размерите на графиката? - person Lostsoul; 15.03.2012
comment
@Lostsoul: радвам се да чуя, че отговорът ми е бил полезен за вас. анализът на графики с помощта на собствения приложен слой на db спрямо „конвенционалния“ процес в две стъпки всъщност е просто лично предпочитание. Разбира се, ние знаем, че изчисленията върху графики (обикновено) са присъщи за паралелизиране - така че за набор от данни › 2GB, бих го обработил чрез Hadoop. Това няма да помогне с проблема с размера на набора от данни, но ако все още не го знаете, погледнете igraph (igraph.sourceforge.net/requirements.html), което е много по-бързо от networkx, дори използвайки обвързванията на python. - person doug; 15.03.2012
comment
Имате деф. ми помогна много. Четох книга за алгоритми и се сетих за графики, но заради теб прочетох няколко книги, посветени на тях (ти ги препоръча) и се заех с networkx, много благодаря! Ще разгледам igraph (никога не съм чувал за него преди). Експериментирах с hbase като хранилище за данни преди, но тъй като не можах да разбера как да вкарам структурата на графиката върху него, изоставих hbase(и hadoop) и вместо това мислех да използвам redis(или neo4j) с нещо като rabbitmq за координиране множество сървъри, обработващи тези източници на данни. - person Lostsoul; 16.03.2012
comment
Предполагам, че проблемът, с който си мислех, че ще се сблъскам, е, че не мислех, че мога да паралелизирам алгоритмите на графиката, които изискват цялата графика (като pagerank), така че започнах да търся нещо, което е наясно с цялата графика (като вашия redis/ networkx плъгин или neo4j).. Не съм сигурен дали това е добър подход, но затова зададох този въпрос, нещо като отправна точка. - person Lostsoul; 16.03.2012
comment
Между другото, не съм сигурен дали се интересувате (може вече да знаете цялата информация тук), но вярвам, че ми предложихте книга, наречена вероятностни графични модели от Koller (което беше невероятно) и тя има безплатен клас в Станфорд, който започна миналата седмица www.pgm-class.org/ Вашите отговори и предложените деф. ме накараха да следвам лекциите (ако не беше безплатно, трябва да получите комисионна :-). - person Lostsoul; 16.03.2012
comment
Благодаря на @Lostsoul и Дъг за вашия много интересен разговор. Моят проблем е доста подобен. Трябва да индексирам голяма графика (4GB), да извърша търсене на индекс на възли и да изчисля най-централното в конкретен подграф (идентифициран чрез алго за търсене на breadfrist). Чудех се дали вашият избор беше в крайна сметка? Избрахте ли Reddis+NetworkX, neo4j, Python igraph или нещо друго. Отново производителността е ключова тук. Много благодаря - person Kevin.; 05.05.2014
comment
Здравей @Kevin. В крайна сметка използвах искра. Отчасти защото изглеждаше толкова страхотно, а освен това моят приятел разработчик имаше повече опит с него. spark.apache.org - person Lostsoul; 06.05.2014
comment
@doug: Току-що четох за Redis и се интересувам от графики и така попаднах на този страхотен отговор. Имам обаче въпрос: когато казвате За да направите това в моята реализация на redis по-горе, ще трябва първо да извлечете графиката от redis в например networkx.... тази стъпка включва ли копиране на памет за цяла графика от redis в python паметта на процеса? Или целият смисъл е, че не трябва да се копира? Благодаря - person user3391564; 29.08.2014
comment
@user3391564, така че добро чисто решение на Python за запазване на извънядрени графики (като все още можете да правите изчисления върху тях) е HDF5 и обвързванията на Python за HDF5, h5py (h5py.org); вижте тази същност в моето репо: gist.github.com/alexland/d011eeeb9724ff072a02 - person doug; 29.08.2014
comment
Благодаря за страхотните усилия - person Ghassan Zein; 01.06.2016

Има реализация на NetworkX, поддържана от SQLlite3, наречена Cloudlight. https://www.assembla.com/spaces/cloudlight/wiki/Tutorial

person Jonathan Hendler    schedule 21.03.2013
comment
Много хубаво, определено мога да се възползвам от това! - person RubyGladiator; 21.05.2013
comment
Не поддържа ли и Python 3? - person 0x90; 11.08.2020

Ще ми е интересно да видя най-добрия начин за използване на твърдия диск. В миналото съм правил множество графики и съм ги записвал като .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
person robert king    schedule 15.02.2012
comment
Благодаря за страхотния отговор Робърт. Мислех за това като най-лошия случай да имам процес, който взема тези плоски файлове (които знам как да създавам) и ги изпраща към Hbase и след това също ги генерира при поискване. Не мисля, че това е най-добрият отговор, защото понякога базата данни надвишава системната памет за съхранение (която в крайна сметка ще съхранява тези данни), ако има начин тя постоянно да се отнася към базата данни, проблемът с паметта изчезва. - person Lostsoul; 16.02.2012
comment
Да, надявам се някой да публикува по-добър отговор. - person robert king; 16.02.2012
comment
Вашият отговор (и мисловен процес) е страхотен, защото поне има план Б в най-лошия случай. Не би трябвало да е твърде трудно да се изпращат файлове за анализ, който ограничава само размера на данните до размера на паметта (но бих искал да избегна тази работа, ако вече е свършена) - person Lostsoul; 16.02.2012