import java.util.*;
import java.awt.*;
import java.io.*;
public class Project4
{
public static void main (String[] args)
{
// MAIN CODE
String noteRepresentation = "78!9#a#bc$d%ef^g&A*BC(D)EF_G+H";
String noteString = SimpleInput.getString("String of notes");
// init strLen etc
int strLen = noteString.length();
int samples = (int)((.125) * (22050)); // 1/8 Times the sample per sec
int finalLen = strLen * samples;
// Create a silence array
double silenceArray[] = new double[(int)samples];
// = new double[(double)samples]; // Be able to create a new array for the silence (periods).
// Create a main sound sample
SoundSample[] ssarrFS = new SoundSample[(int)finalLen];
String noteLetter;
for ( int noteIndex = 0; noteIndex < noteString.length(); noteIndex++)
{
double freq = -1;
double amplitude = -1;
noteLetter = noteString.substring(noteIndex, noteIndex + 1);
getFreq(noteLetter);
getAmp(freq, noteLetter);
SoundSample[] tempArray = createSineWave(freq, amplitude);
if (noteRepresentation.indexOf(noteLetter) == -1)
{
//Silence
for(int index1 = 0;index1<samples;index1++)
{
int value1 = tempArray[index1].getValue();
ssarrFS[(int)((index1+(samples*(noteIndex))))].setValue(value1);
}
}
else
{
freq = -1;
amplitude = -1;
for(int index2 = 0;index2<samples;index2++)
{
getFreq(noteLetter);
getAmp(freq, noteLetter);
int value2 = tempArray[index2].getValue();
ssarrFS[(int)(index2+(samples*(noteIndex)))].setValue(value2);
}
}
}
Sound sFinal = modifySound(finalLen, ssarrFS);
sFinal.explore();
}
public static Sound modifySound(int finalLen, SoundSample[] ssarrFS)
{
Sound sFinal = new Sound( finalLen+1);
SoundSample[] ssarr3 = sFinal.getSamples();
int ind;
for (ind = 0 ; ind < finalLen ; ++ind )
{
int valueFinal = ssarrFS[ind].getValue();
// check for clipping
if ( valueFinal > 32767 )
{
valueFinal = 32767;
}
if ( valueFinal < -32768 )
{
valueFinal = -32768;
}
ssarr3[ind].setValue ( valueFinal );
}
return sFinal;
}
public static double getFreq (String noteLetter)
{
String noteRepresentation = "78!9#a#bc$d%ef^g&A*BC(D)EF_G+H";
double x = noteRepresentation.indexOf(noteLetter); // x becomes 15
double y = noteRepresentation.indexOf('H'); // y becomes 29
double exponent = (double)((x - y)/12.0);
double freq = (double)(440.0 * Math.pow (2.0, exponent)); // fr
System.out.println(freq);
return freq;
}
public static SoundSample[] createSineWave (double freq, double amplitude)
{
Sound s = new Sound ((int)((.125) * (22050)));
int samplingRate = (int)(s.getSamplingRate());
int rawValue = 0;
int value = 0;
int interval = (int)(1.0 / freq);
int samplesPerCycle = (int)(interval * samplingRate);
int maxValue =(int)( 2 * Math.PI);
SoundSample[] tempArray = s.getSamples();
int index;
for (int i = 0 ; i < s.getLength(); ++i )
{
rawValue = (int)(Math.sin ((i / samplesPerCycle) * maxValue));
value = (int) (amplitude * rawValue);
tempArray[i].setValue(value);
}
//s = null;
//System.gc();
return tempArray;
}
public static double getAmp (double freq, String noteLetter)
{
double samplesPerCycle = 22050 / freq;
double sampleIndex = 22050 / 8;
double wavePoint = sampleIndex / samplesPerCycle;
double rawSample = Math.sin (wavePoint * 2.0 * Math.PI);
double amplitude = rawSample * 20000;
System.out.println(amplitude);
return amplitude;
}
}
I am trying to combine notes that a user will input and be able to take their frequency and amplitudes and be able to create a .wav file that will output the sound. When I try to compile the current code, I keep receiving a nullpointerexception error at line
ssarrFS[(int)(index2+(samples*(noteIndex)))].setValue(value2);
I believe that I have incorrectly set up my arrays and may have caused memory leaks in my program.
You declare your array here
SoundSample[] ssarrFS = new SoundSample[(int)finalLen];
But then you never populate it's values, and you try to use it here:
ssarrFS[(int)((index1+(samples*(noteIndex))))].setValue(value1);
When you try to use it though, your array looks like this:
ssarrFS = [0] = null
[1] = null
[2] = null
...
[finalLen] = null
You attempt to call setValue on an element inside of it. Because you've not populated ssarrFS, this amounts to:
null.setValue(value1);
And because null does not refer to an object in memory, this will throw your NullPointerException.
Related
this is a continuation of this post. I must calculate many times some statistics(Max, mean, min, median and std dev) of arrays and I have a performance issue given the sort of my arrays in the method calcMaxMinMedian.
Given, I could not improve much further the summary statistics of an array performance. I am trying now to understand strategies and work arounds to parallelize my upper calls or any other smart thoughts.
I have seen this doc but I am not familiar
As well as this (post)[https://stackoverflow.com/questions/20375176/should-i-always-use-a-parallel-stream-when-possible/20375622].
I tried using parallel streams, however probably given my SharedResource, the actual performance using the for loop was worse.
Time (s) functionUsingForLoop173
Time (s) functionUsingParallelStream194
Do anyone have an idea of what could I try to parallelize or any other thoughts on how to improve the overrall performance?
Here is what I tried:
public class MaxMinMedianArrayUtils {
int[] sharedStaticResource={1,5,5};//Shared resource across
/**
* Return an array with summary statistics. Max, mean,std dev,median,min.
* Throw an IllegalArgumentException if array is empty.
*
* #param a array.
* #return array returning Max(0), mean(1),std dev(2),median(3),min(4) in
* respective
* positions.
*/
public static double[] getSummaryStatistics(double[] a) {
double[] summary = new double[5];
if (a.length == 0) {
throw new IllegalArgumentException(
"Array is empty, please " + "verify" + " the values.");
} else if (a.length == 1) {
summary[0] = a[0];
summary[1] = a[0];
summary[2] = 0;
summary[3] = a[0];
summary[4] = a[0];
} else {
double[] meandStd = calcMeanSDSample(a);
summary[1] = meandStd[0];//Mean
summary[2] = meandStd[1];//Standard Deviation
double[] maxMinMedian = calcMaxMinMedian(a);
summary[0] = maxMinMedian[0];//Max
summary[4] = maxMinMedian[1];//Min
summary[3] = maxMinMedian[2];//Median
}
return summary;
}
public static double[] calcMeanSDSample(double numArray[]) {
int length = numArray.length;
double[] meanStd = new double[2];
if (length == 0) {
throw new IllegalArgumentException(
"Array is empty, please " + "verify" + " the values.");
} else if (length == 1) {
meanStd[0] = numArray[0];
meanStd[1] = 0.0;
} else {
double sum = 0.0, standardDeviation = 0.0;
for (double num : numArray) {
sum += num;
}
meanStd[0] = sum / length;
for (double num : numArray) {
standardDeviation += Math.pow(num - meanStd[0], 2);
}
meanStd[1] =
Math.sqrt(standardDeviation / ((double) length - 1.0));//-1
// because it is
// for sample
}
return meanStd;
}
public static double[] calcMaxMinMedian(double[] a) {
double[] maxMinMedian = new double[3];
if (a.length == 0) {
throw new IllegalArgumentException(
"Array is empty, please " + "verify" + " the values.");
} else if (a.length == 1) {
for (int i = 0; i < 3; i++) {
maxMinMedian[i] = a[0];
}
} else {
Arrays.sort(a);
maxMinMedian[0] = a[a.length - 1];
maxMinMedian[1] = a[0];
maxMinMedian[2] = (a.length % 2 != 0) ? (double) (a[a.length / 2]) :
(double) ((a[(a.length - 1) / 2] + a[a.length / 2]) / 2.0);
}
return maxMinMedian;
}
public static void main(String[] args) {
int numVals = 1000;
// double[] ar = new double[numVals];
int numCalculations = 2 * 1000 * 1 * 1000;
// int numCalculations = 2 * 1000;
MaxMinMedianArrayUtils maxMinMedianArrayUtils=
new MaxMinMedianArrayUtils();
Instant start = Instant.now();
double[][] statsPerCalculation=
maxMinMedianArrayUtils.functionUsingForLoop(numVals,
numCalculations);
Instant end = Instant.now();
long totalTime = Duration.between(start, end).toSeconds();
System.out.println("Time (s) functionUsingForLoop" + totalTime);
Instant start3 = Instant.now();
double[][] statsPerCalculation3=
maxMinMedianArrayUtils.functionUsingParallelStream(numVals,
numCalculations);
Instant end3 = Instant.now();
long totalTime3 = Duration.between(start3, end3).toSeconds();
System.out.println("Time (s) functionUsingParallelStream" + totalTime3);
}
private double[][] functionUsingForLoop(int numVals,
int numCalculations) {
// calculations that is used to get some values, but is not modified.
double[][] statsPerCalculation= new double[numCalculations][5];//Each
// line
// stores
// the stats of the array generated in the numCalculations loop
for (int i = 0; i < numCalculations; i++) {//Complete independent
// calculations that I want to parallelize
double[]array=functionSimulateCalculations(numVals);
double[] stats = getSummaryStatistics(array);
for(int s = 0; s < stats.length; s++) {//Copy
statsPerCalculation[i][s] = stats[s];
}
}
return statsPerCalculation;
}
private double[][] functionUsingParallelStream(int numVals,
int numCalculations) {
// calculations that is used to get some values, but is not modified.
double[][] statsPerCalculation= new double[numCalculations][5];//Each
// line
// stores
// the stats of the array generated in the numCalculations loop
double[][] finalStatsPerCalculation = statsPerCalculation;
IntStream.range(0,numCalculations).parallel().forEach((i)->{
double[] array=functionSimulateCalculations(numVals);
double[] stats = getSummaryStatistics(array);
for(int s = 0; s < stats.length; s++) {
finalStatsPerCalculation[i][s] = stats[s];
}
}
);
return statsPerCalculation;
}
private double[] functionSimulateCalculations(int numVals) {
double[] ar=new double[numVals];
for (int k = 0; k < numVals; k++) {//To simulate the
// actual function of my
// use case
ar[k] = Math.random()*sharedStaticResource[0];
}
return ar;
}
} // Utility
Part of your issue is that you are computing your randomised the data samples inside the tests, but have contention with the singleton random number generation in parallel threads. Also this means that you have no means of validating that the parallel algorithm matches the serial results.
Refactor your tests so that inputs are pre-computed once - you don't care about timing this step:
private double[][] generateInputData(int numVals, int numCalculations) {
// calculations that is used to get some values, but is not modified.
double[][] inputs = new double[numCalculations][];// Each
for (int i = 0; i < numCalculations; i++) {
inputs[i] = functionSimulateCalculations(numVals);
}
return inputs;
}
Then you can run both tests on same inputs:
private double[][] functionUsingForLoop(double[][]arrays) {
// calculations that is used to get some values, but is not modified.
int numCalculations = arrays.length;
double[][] statsPerCalculation = new double[numCalculations][5];// Each
for (int i = 0; i < numCalculations; i++) {
double[] stats = getSummaryStatistics(arrays[i]);
for (int s = 0; s < stats.length; s++) {
statsPerCalculation[i][s] = stats[s];
}
}
return statsPerCalculation;
}
private double[][] functionUsingParallelStream(double[][]arrays) {
int numCalculations = arrays.length;
double[][] statsPerCalculation = new double[numCalculations][5];// Each
double[][] finalStatsPerCalculation = statsPerCalculation;
IntStream.range(0, numCalculations).parallel().forEach((i) -> {
double[] stats = getSummaryStatistics(arrays[i]);
for (int s = 0; s < stats.length; s++) {
finalStatsPerCalculation[i][s] = stats[s];
}
});
return statsPerCalculation;
}
Finally make your main() do some warmups, initialise the arrays, time each section and compare the results:
for (int numCalculations : new int[] { 1, 2, 8, 8, 2 * 1000, 2* 10000, 2*1000*1*1000 } ) {
double[][] arrays = maxMinMedianArrayUtils.generateInputData(numVals, numCalculations);
// ...
double[][] statsPerCalculation= maxMinMedianArrayUtils.functionUsingForLoop(arrays);
// ...
double[][] statsPerCalculation3= maxMinMedianArrayUtils.functionUsingParallelStream(arrays);
// ...
// COMPARE the results
if (statsPerCalculation3.length != statsPerCalculation.length)
throw new RuntimeException("Results not same!");
for (int i = statsPerCalculation3.length - 1; i >= 0; i--) {
// System.out.println("statsPerCalculation ["+i+"]="+Arrays.toString(statsPerCalculation[i]));
// System.out.println("statsPerCalculation3["+i+"]="+Arrays.toString(statsPerCalculation3[i]));
for (int v = statsPerCalculation3[i].length - 1; v >= 0; v--) {
if (Math.abs(statsPerCalculation3[i][v]-statsPerCalculation[i][v]) > 0.0000000000001)
throw new RuntimeException("Results not same at ["+i+"]["+v+"]");
}
}
}
At this point, you'll see quite different trend in the results, parallel stream version a lot quicker than non-parallel.
I am trying to use java to pass an array to get the mean, median,mode , max an min in java. I am currently having an issue passing the array to a function and return its value so i can output the results. I believe i have the loops correct to solve the mean median and mode but i cannot get them to send and receive as wanted. How can I pass the array and send back the values needed?
UPDATE: i have updated the code it will compile and i can input the number of years but i get several errors following after that. it is also not printing the outputs
Exception in thread "main" java.util.UnknownFormatConversionException: Conversion = 'i'
at java.util.Formatter$FormatSpecifier.conversion(Formatter.java:2646)
at java.util.Formatter$FormatSpecifier.(Formatter.java:2675)
at java.util.Formatter.parse(Formatter.java:2528)
at java.util.Formatter.format(Formatter.java:2469)
at java.io.PrintStream.format(PrintStream.java:970)
at java.io.PrintStream.printf(PrintStream.java:871)
at la5cs1110_woodspl_03.pkg17.pkg2016.La5cs1110_WoodsPl_03172016.main(La5cs1110_WoodsPl_03172016.java:56)
Java Result: 1
public static void main(String[] args) {
int i;
List<Double> hArray = new ArrayList<>();
int nYears = 0, y = 0;
double rMax = 0.00,rMin = 100.00;
//get input check if between 1-80
while(y == 0){
String userData = JOptionPane.showInputDialog
("Enter number of years");
nYears = Integer.parseInt(userData);
if (nYears > 1 && nYears <= 80 )
y = 1;
}
y = 0;
while(y <= nYears){
for(i = 0; i < 12; i++){
Random rand = new Random();
double rNum = rand.nextFloat() * (rMax - rMin) + rMin;
hArray.add(rNum);
}
double mean = getMean (hArray);
double median = getMedian (hArray);
double mode = getMode (hArray);
double max = getMaxValue(hArray);
double min = getMinValue (hArray);
System.out.printf("In year %i the Mean = %d , mode = %d, median = %d," +
" max = %d, min = %d", y , mean, median, mode, max, min);
y++;
}
}
private static double getMean(List<Double> hArray) {
double sum = 0;
for (int i = 0; i < hArray.size(); i++) {
sum += hArray.get(i);
}
return sum / hArray.size();
}
//Median
private static double getMedian(List<Double> hArray) {
int middle = hArray.size()/2;
if (hArray.size() %2 == 1) {
return hArray.get(middle);
} else {
return (hArray.get(middle-1) + hArray.get(middle)) / 2.0;
}
}
//Mode
public static double getMode(List<Double> hArray) {
double maxValue = 0, maxCount = 0;
for (int i = 0; i < hArray.size(); ++i) {
int count = 0;
for (int j = 0; j < hArray.size(); ++j) {
if (hArray.get(j) == hArray.get(i)) ++count;
}
if (count > maxCount) {
maxCount = count;
maxValue = hArray.get(i);
}
}
return maxValue;
}
public static double getMaxValue(List<Double> hArray){
double maxValue = hArray.get(0);
for(int i=1;i < hArray.size();i++){
if(hArray.get(i) > maxValue){
maxValue = hArray.get(i);
}
}
return maxValue;
}
public static double getMinValue(List<Double> hArray){
double minValue = hArray.get(0);
for(int i=1;i<hArray.size();i++){
if(hArray.get(i) < minValue){
minValue = hArray.get(i);
}
}
return minValue;
}
}
Your hArray is a List. You should convert it to an array first.
getMean(hArray.toArray)
Check out this.
This does not compile, you try to pass a Double to a method, which expects a double[]. So you have to change the parameter of your methods and use a List and just pass in the hArray (see Tibrogargan answer - i.e., you would have to modify each of your implementations) or do the following:
create a Double[]
Double[] hArray2 = hArray.toArray(new Double[hArray.size()]);
change your methods' signature, so that they expect an Double[]
private static double getMean(Double[] hArray) { ...}
pass hArray2 instead of hArray
double mean = getMean(hArray2);
// ...
That should be it.
Replace the section where you're trying to pass a single element from the array to your statistics functions with calls using the whole array and change the signature of the calls so they take a List<Double> param, not a double[]. Something like this:
double mean = getMean (hArray);
double median = getMedian (hArray);
double mode = getMode (hArray);
double max = getMaxValue(hArray);
double min = getMinValue (hArray);
//Mean
private static double getMean(List<Double> hArray) {
double sum = 0;
for (int i = 0; i < hArray.size(); i++) {
sum += hArray.get(i);
}
return sum / hArray.size();
}
See also: How do you calculate the variance, median, and standard deviation in C++ or Java?
Fix for median:
Copied directly from this above link with some minor modifications to use a List as a param
public Double median(List<Double> list)
{
Double[] array = list.toArray(new Double[list.size()]);
Arrays.sort(data);
if (data.length % 2 == 0)
{
return (data[(data.length / 2) - 1] + data[data.length / 2]) / 2.0;
}
else
{
return data[data.length / 2];
}
}
Fix for mode:
public Double mode(List<Double> list)
{
java.util.TreeMap<Double,Integer> map = new java.util.TreeMap<>();
Double maxVal = null;
int maxCount = 0;
for (Double d : list) {
int count = 0;
if (map.containsKey(d)) {
count = map.get(d) + 1;
} else {
count = 1;
}
map.put(d, count);
if (count > maxCount) {
maxVal = d;
maxCount = count;
}
}
return maxVal;
}
I need to find the mean, median, mode, and range from an input file.
[input file has the numbers{60,75,53,49,92,71}]
I don't know how to print the calculations from the range out or calculate the mode.
It's pretty bad, I'm very new to Java.
It would be great if anyone could help me with it.
import java.io.*;
import java.util.*;
public class grades {
public static double avg(double[] num) {
double total = 0;
int j = 0;
for (; j < num.length; j++) {
total += num[j];
}
return (total / j);
}
public double getRange(double[] numberList) {
double initMin = numberList[0];
double initMax = numberList[0];
for (int i = 1; i <= numberList.length; i++) {
if (numberList[i] < initMin) initMin = numberList[i];
if (numberList[i] > initMax) initMax = numberList[i];
double range = initMax - initMin;
}
return range;
}
public static void main(String[] args) throws IOException {
double[] num = new double[12];
File inFile = new File("data.txt");
Scanner in = new Scanner(inFile);
for (int i = 0; i < num.length && in.hasNext(); i++) {
num[i] = in.nextDouble();
// System.out.println(num[i]);
}
double avg = grades.avg(num);
System.out.println("Arithmetic Mean = " + avg);
System.out.printf("Median = %.2f%n", grades.getMedian(num));
System.out.println("Range = " + range);
}
public static double getMedian(double[] num) {
int pos = (int) num.length / 2;
return num[pos];
}
}
I don't know how to print the calculations from the range out or calculate the mode.
You have already written a function to calculate the Range. Here is how you can print the Range.
System.out.println("Range = " + getRange(num));
Here is a quick code snippet to calculate the Mode:
public static double calculateMode(final double[] numberList) {
double[] cnts = new double[numberList.length];
double mode = 0, max = 0;
for (int i = 0; i < numberList.length; i++) {
/* Update Count Counter */
cnts[numberList[i]]++;
/* Check */
if (max < cnts[numberList[i]]) {
/* Update Max */
max = cnts[numberList[i]];
/* Update Mode */
mode = numberList[i];
}
}
/* Return Result */
return mode;
}
try sorting the element into an array.it will give following results:
[49,53,60,71,75,92]
suppose you stored it in array A.
int arrLength=A.length();
for(i=0,sum=0;i<arrlength;i++)
sum=sum+A[i]
mean=sum/arrLength;
median=A[arrLength/2]
I think you didn't sort the elements before finding median.
Do same thing to calculate range.It will be easier , I feel
I have a big problem. I try to create a neural network and want to train it with a backpropagation algorithm. I found this tutorial here http://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/ and tried to recreate it in Java. And when I use the training data he uses, I get the same results as him.
Without backpropagation my TotalError is nearly the same as his. And when I use the back backpropagation 10 000 time like him, than I get the nearly the same error. But he uses 2 Input Neurons, 2 Hidden Neurons and 2 Outputs but I'd like to use this neural network for OCR, so I need definitely more Neurons. But if I use for example 49 Input Neurons, 49 Hidden Neurons and 2 Output Neurons, It takes very long to change the weights to get a small error. (I believe it takes forever.....). I have a learningRate of 0.5. In the constructor of my network, I generate the neurons and give them the same training data like the one in the tutorial and for testing it with more neurons, I gave them random weights, inputs and targets. So can't I use this for many Neurons, does it takes just very long or is something wrong with my code ? Shall I increase the learning rate, the bias or the start weight?
Hopefully you can help me.
package de.Marcel.NeuralNetwork;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Random;
public class Network {
private ArrayList<Neuron> inputUnit, hiddenUnit, outputUnit;
private double[] inHiWeigth, hiOutWeigth;
private double hiddenBias, outputBias;
private double learningRate;
public Network(double learningRate) {
this.inputUnit = new ArrayList<Neuron>();
this.hiddenUnit = new ArrayList<Neuron>();
this.outputUnit = new ArrayList<Neuron>();
this.learningRate = learningRate;
generateNeurons(2,2,2);
calculateTotalNetInputForHiddenUnit();
calculateTotalNetInputForOutputUnit();
}
public double calcuteLateTotalError () {
double e = 0;
for(Neuron n : outputUnit) {
e += 0.5 * Math.pow(Math.max(n.getTarget(), n.getOutput()) - Math.min(n.getTarget(), n.getOutput()), 2.0);
}
return e;
}
private void generateNeurons(int input, int hidden, int output) {
// generate inputNeurons
for (int i = 0; i < input; i++) {
Neuron neuron = new Neuron();
// for testing give each neuron an input
if(i == 0) {
neuron.setInput(0.05d);
} else if(i == 1) {
neuron.setOutput(0.10d);
}
inputUnit.add(neuron);
}
// generate hiddenNeurons
for (int i = 0; i < hidden; i++) {
Neuron neuron = new Neuron();
hiddenUnit.add(neuron);
}
// generate outputNeurons
for (int i = 0; i < output; i++) {
Neuron neuron = new Neuron();
if(i == 0) {
neuron.setTarget(0.01d);
} else if(i == 1) {
neuron.setTarget(0.99d);
}
outputUnit.add(neuron);
}
// generate Bias
hiddenBias = 0.35;
outputBias = 0.6;
// generate connections
double startWeigth = 0.15;
// generate inHiWeigths
inHiWeigth = new double[inputUnit.size() * hiddenUnit.size()];
for (int i = 0; i < inputUnit.size() * hiddenUnit.size(); i += hiddenUnit.size()) {
for (int x = 0; x < hiddenUnit.size(); x++) {
int z = i + x;
inHiWeigth[z] = round(startWeigth, 2, BigDecimal.ROUND_HALF_UP);
startWeigth += 0.05;
}
}
// generate hiOutWeigths
hiOutWeigth = new double[hiddenUnit.size() * outputUnit.size()];
startWeigth += 0.05;
for (int i = 0; i < hiddenUnit.size() * outputUnit.size(); i += outputUnit.size()) {
for (int x = 0; x < outputUnit.size(); x++) {
int z = i + x;
hiOutWeigth[z] = round(startWeigth, 2, BigDecimal.ROUND_HALF_UP);
startWeigth += 0.05;
}
}
}
private double round(double unrounded, int precision, int roundingMode)
{
BigDecimal bd = new BigDecimal(unrounded);
BigDecimal rounded = bd.setScale(precision, roundingMode);
return rounded.doubleValue();
}
private void calculateTotalNetInputForHiddenUnit() {
// calculate totalnetinput for each hidden neuron
for (int s = 0; s < hiddenUnit.size(); s++) {
double net = 0;
int x = (inHiWeigth.length / inputUnit.size());
// calculate toAdd
for (int i = 0; i < x; i++) {
int v = i + s * x;
double weigth = inHiWeigth[v];
double toAdd = weigth * inputUnit.get(i).getInput();
net += toAdd;
}
// add bias
net += hiddenBias * 1;
net = net *-1;
double output = (1.0 / (1.0 + (double)Math.exp(net)));
hiddenUnit.get(s).setOutput(output);
}
}
private void calculateTotalNetInputForOutputUnit() {
// calculate totalnetinput for each hidden neuron
for (int s = 0; s < outputUnit.size(); s++) {
double net = 0;
int x = (hiOutWeigth.length / hiddenUnit.size());
// calculate toAdd
for (int i = 0; i < x; i++) {
int v = i + s * x;
double weigth = hiOutWeigth[v];
double outputOfH = hiddenUnit.get(s).getOutput();
double toAdd = weigth * outputOfH;
net += toAdd;
}
// add bias
net += outputBias * 1;
net = net *-1;
double output = (double) (1.0 / (1.0 + Math.exp(net)));
outputUnit.get(s).setOutput(output);
}
}
private void backPropagate() {
// calculate ouputNeuron weigthChanges
double[] oldWeigthsHiOut = hiOutWeigth;
double[] newWeights = new double[hiOutWeigth.length];
for (int i = 0; i < hiddenUnit.size(); i += 1) {
double together = 0;
double[] newOuts = new double[hiddenUnit.size()];
for (int x = 0; x < outputUnit.size(); x++) {
int z = x * hiddenUnit.size() + i;
double weigth = oldWeigthsHiOut[z];
double target = outputUnit.get(x).getTarget();
double output = outputUnit.get(x).getOutput();
double totalErrorChangeRespectOutput = -(target - output);
double partialDerivativeLogisticFunction = output * (1 - output);
double totalNetInputChangeWithRespect = hiddenUnit.get(x).getOutput();
double puttedAllTogether = totalErrorChangeRespectOutput * partialDerivativeLogisticFunction
* totalNetInputChangeWithRespect;
double weigthChange = weigth - learningRate * puttedAllTogether;
// set new weigth
newWeights[z] = weigthChange;
together += (totalErrorChangeRespectOutput * partialDerivativeLogisticFunction * weigth);
double out = hiddenUnit.get(x).getOutput();
newOuts[x] = out * (1.0 - out);
}
for (int t = 0; t < newOuts.length; t++) {
inHiWeigth[t + i] = (double) (inHiWeigth[t + i] - learningRate * (newOuts[t] * together * inputUnit.get(t).getInput()));
}
hiOutWeigth = newWeights;
}
}
}
And my Neuron Class:
package de.Marcel.NeuralNetwork;
public class Neuron {
private double input, output;
private double target;
public Neuron () {
}
public void setTarget(double target) {
this.target = target;
}
public void setInput (double input) {
this.input = input;
}
public void setOutput(double output) {
this.output = output;
}
public double getInput() {
return input;
}
public double getOutput() {
return output;
}
public double getTarget() {
return target;
}
}
Think about it: you have 10,000 propagations through 49->49->2 neurons. Between the input layer and the hidden layer, you have 49 * 49 links to propagate through, so parts of your code are being executed about 24 million times (10,000 * 49 * 49). That is going to take time. You could try 100 propogations, and see how long it takes, just to give you an idea.
There are a few things that can be done to increase performance, like using a plain array instead of an ArrayList, but this is a better topic for the Code Review site. Also, don't expect this to give drastic improvements.
Your back propagation code has complexity of O(h*o + h^2) * 10000, where h is the number of hidden neurons and o is the number of output neurons. Here's why.
You have a loop that executes for all of your hidden neurons...
for (int i = 0; i < hiddenUnit.size(); i += 1) {
... containing another loop that executes for all the output neurons...
for (int x = 0; x < outputUnit.size(); x++) {
... and an additional inner loop that executes again for all the hidden neurons...
double[] newOuts = new double[hiddenUnit.size()];
for (int t = 0; t < newOuts.length; t++) {
... and you execute all of that ten thousand times. Add on top of this O(i + h + o) [initial object creation] + O(i*h + o*h) [initial weights] + O(h*i) [calculate net inputs] + O(h*o) [calculate net outputs].
No wonder it's taking forever; your code is littered with nested loops. If you want it to go faster, factor these out - for example, combine object creation and initialization - or reduce the number of neurons. But significantly cutting the number of back propagation calls is the best way to make this run faster.
I made 2 small scripts in physics today, but now it is starting to bug me.
The first script, is 100% accurate: It is used to calculate the number of bill and coins required for the desired amount of cash.
First Script:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Change {
static Money[] coins;
static int[] counts;
public static void main(String[] args) throws IOException {
coins = new Money[11];
counts = new int[11];
coins[0] = new Money(100);
coins[1] = new Money(50);
coins[2] = new Money(20);
coins[3] = new Money(10);
coins[4] = new Money(5);
coins[5] = new Money(2);
coins[6] = new Money(1);
coins[7] = new Money(25, true);
coins[8] = new Money(10, true);
coins[9] = new Money(5, true);
coins[10] = new Money(1, true);
System.out.println("Please type the change:\n");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String values = br.readLine();
String[] split = values.split("\\.");
System.out.println();
int whole = Integer.parseInt(split[0]);
int small = Integer.parseInt(split[1]);
for (int i = 0; i < 7; i++) {
while (whole >= coins[i].getValue()) {
whole -= coins[i].getValue();
counts[i]++;
}
}
for (int i = 7; i < 11; i++) {
while (small >= coins[i].getValue()) {
small -= coins[i].getValue();
counts[i]++;
}
}
for (int i = 0; i < 11; i++) {
if (counts[i] > 0)
System.out
.println((coins[i].getValue() == 100 ? "" : " ")
+ (coins[i].isDecimal() ? (" 0."
+ (coins[i].getValue() < 10 ? "0" : "") + coins[i]
.getValue()) + ": " + counts[i]
: ((coins[i].getValue() <= 5 ? " " : "") + coins[i]
.getValue())
+ ".00: "
+ counts[i]));
}
}
public static class Money {
int value;
boolean decimal;
Money(int value) {
this(value, false);
}
Money(int value, boolean decimal) {
this.value = value;
this.decimal = decimal;
}
boolean isDecimal() {
return decimal;
}
int getValue() {
return value;
}
}
}
Second script:
import java.io.IOException;
public class ChangeMax {
static Money[] coins;
static int[] nums = new int[2];
static int max = -2147483648;
public static void main(String[] args) throws IOException{
coins = new Money[11];
coins[0] = new Money(100);
coins[1] = new Money(50);
coins[2] = new Money(20);
coins[3] = new Money(10);
coins[4] = new Money(5);
coins[5] = new Money(2);
coins[6] = new Money(1);
coins[7] = new Money(25, true);
coins[8] = new Money(10, true);
coins[9] = new Money(5, true);
coins[10] = new Money(1, true);
for(int i = 0; i < 100; i++){
int temp1 = i;
for(int h = 1; h < 100; h++){
int temp2 = h;
int[] counts = new int[100];
for (int j = 0; j < 7; j++) {
while (temp1 >= coins[j].getValue()) {
temp1 -= coins[j].getValue();
counts[j]++;
}
}
for (int k = 7; k < 11; k++) {
while (temp2 >= coins[k].getValue()) {
temp2 -= coins[k].getValue();
counts[k]++;
}
}
int sum = 0;
for(int p : counts){
sum += p;
}
if(sum > max){
max = sum;
nums[0] = i;
nums[1] = h;
}
}
}
System.out.println("\nMax coins and bills required at: $"+nums[0]+"."+(nums[1] > 9 ? nums[1] : "0" + nums[1]) + ": "+max+"\n");
}
public static class Money {
int value;
boolean decimal;
Money(int value) {
this(value, false);
}
Money(int value, boolean decimal) {
this.value = value;
this.decimal = decimal;
}
boolean isDecimal() {
return decimal;
}
int getValue() {
return value;
}
}
}
The second script, does the same thing, but runs through all the values under $100.
The problem is, is that the second script says the max amount is 9, and achieved at $0.94.
The first, script, when you type something like $1.94, does not register that 10 is the new highest number, instead of 9.
What seems to be the problem?
Since I am not planning on doing your homework I am not going to provide you with working code, but both scripts can be easily improved
1) Your money objects know whether a value of e.g. 10 represents 10 whole dollars, or 10 cents (or whatever you use in America, I would use Euro's and cents). But still you use an hard-coded index of your array where you switch from dollars to cents
2) The first script will fail when somebody uses a nice rounded number as input, without decimal part
3) If you would convert your input first to cents, and all your values in your coin array as well, your code will end up much cleaner and easier to understand. Something in the form of
int startAmount = ... ;//in cents
int remainder = startAmount;
int coinCounter = new int[coins.length];
for ( int i = 0; i < coins.length; i++ ){
int currentCoin = coins[i];//in cents
coinCointer[i] = 0;
while( remainder >= currentCoin ){
coinCointer[i] = coinCointer[i] + 1;
remainder = remainder - currentCoin;
}
}
//print out by looping over coinCounter,
//and use the info contained in the Money class