Transformador personalizado para sklearn Pipeline que altera tanto X como y

Quiero crear mi propio transformador para usar con la tubería de Sklearn. Por lo tanto, estoy creando una clase que implementa métodos de ajuste y transformación. El propósito del transformador será eliminar las filas de la matriz que tengan más de un número específico de NaN. Entonces, el problema al que me enfrento es ¿cómo puedo cambiar las matrices X e y que se pasan al transformador? Creo que esto debe hacerse en el método de ajuste, ya que tiene acceso tanto a X como a y. Ya que Python pasa los argumentos por asignación una vez que reasigne X a una nueva matriz con menos filas, la referencia a la X original se pierde (y, por supuesto, lo mismo es cierto para y). ¿Es posible mantener esta referencia?

Estoy usando un DataFrame de pandas para eliminar fácilmente las filas que tienen demasiados NaN, puede que esta no sea la forma correcta de hacerlo en mi caso de uso. El código actual se ve así:

class Dropna(): # thresh is max number of NaNs allowed in a row def __init__(self, thresh=0): self.thresh = thresh def fit(self, X, y): total = X.shape[1] # +1 to account for 'y' being added to the dframe new_thresh = total + 1 - self.thresh df = pd.DataFrame(X) df['y'] = y df.dropna(thresh=new_thresh, inplace=True) X = df.drop('y', axis=1).values y = df['y'].values return self def transform(self, X): return X 

La modificación del eje de muestra, por ejemplo, la eliminación de muestras, ¿no cumple (todavía) con la API del transformador de scikit-learn? Por lo tanto, si necesita hacer esto, debe hacerlo fuera de las llamadas a scikit learn, como preprocesamiento.

Tal como está ahora, la API del transformador se utiliza para transformar las características de una muestra dada en algo nuevo. Esto puede contener implícitamente información de otras muestras, pero las muestras nunca se eliminan.

Otra opción es intentar imputar los valores faltantes. Pero una vez más, si necesita eliminar muestras, trátelas como preprocesamiento antes de usar scikit learn.

Puede resolver esto fácilmente usando el método sklearn.preprocessing.FunctionTransformer ( http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.FunctionTransformer.html )

Solo necesitas poner tus alternaciones a X en una función.

 def drop_nans(X, y=None): total = X.shape[1] new_thresh = total - thresh df = pd.DataFrame(X) df.dropna(thresh=new_thresh, inplace=True) return df.values 

entonces obtienes tu transformador llamando

 transformer = FunctionTransformer(drop_nans, validate=False) 

que puede utilizar en la tubería. El umbral se puede establecer fuera de la función drop_nans.

Use ” copias en profundidad ” más adelante, en la tubería y X , y permanezca protegido

.fit() puede primero asignar en cada llamada copia en profundidad a nuevas variables de clase

 self.X_without_NaNs = X.copy() self.y_without_NaNs = y.copy() 

y luego reducir / transformar estos para no tener más NaN -s que los ordenados por self.treshold