Scikit-learn: Ajuste de estimadores adicionales para métodos de conjunto

Creado en 16 ene. 2013  ·  73Comentarios  ·  Fuente: scikit-learn/scikit-learn

Me gustaría proponer un método de instancia adicional a los estimadores de conjunto para ajustar subestimadores adicionales. Preparé una implementación para aumentar el gradiente que parece funcionar a través de mis pruebas limitadas. Estaba pensando que la firma sería algo así como

def fit_extend(self, X, y, n_estimators):

donde self.n_estimators += n_estimators se actualiza como tal. No creo que fit_extend sea un nombre particularmente bueno, así que agradecería otras sugerencias. Tal vez querríamos codificar las características y etiquetas cuando se llama a fit() para que podamos comprobar que se proporcionan las mismas características y etiquetas a esta función.

Si la gente piensa que esto sería una adición útil, estaría dispuesto a armar un PR, parece que debería ser sencillo de implementar y agregar pruebas/documentos.

New Feature

Todos 73 comentarios

Esta es definitivamente una característica que queremos. La pregunta es: ¿cuál sería la mejor manera de implementarlo (en términos de API)?
Hay algo ligeramente similar en adaboost pr: #522. Eso implementa la predicción con un subconjunto de estimadores, lo que también es muy útil.

¿Cómo crees que se ve el escenario/código, donde un usuario quiere fit_extend ? Probablemente sea más útil en un entorno interactivo, ¿verdad?

Hay una función ligeramente relacionada en SGD, partial_fit . Sin embargo, eso es en realidad para el aprendizaje en línea, por lo que obtiene datos diferentes.

Me gustaría obtener esta función agregando la menor cantidad posible de API y nombres;)

Por cierto, no haría hash X y y . No veo una razón para obligar al usuario a proporcionar los mismos datos de entrada.

Me gustaría entrenar una pequeña cantidad de subestimadores a la vez (y esperar un tiempo relativamente corto). Luego, pruébelo en mi conjunto de validación cruzada y, si mi puntaje CV sigue cayendo, puedo continuar entrenando. A diferencia de entrenar una gran cantidad de subestimadores y esperar mucho tiempo (varias horas para mí). Esa fue mi motivación.

Puedo entender dudar acerca de agregar otro método de instancia. Pensé que podría valer la pena agregar otro parámetro opcional para encajar (), pero vi esta cita en la página de contribución.

los parámetros de ajuste deben restringirse a variables directamente dependientes de los datos

Así que no estaba seguro de que fuera una buena idea. haría

def fit(self, X, y, n_estimators=self.n_estimators)

¿estar bien visto? Luego, si n_estimators > self.n_estimators , entrenaremos a muchos más estimadores.

Estoy de acuerdo en que agregar el parámetro n_estimators al método de predicción es bueno, pero creo que estará de acuerdo en que resuelve un problema diferente. Para mi problema, realizar una búsqueda de cuadrícula en n_estimators no es realmente una opción porque lleva mucho tiempo.

Hasta que acuerdemos una interfaz adecuada para hacer eso, podría usar el siguiente truco:

# Train a forest of 10 trees
clf1 = RandomForestClassifier(n_estimators=10)
clf1.fit(X, y)

# Train a second forest of 10 trees
clf2 = RandomForestClassifier(n_estimators=10)
clf2.fit(X, y)

# Extend clf1 with clf2
clf1.estimators_.extend(clf2.estimators_)
clf1.n_estimators += clf2.n_estimators

# clf1 now counts 20 trees

Tenga en cuenta que esto solo funciona para RandomForest y ExtraTrees. El mismo truco no se puede usar con Gradient Boosting.

Ver #1626. ¿Sería la interrupción temprana una solución aceptable para usted?

@amueller Comparto la misma opinión que @glouppe aquí https://github.com/scikit-learn/scikit-learn/issues/1626#issuecomment -12785168. Me gusta detenerme temprano, pero en mi opinión no resuelve esto.

Está bien. Entonces deberíamos buscar una solución que permita la detención anticipada y la adición de estimadores adicionales.

Pensándolo un poco más, creo que el método partial_fit sería la interfaz correcta. En SGD puede llamar a partial_fit ya sea con los mismos datos o con nuevos datos y sigue aprendiendo. La diferencia es que en SGD, si itera manualmente sobre lotes, obtiene el algoritmo original. Para los conjuntos, eso no sería cierto. Necesitará usar todos los datos en cada llamada a partial_fit .

Pensándolo un poco más, creo que el método de ajuste parcial sería el correcto
interfaz.

Me gusta esta sugerencia. ¿Qué piensa otra gente?

Solo para aclarar, ¿qué sucedería exactamente en partial_fit en el caso de conjuntos? ¿Eso agregaría n_estimators más estimadores, donde n_estimators es el valor del parámetro del constructor? (¿o podríamos cambiar ese valor?)

Buena pregunta. También pensé en eso;) en realidad, querrías cambiar eso, ¿verdad? podrías cambiar eso después por set_params pero eso se siente incómodo :-/

Lo siento por unirme a la discusión tan tarde.

Estoy de acuerdo en que necesitamos esa funcionalidad, sin embargo, no estoy seguro de si fit_extends es la mejor solución para el problema que describe @jwkvam . Para realizar una detención anticipada, el usuario debe escribir un código que básicamente llame repetidamente a fit_extends y luego verifique el error de CV.

Prefiero proponer el parámetro de ajuste monitor que discutimos en el pasado: est.fit(X, y, monitor=some_callable) donde se llamará a some_callable después de cada iteración y se pasa el estado completo del estimador. El invocable también podría devolver un valor independientemente de si el entrenamiento debe continuar o no.

El uso de una api de este tipo podría implementar no solo la detención anticipada, sino también informes personalizados (por ejemplo, trazado interactivo del puntaje de entrenamiento frente a la prueba) y captura de imágenes (todas las iteraciones X descargan el objeto estimador y lo copian en alguna ubicación; esto es excelente si está ejecutando en instancias de spot EC2 o algún otro hardware poco confiable ;-)

Sin embargo, incluso con una API monitor , creo que sería necesaria una API para ajustar más estimadores una vez que se haya ajustado el modelo (es decir fit_extends ); a menudo, uno entrena un modelo y hace un poco de introspección para descubrir que probablemente sea mejor haber ejecutado más iteraciones: los estimadores existentes usan el parámetro warm_start para implementar dicha funcionalidad (por ejemplo, vea linear_model.ElasticNet ) - aquí está la cadena de documentación del parámetro: :

warm_start : bool, optional
When set to True, reuse the solution of the previous call to fit as initialization, otherwise, just erase the previous solution.

Personalmente, prefiero fit_extends (o fit_more ) a warm_start - el inicio en caliente es bastante implícito - tienes que:

est = GradientBoostingRegressor(n_estimators=1000)
est.fit(X, y)

# now we want to fit more estimators to ``est`` 
# if you forget warm_start=True you nuke your previous estimators - quite implicit
est.fit(X, y, n_estimators=2000, warm_start=True)

# alternatively - more explicit
est.fit_more(X, y, n_estimators=1000)

alternativamente - más explícito

est.fit_more(X, y, n_estimadores=1000)

Para mí, fit_more corresponde realmente al ajuste parcial que tenemos en
otros estimadores.

@pprett Creo que debería haber una manera fácil de hacer cosas fáciles. una API de monitor es muy flexible, pero en realidad desea detenerse antes de tiempo cada vez que usa un estimador, ¿verdad? Por lo tanto, no debería haber necesidad de escribir una devolución de llamada para hacer eso. Además, debe ser compatible con GridSearchCV.

Para mí, fit_more corresponde realmente al ajuste parcial que tenemos en
otros estimadores.

No lo creo. En partial_fit , "parcial" significa acceso parcial a los datos: usted espera que los datos no quepan en la memoria a la vez, por lo que encaja con un fragmento a la vez y actualiza el modelo de forma incremental mientras escanea los datos. .

En este caso, queremos cambiar la cantidad de subestimadores, pero es posible que deseemos reutilizar exactamente los mismos datos en cada llamada.

Por una razón similar, ElasticNet tiene un parámetro constructor warm_start en lugar de un método partial_fit y SGDClassifier tiene un parámetro warm_start y un método partial_fit : sirven diferentes propósitos

