Je lis sur les filtres à fleurs et ils semblent tout simplement stupides. Tout ce que vous pouvez accomplir avec un filtre de bloom, vous pouvez le faire dans moins d'espace, plus efficacement, en utilisant une seule fonction de hachage plutôt que plusieurs, ou c'est ce qu'il semble. Pourquoi utiliseriez-vous un filtre Bloom et comment est-il utile?
De Wikipedia :
Les filtres Bloom ont un avantage d'espace important par rapport aux autres structures de données pour représenter des ensembles, tels que les arbres de recherche binaires à équilibrage automatique, les essais, les tables de hachage ou les tableaux simples ou les listes liées des entrées. La plupart d'entre eux nécessitent de stocker au moins les éléments de données eux-mêmes, ce qui peut nécessiter un petit nombre de bits, pour les petits entiers, à un nombre arbitraire de bits, comme pour les chaînes (les essais sont une exception, car ils peuvent partager le stockage entre éléments avec des préfixes égaux). Les structures liées entraînent une surcharge d'espace linéaire supplémentaire pour les pointeurs. Un filtre Bloom avec une erreur de 1% et une valeur optimale de k, en revanche, ne nécessite qu'environ 9,6 bits par élément, quelle que soit la taille des éléments. Cet avantage provient en partie de sa compacité, héritée des tableaux, et en partie de sa nature probabiliste. Si un taux de faux positifs de 1% semble trop élevé, chaque fois que nous ajoutons environ 4,8 bits par élément, nous le diminuons de dix fois.
C'est assez clair pour moi.
Un filtre bloom ne stocke pas les éléments eux-mêmes, c'est le point crucial. Vous n'utilisez pas de filtre de bloom pour tester si un élément est présent, vous l'utilisez pour tester s'il n'est certainement pas présent, car il ne garantit aucune fausse négatifs. Cela vous permet de ne pas faire de travail supplémentaire pour les éléments qui n'existent pas dans un ensemble (tels que disk IO pour les rechercher).
Et le tout dans beaucoup moins d'espace que quelque chose comme une table de hachage (qui sera probablement partiellement sur le disque pour les grands ensembles de données). Bien que vous puissiez utiliser un filtre de floraison en conjonction avec une structure comme une table de hachage, une fois que vous êtes certain que l'élément a une chance d'être présent.
Ainsi, un exemple de modèle d'utilisation pourrait être:
Vous avez beaucoup de données sur disque - vous décidez de la limite d'erreur que vous voulez (par exemple 1%), qui prescrit la valeur de m. Ensuite, le k optimal est déterminé (à partir de la formule donnée dans l'article). Vous remplissez une fois votre filtre à partir de ces données liées au disque.
Vous avez maintenant le filtre en RAM. Lorsque vous devez traiter un élément, vous interrogez votre filtre pour voir s'il a une chance d'exister dans votre ensemble de données. Si ce n'est pas le cas, aucun travail supplémentaire n'est effectué. Pas de lecture de disque, etc. (ce que vous auriez à faire s'il s'agissait d'un hachage ou d'un arbre, etc.).
Sinon, si le filtre dit "Oui, c'est là-dedans", il y a 1% de chance que ce soit faux, alors faites le travail nécessaire pour le découvrir. 99% du temps, vraiment sera être là, donc le travail n'était pas pour rien.
Alex l'a assez bien expliqué. Pour ceux qui ne l'ont pas encore bien compris, j'espère que cet exemple vous aidera à comprendre:
Disons que je travaille pour Google, dans l'équipe Chrome, et je veux ajouter une fonctionnalité au navigateur qui informe l'utilisateur si l'URL qu'il a entrée est une URL malveillante. J'ai donc un ensemble de données d'environ 1 million d'URL malveillantes, la taille de ce fichier étant d'environ 25 Mo. Comme la taille est assez grande, (grande par rapport à la taille du navigateur lui-même), je stocke ces données sur un serveur distant.
Cas 1: j'utilise une fonction de hachage avec une table de hachage. Je décide d'une fonction de hachage efficace et exécute tous les 1 million d'URL via la fonction de hachage pour obtenir des clés de hachage. Je fais ensuite une table de hachage (un tableau), où la clé de hachage me donnerait l'index pour placer cette URL. Alors maintenant, une fois que j'ai haché et rempli la table de hachage, je vérifie sa taille. J'ai stocké les 1 million d'URL dans la table de hachage avec leurs clés. La taille est donc d'au moins 25 Mo. Cette table de hachage, en raison de sa taille, sera stockée sur un serveur distant. Lorsqu'un utilisateur arrive et entre une URL dans la barre d'adresse, je dois vérifier s'il est malveillant. Ainsi, je lance l'URL via la fonction de hachage (le navigateur lui-même peut le faire) et j'obtiens une clé de hachage pour cette URL. Je dois maintenant faire une demande à mon serveur distant avec cette clé de hachage, pour vérifier si l'URL particulière dans ma table de hachage avec cette clé particulière est la même que celle que l'utilisateur a entrée. Si oui, il est malveillant et si non, il n'est pas malveillant. Ainsi, chaque fois que l'utilisateur entre une URL, une demande au serveur distant doit être faite pour vérifier s'il s'agit d'une URL malveillante. Cela prendrait beaucoup de temps et ralentirait ainsi mon navigateur.
Cas 2: j'utilise un filtre bloom. La liste complète de 1 million d'URL est exécutée à travers le filtre de floraison à l'aide de plusieurs fonctions de hachage et les positions respectives sont marquées comme 1, dans un énorme tableau de 0. Disons que nous voulons un taux de faux positifs de 1%, en utilisant une calculatrice de filtre de floraison ( http://hur.st/bloomfilter?n=1000000&p=0.01 ), nous obtenons la taille du filtre de floraison requis comme seulement 1,13 Mo. Cette petite taille est attendue car, même si la taille du tableau est énorme, nous ne stockons que 1 ou 0 et non les URL comme dans le cas de la table de hachage.Ce tableau peut être traité comme un tableau de bits. Autrement dit, puisque nous n'avons que deux valeurs 1 et 0, nous pouvons définir des bits individuels au lieu d'octets. Cela réduirait l'espace pris par 8 fois. Ce filtre bloom de 1,13 Mo, en raison de sa petite taille, peut être stocké dans le navigateur Web lui-même !! Ainsi, lorsqu'un utilisateur arrive et entre une URL, nous appliquons simplement les fonctions de hachage requises (dans le navigateur lui-même) et vérifions toutes les positions dans le filtre de floraison (qui est stocké dans le navigateur). Une valeur de 0 dans n'importe laquelle des positions nous indique que cette URL n'est DEFINITIVEMENT PAS dans la liste des URL malveillantes et que l'utilisateur peut continuer librement. Ainsi, nous n'avons pas appelé le serveur et donc gagné du temps. Une valeur de 1 nous indique que l'URL PEUT être dans la liste des URL malveillantes. Dans ces cas, nous appelons le serveur distant et là-bas, nous pouvons utiliser une autre fonction de hachage avec une table de hachage comme dans le premier cas pour récupérer et vérifier si l'URL est réellement présente. Étant donné que la plupart du temps, une URL n'est pas susceptible d'être malveillante, le petit filtre de floraison dans le navigateur comprend cela et permet ainsi de gagner du temps en évitant les appels vers le serveur distant. Seulement dans certains cas, si le filtre de bloom nous indique que l'URL PEUT être malveillante, seulement dans ces cas, nous appelons le serveur. Cette "PUISSANCE" a 99% raison.
Ainsi, en utilisant un petit filtre de floraison dans le navigateur, nous avons gagné beaucoup de temps car nous n'avons pas besoin d'appeler le serveur pour chaque URL saisie.
Nous pouvons voir que la table de hachage avec une seule fonction de hachage est utilisée à des fins différentes d'un filtre de bloom. J'espère que cela dissipe vos doutes :)
J'ai mis en place un filtre bloom pour la tâche de test d'URL malveillants en Python. Le code peut être trouvé ici - https://github.com/tarunsharma1/Bloom-Filter Le code est très simple à comprendre et une description détaillée est fournie dans le fichier readme.
Je vais commencer par l'explication de ce qu'est un filtre bloom, ce qu'il peut et ne peut pas faire, pourquoi en avons-nous besoin, montrer une description intuitive de son fonctionnement et donner un exemple quand il peut être utile.
Donc, un filtre de bloom standard est un structure de données probabiliste que peut *:
definitely not in the set
ou possibly in the set
Ce possibly in the set
Est exactement pourquoi il est appelé probabiliste. L'utilisation de mots intelligents signifie que faux positif sont possibles (il peut y avoir des cas où il pense à tort que l'élément est positif) mais qu'un faux négatif est impossible.
Mais cela ne peut pas *:
*Cet ensemble de can/can't est pour un filtre de floraison de base. Parce qu'il s'agit d'une structure de données utile qui a été créée il y a longtemps, les gens ont trouvé comment augmenter avec d'autres fonctionnalités tiles .
Mais attendez une minute: nous connaissons déjà une structure de données qui peut répondre à tout cela sans vague "possible" et aussi sans toutes les limitations (ne peut pas supprimer, ne peut pas tout montrer). Et cela s'appelle un set . Et voici un avantage majeur d'un filtre de bloom: il est efficace en espace et constant en espace .
Cela signifie que peu importe le nombre d'éléments que nous y stockons, l'espace sera le même. Oui, un filtre de floraison avec des éléments 10^6
(Filtre de floraison inutile) prendra la même quantité d'espace qu'un filtre de floraison avec des éléments 10^20
Et le même espace que le filtre de floraison avec 0
éléments. Alors, combien d'espace cela prendra-t-il? C'est à vous de décider (mais il y a un échange de: plus vous avez d'éléments, plus vous êtes incertain avec vous possible in the set
Réponse.
Une autre chose intéressante est que c'est un espace constant. Lorsque vous enregistrez les données dans un ensemble, vous devez réellement enregistrer ces données. Donc, si vous stockez this long string in the set
, Vous devez au moins utiliser 27 octets d'espace. Mais pour une erreur de 1% et une valeur optimale de k **, vous aurez besoin d'environ 9,6 bits (<2 octets) par élément (qu'il s'agisse d'un int court ou d'un énorme mur de texte).
Une autre propriété est que toutes les opérations prennent un temps constant, ce qui n'est absolument pas la même chose que le temps constant amorti dans le cas d'ensembles (rappelez-vous que si l'ensemble a des collisions, il peut se détériorer en O(n)
temps).
**k est une valeur des fonctions de hachage utilisées dans le filtre de floraison
Je ne décrirai pas comment les filtres de floraison fonctionnent (l'article wikipedia fait un très bon travail pour tout expliquer). Ici, je vais dire brièvement les bases.
m
k
différentes fonctions de hachage (plus elles sont indépendantes, mieux c'est)k
hachages de cette valeur et définissez les bits correspondants à 1k
et si au moins l'un d'entre eux n'est pas défini, il n'est sûrement pas dans l'ensemble. Sinon, il peut être dans l'ensemble.Même cette description suffit pour comprendre pourquoi nous ne pouvons pas être sûrs (vous pouvez obtenir tous les bits définis à partir de diverses autres valeurs). Voici ne visualisation très agréable de son fonctionnement .
Alors, quand les filtres de floraison peuvent-ils être utiles? La réponse courte est partout où les faux positifs sont acceptables et où vous voudriez vérifier si quelque chose est dans l'ensemble , mais même s'ils ne le sont pas, il peut être une première ligne de défense pour exclure les appels coûteux aux vérificateurs.
Voici une liste de descriptions plus concrètes:
Les filtres Bloom sont très utiles en bioinformatique. Ils peuvent être plus économes en espace par rapport à l'utilisation d'un hachage normal, surtout lorsque la taille des chaînes avec lesquelles vous travaillez peut être de centaines de millions de lettres avec un très petit alphabet, c'est-à-dire {A, G, T, C}. Ils sont généralement utilisés pour évaluer si un certain k-mer est présent ou absent dans un génome. Il y a un exemple de celui utilisé pour quelque chose de pertinent ici .
MODIFIER:
Les multiples fonctions de hachage sont utilisées pour minimiser les faux positifs. L'espoir est qu'entre toutes les fonctions de hachage k, chaque valeur aura une signature unique dans le tableau de bits par rapport à toutes les autres valeurs possibles. Cependant, les faux positifs existent, mais ils peuvent être minimisés à un niveau gérable. En utilisant cette technique, vous hachez des éléments indépendamment de leur taille. Lorsque vous les recherchez, vous utilisez chaque fonction de hachage et vérifiez que leurs valeurs binaires sont bien 1.
Comparez cela au génome humain, où une augmentation de la taille de l'élément augmente considérablement la taille de la table de hachage (la taille de la table est de 4 * 4k). Cela suppose que vous codiez les éléments en utilisant 2 bits/lettre.
Si un filtre Bloom renvoie qu'un élément est membre de l'ensemble, il existe une certaine probabilité de faux positif. Si une seule fonction de hachage était utilisée pour indiquer l'appartenance à l'ensemble, la probabilité d'un faux positif serait plus élevée que l'utilisation de plusieurs fonctions de hachage.