fastai 表格模型 - 如何获得新数据的预测?

问题描述

我使用的是kaggle房价数据集,分为:训练和测试

  • 我使用训练集构建了一个带有 fastai tabular 的模型
  • 如何预测测试数据集的值?

我知道这听起来很简单,大多数其他库都会像 model.predict(test) 那样做,但这里的情况并非如此。 我搜索了 fastai 论坛和 SO 和文档。关于这个问题有很多主题,其中大多数要么没有答案,要么是过时的解决方法(因为 fastai2 最近发布,现在仅称为 fastai)。

一个。 model.predict 仅适用于单行并且循环测试不是最佳的。很慢。

B. model.get_preds 给出你训练数据的结果

请建议您可以使用训练有素的学习器来预测表格数据的新 df。

解决方法

model.get_preds 用于对看不见的数据进行批量预测。您只需对这些新数据应用与训练数据相同的转换即可。

dl = model.dls.test_dl(test_data,bs=64) # apply transforms
preds,_ = model.get_preds(dl=dl) # get prediction

fastai 的论坛非常活跃,您可能会收到库开发人员的回复,所以以后也可以试试。

,

我发现了一个问题。对于未来的读者 - 为什么你不能为新的 df 获得 get_preds 的工作?

(在kaggle的房价上涨上测试)

问题的根源在于绝对的 nans。如果您使用一组猫特征训练模型,请说颜色 = 红色、绿色、蓝色;并且您的新 df 具有颜色:红色、绿色、蓝色、黑色 - 它会抛出错误,因为它不知道如何处理新类(黑色)。更不用说你需要在任何地方都有相同的列,这可能很棘手,因为如果你像我一样使用 fillmissing proc,这很好,它会为 cat 值(是否丢失)创建新的列。因此,您需要对猫的这些 nan 进行三重检查。 我真的很想让 fastai 从头到尾让它工作:

训练/测试的列是相同的,只有训练有 1 个额外的目标。在这一点上,一些猫群中有不同的类。我只是决定将它们结合起来(只是为了让它工作),但它不会引入泄漏吗?

combined = pd.concat([train,test]) # test will have nans at target,but we don't care
cont_cols,cat_cols = cont_cat_split(combined,max_card=50)
combined = combined[cat_cols]

我们在做一些调整。

train[cont_cols] = train[cont_cols].astype('float') # if target is not float,there will be an error later
test[cont_cols[:-1]] = test[cont_cols[:-1]].astype('float'); # slice target off (I had mine at the end of cont_cols)

进入 Tabular Panda

procs = [Categorify,FillMissing]

to = TabularPandas(combined,procs = procs,cat_names = cat_cols)

train_to_cat = to.items.iloc[:train.shape[0],:] # transformed cat for train
test_to_cat = to.items.iloc[train.shape[0]:,:] # transformed cat for test. Need to separate them

to.items 将为我们提供转换后的 cat 列。之后,我们需要将所有东西重新组装在一起

train_imp = pd.concat([train_to_cat,train[cont_cols]],1) # assemble new cat and old cont together
test_imp = pd.concat([test_to_cat,test[cont_cols[:-1]]],1) # exclude SalePrice

train_imp['SalePrice'] = np.log(train_imp['SalePrice']) # metric for kaggle

之后,我们按照 fastai 教程进行操作。

dep_var = 'SalePrice'
procs = [Categorify,FillMissing,Normalize]
splits = RandomSplitter(valid_pct=0.2)(range_of(train_imp))

to = TabularPandas(train_imp,cat_names = cat_cols,cont_names = cont_cols[:-1],# we need to exclude target
                   y_names = 'SalePrice',splits=splits)

dls = to.dataloaders(bs=64)

learn = tabular_learner(dls,n_out=1,loss_func=F.mse_loss)
learn.lr_find()

learn.fit_one_cycle(20,slice(1e-2,1e-1),cbs=[ShowGraphCallback()])

此时,我们有一个学习器,但仍然无法预测。做完之后我想:

dl = learn.dls.test_dl(test_imp,bs=64)
preds,_ = learn.get_preds(dl=dl) # get prediction

它会起作用(cont 值的预处理和预测),但不会。它不会填充。 所以只需在测试中找到并填充 nans:

missing = test_imp.isnull().sum().sort_values(ascending=False).head(12).index.tolist()
for c in missing:
    test_imp[c] = test_imp[c].fillna(test_imp[c].median())

之后我们终于可以预测了:

dl = learn.dls.test_dl(test_imp,_ = learn.get_preds(dl=dl) # get prediction

final_preds = np.exp(preds.flatten()).tolist()

sub = pd.read_csv('../input/house-prices-advanced-regression-techniques/sample_submission.csv')
sub.SalePrice = final_preds

filename = 'submission.csv'
sub.to_csv(filename,index=False)

为冗长的叙述道歉,但我对编码比较陌生,这个问题很难指出。关于如何在线解决它的信息很少。简而言之,这是一种痛苦。

不幸的是,这仍然是解决问题的方法。如果任何特征中的类数对于测试来说是不同的,它就会吓坏了。同样奇怪的是,它在将测试拟合到 dls 时没有填充。

如果您有任何愿意分享的建议,请告诉我。