Estoy de acuerdo en que la API del monitor sería muy útil en general (para tratar con instantáneas, detenciones anticipadas y demás) pero no resolvería el problema de aumentar la cantidad de subestimadores de manera interactiva.

También podríamos tener:

est.fit(X, y, n_additional_estimators=1, warm_start=True)

O incluso crecer un 110% (10% más estimadores):

est.fit(X, y, additional_estimators=0.1, warm_start=True)

Hum, no me fijé mucho en la API de inicio en caliente que tenemos actualmente. No hay documentación central para eso, ¿verdad?
Realmente deberíamos pensar en la organización de los documentos. Recibimos bastantes comentarios al respecto en la encuesta :-/

@ogrisel Tendría que echar un vistazo a la implementación de SGD para ver los detalles, pero ¿cuál es la diferencia en lo que realmente sucede entre arranques en caliente y ajuste parcial? Creo que estamos de acuerdo en el punto de los mismos/datos cambiantes.
¿ warm_start hace varias épocas y partial_fit no? Eso tendría sentido para mí, y entonces probablemente deberíamos mantenerlos separados.
Si ya tenemos la API de inicio en caliente, definitivamente deberíamos "simplemente" implementarla para los estimadores de conjunto.

warm_start simplemente evita que se olvide del estado anterior (suponiendo que el estado interno del modelo probablemente hará que converja más rápido a la solución de la nueva llamada con el nuevo hiperparámetro).

2013/1/30 Andreas Mueller [email protected]

@ogrisel https://github.com/ogrisel Tendría que echar un vistazo al SGD
implementación para ver los detalles pero cuál es la diferencia en lo que
sucede realmente entre arranques en caliente y ajuste parcial? creo que estamos de acuerdo en
el punto de los mismos / datos cambiantes.
¿warm_start hace varias épocas y parcial_fit no? Eso podría
tiene sentido para mí, y entonces probablemente deberíamos mantenerlos separados.
Si ya tenemos la API de arranque en caliente, definitivamente deberíamos "simplemente"
implementar eso para los estimadores de conjunto.

Creo que la principal diferencia es la _semántica_: la idea principal detrás
warm_start es converger más rápidamente, pero no importa el valor
¡ warm_start ha obtenido la misma solución!
El ajuste parcial, por otro lado, cambia el modelo subyacente. Considera el
siguiente ejemplo:

# this is the intended use-case for warm_start is faster convergence

clf = SGDClassifier(n_epochs=10)
clf.fit(X, y)

clf2 = clone(clf)
clf3 = SGDClassifier(n_epochs=10)

clf2.fit(X, y, warm_start=True)
clf3.fit(X, y)

# clf2 and clf3 should converge to the same solution - but since clf3

puede reutilizar los pesos ajustados de clf podría converger más rápidamente
# debajo del capó SGDClassifier.fit restablece el modo de estado de "entrenamiento"
el estimador (tasa de aprendizaje adaptativo para sgd)

# now partial fit
clf = SGDClassifier(n_epochs=10)
clf.partial_fit(X, y, classes)
# training has not completed yet "training" state (adaptive learning rate) is stored.

clf.partial_fit(X, y)  # resume with previous learning rate

Descargo de responsabilidad: Este ejemplo puede ser pedante porque las diferencias en los términos
de los pesos aprendidos es mínimo, pero conceptualmente son en mi humilde opinión totalmente
cosas diferentes...


Responda a este correo electrónico directamente o véalo en Gi tHubhttps://github.com/scikit-learn/scikit-learn/issues/1585#issuecomment -12883146.

Pedro Prettenhofer

La API warm_start se introdujo inicialmente para permitir un cálculo más rápido de una serie de modelos lineales idénticos al usar una ruta de regularizadores alpha . Esto es algo similar a aumentar iterativamente la cantidad de subestimadores en un modelo de conjunto potenciado, por lo que podríamos decidir reutilizar warm_start para abordar ese caso de uso también, pero si esta API resulta engorrosa para los modelos potenciados, podría ser mejor. para repensarlo ahora que tenemos un caso de uso adicional.

Estoy de acuerdo con el análisis de @pprett .

No sé qué hacer con el análisis de @pprett .

