Ole*_*dov 6 python tabular fast-ai
我使用的是kaggle房价数据集,它分为:训练和测试
我知道这听起来很简单,大多数其他库都会像 model.predict(test) 那样做,但这里的情况并非如此。我搜索过 fastai 论坛以及 SO 和文档。关于这个问题有很多主题,其中大多数要么没有答案,要么是过时的解决方法(因为 fastai2 最近发布,现在简称为 fastai)。
A。model.predict 仅适用于单行,并且循环测试并不是最佳的。它非常慢。
b. model.get_preds 给出您训练的数据的结果
请建议您可以使用受过训练的学习器针对表格数据来预测新的 df 吗?
小智 8
model.get_preds用于对未见过的数据进行批量预测。您只需对这些新数据应用与训练数据相同的转换即可。
dl = model.dls.test_dl(test_data, bs=64) # apply transforms
preds, _ = model.get_preds(dl=dl) # get prediction
Run Code Online (Sandbox Code Playgroud)
fastai 的论坛非常活跃,您可能会得到库开发人员的回复,因此将来也可以尝试一下。
我发现了一个问题。对于未来的读者 - 为什么你不能get_preds为 new df 找到工作?
(在kaggle的房价先进的情况下进行测试)
问题的根源在于绝对的 nan。如果您使用一组猫特征训练模型,例如颜色 = 红色、绿色、蓝色;你的新 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]
Run Code Online (Sandbox Code Playgroud)
我们在做的时候做了一些调整。
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)
Run Code Online (Sandbox Code Playgroud)
成功进入 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
Run Code Online (Sandbox Code Playgroud)
to.items 将为我们提供转换后的猫列。之后,我们需要将所有东西重新组装在一起
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
Run Code Online (Sandbox Code Playgroud)
之后,我们按照 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()])
Run Code Online (Sandbox Code Playgroud)
此时,我们有了一个学习器,但仍然无法预测。我们这样做之后我想:
dl = learn.dls.test_dl(test_imp, bs=64)
preds, _ = learn.get_preds(dl=dl) # get prediction
Run Code Online (Sandbox Code Playgroud)
它会起作用(预处理连续值并预测),但不行。它不会填充。所以只需在测试中找到并填写nan:
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())
Run Code Online (Sandbox Code Playgroud)
之后我们终于可以预测:
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)
Run Code Online (Sandbox Code Playgroud)
对于冗长的叙述表示歉意,但我对编码相对较新,这个问题很难指出。关于如何解决在线问题的信息很少。简而言之,这是一种痛苦。
不幸的是,这仍然是解决问题的方法。如果测试中任何功能中的类数量不同,它就会崩溃。同样奇怪的是,在对 dls 进行拟合测试时它没有填充。
如果您有任何愿意分享的建议,请告诉我。