我正在创建一个分类器,它将矢量化的书籍文本作为输入,并作为输出预测书籍是否是";"好";或";坏";。
我有40本书,27本好,13本坏。我把每本书分成5条记录(5个10页的片段(来增加数据量,所以总共有200条记录。
最终,我会将模型应用于所有书籍,并使用它来预测未标记的书籍。
估计模型精度的最佳方法是什么?我还将使用这个估计值进行模型比较、调整等。
我正在考虑的两个选项:
- 运行一个循环,对模型进行X次测试,并查看每次拆分的准确性
- 使用交叉验证(专门对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
最后,你的数据集似乎很小,如果你在一列火车和另一列火车之间经历了漫长的等待时间,我建议你考虑写一个小的缓存系统,以减少加载和处理时间。你可以在这里找到一个使用小缓存系统的示例代码