En el caso de modelos lineales, el estimador convergerá al mismo resultado, incluso cuando el arranque en caliente obtenga datos diferentes a los del ajuste original. Si "comenzamos en caliente" conjuntos / árboles, ese no sería el caso.
Podríamos intentar asegurarnos de que los datos proporcionados cuando el arranque en caliente es el mismo que el original.

Por el momento, "arranque en caliente" se refiere a un procedimiento de optimización, que no existe en los métodos basados ​​en árboles.
Mientras que partial fit retiene todo el estado del estimador y sigue ajustándose.

Por otro lado, las llamadas posteriores al ajuste parcial en lotes conducen al mismo modelo que el entrenamiento en todos los datos.

Nuevamente, esto es diferente del caso del árbol/conjunto. Siento que esto se remonta a mi argumento de que esto es más un algoritmo de ruta que cualquier otra cosa;)

Así que veo dos soluciones posibles: asegúrese de que el inicio en caliente siempre se llame con los mismos datos, luego agregar estimadores sería un inicio en caliente.
Si no, necesitamos una tercera forma de reacondicionar un modelo dado.
¿Dónde están los documentos para eso actualmente, por cierto;)

asegúrese de que el arranque en caliente siempre se llame con los mismos datos.

¿Porque? Deje que el usuario decida cómo y para qué quiere usar warm_start .

¿Dónde están los documentos para eso actualmente, por cierto;)

http://scikit-learn.org/dev/modules/generated/sklearn.linear_model.ElasticNet.html

warm_start : bool, optional
When set to True, reuse the solution of the previous call to fit as initialization, otherwise, just erase the previous solution.

Estoy de acuerdo en que dar motivación sería útil, por ejemplo en este caso:

"Esto es útil para calcular de manera eficiente una ruta de regularización de modelos de ElasticNet como lo hace la función :func: enet_path ".

Pensé que el argumento era sobre semántica. Creo que una semántica se define dando al usuario alguna garantía de lo que sucederá. De esa manera, el usuario no necesita conocer todos los detalles del algoritmo.
Pensé que la garantía de warm_start era "warm_start no cambia el resultado", mientras que la garantía de partial_fit era "iterar sobre lotes no cambia el resultado".

Si no hay garantía, entonces no veo cómo puede haber una semántica común.

Le garantizamos al usuario que si vuelve a proporcionar los mismos datos con warm_start=true, obtendrá los mismos resultados (solo que más rápido). Pero no debemos evitar que el usuario use datos diferentes si hace una conjetura informada de que comenzar en caliente con los nuevos datos lo ayudará a resolver su problema (por ejemplo, resolver los nuevos datos más rápido si supone que los nuevos datos se distribuyen razonablemente). de manera similar a los primeros datos y, por lo tanto, iniciar el optimizador desde la posición anterior debería acelerar las cosas).

Para estimadores lineales está bien. Pero si quiere usar warm_start en conjuntos, de repente tendrá una semántica muy diferente.

De hecho, hacer crecer un conjunto potenciado en el cambio de datos es extraño y probablemente inútil (a menos que sea una forma de inyectar algo de aleatorización para algún estimador de meta-metaconjunto que se empaca en modelos potenciados, ¿quizás?). Sin embargo, no creo que debamos intentar imponer que los datos no cambien entre llamadas. En su lugar, documentemos el escenario de uso esperado para esa opción en la cadena de documentación.

está bien. Entonces, básicamente, la cadena de documentación debería decir "use warm_start con los mismos datos a menos que sepa exactamente lo que está haciendo".
Bien por mi. ¿Alguien se opuso a usar warm_start ?

Aunque todavía tengo que echar un vistazo a cómo se maneja eso en SGD y ENet...

De hecho, el conjunto creciente de datos cambiantes es extraño y probablemente inútil

No, no es inútil: es una estrategia de submuestreo específica. lo practico
La diferencia con un método en línea es que desea que el lote sea grande.

El 30/01/2013 a las 11:42, Peter Prettenhofer escribió:

Creo que la principal diferencia es la _semántica_: la idea principal detrás
warm_start es converger más rápidamente, pero no importa el valor
¡ warm_start ha obtenido la misma solución!
Pensándolo bien, esto está mal.
En SGDClassifier, si encajas dos veces con warm_start definitivamente
obtener diferentes soluciones. Dependiendo de lo que haya hecho antes, puede obtener
mejores o peores soluciones, pero el tiempo de entrenamiento será exactamente el mismo.

