文本作者归属分析:从功能词到安然数据集应用
立即解锁
发布时间: 2025-08-21 01:07:22 阅读量: 2 订阅数: 3 


Python数据挖掘实战指南
### 文本作者归属分析:从功能词到安然数据集应用
#### 1. 基于功能词的分类
首先,我们需要导入所需的类。其中,支持向量机(SVM)是一个新引入的概念,后续会详细介绍,目前可将其视为一种标准分类算法。以下是导入相关类和工具的代码:
```python
from sklearn.svm import SVC
from sklearn.cross_validation import cross_val_score
from sklearn.pipeline import Pipeline
from sklearn import grid_search
```
支持向量机有多个参数,这里先盲目使用部分参数,后续再详细探讨。我们使用字典来设置要搜索的参数,对于`kernel`参数,尝试`linear`和`rbf`;对于`C`,尝试值为 1 和 10。然后创建网格搜索来寻找最佳参数组合:
```python
parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}
svr = SVC()
grid = grid_search.GridSearchCV(svr, parameters)
```
需要注意的是,高斯核(如`rbf`)仅适用于规模合理的数据集,例如特征数量少于约 10000 的情况。
接下来,我们设置一个管道,使用`CountVectorizer`(仅使用功能词)进行特征提取,并结合支持向量机的网格搜索。代码如下:
```python
pipeline1 = Pipeline([('feature_extraction', extractor),
('clf', grid)
])
```
最后,应用`cross_val_score`获取该管道的交叉验证分数,结果为 0.811,这意味着大约 80%的预测是正确的。对于 7 位作者的情况,这是一个不错的结果。
#### 2. 支持向量机原理
支持向量机(SVM)是基于简单直观思想的分类算法,它最初只能对两类进行分类(不过可扩展到多类)。假设两类数据可以用一条直线分隔,直线上方的点属于一类,下方的点属于另一类。SVM 的目标就是找到这条最佳分隔线,类似于线性回归的工作方式,但 SVM 会找到使数据集分隔效果最佳的直线。
例如,有三条分隔数据集的线(蓝色、黑色和绿色),直观上人们通常会选择蓝色线,因为它能最大程度地分隔数据,即与每类中的任何点都有最大距离。寻找这条线是一个优化问题,基于找到具有最大间隔距离的边界线。
在训练模型后,我们得到一条最大间隔线。对新样本进行分类时,只需判断它是在线上方还是下方。如果在线上方,则预测为一类;如果在线下方,则预测为另一类。
对于多类分类问题,我们会创建多个 SVM(每个都是二元分类器),并使用多种策略将它们连接起来。一种基本策略是为每个类创建一个一对多分类器,即使用给定类和所有其他样本进行训练,对每个类都这样操作,然后在新样本上运行每个分类器,选择最佳匹配结果。在大多数 SVM 实现中,这个过程会自动完成。
在之前的代码中,我们看到了两个参数:`C`和`kernel`。`C`参数是拟合 SVM 的重要参数,它关系到分类器在多大程度上要正确预测所有训练样本,同时存在过拟合的风险。选择较高的`C`值会找到间隔较小的分隔线,旨在正确分类所有训练样本;选择较低的`C`值会得到间隔较大的分隔线,即使这意味着一些训练样本会被错误分类,但这样过拟合的可能性较低,不过可能会选择一条总体上较差的分隔线。
SVM 的一个局限性是其基本形式只能分隔线性可分的数据。如果数据不是线性可分的,就需要使用核函数。
#### 3. 核函数
当数据不能线性分隔时,解决方法是将其嵌入到更高维的空间。简单来说,就是添加伪特征,直到数据变得线性可分(只要添加足够合适的特征,这总是可以实现的)。
在寻找分隔数据集的最佳直线时,我们经常会计算样本的内积。通过使用一个基于点积的函数,我们可以有效地制造新特征,而无需实际定义这些新特征,这很方便,因为我们本来也不知道这些特征是什么。现在,我们将核函数定义为数据集两个样本函数的点积,而不是基于样本本身(和虚构的特征)。
常见的核函数有多种,线性核是最直接的,它只是两个样本特征向量、权重特征和偏置值的点积;还有多项式核,它将点积提升到给定的次数(例如 2);其他包括高斯(`rbf`)和 Sigmoidal 函数。在之前的代码示例中,我们测试了线性核和`rbf`核。
这些核函数实际上定义了两个样本之间的距离,用于 SVM 对新样本的分类。理论上,可以使用任何距离,但可能不具备便于 SVM 训练优化的相同特性。在`scikit-learn`的 SVM 实现中,我们可以通过定义`kernel`参数来改变计算中使用的核函数。
#### 4. 字符 n - 元组
除了功能词,字符 n - 元组也是一种用于预测文档作者的特征类型。n - 元组是 n 个对象的序列,对于文本,n 通常在 2 到 6 之间。词 n - 元组常用于许多研究,通常与文档主题相关,而字符 n - 元组在作者归属分析中已被证明具有很高的质量。
在文本文档中,我们将文档表示为字符序列,从中提取 n - 元组并训练模型。一种标准模型与之前使用的词袋模型非常相似。对于训练语料库中的每个不同 n - 元组,我们为其创建一个特征。例如,`<e t>`是一个 n - 元组,它由字母 e、一个空格和字母 t 组成(尖括号用于表示 n - 元组的开始和结束,不属于元组本身)。然后,我们使用训练文档中每个 n - 元组的频率来训练模型,并使用创建的特征矩阵训练分类器。
字符 n - 元组有多种定义方式,有些应用只选择单词内的字符,忽略空格和标点符号;而有些则会使用这些信息。一种常见的理论解释是,人们通常会写他们容易说的单词,而字符 n - 元组(至少当 n 在 2 到 6 之间时)是音素(我们说话时发出的声音)的良好近似。从这个意义上说,使用字符 n - 元组可以近似单词的声音,进而近似写作风格。
字符 n - 元组矩阵的一个主要特点是它是稀疏的,并且随着 n 值的增加,稀疏性会迅速增加。例如,当 n = 2 时,大约 75%的特征矩阵为零;当 n = 5 时,超过 93%为零。不过,这通常比同类型的词 n - 元组矩阵稀疏性要低,使用基于词的分类器时不应会造成太多问题。
我们使用`CountVectorizer`类来提取字符 n - 元组,通过设置`analyzer`参数并指定 n 值来提取相应的 n - 元组。`scikit-learn`的实现使用 n - 元组范围,允许同时提取多种大小的 n - 元组。在本次实验中,我们不深入探讨不同的 n 值,所以将值设置为相同。要提取大小为 3 的 n - 元组,需要将 n - 元组范围指定为`(3, 3)`。
我们可以重用之前代码中的网格搜索,只需在新管道中指定新的特征提取器:
```python
pipeline = Pipeline([('feature_extraction', CountVectorizer(analyzer='char', ngram_range=(3, 3))),
('classifier', grid)
])
scores = cross_val_score(pipeline, documents, classes, scoring='f1')
print("Score: {:.3f}".format(np.mean(scores)))
```
功能词和字符 n - 元组之间存在很多隐含的重叠,因为功能词中的字符序列更有可能出现。然而,实际特征非常不同,字符 n - 元组会捕获标点符号,而功能词不会。例如,字符 n - 元组会包含句子末尾的句号,而基于功能词的方法只会使用前面的单词本身。
#### 5. 安然数据集概述
安然公司在 20 世纪 90
0
0
复制全文
相关推荐










