700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 朴素贝叶斯--过滤垃圾邮件实例

朴素贝叶斯--过滤垃圾邮件实例

时间:2018-08-19 08:12:47

相关推荐

朴素贝叶斯--过滤垃圾邮件实例

使用朴素贝叶斯解决一些现实生活中的问题时,需要先从文本内容得到字符串列表,然后生成词向量。下面这个例子中,我们将了解朴素贝叶斯的一个最著名的应用:电子邮件垃圾过滤。

数据集下载

1. 准备数据

import re"""函数说明:接收一个大字符串并将其解析为字符串列表Parameters:无Returns:无"""def textParse(bigString): #将字符串转换为字符列表listOfTokens = re.split(r'\W*', bigString)#将特殊符号作为切分标志进行字符串切分,即非字母、非数字return [tok.lower() for tok in listOfTokens if len(tok) > 2] #除了单个字母,例如大写的I,其它单词变成小写"""函数说明:将切分的实验样本词条整理成不重复的词条列表,也就是词汇表Parameters:dataSet - 整理的样本数据集Returns:vocabSet - 返回不重复的词条列表,也就是词汇表"""def createVocabList(dataSet):vocabSet = set([]) #创建一个空的不重复列表for document in dataSet:vocabSet = vocabSet | set(document) #取并集return list(vocabSet)if __name__ == '__main__':docList = []; classList = []for i in range(1, 26):#遍历25个txt文件wordList = textParse(open('email/spam/%d.txt' % i, 'r').read())#读取每个垃圾邮件,并字符串转换成字符串列表docList.append(wordList)classList.append(1) #标记垃圾邮件,1表示垃圾文件wordList = textParse(open('email/ham/%d.txt' % i, 'r').read())#读取每个非垃圾邮件,并字符串转换成字符串列表docList.append(wordList)classList.append(0) #标记非垃圾邮件,1表示垃圾文件 vocabList = createVocabList(docList)#创建词汇表,不重复print(vocabList)

运行结果:

