数据挖掘(六)
数据挖掘(六)
文章目录
-
- 数据挖掘(六)
-
- 消除歧义
-
- 从Twitter下载数据
- 加载数据集并分类
- 文本转换器
-
- 词袋
- N元语法
- 其他特征
- 朴素贝叶斯
-
- 贝叶斯定理
- 朴素贝叶斯算法
- 算法应用实例
- 应用
-
- 抽取特征
- 将字典转换为矩阵
- 训练朴素贝叶斯分类器
- 组装所有的部件
- 完整代码
本文使用朴素贝叶斯进行社会媒体挖掘,消除社交媒体用语的其一。朴素贝叶斯算法在计算用于分类的概率时,为了简化计算假设各个特征之间是相互独立的,稍微扩展就能用于对其他类型数据集进行分类,且不依赖于数值特征。
消除歧义
文本称为无结构格式,虽然包含很多信息,但是却没有标题、特定格式,语法松散以及其他问题,导致难以从中提取有用信息。数据间联系紧密,行文中经常相互提及,交叉引用现象也很常见,因此从这种格式中提取信息难度很大。文本挖掘的一个难点在于歧义。
从Twitter下载数据
- 以区分Twitter消息中Python的意思为例,一条消息称为tweet,最多不能超过140个字符。“#”号经常用来表示消息的主题。实验的目的是根据消息的内容判断消息中的Python是不是编程语言。
- 从Twitter网站中下载语料,剔除垃圾信息后用于分类任务。由于访问外网的限制,数据是通过网络途径获取。
加载数据集并分类
- 消息存储格式近似于JSON,JSON格式不会对数据强加过多用于表示结构的信息,可以直接用JavaScript语言读取。JSON定义了如数字、字符串、数组、字典等基本对象,适合存储包含非数值类型的数据。如果数据集全都是数值类型,为了节省空间和事件,最好使用类似于numpy矩阵这样的格式来存储。我们的数据集和JSON对象的区别在于,每两条消息之间有一行空行,目的是防止新追加的消息和前面的消息混在一起。我们使用json库解析数据集,需要先根据空行把度进行的文件拆分成一个列表得到真正的消息对象。
import os
import json
input_filename = os.path.join(os.getcwd(), 'data_mining', 'twitter', 'python_tweets.json')
classes_filename = os.path.join(os.getcwd(), 'data_mining', 'twitter', 'python_classes.json')
replicable_dataset = os.path.join(os.getcwd(), 'data_mining', 'twitter', 'replicable_dataset.json')
# tweets列表存储从文件中读进来的每条消息
tweets =[]
with open(input_filename) as inf:
for line in inf:
if len(line.strip()) == 0:
continue
tweets.append(json.loads(line)['text'])
print('加载了%d条tweets'%len(tweets))
加载了95条tweets
- 对于像Twitter这样禁止直接分享数据集的情况,我们可以只分享消息编号,把消息编号及其类别保存下来。保存所有消息的类别很容易,遍历数据集抽取编号,然而我们无法确定以后能再次获得所有消息,因此类别和消息可能就无法对应,我们只输出实际能用到的类别。首先创建列表存储我们能再次获取到的消息的类别,然后创建字典为消息的编号和类别建立起映射关系。
tweets =[]
labels = []
with open(input_filename) as inf:
for line in inf:
if len(line.strip()) == 0:
continue
tweets.append(json.loads(line))
with open(classes_filename) as inf:
labels = json.load(inf)
dataset = [(tweet['id'], label) for tweet, label in zip(tweets, labels)]
# 把结果保存到replicable_dataset.json
with open(replicable_dataset, 'w') as outf:
json.dump(dataset, outf)
文本转换器
词袋
- 文本数据集包括图书、文章、网站、手稿、代码以及其他形式的文本,有多种测量方法可以吧文本转换成算法可以处理的形式。比如平均词长和平均句长可以用来预测文本的可读性,还有单词是否出现等。
- 一种最简单高效的模型是只统计数据集中每个单词的出现次数,我们创建一个矩阵,每行表示数据集中的一篇文档,每列代表一个词。矩阵中的每项为某个词在文档中的出现次数。
from collections import Counter
# 统计单词时通常把所有字母转换为小写
s = """She is such a charming woman, it's hard to forget""".lower()
words = s.split()
# Counter方法统计列表汇总各字符串出现次数
c = Counter(words)
# 输出出现次数最多的前5个单词
c.most_common(5)
- 词袋模型主要分为三种:第一种是使用词语实际出现次数作为词频,缺点是当文档长度差异明显时,词频差距会非常大。第二种是使用归一化后的词频,每篇文档中所有词语的词频之和为1,规避了文档长度对词频的影响。第三种是使用二值特征来表示,单词在文档中出现值为1,不出现值为0。更通用的规范化方法叫做词频逆文档频率法(tf-idf),该加权方法用词频来代替词的出现次数,然后再用词频除以包含该词的文档的数量。Python有很多用于处理文本的库,比如NLTK自然语言处理工具集库,在分词方面提供了更多选择。
N元语法
- 比起用单个词作特征,使用N元语法能更好地描述文档,N元语法指由几个连续的词组成的子序列,可以理解为每条消息里一组连续的词。N元语法的计算方法和计算单个词语方法相同,我们把构成N元语法的几个词看成是词袋中的一个词。N元语法作为特征的数据集中每一项就变成了N元语法在给定文档中的词频。
- N元语法中的参数n,对于英语而言,一开始取2到5个值就可以,有些应用可能要使用更高的值。比如说当n取3时,我们从*Always look on the bright side of life.*中抽取前几个N元语法。第一个三元语法是Always look on,第二个是look on the,第三个是on the bright。几个N元语法有重合,其中三个词有不同程度的重复。
- N元语法比起单个词的优点是不用通过大量的计算,就提供了有助于理解词语用法的上下文信息,缺点是特征矩阵变得更为稀疏。对于社交媒体所产生的的内容以及其他短文档,N元语法不可能出现在多篇不同的文档中,除非是转发。然而在长文档中,N元语法就很有效。文档的另一种N元语法关注的不是一组词而是一组字符,字符N元语法有助于发现拼写错误。
其他特征
- 除了N元语法外,还可以抽取句法特征比如特定词语在句子中的用法。对于需要理解文本含义的数据挖掘应用,往往会用到词性。
朴素贝叶斯
贝叶斯定理
- 朴素贝叶斯概率模型是对贝叶斯统计方法的朴素解释为基础的,特征类型和形式多样的数据集可以用它进行分类。从频率轮者角度出发看问题的思想,假定数据遵从某种分布,我们的目标是确定该种分布的几个参数,我们假定参数是固定的,然后用自己的模型来套用数据,甚至通过测试来证明数据与我们的模型相吻合。相反,贝叶斯统计实际上是根据普通人实际的推理方式来建模。我们用拿到的数据来更新模型对某事件即将发生的可能性的预测结果。
- 在贝叶斯统计学中,我们使用数据来描述模型,而不是使用模型来描述数据。贝叶斯定理只在计算在已知B发生的情况下,A发生的概率是多少,即P(A|B)的值。大多数情况下B是被观察事件,A是预测结果。对于数据挖掘来说,B通常是观察样本个体,A是被预测个体所属类别。
P ( A ∣ B ) = P ( B ∣ A ) P ( A ) P ( B ) P(A|B) = \frac{P(B|A)P(A)}{P(B)} P(A∣B)=P(B)P(B∣A)P(A)