Trying to fix, again...

This commit is contained in:
blacklight 2009-08-10 18:06:52 +02:00
parent 3f56c8404c
commit 37995f75c2
5 changed files with 147 additions and 65 deletions

View File

@ -26,10 +26,10 @@
using namespace std; using namespace std;
//! Default rand value: |sin(rand)|, always >= 0 and <= 1 //! Default rand value: |sin(rand)|, always >= 0 and <= 1
#define RAND ( abs( sin(rand()) ) ) #define RAND (double) ( (rand() / (RAND_MAX/2)) - 1)
//! Initial value for the inertial momentum of the synapses //! Initial value for the inertial momentum of the synapses
#define BETA0 0.7 #define BETA0 0.8
/** /**
* @namespace neuralpp * @namespace neuralpp
@ -40,8 +40,6 @@ namespace neuralpp {
class Neuron; class Neuron;
class Layer; class Layer;
class NeuralNet; class NeuralNet;
class NetworkFileNotFoundException;
class InvalidXMLException;
/** /**
* @class NeuralNet * @class NeuralNet
@ -67,11 +65,11 @@ namespace neuralpp {
void commitChanges (Layer *l); void commitChanges (Layer *l);
/** /**
* @brief It get the error made on the expected result as |v-v'|/v * @brief Get the error made on the expected result as |v-v'|/v
* @param ex Expected value * @param ex Expected value
* @return Mean error * @return Mean error
*/ */
double error(double ex); double error(double ex) const;
/** /**
* @brief Private pointer to function, containing the function to * @brief Private pointer to function, containing the function to
@ -117,7 +115,7 @@ namespace neuralpp {
* @param file Binary file containing a neural network previously saved by save() method * @param file Binary file containing a neural network previously saved by save() method
* @throw NetworkFileNotFoundException * @throw NetworkFileNotFoundException
*/ */
NeuralNet (const char* file) throw(NetworkFileNotFoundException); NeuralNet (const string file) throw(NetworkFileNotFoundException);
/** /**
@ -140,7 +138,7 @@ namespace neuralpp {
* an only neuron) * an only neuron)
* @return The output value of the network * @return The output value of the network
*/ */
double getOutput(); double getOutput() const;
/** /**
* @brief It gets the output of the network in case the output layer contains more neurons * @brief It gets the output of the network in case the output layer contains more neurons
@ -153,7 +151,7 @@ namespace neuralpp {
* build your network by using setExpected. * build your network by using setExpected.
* @return The expected output value for a certain training phase * @return The expected output value for a certain training phase
*/ */
double expected(); double expected() const;
/** /**
* @brief It sets the value you expect from your network * @brief It sets the value you expect from your network
@ -189,8 +187,10 @@ namespace neuralpp {
/** /**
* @brief Save a trained neural network to a binary file * @brief Save a trained neural network to a binary file
* @param fname Binary file where you're going to save your network * @param fname Binary file where you're going to save your network
* @throws NetworkFileWriteException When you get an error writing the network's information to
* a file
*/ */
bool save(const char* fname); void save(const char* fname) throw(NetworkFileWriteException);
/** /**
* @brief Train a network using a training set loaded from an XML file. A sample XML file * @brief Train a network using a training set loaded from an XML file. A sample XML file
@ -296,14 +296,14 @@ namespace neuralpp {
* @brief Set the weight of the synapsis * @brief Set the weight of the synapsis
* @param w Weight to be set * @param w Weight to be set
*/ */
void setWeight(double w); void setWeight(double w) throw(InvalidSynapticalWeightException);
/** /**
* @brief It sets the delta (how much to change the weight after an update) * @brief It sets the delta (how much to change the weight after an update)
* of the synapsis * of the synapsis
* @param d Delta to be set * @param d Delta to be set
*/ */
void setDelta(double d); void setDelta(double d) throw(InvalidSynapticalWeightException);
/** /**
* @brief Return the weight of the synapsis * @brief Return the weight of the synapsis
@ -476,7 +476,7 @@ namespace neuralpp {
* @param i Index of the neuron to get in the layer * @param i Index of the neuron to get in the layer
* @return Reference to the i-th neuron * @return Reference to the i-th neuron
*/ */
Neuron& operator[] (size_t i); Neuron& operator[] (size_t i) throw(NetworkIndexOutOfBoundsException);
/** /**
* @brief It links a layer to another * @brief It links a layer to another
@ -504,7 +504,7 @@ namespace neuralpp {
/** /**
* @return Number of neurons in the layer * @return Number of neurons in the layer
*/ */
size_t size(); size_t size() const;
}; };
struct netrecord { struct netrecord {

View File

@ -31,6 +31,17 @@ namespace neuralpp {
const char* what() const throw() { return "Attempt to load a neural network from an invalid network file"; } const char* what() const throw() { return "Attempt to load a neural network from an invalid network file"; }
}; };
/**
* @class NetworkFileWriteException
* @brief Exception thrown when trying to write the network's information to a file that cannot
* be written
*/
class NetworkFileWriteException : public std::exception {
public:
NetworkFileWriteException() {}
const char* what() const throw() { return "There was an error while writing the network file"; }
};
/** /**
* @class InvalidXMLException * @class InvalidXMLException
* @brief Exception thrown when trying parsing an invalid XML * @brief Exception thrown when trying parsing an invalid XML
@ -40,6 +51,28 @@ namespace neuralpp {
InvalidXMLException() {} InvalidXMLException() {}
const char* what() const throw() { return "Attempt to load an invalid XML file"; } const char* what() const throw() { return "Attempt to load an invalid XML file"; }
}; };
/**
* @class NetworkIndexOutOfBoundsException
* @brief Exception raised when trying to access a neuron whose index is larger than the number
* of neurons in the network
*/
class NetworkIndexOutOfBoundsException : public std::exception {
public:
NetworkIndexOutOfBoundsException() {}
const char* what() const throw() { return "Attempt to access a non-existing neuron"; }
};
/**
* @class InvalidSynapticalWeightException
* @brief Exception raised when, while trying the network or directly, the weight of a synapsis is
* set to a value |w| > 1
*/
class InvalidSynapticalWeightException : public std::exception {
public:
InvalidSynapticalWeightException() {}
const char* what() const throw() { return "Attempt to set an invalid weight for the synapsis"; }
};
} }
#endif #endif

