• 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
    
  • 相关阅读:
    Linux进程管理概述
    【反转单链表】一篇就够了
    线性数据结构
    Linux的su和sudo有什么区别?如何使用?
    关于CentOS切换中文输入法的问题
    MySQL 初识
    MySQL 增-删-改操作
    数据库简介
    MySQL 查询操作
    HANDLER Statement
  • 原文地址:https://www.cnblogs.com/JustinRochester/p/16211774.html
Copyright © 2020-2023  润新知