繁体   English   中英

sklearn错误ValueError:输入包含NaN,无穷大或对于dtype('float64')来说太大的值

[英]sklearn error ValueError: Input contains NaN, infinity or a value too large for dtype('float64')

我正在使用 sklearn 并且在亲和力传播方面遇到问题。 我已经建立了一个输入矩阵,但我不断收到以下错误。

ValueError: Input contains NaN, infinity or a value too large for dtype('float64').

我跑了

np.isnan(mat.any()) #and gets False
np.isfinite(mat.all()) #and gets True

我尝试使用

mat[np.isfinite(mat) == True] = 0

删除无限值,但这也不起作用。 我可以做些什么来摆脱矩阵中的无限值,以便我可以使用亲和传播算法?

我正在使用 anaconda 和 python 2.7.9。

这可能发生在 scikit 内部,这取决于你在做什么。 我建议阅读有关您正在使用的功能的文档。 您可能正在使用一个取决于例如您的矩阵是正定的并且不满足该标准的矩阵。

编辑:我怎么能错过:

np.isnan(mat.any()) #and gets False
np.isfinite(mat.all()) #and gets True

显然是错误的。 正确的是:

np.any(np.isnan(mat))

np.all(np.isfinite(mat))

您想检查任何元素是否为 NaN,而不是any函数的返回值是否为数字...

sklearnpandas一起使用时,我收到了相同的错误消息。 我的解决方案是在运行任何 sklearn 代码之前重置我的数据帧df的索引:

df = df.reset_index()

当我删除df中的一些条目时,我多次遇到此问题,例如

df = df[df.label=='desired_one']

这是我的函数(基于this )来清理nanInf和缺失单元格的数据集(对于倾斜的数据集):

import pandas as pd
import numpy as np

def clean_dataset(df):
    assert isinstance(df, pd.DataFrame), "df needs to be a pd.DataFrame"
    df.dropna(inplace=True)
    indices_to_keep = ~df.isin([np.nan, np.inf, -np.inf]).any(1)
    return df[indices_to_keep].astype(np.float64)

在大多数情况下,摆脱无限和空值可以解决这个问题。

摆脱无限的价值。

df.replace([np.inf, -np.inf], np.nan, inplace=True)

以您喜欢的方式摆脱空值、特定值(例如 999、均值)或创建自己的函数来估算缺失值

df.fillna(999, inplace=True)

这是它失败的检查:

哪个说

def _assert_all_finite(X):
    """Like assert_all_finite, but only for ndarray."""
    X = np.asanyarray(X)
    # First try an O(n) time, O(1) space solution for the common case that
    # everything is finite; fall back to O(n) space np.isfinite to prevent
    # false positives from overflow in sum method.
    if (X.dtype.char in np.typecodes['AllFloat'] and not np.isfinite(X.sum())
            and not np.isfinite(X).all()):
        raise ValueError("Input contains NaN, infinity"
                         " or a value too large for %r." % X.dtype)

因此,请确保您的输入中有非 NaN 值。 所有这些值实际上都是浮点值。 任何值都不应该是 Inf 。

我的输入数组的维度是倾斜的,因为我的输入 csv 有空格。

使用此版本的 python 3:

/opt/anaconda3/bin/python --version
Python 3.6.0 :: Anaconda 4.3.0 (64-bit)

查看错误的详细信息,我找到了导致失败的代码行:

/opt/anaconda3/lib/python3.6/site-packages/sklearn/utils/validation.py in _assert_all_finite(X)
     56             and not np.isfinite(X).all()):
     57         raise ValueError("Input contains NaN, infinity"
---> 58                          " or a value too large for %r." % X.dtype)
     59 
     60 

ValueError: Input contains NaN, infinity or a value too large for dtype('float64').

由此,我能够提取正确的方法来使用错误消息给出的相同测试来测试我的数据发生了什么: np.isfinite(X)

然后通过一个快速而肮脏的循环,我发现我的数据确实包含nans

