2012-09-28 2 views
2

Bonjour, J'ai essayé d'implémenter l'algorithme DBSCAN pour Neo4j, mais je suis confronté à de sérieux goulots d'étranglement. Je vais décrire la mise en œuvre puis demander de l'aide.Optimisation de DBSCAN pour neo4j en Cypher/Python

J'ai discrétisé les valeurs epsilon possibles et mis des comptes du nombre de voisins sous chaque discrétisation dans chaque nœud afin de pouvoir récupérer tous les nœuds de base dans une requête.

START a = node(*) 
WHERE a.rel<cutoff threshold>! >= {minp} 
RETURN a 

Cette partie est rapide, la partie qui n'est pas rapide est le suivi requête:

START a = node({i}) 
SET a.label<cutoff threshold>_<minpoints> = {clust} 
WITH a 
MATCH a -[:'|'.join(<valid distance relations>)]- (x) 
WHERE not(has(x.label<cutoff threshold>_<minpoints>)) 
WITH x 
SET x.label<cutoff threshold>_<minpoints>={clust} 
RETURN x 

Je prends alors un nœud de base pour démarrer à partir, et aussi longtemps que il y a encore noyau voisins de noeud, exécutez la requête ci-dessus pour étiqueter leurs voisins. Je pense que le problème est que mon graphique a des niveaux très différents de sparsité - à partir de seulement une faible similitude, il est presque entièrement connecté, avec ~ 50M relations entre ~ 10k nœuds, alors qu'à forte similitude, il y en a aussi peu que ~ 20k relations entre ~ 10k nœuds (ou moins). Peu importe quoi, c'est toujours très lent. Quelle est la meilleure façon pour moi de gérer cela? Est-ce indexer sur le type de relation et le noeud de départ? Je n'ai pas été capable de trouver des ressources sur ce problème, et étonnamment il n'y a pas déjà une implémentation car il s'agit d'un algorithme graphique assez standard. Je pourrais utiliser scikit.learn mais alors je serais limité aux matricies de distance en mémoire seulement :(

+0

peut-être parce que neo4j est optimisé pour la traversée de graphe et non primaire pour l'insertion/l'édition de graphe. J'ai vu quelque part une comparaison entre neo4j et d'autres moteurs de graphique DB dans la vitesse de traitement des données et neo4j était calme lent. d'autre part, il a surpassé les autres dans la vitesse du graphique traversant – ulkas

Répondre

0

Quelle version de neo4j avez-vous essayé avec? Jusqu'à ce que la performance de 1.8 n'ait pas été un objectif de conception de chiffrement (plutôt la langue) Jetez un oeil à un instantané récent (1.9-SNAP).

Assurez-vous également que votre jeu de données hot n'est pas simplement chargé à partir du disque (sinon vous mesurez le disque-io) de sorte que votre memory mapped settings et aussi le tas JVM est assez grand.

Vous pouvez également consulter le cache GCR de Neo4j enterprise qui a une empreinte mémoire plus petite.

Quelle est la cardinalité de count(x) dans votre requête? Si c'est trop petit, vous avez trop de petites transactions en cours. Selon si votre exécution python embedded ou REST utiliser un plus grand tx-scope ou REST-batch-operations

Vous utilisez déjà des paramètres ce qui est génial. Quelle est la variabilité de vos rel-types?

Une chance de partager votre ensemble de données/générateur et le code avec nous (Neo4j) pour les tests de performance de notre côté?

+0

Merci pour les conseils! La cardinalité de count (x) est très variable - je vérifie chaque nœud au moins une fois (dans l'ensemble de base) donc en général il est petit (0-10), mais pour certains nœuds de base il sera plus grand, ~ 100- 1000 pour être spécifique. Idéalement, je voudrais être en mesure de ne renvoyer que les nœuds qui ont des liens sortants non marqués car cela diminuerait considérablement les requêtes de petite cardinalité. J'ai discrétisé les poids en différents types de liens car je ne savais pas comment interroger sur la relation telle que r.weight Elliot

+0

Aussi, je suis heureux de partager des données + le code source, mais je dois avoir au moins une méthode de mise en cluster qui fonctionne avant que j'aie le temps de l'empaqueter pour vous. DBSCAN n'est pas "vraiment" la bonne chose, je pense que OPTICS pourrait fonctionner pour mes données mais je vais probablement utiliser HDP pour avoir des clusters qui se chevauchent. – Elliot

+0

N'hésitez pas à partager ce que vous pensez être sensible. Nous pouvons également continuer cette discussion sur le groupe Google Neo4j. –

0

Il y a des implémentations de DBSCAN autour de cette indexation d'utilisation. L'approche que vous devrez peut-être précalculer est en fait une version clairsemée de votre graphique, avec seulement les arêtes qui sont dans le seuil epsilon

Ce que je voudrais souligner, c'est que vous avez apparemment des densités différentes votre ensemble de données, vous pouvez donc utiliser OPTICS, qui est une variante de DBSCAN qui supprime le paramètre epsilon (et qui n'a pas besoin de distinguer les nœuds "core", car chaque nœud est un nœud de base pour un certain epsilon) N'utilisez pas la version Weka (ou la version python inspirée de weka) qui flotte autour). Ils sont à moitié OPTIQUE et à moitié DBSCAN.

Lorsque vous avez des tas modifiables triés efficaces disponibles, OPTICS peut être assez rapide.

+0

Oui, j'ai regardé OPTIQUE, mais je me suis dit que je me couperais les dents sur l'algorithme plus simple (aussi ne pouvait pas trouver un bon qui n'était pas Weka mais je vais regarder plus dur). L'implémentation de scikit fonctionne pour mon cas d'utilisation immédiate, mais une implémentation de base de données graphique a le potentiel pour des mises à jour incrémentales de persistance. Il n'est pas très utile de faire le seuillage epsilon parce que j'ai besoin des deux niveaux, et bien qu'il gagnera du temps pour la détection des doublons, il ne le fera pas pour le clustering flou (détection de type langage/document). Je préférerais avoir une implémentation qui fonctionne pour les deux. – Elliot