J'ai (~ un million) de vecteurs de caractéristiques. Il y a (~ un million) d'entités binaires, mais dans chaque vecteur, seulement (~ un millier) d'entre elles seraient égales à , les autres étant . Je recherche les paires de vecteurs qui ont au moins (~ cent) traits en commun ( dans les deux). Le nombre de ces paires est d'une ampleur similaire à (~ un million).M K 1 0 L 1 N
Je pense que cela pourrait être envisagé comme la recherche de paires de points proches dans un espace de très grande dimension. La fonction de distance pourrait être telle qu'elle est basée sur le nombre de caractéristiques que les deux vecteurs ont en commun. Mais il serait probablement utile avec une métrique de distance plus conventionnelle (comme Euclidienne) également.
Quels algorithmes bien connus seraient utiles pour aborder ce problème? Tout ce qui est quadratique en ou ne sera pas pratique.M
Un exemple de formulation du problème dans le monde réel est de considérer personnes se déplaçant entre plusieurs endroits. Si deux personnes se trouvaient au même endroit en même temps, nous disons qu'elles se sont rencontrées. (Le nombre de combinaisons emplacement-temps avec au moins 1 personne présente est ) Nous recherchons des amis: des personnes qui se sont rencontrées au moins fois.M L
la source
Réponses:
Il semble que l'approche que vous recherchez est une combinaison de signatures minhash et de hachage sensible à la localité (LSH); le pdf (disponible gratuitement) de Mining Massive Datasets décrit cette approche (et d'autres mesures de similitude) en détail dans le chapitre 3, mais brièvement:
Une signature minhash est une représentation condensée de votre matrice d'origine qui est construite en appliquant un certain nombre n de fonctions de hachage aux entités, réduisant ainsi le nombre d'entités par observation. Cela réduit la taille de vos données, mais vous remarquerez probablement que cela vous laisse toujours avec un problème .O ( N2)
Pour résoudre ce problème, MMDS conseille que si tout ce que vous voulez trouver est des paires au-dessus d'un certain seuil de similitude (qui semblerait s'appliquer dans votre cas), alors vous pouvez vous concentrer uniquement sur les paires qui sont les plus susceptibles d'être similaires - cette approche s'appelle Locality Sensitive Hashing , et dans la section 3.4, ils expliquent comment combiner l'approche de signature minhash avec LSH.
En plus du texte, des cours sont également disponibles sur le cours Coursera du même nom.
la source
Ce n'est qu'un produit intérieur de vecteurs de caractéristiques binaires. Lorsque le produit intérieur est supérieur à , la paire aura au moins éléments en commun. Cela devrait être un calcul relativement rapide - au moins, plus rapide que la distance euclidienne, ce qui serait inutile et lent pour ces données. Parce que vous stipulez que vous recherchez des paires, cela signifie par nature que vous devez effectuer des calculs pour comparer chaque vecteur.L ( NL - 1 L ( N2)
Trouver des points proches les uns des autres est en effet un problème de regroupement. Mais la première étape des algorithmes de clustering que je connais est le calcul des distances par paires ou des similitudes. Je suis sûr que quelqu'un a développé des alternatives plus efficaces. Un point sur la terminologie: avoir au moins voisins communs est formulé comme une similitude , pas une distance! Les produits internes sont, dans ce cas, des similitudes de cosinus non normalisés.L
Vous pouvez rendre cela plus maniable en effectuant le calcul du produit interne uniquement lorsque la somme du vecteur de caractéristique (qui est dans ce cas la même que la norme) pour une observation est supérieure à , car il est impossible pour ce vecteur de caractéristique binaire d'avoir un produit intérieur avec un autre vecteur caractéristique binaire qui satisfera mon critère lorsque cette somme est inférieure à . De toute évidence, le calcul de ces sommes n'est qu'une complexité , c'est donc un moyen bon marché de réduire l'ampleur de l'étape de produit interne.L O ( N )L - 1 L O ( N)
Mais la manière classique de réduire l'étendue de ce problème consiste à effectuer un préfiltrage supplémentaire. Êtes-vous particulièrement intéressé par le fait qu'une fonctionnalité quelque peu inhabituelle prenne la valeur 1? Si tel est le cas, effectuez uniquement le calcul pour ces vecteurs de caractéristiques.
Ou peut-être pourriez-vous bénéficier d'un recadrage de votre problème. Par exemple, l'échantillonnage est connu pour avoir de belles propriétés; des statistiques inférentielles développent cette idée assez en profondeur. Il est donc peut-être impossible d'analyser l'ensemble des données, mais il est parfaitement possible d'examiner un petit échantillon. Je ne sais pas à quelle question vous essayez de répondre, mais si vous concevez soigneusement votre expérience, vous pouvez vous en tirer avec seulement quelques milliers d'observations, avec plus que suffisamment de données restantes à des fins de validation.
Après une réflexion supplémentaire, j'ai une intuition forte que les données que vous travaillez avec une sorte de graphique . Il est très plausible que soit composé de plusieurs composants connectés, auquel cas vous pouvez décomposer en un ensemble de graphiques, avec l'effet secondaire heureux de réduire la dimensionnalité des données. Même si le graphique n'est que deux composants connectés de la même taille, cela signifie que vos comparaisons par paires ont à peu près le coût total!G G O ( N 2 ) 1g g g O ( N2) 14
Si le graphique est symétrique, les observations suivantes peuvent être utiles:
Si vous avez un graphique bipartite reliant les personnes aux comportements, vous pouvez le considérer comme un réseau d'affiliation , avec des personnes comme des lignes et des comportements comme des colonnes. Si vous voulez connecter les gens à des gens via les comportements qu'ils ont en commun, vous pouvez calculer . est le nombre de comportements que les gens ont en commun. Évidemment, l'ensemble des sommets où répond à votre question.B B BT= A UNEje j UNEje j≥ L
la source
À la recherche de personnes se réunissant en blocs spatio-temporels:Ns p a c e Nt i m e
O ( N2)
espace en blocs (blocs de ville, km2, ) et le temps en blocs . Il y a de fortes chances que si les gens se rencontrent, ils se rencontreront dans le même bloc. Exécutez donc NN dans chaque bloc. Les temps d'exécution et les taux d'erreur dépendront bien sûr de la taille et de la forme des blocs (également de ce que vous pouvez paralléliser / MapReduce), mais vous avez des paramètres avec lesquels jouer - ingénierie, pas ouvert .
Voir aussi:
voisins les plus proches recherche de données de très haute dimension sur datascience.stackexchange
pairwise.py :
la source
Pour chaque fonctionnalité, créez un dictionnaire contenant les index partageant cette fonctionnalité. Espérons que ce nombre ne sera pas trop grand (si vous avez une fonctionnalité partagée par tous les index, cette approche est ruinée, vous pouvez arrêter de lire ici).
J'ai appliqué cette méthode pour implémenter un KNN sur un grand ensemble de texte (train: 2 000 000 lignes, tester 35 000 lignes, nombre d'entités: 10 000, nombre moyen d'entités par élément: 20), qui a fonctionné en une heure environ. .
la source
L. Erotz, M. Steinbach et V. Kumar. "Un nouvel algorithme de clustering de voisins les plus proches et ses applications." Actes du 1er atelier sur le regroupement des données de haute dimension et leurs applications, 2002.
la source
Étant donné que votre k est 100 et votre n est 1e6, cela devrait vous donner une vitesse de ~ 1e4x par rapport à la FFT classique.
Si vous avez besoin de 20 fois plus de vitesse et que vous êtes un preneur de risques, au lieu de convoluer toutes les lignes contre le domaine et de rechercher le pic, vous pouvez démarrer un sous-ensemble de lignes.
Vous pouvez également préfiltrer les colonnes en supprimant les colonnes dont les sommes sont inférieures à 50, ou tout autre seuil qui est de l'ordre de la moitié du nombre de lignes que vous cherchez à faire correspondre. Au minimum, vous devez supprimer les colonnes de tous les zéros et de tous les 1 comme non informatifs. Idem avec des lignes entièrement vides ou suffisamment vides, ou des lignes si pleines qu'elles ne sont pas pertinentes.
À faire: je devrais mettre un exemple ici en utilisant des données synthétiques et comparer certaines des méthodes.
la source
Je viens de tomber sur un document qui est directement pertinent.
Il est en fait implémenté dans https://github.com/soundcloud/cosine-lsh-join-spark où je l'ai trouvé.
Il est basé sur un hachage sensible à la localité (déjà mentionné dans d'autres réponses). Après avoir réduit les vecteurs de caractéristiques à un espace de faible dimension, il utilise une jointure de distance de Hamming rapide pour trouver les voisins les plus proches.
la source