看了原理和比人的代码后,终于自己写了一个EM的实现。

我从网上找了一些身高性别的数据,用EM算法通过身高信息来识别性别。

实现的效果还行,正确率有84% (初始数据 男生170 女生160 方差都是10)

79%  (初始数据 男生165 女生150 方差都是10)

正确率与初始值有关。

/*
试图用EM算法来根据输入的身高来区分性别
*/ #include<iostream>
#include<fstream>
#include<algorithm>
#include<vector>
using namespace std; #define PI 3.14159
#define max(x,y) (x > y ? x : y) typedef struct FLOAT2
{
float f1;
float f2;
}FLOAT2;
typedef struct Gaussian
{
float mean;
float var;
}Gaussian; typedef struct EMData
{
char sex;
float fHeight;
}EMData; //获取身高性别数据
int getdata(vector<EMData> &Data)
{
ifstream fin;
fin.open("data.txt");
if(!fin)
{
cout<<"error: can't open the file."<<endl;
return -;
} while(!fin.eof())
{
char c[];
float height;
fin >> c >> height;
EMData data;
data.sex = c[];
data.fHeight = height;
Data.push_back(data);
} return ;
} //根据身高数据区分性别, 返回正确率
float predict(vector<EMData> Data)
{
//设符合正态分布
Gaussian sex[];
float a[]; //男女生所占百分比
float t = ;
float tlimit = 0.000001; //收敛条件 //赋初值 下标0表示男生 1表示女生
sex[].mean = 180.0;
sex[].var = 10.0;
sex[].mean = 150.0;
sex[].var = 10.0;
a[] = 0.5;
a[] = 0.5; while(t > tlimit)
{
Gaussian sex_old[];
float a_old[];
sex_old[] = sex[];
sex_old[] = sex[];
a_old[] = a[];
a_old[] = a[]; //计算每个样本分别被两个模型抽中的概率
vector<FLOAT2> px; vector<EMData>::iterator it;
for(it = Data.begin(); it < Data.end(); it++)
{
FLOAT2 p;
p.f1 = /(sqrt( * PI * sex[].var)) * exp(-(it->fHeight - sex[].mean) * (it->fHeight - sex[].mean) / ( * sex[].var));
p.f2 = /(sqrt( * PI * sex[].var)) * exp(-(it->fHeight - sex[].mean) * (it->fHeight - sex[].mean) / ( * sex[].var));
px.push_back(p);
} //E步
//计算每个样本属于男生或女生的概率
vector<FLOAT2>::iterator it2;
for(it2 = px.begin(); it2 < px.end(); it2++)
{
float sum = 0.0;
(*it2).f1 *= a[];
sum += (*it2).f1;
(*it2).f2 *= a[];
sum += (*it2).f2; (*it2).f1 = (*it2).f1/sum;
(*it2).f2 = (*it2).f2/sum;
} //M步
float sum_male = , sum_female = ;
float sum_mean_male = , sum_mean_female = ;
for(it2 = px.begin(), it = Data.begin(); it2 < px.end(); it2++, it++)
{
sum_male += (*it2).f1;
sum_female += (*it2).f2;
sum_mean_male += (*it2).f1 * (it->fHeight);
sum_mean_female += (*it2).f2 * (it->fHeight);
}
//更新a
a[] = sum_male/(sum_male + sum_female);
a[] = sum_female/(sum_male + sum_female); //更新均值
sex[].mean = sum_mean_male/ sum_male;
sex[].mean = sum_mean_female/ sum_female; //更新方差
float sum_var_male = , sum_var_female = ;
for(it2 = px.begin(), it = Data.begin(); it2 < px.end(); it2++, it++)
{
sum_var_male += (*it2).f1 * ((it->fHeight) - sex[].mean) * ((it->fHeight) - sex[].mean);
sum_var_female += (*it2).f2 * ((it->fHeight) - sex[].mean) * ((it->fHeight) - sex[].mean);
}
sex[].var = sum_var_male / sum_male;
sex[].var = sum_var_female / sum_female; //计算变化率
t = max((a[] - a_old[])/a_old[], (a[] - a_old[])/a_old[]);
t = max(t, (sex[].mean - sex_old[].mean)/sex_old[].mean);
t = max(t, (sex[].mean - sex_old[].mean)/sex_old[].mean);
t = max(t, (sex[].var - sex_old[].var)/sex_old[].var);
t = max(t, (sex[].var - sex_old[].var)/sex_old[].var);
} //计算正确率
int correct_num = ;
float correct_rate = ;
vector<EMData>::iterator it;
for(it = Data.begin(); it < Data.end(); it++)
{
float p[];
char csex;
for(int i = ; i < ; i++)
{
p[i] = /(sqrt( * PI * sex[i].var)) * exp(-(it->fHeight - sex[i].mean) * (it->fHeight - sex[i].mean) / ( * sex[i].var));
} csex = (p[] > p[]) ? 'm' : 'f';
if(csex == it->sex)
correct_num++;
} correct_rate = (float)correct_num / Data.size();
return correct_rate;
} int main()
{
vector<EMData> Data;
getdata(Data);
float correct_rate = predict(Data);
cout << "correct rate = "<< correct_rate << endl;
return ;
}

数据:data.txt内容

