当前位置: 首页 > article >正文

使用 TFIDF+分类器 范式进行企业级文本分类(二)

1.开场白

上一期讲了 TF-IDF 的底层原理,简单讲了一下它可以将文本转为向量形式,并搭配相应分类器做文本分类,且即便如今的企业实践中也十分常见。详情请见我的上一篇文章 从One-Hot到TF-IDF(点我跳转)

光说不练假把式,在这篇文章中,你更加深刻了解TF-IDF是如何做文本分类的。具体有:

  1. 使用sklearn库进行TFIDF向量化
  2. 使用不同的分类器(SVM, 随机森林, XGBoost)做文本分类
  3. 搭配不同分类器的效果如何?

在开始之前推荐一个Github的开源项目。里面有很多开源数据集,很适合新手去探索 --> NLP民工乐园(本篇文章的数据集也是取自这里)

2.原理

1.TFIDF

TFIDF的原理虽然之前已经介绍了,但是这里还是简单讲一下好了。

TF-IDF(Term Frequency-Inverse Document Frequency)是一种用于信息检索和文本挖掘的加权技术,用于评估一个词在文档中的重要程度。它由两部分组成:

1. 词频(Term Frequency, TF)
衡量一个词在当前文档中出现的频率:

T F ( t , d ) = f t , d ∑ t ′ ∈ d f t ′ , d TF(t, d) = \frac{f_{t,d}}{\sum_{t' \in d} f_{t',d}} TF(t,d)=tdft,dft,d

其中:

  • f t , d f_{t,d} ft,d:词 t t t 在文档 d d d 中的出现次数
  • ∑ t ′ ∈ d f t ′ , d \sum_{t' \in d} f_{t',d} tdft,d:文档 d d d 中所有词的出现次数总和

2. 逆文档频率(Inverse Document Frequency, IDF)
衡量一个词的普遍重要性(在多少文档中出现):

I D F ( t , D ) = log ⁡ ( N ∣ { d ∈ D : t ∈ d } ∣ ) IDF(t, D) = \log \left( \frac{N}{|\{d \in D : t \in d\}|} \right) IDF(t,D)=log({dD:td}N)

其中:

  • N N N:语料库中文档的总数
  • ∣ { d ∈ D : t ∈ d } ∣ |\{d \in D : t \in d\}| {dD:td}:包含词 t t t 的文档数量

3. TF-IDF 最终公式
将TF和IDF相乘得到最终权重:

T F - I D F ( t , d , D ) = T F ( t , d ) × I D F ( t , D ) TF\text{-}IDF(t, d, D) = TF(t, d) \times IDF(t, D) TF-IDF(t,d,D)=TF(t,d)×IDF(t,D)

4. 变体说明
实际应用中可能存在不同变体,例如:

  • TF变体:对数缩放 T F = log ⁡ ( 1 + f t , d ) TF = \log(1 + f_{t,d}) TF=log(1+ft,d)
  • IDF变体:避免除零 I D F = log ⁡ ( N 1 + n t ) + 1 IDF = \log(\frac{N}{1 + n_t}) + 1 IDF=log(1+ntN)+1
  • 归一化:对文档向量进行L2归一化

2.SVM

全名支持向量机,简称SVM,在2000年前后的CPU时代,它也曾是顶流。

具体原理见我的另一篇文章,这是一篇背书于《统计学习方法》的、用严谨的数学进行SVM推导的文章 --> 支持向量机

之所以他曾是顶流,主要因为它具备如下优势

  1. SVM不存在现代深度学习反向传播的过拟合
  2. 小样本数据集上表现良好
  3. CPU环境下就能训练、推理,边缘设备(普通电脑)上也能跑起来
  4. 数学背景好,理论严谨

但是现在又被“淘汰”了,原因有:

  1. 大数据时代,SVM拓展性不足,数据量庞大的情况下训练很慢,相反深度学习可以利用GPU的并行,加速推理
  2. 泛化能力有限,SVM需要手动特征,而深度学习可以端到端自动学习特征
  3. 非线性场景能力有限,即便有核技巧处理非线性场景,但是函数选择和调参比较麻烦。
  4. 深度学习可以叠的很深,可以学习到数据中更加抽象、深层的信息,但SVM与之相比是浅层模型,学习到的信息有限。

关于支持向量机的作者 Vapnik,他还和现任人工智能的三驾马车 LeCun 有一段有趣的轶事,他们两个同为贝尔实验室的同事,因为学术之争处处不合。后来他们两位之间的争论某种意义上来说也代表了传统机器学习和深度学习之间的对碰。具体请见我的另一篇文章 自然语言处理发展史(点我跳转)

3.XGBoost

XGBoost 是梯度提升树GBDT的改良版,他们都是树模型的一种。

什么?你问我什么是树模型?好吧,这里我来解答一下,其实树模型是决策树类模型的简称,业内常常管决策树类的模型叫输模型。

