python - logistic - hyperparameters sklearn
GridSearch y Python de scikit en general no están liberando memoria (3)
No estoy familiarizado con GridSearch, señor, pero sugiero que cuando la memoria y las grandes listas son un problema, escriba un pequeño generador personalizado. Se puede reutilizar para todos sus artículos, solo use uno que tome cualquier lista. Si implementa más allá de la solución más baja, primero lea este artículo, el mejor artículo generador que he encontrado. Escribí todo y fui pieza por pieza, cualquier pregunta que tengas después de leerla, puedo intentarlo también
https://www.jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/
No es necesario: for p1 in parameterset1:
Tratar
def listerator(this_list):
i = 0
while True:
yield this_list[i]
i += 1
La palabra ''rendimiento'' (en cualquier parte de la declaración) hace de esto un generador, no una función regular. Esto pasa y dice que igual a 0, mientras que es cierto que tengo que hacer cosas, ellos quieren que ceda this_list [0], aquí tienes. Te esperaré en i += 1
si me necesitas de nuevo. La próxima vez que se invoca, toma i += 1
y nota que todavía está en un ciclo while y le da a this_list [1] y registra su ubicación ( i += 1
nuevamente ... esperará ahí hasta que llamado de nuevo). Tenga en cuenta que al alimentarlo con la lista una vez y hacer un generador (x aquí), se agotará su lista.
In [141]: x = listerator([1,2,3])
In [142]: next(x)
Out[142]: 1
In [143]: next(x)
Out[143]: 2
In [144]: next(x)
Out[144]: 3
In [148]: next(x)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-148-5e4e57af3a97> in <module>()
----> 1 next(x)
<ipython-input-139-ed3d6d61a17c> in listerator(this_list)
2 i = 0
3 while True:
----> 4 yield this_list[i]
5 i += 1
6
IndexError: list index out of range
Veamos si podemos usarlo en a para:
In [221]: for val in listerator([1,2,3,4]):
.....: print val
.....:
1
2
3
4
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-221-fa4f59138165> in <module>()
----> 1 for val in listerator([1,2,3,4]):
2 print val
3
<ipython-input-220-263fba1d810b> in listerator(this_list, seed)
2 i = seed or 0
3 while True:
----> 4 yield this_list[i]
5 i += 1
IndexError: list index out of range
Nop. Tratemos de manejar eso:
def listerator(this_list):
i = 0
while True:
try:
yield this_list[i]
except IndexError:
break
i += 1
In [223]: for val in listerator([1,2,3,4]):
print val
.....:
1
2
3
4
Eso funciona. Ahora no intentará a ciegas devolver un elemento de lista, incluso si no está allí. Por lo que dijiste, casi puedo garantizarte que deberás poder sembrar (recoger de un cierto lugar, o comenzar de nuevo desde un lugar determinado):
def listerator(this_list, seed=None):
i = seed or 0
while True:
try:
yield this_list[i]
except IndexError:
break
i += 1
In [150]: l = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
In [151]: x = listerator(l, 8)
In [152]: next(x)
Out[152]: 9
In [153]: next(x)
Out[153]: 10
In [154]: next(x)
Out[154]: 11
i = seed or 0
es una cosa que busca semilla, pero la semilla se predetermina a Ninguna, por lo que generalmente comenzará en el lugar lógico, 0, el comienzo de la lista
¿Cómo puedes usar esta bestia sin usar (casi) ningún recuerdo?
parameterset1 = [1,2,3,4]
parameterset2 = [''a'',''b'',''c'',''d'']
In [224]: for p1 in listerator(parameterset1):
for p2 in listerator(parameterset2):
print p1, p2
.....:
1 a
1 b
1 c
1 d
2 a
2 b
2 c
2 d
3 a
3 b
3 c
3 d
4 a
4 b
4 c
4 d
eso parece familiar ¿eh? Ahora puede procesar un billón de valores uno por uno, eligiendo los más importantes para escribir en el disco y nunca explotar su sistema. ¡Disfrutar!
Hice algunas observaciones extrañas de que mis GridSearches siguen fallando después de un par de horas y al principio no pude entender por qué. Supervisé el uso de memoria con el tiempo y vi que comenzó con unos pocos gigabytes (~ 6 Gb) y siguió aumentando hasta que se colgó el nodo cuando alcanzó el máximo. 128 Gb el hardware puede tomar. Estaba experimentando con bosques aleatorios para la clasificación de una gran cantidad de documentos de texto. Para simplificar, para descubrir qué está pasando, volví a la ingenua Bayes.
Las versiones que estoy usando son
- Python 3.4.2
- scikit-learn 0.15.2
Encontré una discusión relacionada en la lista scikit-issue en GitHub sobre este tema: https://github.com/scikit-learn/scikit-learn/issues/565 y https://github.com/scikit-learn/scikit-learn/pull/770
¡Y parece que ya se trató con éxito!
Entonces, el código relevante que estoy usando es
grid_search = GridSearchCV(pipeline,
parameters,
n_jobs=1, #
cv=5,
scoring=''roc_auc'',
verbose=2,
pre_dispatch=''2*n_jobs'',
refit=False) # tried both True and False
grid_search.fit(X_train, y_train)
print(''Best score: {0}''.format(grid_search.best_score_))
print(''Best parameters set:'')
Solo por curiosidad, más tarde decidí hacer la búsqueda de grillas de manera rápida y sucia a través de un ciclo anidado
for p1 in parameterset1:
for p2 in parameterset2:
...
pipeline = Pipeline([
(''vec'', CountVectorizer(
binary=True,
tokenizer=params_dict[i][0][0],
max_df=params_dict[i][0][1],
max_features=params_dict[i][0][2],
stop_words=params_dict[i][0][3],
ngram_range=params_dict[i][0][4],)),
(''tfidf'', TfidfTransformer(
norm=params_dict[i][0][5],
use_idf=params_dict[i][0][6],
sublinear_tf=params_dict[i][0][7],)),
(''clf'', MultinomialNB())])
scores = cross_validation.cross_val_score(
estimator=pipeline,
X=X_train,
y=y_train,
cv=5,
scoring=''roc_auc'',
n_jobs=1)
params_dict[i][1] = ''%s,%0.4f,%0.4f'' % (params_dict[i][1], scores.mean(), scores.std())
sys.stdout.write(params_dict[i][1] + ''/n'')
Hasta aquí todo bien. La búsqueda de cuadrícula se ejecuta y escribe los resultados en stdout. Sin embargo, después de un tiempo excede el límite de memoria de 128 GB de nuevo. Mismo problema que con GridSearch en scikit. Después de un poco de experimentación, finalmente descubrí que
gc.collect()
len(gc.get_objects()) # particularly this part!
en el bucle for soluciona el problema y el uso de memoria se mantiene constantemente a 6.5 Gb durante el tiempo de ejecución de ~ 10 horas.
Eventualmente, conseguí que funcione con la corrección anterior, sin embargo, tengo curiosidad por escuchar sus ideas sobre lo que podría estar causando este problema y sus sugerencias y sugerencias.
No puedo ver tu código exacto, pero hoy tuve un problema similar. Vale la pena intentarlo. La expansión de memoria similar puede ocurrir fácilmente cuando copiamos valores de una matriz mutable o enlistamos un objeto similar a otra variable creando una copia de la original y luego modificamos la nueva matriz o lista con append o algo similar aumentando el tamaño de y al mismo tiempo aumentar el objeto original también en el fondo.
Entonces este es un proceso exponencial, así que después de un tiempo nos quedamos sin memoria. Pude y quizás puedas evitar este tipo de fenómeno con deepcopy()
el objeto original en un valor que pasa.
Tuve el problema similar, exploté la memoria con un proceso similar, luego logré quedarme con una carga de memoria del 10%.
ACTUALIZACIÓN: Ahora veo el fragmento del código con pandas DataFrame. Habría un problema de validación tan fácil.
RandomForest en 0.15.2 no admite entradas dispersas.
Actualice sklearn y vuelva a intentarlo ... con suerte, esto permitirá que las múltiples copias que terminan consumiendo tengan menos memoria. (y acelerar las cosas)