['eugene', 'biggerpenis', 'was', 'endorsed', 'starting', 'improving', 'life', 'ideas', 'drunk', 'door', 'wednesday', 'docs', 'genuine', 'inform', '588', 'welcome','location', 'scenic', 'try', 'assigning', 'incredib1e', 'order', 'survive', 'fine', 'ups', 'view', 'know', 'monte', 'phentermin', 'julius', 'located', 'either', '300x', 'shape', 'food', 'gas', 'program', 'permanantly', 'may', 'now', 'borders', 'based', 'for', 'brand', 'inside', 'money', 'trusted', 'both', 'cold', 'ferguson', 'should', 'dozen', 'magazine', 'must', 'attaching', 'past', 'jpgs', 'watchesstore', 'bin', 'scifinance', '562', 'questions', 'said', 'reply', 'worldwide', 'jocelyn', 'serial', 'don', 'link', 'management', 'about', 'freeviagra', 'visa', 'night', 'hours', 'uses', 'wallets', 'does', 'cannot', 'would', 'your', '100', 'designed', 'pharmacy', 'grow', 'been', 'products', 'warranty', 'reliever', 'earn', 'but', 'noprescription', 'groups', 'inconvenience', 'runs', 'are', 'windows', 'being', 'recieve', 'intenseorgasns', 'zolpidem', 'phone', 'lunch', 'express', 'today', 'guy', 'cost', 'time', 'announcement', 'hope', 'linkedin', 'want', '', 'drugs', '138', '86152', 'learn', 'wilmott', 'opioid', 'arolexbvlgari', 'town', 'rain', 'launch', 'such', 'changes', 'business', 'keep', 'ma1eenhancement', 'having', 'safe', 'mailing', 'address', '325', 'web', 'tickets', 'development', 'aged', 'selected', 'tabs', 'regards', 'rent', 'jay', 'girl', 'this', 'spaying', 'couple', 'cartier', 'work', 'source', 'needed', 'significantly', 'far', 'moderate', 'creation', 'turd', 'series', 'huge', 'amazing', 'softwares', 'full', 'gucci', 'cheers', 'bathroom', 'high', 'what', 'ordercializviagra', 'dhl', 'will', 'louis', 'job', 'museum', 'buyviagra', 'individual', 'jewerly', 'online', 'logged', 'certified', '5mg', 'others', 'whybrew', 'they', 'credit', '174623', 'natural', 'out', 'one', 'increase', 'february', 'required', 'top', 'once', 'safest', '30mg', 'courier', 'discount', 'network', 'went', 'sophisticated', 'bettererections', 'you', 'sorry', 'those', 'moderately', 'decision', 'update', 'pro', 'received', 'art', 'told', 'forum', 'thanks', 'financial', 'edit', 'computing', 'millions', 'code', 'had', 'school', 'haloney', 'way', 'how', '195', 'severepain', 'pick', 'yesterday', 'create', 'well', 'cat', 'vicodin', 'station', 'ones', 'chapter', 'competitive', '291', 'site', 'concise', 'strategy', 'york', 'tour', 'who', '15mg', 'inches', 'jar', 'status', 'oem', 'storage', 'good', 'private', 'team', 'supporting', 'tool', 'office', 'butt', 'email', 'accepted', 'below', 'quantitative', 'coast', 'inspired', 'knocking', 'cuda', '66343', '129', 'running', 'finder', 'ryan', 'that', 'exhibit', 'horn', '366', 'requested', 'explosive', 'right', 'shipping', 'another', 'incoming', 'answer', 'codeine', 'supplement', 'strategic', 'computer', 'think', 'works', 'discussions', 'service', '10mg', 'experts', 'wilson', 'generation', 'mom', 'issues', '203', 'father', 'instead', '292', 'arvind', 'bags', '', 'notification', 'python', 'there', 'assistance', 'longer', 'yourpenis', 'interesting', 'follow', 'mandelbrot', 'heard', 'enjoy', 'could', 'automatic', 'cards', 'check', 'nvidia', 'file', 'things', 'carlo', 'color', 'level', 'message', '625', 'come', 'please', 'functionalities', 'store', 'pavilion', 'viagranoprescription', 'each', 'generates', 'mandatory', 'control', 'thank', 'used', 'dior', 'copy', 'capabilities', 'find', 'commented', '', 'care', 'them', 'superb', 'enough', 'invitation', 'let', 'take', 'game', 'sure', 'expo', 'great', 'focus', 'wrote', 'watches', 'talked', 'approved', 'can', 'plane', 'chance', 'shipment', 'bad', 'writing', 'winter', 'treat', 'hommies', 'sounds', 'brands', 'help', 'behind', 'doing', 'methods', 'google', 'chinese', 'focusing', 'analgesic', 'possible', 'oris', 'window', 'items', 'ready', 'important', 'buy', 'information', '50092', 'amex', 'hermes', 'lined', 'speedpost', 'jqplot', 'prototype', 'thickness', 'back', 'differ', 'automatically', 'book', 'pages', 'bargains', 'hydrocodone', 'some', 'pictures', 'thirumalai', 'design', 'since', 'foaming', 'trip', 'knew', 'much', 'modelling', '1924', 'dusty', 'gain', 'germany', 'wholesale', 'effective', 'john', 'yeah', 'just', 'accept', 'ambiem', 'meet', 'quality', 'hotels', 'everything', 'tesla', 'kerry', 'favorite', 'pricing', 'thread', 'volume', 'titles', 'experience', 'gpu', 'troy', 'made', 'website', 'stuff', 'major', '430', 'saw', 'free', 'holiday', 'specifically', 'blue', '50mg', 'page', 'lists', 'contact', 'jose', 'doctor', 'discreet', 'customized', 'ultimate', '130', 'got', 'fractal', 'length', 'stepp', 'close', 'add', 'fedex', 'has', 'doors', 'nature', 'see', 'storedetailview_98', '14th', 'pretty', 'don抰', 'new', '180', 'rude', 'use', 'signed', 'creative', 'brandviagra', 'jquery', 'model', 'car', 'also', 'more', 'rock', 'example', '513', 'cheap', 'per', '119', 'using', 'riding', 'sky', '492', 'sent', 'expertise', 'photoshop', 'might', 'pills', '90563', 'price', 'mba', 'tokyo', 'advocate', 'enabled', 'fans', '199', 'class', 'because', 'held', 'acrobat', 'you抮e', 'hangzhou', 'died', 'thing', 'success', 'placed', '570', 'support', 'thought', 'hotel', 'low', 'glimpse', 'fermi', 'of_penisen1argement', 'members', 'have', 'definitely', 'style', 'mathematician', 'hold', 'via', 'get', 'upload', 'china', 'files', 'articles', 'place', 'need', 'easily', 'giants', 'all', 'group', 'going', 'working', 'through', 'benoit', 'his', '322', 'retirement', 'often', 'vuitton', 'net', 'the', 'approach', 'from', 'party', 'insights', 'doggy', 'peter', 'reservation', 'tiffany', 'canadian', '200', 'connection', 'ofejacu1ate', 'forward', 'thailand', 'wasn', 'grounds', 'income', 'includes', 'watson', 'access', '120', 'changing', 'days', 'not', '0nline', 'item', 'year', 'core', 'when', 'programming', 'over', '100m', 'then', 'specifications', 'gains', 'looking', 'cs5', 'any', 'name', 'day', 'featured', '750', 'call', 'cats', 'guaranteeed', 'harderecetions', 'faster', 'came', 'mathematics', 'pls', 'fast', 'off', 'moneyback', 'transformed', 'release', 'proven', 'done', 'naturalpenisenhancement', 'risk', '396', 'bike', 'note', 'leaves', 'zach', 'adobe', 'betterejacu1ation', 'most', 'femaleviagra', 'home', 'opportunity', 'fundamental', 'encourage', 'yay', 'parallel', 'province', 'plus', 'same', 'vivek', 'listed', 'sliding', 'cca', 'withoutprescription', 'while', 'too', 'prices', 'methylmorphine', 'plugin', '156', 'brained', 'hamm', 'download', 'prepared', 'extended', 'features', 'mandarin', 'tent', 'roofer', 'october', 'www', 'sites', 'fbi', 'only', 'famous', 'away', 'number', 'train', 'where', '225', 'two', 'reputable', 'pill', 'share', 'herbal', 'ems', 'http', 'mail', 'least', '100mg', 'and', 'latest', 'narcotic', 'percocet', 'hello', 'than', 'professional', 'comment', 'thousand', 'like', 'suggest', 'pain', 'derivatives', '25mg', 'com', '219', 'finance', 'perhaps', 'with', 'fda', 'these', 'here', 'microsoft', 'save', 'owner', 'delivery', '385']

