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

classifiers in scikit-learn that handle nan/null

我想知道是否有分类器可以处理 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 似乎就可以正常工作。

编辑 2(我更老更聪明) 一些 gbm 库(例如 xgboost)正是出于此目的使用三叉树而不是二叉树:2 children 用于 yes/no 决策,1 child 用于缺失决策。 sklearn 是 using a binary tree

我做了一个示例,其中包含训练和测试集中的缺失值

我刚刚使用 SimpleImputer class 选择了一种用均值替换缺失数据的策略。还有其他策略。

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]

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

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

简答

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


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

this article, scikit-learn's decision trees and KNN algorithms are not (yet 中所述)足够强大 可以处理缺失值。如果插补没有意义,请不要这样做。

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

keep in mind this is a made-up example

考虑一个包含行汽车(“Danho Diesel”、“Estal Electric”、“Hesproc Hybrid”)和列及其属性的数据集(重量、最高速度、加速度、功率输出、二氧化硫排放、范围)。

电动汽车不产生废气 - 因此 Estal Electric 的 二氧化硫排放量应该是 NaN 值(缺失) 。您可能会争辩说它应该设置为 0 - 但电动汽车不会产生二氧化硫。估算值会破坏您的预测。

this article, scikit-learn's decision trees and KNN algorithms are not (yet 中所述)足够强大 可以处理缺失值。如果插补没有意义,请不要这样做。

对于位于 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