看了原理和比人的代码后,终于自己写了一个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. 编译本地64位版本的hadoop-2.6.0

     官方提供的hadoop-2.x版本貌似都是32位的,在64位机子下使用可能会报错,最好使用官方提供的源码进行本地编译,编译成适合本地硬件环境的64位软件包. 关于native  Hadoop是使用J ...

  2. VS上利用C#实现一个简单的串口程序记录

    一.背景 工作上需要利用串口往下位机写入数据,VC太老,正好借此机会来熟悉一直很想接触的VS之C#. 感谢Tony托尼哥的串口通信代码,感谢梦真的C#的技术支持. 二.正文 1.项目架构:(以我现有的 ...

  3. OC第九节——协议与代理

    一.理解协议与代理 协议: 协议就是需要相互遵守的约定.规范:需要去实现协议中规定的方法. 代理: 代理是一个概念,很难用一个名词去定义(如我们可以说协议其实就是一个方法列表).它更像是一种关系,我要 ...

  4. OC第四节——NSDictionary和NSMutableDictionary

    NSDictionary    1.什么是字典        字典是也是一种集合结构,功能与我们现实中的字典工具一样    2.字典的元素是什么        任意类型的对象地址构成键值对    3. ...

  5. 字符串匹配算法——KMP算法

    处理字符串的过程中,难免会遇到字符匹配的问题.常用的字符匹配方法 1. 朴素模式匹配算法(Brute-Force算法) 求子串位置的定位函数Index( S, T, pos). 模式匹配:子串的定位操 ...

  6. iOS开发——高级篇——换肤、静态库

    一.换肤 1.思路1> 解决方案1,使用颜色作为图片素材的命名关键字 问题1:要保证每套图片的文件名 颜色+ 名称.png的格式比较麻烦 问题2:如果要将某一个图片应用到其他皮肤不方便2> ...

  7. crontab用法与实例

    导读 在Linux系统的实际使用中,可能会经常碰到让系统在某个特定时间执行某些任务的情况,比如定时采集服务器的状态信息.负载状况:定时执行某些任务/脚本来对远端进行数据采集等.这里将介绍下cronta ...

  8. iTool拷贝app到电脑上

    iTool拷贝app到电脑上 方法一. iTool找到你的app, 归档在桌面, 桌面就生成了ipa, 其实ipa是一个压缩包, 使用解压软件解压之后 生成Payload文件夹, 点开就可以看到Clo ...

  9. Android 简易XML解析

    首先创建在Android工程中创建一个Assets文件夹 app/src/main/assets 在这里添加一个名为 data.xml的文件,然后编辑这个文件,加入如下XML格式内容 <?xml ...

  10. Mac之vim普通命令使用[转]

    高级一些的编辑器,都会包含宏功能,vim当然不能缺少了,在vim中使用宏是非常方便的: :qx     开始记录宏,并将结果存入寄存器xq     退出记录模式@x     播放记录在x寄存器中的宏命 ...