Por lo tanto warm_start en SGDClassifier no se puede usar para la selección de modelos.
Por otro lado, partial_fit podría usarse para encontrar la mejor
max_iter .

Cuanto más lo pienso, más confuso se vuelve para mí :-/

Por cierto, ¿hay alguna razón por la que warm_start sea un parámetro de inicio?
y partial_fit es una función?
¿No sería más fácil si partial_fit también fuera un parámetro de inicio?

Por cierto, ¿hay alguna razón por la que warm_start sea un parámetro de inicio?
y partial_fit es una función?

Porque partial_fit es una estrategia específica que puede diferir de la
estrategia utilizada en fit .

¿No sería más fácil si partial_fit también fuera un parámetro de inicio?

Creo que sería confuso. El objetivo de partial_fit es ser un
bloque de construcción utilizable en un marco fuera del núcleo. Usando fit para esto
propósito podría conducir a resultados bastante catastróficos.

No entiendo tu argumento. Lo que hace fit es básicamente "olvidar el modelo, llamar a partial_fit ".

Hm, tal vez lo que quiere decir es que fit podría necesitar hacer menos trabajo que partial_fit porque partial_fit necesita almacenar las "estadísticas suficientes" de los datos anteriores y el ajuste no lo hace. necesitas hacer eso?

No entiendo tu argumento. Lo que hace el ajuste es básicamente "olvidar el modelo,
llame a ajuste_parcial".

Puede hacer más. Por lo general, baraja los datos antes de llamar parcial
encajar. También puede dividirlo en mini lotes de un tamaño seleccionable por el usuario.

Hm, tal vez lo que quieres decir es que el ajuste podría necesitar hacer menos trabajo que el ajuste parcial
porque parcial_fit necesita almacenar las "estadísticas suficientes" de la anterior
data and fit no necesita hacer eso?

Podría ser el caso. También podría ser que el ajuste necesite hacer más
trabajar para convertir un gran conjunto de datos por lotes en un conjunto de mini lotes.

hm ok tal vez esto no es tan importante en este momento.

Me gustaría minimizar la cantidad de mecanismos que tenemos en sklearn, y definitivamente necesitamos uno (¿más?) para una selección eficiente del modelo. En los algoritmos decentes de coordenadas, la opción warm_start se introdujo exactamente para este propósito. No estoy seguro de que sea lo suficientemente general como para hacer eso (¿y si hay más de un parámetro?) y ya no cumple con este requisito en SGDClassifier.

(simplemente eliminé gran parte del comentario anterior porque me estaba repitiendo).

Me gustaría minimizar la cantidad de mecanismos que tenemos en sklearn, y definitivamente necesitamos uno (¿más?) para una selección eficiente del modelo. En los algoritmos decentes de coordenadas, la opción warm_start se introdujo exactamente para este propósito. No estoy seguro de que sea lo suficientemente general como para hacer eso (¿y si hay más de un parámetro?) y ya no cumple con este requisito en SGDClassifier.

No entiendo este último comentario. warm_start es perfectamente válido para SGDClassifier (además de partial_fit ): en este momento, SGDClassifier no tiene verificación de convergencia/detención anticipada. Pero tan pronto como lo haya hecho, warm_starting hará posible calcular la ruta de regularización más rápido, exactamente como para ElasticNet.

SGDClassifier realiza n_iter épocas de actualizaciones y luego se detiene. Dónde termina después n_iter pasos depende en gran medida de dónde comenzó.
Incluso si realiza una "detención anticipada", esto sería una detención anticipada en el conjunto de validación, no una detención anticipada de la optimización. SGDClassfier no tiene el objetivo de optimizar completamente el objetivo hasta el final. Entonces, dónde terminará dependerá de la inicialización.
En particular, para detenerse antes de tiempo (¡en un conjunto de validación!) podría ser mejor hacer menos iteraciones, lo que lleva a un sesgo más bajo.

En particular, no creo que una "ruta de regularización para alfa" tenga sentido en la configuración SGD. El "camino" es una secuencia de óptimos. SGD nunca encontrará el óptimo, por lo que los lugares en los que terminará probablemente dependerán tanto de la escala de la tasa de aprendizaje como de la regularización real.

