f1_score metric en lightgbm

Quiero entrenar un modelo lgb con métrica personalizada: f1_score con promedio weighted .

Revisé los ejemplos avanzados de lightgbm aquí y encontré la implementación de la función de error binario personalizada. Implementé una función similar para devolver f1_score como se muestra a continuación.

 def f1_metric(preds, train_data): labels = train_data.get_label() return 'f1', f1_score(labels, preds, average='weighted'), True 

Intenté entrenar el modelo pasando el parámetro f1_metric como f1_metric como se muestra a continuación.

 evals_results = {} bst = lgb.train(params, dtrain, valid_sets= [dvalid], valid_names=['valid'], evals_result=evals_results, num_boost_round=num_boost_round, early_stopping_rounds=early_stopping_rounds, verbose_eval=25, feval=f1_metric) 

Luego estoy obteniendo ValueError: Found input variables with inconsistent numbers of samples:

El conjunto de entrenamiento se pasa a la función en lugar del conjunto de validación.

    ¿Cómo puedo configurar para que se pase el conjunto de validación y se devuelva f1_score?

    Los documentos son un poco confusos. Al describir la firma de la función que se pasa a feval, llaman a sus parámetros preds y train_data , lo cual es un poco engañoso.

    Pero lo siguiente parece funcionar:

     from sklearn.metrics import f1_score def lgb_f1_score(y_hat, data): y_true = data.get_label() y_hat = np.round(y_hat) # scikits f1 doesn't like probabilities return 'f1', f1_score(y_true, y_hat), True evals_result = {} clf = lgb.train(param, train_data, valid_sets=[val_data, train_data], valid_names=['val', 'train'], feval=lgb_f1_score, evals_result=evals_result) lgb.plot_metric(evals_result, metric='f1') 

    Para usar más de una métrica personalizada, defina una función general de métricas personalizadas como la anterior, en la que calcula todas las métricas y devuelve una lista de tuplas.

    Edición: el código fijo, por supuesto, con F1 más grande, mejor se debe establecer en Verdadero.