为什么训练集用fit_transform()而测试集用transform()及sklearn.feature_extraction.text.CountVectorizer API详解

本文深入解析Sklearn中fit_transform与transform的区别,通过实例说明为何训练集与测试集需采用不同尺度化方法,强调参数一致性对模型泛化能力的重要性。

真正讲明白的

https://blog.youkuaiyun.com/yyhhlancelot/article/details/85097656

 

API

https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer

 

真正讲明白的博客内容

Sklearn 里面的fit transform fit_transform的区别(为什么训练集用fit_transform()而测试集用transform()?)
 yyhhlancelot 最后发布于2018-12-19 15:34:40 阅读数 1820  收藏 12
展开
在国内网上找了很多资料,感觉都说的不明不白不清不楚,很多博客都是根据原始document来进行阐述,使用的时候也是按照格式使用,最后去外网感觉终于有点搞明白了来头。

参考:

https://stackoverflow.com/questions/23838056/what-is-the-difference-between-transform-and-fit-transform-in-sklearn
https://stackoverflow.com/questions/38692520/what-is-the-difference-between-fit-transform-and-transform-in-sklearn-countvecto
https://stackoverflow.com/questions/43675665/when-scale-the-data-why-the-train-dataset-use-fit-and-transform-but-the-te
https://sebastianraschka.com/faq/docs/scale-training-test.html
推荐大家一定点进第四个去阅读一下,如果觉得英文阅读不方便,也可以看一下我接下来的解释。

首先要提及的一点,这些方法都是用来对数据进行尺度化(标准化)。

我们使用Z-score方法将数据进行正态分布化:

对训练集使用这些方法:

fit():计算数据的参数,(均值),(标准差),并存储在对象中(例如实例化的CountVectorizer()等)。
transform():将这些参数应用到数据集,进行标准化(尺度化)。
fit_transform():将前两种方法合并,fit + transform,然后对数据集使用。
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit_tranform(X_train)
sc.tranform(X_test)
不管是StandardScaler或是其他类,道理都是相通的,所以不用纠结类的问题。

这里就要提出来一个问题,为什么test数据集只使用transfrom()?

按照通俗的解释是 对测试集使用通过计算训练集相同的参数来进行尺度化,那到底是为什么呢?

下面我们用一个例子进行说明:

假设我的训练集有三个棒子的样本,它们分别是:

样本1:10cm  ---> class 2
样本2:20cm  ---> class 2
样本3:30cm  ---> class 1
通过给出的数据,我们可以算出以下参数:

mean : 20
std : 8.2
我们对数据进行标准化,得到以下:

样本1:-1.21  ---> class 2
样本2:0  ---> class 2
样本3:1.21  ---> class 1
现在我们对数据做一个假设结论,当小于0.6的就归到class 2,反之就归类到 class 1。这个假设看起来比较有意义,符合数据分布。

接下来,我们看看测试集的样本:

样本4:5cm  ---> class ?
样本5:6cm  ---> class ?
样本6:7cm  ---> class ?
这是“未标准化的”数据,如果我们不对它们进行标准化,那按我们刚刚的假设,那它们都属于class 1了?肯定不可能是吧,好的,那现在假如我们“重新”对它们计算参数,注意了,这里我们是针对测试集计算参数!

我们将测试集标准化后,得到了一下:

样本4:-1.21 
样本5:0 
样本6:1.21 
巧了,和刚刚训练集得到的一模一样。然后我们用我们刚刚训练集训练得到的结论,对它们分类:

样本4:-1.21  ---> class 2
样本5:0  ---> class 2
样本6:1.21  ---> class 1
奇怪的事情发生了,感觉不太对是吧?

那我们用训练集得到的参数对它们进行标准化呢:

样本4:-1.837
样本5:-1.715
样本6:-1.592
按我们开始的假设结论进行分类:

样本4:-1.837 ---> class 2
样本5:-1.715 ---> class 2
样本6:-1.592 ---> class 2
这下似乎看起来有意义多了,我们训练集似乎训练了一个比较说的通的模型(刚刚的假设结论~)。所以,你经常看到为什么大家在说,如果对test_data进行fit_transform()就会"overfitting"就是这么来的。
————————————————
版权声明:本文为优快云博主「yyhhlancelot」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/yyhhlancelot/article/details/85097656

<think>我们被要求解释使用CountVectorizer进行文本向量化和特征提取的Python代码。根据用户提供的引用和之前的对话历史,我们可以结合引用[1]、[2]、[3]、[4]来详细解释。 CountVectorizer是scikit-learn库中用于文本特征提取的一个工具,它将文本数据转换为词频矩阵。具体步骤如下: 1. **分词(Tokenization)**:将文本分解为单词(或标记)的过程。 2. **构建词汇表(Vocabulary)**:从所有文档中提取唯一的单词,并按照一定的顺序(默认按字母顺序)排列形成词汇表。 3. **生成词频向量**:对于每个文档,统计词汇表中每个单词出现的次数,形成一个向量。 此外,我们还可以使用TfidfTransformer将词频矩阵转换为TF-IDF矩阵,其中TF-IDF(Term Frequency-Inverse Document Frequency)是一种常用的文本表示方法,能够反映单词在文档中的重要程度。 下面我们通过一个具体的代码示例来解释: ### 示例代码 ```python from sklearn.feature_extraction.text import CountVectorizer # 示例文本数据 data = ['This is the first document.', 'This document is the second document.', 'And this is the third one.', 'Is this the first document?'] # 初始化CountVectorizer vectorizer = CountVectorizer() # 拟合数据并转换为词频矩阵 X = vectorizer.fit_transform(data) # 查看词汇表 print("词汇表:", vectorizer.get_feature_names_out()) # 输出:['and' 'document' 'first' 'is' 'one' 'second' 'the' 'third' 'this'] # 将词频矩阵转换为数组形式 print("词频矩阵:\n", X.toarray()) # 输出: # [[0 1 1 1 0 0 1 0 1] # [0 2 0 1 0 1 1 0 1] # [1 0 0 1 1 0 1 1 1] # [0 1 1 1 0 0 1 0 1]] ``` ### 代码解释 1. **初始化CountVectorizer**:可以设置一些参数,例如: - `stop_words`:移除停用词(如“is”、“the”等)。 - `ngram_range`:指定n-gram的范围,例如(1,2)表示同时考虑单个词和两个词的组合。 - `max_features`:仅考虑词频最高的前N个单词。 2. **拟合和转换**: - `fit_transform(data)`:对数据进行拟合(构建词汇表)并转换为词频矩阵。返回的是一个稀疏矩阵(为了节省内存),可以使用`toarray()`方法转换为稠密矩阵(数组形式)。 3. **生成的词频矩阵**: - 每一行代表一个文档,每一列代表词汇表中的一个单词。 - 矩阵中的值表示该单词在文档中出现的次数。 ### 结合TF-IDF 如果我们想得到TF-IDF特征,可以使用`TfidfTransformer`或者直接使用`TfidfVectorizer`(它等价于CountVectorizer加上TfidfTransformer)。 ```python from sklearn.feature_extraction.text import TfidfVectorizer tfidf_vectorizer = TfidfVectorizer() X_tfidf = tfidf_vectorizer.fit_transform(data) print("TF-IDF矩阵:\n", X_tfidf.toarray()) ``` ### 作用 通过CountVectorizer和TF-IDF转换,我们将文本数据转换成了数值向量,这些向量可以用于机器学习模型的训练,例如: - 文本分类(如垃圾邮件识别、新闻分类) - 文本聚类 - 文本相似度计算 ### 引用说明 在文本特征提取中,CountVectorizer通过计数将文档转换为向量,并生成一个存储词汇向量空间的模型[^1]。同时,我们可以通过TfidfTransformer将词频矩阵转换为TF-IDF矩阵,以更好地表示词语的重要性[^2]。这些向量化方法为后续的文本分析任务(如相似性比较、聚类、分类)奠定了基础[^3]。 ### 注意事项 - 默认情况下,CountVectorizer会按照字母顺序对词汇表进行排序,但也可以通过`vocabulary`参数自定义词汇表顺序[^2]。 - 对于中文文本,需要先进行分词(可以使用jieba等分词工具),然后将分词后的列表转换为空格分隔的字符串,再输入到CountVectorizer中。 §§相关问题§§ 1. 如何在使用CountVectorizer时移除停用词? 2. 如何自定义CountVectorizer的分词器(tokenizer)以处理中文文本? 3. 在使用TfidfVectorizer时,如何调整TF-IDF计算的公式(如使用不同的平滑方法)? 4. 如何将文本向量化后的特征用于机器学习分类任务(如朴素贝叶斯分类)?</think>### 使用CountVectorizer进行文本向量化的功能详解 `CountVectorizer`是scikit-learn库中用于文本特征提取的核心工具,它将文本数据转换为数值特征矩阵。以下是对其功能的分步解释: #### 1. **核心功能** - **词袋模型(BoW)实现**:将文本转换为词频向量 - **特征提取流程**: 1. 分词:将文本拆分为单词(token) 2. 构建词汇表:创建所有唯一单词的字典 3. 向量化:统计每个文档中各单词的出现次数 - **输出结构**:生成文档-词项矩阵(行=文档,列=单词,值=词频) #### 2. **关键参数解析** ```python from sklearn.feature_extraction.text import CountVectorizer # 基础用法 vectorizer = CountVectorizer( stop_words='english', # 移除停用词(如"the", "is") ngram_range=(1,2), # 同时提取单词和二元组 max_features=1000, # 仅保留最高频的1000个词 binary=False # False=计数模式,True=二值模式 ) ``` #### 3. **工作流程示例** ```python # 输入文本数据 [^4] corpus = [ 'This is the first document.', 'This document is the second document.', 'And this is the third one.', 'Is this the first document?' ] # 训练转换器并生成特征矩阵 X = vectorizer.fit_transform(corpus) # 查看词汇表 print(vectorizer.get_feature_names_out()) # 输出: ['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this'] # 查看特征矩阵 print(X.toarray()) """ 输出: [[0 1 1 1 0 0 1 0 1] # 第一行: "document"出现1次,"first"1次... [0 2 0 1 0 1 1 0 1] # 第二行: "document"出现2次 [1 0 0 1 1 0 1 1 1] [0 1 1 1 0 0 1 0 1]] """ ``` #### 4. **数学表示** 令$D$为文档集合,$V$为词汇表,则特征矩阵为: $$ \mathbf{X} = \begin{bmatrix} x_{11} & x_{12} & \cdots & x_{1|V|} \\ x_{21} & x_{22} & \cdots & x_{2|V|} \\ \vdots & \vdots & \ddots & \vdots \\ x_{|D|1} & x_{|D|2} & \cdots & x_{|D||V|} \end{bmatrix} $$ 其中$x_{ij}$表示文档$i$中单词$j$的出现次数。 #### 5. **下游应用** - **TF-IDF转换**:可作为`TfidfTransformer`的输入[^2] - **机器学习输入**:为分类/聚类提供特征向量[^3] - **语义分析**:结合LDA等算法进行主题建模[^1] #### 6. **与TF-IDF的关系** ```mermaid graph LR A[原始文本] --> B(CountVectorizer) B --> C[词频矩阵] C --> D(TfidfTransformer) D --> E[TF-IDF矩阵] ``` #### 7. **自定义词汇表** ```python # 使用预定义词汇表 [^2] custom_vocab = ['first', 'second', 'document'] vectorizer = CountVectorizer(vocabulary=custom_vocab) # 此时特征矩阵仅包含指定词汇 ``` ### 典型应用场景 1. 文本分类(垃圾邮件检测) 2. 信息检索(搜索引擎) 3. 文档相似度计算 4. 主题建模(LDA输入) > 关键优势:将非结构化文本转换为结构化数值特征,使传统机器学习算法能处理文本数据[^3]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值