【ML特征工程】第 4 章 :特征缩放的影响:从词袋到 Tf-Idf

news/2024/5/10 7:48:05/文章来源:https://blog.csdn.net/sikh_0529/article/details/128035024

   🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎

📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃

🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​

📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】  深度学习【DL】

 🖍foreword

✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。

如果你对这个系列感兴趣的话,可以关注订阅哟👋

文章目录

Tf-Idf:词袋的简单转折

TF-IDF 背后的直觉

进行测试

创建分类数据集

使用 Tf-Idf 转换扩展词袋

测试集上的特征缩放

逻辑回归分类

使用正则化调整 Logistic 回归

重要:比较模型时调整超参数

深潜:发生了什么?

TF-IDF = 列缩放

概括


词袋表示很容易生成,但远非完美。如果我们对所有单词进行平均计数,那么有些词最终被强调得比我们需要的更多。回忆一下第 3 章中艾玛和乌鸦的例子。我们想要一个强调两个主要角色的文档表示。“Emma”和“raven”这两个词都出现了三次,但“the”出现了八次,“and”出现了五次,“it”和“was”都出现了四次。仅仅通过简单的频率计数,主角并不能脱颖而出。这是有问题的。

挑选出诸如“华丽”、“闪闪发光”、“恐吓”、“暂时”和“统治”等词也很好,因为它们有助于设定段落的整体基调。它们表示情绪,这对数据科学家来说可能是非常有价值的信息。因此,理想情况下,我们想要一种能够突出显示有意义的词的表示。

Tf-Idf:词袋的简单转折

Tf-idf 是对词袋方法的简单改造。它代表词频——逆文档频率。tf-idf 不是查看数据集中每个文档中每个单词的原始计数,而是查看标准化计数,其中每个单词计数除以该单词出现的文档数。即:

bow( w , d ) = # 单词w在文档d中出现的次数

