splitting the list in two parts in java - java

I have a array which is inside the for loop which is to be first converted to an list and then split into 2 halves the first part of the list is being stored in s1 list and second part is being stored in w1,this is to be done recursively till the loop ends and in the end of the method i will be returning both s1 and w1 this is the code i have done so far-:
public Pair daubTrans( double s[] ) throws Exception
{
final int N = s.length;
int n;
//double t1[] = new double[100000];
//List<Double> t1 = new ArrayList<Double>();
// double s1[] = new double[100000];
List<double[]> w1 = new ArrayList<double[]>();
List<double[]> s1 = new ArrayList<double[]>();
List<double[]> lList = new ArrayList<double[]>();
//List<double[]> t1 = new ArrayList<double[]>();
for (n = N; n >= 4; n >>= 1) {
double[] t1= transform( s, n );
int length = t1.length;
// System.out.println(n);
// LinkedList<double> t1 =new LinkedList<double>( Arrays.asList(t1));
/* for(double[] d: t1)
{
t1.add(d);
}*/
lList = Arrays.asList(t1);
length=lList.size();
//System.out.print(lList.size());
// System.arraycopy(src, srcPos, dest, destPos, length)
/* s1= t1.subList(0, 1);
w1= t1.subList(0, 1); */
/* if(n==N)
{
s1= lList.subList(0, length/2-1);
w1= lList.subList(length/2-1, length);
}
else
{
s1=lList.subList(( length/2), length);
w1=lList.subList(( length/2), length);
} */
// System.arraycopy(t1,0, s1, n==N?0:t1.size()/2-1, t1.size()/2-1);
// System.arraycopy(t1,(length/2), w1, n==N?0:t1.size()/2-1, t1.size()/2-1);
// System.out.println(w1.length);
}
return new Pair(s1, w1);
}
where pair class is defined so as to return the 2 list and transform returns an array of type double which is being stored in t1 array.
now i am getting problem in converting t1 array to list type and also on how to split the list formed by elements of t1 into 2 parts. THE CODE FOR TRANSFORM IS -:
protected double[] transform( double a[], int n )
{
if (n >= 4) {
int i, j;
int half = n >> 1;
double tmp[] = new double[n];
i = 0;
for (j = 0; j < n-3; j = j + 2) {
tmp[i] = a[j]*h0 + a[j+1]*h1 + a[j+2]*h2 + a[j+3]*h3;
tmp[i+half] = a[j]*g0 + a[j+1]*g1 + a[j+2]*g2 + a[j+3]*g3;
i++;
}
// System.out.println(i);
tmp[i] = a[n-2]*h0 + a[n-1]*h1 + a[0]*h2 + a[1]*h3;
tmp[i+half] = a[n-2]*g0 + a[n-1]*g1 + a[0]*g2 + a[1]*g3;
for (i = 0; i < n; i++) {
a[i] = tmp[i];
}
}
return a;
} // transform
this is the whole code-:
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.lang.Math.*;
class daub {
protected final double sqrt_3 = Math.sqrt( 3 );
protected final double denom = 4 * Math.sqrt( 2 );
//
// forward transform scaling (smoothing) coefficients
//
protected final double h0 = (1 + sqrt_3)/denom;
protected final double h1 = (3 + sqrt_3)/denom;
protected final double h2 = (3 - sqrt_3)/denom;
protected final double h3 = (1 - sqrt_3)/denom;
//
// forward transform wavelet coefficients
//
protected final double g0 = h3;
protected final double g1 = -h2;
protected final double g2 = h1;
protected final double g3 = -h0;
//
// Inverse transform coefficients for smoothed values
//
protected final double Ih0 = h2;
protected final double Ih1 = g2; // h1
protected final double Ih2 = h0;
protected final double Ih3 = g0; // h3
//
// Inverse transform for wavelet values
//
protected final double Ig0 = h3;
protected final double Ig1 = g3; // -h0
protected final double Ig2 = h1;
protected final double Ig3 = g1; // -h2
List<Double> doubleList = new ArrayList<Double>();
/**
<p>
Forward wavelet transform.
protected double[] transform( double a[], int n )
{
if (n >= 4) {
int i, j;
int half = n >> 1;
double tmp[] = new double[n];
i = 0;
for (j = 0; j < n-3; j = j + 2) {
tmp[i] = a[j]*h0 + a[j+1]*h1 + a[j+2]*h2 + a[j+3]*h3;
tmp[i+half] = a[j]*g0 + a[j+1]*g1 + a[j+2]*g2 + a[j+3]*g3;
i++;
}
// System.out.println(i);
tmp[i] = a[n-2]*h0 + a[n-1]*h1 + a[0]*h2 + a[1]*h3;
tmp[i+half] = a[n-2]*g0 + a[n-1]*g1 + a[0]*g2 + a[1]*g3;
for (i = 0; i < n; i++) {
a[i] = tmp[i];
}
}
return a;
} // transform
protected void invTransform( double a[], int n )
{
if (n >= 4) {
int i, j;
int half = n >> 1;
int halfPls1 = half + 1;
double tmp[] = new double[n];
// last smooth val last coef. first smooth first coef
tmp[0] = a[half-1]*Ih0 + a[n-1]*Ih1 + a[0]*Ih2 + a[half]*Ih3;
tmp[1] = a[half-1]*Ig0 + a[n-1]*Ig1 + a[0]*Ig2 + a[half]*Ig3;
j = 2;
for (i = 0; i < half-1; i++) {
// smooth val coef. val smooth val coef. val
tmp[j++] = a[i]*Ih0 + a[i+half]*Ih1 + a[i+1]*Ih2 + a[i+halfPls1]*Ih3;
tmp[j++] = a[i]*Ig0 + a[i+half]*Ig1 + a[i+1]*Ig2 + a[i+halfPls1]*Ig3;
}
for (i = 0; i < n; i++) {
a[i] = tmp[i];
}
}
}
/**
Forward Daubechies D4 transform
*/
public Pair daubTrans( double s[] ) throws Exception
{
final int N = s.length;
int n;
//double t1[] = new double[100000];
//List<Double> t1 = new ArrayList<Double>();
// double s1[] = new double[100000];
List<double[]> w1 = new ArrayList<double[]>();
List<double[]> s1 = new ArrayList<double[]>();
List<double[]> lList = new ArrayList<double[]>();
//List<double[]> t1 = new ArrayList<double[]>();
for (n = N; n >= 4; n >>= 1) {
double[] t1= transform( s, n );
int length = t1.length;
// System.out.println(n);
// LinkedList<double> t1 =new LinkedList<double>( Arrays.asList(t1));
/* for(double[] d: t1)
{
t1.add(d);
}*/
lList = Arrays.asList(t1);
length=lList.size();
//System.out.print(lList.size());
// System.arraycopy(src, srcPos, dest, destPos, length)
/* s1= t1.subList(0, 1);
w1= t1.subList(0, 1); */
if(n==N)
{
s1= lList.subList(0, length/2-1);
w1= lList.subList(length/2-1, length);
}
else
{
s1=lList.subList(( length/2), length);
w1=lList.subList(( length/2), length);
}
// System.arraycopy(t1,0, s1, n==N?0:t1.size()/2-1, t1.size()/2-1);
// System.arraycopy(t1,(length/2), w1, n==N?0:t1.size()/2-1, t1.size()/2-1);
// System.out.println(w1.length);
}
return new Pair(s1, w1);
}
/**

Please add the code of transform(s,n) to this question.
Why this? for (n = N; n >= 4; n >>= 1) {} It seems to be easier: for (int n = N; n >= 4; n--) {}
This is crazy: List<double[]> If you'd like to use a list of doubles then use this: List<double>
What is the result that you would like to see?

Related

High memory usage in java program (lots of recursion with arrays)

I am having a problem that has been bugging me for few days now. I am doing a college asignment where i have to multiply 2 big numbers (each number can be up to 10000 digits), for that reason i have to use arrays.
I have to use naive divide and conquer method using a special formula and it is working, i get the correct output.
The problem though is that program's ram usage peaks at 715MB while the college server which will test my outputs only permits peaks less then 10MB !
I used visualVM to get some statistics and it shows that at the end of main method i have over 25.000 int arrays opened, which obviously means that garbage collector won't clean them. I tried manualy removing arrays by array = null but it has no effect. Even more, size of arrays in program has no effect on ram usage, if i make all arrays of size 10000 or if i make them smaller, ram usage is still 715MB. Nothing i tried has made even 1Kb difference in ram usage. What am i doing wrong ?
import java.util.*;
public class Naloga2 {
static int firstNumberLength;
static int secondNumberLength;
static int count;
public static void main(String[] args) {
firstNumberLength = 0;
secondNumberLength = 0;
start(args);
System.out.println("Check memory usage and press any key");
Scanner scan = new Scanner(System.in);
scan.nextLine();
}
static void printArray(int[] a, int length) {
for(int i=0;i<length;i++) System.out.print(a[i]);
System.out.println();
}
static void printArrayNoNewLine(int[] a, int length) {
for(int i=0;i<length;i++) System.out.print(a[i]);
}
static int[] obrniTabelo(int[] tabela, int dolzinaTabele) {
int[] novaTabela = new int[firstNumberLength + secondNumberLength];
for(int i=0;i<dolzinaTabele;i++) {
novaTabela[i] = tabela[dolzinaTabele - i - 1];
}
return novaTabela;
}
static void readNumbers(int[] a, int[] b) {
Scanner sc = new Scanner(System.in);
String temp1 = "1814760427359093701773634896055154238604621068079345503988844965147764988324706056377247443923778795928948605699104801900306908537904148935233121873094936503998915865745862371767010306054062906768898568957847355344002122176514654744790212626620584107994283130875249861052935175219132106429755509971192581933953801388381188460986660581979158129483917001271702223407654800335931472019985629221607213865018069283189966200621625300134";
String temp2 = "97512060979417027247066473890437645860252983792423404628415959133594150264916901106891610016700858329869623573382829998749019896997745761637960733420798357562414782788848733769941600640359229331196534760613331886605807310229536529299047661042932723686940506490467693828359124032044766542882911974806517818312853119004786073768385133003204124346870416398337405003873260912959735781385513491033737150032844086069531948792576932151901897811096445945530418292434773408981209319417729967465446257427784080363848953538788259430643983374127862528899812266699138053211381274176090725067261872355977420957399650610409274997690573284775365452519492094199150332836530293736450846555043855394905294740708235099468050036111579819724363868989787277506605869758256547608040247461962450653542826639244219294087064008107664753142535552152880164752050308970662812876788273331513642358933315796998961151437131149920030780118660547331872894504653590764949555989125948482198399816531852334011945495558518939896596518131272300822293060394523495515862731265541258202053045616084735425799134171661329905235453695720851880506732702524221829703587444566936446048580047972702945614278702240636251666791566010549308512827456794434888225729025123511920552233844557238739513734443927750297099927757353661453279831551902974620243283691649185034824294607701567938075725970651517685420371143465190361476038554928265834067374093805712372282561321345651430079136538347289657425955000036298701183558407903511884604388721633166414508318158";
firstNumberLength = temp1.length();
secondNumberLength = temp2.length();
for(int i=0;i<firstNumberLength;i++) a[i] = temp1.charAt(i) - 48;
for(int i=0;i<secondNumberLength;i++) b[i] = temp2.charAt(i) - 48;
}
static void start(String[] args) {
int a[] = new int[10000];
int b[] = new int[10000];
readNumbers(a, b);
int aa[] = new int[firstNumberLength];
int bb[] = new int[secondNumberLength];
for(int i=0;i<firstNumberLength;i++) aa[i] = a[i];
for(int i=0;i<secondNumberLength;i++) bb[i] = b[i];
dv(aa, bb, "count");
}
static int[] steviloPlusSteviloRu (int[] a, int[] b, int[] tempDolzina) {
a = obrniTabelo(a, tempDolzina[0]);
b = obrniTabelo(b, tempDolzina[1]);
int prenos = 0;
if(tempDolzina[0] < tempDolzina[1]) {
tempDolzina[0] = tempDolzina[1];
}
int limit = tempDolzina[1];
for(int i=0;i<tempDolzina[1];i++) {
a[i] = a[i] + b[i] + prenos;
prenos = 0;
if(a[i] > 9) {
prenos = a[i] / 10;
a[i] = a[i] % 10;
}
}
while(prenos > 0) {
if(prenos > 9) System.out.println("prenos nad 9, error !");
a[limit] = a[limit] + prenos;
prenos = 0;
if(a[limit] > 9) {
prenos = a[limit] / 10;
a[limit] = a[limit] % 10;
}
if(limit == tempDolzina[0]) tempDolzina[0]++;
limit++;
}
a = obrniTabelo(a, tempDolzina[0]);
return a;
}
static int[] stevkaKratSteviloDv(int[] a, int b, int[] length) { // dv - mnozenje z stevko
int prenos = 0;
a = obrniTabelo(a, length[0]);
for(int i=0;i<length[0];i++) {
a[i] = a[i] * b + prenos;
prenos = 0;
if(a[i] > 9) {
prenos = a[i] / 10;
a[i] = a[i] % 10;
}
}
if(prenos > 0 ) {
if(prenos > 9) System.out.println("prenos vecji od 9 !!");
a[length[0]] = prenos;
length[0]++;
}
a = obrniTabelo(a, length[0]);
return a;
}
static void dv(int[] a, int[] b, String m) { // dk
int mode = 0;
if(m.equals("count")) mode = 1;
if(mode == 1) {
printArray(a, firstNumberLength);
printArray(b, secondNumberLength);
}
int[] dolzine = {firstNumberLength, secondNumberLength};
int[] dolzina = {firstNumberLength, secondNumberLength};
int[] len1 = {firstNumberLength};
int[] len2 = {secondNumberLength};
int[] len3 = new int[1];
int[] rezultat = dvRek(a, b, len1, len2, len3, mode);
rezultat = odstrani(rezultat, len3);
if(mode == 0) {
printArray(rezultat, len3[0]);
} else System.out.println(count);
}
static int[] subSet(int[] aa, int[] length, int mode) { // returns subset, depends on mode
int dolzina = length[0];
if(dolzina < 2) {
System.out.println("error, dolzina je " + dolzina);
return aa;
}
int start = 0;
int stop = dolzina / 2;
if(mode == 1) {
start = dolzina / 2;
stop = dolzina;
}
int[] temp = new int[length[0]];
int index = 0;
for(int i=start;i<stop;i++) {
temp[index] = aa[i];
index++;
}
length[0] = (stop - start);
aa = null;
return temp;
}
static int[] dodajNicle(int[] aa, int[] length, int num) { // adds zeroes, basicly multiplying with 10^num
int[] temp = new int[length[0] + num];
for(int i=0;i<length[0];i++) temp[i] = aa[i];
for(int i=0;i<num;i++) {
temp[length[0]] = 0;
length[0]++;
}
aa = null;
return temp;
}
static int[] dopolni(int[] aa, int[] length, int num) { // adds num zeros at start and returns
aa = obrniTabelo(aa, length[0]);
int start = length[0];
int end = start + num;
for(int i=start;i<end;i++) aa[i] = 0;
length[0] = length[0] + num;
aa = obrniTabelo(aa, length[0]);
return aa;
}
static int[] odstrani(int[] aa, int[] length) { // removes zeros from beginning
aa = obrniTabelo(aa, length[0]);
for(int i=(length[0]-1);i>0;i--)
if(aa[i] == 0) length[0]--;
else break;
aa = obrniTabelo(aa, length[0]);
return aa;
}
static int[] dvRek (int[] a, int[] b, int[] lengthA, int[] lengthB, int[] lengthC, int mode) {
a = odstrani(a, lengthA);
b = odstrani(b, lengthB);
if(mode == 0) {
printArrayNoNewLine(a, lengthA[0]);
System.out.print(" ");
printArray(b, lengthB[0]);
}
if(lengthA[0] == 1) {
if(a[0] == 0) {
lengthC[0] = 1;
return new int[1];
}
int temp = lengthB[0];
int minus = 0;
for(int i=0;i<temp;i++) {
if(b[i] == 0) minus++;
if(b[i] > 0) break;
}
count = count + temp - minus;
b = stevkaKratSteviloDv(b, a[0], lengthB);
lengthC[0] = lengthB[0];
lengthB[0] = temp;
return b;
} else if (lengthB[0] == 1) {
if(b[0] == 0) {
lengthC[0] = 1;
return new int[1];
}
int temp = lengthA[0];
int minus = 0;
for(int i=0;i<temp;i++) {
if(a[i] == 0) minus++;
if(a[i] > 0) break;
}
count = count + temp - minus;
a = stevkaKratSteviloDv(a, b[0], lengthA);
lengthC[0] = lengthA[0];
return a;
} else {
if(lengthA[0] > lengthB[0]) {
b = dopolni(b, lengthB, (lengthA[0] - lengthB[0]));
}
else if (lengthA[0] < lengthB[0]) {
a = dopolni(a, lengthA, (lengthB[0] - lengthA[0]));
}
int[] a1Len = { lengthA[0] };
int[] a0Len = { lengthA[0] };
int[] b1Len = { lengthB[0] };
int[] b0Len = { lengthB[0] };
int[] a1 = subSet(a, a1Len, 0);
int[] a0 = subSet(a, a0Len, 1);
int[] b1 = subSet(b, b1Len, 0);
int[] b0 = subSet(b, b0Len, 1);
a = null;
b = null;
int[] temp = new int[1];
int[] tempp = new int[1];
temp[0] = b0Len[0];
tempp[0] = a0Len[0];
int[] a0b0 = dvRek(a0, b0, tempp, temp, lengthC, mode);
int[] a0b0Len = { lengthC[0] };
temp[0] = b1Len[0];
tempp[0] = a0Len[0];
int[] a0b1 = dvRek(a0, b1, tempp, temp, lengthC, mode);
int[] a0b1Len = { lengthC[0] };
//a1b0
temp[0] = b0Len[0];
tempp[0] = a1Len[0];
int[] a1b0 = dvRek(a1, b0, tempp, temp, lengthC, mode);
int[] a1b0Len = { lengthC[0] };
//a1b1
temp[0] = b1Len[0];
tempp[0] = a1Len[0];
int[] a1b1 = dvRek(a1, b1, tempp, temp, lengthC, mode);
int[] a1b1Len = { lengthC[0] };
int n = lengthA[0];
if(lengthB[0] > n) n = lengthB[0];
if(n % 2 != 0) n++;
int[] temp1 = dodajNicle(a1b1, a1b1Len, n );
int[] dolzine = {a0b1Len[0], a1b0Len[0]};
int[] temp2 = steviloPlusSteviloRu(a0b1, a1b0, dolzine);
temp2 = dodajNicle(temp2, dolzine, (n/2) );
int[] dolzine1 = {a1b1Len[0], dolzine[0]};
int[] temp3 = steviloPlusSteviloRu(temp1, temp2, dolzine1);
int[] dolzine2 = {dolzine1[0], a0b0Len[0] };
int[] temp4 = steviloPlusSteviloRu(temp3, a0b0, dolzine2);
lengthC[0] = dolzine2[0];
a = null;
b = null;
a0b0 = null;
a1b0 = null;
a0b1 = null;
a1b1 = null;
a0 = null;
a1 = null;
b0 = null;
b1 = null;
lengthA = null;
lengthB = null;
lengthC = null;
temp = null;
tempp = null;
dolzine = null;
dolzine1 = null;
dolzine2 = null;
temp1 = null;
temp2 = null;
temp3 = null;
return temp4;
}
}
}

Test method for multilayer perceptron

This is Multi-Layer Perceptron using Backpropagation algorithm.I found this code on codetidy.com and i want to test it .
"mlp.java"
/***** This ANN assumes a fully connected network *****/
import java.util.*;
import java.io.*;
public class MLP {
static ArrayList<Neuron> input, hidden, output;
ArrayList<Pattern> pattern;
static double bias;
double learningRate;
Random random;
public MLP(int numInput, int numHidden, int numOutput, int rangeMin, int rangeMax, double learningRate, Random random, File f) {
this.learningRate = learningRate;
this.random = random;
input = new ArrayList<Neuron>();
hidden = new ArrayList<Neuron>();
output = new ArrayList<Neuron>();
pattern = readPattern(f);
int i;
// bias is random value between [rangeMin, rangeMax] --> [-1, 1]
bias = 1;//randomDouble(rangeMin, rangeMax);
// initialize inputs
for (i = 0; i < numInput; i++) {
input.add(new Neuron("x"+(i+1), 0, randomDoubleArray(numHidden, rangeMin, rangeMax))); // set initial values to 0
}
// initialize hidden
for (i = 0; i < numHidden; i++) {
hidden.add(new Neuron("h"+(i+1), randomDoubleArray(numOutput, rangeMin, rangeMax)));
}
// initialize output
for (i = 0; i < numOutput; i++) {
output.add(new Neuron("y"+(i+1)));
}
// link inputs forward to hidden
for (Neuron x : input) {
x.connect(hidden, 1);
}
// link hidden
for (Neuron h : hidden) {
// back to inputs
h.connect(input, 0);
// forward to output
h.connect(output, 1);
}
// link output back to hidden
for (Neuron y : output) {
y.connect(hidden, 0);
}
}
void train() {
int i;
double[] error = new double[pattern.size()];
boolean done = false;
// main training loop
while(!done) {
// loop through input patterns, save error for each
for (i = 0; i < pattern.size(); i++) {
/*** Set new pattern ***/
setInput(pattern.get(i).values);
/*** Feed-forward computation ***/
forwardPass();
/*** Backpropagation with weight updates ***/
error[i] = backwardPass();
}
boolean pass = true;
// check if error for all runs is <= 0.05
for (i = 0; i < error.length; i++) {
if (error[i] > 0.05)
pass = false;
}
if (pass) // if all cases <= 0.05, convergence reached
done = true;
}
}
void setInput(int[] values) {
for (int i = 0; i < values.length; i++) {
input.get(i).value = values[i];
}
}
double backwardPass() {
int i;
double[] outputError = new double[output.size()];
double[] outputDelta = new double[output.size()];
double[] hiddenError = new double[hidden.size()];
double[] hiddenDelta = new double[hidden.size()];
/*** Backpropagation to the output layer ***/
// calculate delta for output layer: d = error * sigmoid derivative
for (i = 0; i < output.size(); i++) {
// error = desired - y
outputError[i] = getOutputError(output.get(i));
// using sigmoid derivative = sigmoid(v) * [1 - sigmoid(v)]
outputDelta[i] = outputError[i] * output.get(i).value * (1.0 - output.get(i).value);
}
/*** Backpropagation to the hidden layer ***/
// calculate delta for hidden layer: d = error * sigmoid derivative
for (i = 0; i < hidden.size(); i++) {
// error(i) = sum[outputDelta(k) * w(kj)]
hiddenError[i] = getHiddenError(hidden.get(i), outputDelta);
// using sigmoid derivative
hiddenDelta[i] = hiddenError[i] * hidden.get(i).value * (1.0 - hidden.get(i).value);
}
/*** Weight updates ***/
// update weights connecting hidden neurons to output layer
for (i = 0; i < output.size(); i++) {
for (Neuron h : output.get(i).left) {
h.weights[i] = learningRate * outputDelta[i] * h.value;
}
}
// update weights connecting input neurons to hidden layer
for (i = 0; i < hidden.size(); i++) {
for (Neuron x : hidden.get(i).left) {
x.weights[i] = learningRate * hiddenDelta[i] * x.value;
}
}
// return outputError to be used when testing for convergence?
return outputError[0];
}
void forwardPass() {
int i;
double v, y;
// loop through hidden layers, determine current value
for (i = 0; i < hidden.size(); i++) {
v = 0;
// get v(n) for hidden layer i
for (Neuron x : input) {
v += x.weights[i] * x.value;
}
// add bias
v += bias;
// calculate f(v(n))
y = activate(v);
hidden.get(i).value = y;
}
// calculate output?
for (i = 0; i < output.size(); i++) {
v = 0;
// get v(n) for output layer
for (Neuron h : hidden) {
v += h.weights[i] * h.value;
}
// add bias
v += bias;
// calculate f(v(n))
y = activate(v);
output.get(i).value = y;
}
}
double activate(double v) {
return (1 / (1 + Math.exp(-v))); // sigmoid function
}
double getHiddenError(Neuron j, double[] outputDelta) {
// calculate error sum[outputDelta * w(kj)]
double sum = 0;
for (int i = 0; i < j.right.size(); i++) {
sum += outputDelta[i] * j.weights[i];
}
return sum;
}
double getOutputError(Neuron k) {
// calculate error (d - y)
// note: desired is 1 if input contains odd # of 1's and 0 otherwise
int sum = 0;
double d;
for (Neuron x : input) {
sum += x.value;
}
if (sum % 2 != 0)
d = 1.0;
else
d = 0.0;
return Math.abs(d - k.value);
}
double[] randomDoubleArray(int n, double rangeMin, double rangeMax) {
double[] a = new double[n];
for (int i = 0; i < n; i++) {
a[i] = randomDouble(rangeMin, rangeMax);
}
return a;
}
double randomDouble(double rangeMin, double rangeMax) {
return (rangeMin + (rangeMax - rangeMin) * random.nextDouble());
}
ArrayList<Pattern> readPattern(File f) {
ArrayList<Pattern> p = new ArrayList<Pattern>();
try {
BufferedReader r = new BufferedReader(new FileReader(f));
String s = "";
while ((s = r.readLine()) != null) {
String[] columns = s.split(" ");
int[] values = new int[columns.length];
for (int i = 0; i < values.length; i++) {
values[i] = Integer.parseInt(columns[i]);
}
p.add(new Pattern(values));
}
r.close();
}
catch (IOException e) { }
return p;
}
public static void main(String[] args) {
Random random = new Random(1234);
File file = new File("input.txt");
MLP mlp = new MLP(4, 4, 1, -1, 1, 0.1, random, file);
mlp.train();
}
}
"neuron.java"
import java.util.ArrayList;
public class Neuron {
String name;
double value;
double[] weights;
ArrayList<Neuron> left, right;
public Neuron(String name, double value, double[] weights) { // constructor for input neurons
this.name = name;
this.value = value;
this.weights = weights;
right = new ArrayList<Neuron>();
}
public Neuron(String name, double[] weights) { // constructor for hidden neurons
this.name = name;
this.weights = weights;
value = 0; // default initial value
left = new ArrayList<Neuron>();
right = new ArrayList<Neuron>();
}
public Neuron(String name) { // constructor for output neurons
this.name = name;
value = 0; // default initial value
left = new ArrayList<Neuron>();
}
public void connect(ArrayList<Neuron> ns, int direction) { // 0 is left, 1 is right
for (Neuron n : ns) {
if (direction == 0)
left.add(n);
else
right.add(n);
}
}
}
"pattern.java"
public class Pattern {
int [] values;
public Pattern (int [] Values)
{
this.values=Values;
}
}
How can i count the correct and wrong classified samples?

FFT returns large values which become NaN

I'm using a FFT class to get the fundamental frequency. I'm passing an array of some double values. Array is like queue. when add a new values array will be updated. But my problem is output array will become large numbers time to time. Its become E to the power value and finally returns NaN. Im using below FFT class and I'm confused in where is the problem. Its a big help if anyone can give a help by figuring out the cause.
here is my FFT class
public class FFT {
int n, m;
// Lookup tables. Only need to recompute when size of FFT changes.
double[] cos;
double[] sin;
double[] window;
public FFT(int n) {
this.n = n;
this.m = (int)(Math.log(n) / Math.log(2));
// Make sure n is a power of 2
if(n != (1<<m))
throw new RuntimeException("FFT length must be power of 2");
// precompute tables
cos = new double[n/2];
sin = new double[n/2];
// for(int i=0; i<n/4; i++) {
// cos[i] = Math.cos(-2*Math.PI*i/n);
// sin[n/4-i] = cos[i];
// cos[n/2-i] = -cos[i];
// sin[n/4+i] = cos[i];
// cos[n/2+i] = -cos[i];
// sin[n*3/4-i] = -cos[i];
// cos[n-i] = cos[i];
// sin[n*3/4+i] = -cos[i];
// }
for(int i=0; i<n/2; i++) {
cos[i] = Math.cos(-2*Math.PI*i/n);
sin[i] = Math.sin(-2*Math.PI*i/n);
}
makeWindow();
}
protected void makeWindow() {
// Make a blackman window:
// w(n)=0.42-0.5cos{(2*PI*n)/(N-1)}+0.08cos{(4*PI*n)/(N-1)};
window = new double[n];
for(int i = 0; i < window.length; i++)
window[i] = 0.42 - 0.5 * Math.cos(2*Math.PI*i/(n-1))
+ 0.08 * Math.cos(4*Math.PI*i/(n-1));
}
public double[] getWindow() {
return window;
}
/***************************************************************
* fft.c
* Douglas L. Jones
* University of Illinois at Urbana-Champaign
* January 19, 1992
* http://cnx.rice.edu/content/m12016/latest/
*
* fft: in-place radix-2 DIT DFT of a complex input
*
* input:
* n: length of FFT: must be a power of two
* m: n = 2**m
* input/output
* x: double array of length n with real part of data
* y: double array of length n with imag part of data
*
* Permission to copy and use this program is granted
* as long as this header is included.
****************************************************************/
public void fft(double[] x, double[] y)
{
int i,j,k,n1,n2,a;
double c,s,e,t1,t2;
// Bit-reverse
j = 0;
n2 = n/2;
for (i=1; i < n - 1; i++) {
n1 = n2;
while ( j >= n1 ) {
j = j - n1;
n1 = n1/2;
}
j = j + n1;
if (i < j) {
t1 = x[i];
x[i] = x[j];
x[j] = t1;
t1 = y[i];
y[i] = y[j];
y[j] = t1;
}
}
// FFT
n1 = 0;
n2 = 1;
for (i=0; i < m; i++) {
n1 = n2;
n2 = n2 + n2;
a = 0;
for (j=0; j < n1; j++) {
c = cos[a];
s = sin[a];
a += 1 << (m-i-1);
for (k=j; k < n; k=k+n2) {
t1 = c*x[k+n1] - s*y[k+n1];
t2 = s*x[k+n1] + c*y[k+n1];
x[k+n1] = x[k] - t1;
y[k+n1] = y[k] - t2;
x[k] = x[k] + t1;
y[k] = y[k] + t2;
}
}
}
}
// Test the FFT to make sure it's working
public static void main(String[] args) {
int N = 8;
FFT fft = new FFT(N);
double[] window = fft.getWindow();
double[] re = new double[N];
double[] im = new double[N];
// Impulse
re[0] = 1; im[0] = 0;
for(int i=1; i<N; i++)
re[i] = im[i] = 0;
beforeAfter(fft, re, im);
// Nyquist
for(int i=0; i<N; i++) {
re[i] = Math.pow(-1, i);
im[i] = 0;
}
beforeAfter(fft, re, im);
// Single sin
for(int i=0; i<N; i++) {
re[i] = Math.cos(2*Math.PI*i / N);
im[i] = 0;
}
beforeAfter(fft, re, im);
// Ramp
for(int i=0; i<N; i++) {
re[i] = i;
im[i] = 0;
}
beforeAfter(fft, re, im);
long time = System.currentTimeMillis();
double iter = 30000;
for(int i=0; i<iter; i++)
fft.fft(re,im);
time = System.currentTimeMillis() - time;
System.out.println("Averaged " + (time/iter) + "ms per iteration");
}
protected static void beforeAfter(FFT fft, double[] re, double[] im) {
System.out.println("Before: ");
printReIm(re, im);
fft.fft(re, im);
System.out.println("After: ");
printReIm(re, im);
}
protected static void printReIm(double[] re, double[] im) {
System.out.print("Re: [");
for(int i=0; i<re.length; i++)
System.out.print(((int)(re[i]*1000)/1000.0) + " ");
System.out.print("]\nIm: [");
for(int i=0; i<im.length; i++)
System.out.print(((int)(im[i]*1000)/1000.0) + " ");
System.out.println("]");
}
}
Below is my main activity class in android which uses the FFT instance
public class MainActivity extends Activity implements SensorEventListener{
static final float ALPHA = 0.15f;
private int count=0;
private static GraphicalView view;
private LineGraph line = new LineGraph();
private static Thread thread;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
TextView title,tv,tv1,tv2,tv3,tv4,tv5,tv6;
RelativeLayout layout;
private double a;
private double m = 0;
private float p,q,r;
public long[] myList;
public double[] myList2;
public double[] gettedList;
static String k1,k2,k3,k4;
int iniX=0;
public FFT fft;
public myArray myArrayQueue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fft=new FFT(128);
myList=new long[128];
myList2=new double[128];
gettedList=new double[128];
myArrayQueue=new myArray(128);
//get the sensor service
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//get the accelerometer sensor
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//get layout
layout = (RelativeLayout)findViewById(R.id.relative);
LinearLayout layout = (LinearLayout) findViewById(R.id.layoutC);
view= line.getView(this);
layout.addView(view);
//get textviews
title=(TextView)findViewById(R.id.name);
//tv=(TextView)findViewById(R.id.xval);
//tv1=(TextView)findViewById(R.id.yval);
//tv2=(TextView)findViewById(R.id.zval);
tv3=(TextView)findViewById(R.id.TextView04);
tv4=(TextView)findViewById(R.id.TextView01);
tv5=(TextView)findViewById(R.id.TextView02);
tv6=(TextView)findViewById(R.id.TextView03);
for (int i = 0; i < myList2.length; i++){
myList2[i] =0;
}
}
public final void onAccuracyChanged(Sensor sensor, int accuracy)
{
// Do something here if sensor accuracy changes.
}
#Override
public final void onSensorChanged(SensorEvent event)
{
count=+1;
// Many sensors return 3 values, one for each axis.
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
//float[] first={x,y,z};
// float[] larst={p,q,r};
//larst= lowPass(first,larst);
//double FY= b.Filter(y);
//double FZ= b.Filter(z);
//get merged value
// m = (float) Math.sqrt(larst[0]*larst[0]+larst[1]*larst[1]+larst[2]*larst[2]);
m=(double)Math.sqrt(x*x+y*y+z*z);
//display values using TextView
//title.setText(R.string.app_name);
//tv.setText("X axis" +"\t\t"+x);
//tv1.setText("Y axis" + "\t\t" +y);
//tv2.setText("Z axis" +"\t\t" +z);
//myList[iniX]=m*m;
//myList[iniX+1]=myList[iniX];
iniX=+1;
//myList[3]=myList[2];
//myList[2]=myList[1];
//myList[1]=myList[0];
myArrayQueue.insert(m*m);
gettedList=myArrayQueue.getMyList();
/* for(int a = myList.length-1;a>0;a--)
{
myList[a]=myList[a-1];
}
myList[0]=m*m;
*/
fft.fft(gettedList, myList2);
k1=Double.toString(myList2[0]);
k2=Double.toString(myList2[1]);
k3=Double.toString(myList2[2]);
k4=Double.toString(myList2[3]);
tv3.setText("[0]= "+k1);
tv4.setText("[1]= "+k2);
tv5.setText("[2]= "+k3);
tv6.setText("[3]= "+k4);
line.addNewPoint(iniX,(float) m);
view.repaint();
}
#Override
protected void onResume()
{
super.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause()
{
super.onPause();
mSensorManager.unregisterListener(this);
}
public void LineGraphHandler(View view){
}
//Low pass filter
protected float[] lowPass( float[] input, float[] output ) {
if ( output == null ) return input;
for ( int i=0; i<input.length; i++ ) {
output[i] = output[i] + ALPHA * (input[i] - output[i]);
}
return output;
}
/*#Override
public void onStart(){
super.onStart();
view= line.getView(this);
setContentView(view);
}*/
}
An FFT output will only produce NaNs if the input contains them. So explicitly check the input array to the FFT for any out-of-range values before calling it to debug your code. Then work backwards from there to find out where they are coming from.

Is there some empirical mode decomposition library in java? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 6 years ago.
Improve this question
I would like to ask you about any empirical mode decomposition library written in java. I cannot find any. Best if it is open source.
Thank you
I have just found a C implementation ( https://code.google.com/p/realtime-emd/ ) and translated it to Java. So please note that this code snipped is not Java styled code, it is just Java code that compiles and runs.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tryout.emd;
/**
*
* #author Krusty
*/
public class Emd {
private void emdSetup(EmdData emd, int order, int iterations, int locality) {
emd.iterations = iterations;
emd.order = order;
emd.locality = locality;
emd.size = 0;
emd.imfs = null;
emd.residue = null;
emd.minPoints = null;
emd.maxPoints = null;
emd.min = null;
emd.max = null;
}
private void emdResize(EmdData emd, int size) {
int i;
// emdClear(emd);
emd.size = size;
emd.imfs = new double[emd.order][]; // cnew(double*, emd->order);
for(i = 0; i < emd.order; i++) emd.imfs[i] = new double[size]; // cnew(double, size);
emd.residue = new double[size]; // cnew(double, size);
emd.minPoints = new int[size / 2]; // cnew(int, size / 2);
emd.maxPoints = new int[size/2]; //cnew(int, size / 2);
emd.min = new double[size]; // cnew(double, size);
emd.max = new double[size]; // cnew(double, size);
}
private void emdCreate(EmdData emd, int size, int order, int iterations, int locality) {
emdSetup(emd, order, iterations, locality);
emdResize(emd, size);
}
private void emdDecompose(EmdData emd, double[] signal) {
int i, j;
System.arraycopy(signal, 0, emd.imfs[0], 0, emd.size); // memcpy(emd->imfs[0], signal, emd->size * sizeof(double));
System.arraycopy(signal, 0, emd.residue, 0, emd.size); // memcpy(emd->residue, signal, emd->size * sizeof(double));
for(i = 0; i < emd.order - 1; i++) {
double[] curImf = emd.imfs[i]; // double* curImf = emd->imfs[i];
for(j = 0; j < emd.iterations; j++) {
emdMakeExtrema(emd, curImf);
if(emd.minSize < 4 || emd.maxSize < 4) break; // can't fit splines
emdInterpolate(emd, curImf, emd.min, emd.minPoints, emd.minSize);
emdInterpolate(emd, curImf, emd.max, emd.maxPoints, emd.maxSize);
emdUpdateImf(emd, curImf);
}
emdMakeResidue(emd, curImf);
System.arraycopy(emd.residue, 0, emd.imfs[i+1], 0, emd.size); // memcpy(emd->imfs[i + 1], emd->residue, emd->size * sizeof(double));
}
}
// Currently, extrema within (locality) of the boundaries are not allowed.
// A better algorithm might be to collect all the extrema, and then assume
// that extrema near the boundaries are valid, working toward the center.
private void emdMakeExtrema(EmdData emd, double[] curImf) {
int i, lastMin = 0, lastMax = 0;
emd.minSize = 0;
emd.maxSize = 0;
for(i = 1; i < emd.size - 1; i++) {
if(curImf[i - 1] < curImf[i]) {
if(curImf[i] > curImf[i + 1] && (i - lastMax) > emd.locality) {
emd.maxPoints[emd.maxSize++] = i;
lastMax = i;
}
} else {
if(curImf[i] < curImf[i + 1] && (i - lastMin) > emd.locality) {
emd.minPoints[emd.minSize++] = i;
lastMin = i;
}
}
}
}
private void emdInterpolate(EmdData emd, double[] in, double[] out, int[] points, int pointsSize) {
int size = emd.size;
int i, j, i0, i1, i2, i3, start, end;
double a0, a1, a2, a3;
double y0, y1, y2, y3, muScale, mu;
for(i = -1; i < pointsSize; i++) {
i0 = points[mirrorIndex(i - 1, pointsSize)];
i1 = points[mirrorIndex(i, pointsSize)];
i2 = points[mirrorIndex(i + 1, pointsSize)];
i3 = points[mirrorIndex(i + 2, pointsSize)];
y0 = in[i0];
y1 = in[i1];
y2 = in[i2];
y3 = in[i3];
a0 = y3 - y2 - y0 + y1;
a1 = y0 - y1 - a0;
a2 = y2 - y0;
a3 = y1;
// left boundary
if(i == -1) {
start = 0;
i1 = -i1;
} else
start = i1;
// right boundary
if(i == pointsSize - 1) {
end = size;
i2 = size + size - i2;
} else
end = i2;
muScale = 1.f / (i2 - i1);
for(j = start; j < end; j++) {
mu = (j - i1) * muScale;
out[j] = ((a0 * mu + a1) * mu + a2) * mu + a3;
}
}
}
private void emdUpdateImf(EmdData emd, double[] imf) {
int i;
for(i = 0; i < emd.size; i++)
imf[i] -= (emd.min[i] + emd.max[i]) * .5f;
}
private void emdMakeResidue(EmdData emd, double[] cur) {
int i;
for(i = 0; i < emd.size; i++)
emd.residue[i] -= cur[i];
}
private int mirrorIndex(int i, int size) {
if(i < size) {
if(i < 0)
return -i - 1;
return i;
}
return (size - 1) + (size - i);
}
public static void main(String[] args) {
/*
This code implements empirical mode decomposition in C.
Required paramters include:
- order: the number of IMFs to return
- iterations: the number of iterations per IMF
- locality: in samples, the nearest two extrema may be
If it is not specified, there is no limit (locality = 0).
Typical use consists of calling emdCreate(), followed by
emdDecompose(), and then using the struct's "imfs" field
to retrieve the data. Call emdClear() to deallocate memory
inside the struct.
*/
double[] data = new double[]{229.49,231.94,232.97,234,233.36,235.15,235.64,235.78,238.95,242.09,240.61,240.29,237.88,252.11,259.16,263.4,262.1,254.85,254.42,261.27,253.92,259.04,251.58,248.96,239.49,229.39,247.02,249.48,254.9,251.27,246.85,245.43,241.52,231.23,235.67,239.99,238.49,237.41,246.4,249.83,253.67,256.71,255.9,248.93,244.05,242.49,236.52,243.63,246.55,247.3,252.56,259.91,264.41,266.55,262.75,266.33,263.53,261.62,259.38,260.94,249.14,244.63,241.66,240.16,241.81,251.57,251.01,252.49,250.23,244.89,245.79,244.55,243.04,238.84,244.98,247.26,251.91,252.81,252.16,256.83,253.8,251.03,250.19,254.66,254.74,255.76,254.52,252.95,254.57,252.29,243.32,244.88,242.26,240.84,245.05,246.12,243.02,242.79,239.05,233.34,236.22,233.69,234.99,235.84,236.43,243.46,245.25,251.67,250.73,255.7,255.85,256.18,259.71,260.7,262.8,268.98,267.81,275.46,275.98,279.85,280.99,284.3,283.17,278.99,279.48,275.96,274.77,270.99,281.01,281.25,281.28,286,287.25,290.35,291.9,294.01,306.1,309.27,301,302.01,301.02,299.03,300.36,299.59,299.38,296.86,292.72,295.83,300.87,304.21,309.53,308.43,309.87,307.4,309.3,307.96,299.58,298.61,293.31,292.25,299.96,298.31,304.76,300.26,306.16,306.35,308.17,302.61,307.72,309.42,308.73,311.36,309.48,312.2,310.98,311.76,312.84,311.5,311.57,312.43,311.81,313.37,315.3,316.24,314.72,315.77,316.54,316.36,314.78,313.71,320.52,322.2,324.83,324.57,326.89,333.05,332.26,334.97,336.19,338.92,331.3,329.54,323.55,317.75,328.19,332.03,334.41,333.79,326.88,330.01,335.56,334.87,334.01,336.99,342.22,345.45,348.33,344.81,347.06,349.32,350.02,353.16,348.47,340.94,329.32,333.22,333.47,338.6,343.52,339.72,342.46,349.69,350.12,345.61,346,342.8,337.15,342.33,343.86,335.95,320.95,325.46,321.59,329.99,331.84,329.88,335.5,341.89,340.82,341.33,339.06,338.94,335.1,331.83,329.59,328.76,328.8,325.86,321.72,323.28,326.9,323.3,318.47,322.74,328.59,333.01,341.07,343.32,340.8,340.54,337.23,340.52,336.78,338.64,339.98,337.23,337.15,338.06,339.86,337.7,337.06,331.15,324.15,326.91,330.54,331.18,326.02,325.22,323.07,327.54,325.81,328.15,338.28,336.03,336.6,334.01,328.76,322.93,323.12,322.39,316.96,317.64,323.32,317.78,316.24,311.47,306.67,316.37,313.76,322.14,317.39,322.93,326.06,324.87,326.46,333.84,339.84,342.11,347.4,349.84,344.28,344.04,348.19,347.95,354.9,363.54,366.51,376.28,376.66,382.51,387.56,392.34,381.81,381.07,379.76,385.86,378.24,381.8,367.01,363.37,343.52,363.74,353.71,363.44,366.64,372.89,370.04,370,356,346.26,346.66,363.35,365.85,363.46,373.05,379.27,379.29,374.27,370.57,363.78,369.32,373.39,373.6,367.12,369.51,374.06,378.61,382.17,389.51,400.33,402.1,400.83,390.79,393.2,392.1,388.3,386.11,379.85,370.85,364.32,362.28,367.87,367.01,359.65,378.14,389.3,391.15,397.22,410.42,408.46,410.65,387.68,384.46,382.09,394.63,386.85,389.6,393.58,393.84,393.67,385.63,386.5,392.01,389.25,388.76,395.08,384.43,374.65,374.06,368.85,378.16,374.21,367.05,364.65,358.88,366.18,356.92,353.59,365.8,362.96,371.71,377.28,379,382.22,380.22,378.41,379.94,382.82,381.09,378.14,369.75,368.54,370.56,371.72,385.08,385.57,387.61,392.26,395.37,391.59,394,393.88,399.94,402.09,406.56,410.81,410.15,411.62,410.95,409.82,408.29,413.04,417.33,416.01,408.76,415.68,408.87,434.4,432.43,435,440.58,443.95,443.67,442.63,447.06,451.24,455.96,463.6,479.63,479.88,488.81,495.48,484.01,488.43,488.34,500.72,498.96,502.22,508.07,511.33,520.71,527.55,529.53,530.22,518.53,515.71,516.12,527.11,530.21,536.85,552.51,573.4,569.49,569.5,584.6,589.33,585.96,582.89,579.69,590.32,597.61,600.67,593.12,583.09,601.65,612.05,607.17,616.29,618.77,611.19,609.01,605.68,588.62,564.21,592.97,591.64,571.32,557.25,556.01,544.9,593.26,591.02,586.45,567.95,566.15,569.9,565.85,549.74,553.85,552.59,553.56,554.86,551.16,542.9,537.99,531.09,515.57,515.82,545.87,541.68,554.9,549.8,546.86,556.56,563.27,561.87,545.59,548.8,547.38,555.78,556.03,564.39,555.49,560.35,556.46,555.84,558.37,569.7,571.29,569.66,561.81,566.12,555.1,556.33,558.73,553.43,567.97,576.26,582.96,593.2,589.25,597.04,591.52,587.84,582.46,588.37,590.25,590.28,589.62,597.46,587.71,587.26,584.43,559.19,559.1,569.1};
Emd emd = new Emd();
EmdData emdData = new EmdData();
int order = 4;
emd.emdCreate(emdData, data.length, order, 20, 0);
emd.emdDecompose(emdData, data);
for (int i=0;i<data.length;i++) {
System.out.print(data[i]+";");
for (int j=0;j<order; j++) System.out.print(emdData.imfs[j][i] + ";");
System.out.println();
}
}
private static class EmdData {
protected int iterations, order, locality;
protected int[] minPoints, maxPoints;
protected double[] min, max, residue;
protected double[][] imfs;
protected int size, minSize, maxSize;
}
}

Implementing a Neural Network in Java: Training and Backpropagation issues

I'm trying to implement a feed-forward neural network in Java.
I've created three classes NNeuron, NLayer and NNetwork. The "simple" calculations seem fine (I get correct sums/activations/outputs), but when it comes to the training process, I don't seem to get correct results. Can anyone, please tell what I'm doing wrong ?
The whole code for the NNetwork class is quite long, so I'm posting the part that is causing the problem:
[EDIT]: this is actually pretty much all of the NNetwork class
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class NNetwork
{
public static final double defaultLearningRate = 0.4;
public static final double defaultMomentum = 0.8;
private NLayer inputLayer;
private ArrayList<NLayer> hiddenLayers;
private NLayer outputLayer;
private ArrayList<NLayer> layers;
private double momentum = NNetwork1.defaultMomentum; // alpha: momentum, default! 0.3
private ArrayList<Double> learningRates;
public NNetwork (int nInputs, int nOutputs, Integer... neuronsPerHiddenLayer)
{
this(nInputs, nOutputs, Arrays.asList(neuronsPerHiddenLayer));
}
public NNetwork (int nInputs, int nOutputs, List<Integer> neuronsPerHiddenLayer)
{
// the number of neurons on the last layer build so far (i.e. the number of inputs for each neuron of the next layer)
int prvOuts = 1;
this.layers = new ArrayList<>();
// input layer
this.inputLayer = new NLayer(nInputs, prvOuts, this);
this.inputLayer.setAllWeightsTo(1.0);
this.inputLayer.setAllBiasesTo(0.0);
this.inputLayer.useSigmaForOutput(false);
prvOuts = nInputs;
this.layers.add(this.inputLayer);
// hidden layers
this.hiddenLayers = new ArrayList<>();
for (int i=0 ; i<neuronsPerHiddenLayer.size() ; i++)
{
this.hiddenLayers.add(new NLayer(neuronsPerHiddenLayer.get(i), prvOuts, this));
prvOuts = neuronsPerHiddenLayer.get(i);
}
this.layers.addAll(this.hiddenLayers);
// output layer
this.outputLayer = new NLayer(nOutputs, prvOuts, this);
this.layers.add(this.outputLayer);
this.initCoeffs();
}
private void initCoeffs ()
{
this.learningRates = new ArrayList<>();
// learning rates of the hidden layers
for (int i=0 ; i<this.hiddenLayers.size(); i++)
this.learningRates.add(NNetwork1.defaultLearningRate);
// learning rate of the output layer
this.learningRates.add(NNetwork1.defaultLearningRate);
}
public double getLearningRate (int layerIndex)
{
if (layerIndex > 0 && layerIndex <= this.hiddenLayers.size()+1)
{
return this.learningRates.get(layerIndex-1);
}
else
{
return 0;
}
}
public ArrayList<Double> getLearningRates ()
{
return this.learningRates;
}
public void setLearningRate (int layerIndex, double newLearningRate)
{
if (layerIndex > 0 && layerIndex <= this.hiddenLayers.size()+1)
{
this.learningRates.set(
layerIndex-1,
newLearningRate);
}
}
public void setLearningRates (Double... newLearningRates)
{
this.setLearningRates(Arrays.asList(newLearningRates));
}
public void setLearningRates (List<Double> newLearningRates)
{
int len = (this.learningRates.size() <= newLearningRates.size())
? this.learningRates.size()
: newLearningRates.size();
for (int i=0; i<len; i++)
this.learningRates
.set(i,
newLearningRates.get(i));
}
public double getMomentum ()
{
return this.momentum;
}
public void setMomentum (double momentum)
{
this.momentum = momentum;
}
public NNeuron getNeuron (int layerIndex, int neuronIndex)
{
if (layerIndex == 0)
return this.inputLayer.getNeurons().get(neuronIndex);
else if (layerIndex == this.hiddenLayers.size()+1)
return this.outputLayer.getNeurons().get(neuronIndex);
else
return this.hiddenLayers.get(layerIndex-1).getNeurons().get(neuronIndex);
}
public ArrayList<Double> getOutput (ArrayList<Double> inputs)
{
ArrayList<Double> lastOuts = inputs; // the last computed outputs of the last 'called' layer so far
// input layer
//lastOuts = this.inputLayer.getOutput(lastOuts);
lastOuts = this.getInputLayerOutputs(lastOuts);
// hidden layers
for (NLayer layer : this.hiddenLayers)
lastOuts = layer.getOutput(lastOuts);
// output layer
lastOuts = this.outputLayer.getOutput(lastOuts);
return lastOuts;
}
public ArrayList<ArrayList<Double>> getAllOutputs (ArrayList<Double> inputs)
{
ArrayList<ArrayList<Double>> outs = new ArrayList<>();
// input layer
outs.add(this.getInputLayerOutputs(inputs));
// hidden layers
for (NLayer layer : this.hiddenLayers)
outs.add(layer.getOutput(outs.get(outs.size()-1)));
// output layer
outs.add(this.outputLayer.getOutput(outs.get(outs.size()-1)));
return outs;
}
public ArrayList<ArrayList<Double>> getAllSums (ArrayList<Double> inputs)
{
//*
ArrayList<ArrayList<Double>> sums = new ArrayList<>();
ArrayList<Double> lastOut;
// input layer
sums.add(inputs);
lastOut = this.getInputLayerOutputs(inputs);
// hidden nodes
for (NLayer layer : this.hiddenLayers)
{
sums.add(layer.getSums(lastOut));
lastOut = layer.getOutput(lastOut);
}
// output layer
sums.add(this.outputLayer.getSums(lastOut));
return sums;
}
public ArrayList<Double> getInputLayerOutputs (ArrayList<Double> inputs)
{
ArrayList<Double> outs = new ArrayList<>();
for (int i=0 ; i<this.inputLayer.getNeurons().size() ; i++)
outs.add(this
.inputLayer
.getNeuron(i)
.getOutput(inputs.get(i)));
return outs;
}
public void changeWeights (
ArrayList<ArrayList<Double>> deltaW,
ArrayList<ArrayList<Double>> inputSet,
ArrayList<ArrayList<Double>> targetSet,
boolean checkError)
{
for (int i=0 ; i<deltaW.size()-1 ; i++)
this.hiddenLayers.get(i).changeWeights(deltaW.get(i), inputSet, targetSet, checkError);
this.outputLayer.changeWeights(deltaW.get(deltaW.size()-1), inputSet, targetSet, checkError);
}
public int train2 (
ArrayList<ArrayList<Double>> inputSet,
ArrayList<ArrayList<Double>> targetSet,
double maxError,
int maxIterations)
{
ArrayList<Double>
input,
target;
ArrayList<ArrayList<ArrayList<Double>>> prvNetworkDeltaW = null;
double error;
int i = 0, j = 0, traininSetLength = inputSet.size();
do // during each itreration...
{
error = 0.0;
for (j = 0; j < traininSetLength; j++) // ... for each training element...
{
input = inputSet.get(j);
target = targetSet.get(j);
prvNetworkDeltaW = this.train2_bp(input, target, prvNetworkDeltaW); // ... do backpropagation, and return the new weight deltas
error += this.getInputMeanSquareError(input, target);
}
i++;
} while (error > maxError && i < maxIterations); // iterate as much as necessary/possible
return i;
}
public ArrayList<ArrayList<ArrayList<Double>>> train2_bp (
ArrayList<Double> input,
ArrayList<Double> target,
ArrayList<ArrayList<ArrayList<Double>>> prvNetworkDeltaW)
{
ArrayList<ArrayList<Double>> layerSums = this.getAllSums(input); // the sums for each layer
ArrayList<ArrayList<Double>> layerOutputs = this.getAllOutputs(input); // the outputs of each layer
// get the layer deltas (inc the input layer that is null)
ArrayList<ArrayList<Double>> layerDeltas = this.train2_getLayerDeltas(layerSums, layerOutputs, target);
// get the weight deltas
ArrayList<ArrayList<ArrayList<Double>>> networkDeltaW = this.train2_getWeightDeltas(layerOutputs, layerDeltas, prvNetworkDeltaW);
// change the weights
this.train2_updateWeights(networkDeltaW);
return networkDeltaW;
}
public void train2_updateWeights (ArrayList<ArrayList<ArrayList<Double>>> networkDeltaW)
{
for (int i=1; i<this.layers.size(); i++)
this.layers.get(i).train2_updateWeights(networkDeltaW.get(i));
}
public ArrayList<ArrayList<ArrayList<Double>>> train2_getWeightDeltas (
ArrayList<ArrayList<Double>> layerOutputs,
ArrayList<ArrayList<Double>> layerDeltas,
ArrayList<ArrayList<ArrayList<Double>>> prvNetworkDeltaW)
{
ArrayList<ArrayList<ArrayList<Double>>> networkDeltaW = new ArrayList<>(this.layers.size());
ArrayList<ArrayList<Double>> layerDeltaW;
ArrayList<Double> neuronDeltaW;
for (int i=0; i<this.layers.size(); i++)
networkDeltaW.add(new ArrayList<ArrayList<Double>>());
double
deltaW, x, learningRate, prvDeltaW, d;
int i, j, k;
for (i=this.layers.size()-1; i>0; i--) // for each layer
{
learningRate = this.getLearningRate(i);
layerDeltaW = new ArrayList<>();
networkDeltaW.set(i, layerDeltaW);
for (j=0; j<this.layers.get(i).getNeurons().size(); j++) // for each neuron of this layer
{
neuronDeltaW = new ArrayList<>();
layerDeltaW.add(neuronDeltaW);
for (k=0; k<this.layers.get(i-1).getNeurons().size(); k++) // for each weight (i.e. each neuron of the previous layer)
{
d = layerDeltas.get(i).get(j);
x = layerOutputs.get(i-1).get(k);
prvDeltaW = (prvNetworkDeltaW != null)
? prvNetworkDeltaW.get(i).get(j).get(k)
: 0.0;
deltaW = -learningRate * d * x + this.momentum * prvDeltaW;
neuronDeltaW.add(deltaW);
}
// the bias !!
d = layerDeltas.get(i).get(j);
x = 1;
prvDeltaW = (prvNetworkDeltaW != null)
? prvNetworkDeltaW.get(i).get(j).get(prvNetworkDeltaW.get(i).get(j).size()-1)
: 0.0;
deltaW = -learningRate * d * x + this.momentum * prvDeltaW;
neuronDeltaW.add(deltaW);
}
}
return networkDeltaW;
}
ArrayList<ArrayList<Double>> train2_getLayerDeltas (
ArrayList<ArrayList<Double>> layerSums,
ArrayList<ArrayList<Double>> layerOutputs,
ArrayList<Double> target)
{
// get ouput deltas
ArrayList<Double> outputDeltas = new ArrayList<>(); // the output layer deltas
double
oErr, // output error given a target
s, // sum
o, // output
d; // delta
int
nOutputs = target.size(), // #TODO ?== this.outputLayer.size()
nLayers = this.hiddenLayers.size()+2; // #TODO ?== layerOutputs.size()
for (int i=0; i<nOutputs; i++) // for each neuron...
{
s = layerSums.get(nLayers-1).get(i);
o = layerOutputs.get(nLayers-1).get(i);
oErr = (target.get(i) - o);
d = -oErr * this.getNeuron(nLayers-1, i).sigmaPrime(s); // #TODO "s" or "o" ??
outputDeltas.add(d);
}
// get hidden deltas
ArrayList<ArrayList<Double>> hiddenDeltas = new ArrayList<>();
for (int i=0; i<this.hiddenLayers.size(); i++)
hiddenDeltas.add(new ArrayList<Double>());
NLayer nextLayer = this.outputLayer;
ArrayList<Double> nextDeltas = outputDeltas;
int
h, k,
nHidden = this.hiddenLayers.size(),
nNeurons = this.hiddenLayers.get(nHidden-1).getNeurons().size();
double
wdSum = 0.0;
for (int i=nHidden-1; i>=0; i--) // for each hidden layer
{
hiddenDeltas.set(i, new ArrayList<Double>());
for (h=0; h<nNeurons; h++)
{
wdSum = 0.0;
for (k=0; k<nextLayer.getNeurons().size(); k++)
{
wdSum += nextLayer.getNeuron(k).getWeight(h) * nextDeltas.get(k);
}
s = layerSums.get(i+1).get(h);
d = this.getNeuron(i+1, h).sigmaPrime(s) * wdSum;
hiddenDeltas.get(i).add(d);
}
nextLayer = this.hiddenLayers.get(i);
nextDeltas = hiddenDeltas.get(i);
}
ArrayList<ArrayList<Double>> deltas = new ArrayList<>();
// input layer deltas: void
deltas.add(null);
// hidden layers deltas
deltas.addAll(hiddenDeltas);
// output layer deltas
deltas.add(outputDeltas);
return deltas;
}
public double getInputMeanSquareError (ArrayList<Double> input, ArrayList<Double> target)
{
double diff, mse=0.0;
ArrayList<Double> output = this.getOutput(input);
for (int i=0; i<target.size(); i++)
{
diff = target.get(i) - output.get(i);
mse += (diff * diff);
}
mse /= 2.0;
return mse;
}
}
Some methods' names (with their return values/types) are quite self-explanatory, like "this.getAllSums" that returns the sums (sum(x_i*w_i) for each neuron) of each layer, "this.getAllOutputs" that return the outputs (sigmoid(sum) for each neuron) of each layer and "this.getNeuron(i,j)" that returns the j'th neuron of the i'th layer.
Thank you in advance for your help :)
Here is a very simple java implementation with tests in the main method :
import java.util.Arrays;
import java.util.Random;
public class MLP {
public static class MLPLayer {
float[] output;
float[] input;
float[] weights;
float[] dweights;
boolean isSigmoid = true;
public MLPLayer(int inputSize, int outputSize, Random r) {
output = new float[outputSize];
input = new float[inputSize + 1];
weights = new float[(1 + inputSize) * outputSize];
dweights = new float[weights.length];
initWeights(r);
}
public void setIsSigmoid(boolean isSigmoid) {
this.isSigmoid = isSigmoid;
}
public void initWeights(Random r) {
for (int i = 0; i < weights.length; i++) {
weights[i] = (r.nextFloat() - 0.5f) * 4f;
}
}
public float[] run(float[] in) {
System.arraycopy(in, 0, input, 0, in.length);
input[input.length - 1] = 1;
int offs = 0;
Arrays.fill(output, 0);
for (int i = 0; i < output.length; i++) {
for (int j = 0; j < input.length; j++) {
output[i] += weights[offs + j] * input[j];
}
if (isSigmoid) {
output[i] = (float) (1 / (1 + Math.exp(-output[i])));
}
offs += input.length;
}
return Arrays.copyOf(output, output.length);
}
public float[] train(float[] error, float learningRate, float momentum) {
int offs = 0;
float[] nextError = new float[input.length];
for (int i = 0; i < output.length; i++) {
float d = error[i];
if (isSigmoid) {
d *= output[i] * (1 - output[i]);
}
for (int j = 0; j < input.length; j++) {
int idx = offs + j;
nextError[j] += weights[idx] * d;
float dw = input[j] * d * learningRate;
weights[idx] += dweights[idx] * momentum + dw;
dweights[idx] = dw;
}
offs += input.length;
}
return nextError;
}
}
MLPLayer[] layers;
public MLP(int inputSize, int[] layersSize) {
layers = new MLPLayer[layersSize.length];
Random r = new Random(1234);
for (int i = 0; i < layersSize.length; i++) {
int inSize = i == 0 ? inputSize : layersSize[i - 1];
layers[i] = new MLPLayer(inSize, layersSize[i], r);
}
}
public MLPLayer getLayer(int idx) {
return layers[idx];
}
public float[] run(float[] input) {
float[] actIn = input;
for (int i = 0; i < layers.length; i++) {
actIn = layers[i].run(actIn);
}
return actIn;
}
public void train(float[] input, float[] targetOutput, float learningRate, float momentum) {
float[] calcOut = run(input);
float[] error = new float[calcOut.length];
for (int i = 0; i < error.length; i++) {
error[i] = targetOutput[i] - calcOut[i]; // negative error
}
for (int i = layers.length - 1; i >= 0; i--) {
error = layers[i].train(error, learningRate, momentum);
}
}
public static void main(String[] args) throws Exception {
float[][] train = new float[][]{new float[]{0, 0}, new float[]{0, 1}, new float[]{1, 0}, new float[]{1, 1}};
float[][] res = new float[][]{new float[]{0}, new float[]{1}, new float[]{1}, new float[]{0}};
MLP mlp = new MLP(2, new int[]{2, 1});
mlp.getLayer(1).setIsSigmoid(false);
Random r = new Random();
int en = 500;
for (int e = 0; e < en; e++) {
for (int i = 0; i < res.length; i++) {
int idx = r.nextInt(res.length);
mlp.train(train[idx], res[idx], 0.3f, 0.6f);
}
if ((e + 1) % 100 == 0) {
System.out.println();
for (int i = 0; i < res.length; i++) {
float[] t = train[i];
System.out.printf("%d epoch\n", e + 1);
System.out.printf("%.1f, %.1f --> %.3f\n", t[0], t[1], mlp.run(t)[0]);
}
}
}
}
}
I tried going over your code, but as you stated, it was pretty long.
Here's what I suggest:
To verify that your network is learning properly, try to train a simple network, like a network that recognizes the XOR operator. This shouldn't take all that long.
Use the simplest back-propagation algorithm. Stochastic backpropagation (where the weights are updated after the presentation of each training input) is the easiest. Implement the algorithm without the momentum term initially, and with a constant learning rate (i.e., don't start with adaptive learning-rates). Once you're satisfied that the algorithm is working, you can introduce the momentum term. Doing too many things at the same time increases the chances that more than one thing can go wrong. This makes it harder for you to see where you went wrong.
If you want to go over some code, you can check out some code that I wrote; you want to look at Backpropagator.java. I've basically implemented the stochastic backpropagation algorithm with a momentum term. I also have a video where I provide a quick explanation of my implementation of the backpropagation algorithm.
Hopefully this is of some help!

Categories