白手起家学习数据科学 ——Naive Bayes之“背后的思想”(十)
来源:互联网 发布:游戏网站源码 编辑:程序博客网 时间:2024/05/21 07:14
如果人们不能互相沟通,那么社会网络就不是一个好的网络。基于此,DataSciencester网站有个大众的特点,允许用户发送消息给其他的用户。大多数用户是有责任的公民,他们只发送受欢迎的“最近好么”(how is it going?)消息,其他一些用户发送极端的垃圾邮件,关于致富方案、无需开处方的药物等,你的用户开始抱怨,所以Messaging部门的副总要求你使用数据科学找到一个方法过滤这些垃圾邮件。
无声的垃圾邮件过滤系统
S是一个”消息是垃圾邮件”事件,V是一个”包含单词viagra的消息”的事件。贝叶斯原理告诉我们,在”包含单词viagra“条件下”消息是垃圾邮件”的概率:
分子是”消息是垃圾邮件”同时”包含单词viagra消息”的概率,然而分母是”包含单词viagra消息”的概率。因此你可以简单的把这个公式看成在”包含单词viagra邮件”集合里,垃圾邮件所占的比重。
如果我们有大量知道是垃圾邮件的消息,以及大量知道是非垃圾邮件的消息,那么我们能简单的评估
例如,如果垃圾邮件50%有单词viagra,但是只有1%的非垃圾邮件有单词viagra,那么在包含单词viagra邮件的前提下,是垃圾邮件的概率是:
更加复杂的垃圾邮件过滤系统
现在设想一下我们有许多单词
朴素贝叶斯(Naive Bayes)最关键的假设是:基于已知消息是垃圾邮件或者不是的前提下,每个单词跟另外的单词是独立的。直观上,这个假设的意思是知道某个垃圾消息包含单词viagra没有给你任何信息是否同样的消息包含单词rolex,数学上表示:
这是一个极端的假设(这就是”naive”的由来)。设想一下我们的词汇表只包含单词viagra和rolex,所有垃圾消息一半是”cheap viagra”,另外一半是”authentic rolex”。这这个案例中,朴素贝叶斯评估包含”viagra”和”rolex”两者的垃圾消息是:
由于我们假定的知识”viagra”和”rolex”从来不一起出现,虽然这个假设不现实,但是这个模型常常执行的 很好并被使用在真实的垃圾过滤系统中。
同理可以推出Bayes理论用于”只有viagra”垃圾邮件过滤,我们能计算一个消息是垃圾邮件的概率:
朴素贝叶斯允许我们把计算出来的概率(单词表里每个单词)简单的一起相乘。
实际中,你通常想要避免多个概率相乘,为了避免一个叫做下溢(underflow)的问题,因为计算机不能处理一个接近于零的浮点型数据(意味着小数点后面有很多位)。回顾一下线性代数
最后的挑战就是评估P(Xi|S)和P(Xi|¬S),即在已知垃圾消息(或非垃圾消息)下包含单词wi的概率。如果我们有相当一部分”训练”消息带着标签”spam”和”nonspam”,很显然简单评估P(Xi|S)看成”spam”消息集中单词wi占的比例。
但是这引起了一个大的问题,设想一下,在我们的训练集上词汇表中”data”单词只出现在非垃圾消息中,那么我们评估
尤其,我们将选择pseudocount—k,评估在spam条件下第i个单词的概率:
例如,在spam条件下,如果”data”发生了0/98(98个spam,有0个包含单词”data”),并且如果k为1,我们评估
实施(Implementation)
现在我们有了所有技术,我们需要建立我们的分类器。首先,让我们创建一个简单的函数,把所有消息切分成不同的单词。把每个消息转换成小写,然后利用
def tokenize(message): message = message.lower() # convert to lowercase all_words = re.findall("[a-z0-9']+", message) # extract the words return set(all_words) # remove duplicates
我们的第二个函数对带有标签的训练集进行计数,它会返回一个字典,其key为单词,value为一个带有2个元素的list [spam_count, non_spam_count],对应在spam和nonspam消息中key出现的次数:
def count_words(training_set): """training set consists of pairs (message, is_spam)""" counts = defaultdict(lambda: [0, 0]) for message, is_spam in training_set: for word in tokenize(message): counts[word][0 if is_spam else 1] += 1 return counts
接下来的步骤是把这些计数转换成概率,这些概率利用我们之前描述的平滑操作,我们的函数会返回一个list,其每行是包含3个元素的tuple,这3个元素分别为单词;spam消息下的单词概率;nonspam消息下的单词概率:
def word_probabilities(counts, total_spams, total_non_spams, k=0.5): """turn the word_counts into a list of triplets w, p(w | spam) and p(w | ~spam)""" return [(w, (spam + k) / (total_spams + 2 * k), (non_spam + k) / (total_non_spams + 2 * k)) for w, (spam, non_spam) in counts.iteritems()]
最后一步是使用这些单词概率(以及我们的朴素贝叶斯假设)为这些消息计算概率:
def spam_probability(word_probs, message): message_words = tokenize(message) log_prob_if_spam = log_prob_if_not_spam = 0.0 # iterate through each word in our vocabulary for word, prob_if_spam, prob_if_not_spam in word_probs: # if *word* appears in the message, # add the log probability of seeing it if word in message_words: log_prob_if_spam += math.log(prob_if_spam) log_prob_if_not_spam += math.log(prob_if_not_spam) # if *word* doesn't appear in the message # add the log probability of _not_ seeing it # which is log(1 - probability of seeing it) else: log_prob_if_spam += math.log(1.0 - prob_if_spam) log_prob_if_not_spam += math.log(1.0 - prob_if_not_spam) prob_if_spam = math.exp(log_prob_if_spam) prob_if_not_spam = math.exp(log_prob_if_not_spam) return prob_if_spam / (prob_if_spam + prob_if_not_spam)
我们把这些连接起来组成Naive Bayes Classifier:
class NaiveBayesClassifier: def __init__(self, k=0.5): self.k = k self.word_probs = [] def train(self, training_set): # count spam and non-spam messages num_spams = len([is_spam for message, is_spam in training_set if is_spam]) num_non_spams = len(training_set) - num_spams # run training data through our "pipeline" word_counts = count_words(training_set) self.word_probs = word_probabilities(word_counts, num_spams, num_non_spams, self.k) def classify(self, message): return spam_probability(self.word_probs, message)
下一章节我们将要测试模型。
- 白手起家学习数据科学 ——Naive Bayes之“背后的思想”(十)
- 白手起家学习数据科学 ——Naive Bayes之“测试模型篇”(十)
- 白手起家学习数据科学 ——梯度下降法之“背后的思想”(六)
- 白手起家学习数据科学 ——k-Nearest Neighbors之“背后的思想”(九)
- 白手起家学习数据科学 ——Probability之“Bayes's 原理和随机变量篇”(四)
- 数据挖掘十大算法——Naive Bayes
- 白手起家学习数据科学 ——处理数据之“数据探索篇”(七)
- 白手起家学习数据科学 ——处理数据之“数据清洗与再处理篇”(七)
- 白手起家学习数据科学 ——处理数据之“操纵数据篇”(七)
- 白手起家学习数据科学 ——可视化数据(一)
- 白手起家学习数据科学 ——处理数据之“尺度变换篇”(七)
- 数据挖掘十大经典算法学习之Naive Bayes朴素贝叶斯
- 数据挖掘十大经典算法学习之Naive Bayes朴素贝叶斯
- 白手起家学习数据科学 ——线性代数之“Vectors篇”(二)
- 白手起家学习数据科学 ——线性代数之“Matrices篇”(二)
- 白手起家学习数据科学 ——Statistics之“中心趋向和离散度篇”(三)
- 白手起家学习数据科学 ——Statistics之“相关性和辛普森悖论篇”(三)
- 白手起家学习数据科学 ——Probability之“独立事件和条件概率篇”(四)
- bluedroid acl 发送和接受
- 利用aapt解析apk文件
- robot framework总结
- android-activity之启动模式singleInstance
- v$sqlarea
- 白手起家学习数据科学 ——Naive Bayes之“背后的思想”(十)
- MySQL InnoDB 锁表与锁行
- WebRTC One-Way video sharing/broadcasting / Demo
- TTreeView customSort 实现 自定义排序
- 嵌入式Linux中SQLITE数据库的应用
- VC中Unicode字符集转UTF-8字符集
- Ext.js5表单—即时查询(结合Ext.Template和远程数据)(52)
- ifconfig找不到命令
- Mysql 存储过程基本语法