En particular, no creo que una "ruta de regularización para alfa" tenga sentido en la configuración SGD. El "camino" es una secuencia de óptimos. SGD nunca encontrará el óptimo,

Para modelos lineales, el problema es convexo. Si n_iter es lo suficientemente grande, SGD con un buen programa de aprendizaje convergerá al óptimo (si no se detiene antes de la convergencia). La velocidad de convergencia cuando se acerca al óptimo no es tan buena como el descenso de coordenadas, pero este es un problema diferente.

así que estamos de acuerdo: los modelos serán diferentes a menos que n_iter sea lo suficientemente grande y el cronograma sea el correcto, lo que es poco probable en la práctica.

Además, una garantía del tipo "los resultados serán los mismos si los demás ajustes se ajustan correctamente" no suena realmente como una garantía.

Olivier Grisel [email protected] schrieb:

En particular, no creo que una "ruta de regularización para alfa" haga
sentido en la configuración SGD. El "camino" es una secuencia de óptimos. voluntad SGD
nunca encontrar el óptimo,

Para modelos lineales, el problema es convexo. Si n_iter es lo suficientemente grande, SGD
con un buen horario de aprendizaje convergerá al óptimo (si
no se detenga antes de la convergencia). La velocidad de convergencia al obtener
más cerca del óptimo no es tan bueno como el descenso coordinado, pero
Este es un problema diferente.


Responda a este correo electrónico directamente o véalo en GitHub:
https://github.com/scikit-learn/scikit-learn/issues/1585#issuecomment-12958852

Diese Nachricht wurde von meinem Android-Mobiltelefon mit K-9 Mail gesendet.

Entonces, ¿qué pasa con

clf = RandomForestClassifier(n_estimators=10)
clf.fit(X, y)
print(clf.score(X, y))
clf.set_params(warm_start=true, n_estimators=20)
clf.fit(X, y)

¿Es ese un patrón de uso aceptable?

¿O quieres estos como parámetros para fit ? En SGD, warm_start es un parámetro __init__ según los documentos.

Reanudemos la discusión. en #1044 @GaelVaroquaux dijo que todavía prefiere partial_fit .
Actualmente, creo que warm_start va más en la dirección correcta, pero no tengo una opinión firme. @ogrisel @pprett @glouppe @larsmans ¿cuál es su opinión sobre el patrón de uso que publiqué anteriormente? ¿O le gustaría tener otra interfaz usando warm_start o partial_fit ?

Actualmente, creo que warm_start está más en la dirección correcta, pero no tengo
una opinión fuerte.

Lo que no me gusta de usar 'warm_start' es que actualmente el
contrato con los estimadores de scikit-learn es que puede llamar a 'fit' y obtener
una respuesta válida/útil independientemente de la historia del objeto. puede ir
más rápido o más lento, pero es algo infalible. Si pasas diferente
datos a un estimador de conjunto, y use el 'warm_start' para ajustar más
estimadores, obtendrá tonterías. me preocupa tener que escribir
código 'defensivo' para evitar este tipo de problemas.

¿Cómo funcionaría partial_fit en nuestra configuración? ¿Es esto correcto?:

est = GradientBoostingRegressor(n_estimators=1000)
est.fit(X, y)
...
est.fit_partial(X, y, n_estimators=1000)  # train another 1000

¿entonces tomaría fit_params arbitrarios o solo n_estimators ?

Personalmente, estoy a favor de un fit_more ya que el caso de uso que nuestro actual partial_fit sirve es bastante diferente y fit_more es más explícito.

Tampoco estoy muy contento con el nombre partial_fit en el caso de conjuntos. Desde mi punto de vista, ese nombre sugiere que construirá algunos estimadores a partir del número total solicitado en el constructor, pero no más.

Si optamos por warm_start , ¿cuál sería la especificación? ¿Establece n_estimators en el constructor y llama a fit agrega n_estimators a más estimadores? ¿Al igual que @amueller hizo arriba? Bueno, no estoy en contra de ese patrón, pero eso no me parece muy intuitivo de todos modos.

Desde un punto de vista muy práctico, me gusta fit_more . es explícito No se requiere explicación. Sin embargo, añade otra función a nuestra API...

