看了原理和比人的代码后,终于自己写了一个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. 关于R中的mode()和class()的区别

    本文原创,转载请注明出处,本人Q1273314690(交流学习) 说明:本文曾经在15年11月在CSDN发过,但是由于CSDN不支持为知笔记的发布为博客的API功能,所以,自今天起,转移到博客园(幸好 ...

  2. mysql 表锁问题

    select * from information_schema.INNODB_lock_waits; select * from information_schema.INNODB_locks; S ...

  3. 【知乎网】Linux IO 多路复用 是什么意思?

    提问一: Linux IO多路复用有 epoll, poll, select,知道epoll性能比其他几者要好.也在网上查了一下这几者的区别,表示没有弄明白. IO多路复用是什么意思,在实际的应用中是 ...

  4. mongodb certification

    又偷懒 也有学到不少东西 这个东西算是小结啦 给2013年的碌碌无为挽回点面子 哈哈~

  5. 关于sql用<>不等于查询数据不对问题

    平常查询数据 ' 当想要查询 不等于1 的数据的时候,一般会这样查询 ' 此处查询结果没查到所有想要的结果,如果night_flag 列数据为 null时,此行数据是查询不到的. 解决方法一: ' 解 ...

  6. EasyUI中Dialog的使用

    $(function () { $('<div id="dlgContent"></div>').appendTo($('body')); $('#dlgC ...

  7. Android开发资源推荐第2季

    Android CPU监控想法,思路,核心技术和代码 Android App /Task/Stack 总体分析 http://www.eoeandroid.com/thread-161703-1-1. ...

  8. iOS开发——高级篇——如何集成支付宝SDK

    一.什么是支付宝 第三方支付平台 和内购非常相似内购是用户将钱付款给苹果,之后苹果分成给商户支付宝是用户将钱付款给支付宝,之后支付宝将钱转入我们的账户 使用支付宝前提购买的物品必须是和应用程序无关的. ...

  9. 剑指Offer 从尾到头打印链表

    题目描述 输入一个链表,从尾到头打印链表每个节点的值. 输入描述: 输入为链表的表头 输出描述: 输出为需要打印的“新链表”的表头 思路: 用容器vector,递归到最后一个元素,push_back到 ...

  10. OpenCV成长之路(9):特征点检测与图像匹配

    特征点又称兴趣点.关键点,它是在图像中突出且具有代表意义的一些点,通过这些点我们可以用来识别图像.进行图像配准.进行3D重建等.本文主要介绍OpenCV中几种定位与表示关键点的函数. 一.Harris ...