至于决策树模型,可以见我另一篇文章 决策树(点我跳转)

跳转文章讲了决策树模型的基本原理,从纯数学的角度出发,带你理解决策树模型。

有了决策树的基础,理解GBDT和XGBoost就不是问题了。

那么让我们先了解GBDT,再看一看他是如何从GBDT过渡到XGBoost的吧

1.GBDT(梯度提升树)

GBDT(Gradient Boosting Decision Tree)的核心思想是通过加法模型(Additive Model)将多个弱分类器(通常是决策树)的预测结果逐步累加,从而逼近真实值
具体来说, 每一轮迭代都会训练一个新的弱分类器,使其拟合当前模型的负梯度(即残差的近似),而非直接拟合残差本身。
这里的“残差”可以理解为当前模型的预测值与真实值之间的误差方向,而GBDT通过梯度下降的策略逐步减少这一误差。

如图,Y = Y1 + Y2 + Y3
在这里插入图片描述

举一个非常简单的例子,比如我今年30岁了,但计算机或者模型GBDT并不知道我今年多少岁,那GBDT咋办呢?

它会在第一个弱分类器(或第一棵树中)随便用一个年龄比如20岁来拟合,然后发现误差有10岁;
接下来在第二棵树中,用6岁去拟合剩下的损失,发现差距还有4岁;
接着在第三棵树中用3岁拟合剩下的差距,发现差距只有1岁了;
最后在第四课树中用1岁拟合剩下的残差,完美。
最终,四棵树的结论加起来,就是真实年龄30岁。

实际工程中,gbdt是计算负梯度,用负梯度近似残差.

那么为什么用负梯度近似残差呢?

回归任务下,GBDT 在每一轮的迭代时对每个样本都会有一个预测值,此时的损失函数为均方差损失函数,
在这里插入图片描述

那此时的负梯度是这样计算的
在这里插入图片描述

所以,当损失函数选用均方损失函数时,每一次拟合的值就是(真实值 - 当前模型预测的值),即残差。
此时的变量是 y i y^i yi,即“当前预测模型的值”,也就是对它求负梯度。

2.XGBoost(极度梯度提升)

核心思想如图
在这里插入图片描述
在这里插入图片描述

(作者陈天奇大佬的原图)
可以看到,男孩的计算得分是两个树的相加 2+0.9=2.9

这不和GBDT一样么!

确实,如果不考虑工程实现、解决问题上的一些差异,xgboost与gbdt比较大的不同就是目标函数的定义

xgboost的目标函数如下图所示:
在这里插入图片描述
在这里插入图片描述

XGBoost的核心算法思想不难,基本就是:

  1. 不断地添加树,不断地进行特征分裂来生长一棵树,每次添加一个树,其实是学习一个新函数f(x),去拟合上次预测的残差。
  2. 当我们训练完成得到k棵树,我们要预测一个样本的分数,其实就是根据这个样本的特征,在每棵树中会落到对应的一个叶子节点,每个叶子节点就对应一个分数
  3. 最后只需要将每棵树对应的分数加起来就是该样本的预测值。

为什么XGBoost要用泰勒展开,优势在哪里?

XGBoost使用了一阶和二阶偏导, 二阶导数有利于梯度下降的更快更准. 使用泰勒展开取得函数做自变量的二阶导数形式, 可以在不选定损失函数具体形式的情况下, 仅仅依靠输入数据的值就可以进行叶子分裂优化计算, 本质上也就把损失函数的选取和模型算法优化/参数选择分开了. 这种去耦合增加了XGBoost的适用性, 使得它按需选取损失函数, 可以用于分类, 也可以用于回归。

3.数据集

该篇文章数据集地址 酒店评论 (也出自开头推荐的那个Github开源项目里)

该数据集是一个酒店评价数据集,有两个字段:

  • review为用户评论
  • label为情感的正负类标签,其中1为正面情绪,0为负面情绪

数据集预览
在这里插入图片描述

4.技术实践

1.sklearn中的使用TFIDF

前提:安装sklearn

pip install scikit-learn

在 scikit-learn (sklearn) 中,TfidfVectorizer 是用于 TF-IDF文本特征提取的主要类。它属于 sklearn.feature_extraction.text 模块,主要用于将文本数据转换为数值特征矩阵

