[Python]Demande d'explication d'un code de <<hash>> pour l'analyse de données

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je suis en train de lire le livre Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow_ Concepts, Tools, and Techniques to Build Intelligent Systems , la deuxième édition et je suis bloqué sur une partie de code que je n’arrive pas à comprendre. J’aimerais tout d’abord donner le contexte; on veut créer un ensemble de set à partir de notre ensemble de données. Pour cela on prend aléatoirement 20% des données. Le problème est qu’en rajoutant de nouvelles données ou juste après ré-exécution du code alors cet ensemble test va changer, et nous voulons le garder constant et lui rajouter une éventuelle 20% de nouvelles données. L’auteur donne la solution suivante (voir code en dessous) en la justifiant par :

For example, you could compute a hash of each instance’s identifier and put that instance in the test set if the hash is lower than or equal to 20% of the maximum hash value. This ensures that the test set will remain consistent across multiple runs, even if you refresh the dataset. The new test set will contain 20% of the new instances, but it will not contain any instance that was previously in the training set.

Le code est :

from zlib import crc32

def test_set_check(identifier, test_ratio):

     return crc32(np.int64(identifier)) & 0xffffffff < test_ratio * 2**32

def split_train_test_by_id(data, test_ratio, id_column):
     ids = data[id_column]

     in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio))

     return data.loc[~in_test_set], data.loc[in_test_set]

Excusez-moi j’ai tenté de mettre tout le code en mode code mais c’est le meilleur affichage que j’ai pu avoir.

J’ai cherché ce que veut dire hash et j’ai compris que généralement les hash functions vont associer à un objet d’entrée un nombre en sortie. Donc si j’ai bien compris ce que l’auteur veut faire, c’est qu’il va prendre les identifiants des données, leur appliquer sa fonction hash pour avoir des nombres et si ce nombre est inférieur à test_ratio*valeur maximale assignée par la hash function alors les données vont dans l’ensemble test sinon elles vont dans l’ensemble d’entraînement. Mais en fait je vois mal la part d’aléatoire dont tout cela. Car on pourrait tout aussi bien les 20% premières données qu’on a (et si on a de nouvelles données qui se rajoutent alors on prendre les 20% premières données de celles-ci aussi…) mais ce procédé n’est pas aléatoire… C’est pour cela que je me redirige vers vous, afin que vous m’expliquiez un peu plus en détail comment ce code marche. J’ai essayé de comprendre la fonction crc32 mais en vain.

J’espère que vous pourrez m’aider à mieux comprendre puisque cette me paraît importante.

Merci d’avance.

+0 -0

Salut,

Le hash est un effet une somme cryptographique calculée à partir des données d’entrée, et qui va généralement renvoyer quelque chose d’assimilable à un nombre (ou d’un ensemble de taille limitée).

L’intérêt dans ton cas c’est qu’il va pouvoir distribuer les données et casser toute relation d’ordre entre tes chaînes de caractères : ce n’est pas parce que a > b que hash(a) > hash(b) par exemple (dans le cas de crc32 ici), et donc tirer 20% des éléments à peu près n’importe où dans l’ensemble.

Pour ce qui est de l’aléatoire, ce n’est pas ton cas ici car utilises l’algo crc32, mais sâche qu’en Python la fonction de hash est effectivement aléatoire sur les chaînes de caractère (pour éviter de les rendre prédictible et se protéger ainsi de certaines attaques sur les dictionnaires). Tu peux tenter de lancer plusieurs fois l’interpréteur Python et constater que hash('toto') ne vaudra pas la même chose à chaque fois.

Bonsoir,

Merci artragis, je m’en souviendrai pour la prochaine fois !

Merci entwanne pour votre explication. Et du coup l’explication de l’auteur manque un peu de rigueur non ? Quand il dit :

For example, you could compute a hash of each instance’s identifier and put that instance in the test set if the hash is lower than or equal to 20% of the maximum hash value.

Si on se suppose dans un cas où la valeur maximale assignée par la fonction est 20, et que la fonction associe à toutes les données, sauf une, des valeurs entre 0 et 4 et la donnée qui reste lui est associée 20, alors on aurait construit un ensemble test constitué de presque toutes les données. Mais je suppose son explication se base sur le fonctionnement de l’algorithme crc32. Et du coup l’algorithme crc32 ne va pas prendre aléatoirement 20% des données, mais la manière dont il le fera est "assimilable à de l’aléatoire" c’est ça ? Et du coup cet algorithme n’est efficace pour notre but que si l’indexation se fait par des chaînes de caractères ou des nombres, car il brise les relations d’ordre entre ce type d’objet. Et il faut que l’indexation soit unique car s’il s’avère que deux données différentes ont même chaîne de caractère comme indexe alors il les mettrait dans toutes les deux dans l’ensemble test.

Salut,

@DavidKayo tu as raison dans ton exemple. Seulement, les fonctions de hachage couramment utilisées (notamment crc32) envoient les données de l’espace de départ à peu près uniformément sur l’espace d’arrivée (ce qui est implicite dans ton bouquin). Du coup, si tu prends les valeurs dont les hash sont inférieurs à 20% de la valeur de hash maximal, tu t’attends à avoir environ 20% de l’ensemble des valeurs.

Une petite précision au passage, un hash n’est pas cryptographique en soi, et toutes les fonctions de hachage n’ont pas de bonnes propriétés pour la cryptographie. La fonction de hashage n’est pas aléatoire non plus, et pour la version python je suppose qu’ils initialisent juste un sel aléatoirement au lancement de l’interpréteur. (j’ai compris ce que tu voulais dire @entwanne)

+1 -0

Oui, c’est extrapoler un peu le fonctionnement du hash avec l’utilisation qu’on en fait habituellement. Les bons algorithmes de hash répartissent à peu près uniformément les résultats, et évitent au maximum les conflits.

Parce que sinon un algorithme tout con pourrait être de renvoyer le code ascii du premier caractère de la chaîne en tant que hash, et ce serait très mauvais pour l’utilisation qui en est faite ici.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte