如何最好地确定模型的准确性?重复的列车/测试分流或cv



我正在创建一个分类器,它将矢量化的书籍文本作为输入,并作为输出预测书籍是否是";"好";或";坏";。

我有40本书,27本好,13本坏。我把每本书分成5条记录(5个10页的片段(来增加数据量,所以总共有200条记录。

最终,我会将模型应用于所有书籍,并使用它来预测未标记的书籍。

估计模型精度的最佳方法是什么?我还将使用这个估计值进行模型比较、调整等。

我正在考虑的两个选项:

  1. 运行一个循环,对模型进行X次测试,并查看每次拆分的准确性
  2. 使用交叉验证(专门对KFold进行分组,以便将每本书的5条记录保存在一起,因为如果不这样做,那将是重大泄漏(

我想尽快在小误差范围内估计精度。重复的列车测试拆分速度较慢,因为即使我按标签进行分层(选择8本好书和4本坏书进行测试(,特定模型的准确度也可能在0.6到0.8之间变化,所以我必须运行大量程序才能得到准确的估计。

另一方面,CV每次运行时都会给我相同的分数,并且在100次列车测试拆分后(在1-1.5%以内(,它似乎与模型的平均精度相对一致

CV要快得多,所以我更喜欢使用它。在这里使用CV有意义吗?我目前使用的是5倍(所以每次跑步要选择8本坚持书,或者总共40张坚持记录(。

此外,CV是否应该在每次运行时都给出完全相同的准确性?(就这一点而言,准确度列表完全相同,顺序相同(。在将X、y和组放入cross_val_score之前,我正在打乱我的语料库。ShuffleSplit会更好吗?这是我的代码:

for i in range(0,5):
    dfcopy = df.copy()
    dfcopy = dfcopy.sample(frac=1).reset_index(drop=True)
    X, y = dfcopy.text, dfcopy.label
    groups = dfcopy.title.tolist()
    
    model = MultinomialNB()
    name = 'LR'
    pipe = Pipeline([('cleaner', clean_transformer()),
                     ('vectorizer', bow_vector),
                     ('classifier', model)])
    score = cross_val_score(estimator=pipe, X=X, y=y, groups=groups, cv=GroupKFold())
    print(score)
    print(np.mean(score))

最后,我应该使用分层吗?我的想法是,我应该这样做,因为我实际上有40个项目要在训练和测试之间分配,所以(随机选择的(测试集可能会以全部/大部分好或全部/大部分坏的结果合理地结束,我不认为这是一个代表准确性的好测试集。

我将尝试按顺序进行:

  • What's the best way to estimate the accuracy my model's going to have? I'll also use this estimate for model comparison, tuning, etc.

  • CV is much faster, so I'd prefer to use it. Does CV make sense to use here?

如果你的折叠彼此非常相似,那么N折叠CV与重复测试和训练之间不会有太大差异。

  • Should CV be giving the exact same accuracy every time I run it?

它取决于两个因素,即超参数和所使用的数据,多项式NB的超参数几乎没有改进的空间。因此,它可以归结为CV折叠的分布。

  • Would a ShuffleSplit be preferable?

ShuffleSplit可能会产生一些差异,但不要指望会有巨大的差异。

正如我所看到的,至少根据我的经验,你可以迈出的一大步是停止使用MultinomialNB——尽管它是一个好的基线,但不会给你带来疯狂的好结果——而是开始使用更复杂的东西,比如SGD分类器、随机森林、感知器,你能想到的,感谢迄今为止在电话和数据标准化方面所做的出色工作。因此,您的模型将变为:

model = RandomForestClassifier()

还有一件可能有用的事情是使用训练/测试/验证集和超参数优化,比如Gridsearch,设置可能需要几个小时,但肯定会有回报。

如果您决定使用train/test/validate,scikit learn将为您提供train_testrongplit功能:

X, y = df.text, df.label    
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=1)

如果您决定使用网格搜索进行超参数优化,则需要:

(1( 定义一组可能的参数

grid_1 = { 
  "n_estimators": [100,200,500],
  "criterion": ["gini", "entropy"],
  "max_features": ['sqrt','log2',0.2,0.5,0.8],
  "max_depth": [3,4,6,10],
  "min_samples_split": [2, 5, 20,50] 
}

(2( 启动网格搜索优化

model = RandomForestClassifier()
grid_search = GridSearchCV(model, grid_1, n_jobs=-1, cv=5)
grid_search.fit(X_train, Y_train)

Gridsearch作为优化技术非常简单,但它将非常有助于提供更好的结果。如果你想加深对这个主题的理解并进一步增强你的代码,你可以在这里找到一个使用更复杂的超参数优化策略的示例代码,比如TPE

最后,你的数据集似乎很小,如果你在一列火车和另一列火车之间经历了漫长的等待时间,我建议你考虑写一个小的缓存系统,以减少加载和处理时间。你可以在这里找到一个使用小缓存系统的示例代码

相关内容

  • 没有找到相关文章

最新更新