male    164
female 156
male 168
female 160
female 162
male 187
female 162
male 167
female 160.5
female 160
female 158
female 164
female 165
male 174
female 166
female 158
male 162
male 175
male 170
female 161
female 169
female 161
female 160
female 167
male 176
male 169
male 178
male 165
female 155
male 183
male 171
male 179
female 154
male 172
female 172
male 173
male 172
male 175
male 160
male 160
male 160
male 175
male 163
male 181
male 172
male 175
male 175
male 167
male 172
male 169
male 172
male 175
male 172
male 170
male 158
male 167
male 164
male 176
male 182
male 173
male 176
male 163
male 166
male 162
male 169
male 163
male 163
male 176
male 169
male 173
male 163
male 167
male 176
male 168
male 167
male 170
female 155
female 157
female 165
female 156
female 155
female 156
female 160
female 158
female 162
female 162
female 155
female 163
female 160
female 162
female 165
female 159
female 147
female 163
female 157
female 160
female 162
female 158
female 155
female 165
female 161
female 159
female 163
female 158
female 155
female 162
female 157
female 159
female 152
female 156
female 165
female 154
female 156
female 162

【EM】C++代码实现的更多相关文章

  1. 【EM】代码理解

    本来想自己写一个EM算法的,但是操作没两步就进行不下去了.对那些数学公式着实不懂.只好从网上找找代码,看看别人是怎么做的. 代码:来自http://blog.sina.com.cn/s/blog_98 ...

  2. CSS中rem、em的区别

    引用文档:http://www.divcss5.com/html/h529.shtml:http://blog.csdn.net/qq_35432904/article/details/5180422 ...

  3. 把pcl的VTK显示融合到MFC(代码找原作者)

    转自PCL中国,原文链接:http://www.pclcn.org/bbs/forum.php?mod=viewthread&tid=223&extra=page%3D1 本人做了少量 ...

  4. 代码覆盖率工具 EMMA

    使用 EMMA 获得功能测试覆盖率 测试覆盖率是评价测试完整性的重要的度量标准之一. EMMA 是一个面向 Java 代码的测试覆盖率收集工具.在测试过程中,使用 EMMA 能使收集和报告测试覆盖率的 ...

  5. border-radius 圆角半径

    CSS3属性之一:border-radius 语法: border-radius : none | <length>{1,4} [ / <length>{1,4} ]? 相关属 ...

  6. CSS3属性之一:border-radius

    语法: border-radius : none | <length>{1,4} [ / <length>{1,4} ]? 相关属性: border-top-right-rad ...

  7. Source Insight设置总结

    在网上搜索了一些关于Source Insight的设置技巧,把这些结果给总结下来: 1. 背景色选择 要改变背景色Options->preference->windows backgrou ...

  8. web CSS的知识- 关于后代选择器,子选择器,兄弟选择器的使用

    1. 后代选择器官方解释:后代选择器可以选择作为某元素后代的元素.理解:选择某一标签的后代中,所有的此标签标记例:ul em {color:red;}就是选择,h1标签后代中中,所有的em.代码如下: ...

  9. light oj 1236 - Pairs Forming LCM & uva 12546 - LCM Pair Sum

    第一题给定一个大数,分解质因数,每个质因子的个数为e1,e2,e3,……em, 则结果为((1+2*e1)*(1+2*e2)……(1+2*em)+1)/2. 代码如下: #include <st ...

随机推荐

  1. ajax浅析---ScriptManagerProxy

    使用ScriptManagerProxy控件 在ASP.NET AJAX中,由于一个ASPX页面上只能有一个ScriptManager控件,所以在有母版页的情况下,如果需要在Master-Page和C ...

  2. linux 分区问题

    一.最简单的分区 仅分出根目录(/)和最简单的内存置换空间(swap)即可 以虚拟机的分区(20G)为例: 一般给/分15G来安装linux系统,512M给swap,另外的4G可以留下备用 二.复杂一 ...

  3. win7下搭建web服务器

    简介 微软为了操作系统的安全,默认把web.ftp等服务默认关闭了,重新打开也非常简单. step 1 打开控制面板: step 2: step 3: step 4: 单击确定之后等个几分钟,web服 ...

  4. IE浏览器版本判断

    <script type="text/javascript"> var browser=navigator.appName var b_version=navigato ...

  5. 浮动层-JS兼容IE6

    //引用jquery 包/*orderBycat 与 orderBycatHead 双层浮动*/ $(window).scroll(function () { var top = $(window). ...

  6. httpd服务访问控制

    客户机地址限制 通过配置Order.Deny from.Allow from 来限制客户机 allow.deny :先"允许"后"拒绝" ,默认拒绝所有为明确的 ...

  7. Android Fragment完全解析,关于碎片你所需知道的一切

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8881711 我们都知道,Android上的界面展示都是通过Activity实现的, ...

  8. Android内存性能优化(内部资料总结) eoe转载

    刚入门的童鞋肯能都会有一个疑问,Java不是有虚拟机了么,内存会自动化管理,我们就不必要手动的释放资源了,反正系统会给我们完成.其实Java中没有指针的概念,但是指针的使用方式依然存在,一味的依赖系统 ...

  9. PowerDesigner的使用(一)

    一. PowerDesigner 功能 1. 需求管理:记录需求,分析设计模型 2. 生成文档:生成HTML格式文档,方便沟通. 3. 影响度分析:模型之间连接起来,同步修改功能. 4. 数据映射:提 ...

  10. windowSoftInputMode属性讲解

    windowSoftInputMode属性讲解(下面这段内容我参考别人的博客,并加入我的一些意见) 我们从这个属性的名称中,可以很直观的看出它的作用,这个属性就是来设置窗口软键盘的交互模式的.andr ...