print(p[:,0].shape)
index = 0
for i in p[:,0]:
    if not np.isfinite(i):
        print(index, i)
    index +=1

(367340,)
4454 nan
6940 nan
10868 nan
12753 nan
14855 nan
15678 nan
24954 nan
30251 nan
31108 nan
51455 nan
59055 nan
...

现在我要做的就是删除这些索引处的值。

这里没有一个答案对我有用。 这是行得通的。

Test_y = np.nan_to_num(Test_y)

它用高有限值替换无穷大值,用数字替换 nan 值

我有同样的错误,在我的例子中 X 和 y 是数据帧,所以我必须先将它们转换为矩阵:

X = X.values.astype(np.float)
y = y.values.astype(np.float)

编辑:最初建议的 X.as_matrix() 已弃用

尝试选择行子集后出现错误:

df = df.reindex(index=my_index)

原来my_index包含df.index中不包含的值,因此 reindex 函数插入了一些新行并用nan填充它们。

删除所有无限值:

(并用该列的 min 或 max 替换)

import numpy as np

# generate example matrix
matrix = np.random.rand(5,5)
matrix[0,:] = np.inf
matrix[2,:] = -np.inf
>>> matrix
array([[       inf,        inf,        inf,        inf,        inf],
       [0.87362809, 0.28321499, 0.7427659 , 0.37570528, 0.35783064],
       [      -inf,       -inf,       -inf,       -inf,       -inf],
       [0.72877665, 0.06580068, 0.95222639, 0.00833664, 0.68779902],
       [0.90272002, 0.37357483, 0.92952479, 0.072105  , 0.20837798]])

# find min and max values for each column, ignoring nan, -inf, and inf
mins = [np.nanmin(matrix[:, i][matrix[:, i] != -np.inf]) for i in range(matrix.shape[1])]
maxs = [np.nanmax(matrix[:, i][matrix[:, i] != np.inf]) for i in range(matrix.shape[1])]

# go through matrix one column at a time and replace  + and -infinity 
# with the max or min for that column
for i in range(matrix.shape[1]):
    matrix[:, i][matrix[:, i] == -np.inf] = mins[i]
    matrix[:, i][matrix[:, i] == np.inf] = maxs[i]

>>> matrix
array([[0.90272002, 0.37357483, 0.95222639, 0.37570528, 0.68779902],
       [0.87362809, 0.28321499, 0.7427659 , 0.37570528, 0.35783064],
       [0.72877665, 0.06580068, 0.7427659 , 0.00833664, 0.20837798],
       [0.72877665, 0.06580068, 0.95222639, 0.00833664, 0.68779902],
       [0.90272002, 0.37357483, 0.92952479, 0.072105  , 0.20837798]])

DecisionTreeClassifier 输入检查中似乎出现问题,请尝试

X_train = X_train.replace((np.inf, -np.inf, np.nan), 0).reset_index(drop=True)

我得到了同样的错误。 在进行任何替换、替换等操作之前,它与df.fillna(-99999, inplace=True)一起使用

我想提出一个适合我的 numpy 解决方案。 线

from numpy import inf
inputArray[inputArray == inf] = np.finfo(np.float64).max

用最大 float64 数替换 numpy 数组的所有无限值。

我发现在一个新列上调用 pct_change 之后,nan 存在于其中一行中。 我使用以下代码删除了 nan 行

df = df.replace([np.inf, -np.inf], np.nan)
df = df.dropna()
df = df.reset_index()

就我而言,问题是许多 scikit 函数返回 numpy 数组,这些数组没有 pandas 索引。 因此,当我使用这些 numpy 数组构建新的 DataFrame,然后尝试将它们与原始数据混合时,出现了索引不匹配。

dataset = dataset.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

这对我有用

如果您正在运行估算器,则可能是您的学习率太高。 我不小心将错误的数组传递给了网格搜索,最终以 500 的学习率进行了训练,我可以看到这会导致训练过程出现问题。

