分类算法(2) ---- 朴素贝叶斯算法(NB)
来源:互联网 发布:怎样撤回淘宝手机充值 编辑:程序博客网 时间:2024/06/16 22:15
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。
朴素贝叶斯分类器假设样本每个特征与其他特征都不相关。
一. 基于离散变量
下面以一个简单的数据集为例,阐述基于NB的回归/预测模型:
上述三篇文本的词列表如下:
首先可以将上述两篇训练文本(train1和train2),以及一篇测试文本(test1)转为如下向量格式:
分析:
基于NB的回归模型如何在已知train1和train2的标准答案(即公众感到“joy”的概率)分别为0.6和0.7的前提下,预测test1对应的公众感到“joy”的概率值。
为了便于模型的推导,我们将文本train1记为d1,train2记为d2,test1记为d3,情感joy记为j,词sheva记为s,词goal记为g。我们要估计的是p(d3, j),即文本test1和情感joy的联合概率值(也就是说,100名用户看到test1,会有多大的可能性将它关联到joy)。由于d3包含s和g两个词,因此要估计的p(d3, j)近似等于p(s, g, j),即词sheva、goal和情感joy的联合概率值。基于NB的回归模型利用所有的训练文本及其标准答案来估计这个值:
p(s, g, j) = p(d1, s, g, j) + p(d2, s, g, j) 概率的加法法则,
其中,p(d1, s, g, j) = p(d1, j, s, g) = p(d1, j)p(s | d1, j)p(g | d1, j, s) 概率的乘法法则,同上
上式中,p(d1, j) = 0.6;p(s | d1, j) = 0.33;p(g | d1, j, s) = 0,这里假设给定每篇文本和情感的前提下,词与词之间是独立的,也就是说p(g | d1, j, s) = p(g | d1, j) = 0。
所以,p(d1, s, g, j) = 0.6*0.33*0 = 0。
同理,p(d2, s, g, j) = 0.7*0.25*0.25 = 0.044。
所以,p(s, g, j) = 0 + 0.044 = 0.044。即,基于NB的回归模型会将test1对应的公众感到“joy”的概率值预测为0.044。
存在的问题:
(1)一个词概率为0就会得到全0结果
解决方法:拉普拉斯平滑,将乘式中所有的0用一个很小的常数代替
(2)乘积过小
下溢出解决方法:对乘积取自然对数,将相乘变为相加,计算完以后 加上一个数作补偿再做指数变换。
(这个方法更大的好处是,可以将计算过程转为非常简单的矩阵乘法)
预测结果非常小解决方法:将所有结果进行归一化, 算出所有情感值之和,取每一个值除以总和的商。
二. 基于连续变量
需要将连续变量离散化:
(1)使用相应的离散区间替换连续属性值。但是这种方法不方便控制离散区间划分的粒度。
(2)假设变量服从高斯分布,使用训练数据来估计分布的参数。
附上属性连续型代码,数据集格式为:第一行为58个属性名称,最后一个是分享值(0或1),接下来n行是训练数据集,再继续来m行是预测数据集,其share值为空。需要求出预测数据集的share预测值。
<span style="font-size:14px;">#include <bits/stdc++.h>#define train_n 27751#define test_n 11893#define feature_n 58#define pi acos(-1)#define inf 1000000using namespace std;double MAX[60],MIN[60];struct Continuous{//连续型属性 double mean[2],var[2]; //m/v[i]是share=i的均值和方差 }f[60];typedef vector<double> feature;vector <feature> text; //所有文本vector <int> shares; //测试文本的share值double p[2];// share=0/1概率 int text_n = test_n+train_n; //所有文本个数 void input(){string line;double data;int n;ifstream fin("Datac_all.csv");getline(fin, line);for(int i=0;i<text_n;i++){ getline(fin, line);istringstream ss(line);feature tmp;while (!ss.eof()){ss >> data; //忽略逗号 ss.ignore(line.size(), ',');tmp.push_back(data);}text.push_back(tmp);if(i<train_n){shares.push_back(data); if(data>0) n++;//计算share=1的个数 }}fin.close();p[1] = 1.0*n / train_n;p[0] = 1.0*(train_n-n) / train_n;cout << "The read is done\n";}void train_work()//计算均值(mean)和方差(var) {for (int i=0; i<feature_n; i++)//对每个属性 {for (int j=0; j<train_n; j++){int k = shares[j];f[i].mean[k] += text[j][i];}f[i].mean[1] /= train_n;//share=1的均值 f[i].mean[0] /= train_n;//share=0的均值 for (int j=0; j<train_n; j++){int k = shares[j];f[i].var[k] += (text[j][i]-f[i].mean[k])*(text[j][i]-f[i].mean[k]);}f[i].var[1] /= train_n;//share=1的方差 f[i].var[0] /= train_n;//share=0的方差 }cout << "The train is done\n";}double gauss_probability(int i, int j, int share)//计算概率 {double x = text[i][j];double m = f[j].mean[share];double v = f[j].var[share];return (exp(-(x-m)*(x-m)/(2*v)) / (sqrt(2*pi*v)));//高斯分布 }void predict()//进行预测 {ofstream out("NB.txt");for (int i=train_n; i<text_n; i++){double share = p[1], not_share = p[0];for (int j=0; j<feature_n; j++){share *= gauss_probability(i, j, 1);not_share *= gauss_probability(i, j, 0);}out << (share>not_share) << endl;}cout << "The predict is done\n";}int main(){input();train_work();predict();return 0;}</span>
- 分类算法(2) ---- 朴素贝叶斯算法(NB)
- 分类算法:朴素贝叶斯NB
- 朴素贝叶斯分类-NB算法
- 朴素贝叶斯算法(NB)
- Naive Bayes算法(NB算法---朴素贝叶斯)
- 朴素贝叶斯算法(分类算法)
- 朴素贝叶斯(Bayes)分类器算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 朴素贝叶斯分类算法
- 华为2016某比赛初赛, 傻X做法不能看
- 移动端应该如何动态设置字体大小?
- checkbox取值
- maven打好的jar包如何在运行时指定main-class
- 【Algorithm】 多边形+凸包+面积
- 分类算法(2) ---- 朴素贝叶斯算法(NB)
- HashTable
- mysql 练习总结
- Android Looper 分析1
- IDA Pro "Bogus or irresponsive remote server"解决方案
- 更改SQL SERVER 验证方式 (from windows to SQL SERVER)
- HTTP中的重定向和请求转发的区别
- Linux中如何查看修改系统的时间和时区
- screen 使用笔记