📄 layer.cpp
字号:
/*
nn-utility (Provides neural networking utilities for c++ programmers)
Copyright (C) 2003 Panayiotis Thomakos
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//To contact the author send an email to panthomakos@users.sourceforge.net
#include "nn-utility.h"
using namespace nn_utility;
template<class T> void layer<T>:: define( int rows, int cols ){
set_defaults();
row = rows; col = cols;
for ( int clear = 0; clear < cols; clear++ )
weight[clear] = 0;
};
template<class T>
void layer<T>:: definei( int row_, int col_, T value, ... ){
set_defaults();
row = row_; col = col_;
for ( int clear = 0; clear < col_; clear++ )
weight[clear] = 0;
va_list argument_ptr;
matrix[0][0] = value;
va_start(argument_ptr, value);
for ( int i = 0; i < row; i++ ){
//the insert if statement determines whether that value has already been placed, since the
//first value is read outside the loop
for ( int e = ( i == 0 ? 1 : 0 ); e < col; e++ ){
matrix[i][e] = (T)va_arg(argument_ptr, int);
}
}
va_end(argument_ptr);
}
template<class T>
void layer<T>:: definef( int row_, int col_, T value, ... ){
set_defaults();
row = row_; col = col_;
for ( int clear = 0; clear < col_; clear++ )
weight[clear] = 0;
va_list argument_ptr;
matrix[0][0] = value;
va_start(argument_ptr, value);
for ( int i = 0; i < row; i++ ){
//the insert if statement determines whether that value has already been placed, since the
//first value is read outside the loop
for ( int e = ( i == 0 ? 1 : 0 ); e < col; e++ ){
matrix[i][e] = (T)va_arg(argument_ptr, double);
}
}
va_end(argument_ptr);
}
template<class T>
void layer<T>:: define( char *filename, int index ){
binary_fire = false;
fstream infile( filename, ios::in );
char buffer[256];
for ( int i = 0; i < index; i++ ){
infile >> buffer;
infile >> buffer;
while ( buffer[0] != ':' && buffer != NULL )
infile >> buffer;
}
if ( buffer[0] != ':' ){
infile >> buffer;}
if ( buffer[0] == ':' ){
do{
infile >> buffer;
if ( buffer[0] == 's' ){
Next = NULL;
Previous = NULL;
infile >> row >> col;
}
else if ( buffer[0] == 'b' ){
for ( int i = 0; i < col; i++ )
infile >> weight[i];
}
else if ( buffer[0] == 'w' ){
for ( int i = 0; i < row; i++ ){
for ( int e = 0; e < col; e++ ){
infile >> matrix[i][e];}
}
}
else if ( buffer[0] == 'f' ){
binary_fire = true;
for ( int i = 0; i < col; i++ ){
for ( int e = 0; e < row; e++ ){
infile >> binary_number[i][e];
}
}
}
}while( buffer[0] != ':' && buffer[0] != '\0' );
}
infile.close();
}
template<class T>
void layer<T>:: define( char *filename, int index, layer<T> **PREV ){
binary_fire = false;
fstream infile( filename, ios::in );
char buffer[256];
for ( int i = 0; i < index; i++ ){
infile >> buffer;
infile >> buffer;
while ( buffer[0] != ':' && buffer != NULL )
infile >> buffer;
}
if ( buffer[0] != ':' ){
infile >> buffer;}
if ( buffer[0] == ':' ){
do{
infile >> buffer;
if ( buffer[0] == 's' ){
Next = NULL;
Previous = NULL;
infile >> row >> col;
}
else if ( buffer[0] == 'b' ){
for ( int i = 0; i < col; i++ )
infile >> weight[i];
}
else if ( buffer[0] == 'w' ){
for ( int i = 0; i < row; i++ ){
for ( int e = 0; e < col; e++ ){
infile >> matrix[i][e];}
}
}
else if ( buffer[0] == 'f' ){
for ( int i = 0; i < col; i++ )
for ( int e = 0; e < row; e++ ){
infile >> binary_number[i][e];
}
}
}while( buffer[0] != ':' && buffer[0] != '\0' );
}
infile.close();
if ( (*PREV) ){
(*PREV)->Next = this;
Previous = (*PREV);
}
}
template<class T>
void layer<T>:: set_defaults( ){
Previous = NULL;
Next = NULL;
binary_fire = false;
length = 0;
network_recurrent = false;
annealing_on = false;
};
template<class T>
void layer<T>:: FeedForward( VECTOR in, VECTOR &final ){
for ( int e = 0; e < col; e++ ){
VECTOR vector;
CreateVector( vector, e );
VECTOR fire;
int counter = row;
if ( binary_fire ){
counter = 0;
for ( int r = 0; r < row; r++ )
if ( binary_number[e][r] )
fire[counter++] = in[r];
}
else{ CopyVector( fire, in, row ); }
result[e] = function( fire, vector, weight[e], counter, ( !(Next) ? true : false ) );
}
if ( !(Next) ){ CopyVector( final, result, col ); }
else{ Next->FeedForward( result, final ); }
}
template<class T>
void layer<T>:: BackPropagate( VECTOR input, VECTOR target, T learning_rate, int length ){
VECTOR NewTarget;
ClearVector( NewTarget, row );
if ( !(Previous) ){
UpdateLayer( target, NewTarget, length, learning_rate, input, result, ( Next ? 0 : 1 ) ); }
else{
UpdateLayer( target, NewTarget, length, learning_rate, Previous->result, result, ( !(Next) ? 1 : 0 ) ); }
if ( Previous ){ Previous->BackPropagate( input, NewTarget, learning_rate, length ); }
}
template<class T>
void layer<T>:: CreateVector( VECTOR &vector, int column ){
for ( int j = 0; j < row; j++ ){ vector[j] = matrix[j][column]; } }
template<class T>
void layer<T>:: Seti( T value, ... ){
va_list argument_ptr; matrix[0][0] = value;
va_start(argument_ptr, value);
for ( int i = 0; i < row; i++ ){
//the insert if statement determines whether that value has already been placed, since the
//first value is read outside the loop
for ( int e = ( i == 0 ? 1 : 0 ); e < col; e++ ){
matrix[i][e] = (T)va_arg(argument_ptr, int);
}
}
va_end(argument_ptr);
}
template<class T>
void layer<T>:: Setf( T value, ... ){
va_list argument_ptr; matrix[0][0] = value;
va_start(argument_ptr, value);
for ( int i = 0; i < row; i++ ){
//the insert if statement determines whether that value has already been placed, since the
//first value is read outside the loop
for ( int e = ( i == 0 ? 1 : 0 ); e < col; e++ ){
matrix[i][e] = (T)va_arg(argument_ptr, double);
}
}
va_end(argument_ptr);
}
template<class T> void layer<T>:: SetBinary( int value, ... ){
binary_fire = true;
va_list argument_ptr;
binary_number[0][0] = (T) value;
va_start(argument_ptr, value);
for ( int i = 0; i < col; i++ ){
//the insert if statement determines whether that value has already been placed, since the
//first value is read outside the loop
for ( int e = ( i == 0 ? 1 : 0 ); e < row; e++ ){
binary_number[i][e] = (T)va_arg(argument_ptr, int);
}
}
va_end(argument_ptr);
}
template<class T> void layer<T>:: SetColumn( int index, VECTOR to_load ){
for ( int i = 0; i < row; i++ )
matrix[i][index] = to_load[i]; }
template<class T> void layer<T>:: Print(){
cout << "\n[\t";
int i;
for ( i = 0; i < col; i++ )
cout << "w:" << weight[i] << "\t";
cout << "]";
for ( i = 0; i < row; i++ ){
for ( int e = 0; e < col; e++ ){
if ( e == 0 )
cout << "\n[\t";
cout << setprecision(2) << matrix[i][e] << "\t";
if ( e == col-1 )
cout << "]";
}
}
}
template<class T> void layer<T>:: SetConstant( T n ){
for ( int i = 0; i < row; i++ )
for ( int e = 0; e < col; e++ )
matrix[i][e] = n; }
template<class T> void layer<T>:: annealing( VECTOR input, int len, VECTOR output, int length ){
annealing_length = len;
int one = 0, two = 0;
for ( int i = 0; i < length; i++ ){
one += (int) output[i];
two += (int) annealing_result[i];}
annealing_energy = (T) (float)(two-one);
annealing_probability = (T)exp(-1*annealing_energy/annealing_temperature);
if ( annealing_energy < 0 || ((rand() % 2)+1)/rand() < annealing_probability ){
CopyVector( annealing_input, input, len );
int flip = rand() % len;
annealing_input[flip] = !(annealing_input[flip]);
annealing_update++;
}
if ( annealing_update >= annealing_M ){
annealing_update = 0;
annealing_temperature *= annealing_alpha;
}
}
template<class T> void layer<T>:: set_annealing( VECTOR initial, int len, T temperature, T alpha, int M ){
annealing_on = true;
CopyVector( annealing_input, initial, len );
annealing_temperature = temperature;
annealing_alpha = alpha;
annealing_M = M;
}
template<class T> void layer<T>:: write( ostream &output ){
output << '\n' << row << " " << col << '\n';
int i;
for ( i = 0; i < col; i++ )
output << setw(8) << weight[i];
for ( i = 0; i < row; i++ ){
for ( int e = 0; e < col; e++ ){
if ( e == 0 )
output << "\n";
output << setw(8) << setprecision(2) << matrix[i][e];
}
}
}
template<class T> void layer<T>:: read( istream &input ){
input >> row >> col;
set_defaults();
define( row, col );
int i;
for ( i = 0; i < col; i++ )
input >> weight[i];
for ( i = 0; i < row; i++ ){
for ( int e = 0; e < col; e++ ){
input >> matrix[i][e];}
}
}
template<class T> void layer<T>:: define_recurrent(){
ClearVector( NULL_VECTOR, NN_UTIL_SIZE-1, 0 );
network_recurrent = true;
length = 0;
}
template<class T> void layer<T>:: add( layer<T> **ADD ){ layers[length] = (*ADD); length++; }
template<class T> void layer<T>::FeedForward( MATRIX input, MATRIX &final, int inputs ){ FeedForward_recurrent( input, final, inputs ); }
template<class T> int layer<T>::THETA( int x ){ return ( x >= 1 ? 1 : 0 ); }
template<class T> int layer<T>::F( int x, int e, int l ){ return x-(abs(x-e)*THETA(x-e))-(abs(x-l)*THETA(x-l)); }
template<class T> void layer<T>:: FeedForward_recurrent( MATRIX input, MATRIX &final, int inputs ){
int interations = length+inputs-1;
int e = ( inputs <= length ? inputs : length );
int l = ( length >= inputs ? length : inputs );
for ( int t = 1; t <= interations; t++ ){
int w = ( t-inputs > 0 ? t-inputs : 0 );
for ( int a = w; a <= w+F(t, e, l)-1; a++ ){
VECTOR shoot;
Merge( shoot,
( t-a == 0 ? NULL_VECTOR : history[a][t-a-1] ), layers[a]->col,
( a == 0 ? input[t-1] : history[a-1][t-a] ), layers[a]->row-layers[a]->col );
layers[a]->FeedForward( shoot, history[a][t-a] );
if ( a == length-1 ){ CopyVector( final[t-length], history[a][t-a], layers[a]->col ); }
}
}
}
template<class T> void layer<T>:: BackPropagate_recurrent( MATRIX input, MATRIX target, T learning_rate, int inputs ){
int interations = length+inputs-1;
int e = ( inputs <= length ? inputs : length );
int l = ( length >= inputs ? length : inputs );
for ( int t = interations; t >= 1; t-- ){
int w = ( t-inputs > 0 ? t-inputs : 0 );
for ( int a = w+F(t, e, l)-1; a >= w; a-- ){
VECTOR shoot;
Merge( shoot,
( t-a == 0 ? NULL_VECTOR : history[a][t-a-1] ), layers[a]->col,
( a == 0 ? input[t-1] : history[a-1][t-a] ), layers[a]->row-layers[a]->col );
layers[a]->UpdateLayer( ( a == length-1 ? target[t-length] : history[a+1][t-a] ),
history[a][t-a], layers[a]->col, learning_rate,
shoot, history[a][t-a], ( a == length-1 ? true : false ) );
}
}
}
// void layer<T>:: Train( int interations, float learning_rate );
template<class T> void layer<T>:: Merge( VECTOR &destination, VECTOR first, int len1, VECTOR second, int len2 ){
CopyVector( destination, first, len1 );
for ( int i = 0; i < len2; i++ ){ destination[i+len1] = second[i]; } }
template<class T> void layer<T>:: SetConstant_recurrent( T n ){
for ( int i = 0; i < length; i++ )
layers[i]->SetConstant( n ); }
template<class T> void layer<T>:: SetConstant_recurrent( int index, T n ){
layers[index]->SetConstant( n ); }
/*User defined feed forward sweep function*/
template<class T> T layer<T>::function( VECTOR in, VECTOR weight, T bias, int length, bool output){ return 0; };
/*User defined functino to update a layer in a back propagation sweep*/
template<class T> void layer<T>:: UpdateLayer( VECTOR target, VECTOR &new_target, int length,
T learning_rate, VECTOR input, VECTOR result, bool output ){};
template nn_utility::layer<double>;
template nn_utility::layer<float>;
template nn_utility::layer<int>;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -