2010-02-12 14 views
7

Estoy buscando un generador de funciones de funciones hash que podría generar una familia de funciones hash dado un conjunto de parámetros. No he encontrado ningún generador de ese tipo hasta el momento. ¿Hay alguna manera de hacerlo con el paquete hashlib?funciones hash generador de familia en python

Por ejemplo me gustaría hacer algo como:

h1 = hash_function(1) 
h2 = hash_function(2) 
... 

y h1 y h2 habría diferentes funciones hash.

Para aquellos de ustedes que puedan saber sobre esto, estoy tratando de implementar un algoritmo de min-hash en un conjunto de datos muy grande.

Básicamente, tengo un gran conjunto de características (100 millones a 1 mil millones) para un documento dado, y necesito crear de 1000 a 10000 permutaciones aleatorias diferentes para este conjunto de características.

NO deseo de construir las permutaciones aleatorias de forma explícita por lo que la técnica que le gustaría utilizar en el siguiente:

  1. generar una función hash h y considerar que durante dos índices r y s
  2. r aparece antes del s en la permutación si es h(r) < h(s) y lo hace para 100 a 1000 funciones hash diferentes.

¿Hay alguna biblioteca conocida que me haya pasado por alto? ¿O cualquier forma estándar de generar familias de funciones hash con python de las que puedas estar al tanto?

Respuesta

6

que acababa de hacer algo como (si es que no es necesario hilo de seguridad - no es difícil de alterar Si necesita hilo de seguridad - y asumiendo una versión de 32 bits de Python):

import random 

_memomask = {} 

def hash_function(n): 
    mask = _memomask.get(n) 
    if mask is None: 
    random.seed(n) 
    mask = _memomask[n] = random.getrandbits(32) 
    def myhash(x): 
    return hash(x)^mask 
    return myhash 
+1

Gracias por esta respuesta. Parece que funciona muy bien. ¿Alguna particular para usar ese tipo de funciones hash? eficiencia? producirá permutaciones aproximadas muy diferentes en algún sentido? –

+0

El 'hash' incorporado es decente y bastante eficiente. Decirlo con un número que depende (pero de manera bastante caótica) del índice dentro de la familia parece otra forma decente/eficiente de activar esa función hash. en una familia Si la velocidad no es un problema, puedes usar hashing más fuerte (calidad de criptografía), supongo - que presumiblemente te dará mayor calidad (ni el hash ni el azar son de calidad criptográfica y por lo tanto ninguno es su XOR ;-) pero el impacto de velocidad es REALMENTE grande (órdenes de magnitud ...). –

+0

Gracias. En realidad, creo que la velocidad será clave para mí aquí. La única "calidad" que estoy buscando es que las funciones hash generen permutaciones aleatorias "tan diferentes" como sea posible (aunque no estoy seguro de cómo cuantificar esto ...) por el proceso que describí en mi pregunta original. De nuevo, muchas gracias por tu excelente respuesta. –

0

Como se mencionó anteriormente, puede utilizar hashing universal para minhash. Por ejemplo:

import random 



def minhash(): 
    d1 = set(random.randint(0, 2000) for _ in range(1000)) 
    d2 = set(random.randint(0, 2000) for _ in range(1000)) 
    jacc_sim = len(d1.intersection(d2))/len(d1.union(d2)) 
    print("jaccard similarity: {}".format(jacc_sim)) 

    N_HASHES = 200 
    hash_funcs = [] 
    for i in range(N_HASHES): 
     hash_funcs.append(universal_hashing()) 

    m1 = [min([h(e) for e in d1]) for h in hash_funcs] 
    m2 = [min([h(e) for e in d2]) for h in hash_funcs] 
    minhash_sim = sum(int(m1[i] == m2[i]) for i in range(N_HASHES))/N_HASHES 
    print("min-hash similarity: {}".format(minhash_sim)) 



def universal_hashing(): 
    def rand_prime(): 
     while True: 
      p = random.randrange(2 ** 32, 2 ** 34, 2) 
      if all(p % n != 0 for n in range(3, int((p ** 0.5) + 1), 2)): 
       return p 
    m = 2 ** 32 - 1 
    p = rand_prime() 
    a = random.randint(0, p) 
    if a % 2 == 0: 
     a += 1 
    b = random.randint(0, p) 
    def h(x): 
     return ((a * x + b) % p) % m 
    return h 

Reference

+0

Si bien este enlace puede responder la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace de referencia. Las respuestas de solo enlace pueden dejar de ser válidas si la página vinculada cambia. - [De la opinión] (/ reseña/mensajes de baja calidad/18596735) – Yaron