View File

@ -19,7 +19,9 @@ namespace neuralpp {
for (size_t i = 0; i < sz; i++) { for (size_t i = 0; i < sz; i++) {
Neuron n(a, d); Neuron n(a, d);
elements.push_back(n); elements.push_back(n);
} actv_f = a; }
actv_f = a;
deriv = d; deriv = d;
} }
@ -30,11 +32,14 @@ namespace neuralpp {
deriv = d; deriv = d;
} }
size_t Layer::size() { size_t Layer::size() const {
return elements.size(); return elements.size();
} }
Neuron & Layer::operator[](size_t i) { Neuron & Layer::operator[](size_t i) throw(NetworkIndexOutOfBoundsException) {
if (i > size())
throw NetworkIndexOutOfBoundsException();
return elements[i]; return elements[i];
} }

View File

@ -11,7 +11,9 @@
* this program. If not, see <http://www.gnu.org/licenses/>. * * this program. If not, see <http://www.gnu.org/licenses/>. *
**************************************************************************************************/ **************************************************************************************************/
#include <fstream>
#include <sstream> #include <sstream>
#include "neural++.hpp" #include "neural++.hpp"
#include "Markup.h" #include "Markup.h"
@ -56,7 +58,7 @@ namespace neuralpp {
link(); link();
} }
double NeuralNet::getOutput() { double NeuralNet::getOutput() const {
return (*output)[0].getActv(); return (*output)[0].getActv();
} }
@ -68,7 +70,7 @@ namespace neuralpp {
return v; return v;
} }
double NeuralNet::error(double expected) { double NeuralNet::error(double expected) const {
return abs((getOutput() - expected * return abs((getOutput() - expected *
deriv(getOutput())) / (abs(expected))); deriv(getOutput())) / (abs(expected)));
} }
@ -92,7 +94,7 @@ namespace neuralpp {
ex = e; ex = e;
} }
double NeuralNet::expected() { double NeuralNet::expected() const {
return ex; return ex;
} }
@ -168,12 +170,12 @@ namespace neuralpp {
} }
} }
bool NeuralNet::save(const char *fname) { void NeuralNet::save (const char *fname) throw(NetworkFileWriteException) {
FILE *fp;
struct netrecord record; struct netrecord record;
ofstream out(fname);
if (!(fp = fopen(fname, "wb"))) if (!out)
return false; throw NetworkFileWriteException();
record.input_size = input->size(); record.input_size = input->size();
record.hidden_size = hidden->size(); record.hidden_size = hidden->size();
@ -183,96 +185,113 @@ namespace neuralpp {
record.l_rate = l_rate; record.l_rate = l_rate;
record.ex = ex; record.ex = ex;
if (fwrite(&record, sizeof(struct netrecord), 1, fp) <= 0) if (out.write((char*) &record, sizeof(struct netrecord)) <= 0)
return false; throw NetworkFileWriteException();
// Saving neurons' state // Saving neurons' state
for (unsigned int i = 0; i < input->size(); i++) { for (unsigned int i = 0; i < input->size(); i++) {
struct neuronrecord r; struct neuronrecord r;
r.prop = (*input)[i].getProp(); r.prop = (*input)[i].getProp();
r.actv = (*input)[i].getActv(); r.actv = (*input)[i].getActv();
fwrite(&r, sizeof(struct neuronrecord), 1, fp);
if (out.write((char*) &r, sizeof(struct neuronrecord)) <= 0)
throw NetworkFileWriteException();
} }
for (unsigned int i = 0; i < hidden->size(); i++) { for (unsigned int i = 0; i < hidden->size(); i++) {
struct neuronrecord r; struct neuronrecord r;
r.prop = (*hidden)[i].getProp(); r.prop = (*hidden)[i].getProp();
r.actv = (*hidden)[i].getActv(); r.actv = (*hidden)[i].getActv();
fwrite(&r, sizeof(struct neuronrecord), 1, fp);
if (out.write((char*) &r, sizeof(struct neuronrecord)) <= 0)
throw NetworkFileWriteException();
} }
for (unsigned int i = 0; i < output->size(); i++) { for (unsigned int i = 0; i < output->size(); i++) {
struct neuronrecord r; struct neuronrecord r;
r.prop = (*output)[i].getProp(); r.prop = (*output)[i].getProp();
r.actv = (*output)[i].getActv(); r.actv = (*output)[i].getActv();
fwrite(&r, sizeof(struct neuronrecord), 1, fp);
if (out.write((char*) &r, sizeof(struct neuronrecord)) <= 0)
throw NetworkFileWriteException();
} }
// Saving synapsis' state // Saving synapsis' state
for (unsigned int i = 0; i < input->size(); i++) { for (unsigned int i = 0; i < input->size(); i++) {
int nout = (*input)[i].nOut(); int nout = (*input)[i].nOut();
fwrite(&nout, sizeof(int), 1, fp);
if (out.write((char*) &nout, sizeof(int)) <= 0)
throw NetworkFileWriteException();
for (int j = 0; j < nout; j++) { for (int j = 0; j < nout; j++) {
struct synrecord r; struct synrecord r;
r.w = (*input)[i].synOut(j).getWeight(); r.w = (*input)[i].synOut(j).getWeight();
r.d = (*input)[i].synOut(j).getDelta(); r.d = (*input)[i].synOut(j).getDelta();
fwrite(&r, sizeof(struct synrecord), 1,
fp); if (out.write((char*) &r, sizeof(struct synrecord)) <= 0)
throw NetworkFileWriteException();
} }
} }
for (unsigned int i = 0; i < output->size(); i++) { for (unsigned int i = 0; i < output->size(); i++) {
int nin = (*output)[i].nIn(); int nin = (*output)[i].nIn();
fwrite(&nin, sizeof(int), 1, fp);
if (out.write((char*) &nin, sizeof(int)) <= 0)
throw NetworkFileWriteException();
for (int j = 0; j < nin; j++) { for (int j = 0; j < nin; j++) {
struct synrecord r; struct synrecord r;
r.w = (*output)[i].synIn(j).getWeight(); r.w = (*output)[i].synIn(j).getWeight();
r.d = (*output)[i].synIn(j).getDelta(); r.d = (*output)[i].synIn(j).getDelta();
fwrite(&r, sizeof(struct synrecord), 1,
fp); if (out.write((char*) &r, sizeof(struct synrecord)) <= 0)
throw NetworkFileWriteException();
} }
} }
for (unsigned int i = 0; i < hidden->size(); i++) { for (unsigned int i = 0; i < hidden->size(); i++) {
int nin = (*hidden)[i].nIn(); int nin = (*hidden)[i].nIn();
fwrite(&nin, sizeof(int), 1, fp);
if (out.write((char*) &nin, sizeof(int)) <= 0)
throw NetworkFileWriteException();
for (int j = 0; j < nin; j++) { for (int j = 0; j < nin; j++) {
struct synrecord r; struct synrecord r;
r.w = (*hidden)[i].synIn(j).getWeight(); r.w = (*hidden)[i].synIn(j).getWeight();
r.d = (*hidden)[i].synIn(j).getDelta(); r.d = (*hidden)[i].synIn(j).getDelta();
fwrite(&r, sizeof(struct synrecord), 1,
fp); if (out.write((char*) &r, sizeof(struct synrecord)) <= 0)
throw NetworkFileWriteException();
} }
} }
for (unsigned int i = 0; i < hidden->size(); i++) { for (unsigned int i = 0; i < hidden->size(); i++) {
int nout = (*hidden)[i].nOut(); int nout = (*hidden)[i].nOut();
fwrite(&nout, sizeof(int), 1, fp);
if (out.write((char*) &nout, sizeof(int)) <= 0)
throw NetworkFileWriteException();
for (int j = 0; j < nout; j++) { for (int j = 0; j < nout; j++) {
struct synrecord r; struct synrecord r;
r.w = (*hidden)[i].synOut(j).getWeight(); r.w = (*hidden)[i].synOut(j).getWeight();
r.d = (*hidden)[i].synOut(j).getDelta(); r.d = (*hidden)[i].synOut(j).getDelta();
fwrite(&r, sizeof(struct synrecord), 1,
fp); if (out.write((char*) &r, sizeof(struct synrecord)) <= 0)
throw NetworkFileWriteException();
} }
} }
fclose(fp); out.close();
return true;
} }
NeuralNet::NeuralNet(const char *fname) throw(NetworkFileNotFoundException) { NeuralNet::NeuralNet(const string fname) throw(NetworkFileNotFoundException) {
struct netrecord record; struct netrecord record;
FILE *fp; ifstream in(fname.c_str());
if (!(fp = fopen(fname, "rb"))) if (!in)
throw NetworkFileNotFoundException(); throw NetworkFileNotFoundException();
if (fread(&record, sizeof(struct netrecord), 1, fp) <= 0) if (in.read((char*) &record, sizeof(struct netrecord)) <= 0)
throw NetworkFileNotFoundException(); throw NetworkFileNotFoundException();
*this = *this =
@ -283,7 +302,9 @@ namespace neuralpp {
// Restore neurons // Restore neurons
for (unsigned int i = 0; i < input->size(); i++) { for (unsigned int i = 0; i < input->size(); i++) {
struct neuronrecord r; struct neuronrecord r;
fread(&r, sizeof(struct neuronrecord), 1, fp);
if (in.read((char*) &r, sizeof(struct neuronrecord)) <= 0)
throw NetworkFileNotFoundException();
(*input)[i].setProp(r.prop); (*input)[i].setProp(r.prop);
(*input)[i].setActv(r.actv); (*input)[i].setActv(r.actv);
@ -292,7 +313,9 @@ namespace neuralpp {
for (unsigned int i = 0; i < hidden->size(); i++) { for (unsigned int i = 0; i < hidden->size(); i++) {
struct neuronrecord r; struct neuronrecord r;
fread(&r, sizeof(struct neuronrecord), 1, fp);
if (in.read((char*) &r, sizeof(struct neuronrecord)) <= 0)
throw NetworkFileNotFoundException();
(*hidden)[i].setProp(r.prop); (*hidden)[i].setProp(r.prop);
(*hidden)[i].setActv(r.actv); (*hidden)[i].setActv(r.actv);
@ -301,7 +324,9 @@ namespace neuralpp {
for (unsigned int i = 0; i < output->size(); i++) { for (unsigned int i = 0; i < output->size(); i++) {
struct neuronrecord r; struct neuronrecord r;
fread(&r, sizeof(struct neuronrecord), 1, fp);
if (in.read((char*) &r, sizeof(struct neuronrecord)) <= 0)
throw NetworkFileNotFoundException();
(*output)[i].setProp(r.prop); (*output)[i].setProp(r.prop);
(*output)[i].setActv(r.actv); (*output)[i].setActv(r.actv);
@ -323,12 +348,16 @@ namespace neuralpp {
// Restore synapsis // Restore synapsis
for (unsigned int i = 0; i < input->size(); i++) { for (unsigned int i = 0; i < input->size(); i++) {
int nout; int nout;
fread(&nout, sizeof(int), 1, fp);
if (in.read((char*) &nout, sizeof(int)) <= 0 )
throw NetworkFileNotFoundException();
for (int j = 0; j < nout; j++) { for (int j = 0; j < nout; j++) {
struct synrecord r; struct synrecord r;
fread(&r, sizeof(struct synrecord), 1, fp);
if (in.read((char*) &r, sizeof(struct synrecord)) <= 0)
throw NetworkFileNotFoundException();
(*input)[i].synOut(j).setWeight(r.w); (*input)[i].synOut(j).setWeight(r.w);
(*input)[i].synOut(j).setDelta(r.d); (*input)[i].synOut(j).setDelta(r.d);
} }
@ -336,11 +365,15 @@ namespace neuralpp {
for (unsigned int i = 0; i < output->size(); i++) { for (unsigned int i = 0; i < output->size(); i++) {
int nin; int nin;
fread(&nin, sizeof(int), 1, fp);
if (in.read((char*) &nin, sizeof(int)) <= 0)
throw NetworkFileNotFoundException();
for (int j = 0; j < nin; j++) { for (int j = 0; j < nin; j++) {
struct synrecord r; struct synrecord r;
fread(&r, sizeof(struct synrecord), 1, fp);
if (in.read((char*) &r, sizeof(struct synrecord)) <= 0)
throw NetworkFileNotFoundException();
(*output)[i].synIn(j).setWeight(r.w); (*output)[i].synIn(j).setWeight(r.w);
(*output)[i].synIn(j).setDelta(r.d); (*output)[i].synIn(j).setDelta(r.d);
@ -349,11 +382,15 @@ namespace neuralpp {
for (unsigned int i = 0; i < hidden->size(); i++) { for (unsigned int i = 0; i < hidden->size(); i++) {
int nin; int nin;
fread(&nin, sizeof(int), 1, fp);
if (in.read((char*) &nin, sizeof(int)) <= 0)
throw NetworkFileNotFoundException();
for (int j = 0; j < nin; j++) { for (int j = 0; j < nin; j++) {
struct synrecord r; struct synrecord r;
fread(&r, sizeof(struct synrecord), 1, fp);
if (in.read((char*) &r, sizeof(struct synrecord)) <= 0)
throw NetworkFileNotFoundException();
(*hidden)[i].synIn(j).setWeight(r.w); (*hidden)[i].synIn(j).setWeight(r.w);
(*hidden)[i].synIn(j).setDelta(r.d); (*hidden)[i].synIn(j).setDelta(r.d);
@ -362,18 +399,22 @@ namespace neuralpp {
for (unsigned int i = 0; i < hidden->size(); i++) { for (unsigned int i = 0; i < hidden->size(); i++) {
int nout; int nout;
fread(&nout, sizeof(int), 1, fp);
if (in.read((char*) &nout, sizeof(int)) <= 0)
throw NetworkFileNotFoundException();
for (int j = 0; j < nout; j++) { for (int j = 0; j < nout; j++) {
struct synrecord r; struct synrecord r;
fread(&r, sizeof(struct synrecord), 1, fp);
if (in.read((char*) &r, sizeof(struct synrecord)) <= 0)
throw NetworkFileNotFoundException();
(*hidden)[i].synOut(j).setWeight(r.w); (*hidden)[i].synOut(j).setWeight(r.w);
(*hidden)[i].synOut(j).setDelta(r.d); (*hidden)[i].synOut(j).setDelta(r.d);
} }
} }
fclose(fp); in.close();
} }
void NeuralNet::train(string xmlsrc, NeuralNet::source src = void NeuralNet::train(string xmlsrc, NeuralNet::source src =
@ -438,7 +479,7 @@ namespace neuralpp {
return; return;
} }
void NeuralNet::initXML(string & xml) { void NeuralNet::initXML(string& xml) {
xml.append xml.append
("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" ("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
"<!DOCTYPE NETWORK SYSTEM \"http://blacklight.gotdns.org/prog/neuralpp/trainer.dtd\">\n" "<!DOCTYPE NETWORK SYSTEM \"http://blacklight.gotdns.org/prog/neuralpp/trainer.dtd\">\n"

View File

@ -72,14 +72,17 @@ namespace neuralpp {
return prev_delta; return prev_delta;
} }
void Synapsis::setWeight(double w) { void Synapsis::setWeight(double w) throw(InvalidSynapticalWeightException) {
if (weight > 1.0) if (weight > 1.0)
weight = 1.0; throw InvalidSynapticalWeightException();
else
weight = w; weight = w;
} }
void Synapsis::setDelta(double d) { void Synapsis::setDelta(double d) throw(InvalidSynapticalWeightException) {
if (d > 1.0)
throw InvalidSynapticalWeightException();
prev_delta = delta; prev_delta = delta;
delta = d; delta = d;
} }