TF-IDF 和非 TF-IDF 特征的准确性
Accuracy with TF-IDF and non-TF-IDF features
我 运行 具有 TF-IDF 和非 TF-IDF 特征的随机森林算法。
特征总数约为 130k(在对 TF-IDF 特征进行特征选择后),训练集的观察值约为 120k。
其中大约 500 个是非 TF-IDF 特征。
问题是随机森林在相同测试集上的准确性
-只有非TF-IDF特征是87%
- TF-IDF和非TF-IDF特征为76%
精度的这种显着恶化在我脑海中提出了一些问题。
我训练模型的相关代码如下:
drop_columns = ['labels', 'complete_text_1', 'complete_text_2']
# Split to predictors and targets
X_train = df.drop(columns=drop_columns).values
y_train = df['labels'].values
# Instantiate, train and transform with tf-idf models
vectorizer_1 = TfidfVectorizer(analyzer="word", ngram_range=(1,2), vocabulary=tf_idf_feature_names_selected)
X_train_tf_idf_1 = vectorizer_1.fit_transform(df['complete_text_1'])
vectorizer_2 = TfidfVectorizer(analyzer="word", ngram_range=(1,2), vocabulary=tf_idf_feature_names_selected)
X_train_tf_idf_2 = vectorizer_2.fit_transform(df['complete_text_2'])
# Covert the general features to sparse array
X_train = np.array(X_train, dtype=float)
X_train = csr_matrix(X_train)
# Concatenate the general features and tf-idf features array
X_train_all = hstack([X_train, X_train_tf_idf_1, X_train_tf_idf_2])
# Instantiate and train the model
rf_classifier = RandomForestClassifier(n_estimators=150, random_state=0, class_weight='balanced', n_jobs=os.cpu_count()-1)
rf_classifier.fit(X_train_all, y_train)
就个人而言,我没有在我的代码中发现任何错误(上面的这篇文章和一般的)。
我为解释这种准确性下降而制定的假设如下。
- 非 TF-IDF 特征的数量只有 500 个(在总共 130k 个特征中)
- 这提供了一些机会,即随机森林的树在每次分割时没有选择那么多的非 TF-IDF 特征(例如,因为
max_features
等)
- 因此,如果非 TF-IDF 特征确实很重要,那么这将产生问题,因为它们没有得到足够的考虑。
与此相关,当我在训练后检查随机森林的特征重要性时,我发现非 TF-IDF 特征的重要性非常低(尽管我不确定指标的可靠性如何特征重要性,尤其是包含 TF-IDF 特征时)。
你能用不同的方式解释我的分类器准确率下降的原因吗?
无论如何,你建议做什么?
结合 TF-IDF 和非 TF-IDF 特征的一些其他想法如下。
一种选择是拥有两个独立的(随机森林)模型——一个用于 TF-IDF 特征,一个用于非 TF-IDF 特征。
然后这两个模型的结果将通过(加权)投票或元分类进行组合。
您认为 130K 的特征对于随机森林来说太多了,这听起来是对的。您没有提到您的数据集中有多少示例,这对于选择可能的后续步骤至关重要。这是我的一些想法。
如果数据点的数量足够大,您可能想为 TF-IDF 特征训练一些转换 - 例如你可能想训练这些 TF-IDF 特征的小维嵌入,比如 64 维 space 然后例如一个小的 NN 在此之上(甚至可能是一个线性模型)。嵌入后,您可以将它们用作转换,为每个示例生成 64 个附加功能,以替换 TF-IDF 功能以进行随机森林训练。或者只是用这种架构的神经网络替换整个随机森林,例如TF-IDF 都通过全连接层组合成几个神经元,然后与其他特征连接(与嵌入非常相似,但作为神经网络的一部分)。
如果您没有足够的数据来训练大型神经网络,也许您可以尝试训练 GBDT 集成而不是随机森林。与随机森林相比,它在挑选好的特征方面可能应该做得更好,随机森林肯定会受到很多嘈杂无用特征的影响。您也可以先训练一些原始版本,然后在此基础上进行特征选择(同样,我希望它与随机森林相比应该做得更合理)。
我的猜测是你的假设部分正确。
使用完整数据集(在 130K 特征模型中)时,树中的每个拆分仅使用 500 个非 TF-IDF 特征的一小部分。因此,如果非 TF-IDF 特征很重要,那么每次拆分都会错过很多有用的数据。一次拆分忽略的数据可能会用于树中的不同拆分,但结果不如每次拆分使用更多数据时的结果好。
我认为还有一些非常重要的 TF-IDF 功能。事实上,我们拥有如此多的特征意味着每次拆分时都会考虑这些特征的一小部分。
换句话说:问题不在于我们正在削弱非 TF-IDF 功能。 问题是我们正在削弱 所有 有用的特征(包括非 TF-IDF 和 TF-IDF)。 这是沿着亚历山大的回答。
鉴于此,您提出的解决方案并不能很好地解决问题。如果你制作两个随机森林模型,一个有 500 个非 TF-IDF 特征,另一个有 125K 个 TF-IDF 特征,第二个模型将表现不佳,并对结果产生负面影响。如果您将 500 模型的结果作为附加功能传递给 125K 模型,您仍然表现不佳。
如果我们想坚持使用随机森林,更好的解决方案是增加 max_features
and/or 树的数量。这将增加在每次拆分时考虑有用特征的几率,从而产生更准确的模型。
我 运行 具有 TF-IDF 和非 TF-IDF 特征的随机森林算法。
特征总数约为 130k(在对 TF-IDF 特征进行特征选择后),训练集的观察值约为 120k。
其中大约 500 个是非 TF-IDF 特征。
问题是随机森林在相同测试集上的准确性
-只有非TF-IDF特征是87%
- TF-IDF和非TF-IDF特征为76%
精度的这种显着恶化在我脑海中提出了一些问题。
我训练模型的相关代码如下:
drop_columns = ['labels', 'complete_text_1', 'complete_text_2']
# Split to predictors and targets
X_train = df.drop(columns=drop_columns).values
y_train = df['labels'].values
# Instantiate, train and transform with tf-idf models
vectorizer_1 = TfidfVectorizer(analyzer="word", ngram_range=(1,2), vocabulary=tf_idf_feature_names_selected)
X_train_tf_idf_1 = vectorizer_1.fit_transform(df['complete_text_1'])
vectorizer_2 = TfidfVectorizer(analyzer="word", ngram_range=(1,2), vocabulary=tf_idf_feature_names_selected)
X_train_tf_idf_2 = vectorizer_2.fit_transform(df['complete_text_2'])
# Covert the general features to sparse array
X_train = np.array(X_train, dtype=float)
X_train = csr_matrix(X_train)
# Concatenate the general features and tf-idf features array
X_train_all = hstack([X_train, X_train_tf_idf_1, X_train_tf_idf_2])
# Instantiate and train the model
rf_classifier = RandomForestClassifier(n_estimators=150, random_state=0, class_weight='balanced', n_jobs=os.cpu_count()-1)
rf_classifier.fit(X_train_all, y_train)
就个人而言,我没有在我的代码中发现任何错误(上面的这篇文章和一般的)。
我为解释这种准确性下降而制定的假设如下。
- 非 TF-IDF 特征的数量只有 500 个(在总共 130k 个特征中)
- 这提供了一些机会,即随机森林的树在每次分割时没有选择那么多的非 TF-IDF 特征(例如,因为
max_features
等) - 因此,如果非 TF-IDF 特征确实很重要,那么这将产生问题,因为它们没有得到足够的考虑。
与此相关,当我在训练后检查随机森林的特征重要性时,我发现非 TF-IDF 特征的重要性非常低(尽管我不确定指标的可靠性如何特征重要性,尤其是包含 TF-IDF 特征时)。
你能用不同的方式解释我的分类器准确率下降的原因吗?
无论如何,你建议做什么?
结合 TF-IDF 和非 TF-IDF 特征的一些其他想法如下。
一种选择是拥有两个独立的(随机森林)模型——一个用于 TF-IDF 特征,一个用于非 TF-IDF 特征。 然后这两个模型的结果将通过(加权)投票或元分类进行组合。
您认为 130K 的特征对于随机森林来说太多了,这听起来是对的。您没有提到您的数据集中有多少示例,这对于选择可能的后续步骤至关重要。这是我的一些想法。
如果数据点的数量足够大,您可能想为 TF-IDF 特征训练一些转换 - 例如你可能想训练这些 TF-IDF 特征的小维嵌入,比如 64 维 space 然后例如一个小的 NN 在此之上(甚至可能是一个线性模型)。嵌入后,您可以将它们用作转换,为每个示例生成 64 个附加功能,以替换 TF-IDF 功能以进行随机森林训练。或者只是用这种架构的神经网络替换整个随机森林,例如TF-IDF 都通过全连接层组合成几个神经元,然后与其他特征连接(与嵌入非常相似,但作为神经网络的一部分)。
如果您没有足够的数据来训练大型神经网络,也许您可以尝试训练 GBDT 集成而不是随机森林。与随机森林相比,它在挑选好的特征方面可能应该做得更好,随机森林肯定会受到很多嘈杂无用特征的影响。您也可以先训练一些原始版本,然后在此基础上进行特征选择(同样,我希望它与随机森林相比应该做得更合理)。
我的猜测是你的假设部分正确。
使用完整数据集(在 130K 特征模型中)时,树中的每个拆分仅使用 500 个非 TF-IDF 特征的一小部分。因此,如果非 TF-IDF 特征很重要,那么每次拆分都会错过很多有用的数据。一次拆分忽略的数据可能会用于树中的不同拆分,但结果不如每次拆分使用更多数据时的结果好。
我认为还有一些非常重要的 TF-IDF 功能。事实上,我们拥有如此多的特征意味着每次拆分时都会考虑这些特征的一小部分。
换句话说:问题不在于我们正在削弱非 TF-IDF 功能。 问题是我们正在削弱 所有 有用的特征(包括非 TF-IDF 和 TF-IDF)。 这是沿着亚历山大的回答。
鉴于此,您提出的解决方案并不能很好地解决问题。如果你制作两个随机森林模型,一个有 500 个非 TF-IDF 特征,另一个有 125K 个 TF-IDF 特征,第二个模型将表现不佳,并对结果产生负面影响。如果您将 500 模型的结果作为附加功能传递给 125K 模型,您仍然表现不佳。
如果我们想坚持使用随机森林,更好的解决方案是增加 max_features
and/or 树的数量。这将增加在每次拆分时考虑有用特征的几率,从而产生更准确的模型。