2.根据词汇表,我们就可以将每个文本向量化。我们将数据集分为训练集和测试集,使用交叉验证的方式测试朴素贝叶斯分类器的准确性。编写代码如下:

import numpy as npimport randomimport re"""函数说明:将切分的实验样本词条整理成不重复的词条列表,也就是词汇表Parameters:dataSet - 整理的样本数据集Returns:vocabSet - 返回不重复的词条列表,也就是词汇表"""def createVocabList(dataSet):vocabSet = set([]) #创建一个空的不重复列表for document in dataSet:vocabSet = vocabSet | set(document) #取并集return list(vocabSet)"""函数说明:根据vocabList词汇表,将inputSet向量化,向量的每个元素为1或0Parameters:vocabList - createVocabList返回的列表inputSet - 切分的词条列表Returns:returnVec - 文档向量,词集模型"""def setOfWords2Vec(vocabList, inputSet):returnVec = [0] * len(vocabList)#创建一个其中所含元素都为0的向量for word in inputSet: #遍历每个词条if word in vocabList: #如果词条存在于词汇表中,则置1returnVec[vocabList.index(word)] = 1else: print("the word: %s is not in my Vocabulary!" % word)return returnVec #返回文档向量"""函数说明:根据vocabList词汇表,构建词袋模型Parameters:vocabList - createVocabList返回的列表inputSet - 切分的词条列表Returns:returnVec - 文档向量,词袋模型"""def bagOfWords2VecMN(vocabList, inputSet):returnVec = [0]*len(vocabList)#创建一个其中所含元素都为0的向量for word in inputSet: #遍历每个词条if word in vocabList: #如果词条存在于词汇表中,则计数加一returnVec[vocabList.index(word)] += 1return returnVec #返回词袋模型"""函数说明:朴素贝叶斯分类器训练函数Parameters:trainMatrix - 训练文档矩阵,即setOfWords2Vec返回的returnVec构成的矩阵trainCategory - 训练类别标签向量,即loadDataSet返回的classVecReturns:p0Vect - 侮辱类的条件概率数组p1Vect - 非侮辱类的条件概率数组pAbusive - 文档属于侮辱类的概率"""def trainNB0(trainMatrix,trainCategory):numTrainDocs = len(trainMatrix) #计算训练的文档数目numWords = len(trainMatrix[0]) #计算每篇文档的词条数pAbusive = sum(trainCategory)/float(numTrainDocs) #文档属于侮辱类的概率p0Num = np.ones(numWords); p1Num = np.ones(numWords) #创建numpy.ones数组,词条出现数初始化为1,拉普拉斯平滑p0Denom = 2.0; p1Denom = 2.0 #分母初始化为2,拉普拉斯平滑for i in range(numTrainDocs):if trainCategory[i] == 1: #统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···p1Num += trainMatrix[i]p1Denom += sum(trainMatrix[i])else: #统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···p0Num += trainMatrix[i]p0Denom += sum(trainMatrix[i])p1Vect = np.log(p1Num/p1Denom) #取对数,防止下溢出 p0Vect = np.log(p0Num/p0Denom) return p0Vect,p1Vect,pAbusive #返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率"""函数说明:朴素贝叶斯分类器分类函数Parameters:vec2Classify - 待分类的词条数组p0Vec - 侮辱类的条件概率数组p1Vec -非侮辱类的条件概率数组pClass1 - 文档属于侮辱类的概率Returns:0 - 属于非侮辱类1 - 属于侮辱类"""def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):p1 = sum(vec2Classify * p1Vec) + np.log(pClass1) #对应元素相乘。logA * B = logA + logB,所以这里加上log(pClass1)p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)if p1 > p0:return 1else:return 0"""函数说明:朴素贝叶斯分类器训练函数Parameters:trainMatrix - 训练文档矩阵,即setOfWords2Vec返回的returnVec构成的矩阵trainCategory - 训练类别标签向量,即loadDataSet返回的classVecReturns:p0Vect - 侮辱类的条件概率数组p1Vect - 非侮辱类的条件概率数组pAbusive - 文档属于侮辱类的概率"""def trainNB0(trainMatrix,trainCategory):numTrainDocs = len(trainMatrix) #计算训练的文档数目numWords = len(trainMatrix[0]) #计算每篇文档的词条数pAbusive = sum(trainCategory)/float(numTrainDocs) #文档属于侮辱类的概率p0Num = np.ones(numWords); p1Num = np.ones(numWords) #创建numpy.ones数组,词条出现数初始化为1,拉普拉斯平滑p0Denom = 2.0; p1Denom = 2.0 #分母初始化为2,拉普拉斯平滑for i in range(numTrainDocs):if trainCategory[i] == 1: #统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···p1Num += trainMatrix[i]p1Denom += sum(trainMatrix[i])else: #统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···p0Num += trainMatrix[i]p0Denom += sum(trainMatrix[i])p1Vect = np.log(p1Num/p1Denom) #取对数,防止下溢出 p0Vect = np.log(p0Num/p0Denom) return p0Vect,p1Vect,pAbusive #返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率"""函数说明:接收一个大字符串并将其解析为字符串列表Parameters:无Returns:无"""def textParse(bigString): #将字符串转换为字符列表listOfTokens = re.split(r'\W*', bigString)#将特殊符号作为切分标志进行字符串切分,即非字母、非数字return [tok.lower() for tok in listOfTokens if len(tok) > 2] #除了单个字母,例如大写的I,其它单词变成小写"""函数说明:测试朴素贝叶斯分类器Parameters:无Returns:无"""def spamTest():docList = []; classList = []; fullText = []for i in range(1, 26):#遍历25个txt文件wordList = textParse(open('email/spam/%d.txt' % i, 'r').read())#读取每个垃圾邮件,并字符串转换成字符串列表docList.append(wordList)fullText.append(wordList)classList.append(1) #标记垃圾邮件,1表示垃圾文件wordList = textParse(open('email/ham/%d.txt' % i, 'r').read())#读取每个非垃圾邮件,并字符串转换成字符串列表docList.append(wordList)fullText.append(wordList)classList.append(0) #标记非垃圾邮件,1表示垃圾文件 vocabList = createVocabList(docList)#创建词汇表,不重复trainingSet = list(range(50)); testSet = [] #创建存储训练集的索引值的列表和测试集的索引值的列表 for i in range(10): #从50个邮件中,随机挑选出40个作为训练集,10个做测试集randIndex = int(random.uniform(0, len(trainingSet)))#随机选取索索引值testSet.append(trainingSet[randIndex])#添加测试集的索引值del(trainingSet[randIndex]) #在训练集列表中删除添加到测试集的索引值trainMat = []; trainClasses = []#创建训练集矩阵和训练集类别标签系向量 for docIndex in trainingSet: #遍历训练集trainMat.append(setOfWords2Vec(vocabList, docList[docIndex])) #将生成的词集模型添加到训练矩阵中trainClasses.append(classList[docIndex]) #将类别添加到训练集类别标签系向量中p0V, p1V, pSpam = trainNB0(np.array(trainMat), np.array(trainClasses)) #训练朴素贝叶斯模型errorCount = 0 #错误分类计数for docIndex in testSet: #遍历测试集wordVector = setOfWords2Vec(vocabList, docList[docIndex]) #测试集的词集模型if classifyNB(np.array(wordVector), p0V, p1V, pSpam) != classList[docIndex]: #如果分类错误errorCount += 1 #错误计数加1print("分类错误的测试集:",docList[docIndex])print('错误率:%.2f%%' % (float(errorCount) / len(testSet) * 100))if __name__ == '__main__':spamTest()

运行结果1:

分类错误的测试集: ['oem', 'adobe', 'microsoft', 'softwares', 'fast', 'order', 'and', 'download', 'microsoft', 'office', 'professional', 'plus', '', '', '129', 'microsoft', 'windows', 'ultimate', '119', 'adobe', 'photoshop', 'cs5', 'extended', 'adobe', 'acrobat', 'pro', 'extended', 'windows', 'professional', 'thousand', 'more', 'titles']分类错误的测试集: ['home', 'based', 'business', 'opportunity', 'knocking', 'your', 'door', 'don抰', 'rude', 'and', 'let', 'this', 'chance', 'you', 'can', 'earn', 'great', 'income', 'and', 'find', 'your', 'financial', 'life', 'transformed', 'learn', 'more', 'here', 'your', 'success', 'work', 'from', 'home', 'finder', 'experts']错误率:20.00%

运行结果2:

分类错误的测试集: ['home', 'based', 'business', 'opportunity', 'knocking', 'your', 'door', 'don抰', 'rude', 'and', 'let', 'this', 'chance', 'you', 'can', 'earn', 'great', 'income', 'and', 'find', 'your', 'financial', 'life', 'transformed', 'learn', 'more', 'here', 'your', 'success', 'work', 'from', 'home', 'finder', 'experts']错误率:10.00%

运行结果3:

错误率:0.00%

函数spamTest()会输出在10封随机选择的电子邮件上的分类错误概率。既然这些电子邮件是随机选择的,所以每次的输出结果可能有些差别。如果发现错误的话,函数会输出错误的文档的此表,这样就可以了解到底是哪篇文档发生了错误。如果想要更好地估计错误率,那么就应该将上述过程重复多次,比如说10次,然后求平均值。相比之下,将垃圾邮件误判为正常邮件要比将正常邮件归为垃圾邮件好。为了避免错误,有多种方式可以用来修正分类器。

参考博客:/

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。