【EM】C++代码实现
看了原理和比人的代码后,终于自己写了一个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++代码实现的更多相关文章
- 【EM】代码理解
本来想自己写一个EM算法的,但是操作没两步就进行不下去了.对那些数学公式着实不懂.只好从网上找找代码,看看别人是怎么做的. 代码:来自http://blog.sina.com.cn/s/blog_98 ...
- CSS中rem、em的区别
引用文档:http://www.divcss5.com/html/h529.shtml:http://blog.csdn.net/qq_35432904/article/details/5180422 ...
- 把pcl的VTK显示融合到MFC(代码找原作者)
转自PCL中国,原文链接:http://www.pclcn.org/bbs/forum.php?mod=viewthread&tid=223&extra=page%3D1 本人做了少量 ...
- 代码覆盖率工具 EMMA
使用 EMMA 获得功能测试覆盖率 测试覆盖率是评价测试完整性的重要的度量标准之一. EMMA 是一个面向 Java 代码的测试覆盖率收集工具.在测试过程中,使用 EMMA 能使收集和报告测试覆盖率的 ...
- border-radius 圆角半径
CSS3属性之一:border-radius 语法: border-radius : none | <length>{1,4} [ / <length>{1,4} ]? 相关属 ...
- CSS3属性之一:border-radius
语法: border-radius : none | <length>{1,4} [ / <length>{1,4} ]? 相关属性: border-top-right-rad ...
- Source Insight设置总结
在网上搜索了一些关于Source Insight的设置技巧,把这些结果给总结下来: 1. 背景色选择 要改变背景色Options->preference->windows backgrou ...
- web CSS的知识- 关于后代选择器,子选择器,兄弟选择器的使用
1. 后代选择器官方解释:后代选择器可以选择作为某元素后代的元素.理解:选择某一标签的后代中,所有的此标签标记例:ul em {color:red;}就是选择,h1标签后代中中,所有的em.代码如下: ...
- 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 ...
随机推荐
- angular $resource模块
目录(?)[-] 安装 应用resource 扩展resource 上一篇中讲到使用$http同服务器进行通信,但是功能上比较简单,angularjs还提供了另外一个可选的服务$resource, ...
- codevs2171 棋盘覆盖
题目描述 Description 给出一张n*n(n<=100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少1*2的多米诺骨牌进行掩盖. 输入描述 Input Description 第一 ...
- Latex 数学符号表
- uml面向对象建模基础总结
uml九种图,其中的细节不说了.在后面的具体使用中提到这九种图. 建模流程: 1.分析需求. 2.通过分析名词,发现类,使用到类图. 3.建立用例模型,通过参与者分析用例,使用到用例图. 4.为用例建 ...
- CodeForces 353B Two Heaps
B. Two Heaps Valera has 2·n cubes, each cube contains an integer from 10 to 99. He arbitrarily cho ...
- 北美IT公司大致分档
北美IT公司大致分档(from mitbbs.com) 第一档: Uber, Snapchat, Airbnb, Dropbox, Pinterest 第二档:Facebook, LinkedIn, ...
- 机器学习之Hash集合问题
问题来源与七月学习之 (3.x线性代数与矩阵运算基础)
- 自己动手开发jQuery插件
因为工作需要,所以这几天琢磨了一下关于jQuery插件开发的问题,经过一天鏖战,终于完成自己动手做的第一个jQuery插件,对于俺这种见了css就蛋疼菊紧的人来说,一天时间8小时,保守估计有5个小时在 ...
- HTML5的新特性及技巧分享总结
原文链接:http://www.aseoe.com/show-10-645-1.html?utm_source=tuicool&utm_medium=referral 1. 新的Doctype ...
- jq常用的方法
.eq(i) //获取第几个元素 .text() //获取或设置元素文本内容 .html() //获取或设置元素html代码内容 .val() //获取或设置表单元素值 .attr() //获取或设置 ...