saving - python 3.6 pickle
Pickle dump archivo enorme sin error de memoria (9)
Si su clave y sus valores son cadenas, puede usar uno de los motores de almacenamiento de valores-clave persistentes incrustados disponibles en la biblioteca estándar de Python. Ejemplo de los documentos del módulo anydbm
:
import anydbm
# Open database, creating it if necessary.
db = anydbm.open(''cache'', ''c'')
# Record some values
db[''www.python.org''] = ''Python Website''
db[''www.cnn.com''] = ''Cable News Network''
# Loop through contents. Other dictionary methods
# such as .keys(), .values() also work.
for k, v in db.iteritems():
print k, ''/t'', v
# Storing a non-string key or value will raise an exception (most
# likely a TypeError).
db[''www.yahoo.com''] = 4
# Close when done.
db.close()
Tengo un programa en el que, básicamente, ajusto la probabilidad de que sucedan ciertas cosas en función de lo que ya se sabe. Mi archivo de datos ya está guardado como un objeto de diccionario de salmuera en Dictionary.txt. El problema es que cada vez que ejecuto el programa, extrae el Dictionary.txt, lo convierte en un objeto de diccionario, lo edita y sobrescribe Dictionary.txt. Esto es bastante intensivo de memoria ya que el Dictionary.txt tiene 123 MB. Cuando vuelvo recibo el MemoryError, todo parece estar bien cuando lo saco.
¿Hay una forma mejor (más eficiente) de hacer las ediciones? (Quizás sin tener que sobrescribir el archivo completo cada vez)
¿Hay alguna manera de invocar la recolección de basura (a través del módulo gc)? (Ya lo tengo habilitado automáticamente a través de gc.enable ())
Sé que además de readlines () puedes leer línea por línea. ¿Hay alguna manera de editar el diccionario de forma incremental línea por línea cuando ya tengo un archivo de objeto de diccionario completamente completado en el programa?
¿Alguna otra solución?
Gracias por tu tiempo.
¿Has intentado utilizar la función de enrutamiento de transmisión por secuencias ?: https://code.google.com/p/streaming-pickle/
Acabo de resolver un error de memoria similar al cambiar al enmudecimiento de transmisión.
¿Qué tal esto?
import cPickle as pickle
p = pickle.Pickler(open("temp.p","wb"))
p.fast = True
p.dump(d) # d could be your dictionary or any file
Tuve un error de memoria y lo resolví usando protocol = 2:
cPickle.dump(obj, file, protocol=2)
Soy el autor de un paquete llamado klepto
(y también el autor de dill
). klepto
está diseñado para almacenar y recuperar objetos de una manera muy simple, y proporciona una interfaz de diccionario simple para bases de datos, memoria caché y almacenamiento en disco. A continuación, muestro el almacenamiento de objetos grandes en un "archivo de directorio", que es un directorio del sistema de archivos con un archivo por entrada. Elijo serializar los objetos (es más lento, pero usa dill
, por lo que puede almacenar casi cualquier objeto), y elijo un caché. Usar una caché de memoria me permite tener acceso rápido al archivo de directorio, sin tener que tener todo el archivo en la memoria. La interacción con una base de datos o un archivo puede ser lenta, pero la interacción con la memoria es rápida ... y puede rellenar la memoria caché a su gusto desde el archivo.
>>> import klepto
>>> d = klepto.archives.dir_archive(''stuff'', cached=True, serialized=True)
>>> d
dir_archive(''stuff'', {}, cached=True)
>>> import numpy
>>> # add three entries to the memory cache
>>> d[''big1''] = numpy.arange(1000)
>>> d[''big2''] = numpy.arange(1000)
>>> d[''big3''] = numpy.arange(1000)
>>> # dump from memory cache to the on-disk archive
>>> d.dump()
>>> # clear the memory cache
>>> d.clear()
>>> d
dir_archive(''stuff'', {}, cached=True)
>>> # only load one entry to the cache from the archive
>>> d.load(''big1'')
>>> d[''big1''][-3:]
array([997, 998, 999])
>>>
klepto
proporciona acceso rápido y flexible a grandes cantidades de almacenamiento, y si el archivo permite el acceso paralelo (por ejemplo, algunas bases de datos), puede leer los resultados en paralelo. También es fácil compartir resultados en diferentes procesos paralelos o en diferentes máquinas. Aquí creo una segunda instancia de archivo, apuntando al mismo archivo de directorio. Es fácil pasar claves entre los dos objetos, y no funciona de manera diferente a un proceso diferente.
>>> f = klepto.archives.dir_archive(''stuff'', cached=True, serialized=True)
>>> f
dir_archive(''stuff'', {}, cached=True)
>>> # add some small objects to the first cache
>>> d[''small1''] = lambda x:x**2
>>> d[''small2''] = (1,2,3)
>>> # dump the objects to the archive
>>> d.dump()
>>> # load one of the small objects to the second cache
>>> f.load(''small2'')
>>> f
dir_archive(''stuff'', {''small2'': (1, 2, 3)}, cached=True)
También puede elegir entre varios niveles de compresión de archivos y si desea que los archivos se mapeen en la memoria. Hay muchas opciones diferentes, tanto para backends de archivos como para backends de bases de datos. La interfaz es idéntica, sin embargo.
Con respecto a sus otras preguntas sobre recolección de basura y edición de partes del diccionario, ambas son posibles con klepto
, ya que puede cargar y eliminar objetos de la memoria caché, volcar, cargar y sincronizar con el backend de archivo, o cualquiera de los otros métodos de diccionario.
Vea un tutorial más largo aquí: https://github.com/mmckerns/tlkklp
Obtenga klepto
aquí: https://github.com/uqfoundation
Ninguna de las respuestas anteriores funcionó para mí. Terminé usando Hickle, que es un reemplazo directo para pickle basado en HDF5. En lugar de guardarlo en un pickle, guarda los datos en un archivo HDF5. La API es idéntica para la mayoría de los casos de uso y tiene algunas características realmente geniales, como la compresión.
pip install hickle
Ejemplo:
# Create a numpy array of data
array_obj = np.ones(32768, dtype=''float32'')
# Dump to file
hkl.dump(array_obj, ''test.hkl'', mode=''w'')
# Load data
array_hkl = hkl.load(''test.hkl'')
Yo estaba teniendo el mismo problema. Yo uso joblib y el trabajo estaba hecho. En caso de que alguien quiera saber otras posibilidades.
de sklearn.externals import joblib
guardar el modelo en el disco
filename = ''finalized_model.sav''
joblib.dump (modelo, nombre de archivo)
algún tiempo después...
cargar el modelo desde el disco loaded_model = joblib.load (filename) result =
loaded_model.score (X_test, Y_test) imprimir (resultado)
Esto puede parecer trivial, pero trate de usar el Python de 64 bits si no lo está.
Recientemente tuve este problema. Después de probar cpickle con ASCII y el protocolo binario 2, descubrí que mi SVM del juego de aprendizaje de la ciencia ficción entrenado en más de 20 gb de datos no estaba encurtiendo debido a un error de memoria. Sin embargo, el paquete de eneldo pareció resolver el problema. Dill no creará muchas mejoras para un diccionario, pero puede ayudar con la transmisión. Está destinado a transmitir bytes en escabeche a través de una red.
import dill
with open(path,''wb'') as fp:
dill.dump(outpath,fp)
dill.load(fp)
Si la eficiencia es un problema, intente cargar / guardar en una base de datos. En este caso, su solución de almacenamiento puede ser un problema. En 123 mb, Pandas debería estar bien. Sin embargo, si la máquina tiene memoria limitada, SQL ofrece operaciones de bolsa rápidas y optimizadas sobre los datos, generalmente con soporte multiproceso. Mi kernel polym salvado.