下面讲一下它的关键参数吧~

  1. stop_words{‘english’}, list, default=None
  2. ngram_range: tuple (min_n, max_n)` default=(1, 1)
    a. 要提取的不同n-gram的n值范围的下限和上限。将使用min_n<=n<=max_n的所有n值。
  3. max_dffloat or int, default=1.0:
    i. 在构建词汇表时,忽略文档频率严格高于给定阈值的术语(特定于语料库的停用词)。如果在[0.0,1.0]范围内,则该参数表示文档的比例,即整数绝对计数。如果词汇表不是None,则忽略此参数。
  4. min_df float or int, default=1
    i. 在构建词汇表时,忽略文档频率严格低于给定阈值的术语。这个值在文献中也被称为截止值。如果浮点数在[0.0,1.0]的范围内,则该参数表示文档的比例,即整数绝对计数。如果词汇表不是None,则忽略此参数。
  5. max_features int, default=None
    i. 如果不是None,则构建一个词汇表,只考虑语料库中按词频排序的顶级max_features。否则,将使用所有功能。
    如果词汇表不是None,则忽略此参数。
  6. smooth_idf bool, default=True
    i. 通过在文档频率上加1来平滑idf权重,就像看到一个额外的文档包含集合中的每个术语一样。
  7. sublinear_tf bool, default=False
    i. 应用亚线性tf缩放,即将 tf 替换为1 + log(tf)。
tfidf = TfidfVectorizer(max_features=5000, stop_words=stopwords, ngram_range=(1,2),min_df=3,           # 过滤低频词max_df=0.9,          # 过滤高频词# sublinear_tf=True, # 对数平滑,降低词频影响
)
X = tfidf.fit_transform(train_df['processed_text'])
  1. 总结
    a. 注意调整ngram_rangemax_features 。直接对效率和特征表示能力相关联。

2.XGBoost

前提:安装XGBoost

pip install xgboost

下面讲讲xgboost的使用吧

1. 通用参数
宏观函数控制 在 xgboost.config_context() 设置
a. verbosity: Valid values of 0 (silent), 1 (warning), 2 (info), and 3 (debug).

2. 一般参数:
a. booster [default= gbtree ]。使用哪种助推器。可以是gbtree、gblinear或dart;gbtree和dart使用基于树的模型,而gblinear使用线性函数。
b. device [default= cpu]
c. nthread [如果未设置,则默认为可用的最大线程数]

3. Booster 参数
a. eta [default=0.3, alias(别名): learning_rate]
b. gamma [default=0, alias: min_split_loss][0,∞]

  • 在树的叶子节点上进行进一步分区所需的最小损失减少。gamma越大,算法就越保守。请注意,没有进行分割的树可能仍然包含一个非零分数的终端节点。

c. max_depth [default=6][0,∞]

  • 树的最大深度。增加此值将使模型更加复杂,更有可能过度拟合。0表示深度没有限制。请注意,XGBoost在训练深层树时会大量消耗内存。精确树方法需要非零值。

d. min_child_weight [default=1][0,∞]

  • 孩子结点所需实例权重的最小总和。如果树分区步骤导致叶节点的实例权重之和小于min_child_weight,则构建过程将放弃进一步的分区。在线性回归任务中,这只对应于每个节点中需要的最小实例数。min_child_weight越大,算法就越保守。

e. subsample [default=1]

  • 训练实例的子样本比率。将其设置为0.5意味着XGBoost将在种植树木之前随机采样一半的训练数据。这将防止过拟合。子采样将在每次增强迭代中发生一次。

f. lambda [default=1, alias: reg_lambda]

  • 权重的L2正则化项。增加此值将使模型更加保守。range: [0, ∞]

g. alpha [default=0, alias: reg_alpha]

  • 权重上的L1正则化项。增加此值将使模型更加保守。range: [0, ∞]

h. tree_method string [default= auto] auto, exact, approx, hist

  • auto: 与hist-tree方法相同。
  • exact: 精确贪婪算法。枚举所有拆分的候选人。
  • approx:使用分位数草图和梯度直方图的近似贪婪算法。
  • hist: 更快的直方图优化近似贪婪算法。

i. scale_pos_weight [default=1]

  • 控制正负权重的平衡,对不平衡的类很有用。需要考虑的典型值:sum(负实例)/sum(正实例)。

4. 特定学习任务参数
指定学习任务和相应的学习目标。目标选项如下

  • objective [default=reg:squarederror]
    a. reg:squarederror: 平方误差:损失平方的回归
    b. reg:squaredlogerror: 平方对数误差:具有平方对数损失的回归。所有输入标签都必须大于-1
    c. reg:logistic: 逻辑回归,输出概率
    d. reg:pseudohubererror:伪Huber误差:使用伪Huber损失的回归,这是绝对损失的两次可微替代方案。
    e. reg:absoluteerror: 绝对误差:L1误差回归。当使用树模型时,在树构建后刷新叶值。如果在分布式训练中使用,叶值将作为所有工人的平均值计算,这并不能保证是最优的。
    f. reg:quantileerror:分位数损失,也称为弹球损失。
    g. binary:logistic: 二元逻辑回归:用于二元分类的逻辑回归,输出概率
    h. binary:logitraw: 二元分类的逻辑回归,逻辑转换前的输出分数
    i. binary:hinge:二元分类的铰链损失。这使得预测为0或1,而不是产生概率。
    j. multi:softmax: 设置XGBoost使用softmax目标进行多类分类,还需要设置num_class(类的数量)
    k. multi:softprob: 与softmax相同,但输出一个 ndatanclass 向量,该向量可以进一步整形为ndatanclass矩阵。结果包含每个数据点属于每个类的预测概率。
  • eval_metric [default according to objective] :验证数据的评估指标,将根据目标分配默认指标(回归的rmse,分类的logloss,排名的平均精度:映射等)
    a. rmse: 均方根误差
    b. mae: 平均绝对误差
    c. logloss: 负对数似然
    d. auc: ROC曲线下与坐标轴围成的面积。可用于分类和学习任务排名。
    • 用于二分类时,目标函数应为binary:logistic或类似的处理概率的函数。
    • 用于多分类时,目标函数应为multi:softprob而非multi:softmax,因为后者不输出概率。AUC通过1对其余类计算,参考类由类别比例加权。
    • 当输入数据集只包含负样本或正样本时,输出为NaN。具体行为取决于实现,例如scikit-learn会返回0.5。

5. XGBoost调优

1.控制过拟合

当你观察到训练精度很高,但测试精度很低时,很可能会遇到过拟合问题

在XGBoost中,通常有两种方法可以控制过拟合:

第一种方法是直接控制模型的复杂性
a. 包括 max_depth, min_child_weight and gamma.

第二种方法是增加随机性,使训练对噪声具有鲁棒性。
a. 包括 subsample and colsample_bytree
b. 您还可以减小步长 eta。执行此操作时,请记住增加num_round

2.处理不平衡数据集

数据集非常不平衡。这会影响XGBoost模型的训练,有两种方法可以改进它。

  • 如果你只关心预测的整体性能指标(AUC)
    • 通过 scale_pos_weight平衡正负权重
  • 如果你关心预测正确的概率
    • 将参数 max_delta_step设置为有限数(比如1)以帮助收敛

5.使用TFIDF做特征,用SVM或XGBoost做分类器,做酒店评价的情感分析

在这里插入图片描述

1.分词

ps:由于中文和英文不一样,英文会天然的使用空格进行分词,但是中文的一句话是连贯的。如:

英文:I want to go to Beijing.
中文:我想去北京。

如果把英语交给模型,模型收到的是 ["I", "want", "to", "go", "to", "Beijing", "."],总共6个词。
但是如果把中文交给模型,模型收到的是 我想去北京。,总共1个词。

故在NLP中,中文领域都是要分词的。

但是中文如果直接以“字”分词,效果可能很可能不好,因为中文是以词为单位的。如 北京 (一个词)和 (两个字)是两个完全不同的概念。

如果是传统的机器学习文本分类,如SVM和XGBoost通常是采用 Jieba 库来进行分词的。

关于这个库我以后会专门出一篇文章来讲。

总之,在这篇文章中先不考虑jieba的原理,你只需要知道他可以进行如下方式的分词即可。

text = "我要去北京。"
print(jieba.lcut(text))# # ['我要', '去', '北京', '。']

1.这里使用的是 lcut而不是cut,是因为方便打印展示,lcut会直接返回list(迭代器),而cut会返回一个生成器<generator object Tokenizer.cut at 0x164a07a00>.
2.其实业务中大多还是采用生成器cut的形式,因为生成器是惰性迭代计算的,内存效率高。


简单解释一下生成器和迭代器的区别。

生成器 vs 迭代器(列表)(以"我要去北京。"为例)

列表:像把所有分词结果装进盒子
lcut(“我要去北京。”) → 直接给你 [‘我要’, ‘去’, ‘北京’, ‘。’]
生成器:像现用现做的流水线
cut(“我要去北京。”) → 需要时才一个个生成:
‘我要’ → ‘去’ → ‘北京’ → ‘。’

区别:
列表:一次性全做好(占内存,但能反复用)
生成器:用的时候才做(省内存,但只能用一次)

(如果同学不理解生成器和列表的区别,可以评论或留言,我会迅速转门出一篇文章来阐述他俩的区别)


2.使用SVM做分类器

import time
import pandas as pd
import jieba
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import SVC
from sklearn.metrics import classification_report# 记录总开始时间
total_start = time.time()# 1. 数据加载
print("1. 正在加载数据...")
start = time.time()
data = pd.read_csv('/Users/zhangqingjie/Downloads/ChnSentiCorp_htl_all.csv')  # 替换为你的文件路径
print(f"数据加载完成,用时: {time.time() - start:.2f}秒")
print(f"数据样本数: {len(data)}")# 2. 中文分词
print("\n2. 正在进行中文分词...")
start = time.time()def chinese_tokenizer(text):return ' '.join(jieba.cut(text))data['review'] = data['review'].fillna('')
data['tokenized_review'] = data['review'].apply(chinese_tokenizer)
print(f"分词完成,用时: {time.time() - start:.2f}秒")# 3. 数据划分
print("\n3. 正在划分训练集和测试集...")
start = time.time()
X_train, X_test, y_train, y_test = train_test_split(data['tokenized_review'], data['label'], test_size=0.2, random_state=42,shuffle=True
)
print(f"数据划分完成,用时: {time.time() - start:.2f}秒")
print(f"训练集大小: {len(X_train)}, 测试集大小: {len(X_test)}")# 4. TF-IDF特征提取
print("\n4. 正在进行TF-IDF特征提取...")
start = time.time()
tfidf = TfidfVectorizer(max_features=5000)
X_train_tfidf = tfidf.fit_transform(X_train)
X_test_tfidf = tfidf.transform(X_test)
print(f"TF-IDF特征提取完成,用时: {time.time() - start:.2f}秒")
print(f"特征维度: {X_train_tfidf.shape[1]}")# 5. SVM模型训练
print("\n5. 正在训练SVM模型...")
start = time.time()
svm_model = SVC(kernel='linear', random_state=42)
svm_model.fit(X_train_tfidf, y_train)
print(f"SVM模型训练完成,用时: {time.time() - start:.2f}秒")# 6. 模型评估
print("\n6. 正在评估模型...")
start = time.time()
y_pred = svm_model.predict(X_test_tfidf)
print("分类报告:")
print(classification_report(y_test, y_pred))
print(f"模型评估完成,用时: {time.time() - start:.2f}秒")# 总用时
print(f"\n总用时: {time.time() - total_start:.2f}秒")

最终效果

分类报告:precision    recall  f1-score   support0       0.84      0.76      0.80       5051       0.89      0.93      0.91      1049accuracy                           0.88      1554macro avg       0.87      0.85      0.86      1554
weighted avg       0.88      0.88      0.88      1554

3.使用XGBoost做分类器

import time
import pandas as pd
import jieba
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from xgboost import XGBClassifier
from sklearn.metrics import classification_report# 记录总开始时间
total_start = time.time()# 1. 数据加载
print("1. 正在加载数据...")
start = time.time()
data = pd.read_csv('/Users/zhangqingjie/Downloads/ChnSentiCorp_htl_all.csv')  # 替换为你的文件路径
print(f"数据加载完成,用时: {time.time() - start:.2f}秒")
print(f"数据样本数: {len(data)}")# 2. 中文分词
print("\n2. 正在进行中文分词...")
start = time.time()def chinese_tokenizer(text):return ' '.join(jieba.cut(text))data['review'] = data['review'].fillna('')
data['tokenized_review'] = data['review'].apply(chinese_tokenizer)
print(f"分词完成,用时: {time.time() - start:.2f}秒")# 3. 数据划分
print("\n3. 正在划分训练集和测试集...")
start = time.time()
X_train, X_test, y_train, y_test = train_test_split(data['tokenized_review'], data['label'], test_size=0.2, random_state=42,shuffle=True
)
print(f"数据划分完成,用时: {time.time() - start:.2f}秒")
print(f"训练集大小: {len(X_train)}, 测试集大小: {len(X_test)}")# 4. TF-IDF特征提取
print("\n4. 正在进行TF-IDF特征提取...")
start = time.time()
tfidf = TfidfVectorizer(max_features=5000)
X_train_tfidf = tfidf.fit_transform(X_train)
X_test_tfidf = tfidf.transform(X_test)
print(f"TF-IDF特征提取完成,用时: {time.time() - start:.2f}秒")
print(f"特征维度: {X_train_tfidf.shape[1]}")# 5. XGBoost模型训练
print("\n5. 正在训练XGBoost模型...")
start = time.time()
xgb_model = XGBClassifier(n_estimators=100,max_depth=6,learning_rate=0.1,random_state=42,use_label_encoder=False,eval_metric='logloss'
)
xgb_model.fit(X_train_tfidf, y_train)
print(f"XGBoost模型训练完成,用时: {time.time() - start:.2f}秒")# 6. 模型评估
print("\n6. 正在评估模型...")
start = time.time()
y_pred = xgb_model.predict(X_test_tfidf)
print("分类报告:")
print(classification_report(y_test, y_pred))
print(f"模型评估完成,用时: {time.time() - start:.2f}秒")# 总用时
print(f"\n总用时: {time.time() - total_start:.2f}秒")

效果如下:

              precision    recall  f1-score   support0       0.82      0.65      0.73       5051       0.85      0.93      0.89      1049accuracy                           0.84      1554macro avg       0.84      0.79      0.81      1554
weighted avg       0.84      0.84      0.84      1554

4.效果对比

模型类别精确率召回率F1分数准确率
SVM00.840.760.800.88
10.890.930.91
XGBoost00.820.650.730.84
10.850.930.89

看起来SVM更胜一筹啊。

调调参,尝试抢救一下XGBoost

xgb_model = XGBClassifier(n_estimators=800,max_depth=8,subsample=0.8,        # 每棵树随机采样80%数据learning_rate=0.03,random_state=42,use_label_encoder=False, objective='binary:logistic',eval_metric='logloss'
)

现在效果如下

分类报告:precision    recall  f1-score   support0       0.82      0.73      0.77       5051       0.88      0.92      0.90      1049accuracy                           0.86      1554macro avg       0.85      0.82      0.83      1554
weighted avg       0.86      0.86      0.86      1554

貌似还是差点意思。。。

6. 总结与收获

通过本篇文章的实践,我们系统地学习了如何使用TF-IDF结合不同分类器进行文本分类任务。以下是本次实践的核心收获:

5.1 关键技术掌握

  1. TF-IDF特征提取

    • 熟练使用sklearn的TfidfVectorizer进行文本向量化
    • 理解了max_featuresngram_range等关键参数对特征空间的影响
    • 掌握了中文分词处理技巧
  2. 分类器应用对比

    • 实现了SVM和XGBoost两种主流分类器
    • 观察到SVM在本任务中表现略优(88% vs 86%准确率)
    • 实践了XGBoost的参数调优过程
  3. 完整Pipeline构建

    • 从数据加载、预处理到模型训练评估的全流程实践
    • 掌握了文本分类任务的标准化开发流程

5.2 实践洞见

  1. SVM的优势显现

    • 在小规模文本数据上,SVM展现出更好的分类性能
    • 特别是对负类(差评)的识别更准确(F1 0.80 vs 0.77)
    • 验证了SVM在高维稀疏特征上的优势
  2. XGBoost的调参经验

    • 通过调整n_estimators、learning_rate等参数提升效果
    • 发现树模型需要更精细的参数调整才能达到理想效果
    • 证明了boosting算法在文本分类中的适用性
  3. 特征工程的关键性

    • TF-IDF作为基础特征提取方法仍然非常有效
    • 中文分词质量直接影响最终分类效果
    • 特征维度控制(max_features)对模型效率影响显著

思考题🤔

  1. 在本实验中,SVM在文本分类任务上表现略优于XGBoost(88% vs 86%准确率)。结合文章提到的原理,你认为可能是什么原因导致的?如果数据集规模扩大10倍,结果可能会发生怎样的变化?为什么?

  2. TF-IDF的ngram_range没有特别指定,其实内部是采用默认值的tfidf = TfidfVectorizer(max_features=5000, ngram_range=(1,1)),(即仅使用单词)。如果将其改为(1,2)(包含单词和双词组合),你认为会对分类效果产生什么影响?尝试修改代码并观察结果,验证你的猜想。

下期预告🚀
现在的NLP模型大多是预训练语言模型BERT类和GPT的衍生,你知道最初的预训练语言模型是什么样的么?

在 Transformer 和注意力机制崛起之前,Word2Vec 率先用『词向量』颠覆了传统 NLP——它让单词不再是孤立的符号,而是蕴含语义的数学向量。

下一期将深入拆解:
🔹 为什么Word2Vec是预训练模型的雏形
🔹 CBOW和Skip-Gram究竟有什么区别?
🔹 GloVe、FastText 等变体如何改进 Word2Vec?

相关文章:

使用 TFIDF+分类器 范式进行企业级文本分类(二)

1.开场白 上一期讲了 TF-IDF 的底层原理&#xff0c;简单讲了一下它可以将文本转为向量形式&#xff0c;并搭配相应分类器做文本分类&#xff0c;且即便如今的企业实践中也十分常见。详情请见我的上一篇文章 从One-Hot到TF-IDF&#xff08;点我跳转&#xff09; 光说不练假把…...

《车辆人机工程-汽车驾驶操纵实验》

汽车操纵装置有哪几种&#xff0c;各有什么特点 汽车操纵装置是驾驶员直接控制车辆行驶状态的关键部件&#xff0c;主要包括以下几种&#xff0c;其特点如下&#xff1a; 一、方向盘&#xff08;转向操纵装置&#xff09; 作用&#xff1a;控制车辆行驶方向&#xff0c;通过转…...

[ABC400F] Happy Birthday! 3 题解

考虑正难则反。问题转化为&#xff1a; 一个环上有 n n n 个物品&#xff0c;颜色分别为 c o l i col_i coli​&#xff0c;每次操作选择两个数 i , j i, j i,j 使得 ∀ k ∈ [ i , j ] , c o l k c o l i ∨ c o l k 0 \forall k \in [i, j], col_k col_i \lor col_k …...

python高级编程一(生成器与高级编程)

@TOC 生成器 生成器使用 通过列表⽣成式,我们可以直接创建⼀个列表。但是,受到内存限制,列表容量肯定是有限的。⽽且,创建⼀个包含100万个元素的列表,不仅占⽤很⼤的存储空间,如果我们仅仅需要访问前⾯⼏个元素,那后⾯绝⼤多数元素占 ⽤的空间都⽩⽩浪费了。所以,如果…...

Go 字符串四种拼接方式的性能对比

简介 使用完整的基准测试代码文件&#xff0c;可以直接运行来比较四种字符串拼接方法的性能。 for 索引 的方式 for range 的方式 strings.Join 的方式 strings.Builder 的方式 写一个基准测试文件 echo_bench_test.go package mainimport ("os""stri…...

windows安装fastbev环境时,安装mmdetection3d出现的问题总结

出现的问题如下&#xff1a; C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\include\crt/host_config.h(160): fatal error C1189: #error: -- unsupported Microsoft Visual Studio version! Only the versions between 2017 and 2019 (inclusive) are supporte…...

单片机Day05---动态数码管显示01234567

一、原理图 数组索引段码值二进制显示内容00x3f0011 1111010x060000 0110120x5b0101 1011230x4f0100 1111340x660110 0110450x6d0110 1101560x7d0111 1101670x070000 0111780x7f0111 1111890x6f0110 11119100x770111 0111A110x7c0111 1100B120x390011 1001C130x5e0101 1110D140…...

【Python3教程】Python3基础篇之数据结构

博主介绍:✌全网粉丝22W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…...

muduo库源码分析: One Loop Per Thread

One Loop Per Thread的含义就是&#xff0c;一个EventLoop和一个线程唯一绑定&#xff0c;和这个EventLoop有关的&#xff0c;被这个EventLoop管辖的一切操作都必须在这个EventLoop绑定线程中执行 1.在MainEventLoop中&#xff0c;负责新连接建立的操作都要在MainEventLoop线程…...

使用Python解决Logistic方程

引言 在数学和计算机科学中,Logistic 方程是描述人口增长、传播过程等现象的一种常见模型。它通常用于表示一种有限资源下的增长过程,比如动物种群、疾病传播等。本文将带领大家通过 Python 实现 Logistic 方程的求解,帮助你更好地理解这一经典数学模型。 1.什么是 Logist…...

AI Agent工程师认证-学习笔记(3)——【多Agent】MetaGPT

学习链接:【多Agent】MetaGPT学习教程 源代码链接(觉得很好,star一下):GitHub - 基于MetaGPT的多智能体入门与开发教程 MetaGPT链接:GitHub - MetaGPT 前期准备 1、获取MetaGPT (1)使用pip获取MetaGPT pip install metagpt==0.6.6#或者在国内加速安装镜像 #pip in…...

MCP结合高德地图完成配置

文章目录 1.MCP到底是什么2.cursor配置2.1配置之后的效果2.2如何进行正确的配置2.3高德地图获取key2.4选择匹配的模型 1.MCP到底是什么 作为学生&#xff0c;我们应该如何认识MCP&#xff1f;最近看到了好多跟MCP相关的文章&#xff0c;我觉得我们不应该盲目的追求热点的技术&…...

重读《人件》Peopleware -(5)Ⅰ管理人力资源Ⅳ-质量—若时间允许

20世纪的心理学理论认为&#xff0c;人类的性格主要由少数几个基本本能所主导&#xff1a;生存、自尊、繁衍、领地等。这些本能直接嵌入大脑的“固件”中。我们可以在没有强烈情感的情况下理智地考虑这些本能&#xff08;就像你现在正在做的那样&#xff09;&#xff0c;但当我…...

文献总结:AAAI2025-UniV2X-End-to-end autonomous driving through V2X cooperation

UniV2X 一、文章基本信息二、文章背景三、UniV2X框架1. 车路协同自动驾驶问题定义2. 稀疏-密集混合形态数据3. 交叉视图数据融合&#xff08;智能体融合&#xff09;4. 交叉视图数据融合&#xff08;车道融合&#xff09;5. 交叉视图数据融合&#xff08;占用融合&#xff09;6…...

制造一只电子喵 (qwen2.5:0.5b 微调 LoRA 使用 llama-factory)

AI (神经网络模型) 可以认为是计算机的一种新的 “编程” 方式. 为了充分利用计算机, 只学习传统的编程 (编程语言/代码) 是不够的, 我们还要掌握 AI. 本文以 qwen2.5 和 llama-factory 举栗, 介绍语言模型 (LLM) 的微调 (LoRA SFT). 为了方便上手, 此处选择使用小模型 (qwen2…...

如何查询node inode上限是多少?

在 Linux 系统中&#xff0c;inode 上限由文件系统的类型和格式化时的参数决定。不同文件系统&#xff08;如 ext4、XFS&#xff09;有不同的查询方法。以下是详细操作步骤&#xff1a; 1. 确认文件系统类型 首先确定目标磁盘分区的文件系统类型&#xff08;如 ext4、XFS&…...

Redis核心功能实现

前言 学习是个输入的过程&#xff0c;在进行输入之后再进行一些输出&#xff0c;比如写写文章&#xff0c;笔记&#xff0c;或者做一些技术串讲&#xff0c;虽然需要花费不少时间&#xff0c;但是好处很多&#xff0c;首先是能通过输出给自己的输入带来一些动力&#xff0c;然…...

驱动学习专栏--字符设备驱动篇--1_chrdevbase

字符设备驱动简介 字符设备是 Linux 驱动中最基本的一类设备驱动&#xff0c;字符设备就是一个一个字节&#xff0c;按照字节 流进行读写操作的设备&#xff0c;读写数据是分先后顺序的。比如我们最常见的点灯、按键、 IIC 、 SPI &#xff0c; LCD 等等都是字符设备&…...

Python及C++中的列表

一、Python中的列表&#xff08;List&#xff09; Python的列表是动态数组&#xff0c;内置于语言中&#xff0c;功能强大且易用&#xff0c;非常适合算法竞赛。 1. 基本概念 定义&#xff1a;列表是一个有序、可变的序列&#xff0c;可以存储任意类型的元素&#xff08;整数…...

Oracle DROP、TRUNCATE 和 DELETE 原理

在 Oracle 11g 中&#xff0c;DROP、TRUNCATE 和 DELETE 是三种不同的数据清理操作&#xff0c;它们的底层原理和适用场景有显著差异 1. DELETE 的原理 类型&#xff1a;DML&#xff08;数据操作语言&#xff09; 功能&#xff1a;逐行删除表中符合条件的数据&#xff0c;保留…...

ida 使用记录

文章目录 伪代码-汇编hexstring快捷键 伪代码-汇编 流程图界面——F5——伪代码界面——再点Tab——流程图界面——再按空格——汇编界面流程图界面——空格——汇编界面 hex view - open subviews - hex dump string view - open subviews - string快捷键&#xff1a; sh…...

【连载3】基础智能体的进展与挑战综述

基础智能体的进展与挑战综述 从类脑智能到具备可进化性、协作性和安全性的系统 【翻译团队】刘军(liujunbupt.edu.cn) 钱雨欣玥 冯梓哲 李正博 李冠谕 朱宇晗 张霄天 孙大壮 黄若溪 2. 认知 人类认知是一种复杂的信息处理系统&#xff0c;它通过多个专门的神经回路协调运行…...

MacOs java环境配置+maven环境配置踩坑实录

oracl官网下载jdk 1.8的安装包 注意可能需要注册&#xff01;&#xff01;&#xff01; 下载链接&#xff1a;下载地址点击 注意晚上就不要下载了 报错400 &#xff01;&#xff01;&#xff01; 1.点击安装嘛 2.配置环境变量 export JAVA_HOME/Library/Java/Java…...

【Git】--- 企业级开发流程

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; Git 本篇博客我们讲解Git在企业开发中的整体流程&#xff0c;理解Git在实际企业开发中的高效设计。 &#x1f3e0; 企业级开发流程 一个软件从零开始到最…...

SAP系统客户可回收包材库存管理

问题&#xff1a;客户可回收包材库存管理 现象&#xff1a;回收瓶无库存管理&#xff0c;在库数量以及在客户的库存数量没有统计&#xff0c;管理混乱。 解决方法&#xff1a; 客户可回收包装材料在SAP有标准的解决方案&#xff0c;在集团尚未启用该业务&#xff0c;首先…...

蓝桥杯嵌入式历年省赛客观题

一.第十五届客观题 第十四届省赛 十三届 十二届...

JDK的卸载与安装

卸载JDK 删除java的1安装目录 卸载JAVA_HOME 删除path下关于java的路径 java -version查看 安装JDK 百度搜索JDK&#xff0c;找到下载地址 同意协议 下载电脑对应版本 双击安装 记住安装路径 配置环境变量 我的电脑–>右键–>属性–>高级系统设置 环境变…...

八股系列(分布式与微服务)持续更新!

八股系列&#xff08;分布式与微服务&#xff09; 分布式系统的概念 分布式系统是由多个节点组成&#xff0c;节点之间通过网络协议传递数据&#xff0c;对外表现为一个统一的整体&#xff0c;一个节点可以是一台机器或一个进程&#xff1b;分布式系统的核心功能 资源共享&…...

【源码】Mybatis源码

引言​ MyBatis 作为 Java 开发中广泛使用的持久层框架&#xff0c;其高效且灵活的数据库操作能力备受开发者青睐。在日常开发中&#xff0c;我们熟练运用 MyBatis 的各种功能来实现数据持久化&#xff0c;但深入探究其源码&#xff0c;能让我们更透彻地理解它的工作原理&#…...

解决2080Ti使用节点ComfyUI-PuLID-Flux-Enhanced中遇到的问题

使用蓝大的工作流《一键同时换头、换脸、发型、发色之双pulid技巧》 刚开始遇到的是不支持bf16的错误 根据《bf16 is only supported on A100 GPUs #33》中提到&#xff0c;修改pulidflux.py中的dtype 为 dtype torch.float16 后&#xff0c;出现新的错误&#xff0c;这个…...