Решение NoSQL для сохранения графиков в масштабе

Я увлекся использованием Python и NetworkX для анализа графиков, и по мере того, как я узнаю больше, я хочу использовать все больше и больше данных (думаю, я становлюсь наркоманом данных :-). В конце концов, я думаю, что мой график NetworkX (который хранится в виде словаря) превысит объем памяти в моей системе. Я знаю, что, вероятно, могу просто добавить больше памяти, но мне было интересно, есть ли способ вместо этого интегрировать 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. контейнеры статического графа: FlockDB, адаптированная для MySQL, является наиболее известным примером. Эти БД могут прекрасно хранить и извлекать графики; но чтобы запросить сам график, вы должны сначала получить график из БД, а затем использовать библиотеку (например, отличный Networkx Python) для запроса самого графика.

Графический контейнер на основе Redis, который я обсуждаю ниже, относится ко второй категории, хотя очевидно, что Redis также хорошо подходит для контейнеров из первой категории, о чем свидетельствует redis-graph, удивительно маленький пакет Python для реализации графовой базы данных в Redis.

redis прекрасно подойдет здесь.

Redis — это мощное и надежное хранилище данных, подходящее для производственного использования, но при этом достаточно простое для анализа из командной строки.

Redis отличается от других баз данных тем, что имеет несколько типов структур данных; я бы порекомендовал здесь тип данных hash. Использование этой структуры данных 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 в виде графа NetworkX.

Есть много способов сделать это, ниже мы сделали это в два *этапа*:

  1. извлечь данные из базы данных Redis в матрицу смежности, реализованную в виде двумерного массива 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 и т. д.)? Мне нужно изучить очень большие графики (сотни миллионов новых узлов/день) и сравнить узлы/выполнить рейтинг страниц и т. д. - person Lostsoul; 12.03.2012
comment
neo4j — настоящая графовая база данных; то, что я реализовал в своем ответе, - это постоянный график. Оба могут хранить графики; граф db понимает, что такое граф, поэтому его можно запросить, например, сколько узлов находится между узлами X и узлами Y? Чтобы сделать это в моей реализации redis выше, вам нужно сначала извлечь граф из redis, например, в networkx. Другими словами, neo4j (единственная известная мне графическая база данных с открытым исходным кодом) похожа на мою реализацию Redis + прикладной уровень интеллектуального графа (networkx). Если вы предпочитаете использовать Networkx, то эта дополнительная функциональность может просто помешать. - person doug; 13.03.2012
comment
Большое спасибо, Дуг. Я думаю, что вы ответили на все вопросы о графиках, которые я задавал, и еще больше погрузили меня в интересный мир графиков. Я начинаю рассматривать все свои проблемы как проблемы с графиками, но некоторые из этих проблемных наборов данных могут быть довольно большими. Это немного не связано, но, поскольку вы очень опытны в этой области, знаете ли вы, что networkx деградирует, когда графики достигают определенного размера? Скажем, он достигает нескольких миллиардов узлов? Я провожу собственное тестирование, но немного конфликтую, потому что neo4j, кажется, делает все изначально. Сталкивались ли вы с какими-либо препятствиями с точки зрения размеров графиков? - person Lostsoul; 15.03.2012
comment
@Lostsoul: я рад слышать, что мой ответ был вам полезен. анализ графика с использованием собственного прикладного уровня базы данных по сравнению с «обычным» двухэтапным процессом на самом деле является просто личным предпочтением. Конечно, мы знаем, что вычисления на графах (обычно) по своей природе распараллеливаемы, поэтому для набора данных > 2 ГБ я бы обработал его через 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
Кстати, не уверен, что вам это интересно (возможно, вы уже знаете всю информацию здесь), но я полагаю, что вы предложили мне книгу под названием «Вероятностные графические модели» Коллера (это было потрясающе), и у нее есть бесплатный курс в Стэнфорде, который начался на прошлой неделе. www.pgm-class.org/ Ваши ответы и предлагаемые опр. заставили меня следить за лекциями (если это было не бесплатно, вы должны были получить комиссию :-). - person Lostsoul; 16.03.2012
comment
Спасибо @Lostsoul и Дугу за очень интересную беседу. Моя проблема довольно похожа. Мне нужно проиндексировать большой граф (4 ГБ), выполнить поиск индекса по узлам и вычислить самый центральный в конкретном подграфе (идентифицируемом с помощью алгоритма поиска хлеба). Мне было интересно, был ли в конце концов твой выбор? Вы выбрали Reddis+NetworkX, neo4j, Python igraph или что-то еще? Опять же, здесь важна производительность. Большое спасибо - person Kevin.; 05.05.2014
comment
Привет @Кевин. В итоге я использовал искру. Отчасти потому, что это выглядело так круто, а также у моего друга-разработчика было больше опыта с этим. spark.apache.org - person Lostsoul; 06.05.2014
comment
@doug: я только что читал о Redis и меня интересуют графики, поэтому я наткнулся на этот отличный ответ. Однако у меня есть вопрос: когда вы говорите, чтобы сделать это в моей реализации Redis выше, вам нужно сначала извлечь граф из Redis, например, в networkx.... включает ли этот шаг копирование памяти для всего графа из Redis в Python память процесса? Или все дело в том, что его не нужно копировать? Спасибо - person user3391564; 29.08.2014
comment
@user3391564 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