(Todavía no tengo una opinión firme, estos comentarios simplemente reflejan lo que pienso en este momento)

No estoy completamente en contra de agregar una función, pero no me gustaría que fuera específica para los conjuntos.
Realmente veo una conexión con los algoritmos de ruta, así que creo que compartir una interfaz sería bueno.

Considere la siguiente situación hipotética (quizás no tan realista):
Ajustó un conjunto, pero ahora ve que no se ajusta bien y quiere hacer que sus árboles sean más profundos (digamos que implementamos eso). Este sería otro ejemplo de comportamiento similar a un camino. ¿También harías eso a través fit_more ? ¿O agregar una función fit_deeper ?

Supongo que hay un compromiso entre generalidad y claridad.

@GaelVaroquaux El contrato con partial_fit es en mi humilde opinión que si itera sobre los datos en lotes, obtendrá el mismo resultado. Ese definitivamente no será el caso si se usa aquí. Entonces, ¿por diseño romperíamos el contrato?

Pensándolo de nuevo, tal vez haya lugar para un nuevo método que podríamos usar para implementar el #1626.
No me importaría llamarlo fit_more , pero en el sentido de do some more fitting along the parameter path no en el sentido de fit additional estimators in the ensemble .

Entonces, en mi opinión, deberíamos hacer warm_start (+ tal vez programación defensiva) o agregar otro método que generalmente podemos usar para ajustarnos a lo largo de una ruta de parámetros.

¿Estaría fit_more a la defensiva o no? ;)

-1 a la defensiva. Prefiero documentarlo bien y dejar que el usuario decida qué
es bueno para uno mismo.

El 11 de febrero de 2013 a las 22:14, Andreas Mueller [email protected] escribió:

¿Fit_more entonces estaría a la defensiva o no? ;)


Responda a este correo electrónico directamente o véalo en Gi tHubhttps://github.com/scikit-learn/scikit-learn/issues/1585#issuecomment -13403244.

Yo también estaría en contra defensivo. Me preguntaba si agregar la función realmente resolvió un problema o si solo agregamos otra forma de hacer arranques en caliente. Ambos tienen el mismo problema defensivo/no defensivo, ¿verdad?

Mis disculpas si simplemente estoy repitiendo lo que ya se ha dicho. Pero parece que podría dividir los estimadores en dos clases: los que congelan los parámetros una vez que se ajustan (conjuntos, DT) y los que no (modelos lineales). Con eso quiero decir que con warm_start no reajustarás los primeros n subestimadores de un conjunto o las divisiones existentes en un árbol de decisión. La falta de poder llegar a cualquier parte del espacio de parámetros con warm_start para conjuntos y DT me hace pensar que un método de instancia sería más apropiado.

Si se elige un método de instancia, ¿debe ser más general como señaló @amueller ? Si en algún momento alguien quisiera la capacidad de aumentar la profundidad máxima de los subestimadores, ¿eso también podría manejarse con fit_more() ?

Por lo que vale, también estaría en contra defensivo. Como @GaelVaroquaux señaló anteriormente, proporciona una estrategia de submuestreo, por ejemplo, si sus datos de entrenamiento no caben en la memoria principal.

Después de algunas reflexiones, creo que deberíamos ver el panorama general aquí. En un futuro próximo, me gustaría implementar metaconjuntos genéricos que pudieran combinar cualquier tipo de estimadores. Lo que prefiero ver es un mecanismo de "combinación" que tomaría como entrada una lista de estimadores (ajustados) y produciría un metaestimador combinándolos a todos.

En la práctica, creo que podemos lograrlo sin agregar ninguna función nueva a nuestra API. Por ejemplo, uno podría simplemente pasar dicha lista de estimadores ajustados al constructor del meta-conjunto.

En términos de API, uno podría (aproximadamente) implementar dichos conjuntos de la siguiente manera:

a) Embolsado:

  • constructor: base_estimator (opcional), n_estimators (>=0), una lista L de estimadores ajustados (opcional).
  • ajuste: extienda L con n_estimators nuevas instancias de base_estimators ajustadas sobre (copias de arranque de) las muestras de entrenamiento. Si no se proporciona un estimador base, entonces es equivalente a combinar los estimadores en L .

