在Tensorflow数据集中过滤NaN值

3

有没有一种简单的方法从tensorflow.data.Dataset实例中过滤掉所有包含nan值的条目?类似于Pandas中的dropna方法?


简短示例:

import numpy as np
import tensorflow as tf

X = tf.data.Dataset.from_tensor_slices([[1,2,3], [0,0,0], [np.nan,np.nan,np.nan], [3,4,5], [np.nan,3,4]])
y = tf.data.Dataset.from_tensor_slices([np.nan, 0, 1, 2, 3])
ds = tf.data.Dataset.zip((X,y))
ds = foo(ds)  # foo(x) = ?
for x in iter(ds): print(str(x))

我可以为foo(x)使用什么来获得以下输出:
(<tf.Tensor: shape=(3,), dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>, <tf.Tensor: shape=(), dtype=float32, numpy=0.0>)
(<tf.Tensor: shape=(3,), dtype=float32, numpy=array([3., 4., 5.], dtype=float32)>, <tf.Tensor: shape=(), dtype=float32, numpy=2.0>)

如果您想亲自尝试,请在这里使用Google Colab笔记本

3个回答

3

我的方法与现有答案略有不同。我使用的是tf.reduce_any而不是使用sum:

filter_nan = lambda x, y: not tf.reduce_any(tf.math.is_nan(x)) and not tf.math.is_nan(y)

ds = tf.data.Dataset.zip((X,y)).filter(filter_nan)

list(ds.as_numpy_iterator())

[(array([0., 0., 0.], dtype=float32), 0.0),
 (array([3., 4., 5.], dtype=float32), 2.0)]

2
如何考虑:
def any_nan(t):
    return tf.reduce_sum(
        tf.cast(
            tf.math.is_nan(t),
            tf.int32,
        )
    ) > tf.constant(0)


>>> ds_filtered = ds.filter(lambda x, y: not any_nan(x) and not any_nan(y))
>>> for x in iter(ds_filtered): print(str(x))
(<tf.Tensor: shape=(3,), dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>, <tf.Tensor: shape=(), dtype=float32, numpy=0.0>)
(<tf.Tensor: shape=(3,), dtype=float32, numpy=array([3., 4., 5.], dtype=float32)>, <tf.Tensor: shape=(), dtype=float32, numpy=2.0>)

0

在列数和机器学习模型的性能之间存在一些权衡,最好保留尽可能多的特征列。我建议首先删除目标变量中存在缺失值的所有行,然后删除其他变量中存在剩余缺失值的列。这样,如果特征变量中的缺失条目与缺失目标值一致,您可以保留比仅删除所有缺失条目更多的列。此建议是一般性的,您可以选择保留一些几乎没有缺失条目的特征列,而不是删除带有这些条目的行。

在这里,我假设您的张量中包含特征和目标变量作为列,y_indx是目标的列索引。您也可以使用适当的布尔遮罩。

以下函数从张量X中删除目标列中带有nan值的行。它返回了一个用于被删除行的布尔遮罩,但是如果您不想保留它,可以跳过最后一行。

def drop_na_rows(X, y_indx):
    not_nan = tf.math.logical_not(tf.math.is_nan(X[:, y_indx]))
    return X[not_nan, :], no_nan

下面的函数会删除带有缺失值的列。请注意,对于cols_to_drop参数,您可以使用布尔掩码或适合切片张量的索引,但如果您没有提供任何内容,该函数将返回列的布尔掩码。或者您也可以跳过它。
def drop_na_cols(X, cols_to_drop=None):
    if cols_to_drop is None:
        cols_to_drop = tf.where(tf.reduce_sum(X, axis=1))
    return X[:, cols_to_drop], cols_to_drop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接