基本上,不一定只有您的输入必须全部有效,中间数据也必须有效。

我有同样的问题,在我的情况下,答案很简单,我的 CSV 中有一个没有值的单元格(“x,y,z,”)。 为我设置一个默认值。

使用isneginf可能会有所帮助。 http://docs.scipy.org/doc/numpy/reference/generated/numpy.isneginf.html#numpy.isneginf

x[numpy.isneginf(x)] = 0 #0 is the value you want to replace with

注意:此解决方案仅适用于您有意识地希望在数据集中保留NaN条目的情况。

当我使用一些scikit-learn功能(在我的例子中: GridSearchCV )时,这个错误发生在我身上。 在后台,我使用了一个xgboost XGBClassifier ,它可以优雅地处理NaN数据。 但是, GridSearchCV正在使用sklearn.utils.validation模块,该模块通过调用_assert_all_finite函数来强制输入数据中缺少缺失数据。 这最终导致了一个错误:

ValueError: Input contains NaN, infinity or a value too large for dtype('float64')

旁注: _assert_all_finite接受一个allow_nan参数,如果设置为True ,则不会引起问题。 但是,scikit-learn API 不允许我们控制这个参数。

解决方案

我的解决方案是使用patch模块来使_assert_all_finite函数静音,这样它就不会raise ValueError 这是一个片段

import sklearn
with mock.patch("sklearn.utils.validation._assert_all_finite"):
    # your code that raises ValueError

这将用一个虚拟模拟函数替换_assert_all_finite ,因此它不会被执行。

请注意,修补不是推荐做法,可能会导致不可预知的行为!


编辑:拉取请求应该可以解决问题(尽管截至 2022 年 1 月该修复程序尚未发布)

噗!! 在我的情况下,问题是关于 NaN 值......

您可以使用此功能列出具有 NaN 的列

your_data.isnull().sum()

然后您可以在数据集文件中填写这些 NAN 值。

这是有关如何“用零替换 NaN 和用大有限数替换无穷大”的代码。

your_data[:] = np.nan_to_num(your_data)

numpy.nan_to_num

经过长时间处理这个问题,我意识到这是因为在训练集和测试集的拆分中,所有数据行的数据列都是相同的。 那么一些算法中的一些计算可能会导致无穷大的结果。 如果您使用的数据的方式接近的行更可能相似,那么对数据进行洗牌会有所帮助。 这是 scikit 的一个错误。 我使用的是 0.23.2 版本。

如果您碰巧使用“kc_house_data.csv”数据集(一些评论者和许多数据科学新手似乎使用它,因为它出现在许多流行的课程材料中),数据是错误的,并且是错误的真正来源。

要修复它,截至 2022 年:

  • 删除 csv 文件中的最后(空)行
  • 有两行包含一个空数据值 "x,x,,x,x" - 修复它,不要删除逗号,而是添加一个随机整数值,如 2000,所以它看起来像这样 "x,x ,2000,x,x"

不要忘记在您的项目中保存并重新加载。

所有其他答案都是有用且正确的,但在这种情况下不是:

如果您使用kc_house_data.csv ,您需要修复文件中的数据,没有其他帮助,空的数据字段将随机移动其他数据并生成难以追踪到源的奇怪错误!

尝试

mat.sum()

如果您的数据总和为无穷大(大于最大浮点值 3.402823e+38),您将收到该错误。

从 scikit 源代码中查看 validation.py 中的 _assert_all_finite 函数:

if is_float and np.isfinite(X.sum()):
    pass
elif is_float:
    msg_err = "Input contains {} or a value too large for {!r}."
    if (allow_nan and np.isinf(X).any() or
            not allow_nan and not np.isfinite(X).all()):
        type_err = 'infinity' if allow_nan else 'NaN, infinity'
        # print(X.sum())
        raise ValueError(msg_err.format(type_err, X.dtype))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM