Naive Bayes Exercise

本文将通过朴素贝叶斯解决邮件的分类问题。理论文献参考:http://openclassroom.stanford.edu/MainFolder/DocumentPage.php?course=MachineLearning&doc=exercises/ex6/ex6.html。文章将分为三个部分,首先介绍一下基本的概率概念,然后对给出了特征的邮件进行分类,最后给出邮件特征的提取代码。

概率知识

1、概率:
表示在一系列事件(数据)中发生y 的概率。
2、条件概率:
表示给定x 后,发生y 的概率。
对于分类来说,就只有两种情况:
3、贝叶斯定理:

其中 称之为先验概率,即不需要考虑x 的影响; 表示给定x 后,发生y 的概率,故称之为y 的后验概率。
对于本实验来说,我们将用一个多项的贝叶斯公式:

其中 表示在一封垃圾邮件中给定单词是字典中第k个单词的概率;
表示在一封非垃圾邮件中给定单词是字典中第k个单词的概率;
表示训练邮件中垃圾邮件所占概率;
m 表示训练邮件的数量,第i 封邮件包含 个单词,字典中包含 个单词。

邮件分类

对于给定了特征的邮件来说,只需对训练邮件计算出垃圾邮件和非垃圾邮件对应特征的概率即可,然后通过贝叶斯公式计算出给定特征的邮件,其是垃圾邮件和非垃圾邮件的概率大小,从而确定分类。

clc, clear;

% Load the features
numTrainDocs = 700;
numTokens = 2500;
M = dlmread('train-features.txt', ' ');
spmatrix = sparse(M(:,1), M(:,2), M(:,3), numTrainDocs, numTokens); % size: numTrainDocs * numTokens
                                                                    % row: document numbers
                                                                    % col: words in dirctionary
                                                                    % element: occurrences
train_matrix = full(spmatrix);

% Load the labels for training set
train_labels = dlmread('train-labels.txt'); % i-th label corresponds to the i-th row in train_matrix

% Train
% 1. Calculate \phi_y
phi_y = sum(train_labels) ./ length(train_labels);
% 2. Calculate each \phi_k|y=1 for each dictionary word and store the all
% result in a vector
spam_index = find(1 == train_labels);
nonspam_index = find(0 == train_labels);
spam_sum = sum(train_matrix(spam_index, :));
nonspam_sum = sum(train_matrix(nonspam_index, :));
phi_k_y1 = (spam_sum + 1) ./ (sum(spam_sum) + numTokens);
phi_k_y0 = (nonspam_sum + 1) ./ (sum(nonspam_sum) + numTokens);

% Test set
test_features = dlmread('test-features.txt');
spmatrix = sparse(test_features(:,1), test_features(:,2),test_features(:,3));
test_matrix = full(spmatrix);
numTestDocs = size(test_matrix, 1);
% Calculate probability
prob_spam = log(test_matrix * phi_k_y1') + log(phi_y);
prob_nonspam = log(test_matrix * phi_k_y0') + log(1 - phi_y);
output = prob_spam > prob_nonspam;

% Read the correct labels of the test set
test_labels = dlmread('test-labels.txt');

% Compute the error on the test set
% A document is misclassified if it's predicted label is different from
% the actual label, so count the number of 1's from an exclusive "or"
numdocs_wrong = sum(xor(output, test_labels))

%Print out error statistics on the test set
error = numdocs_wrong/numTestDocs

对于网站上提供的测试文件test.m,在计算是否为垃圾邮件的概率时:
<pre name="code" class="plain">log_a = test_matrix*(log(prob_tokens_spam))' + log(prob_spam);
log_b = test_matrix*(log(prob_tokens_nonspam))'+ log(1 - prob_spam); 
 感觉不对,因为对于垃圾邮件来说,其有特征单词的概率为 
 ,即对于每一个特征单词求总的概率 
然后求对数值,应该是:
log_a = log(test_matrix * prob_tokens_spam') + log(prob_spam);
log_b = log(test_matrix * prob_tokens_nonspam')+ log(1 - prob_spam);  
不知道理解是否正确,望指教。

特征单词提取

对于自己提取邮件中的特征单词,构成字典,然后按照第二部分利用特征单词的概率对邮件进行分类。
主函数,Naive_Bayes.m
clc;clear

% This file extracts features of emails for judging whether an email is a
% spam or not.

%% Read all text files in cell variable 'data'
data = cell(0);
directory = dir('.');
numberDirect = length(directory);
for n = 3 : numberDirect
    files = dir(directory(n).name);
    numberFiles = length(files);
    for i = 3 : numberFiles
        % Be careful the path
        fid = fopen(['.\', directory(n).name, '\', files(i).name]);
        if (-1 == fid)
            fclose(fid);
            continue;
        end
        dataTemp = textscan(fid, '%s', '\n');
        fclose(fid);
        data = [data; dataTemp{1, 1}];
    end
end

%% Sort the data by alphabet.
data = sort(data);

% Count occurrences and delete duplicate words and store in a struct variable.
numberStrings = length(data);
words = struct('strings', {}, 'occurrences', 0);
numberFeature = 1;
occurrences = 1;
for i = 1 : numberStrings - 1
    if (strcmp(char(data(i)), char(data(i + 1))))
        occurrences = occurrences + 1;
    else
        words(numberFeature).strings = char(data(i));
        words(numberFeature).occurrences = occurrences;
        numberFeature = numberFeature + 1;
        occurrences = 1;
    end
end

words = struct2cell(words);
%% This is only for testing, or you can use 
% 'sortrows(cell2mat(words(2, 1, :)))' for getting the 2500 most words.
orders = ones(numberFeature - 1, 1);
for i = 2 : numberFeature - 1
    orders(i) = orders(i) + orders(i - 1);
end
features_number = cell2mat(words(2, 1, :));
features_numbers = [features_number(:), orders];

%% Get the 2500 most words to generate dictionary
features_numbers = sortrows(features_numbers);
directionary = words(:, :, features_numbers(:, 2));
directionary = directionary(1, 1, end - 2500 : end - 1);
directionary = sort(directionary(:));

%% calculate features in all folders for trainset and testset
for n = 3 : numberDirect
    files = dir(directory(n).name);
    numberFiles = length(files);
    for i = 3 : numberFiles
        fid = fopen(['.\', directory(n).name, '\', files(i).name]);
        if (-1 == fid)
            fclose(fid);
            continue;
        end
        dataTemp = textscan(fid, '%s', '\n');
        fclose(fid);
        data = dataTemp{1,1};
        feature = find_indexandcount(data, directionary);
        docnumber = (i - 2) * ones(size(feature, 1), 1);
        featrues = [docnumber, feature];
        
        if (3 == i)
            dlmwrite(['.\', directory(n).name, '\', 'features.txt'], featrues, 'delimiter', ' ');
        else
            dlmwrite(['.\', directory(n).name, '\', 'features.txt'], featrues, '-append', 'delimiter', ' ');
        end
        
    end
end

find_indexandcount.m:
function result = find_indexandcount(email, dictionary)

% This function computes words' index and count in an email by a dictionary.
numberStrings = length(email);
numberWords = length(dictionary);
count = zeros(length(dictionary), 1);
for i = 1 : numberStrings
    count = count + strcmp(email(i), dictionary);
end

% Record order sequence
orders = ones(numberWords, 1);
for i = 2 : length(dictionary) - 1
    orders(i) = orders(i) + orders(i - 1);
end

result = sortrows([orders, count], 2);

% Find words which appear more than 1 times
reserve = find(result(:, 2));
result = result(reserve, :);
end

这样就提取了所有邮件的特征单词,构成字典,并根据此字典得出训练邮件和测试邮件中,每一封邮件的特征单词在字典中的位置及出现的次数,这样转到第二步即可对测试邮件分类。下面的test.m 与步骤2的类似,不过需要将各自文件夹下的features.txt 文本文件提取出来并更改名称,放到当前工作目录下。

test.m
% train.m
% Exercise 6: Naive Bayes text classifier

clear all; close all; clc
% store the number of training examples
numTrainDocs = 350;
% store the dictionary size
numTokens = 2500;

% read the features matrix
M0 = dlmread('nonspam_features_train.txt', ' ');
M1 = dlmread('spam_features_train.txt', ' ');
nonspmatrix = sparse(M0(:,1), M0(:,2), M0(:,3), numTrainDocs, numTokens);
nonspamtrain_matrix = full(nonspmatrix);
spmatrix = sparse(M1(:,1), M1(:,2), M1(:,3), numTrainDocs, numTokens);
spamtrain_matrix = full(spmatrix);

% Calculate probability of spam
phi_y = size(spamtrain_matrix, 1) / (size(spamtrain_matrix, 1) + size(nonspamtrain_matrix, 1));
spam_sum = sum(spamtrain_matrix);
nonspam_sum = sum(nonspamtrain_matrix);
% the k-th entry of prob_tokens_spam represents phi_(k|y=1)
phi_k_y1 = (spam_sum + 1) ./ (sum(spam_sum) + numTokens);
% the k-th entry of prob_tokens_nonspam represents phi_(k|y=0)
phi_k_y0 = (nonspam_sum + 1) ./ (sum(nonspam_sum) + numTokens);

% Test set
test_features_spam = dlmread('spam_features_test.txt',' ');
test_features_nonspam = dlmread('nonspam_features_test.txt',' ');
numTestDocs = max(test_features_spam(:,1));
spmatrix = sparse(test_features_spam(:,1), test_features_spam(:,2),test_features_spam(:,3),numTestDocs, numTokens);
nonspmatrix = sparse(test_features_nonspam(:,1), test_features_nonspam(:,2),test_features_nonspam(:,3),numTestDocs,numTokens);
test_matrix = [full(spmatrix); full(nonspmatrix)];
% Calculate probability
prob_spam = log(test_matrix * phi_k_y1') + log(phi_y);
prob_nonspam = log(test_matrix * phi_k_y0') + log(1 - phi_y);
output = prob_spam > prob_nonspam;

% Compute the error on the test set
test_labels = [ones(numTestDocs, 1); zeros(numTestDocs, 1)];
wrong_numdocs = sum(xor(output, test_labels))

%Print out error statistics on the test set
error_prob = wrong_numdocs/numTestDocs

其结果如下:(分类错误的个数及概率)


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
综合小区管理系统管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、车位管理、车位分配管理、出入管理、字典管理、房屋管理、物业费缴纳管理、公告管理、物业人员投诉管理、我的私信管理、物业人员管理、用户管理、管理员管理。用户的功能包括管理部门以及部门岗位信息,管理招聘信息,培训信息,薪资信息等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 综合小区管理系统管理系统可以提高综合小区管理系统信息管理问题的解决效率,优化综合小区管理系统信息处理流程,保证综合小区管理系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理综合小区管理系统信息,包括出入管理,报修管理,报修管理,物业费缴纳等,可以管理操作员。 出入管理界面,管理员在出入管理界面中可以对界面中显示,可以对招聘信息的招聘状态进行查看,可以添加新的招聘信息等。报修管理界面,管理员在报修管理界面中查看奖罚种类信息,奖罚描述信息,新增奖惩信息等。车位管理界面,管理员在车位管理界面中新增。公告管理界面,管理员在公告管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值