b) Apilamiento:

  • constructor: base_estimator (opcional), n_estimators (>=0), una lista L de estimadores ajustados (opcional).
  • ajuste: extienda L con n_estimators nuevas instancias de base_estimators ajustadas de muestras de arranque, luego vuelva a ajustar un modelo sobre las predicciones de los estimadores.

c) Bosque:

  • constructor: base_estimator (opcional), n_estimators (>=0), una lista L de estimadores ajustados o un bosque (opcional).
  • ajuste: extienda L con n_estimators nuevas instancias de base_estimators ajustadas sobre las muestras de entrenamiento. Aquí también podríamos comprobar si los estimadores en L son bosques o árboles de decisión. Los bosques se aplanarían para poner todos los árboles al mismo nivel.

Además, en dicho marco, el cálculo de un conjunto podría distribuirse fácilmente entre varias máquinas: construya sus estimadores; encurtirlos; luego recombínalos en un solo metaestimador. ¡Incluso se podría envolver esa interfaz en un clúster de MapReduce, sin profundizar en nuestra implementación en absoluto!

¿Qué piensas? Sin embargo, soy consciente de que esto solo es relevante para algunos tipos de conjuntos. Por ejemplo, GBRT y AdaBoost son (en mi opinión) más adecuados para warm_restart o partial_fit .

Para que quede claro, para extender un bosque, uno haría algo como:

forest = RandomForestClassifier(n_estimators=100)
forest.fit()
forest_extended = RandomForestClassifier(n_estimators=100, L=forest)
forest_extended.fit() # now counts 200 trees

¿Cuál es la motivación de esa interfaz? Estoy totalmente de su parte en apoyar más métodos de conjunto. Siento que es bastante incómodo tener una interfaz diferente para GBRT y Random Forest. Realmente no veo la motivación para eso.

Si la motivación principal es distribuir trabajos paralelos vergonzosamente, entonces creo que deberíamos atacar esto implementando una paralelización más poderosa. Hacerlo de la manera que describiste parece bastante manual y hacky.

Básicamente, siento que su propuesta solo resuelve un caso muy especial y deja la mayoría de los casos sin resolver.

Bueno, está bien... Siento que extender los conjuntos potenciados y los conjuntos promedio son cosas muy diferentes.

¿Cuál es el caso de uso para su interfaz, excepto la paralelización? O mejor: ¿en qué casos de uso necesita una interfaz diferente para conjuntos mejorados y embolsado?

El caso de uso es cuando desea combinar varios estimadores. Es natural para conjuntos promedio, pero no tiene sentido en conjuntos potenciados. En esa perspectiva, veo "extender un estimador" como "combinarlo" con más estimadores básicos.

Entonces, el escenario es que ha entrenado a algunos estimadores de embolsado y desea combinarlos, ¿verdad?
¿En qué configuración desea hacer eso excepto para la paralelización? No me queda tan claro, pero tal vez estoy pasando por alto algo obvio.

En el caso de Stacking, los estimadores pueden ser completamente diferentes (por ejemplo, si desea fusionar bosques con svms).

(Indirectamente, esto también podría usarse para implementar estrategias de submuestreo o para monitorear el proceso de ajuste).

No estoy seguro de obtener el ejemplo de apilamiento. Habría imaginado que si tuviéramos una interfaz de apilamiento, podrías especificar un estimador como el estimador base y otro como el superior.

Tal como yo lo veo, el objetivo del apilamiento es combinar las predicciones de estimadores de diferente naturaleza. Cuanto más diversos sean, a menudo mejor.

Ok, entonces los estimadores base serían diferentes. Pero entonces también podríamos construir esto en la interfaz para apilar, ¿verdad?

Resuelto con #2570

@jwkvam Recientemente acordamos en #2570 implementar esta característica usando el parámetro warm_start . Ahora está implementado en GBRT. Intentaré actualizar los bosques con el mismo mecanismo antes del lanzamiento.

@glouppe Tienes razón, olvidé que había escrito esto para cualquier conjunto. Pero realmente solo lo quería para GBRT :) así que en mi prisa, decidí que este problema estaba resuelto. Si lo desea, puede volver a abrirlo y cerrarlo cuando haya terminado, no me importa.

¿Fue útil esta página
0 / 5 - 0 calificaciones