pandas scikit-learn中处理nan/null的分类器

niknxzdl  于 2023-09-29  发布在  其他
关注(0)|答案(5)|浏览(128)

我想知道scikit-learn中是否有处理nan/null值的分类器。我以为随机森林回归器可以处理这个问题,但是当我调用predict时,我得到了一个错误。

X_train = np.array([[1, np.nan, 3],[np.nan, 5, 6]])
y_train = np.array([1, 2])
clf = RandomForestRegressor(X_train, y_train)
X_test = np.array([7, 8, np.nan])
y_pred = clf.predict(X_test) # Fails!

我不能用任何有缺失值的scikit-learn算法调用predict吗?

    • 这在训练过程中不是问题,但当你预测变量为空时,你如何分支?也许你可以把两种方法分开然后平均结果看起来k-NN应该工作得很好,只要距离函数忽略空值。
      **Edit 2(我更老更聪明)**一些gbm库(如xgboost)使用三元树而不是二叉树正是为了这个目的:2个孩子用于是/否决定,1个孩子用于缺失决定。sklearn使用二叉树
b5lpy0ml

b5lpy0ml1#

简短回答

有时缺失值根本不适用。指责他们毫无意义。在这些情况下,您应该使用可以处理缺失值的模型。Scitkit-learn的模型无法处理缺失值。XGBoost可以。

关于scikit-learn和XGBoost的更多信息

正如this article中提到的,scikit-learn的决策树和KNN算法不足以(yet)鲁棒处理缺失值。如果归罪没有意义,就不要做。

考虑插补没有意义的情况。

请记住,这是一个虚构例子
考虑一个数据集,其中有行汽车(“Danho Diesel”、“Estal Electric”、“Hesproc Hybrid”)和列及其属性(重量、最高速度、加速度、功率输出、二氧化硫排放、范围)。
电动汽车不产生废气-因此Estal Electric* 的二氧化硫排放量应为NaN-值(缺失)。你可以争辩说它应该设置为0 -但电动汽车不能产生二氧化硫。估算值会破坏你的预测。
正如this article中提到的,scikit-learn的决策树和KNN算法
不足以(yet)鲁棒**处理缺失值。如果归罪没有意义,就不要做。

v1l68za4

v1l68za42#

我做了一个例子,它包含了训练集和测试集中的缺失值
我只是选择了一个策略,使用SimpleImputer类用平均值替换缺失的数据。还有其他的策略。

from __future__ import print_function

import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.impute import SimpleImputer

X_train = [[0, 0, np.nan], [np.nan, 1, 1]]
Y_train = [0, 1]
X_test_1 = [0, 0, np.nan]
X_test_2 = [0, np.nan, np.nan]
X_test_3 = [np.nan, 1, 1]

# Create our imputer to replace missing values with the mean e.g.
imp = SimpleImputer(missing_values=np.nan, strategy='mean')
imp = imp.fit(X_train)

# Impute our data, then train
X_train_imp = imp.transform(X_train)
clf = RandomForestClassifier(n_estimators=10)
clf = clf.fit(X_train_imp, Y_train)

for X_test in [X_test_1, X_test_2, X_test_3]:
    # Impute each test item, then predict
    X_test_imp = imp.transform(X_test)
    print(X_test, '->', clf.predict(X_test_imp))

# Results
[0, 0, nan] -> [0]
[0, nan, nan] -> [0]
[nan, 1, 1] -> [1]
nkoocmlb

nkoocmlb3#

如果您使用DataFrame,则可以使用fillna。这里我用该列的平均值替换了缺失的数据。

df.fillna(df.mean(), inplace=True)
6fe3ivhb

6fe3ivhb4#

对于位于GeoTIFF图像边缘的NoData(显然不能使用相邻像素值的平均值进行插值),我在几行代码中将其屏蔽。请注意,这是在一个条带上执行的(Sentinel 1图像的VH条带,其首先被转换成阵列)。在我对我的初始图像执行随机森林分类后,我做了以下事情:

image[image>0]=1.0
image[image==0]=-1.0
RF_prediction=np.multiply(RF_prediction,image)
RF_prediction[RF_prediction<0]=-9999.0 #assign a NoData value

保存时,不要忘记指定NoData值:

class_ds = gdal.GetDriverByName('GTiff').Create('RF_classified.tif',img_ds.RasterXSize,\
                                              img_ds.RasterYSize,1,gdal.GDT_Float32)

RF_ds.SetGeoTransform(img_ds.GetGeoTransform())    
srs = osr.SpatialReference()
srs.ImportFromEPSG(32733)                
RF_ds.SetProjection(srs.ExportToWkt()) # export coords to file
RF_ds.GetRasterBand(1).SetNoDataValue(-9999.0) #set NoData value
RF_ds.GetRasterBand(1).WriteArray(RF_prediction)
RF_ds.FlushCache()                     # write to disk
RF_ds = None
slsn1g29

slsn1g295#

HistoricentBoostingClassifier

和sklearn.ensemble.HistGradientBoostingRegressor可以处理NaN值
它们还可以处理分类特征,即不需要对它们进行独热编码。
https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.HistGradientBoostingClassifier.html

相关问题