基于Hebb规则联想器的一些总结

课程结束,老师要求上台做presentation。于是选择了最简单的和Hebb规则有关的题目。编程过程中,除了对神经网络有了更多感性认识,在其他问题上也有了一些收获。这里简单记一下。


程序中用到了有关矩阵的操作,很多人说matlab的矩阵操作很强大。网上查了一下,从C++中调用matlab的相关方法,要么是基于client-server的形式调用,要么是把matlab中的程序封装成COM, DLL来调用。临时学matlab的这些方法似乎来不及,于是就转投boost库,找找看有没有和矩阵有关的操作。


先说说boost库,功能比较强大,是对C++的有益补充。关于这个库的下载编译方法,主要参考了这个教程:http://www.cnblogs.com/wondering/archive/2009/05/21/boost_setup.html, 以及这本书:http://book.douban.com/subject/5276434/。其中ublas库是和矩阵操作有关的。利用它,可以实现基本的矩阵转置,求逆,矩阵矩阵运算,向量向量运算,以及矩阵向量运算。不过,官方的文档不是很给力,例子也不丰富。实现求逆的时候,是直接Google找到别人现成的方法。


这次尝试使用了一下C++的template function机制,有这么几点感想。第一,在非template class中如果创建template function, 那么这个方法的实现代码最好写在头文件中。否则,如果从其他类中调用这个template function的话,会报链接错误LNK2019。搜索了一下原因,大概意思是,有些编译器不支持模板分离,可以参考这里的讨论(http://bbs.csdn.net/topics/190029153),以及stackoverflow上的这段解释“The compiler needs to have access to the entire template definition (not just the signature)in order to generate code for each instantiation of the template, so you need to move the definitions of the functions to your header.

Note: In general most C++ compilers do not easily support the separate compilation model for templates.。但是,如果这个template function在本类内部执行过程中调用的话,那么写在cpp文件中并不影响执行。


另外一点就是,template function中使用的方法,如果对输入类型有要求,那么也无法做到类型无关,除非自己实现一个。比如在求逆的方法中,用到了一个函数lu_factorize(),最初输入int类型的矩阵,总是报错,似乎是因为这个函数在执行过程中调用到了math.h 中的sqrt函数,而这个函数只接受double或float类型的变量。最后把矩阵类型全部换成double才顺利过关。


再记录几个常用的方法,一个是文件读取

#include <string>
#include <fstream>
void coldDish(string path){
	ifstream ifs;
	char read;
	ifs.open(path, fstream::in);
	while(ifs>>read){
		if(read == '1'){
			...
		}else if(...){
			...
		}
	}
	ifs.close();	
}


原来找到一个方法,是将filestream对接到std::cin中,cin也是一个iostream类型,但是在输入完成后,应该对std::cin做一个还原,否则会报系统错误。


关于boost-ublas中的一些东西。首先,求逆矩阵的function,现在还没太看明白这里面用到的函数,拿来用就是了。


#include<boost\numeric\ublas\matrix.hpp>
#include<boost\numeric\ublas\operation.hpp>
#include<boost\numeric\ublas\io.hpp>
#include<boost\numeric\ublas\lu.hpp>
template<class T>
bool numToLet::InvertMatrix(const matrix<T>& input, matrix<T>& inverse){
	using namespace boost::numeric::ublas;
    typedef permutation_matrix<std::size_t> pmatrix;
    // create a working copy of the input
    matrix<T> A(input);
    // create a permutation matrix for the LU-factorization
    pmatrix pm(A.size1());

    // perform LU-factorization
    int res = lu_factorize(A,pm);
    if( res != 0 ) return false;

    // create identity matrix of "inverse"
    inverse.assign(identity_matrix<T>(A.size1()));
	
    // backsubstitute to get the inverse
    lu_substitute(A, pm, inverse);

    return true;
}


另外一个,控制cout格式:

#include <iomanip>
void printee(double i){
	cout<<setiosflags(ios::right)<<setw(2)<<setprecision(2)<<i;
}


其次,如果把matrix变量的声明和初始化分开,让程序看起来更像C++(而不是C那样一个main.cpp全部包办),那么,头文件和对应的构造函数函数中可以写成这样

matrix<double> inputData;//header
inputData = zero_matrix<double>(ROW, LEN);//congstructor


这样InputData就被初始化为ROW*LEN的零矩阵了。

只是一些简单细致的内容,做个笔记,希望对大家有用。


你可能感兴趣的:(C++,template,boost,ublas)