tf-idf( w , d ) = bow( w , d ) * N / (# w出现的文档)

N是数据集中文档的总数。分数N / (# documents ...) 就是所谓的逆文档频率。如果一个词出现在很多文档中,那么它的逆文档频率接近于1。如果一个词只出现在几个文档中,那么它的逆文档频率就会高很多。

或者,我们可以采取log 变换,而不是使用原始逆文档频率。对数将 1 变为 0,并使大数(远大于 1 的数)变小。(稍后会详细介绍。)

如果我们将 tf-idf 定义为:

tf-idf( w , d ) = bow( w , d ) * log ( N / # w出现的文档)

那么出现在每个文档中的单词将被有效地清零,而出现在极少数文档中的单词的计数将比以前更大。

让我们看一些图片来了解它的全部内容。图 4-1显示了一个包含四个句子的简单示例:“it is a puppy”、“it is a cat”、“it is a kitten”和“that is a dog and this is a pen”。我们将这些句子绘制在三个词的特征空间中:“puppy”、“cat”和“is”。

图 4-1。关于猫狗的四句话

现在让我们看一下 tf-idf 表示中的相同四个句子,使用逆向文档频率的对数变换。图 4-2显示了特征空间中的文档。请注意,“是”这个词作为一个特征被有效地消除了,因为它出现在这个数据集中的所有句子中。此外,因为它们每个只出现在四个句子中的一个句子中,所以“puppy”和“cat”这两个词现在的计数比以前高(log(4) = 1.38... > 1)。因此,tf-idf 使稀有词更加突出并有效地忽略了常见词。它与第 3 章中的基于频率的过滤方法密切相关,但在数学上比设置硬截止阈值要优雅得多。

TF-IDF 背后的直觉

Tf-idf 使稀有词更加突出并有效地忽略了常见词。

图 4-2。图4-1中句子的tf-idf表示

进行测试

tf-idf通过对word count特征进行改造乘以常数。因此,它是第 2 章介绍的特征缩放的一个例子。特征缩放在实践中的效果如何?让我们在一个简单的文本分类任务中比较缩放和未缩放特征的性能。是时候写一些代码了!

在示例 4-1中,我们重新访问了Yelp 评论数据集。Yelp 数据集挑战的第 6 轮包含对美国六个城市的近 160 万条企业评论。

示例 4-1。在 Python 中加载和清理 Yelp 评论数据集

>>> import json
>>> import pandas as pd# Load Yelp business data
>>> biz_f = open('yelp_academic_dataset_business.json')
>>> biz_df = pd.DataFrame([json.loads(x) for x in biz_f.readlines()])
>>> biz_f.close()# Load Yelp reviews data
>>> review_file = open('yelp_academic_dataset_review.json')
>>> review_df = pd.DataFrame([json.loads(x) for x in review_file.readlines()])
>>> review_file.close()# Pull out only Nightlife and Restaurants businesses
>>> two_biz = biz_df[biz_df.apply(lambda x: 'Nightlife' in x['categories'] or
...                                         'Restaurants' in x['categories'], 
...                               axis=1)]# Join with the reviews to get all reviews on the two types of business
>>> twobiz_reviews = two_biz.merge(review_df, on='business_id', how='inner')# Trim away the features we won't use
>>> twobiz_reviews = twobiz_reviews[['business_id', 
...                                  'name', 
...                                  'stars_y', 
...                                  'text', 
...                                  'categories']]# Create the target column--True for Nightlife businesses, and False otherwise
>>> two_biz_reviews['target'] =\
...     twobiz_reviews.apply(lambda x: 'Nightlife' in x['categories'],
...                          axis=1)

创建分类数据集

让我们看看是否可以使用评论将企业归类为餐厅或夜生活场所。为了节省训练时间,我们可以提取一部分评论。在这种情况下,两个类别之间的评论计数存在很大差异。这称为类不平衡数据集。不平衡的数据集对于建模来说是有问题的,因为模型将花费大部分精力来适应更大的类别。由于我们在两个类别中都有大量数据,因此解决该问题的一个好方法是将较大类别(餐馆)的采样率降低到与较小类别(夜生活)大致相同的大小。这是一个示例工作流程:

  1. 随机抽取 10% 的夜生活评论和 2.1% 的餐厅评论(选择的百分比是为了使每个类别中的示例数量大致相等)。

  2. 创建此数据集的 70/30 训练测试拆分。在此示例中,训练集最终有 29,264 条评论,测试集有 12,542 条评论。

  3. 训练数据包含 46,924 个唯一单词;这是词袋表示中的特征数量。

例 4-2展示了我们是如何做到这一点的。

示例 4-2。创建平衡分类数据集

# Create a class-balanced subsample to play with
>>> nightlife = \
...   twobiz_reviews[twobiz_reviews.apply(lambda x: 'Nightlife' in x['categories'],
...                                         axis=1)]
>>> restaurants = \
...   twobiz_reviews[twobiz_reviews.apply(lambda x: 'Restaurants' in x['categories'],
...                                         axis=1)]
>>> nightlife_subset = nightlife.sample(frac=0.1, random_state=123)
>>> restaurant_subset = restaurants.sample(frac=0.021, random_state=123)
>>> combined = pd.concat([nightlife_subset, restaurant_subset])# Split into training and test datasets
>>> training_data, test_data = modsel.train_test_split(combined, 
...                                                    train_size=0.7, 
...                                                    random_state=123)
>>> training_data.shape
(29264, 5)
>>> test_data.shape
(12542, 5)

使用 Tf-Idf 转换扩展词袋

本实验的目的是比较词袋、tf-idf 和ℓ 2归一化的有效性分类。请注意,执行 tf-idf 然后执行ℓ 2归一化与单独执行ℓ 2归一化相同。因此,我们只需要测试三组特征:词袋、tf-idf 和词袋之上的逐字ℓ 2规范化。

在示例 4-3中,我们使用 scikit-learnCountVectorizer将评论文本转换为词袋。 所有文本特征化方法都隐含地依赖于分词器,分词器是将文本字符串转换为标记(单词)列表的模块。在此示例中,scikit-learn 的默认标记化模式查找两个或多个字母数字字符的序列。标点符号被视为标记分隔符。

示例 4-3。变换特征

# Represent the review text as a bag-of-words 
>>> bow_transform = text.CountVectorizer()
>>> X_tr_bow = bow_transform.fit_transform(training_data['text'])
>>> X_te_bow = bow_transform.transform(test_data['text'])
>>> len(bow_transform.vocabulary_)
46924>>> y_tr = training_data['target']
>>> y_te = test_data['target']# Create the tf-idf representation using the bag-of-words matrix
>>> tfidf_trfm = text.TfidfTransformer(norm=None)
>>> X_tr_tfidf = tfidf_trfm.fit_transform(X_tr_bow)
>>> X_te_tfidf = tfidf_trfm.transform(X_te_bow)# Just for kicks, l2-normalize the bag-of-words representation
>>> X_tr_l2 = preproc.normalize(X_tr_bow, axis=0)
>>> X_te_l2 = preproc.normalize(X_te_bow, axis=0)

测试集上的特征缩放

关于特征缩放的一个微妙点是它需要知道特征统计那我们最在实践中可能不知道,例如均值、方差、文档频率,ℓ 2范数等。为了计算 tf-idf 表示,我们必须根据训练数据计算逆文档频率,并使用这些统计数据来缩放训练数据和测试数据。在 scikit-learn 中,将特征转换器拟合到训练数据上相当于收集相关统计数据。然后可以将安装的变压器应用于测试数据。

当我们使用训练统计数据来缩放测试数据时,结果看起来会有些模糊。测试集上的最小-最大缩放不再整齐地映射到 0 和1。ℓ 2范数、均值和方差统计数据看起来都有点偏差。这比丢失数据问题少。例如,测试集可能包含训练数据中不存在的词,我们没有文档频率可用于新词。常见的解决方案是简单地在测试集中删除新词。这似乎是不负责任的,但在训练集上训练的模型无论如何都不知道如何处理这些词。一个稍微不那么棘手的选择是明确学习一个“垃圾”词并将所有低频词映射到它,即使在训练集中,如“稀有词”中所讨论的.

逻辑回归分类

逻辑回归是一种简单的线性分类器。由于它的简单性,它通常是一个很好的第一个尝试的分类器。它采用输入特征的加权组合,并通过一个sigmoid 函数传递它,它平滑地将任何实数映射到 0 到 1 之间的数字。该函数将实数输入x转换为 0 到 1 之间的数字。它有一组参数w,表示围绕中点增加的斜率, 0.5。截距项b表示函数输出穿过中点的输入值。如果 sigmoid 输出大于 0.5,逻辑分类器将预测正类,否则预测负类。通过改变wb,人们可以控制决策发生变化的位置,以及决策应该以多快的速度响应围绕该点变化的输入值。

图 4-3说明了 sigmoid 函数。

图 4-3。sigmoid 函数的图示

现在让我们在各种特征集上构建一些简单的逻辑回归分类器,看看他们是怎么做的(例 4-4)。

使用正则化调整 Logistic 回归

逻辑回归有一些花里胡哨的东西。当特征的数量大于数据点的数量时,寻找最佳模型的问题被称为欠定的。解决此问题的一种方法是对训练过程施加额外的约束。这称为正则化,其技术细节在此处讨论。

大多数逻辑回归的实现都允许正则化。为了使用此功能,必须指定一个正则化参数。正则化参数是在模型训练过程中不会自动学习的超参数。相反,它们必须根据手头的问题进行调整,并提供给训练算法。此过程称为超参数调整。(有关如何评估机器学习模型的详细信息,请参阅 Zheng [2015]。)调整超参数的一种基本方法称为网格搜索:您指定超参数值的网格,调谐器以编程方式搜索最佳超参数设置网格。找到最佳超参数设置后,您可以使用该设置在整个训练集上训练模型,并将其在测试集上的性能作为对此类模型的最终评估。

重要:比较模型时调整超参数

在比较模型或特征时调整超参数至关重要。软件包的默认设置总是会返回一个模型。但除非软件在后台执行自动调整,否则它很可能会返回基于次优超参数设置的次优模型。分类器性能对超参数设置的敏感性取决于模型和训练数据的分布。逻辑回归对超参数设置相对稳健(或不敏感)。即便如此,有必要找到并使用正确范围的超参数。否则,一种模型相对于另一种模型的优势可能完全取决于调整参数,而不会反映模型或特征的实际行为。

即使是最好的自动调谐包仍然需要指定搜索的上限和下限,而找到这些限制可能需要手动尝试几次。

在下面的示例中,我们手动将逻辑正则化参数的搜索网格设置为 {1e-5, 0.001, 0.1, 1, 10, 100}。上限和下限尝试了几次以缩小范围。表 4-1给出了每个特征集的最佳超参数设置。

表 4-1。对夜生活场所和餐馆的 Yelp 评论样本进行逻辑回归的最佳超参数设置
 ℓ 2正则化
BoW0.1
2-normalized10
Tf-idf0.001

我们还想测试 tf-idf 和 BoW 之间的准确性差异是否是由于噪声造成的。为此,我们使用k次交叉验证来模拟具有多个统计独立的数据集。它将数据集分成k份。交叉验证过程遍历折叠,使用除一个折叠之外的所有折叠进行训练,并验证保留的折叠的结果。

通过重采样估计方差

现代统计方法假设基础数据来自随机分布。源自数据的模型的性能测量也受到随机噪声的影响。在这种情况下,基于可比较统计数据的数据集,不仅进行一次测量,而且进行多次测量始终是一个好主意。这为我们提供了测量的置信区间。

k折交叉验证就是这样一种策略。重采样是另一种从同一基础数据集生成多个小样本的技术。有关重采样的更多详细信息,请参见 Zheng (2015)。

GridSearchCVscikit-learn运行中的函数网格搜索使用交叉验证(参见示例 4-5)。图 4-4显示了在每个特征集上训练的模型的精度测量分布的盒须图。盒子中的中间线标记了中值精度,盒子本身标记了第一和第三四分位数之间的区域,而胡须扩展到分布的其余部分。

示例 4-5。使用网格搜索调整逻辑回归超参数

>>> import sklearn.model_selection as modsel# Specify a search grid, then do a 5-fold grid search for each of the feature sets
>>> param_grid_ = {'C': [1e-5, 1e-3, 1e-1, 1e0, 1e1, 1e2]}# Tune classifier for bag-of-words representation
>>> bow_search = modsel.GridSearchCV(LogisticRegression(), cv=5, 
...                                  param_grid=param_grid_)
>>> bow_search.fit(X_tr_bow, y_tr)# Tune classifier for L2-normalized word vector
>>> l2_search = modsel.GridSearchCV(LogisticRegression(), cv=5,
...                                 param_grid=param_grid_)
>>> l2_search.fit(X_tr_l2, y_tr)# Tune classifier for tf-idf
>>> tfidf_search = modsel.GridSearchCV(LogisticRegression(), cv=5,
...                                    param_grid=param_grid_)
>>> tfidf_search.fit(X_tr_tfidf, y_tr)# Let's check out one of the grid search outputs to see how it went
>>> bow_search.cv_results_
{'mean_fit_time': array([  0.43648252,   0.94630651,  5.64090128,  15.31248307,  31.47010217,  42.44257565]),
'mean_score_time': array([ 0.00080056,  0.00392466,  0.00864897,  0 .00784755,  0.01192751,  0.0072515 ]),
'mean_test_score': array([ 0.57897075,  0.7518111 ,  0.78283898,  0.77381766,  0.75515992,  0.73937261]),
'mean_train_score': array([ 0.5792185 ,  0.76731652,  0.87697341,  0.94629064,  0.98357195,  0.99441294]),
'param_C': masked_array(data = [1e-05 0.001 0.1 1.0 10.0 100.0],mask = [False False False False False False],fill_value = ?),
'params': ({'C': 1e-05},{'C': 0.001},{'C': 0.1},{'C': 1.0},{'C': 10.0},{'C': 100.0}),
'rank_test_score': array([6, 4, 1, 2, 3, 5]),
'split0_test_score': array([ 0.58028698,  0.75025624,  0.7799795 ,  0.7726341 ,  0.75247694,  0.74086095]),
'split0_train_score': array([ 0.57923964,  0.76860316,  0.87560871,  0.94434003,  0.9819308 ,  0.99470312]),
'split1_test_score': array([ 0.5786776 ,  0.74628396,  0.77669571,  0.76627371,  0 .74867589,  0.73176149]),
'split1_train_score': array([ 0.57917218,  0.7684849 ,  0.87945837,  0.94822946,  0.98504976,  0.99538678]),
'split2_test_score': array([ 0.57816504,  0.75533914,  0.78472578,  0.76832394,  0.74799248,  0.7356911 ]),
'split2_train_score': array([ 0.57977019,  0.76613558,  0.87689548,  0.94566657,  0.98368288,  0.99397719]),
'split3_test_score': array([ 0.57894737,  0.75051265,  0.78332194,  0.77682843,  0.75768968,  0.73855092]),
'split3_train_score': array([ 0.57914745,  0.76678626,  0.87634546,  0.94558346,  0.98385443,  0.99474628]),
'split4_test_score': array([ 0.57877649,  0.75666439,  0.78947368,  0.78503076,  0.76896787,  0.75      ]),
'split4_train_score': array([ 0.57876303,  0.7665727 ,  0.87655903,  0.94763369,  0.98334188,  0.99325132]),
'std_fit_time': array([ 0.03874582,  0.02297261,  1.18862097,  1.83901079,  4.21516797,  2.93444269]),
'std_score_time': array([ 0.00160112,  0.00605009,  0.00623053,  0.00698687,  0.00713112,  0.00570195]),
'std_test_score': array([ 0.00070799,  0.00375907,  0.00432957,  0.00668246,  0.00612049]),
'std_train_score': array([ 0.00032232,  0.00102466,  0.00131222,  0.00143229,  0.00100223,  0.00073252])}# Plot the cross validation results in a box-and-whiskers plot to 
# visualize and compare classifier performance
>>> search_results = pd.DataFrame.from_dict({
...                               'bow': bow_search.cv_results_['mean_test_score'],
...                               'tfidf': tfidf_search.cv_results_['mean_test_score'],
...                               'l2': l2_search.cv_results_['mean_test_score']
...                      })# Our usual matplotlib incantations. Seaborn is used here to make
# the plot pretty.
>>> import matplotlib.pyplot as plt
>>> import seaborn as sns
>>> sns.set_style("whitegrid")>>> ax = sns.boxplot(data=search_results, width=0.4)
>>> ax.set_ylabel('Accuracy', size=14)
>>> ax.tick_params(labelsize=14)

图 4-4。每个特征集和正则化设置下分类器准确度的分布——准确度是通过 5 折交叉验证的平均准确度来衡量的

表 4-2显示了每个超参数设置的平均交叉验证分类器准确度。每列中的星号表示该特征集达到的最高准确度。

表 4-2。平均交叉验证分类器准确度分数
正则化参数BoWℓ 2 -归一化Tf-idf
0.000010.5789710.5757240.721638
0.0010.7518110.5757240.788648 *
0.10.782839 *0.5891200.763566
10.7738180.7342470.741150
100.7551600.776756 *0.721467
1000.7393730.7611060.712309

ℓ 2 个归一化特征的结果在图 4-4中看起来非常糟糕。但不要被愚弄了。精度低的数字是由于非常糟糕的正则化参数设置——次优的超参数会导致非常错误的结论的具体证据。如果我们使用每个特征集的最佳超参数设置来训练模型,如示例 4-6 所示,不同特征集的准确率分数非常接近。

深潜:发生了什么?

为了理解结果背后的“原因”,我们必须查看模型如何使用这些特征。对于像逻辑回归这样的线性模型,这是通过称为数据矩阵的中间对象发生的。

数据矩阵包含表示为固定长度平面向量的数据点。对于词袋向量,数据矩阵是也称为文档术语矩阵图 3-1以向量形式显示了一个词袋向量,图 4-1说明了特征空间中的四个词袋向量。要形成一个文档术语矩阵,只需将文档向量平放,然后将它们堆叠在一起。列代表词汇表中所有可能的词(见图 4-5)。由于大多数文件仅包含所有可能单词的一小部分,该矩阵中的大部分条目都是零;它是一个稀疏矩阵。

图 4-5。五个文档和七个单词的示例文档术语矩阵

特征缩放方法本质上是对数据矩阵的列操作。特别是,tf-idf 和ℓ 2归一化都将整个列(例如n- gram 特征)乘以一个常数。

TF-IDF = 列缩放

Tf-idf 和ℓ 2归一化都是对数据矩阵的列操作。

正如附录 A中所讨论的,训练线性分类器归结为找到特征的最佳线性组合,这些特征是数据矩阵的列向量。解空间的特征在于数据矩阵的列空间和零空间。训练好的线性分类器的质量直接取决于零空间和数据矩阵的列空间。大的列空间意味着特征之间几乎没有线性相关性,这通常是好的。零空间包含不能表示为现有数据的线性组合的“新”数据点;大的零空间可能会有问题。(细读附录 A强烈建议读者阅读线性决策曲面、特征分解和矩阵的基本子空间等概念。)

列缩放操作如何影响数据矩阵的列空间和零空间?答案是“不是很多”。但是 tf-idf 和ℓ 2标准化可能不同的可能性很小。我们现在来看看为什么。

由于几个原因,数据矩阵的零空间可能很大。首先,许多数据集包含彼此非常相似的数据点。这意味着与数据集中的数据点数相比,有效行空间较小。其次,特征的数量可能远大于数据点的数量。词袋特别擅长创建巨大的特征空间。在我们的 Yelp 示例中,训练集中的 29,000 条评论中有 47,000 个特征。此外,不同单词的数量通常随着数据集中文档的数量而增长,因此添加更多文档不一定会降低特征数据比或减少零空间。

对于词袋,与特征数量相比,列空间相对较小。可能有些词在相同文档中出现的次数大致相同。这将导致相应的列向量几乎是线性相关的,从而导致列空间不像它可能的那样满秩(有关满秩的定义,请参见附录 A)。这称为秩不足。(就像动物缺乏维生素和矿物质一样,矩阵可能缺乏秩,输出空间不会像它应该的那样蓬松。)

秩不足的行空间和列空间导致模型为该问题提供过多。线性模型为数据集中的每个特征配备了一个权重参数。如果行和列空间是满秩1 ,那么该模型将允许我们在输出空间中生成任何目标向量。当它们排名不足时,模型的自由度超过了它的需要。这使得确定解决方案变得更加困难。

特征缩放能否解决数据矩阵的秩不足问题?让我们来看看。

列空间定义为所有列向量的线性组合(粗体表示向量):1 + 2 + ... + n v n。特征缩放用常数倍数替换列向量,比如说𝐯˜1=C𝐯1. 但是我们仍然可以通过将1替换为来生成原始的线性组合一个˜1=一个1/C. 似乎特征缩放不会改变列空间的等级。类似地,特征缩放不影响零空间的等级,因为可以通过反向缩放权重向量中的相应条目来抵消缩放后的特征列。

然而,像往常一样,有一个陷阱。如果标量为0,则无法恢复原来的线性组合;1不见了。如果该向量与所有其他列线性无关,那么我们就有效地缩小了列空间并扩大了零空间。

如果该向量与目标输出不相关,那么这可以有效地去除噪声信号,这是一件好事。事实证明,这是 tf-idf 和ℓ 2归一化之间的关键区别。ℓ 2归一化永远不会计算零范数,除非向量包含全零。如果向量接近于零,则其范数也接近于零。除以小范数会突出向量并使其更长。

另一方面,Tf-idf 可以生成接近于零的比例因子,如图 4-2所示。当单词出现在训练集中的大量文档中时,就会发生这种情况。这样的词可能与目标向量没有很强的相关性。将其修剪掉可以让求解器专注于列空间中的其他方向并找到更好的解决方案(尽管精度的提高可能不会很大,因为通常很少有噪声方向可以通过这种方式修剪)。

特征缩放——ℓ 2和 tf-idf——确实对求解器的收敛速度有明显影响。这表明数据矩阵现在具有更小的条件数(最大和最小奇异值之间的比率——有关这些术语的完整讨论,请参见附录 A)。事实上,ℓ 2归一化使条件数接近1。但并不是说条件数越好,解就越好。在这个实验中,ℓ 2归一化比 BoW 或 tf-idf 收敛得快得多。但它对过度拟合也更敏感:它需要更多的正则化并且对优化期间的迭代次数更敏感。

概括

在本章中,我们使用 tf-idf 作为切入点来详细分析特征转换如何影响(或不影响)模型。Tf-idf 是特征缩放的一个例子,因此我们将其性能与另一种特征缩放方法——ℓ 2归一化进行了对比。

结果并不像人们预期的那样。Tf-idf 和ℓ 2归一化不会提高最终分类器的准确度,高于普通词袋。在获得一些统计建模和线性代数印章后,我们明白了原因:它们都没有改变数据矩阵的列空间。

两者之间的一个小区别是 tf-idf 可以“拉伸”字数,也可以“压缩”它。换句话说,它使一些计数更大,而另一些则接近于零。因此,tf-idf 可以完全消除无信息的词。

在此过程中,我们还发现了特征缩放的另一个效果:它改善了数据矩阵的条件数,使线性模型的训练速度更快。ℓ 2归化和 tf-idf 都有这个效果。

总而言之,教训是:正确的特征缩放有助于分类。正确的缩放比例会突出提供信息的词并降低常用词的权重。它还可以提高数据矩阵的条件数。正确的缩放比例不一定是统一的列缩放比例。

这个故事很好地说明了在一般情况下分析特征工程效果的难度。改变特征会影响训练过程和随之而来的模型。线性模型是最容易理解的模型,但它仍然需要非常仔细的实验​​方法和大量深厚的数学知识来梳理理论和实践影响。对于更复杂的模型或特征转换,这几乎是不可能的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_37205.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工作中常用的设计模式--策略模式

一般做业务开发,不太容易有大量使用设计模式的场景。这里总结一下在业务开发中使用较为频繁的设计模式。当然语言为Java,基于Spring框架。 1 策略模式(Strategy Pattern) 一个类的行为或方法,在运行时可以根据条件的不同,有不同的…

(C语言)printf打印的字符串太长了,我想分两行!

本文来自于公众号&#xff1a;C语言编程技术分享 一、提问 有下述C程序&#xff1a; #include <stdio.h> #include <stdlib.h>int main() { printf("123456789012345678901234567890\n");system("pause");return 0; } printf函数要打印的字…

B. Elimination of a Ring Pinely Round 1 (Div. 1 + Div. 2)

传送门 题目意思&#xff1a; 给你一个为环的序列n&#xff0c;这个序列有一个特殊的地方&#xff1a;就是如果有相邻元素相等他就会立马删除其中一个元素&#xff08;第一个和最后一个相邻&#xff09;。 然后你每次可以删除一个元素&#xff0c;问你能删除的最多的操作数是多…

想做副业没有方向,这三条告诉你什么是副业思维

怎样副业赚钱&#xff1f;教你几招&#xff0c;掌控自己的固有思维 你了解钱是怎么来的吗&#xff1f;你如果弄不懂这一点&#xff0c;你也是很难赚到钱的。 钱不是苦的&#xff0c;辛苦努力挣的基本都是一点钱。 假如将你的工作时长换为钱&#xff0c;你可以清晰地赚多少钱…

【情感识别】BP神经网络语音情感识别【含Matlab源码 349期】

⛄一、BP神经网络语音情感识别简介 0 引言 随着科技的迅速发展, 人机交互显得尤为重要。语音是语言的载体, 是人与人之间交流的重要媒介。相较于其它交流方式而言, 语音交流更加直接、便捷。近年来, 随着人机交互研究的不断深入, 语音情感识别更成为了学术界研究的热点, 其涉及…

计算机键盘用途及快捷键

用途&#xff1a; 电脑键盘上有那么多按键&#xff0c;到底都有什么作用呢&#xff1f; 几个重要的按键&#xff0c;一起来了解一下吧。 最上面一排&#xff1a; F1帮助 F2改名 F3搜索 F4地址 F5刷新 F6切换 F10菜单 1、键盘中间区域的所有输入按键。 一共是26个英文字母…

【微服务】springboot + dubbo 整合Sentinel限流

一、前言 限流对一个生产环境的系统来说&#xff0c;具有重要的意义&#xff0c;限流的目的是为了保护系统中的某些核心业务资源不被瞬间的大并发流量冲垮而采取的一种措施&#xff0c;因此一个成熟的架构设计方案&#xff0c;限流也需要纳入到架构设计和规划中。 二、常用的限…

【Linux系统】第二篇、权限管理篇

文章目录一、Linux下的用户二、文件的权限1. 文件访问者的分类2. 文件类型和访问权限3. 文件权限值的表示方法三、文件访问权限的相关设置方法1. chmod2. chown3. chgrp4. umask&#xff08;重点&#xff09;四、file指令五、目录的权限粘滞位一、Linux下的用户 这里我们在上一…

【雷达通信】雷达探测项目仿真附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

多线程(1)

多线程 前言 &#xff1a; 上文主要了解到了进程&#xff0c; 那么为啥需要引入进程呢&#xff1f;   或者说为啥要有进程呢&#xff1f; 其实这里最主要的目的是为了解决 并发编程 这样的问题。 了解 &#xff1a;   这里 cpu 进入了多核心的时代&#xff0c;想要进一步提…

3天3定制大屏,反向PUA

摘要 本次分享一段无讨价还价余地的单人3天定制化大屏全过程&#xff08;强调说拖拽屏的请绕道,和你想的不一样&#xff09;,要动效、要地图、要流光。天坑的心理博弈到最终解决的过程及技术思路。 前因 没啥征兆突然接到说&#xff0c;要在下周完成2个大屏的定制开发,起初没提…

身份安全风险分析

摘要 从勒索软件到 APT&#xff0c;身份风险是重要的攻击向量。 管理 Active Directory 的复杂性&#xff0c;导致所有组织都存在1/6的可利用的特权身份风险。 这些身份风险包括使用过时密码的本地管理员、具有不必要权限的错误配置用户、在终端上暴露的缓存凭据等。 当攻击者…

arthas进阶版排查问题之idea插件工具操作

arthas前面的文章讲了怎么去使用命令排查线上问题&#xff0c;线上出了问题就需要我们去排查问题和处理程序异常&#xff0c;但是线上一般出问题不太好解决&#xff0c;总有一些奇怪的问题&#xff0c;当然很多场景是测试测试不到的&#xff0c;我们不能百分百保证线上不出问题…

阿里大咖纯手写的微服务入门笔记,从基础到进阶直接封神

前言 学习是一种基础性的能力。然而&#xff0c;“吾生也有涯&#xff0c;而知也无涯。”&#xff0c;如果学习不注意方法&#xff0c;则会“以有涯随无涯&#xff0c;殆矣”。 学习就像吃饭睡觉一样&#xff0c;是人的一种本能&#xff0c;人人都有学习的能力。我们在刚出生的…

AcWing 搜素与图论

搜索 DFS 全排列 代码 #include<iostream> using namespace std;int vis[10], a[10];void dfs(int step, int n) {if (step n 1){for (int i 1; i < n; i)printf("%d ", a[i]);printf("\n");return;}for (int i 1; i < n; i){if (!vis[i…

【调优】大数据常见 Join 的使用场景

【调优】大数据常见 Join 的使用场景 上次写了大表和大表 join 的调优方法&#xff0c;今天总结一下大数据常见的 Join 方法。 1.Shuffle Join 大数据采用的是分布式存储&#xff0c;一个表的数据会分散在各个节点。为了进行 join&#xff0c;通常都会进行 shuffle 操作&…

ESG,TO B长期主义里的「新战役」

中国企业最好的方式是从初始阶段就植入ESG基因&#xff0c;使它逐渐从隐形变成显性基因。长期坚持此类发展导向&#xff0c;对后续发展ESG战略&#xff0c;提升ESG合规能力也将成为一种积累和准备。 作者|三七 编辑|皮爷 出品|产业家 20世纪初期&#xff0c;伦敦得到一个延…

HttpMessageConverter 消息转换器

HttpMessageConverter 简介 HttpMessageConverter 是SpringMVC中提供的一个策略接口&#xff0c;它是一个消息转换器类&#xff0c;Spring Mvc中就是由HttpMessageConverter负责转换HTTP的请求和响应。 默认情况下&#xff0c;Spring Boot 会自动加载如下消息类型转换器&…

数字验证学习笔记——UVM学习1

一、类库地图 在SV模块中&#xff0c;验证环境整体的构建&#xff0c;是从底层模块的验证组件搭建到通信和激励生成这些元素无论是软件对象的创建、访问、修改、配置&#xff0c;还是组件之间的通信等都是通过用户自定义的方式来实现的。UVM验证方法学作为之前所有方法学的融合…

【语音去噪】谱减法+维纳滤波+卡尔曼滤波语音去噪【含Matlab源码 1881期】

⛄一、谱减法维纳滤波卡尔曼滤波语音去噪简介 1 维纳滤波算法 在传统的去噪算法中,维纳滤波因其操作简单、去噪效果好,被公认为一种经典的去噪算法。语音信号在时域的表示为: yi( t) si( t) ni( t) ,其中si( t) 、ni( t) 和yi( t) 分别是第i帧原始语音信号、噪声和被噪声污染…