sklearn错误ValueError:输入包含NaN,无穷大或对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

删除无限值,但这也没有工作。 我要怎么做才能去掉矩阵中的无穷大值,这样我就可以使用亲和传播算法了?< / p >

我使用anaconda和python 2.7.9。

671039 次浏览

这可能发生在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函数的返回值是否为数字…

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

这是它失败的检查:

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。

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

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

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

在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
...

现在我要做的就是去掉这些下标处的值。

这是我的函数(基于),用于清理数据集的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)

当使用sklearn熊猫时,我得到了相同的错误消息。我的解决方案是在运行任何sklearn代码之前重置我的dataframe df的索引:

df = df.reset_index()

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

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

我有错误后,试图选择一个子集的行:

df = df.reindex(index=my_index)

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

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

在我的例子中,问题是许多scikit函数返回numpy数组,这些数组没有pandas索引。因此,当我使用那些numpy数组来构建新的dataframe时,有一个索引不匹配,然后我尝试将它们与原始数据混合。

试一试

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))

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

去掉无穷值。

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

以您喜欢的方式摆脱空值,特定的值,如999,平均值,或创建自己的函数来输入缺失的值

df.fillna(999, inplace=True)

移除所有无限值:

(并替换为该列的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]])

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

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

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

这里没有一个答案对我有用。这是有效的。

Test_y = np.nan_to_num(Test_y)

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

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

这对我很有效

如果您正在运行一个估计器,可能是您的学习率太高了。我意外地将错误的数组传递给了网格搜索,最终训练的学习率为500,我可以看到这导致了训练过程中的问题。

基本上,不仅你的输入必须全部有效,中间数据也必须有效。

问题似乎发生在DecisionTreeClassifier输入检查,尝试

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

我有同样的问题,在我的情况下,答案很简单,我有一个单元格在我的CSV没有值("x,y,z,,")。把一个默认值固定为我。

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

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,因此它不会被执行。

请注意,补丁不是一个推荐的做法,可能会导致不可预测的行为!


< p >编辑: Pull Request应该可以解决这个问题(尽管截至2022年1月修复还没有发布)

我发现在一个新列上调用pct_change后,nan存在于一行中。我用下面的代码删除nan行

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

泡芙! !在我的情况下,问题是关于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 您需要修复文件中的数据,没有其他帮助,空数据字段将随机转移其他数据,并产生难以追踪到源的奇怪错误!

在我的例子中,算法要求数据在(0,1)之间不包含。我非常残酷的解决方案是在所有期望值中添加一个小随机数:

y_train = pd.DataFrame(y_train).applymap(lambda x: x + np.random.rand()/100000.0)["col_name"]
y_train[y_train >= 1] = 0.999999

而y_train在[0,1]的范围内。

这当然不适合所有的情况,因为你会弄乱你的输入数据,但如果你有稀疏的数据,只需要一个快速的预测,这是一个解决方案