nnfw/src/learningalgorithm.cpp

00001 /********************************************************************************
00002  *  Neural Network Framework.                                                   *
00003  *  Copyright (C) 2005-2011 Gianluca Massera <emmegian@yahoo.it>                *
00004  *                                                                              *
00005  *  This program is free software; you can redistribute it and/or modify        *
00006  *  it under the terms of the GNU General Public License as published by        *
00007  *  the Free Software Foundation; either version 2 of the License, or           *
00008  *  (at your option) any later version.                                         *
00009  *                                                                              *
00010  *  This program is distributed in the hope that it will be useful,             *
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of              *
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
00013  *  GNU General Public License for more details.                                *
00014  *                                                                              *
00015  *  You should have received a copy of the GNU General Public License           *
00016  *  along with this program; if not, write to the Free Software                 *
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  *
00018  ********************************************************************************/
00019 
00020 #include "neuralnet.h"
00021 #include "learningalgorithm.h"
00022 #include "factory.h"
00023 
00024 namespace farsa {
00025 
00026 void Pattern::setInputsOf( Cluster* cl, const DoubleVector& ins ) {
00027     pinfo[cl].inputs.resize( cl->numNeurons() );
00028     pinfo[cl].inputs.copyValues( ins );
00029 };
00030 
00031 void Pattern::setOutputsOf( Cluster* cl, const DoubleVector& ous ) {
00032     pinfo[cl].outputs.resize( cl->numNeurons() );
00033     pinfo[cl].outputs.copyValues( ous );
00034 };
00035 
00036 void Pattern::setInputsOutputsOf( Cluster* cl, const DoubleVector& ins, const DoubleVector& ous ) {
00037     pinfo[cl].inputs.resize( cl->numNeurons() );
00038     pinfo[cl].inputs.copyValues( ins );
00039     pinfo[cl].outputs.resize( cl->numNeurons() );
00040     pinfo[cl].outputs.copyValues( ous );
00041 };
00042 
00043 DoubleVector Pattern::inputsOf( Cluster* cl ) const {
00044     if ( pinfo.count(cl) != 0 ) {
00045         return pinfo[cl].inputs;
00046     } else {
00047         return DoubleVector();
00048     }
00049 };
00050 
00051 DoubleVector Pattern::outputsOf( Cluster* cl ) const {
00052     if ( pinfo.count(cl) != 0 ) {
00053         return pinfo[cl].outputs;
00054     } else {
00055         return DoubleVector();
00056     }
00057 };
00058 
00059 Pattern::PatternInfo& Pattern::operator[]( Cluster* cl ) {
00060     return pinfo[cl];
00061 };
00062 
00063 void Pattern::configure(ConfigurationParameters& params, QString prefix) {
00064     //--- get all parameters with the prefix 'cluster:'
00065     QStringList clusterList = params.getParametersWithPrefixList( prefix, "cluster:" );
00066     foreach( QString cluster, clusterList ) {
00067         QString id = cluster.split(':')[1];
00068         if ( id.isEmpty() ) continue;
00069         //--- now, it check if there is a inputs and outputs parameter and load it
00070         QString str = params.getValue( prefix + "inputs:" + id );
00071         DoubleVector inputs;
00072         if (!str.isEmpty()) {
00073             QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
00074             for( int i=0; i<list.size(); i++) {
00075                 inputs.append( list[i].toDouble() );
00076             }
00077         }
00078         str = params.getValue( prefix + "outputs:" + id );
00079         DoubleVector outputs;
00080         if (!str.isEmpty()) {
00081             QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
00082             for( int i=0; i<list.size(); i++) {
00083                 outputs.append( list[i].toDouble() );
00084             }
00085         }
00086         if ( inputs.size() == 0 && outputs.size() == 0 ) continue;
00087         Cluster* cl = params.getObjectFromParameter<Cluster>( prefix+cluster, false, true );
00088         if ( inputs.size() > 0 ) {
00089             setInputsOf( cl, inputs );
00090         }
00091         if ( outputs.size() > 0 ) {
00092             setOutputsOf( cl, outputs );
00093         }
00094     }
00095 }
00096 
00097 void Pattern::save(ConfigurationParameters& params, QString prefix) {
00098     params.startObjectParameters(prefix, "Pattern", this);
00099     QString tmpl = "%1:%2";
00100     QList<Cluster*> cls = pinfo.keys();
00101     for( int i=0; i<cls.size(); i++ ) {
00102         PatternInfo& info = pinfo[ cls[i] ];
00103         params.createParameter(prefix, tmpl.arg("cluster").arg(i), cls[i]);
00104         if ( info.inputs.size() > 0 ) {
00105             QStringList list;
00106             for( unsigned int j=0; j<info.inputs.size(); j++ ) {
00107                 list.push_back(QString::number(info.inputs[j]));
00108             }
00109             params.createParameter(prefix, tmpl.arg("inputs").arg(i), list.join(" "));
00110         }
00111         if ( info.outputs.size() > 0 ) {
00112             QStringList list;
00113             for( unsigned int j=0; j<info.outputs.size(); j++ ) {
00114                 list.push_back(QString::number(info.outputs[j]));
00115             }
00116             params.createParameter(prefix, tmpl.arg("outputs").arg(i), list.join(" "));
00117         }
00118     }
00119 }
00120 
00121 void Pattern::describe( QString type ) {
00122     Descriptor d = addTypeDescription( type, "Represent a pattern of inputs/outputs for Clusters", "A Pattern is specified by groups of three parameters: cluster, inputs and outputs. The inputs and outputs parameters specify the values to set on the neurons of the cluster specified by the corresponding cluster parameter. The inputs and outputs parameter are not mandatory but specify a cluster without setting inputs or outputs has no effect" );
00123     d.describeObject( "cluster" ).type( "Cluster" ).props( IsMandatory | AllowMultiple ).help( "The Cluster on which the inputs and outputs parameters referes" );
00124     d.describeReal( "inputs" ).props( IsList | AllowMultiple ).help( "The values to set on the cluster's input neurons" );
00125     d.describeReal( "outputs" ).props( IsList | AllowMultiple ).help( "The values to set on the cluster's output neurons" );
00126 }
00127 
00128 LearningAlgorithm::LearningAlgorithm( NeuralNet* net )
00129     : ParameterSettableWithConfigureFunction() {
00130     this->netp = net;
00131 }
00132 
00133 LearningAlgorithm::LearningAlgorithm()
00134     : ParameterSettableWithConfigureFunction() {
00135     this->netp = NULL;
00136 }
00137 
00138 LearningAlgorithm::~LearningAlgorithm() {
00139 }
00140 
00141 PatternSet LearningAlgorithm::loadPatternSet( ConfigurationParameters& params, QString path, QString prefix ) {
00142     params.startRememberingGroupObjectAssociations();
00143     //--- convert to PatternSet
00144     PatternSet patternSet;
00145     foreach( QString group, params.getGroupsWithPrefixList(path, prefix) ) {
00146         patternSet << *(params.getObjectFromGroup<Pattern>( path + "/" + group ));
00147     }
00148 #ifdef __GNUC__
00149     #warning Se patternSet copia il Pattern creato all interno, allora quelli creati qui creano un leak perche non vengono mai distrutti !!
00150 #endif
00151     params.stopRememberingGroupObjectAssociations();
00152     return patternSet;
00153 }
00154 
00155 void LearningAlgorithm::savePatternSet( PatternSet& set, ConfigurationParameters& params, QString prefix ) {
00156     QString tmpl = prefix+":%1";
00157     for( int i=0; i<set.size(); i++ ) {
00158         QString group = tmpl.arg(i);
00159         params.createGroup( group );
00160         set[i].save( params, group );
00161     }
00162 }
00163 
00164 }