MED 分类器
实现代码:
MED.h
#include <iostream>
#include <vector>
#include <valarray>
#include <assert.h>
typedef long double real;
template<size_t N>
class vec : public std::valarray<real> {
public:
vec() {
assert(N>0);
resize(N);
}
vec(const std::pair<real, real> &p) {
assert(N>0);
resize(N);
(*this)[0]=p.first;
if(N>1)
(*this)[1]=p.second;
}
real dot(const vec& rhs) const {
assert(size()==rhs.size());
real res=0;
for(int i=size()-1; ~i; --i)
res+=(*this)[i]*rhs[i];
return res;
}
real len2() const {
return dot(*this);
}
real len() const {
return sqrtl(len2());
}
friend std::ostream& operator << (std::ostream& out, const vec<N> &v) {
out<<"("<<v[0];
for(int i=1; i<N; ++i)
out<<","<<v[i];
return out<<")";
}
};
template<size_t N>
class Class {
protected:
std::vector<vec<N> > spec;
vec<N> sumvec;
public:
void add(const vec<N>& obj) {
spec.emplace_back(obj);
sumvec+=obj;
}
vec<N> mu() const {
vec<N> v=sumvec;
for(int i=0, x=spec.size(); i<N; ++i)
v[i]/=x;
return v;
}
real dis(const vec<N>& obj) const {
vec<N> now=mu();
now-=obj;
return now.len2();
}
friend std::ostream& operator << (std::ostream& out, const Class &c) {
vec<N> m = c.mu();
return out<<"mu = "<<m<<"\t,size = "<<c.spec.size();
}
};
template<size_t M, size_t N>
class MED {
std::vector<Class<N> > c;
public:
MED() {
assert(M>1);
c.resize(M);
}
void add(int id, const vec<N>& obj) {
assert(id<M);
c[id].add(obj);
}
int classified(const vec<N>& obj) const {
int minid=0;
real minlen=c[0].dis(obj);
for(int i=0; i<M; ++i) {
real nowlen=c[i].dis(obj);
std::cout<<"distance with Class "<<i<<":\t"<<sqrtl(nowlen)<<std::endl;
if(nowlen<minlen) {
minlen=nowlen;
minid=i;
}
}
return minid;
}
friend std::ostream& operator << (std::ostream& out, const MED &m) {
for(int i=0; i<M; ++i)
out<<"Class "<<i<<":\n\t"<<m.c[i]<<"\n";
return out;
}
};
测试代码:
test.cpp
#include <iostream>
#include <map>
#include "MED.h"
class Test {
MED<2, 2> med;
public:
Test() {
load();
std::cout<<med<<std::endl;
}
int classified(const vec<2>& v) {
return med.classified(v);
}
void load() {
std::map< std::pair<real, real> , int> train;
train[std::make_pair(1, 4)]=1;
train[std::make_pair(7, 0)]=1;
train[std::make_pair(3.5, 1)]=1;
train[std::make_pair(4.5, 3)]=1;
train[std::make_pair(4, 4)]=0;
train[std::make_pair(8, 5)]=0;
train[std::make_pair(8, 3)]=0;
train[std::make_pair(12, 4)]=0;
for(auto [v, t] : train)
med.add(t, v);
}
}test;
int main() {
vec<2> v=std::pair<real, real>(4, 5);
int res = test.classified(v);
std::cout<<"Belong to Class "<<res<<std::endl;
return 0;
}
运行结果:
Class 0:
mu = (8,4) ,size = 4
Class 1:
mu = (4,2) ,size = 4
distance with Class 0: 4.12311
distance with Class 1: 3
Belong to Class 1