Hi I coded a single neuron to predict a student's mark for subject D based of the marks they got for subject A, B and C.
After training my neuron with some historical data that contain the 3 marks as well as the actual mark they got for subject D, I then inputed test data to see how closely the predicted mark would match with the actual one.
Below is my Neuron class
public class Neuron
{
double[] Weights = new double[3];
public Neuron(double W1, double W2, double W3)
{
Weights[0] = W1;
Weights[1] = W2;
Weights[2] = W3;
}
public double FnetLinear(int Z1, int Z2, int Z3)
{
return (Z1*Weights[0] + Z2*Weights[1] + Z3*Weights[2]);
}
public void UpdateWeight(int i, double Wi)
{
Weights[i] = Wi;
}
}
And here is my main class
public class Main
{
public int t;
public Neuron neuron;
double LearningRate = 0.00001;
public ArrayList<Marks> TrainingSet, TestSet;
public static void main(String[] args) throws IOException
{
Main main = new Main();
main.run();
}
public void run()
{
TrainingSet = ReadCSV("G:\\EVOS\\EVO_Assignemnt1\\resources\\Streamdata.csv");
TestSet = ReadCSV("G:\\EVOS\\EVO_Assignemnt1\\resources\\Test.csv");
Random ran = new Random();
neuron = new Neuron(ran.nextDouble(), ran.nextDouble(), ran.nextDouble());
train();
Test();
}
public void train()
{
t = 0;
while(t<1000000)
{
for(Marks mark: TrainingSet)
{
for(int i=0; i<neuron.Weights.length; i++)
{
double yp = neuron.FnetLinear(mark.marks[0] , mark.marks[1], mark.marks[2]);
double wi = neuron.Weights[i] - LearningRate*(-2*(mark.marks[3]-yp))*mark.marks[i];
neuron.UpdateWeight(i, wi);
}
}
t++;
}
}
public void Test()
{
System.out.println("Test Set results:");
int count = 1;
for(Marks mark: TestSet)
{
double fnet = neuron.FnetLinear(mark.marks[0] , mark.marks[1], mark.marks[2]);
System.out.println("Mark " + count + ": " + fnet);
count++;
}
}
public static ArrayList<Marks> ReadCSV(String csv)
{
ArrayList<Marks> temp = new ArrayList<>();
String line;
BufferedReader br;
try
{
br = new BufferedReader(new FileReader(csv));
while((line=br.readLine()) != null)
{
String[] n = line.split(",");
Marks stud = new Marks(Integer.valueOf(n[0]), Integer.valueOf(n[1]), Integer.valueOf(n[2]), Integer.valueOf(n[3]));
temp.add(stud);
}
}
catch (Exception e)
{
System.out.println("ERROR");
}
return temp;
}
}
This is the test data with the last number being the actual mark.
After running the test data i get results around these:
As you can see the first 4 marks predictions are way off from the actual mark.
I followed the text book's explenation of Computational Intlligence An Introduction (Chapter 2 if u are curious).
However I would like to know what I im doing wrong. How can I get more accurate results?
Neural networks are very black-box esque; Due to this, it's pretty hard to say exactly why your marks results are way off.
That being said, here are some of the main methods of increasing the accuracy of your neural network:
Adjust the number of layers and neurons; I notice you're only using a single neuron. A single neuron in a neural network is typically just... bad. You're never going to get any good results like that. Neural networks need enough complexity in the form of layering and neuron count in order to calculate or predict whatever it is you're trying to teach it to do. A single neuron by itself really can't learn anything useful. This is also probably a big reason why your network accuracy is so bad.
Train for longer; I notice you're only training your network 1 million times; this is not always enough. For reference, the last time I trained a neural network, I used over 30 million sets of input/output.
Retrain your network with different starting weights; Randomized starting weights are great, but sometimes you just get a bad batch of starting weights. In the same project where I used 30 million input/output sets, I also tried over 25 different configurations of initial starting weights across 15 different layouts of nodes and layers.
Pick a different activation function; Linear activation functions are usually not that useful. I usually default to using a sigmoid function to start off, unless there are specific other functions that fulfill the use case I'm trying to train.
A common pitfall that can cause low accuracy is bad training data; Make sure the training data you're using is correct and is internally consistent with whatever it is you're trying to teach.
As a final note, I find myself having some trouble understanding what kind of a neural network you're trying to write exactly; I've made the assumption that this is some sort of attempt at a feed forward, back propagation neural network with a single neuron in it, but most of the advice here should still apply.
Related
I have a CSV file with 500,000 rows of data and 22 columns. This data represents all commercial flights in the USA for one year. I am being tasked with finding the tail number of the plane that flew the most miles in the data set. Column 5 contains the airplain's tail number for each flight. Column 22 contains the total distance traveled.
Please see my extractQ3 method below. First, created a HashMap for the whole CSV using the createHashMap() method. Then, I ran a for loop to identify every unique tail number in the dataset and stored them in an array called tailNumbers. Then for each unique tail number, I looped through the entire Hashmap to calculate the total miles of distance for that tail number.
The code runs fine on smaller datasets, but once the sized increased to 500,000 rows the code becomes horribly inefficient and takes an eternity to run. Can anyone provide me with a faster way to do this?
public class FlightData {
HashMap<String,String[]> dataMap;
public static void main(String[] args) {
FlightData map1 = new FlightData();
map1.dataMap = map1.createHashMap();
String answer = map1.extractQ3(map1);
}
public String extractQ3(FlightData map1) {
ArrayList<String> tailNumbers = new ArrayList<String>();
ArrayList<Integer> tailMiles = new ArrayList<Integer>();
//Filling the Array with all tail numbers
for (String[] value : map1.dataMap.values()) {
if(Arrays.asList(tailNumbers).contains(value[4])) {
} else {
tailNumbers.add(value[4]);
}
}
for (int i = 0; i < tailNumbers.size(); i++) {
String tempName = tailNumbers.get(i);
int miles = 0;
for (String[] value : map1.dataMap.values()) {
if(value[4].contentEquals(tempName) && value[19].contentEquals("0")) {
miles = miles + Integer.parseInt(value[21]);
}
}
tailMiles.add(miles);
}
Integer maxVal = Collections.max(tailMiles);
Integer maxIdx = tailMiles.indexOf(maxVal);
String maxPlane = tailNumbers.get(maxIdx);
return maxPlane;
}
public HashMap<String,String[]> createHashMap() {
File flightFile = new File("flights_small.csv");
HashMap<String,String[]> flightsMap = new HashMap<String,String[]>();
try {
Scanner s = new Scanner(flightFile);
while (s.hasNextLine()) {
String info = s.nextLine();
String [] piecesOfInfo = info.split(",");
String flightKey = piecesOfInfo[4] + "_" + piecesOfInfo[2] + "_" + piecesOfInfo[11]; //Setting the Key
String[] values = Arrays.copyOfRange(piecesOfInfo, 0, piecesOfInfo.length);
flightsMap.put(flightKey, values);
}
s.close();
}
catch (FileNotFoundException e)
{
System.out.println("Cannot open: " + flightFile);
}
return flightsMap;
}
}
The answer depends on what you mean by "most efficient", "horribly inefficient" and "takes an eternity". These are subjective terms. The answer may also depend on specific technical factors (speed vs. memory consumption; the number of unique flight keys compared to the number of overall records; etc.).
I would recommend applying some basic streamlining to your code, to start with. See if that gets you a better (acceptable) result. If you need more, then you can consider more advanced improvements.
Whatever you do, take some timings to understand the broad impacts of any changes you make.
Focus on going from "horrible" to "acceptable" - and then worry about more advanced tuning after that (if you still need it).
Consider using a BufferedReader instead of a Scanner. See here. Although the scanner may be just fine for your needs (i.e. if it's not a bottleneck).
Consider using logic within your scanner loop to capture tail numbers and accumulated mileage in one pass of the data. The following is deliberately basic, for clarity and simplicity:
// The string is a tail number.
// The integer holds the accumulated miles flown for that tail number:
Map<String, Integer> planeMileages = new HashMap();
if (planeMileages.containsKey(tailNumber)) {
// add miles to existing total:
int accumulatedMileage = planeMileages.get(tailNumber) + flightMileage;
planeMileages.put(tailNumber, accumulatedMileage);
} else {
// capture new tail number:
planeMileages.put(tailNumber, flightMileage);
}
After that, once you have completed the scanner loop, you can iterate over your planeMileages to find the largest mileage:
String maxMilesTailNumber;
int maxMiles = 0;
for (Map.Entry<String, Integer> entry : planeMileages.entrySet()) {
int planeMiles = entry.getValue();
if (planeMiles > maxMiles) {
maxMilesTailNumber = entry.getKey();
maxMiles = planeMiles;
}
}
WARNING - This approach is just for illustration. It will only capture one tail number. There could be multiple planes with the same maximum mileage. You would have to adjust your logic to capture multiple "winners".
The above approach removes the need for several of your existing data structures, and related processing.
If you still face problems, put in some timers to see which specific areas of your code are slowest - and then you will have more specific tuning opportunities you can focus on.
I suggest you use the java 8 Stream API, so that you can take advantage of Parallel streams.
i am trying to calculate the mutual index of concidence of two strings, A and B. I have calculated the frequency of each letter in each string. However, i do not know how to continue from there. Any help is appreciated. The expected output is supposed to be some decimal value. Thanks!
public class MutualIndexOfAB
{
public double calculateMutual(String a, String b)
{
int i, j;
int NA = 0;
int NB = 0;
double sum = 0.0, total = 0.0;
a = a.toUpperCase();
b = b.toUpperCase();
// calculate frequency of each letter in String a
int chA;
for (i=0; i<a.length(); i++)
{
ch = a.charAt(i)-65;
if (chA>=0 && chA <26)
{
values[chA]++;
NA++;
}
}
// calculate frequency of each letter in String b
int chB;
for (j=0; j<b.length(); j++)
{
chB = b.charAt(j)-65;
if (chB>=0 && chB <26)
{
values[chB]++;
NB++;
}
}
}
public static void main(String[] args)
{
MutualIndexOfAB test = new MutualIndexOfAB();
String textA = "cyber security is about how we develop secure computers and computer networks, to ensure that the data stored and transmitted through them is protected from unauthorized access or to combat digital security threats and hazards. as we conduct more of our social, consumer and business activities online, there is a corresponding increase in the demand for ict professionals to manage our digital environment and economy.";
String textB = "cyber security has been identified as one of the strategic priorities in australia to meet the demands of law enforcement, national and state governments, defense, security and finance industries. jobs of the future will be in all of these areas ensuring there is national capability to maintain and build our essential services and stop them from being disrupted, destroyed, or threatened, and that our personal information is not communicated, shared, visualized or analysed without our permission.";
System.out.println("Mutual Index of Concidence of Texts A and B: " + test.calculateMutual(textA, textB));
}
}
Simply create a single loop with an index (instead of two), and then compare the characters of each string, increasing a counter if they match. Then perform division by the total number of characters.
I've written an Adaline Neural Network. Everything that I have compiles, so I know that there isn't a problem with what I've written, but how do I know that I have to algorithm correct? When I try training the network, my computer just says the application is running and it just goes. After about 2 minutes I just stopped it.
Does training normally take this long (I have 10 parameters and 669 observations)?
Do I just need to let it run longer?
Hear is my train method
public void trainNetwork()
{
int good = 0;
//train until all patterns are good.
while(good < trainingData.size())
{
for(int i=0; i< trainingData.size(); i++)
{
this.setInputNodeValues(trainingData.get(i));
adalineNode.run();
if(nodeList.get(nodeList.size()-1).getValue(Constants.NODE_VALUE) != adalineNode.getValue(Constants.NODE_VALUE))
{
adalineNode.learn();
}
else
{
good++;
}
}
}
}
And here is my learn method
public void learn()
{
Double nodeValue = value.get(Constants.NODE_VALUE);
double nodeError = nodeValue * -2.0;
error.put(Constants.NODE_ERROR, nodeError);
BaseLink link;
int count = inLinks.size();
double delta;
for(int i = 0; i < count; i++)
{
link = inLinks.get(i);
Double learningRate = value.get(Constants.LEARNING_RATE);
Double value = inLinks.get(i).getInValue(Constants.NODE_VALUE);
delta = learningRate * value * nodeError;
inLinks.get(i).updateWeight(delta);
}
}
And here is my run method
public void run()
{
double total = 0;
//find out how many input links there are
int count = inLinks.size();
for(int i = 0; i< count-1; i++)
{
//grab a specific link in sequence
BaseLink specificInLink = inLinks.get(i);
Double weightedValue = specificInLink.weightedInValue(Constants.NODE_VALUE);
total += weightedValue;
}
this.setValue(Constants.NODE_VALUE, this.transferFunction(total));
}
These functions are part of a library that I'm writing. I have the entire thing on Github here. Now that everything is written, I just don't know how I should go about actually testing to make sure that I have the training method written correctly.
I asked a similar question a few months ago.
Ten parameters with 669 observations is not a large data set. So there is probably an issue with your algorithm. There are two things you can do that will make debugging your algorithm much easier:
Print the sum of squared errors at the end of each iteration. This will help you determine if the algorithm is converging (at all), stuck at a local minimum, or just very slowly converging.
Test your code on a simple data set. Pick something easy like a two-dimensional input that you know is linearly separable. Will your algorithm learn a simple AND function of two inputs? If so, will it lean an XOR function (2 inputs, 2 hidden nodes, 2 outputs)?
You should be adding debug/test mode messages to watch if the weights are getting saturated and more converged. It is likely that good < trainingData.size() is not happening.
Based on Double nodeValue = value.get(Constants.NODE_VALUE); I assume NODE_VALUE is of type Double ? If that's the case then this line nodeList.get(nodeList.size()-1).getValue(Constants.NODE_VALUE) != adalineNode.getValue(Constants.NODE_VALUE) may not really converge exactly as it is of type double with lot of other parameters involved in obtaining its value and your convergence relies on it. Typically while training a neural network you stop when the convergence is within an acceptable error limit (not a strict equality like you are trying to check).
Hope this helps
I'm trying to compute the convert a R script to java using the apache.commons.math library. Can I use org.apache.commons.math.analysis.interpolation.LoessInterpolator in place of R loess ? I cannot get the same result.
EDIT.
here is a java program that creates a random array(x,y) and compute the loess with LoessInterpolator or by calling R. At the end, the results are printed.
import java.io.*;
import java.util.Random;
import org.apache.commons.math.analysis.interpolation.LoessInterpolator;
public class TestLoess
{
private String RScript="/usr/local/bin/Rscript";
private static class ConsummeInputStream
extends Thread
{
private InputStream in;
ConsummeInputStream(InputStream in)
{
this.in=in;
}
#Override
public void run()
{
try
{
int c;
while((c=this.in.read())!=-1)
System.err.print((char)c);
}
catch(IOException err)
{
err.printStackTrace();
}
}
}
TestLoess()
{
}
private void run() throws Exception
{
int num=100;
Random rand=new Random(0L);
double x[]=new double[num];
double y[]=new double[x.length];
for(int i=0;i< x.length;++i)
{
x[i]=rand.nextDouble()+(i>0?x[i-1]:0);
y[i]=Math.sin(i)*100;
}
LoessInterpolator loessInterpolator=new LoessInterpolator(
0.75,//bandwidth,
2//robustnessIters
);
double y2[]=loessInterpolator.smooth(x, y);
Process proc=Runtime.getRuntime().exec(
new String[]{RScript,"-"}
);
ConsummeInputStream errIn=new ConsummeInputStream(proc.getErrorStream());
BufferedReader stdin=new BufferedReader(new InputStreamReader(proc.getInputStream()));
PrintStream out=new PrintStream(proc.getOutputStream());
errIn.start();
out.print("T<-as.data.frame(matrix(c(");
for(int i=0;i< x.length;++i)
{
if(i>0) out.print(',');
out.print(x[i]+","+y[i]);
}
out.println("),ncol=2,byrow=TRUE))");
out.println("colnames(T)<-c('x','y')");
out.println("T2<-loess(y ~ x, T)");
out.println("write.table(residuals(T2),'',col.names= F,row.names=F,sep='\\t')");
out.flush();
out.close();
double y3[]=new double[x.length];
for(int i=0;i< y3.length;++i)
{
y3[i]=Double.parseDouble(stdin.readLine());
}
System.out.println("X\tY\tY.java\tY.R");
for(int i=0;i< y3.length;++i)
{
System.out.println(""+x[i]+"\t"+y[i]+"\t"+y2[i]+"\t"+y3[i]);
}
}
public static void main(String[] args)
throws Exception
{
new TestLoess().run();
}
}
compilation & exec:
javac -cp commons-math-2.2.jar TestLoess.java && java -cp commons-math-2.2.jar:. TestLoess
output:
X Y Y.java Y.R
0.730967787376657 0.0 6.624884763714674 -12.5936186703287
0.9715042030481429 84.14709848078965 6.5263049649584 71.9725380029913
1.6089216283982513 90.92974268256818 6.269100654071115 79.839773167581
2.159358633515885 14.112000805986721 6.051308261720918 3.9270340708818
2.756903911313087 -75.68024953079282 5.818424835586378 -84.9176311089431
3.090122310789737 -95.89242746631385 5.689740879461759 -104.617807889069
3.4753114955304554 -27.941549819892586 5.541837854229562 -36.0902352062634
4.460153035730264 65.6986598718789 5.168028655980764 58.9472823439219
5.339335553602744 98.93582466233818 4.840314399516663 93.3329030534449
6.280584733084859 41.21184852417566 4.49531113985498 36.7282165788057
6.555538699120343 -54.40211108893698 4.395343460231256 -58.5812856445538
6.68443584999412 -99.99902065507035 4.348559404444451 -104.039069260889
6.831037507640638 -53.657291800043495 4.295400167908642 -57.5419313320511
6.854275630124528 42.016703682664094 4.286978656933373 38.1564179414478
7.401015387322993 99.06073556948704 4.089252482141094 95.7504087842369
8.365502247999844 65.02878401571168 3.7422883733498726 62.5865641279576
8.469992934250815 -28.790331666506532 3.704793544880599 -31.145867173504
9.095139297716374 -96.13974918795569 3.4805388562453574 -98.0047896609079
9.505935493207435 -75.09872467716761 3.3330472034239405 -76.6664588290508
the output values for y are clearly not the same between R and Java; TheY.R column looks good (it's close to the original Y column). How should I change this in order to get Y.java ~ Y.R ?
You need to change the default values of three input parameters to make the Java and R versions identical:
The Java LoessInterpolator only does linear local polynomial regression, but R supports linear (degree=1), quadratic (degree=2), and a strange degree=0 option. So you need to specify degree=1 in R to be identical to Java.
LoessInterpolator defaults number of iterations DEFAULT_ROBUSTNESS_ITERS=2, but R defaults iterations=4. So you need to set control = loess.control(iterations=X) in R (X is the number of iterations).
LoessInterpolator defaults DEFAULT_BANDWIDTH=0.3 but R defaults span=0.75.
I can't speak for the java implementation, but lowess has a number of parameters which control the bandwidth of the fit. Unless you're fitting with the same control parameters you should expect the results to differ. My recommendation whenever people are smoothing data is to plot the original data as well as the fit, and decide for yourself what control parameters yield your desired tradeoff between fidelity to the data and smoothing (aka noise removal).
There are two problems here. First if you plot the data you are generating it looks almost random and the fit generated by loess in R is very poor e.g.
plot(T$x, T$y)
lines(T$s, T2$fitted, col="blue", lwd=3)
Then in your R script you are writing the residuals not the predictions so in this line
out.println("write.table(residuals(T2),'',
col.names= F,row.names=F,sep='\\t')");
you need to change residuals(T2) to predict(T2) e.g.
out.println("write.table(predict(T2),'',
col.names= F,row.names=F,sep='\\t')");
So it was pure chance in your code example that the first couple of lines of residuals generated by R looked a good fit.
For me if I try fitting with some more appropriate data then Java and R do return similar but not identical results. Also I found the results were closer if I did not adjust the default robustnessIter settings.
Looks like this is the week for this type of question. And after reading through all of the new ones and several old ones, I'm no less confused!
I have a text file with 5 employees, each having 10 salary values listed beneath their name. I am to read in this file, find and display the employee Name, minimum salary, maximum salary and the average salary for each person. I must have 3 loops: One to control reading the file, one to lad the data into the array, and one to do the calculations. I have to print the information for each person on one line, and i must allow decimals rounded to 2 decimal places apparently using Math.round which I've never heard of!
I am embarrassed to show you the mess of code I have because it's not much, but I don't know after reading all that I have if I've even started correctly. I do not know if I have even the right idea of how to proceed. Your help is appreciated.
UPDATED CODE: AGAIN!
import javax.swing.*;
import java.io.*;
public class MinMaxSalary3
{
public static void main(String args[])throws Exception
{
// Declare input file to be opened.
FileReader fr = new FileReader ("salary.dat");
BufferedReader br = new BufferedReader (fr);
//General Declarations
final String TITLE = "Employee's Salary Report";
String employeeName, salaryString;
double avgSalary=0.0;
double totalSalary = 0.0;
double sum = 0.0;
// Declare Named Constant for Array.
final int MAX_SAL = 10;
// Declare array here.
int salary[] = new int[MAX_SAL];
System.out.println (TITLE);
while ((employeeName = br.readLine()) != null)
{
System.out.print ("" + employeeName);
// Use this integer variable as your loop index.
int loopIndex;
// Assign the first element in the array to be the minimum and the maximum.
double minSalary = salary[1];
double maxSalary = salary[1];
// Start out your total with the value of the first element in the array.
sum = salary[1];
// Write a loop here to access array values starting with number[1]
for (loopIndex = 1; loopIndex < MAX_SAL ;loopIndex++)
// Within the loop test for minimum and maximum salaries.
{
if (salary[loopIndex] < minSalary)
{
minSalary = salary[loopIndex];
if (salary[loopIndex] > maxSalary)
maxSalary = salary[loopIndex];
}
{
// Also accumulate a total of all salaries.
sum += sum;
// Calculate the average of the 10 salaries.
avgSalary = sum/MAX_SAL;
}
// I know I need to close the files, and end the while loop and any other loops. I just can't think that far right now.
}
{
// Print the maximum salary, minimum salary, and average salary.
System.out.println ("Max Salary" + maxSalary);
System.out.println ("Min Salary" + minSalary);
System.out.println ("Avg Salary" + avgSalary);
}
System.exit(0);
}
}
}
I must have 3 loops: One to control reading the file, one to lad the
data into the array, and one to do the calculations.
What I've written below might just be more gobbledygook to you now, but if you ever get past this class it might be useful to know.
Another way to look at this would be more object-oriented and better decomposition to boot: You need an object to hold the data, to perform the calculations, and render output. How you get that data is immaterial. It's files today; next time it might be HTTP requests.
Start with an Employee object. I deliberately left out a lot of detail that you'll have to fill in and figure out:
package model;
public class Employee {
private String name;
private double [] salaries;
public Employee(String name, int numSalaries) {
this.name = name;
this.salaries = new double[numSalaries];
}
public double getMinSalary() {
double minSalary = Double.MAX_VALUE;
// you fill this in.
return minSalary;
};
public double getMaxSalary() {
double maxSalary = Double.MIN_VALUE;
// you fill this in.
return maxSalary;
}
public double getAveSalary() {
public aveSalary = 0.0;
if (this.salaries.length > 0) {
// you fill this in.
}
return aveSalary;
}
}
The beauty of this approach is that you can test it separately, without worrying about all the nonsense about file I/O. Get this object right, put it aside, and then tackle the next piece. Eventually you'll have a clean solution when you assemble all these smaller pieces together.
Test it without file I/O using JUnit:
package model;
public class EmployeeTest {
#Test
public void testGetters() {
double [] salaries = { 10000.0, 20000.0, 30000.0, 40000.0 };
Employee testEmployee = new Employee("John Q. Test", salaries);
Assert.assertEquals("John Q. Test", testEmployee.getName());
Assert.assertEquals(10000.0, testEmployee.getMinSalary(), 1.0e-3);
Assert.assertEquals(40000.0, testEmployee.getMaxSalary(), 1.0e-3);
Assert.assertEquals(25000.0, testEmployee.getMinSalary(), 1.0e-3);
}
}
The approach you would want to espouse in this situation is an object-oriented approach. Bear in mind that objects are a representation of related data. Consider that an Employee may have information about their salary, name, and what department they work in (as an example).
But that's just one Employee. You may have hundreds.
Consider creating a model of an Employee. Define what is most pertinent to one of them. For example, they all have to have a name, and have to have a salary.
One would then elect to handle the logic of finding information about the collection of Employees - including min, max, and average salaries - outside of the scope of the generic Employee object.
The idea is this:
An Employee knows everything about itself.
The onus is on the developer to tie multiple Employees together.
It's possible that I don't know enough about what your problem is specifically looking for - I'm not even sure that you can use objects, which would really suck - but this is definitely a start.
As for your compilation errors:
salary is a double[]. An array holds many different values of type double inside of it, but a double[] isn't directly a double. Assigning a non-array type to an array type doesn't work, from both a technical stance, and a semantic stance - you're taking something that can hold many values and trying to assign it to a container that can hold one value.
From your code sample, you want to use a loop (with a loop variable i) to iterate over all elements in salary, and assign them some value. Using just salary[0] only modifies the first element.