看了原理和比人的代码后,终于自己写了一个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. ASP.NET Web数据控件

    ASP.NET Web数据控件 1.数据控件简介 这包括数据源控件和格式设置控件,前者使您可以使用 Web 控件访问数据库中的数据,后者使您可以显示和操作ASP.NET 网页上的数据.  2.数据控件 ...

  2. webpack 教程 那些事儿03-webpack两大精华插件,热加载

    本节主要讲述 webpack的两大经典开发调试插件,热插拔内存缓存机制 文章目录 1. html-webpack-plugin插件的使用 2. webpack-dev-middleware 插件登场 ...

  3. linux安装包地址备忘

    64位系统安装包: http://mirrors.163.com/centos/5/os/x86_64/CentOS/ 32位系统安装包: http://mirrors.163.com/centos/ ...

  4. 用jQuery编的一个分页小代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. MongoDB的学习和使用

    一.下载mongodb. 官网下载, 或者http://www.360sdn.com/opensource-datasource/2015/0403/5584.html下载: http://fastd ...

  6. MySQL的InnoDB索引原理详解 (转)

    摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本 ...

  7. 为 Github 创造 Integration

    导读 现在你可以从我们的 集成件目录里面找到更多工具.这个目录目前有超过 15 个分类 — 从 API 管理 到 应用监控, Github 的集成件可以支持您的开发周期的每一个阶段. 我们邀请了具有不 ...

  8. HTTP及状态码汇总

    什么是HTTP: HTTP(HyperText Transfer Protocol超文本传输协议)是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准,为了提供一种发布和接收HTM ...

  9. [codeforces 55]D. Beautiful numbers

    [codeforces 55]D. Beautiful numbers 试题描述 Volodya is an odd boy and his taste is strange as well. It ...

  10. ImageView显示网络图片

    package com.example.urlimage; import java.io.InputStream; import java.net.HttpURLConnection; import ...