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

fastai tabular model - how to get predictions for new data?

我使用的是kaggle房价数据集,分为:train和test

我知道这听起来很简单,大多数其他库也会像 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 的论坛非常活跃,你可能会得到图书馆开发人员的回应,所以以后也去那里试试。

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

(在kaggle的house prices advanced上测试)

问题的根源在于分类 nans。如果你用一组猫的特征来训练你的模型,比如说 color = red, green, blue;并且你的新 df 有颜色:红色,绿色,蓝色,黑色 - 它会抛出一个错误,因为它不知道如何处理 new class (黑色)。更不用说你需要在任何地方都有相同的列,这可能很棘手,因为如果你像我一样使用 fillmissing proc,这很好,它会为 cat 值(丢失或不丢失)创建新的列。所以你需要在猫身上对这些 nans 进行三次检查。 我真的想让它从 fastai 开始工作:

train/test 的列是相同的,只有火车有 1 个额外的 - 目标。此时在某些 cat cols 中有不同的 classes。我只是决定将它们结合起来(只是为了让它起作用),但它不会引入泄漏吗?

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)

进入表格熊猫

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 列。在那之后,我们需要 assemble 一切都恢复原状

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, 
                   procs = procs,
                   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

它会起作用(对连续值和预测进行预处理),但不行。它不会填满。 所以只需在测试中找到并填写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, bs=64)
preds, _ = 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)

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

不幸的是,这仍然是一个问题的解决方法。如果任何功能中 classes 的数量与测试不同,它就会崩溃。同样奇怪的是它在对 dls 进行拟合测试时没有填写。

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