-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathNeuralNet.java
More file actions
243 lines (126 loc) · 6.63 KB
/
NeuralNet.java
File metadata and controls
243 lines (126 loc) · 6.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
package arkangel;
import java.io.IOException;
import java.util.*;
public class NeuralNet {
//bias neurons here can be initizalized to any reasonable value; setting them 0 means they won't be included
double bias = 0.0;
double bias1 = 0.0;
//creating the WordVectorizer objects for training, and then testing the system
static WordVectorizer wv = new WordVectorizer();
static int count =1; //for counting the number of tweets it classifies correctly
static final double learning_rate = 0.08; //setting the rate at which parameters to be updated
static Neuron_Object[] inputLayer,hiddenLayer; //an array of Neuron_Objects for the input
//and hidden layer
static Neuron_Object outputNeuron; //a single neuron required for computing output
//Constructor sets up the network and populates
//and populates each layer with specified number of neurons accordingly
NeuralNet(int inputs, int hidden) {
inputLayer = new Neuron_Object[inputs + 1];
hiddenLayer = new Neuron_Object[hidden + 1];
//iterating over the input and hidden layers to add neuron
for(int i=0; i < inputs; i++) {
inputLayer[i] = new Neuron_Object();
}
inputLayer[inputs] = new Neuron_Object(bias);
for(int i=0; i < hidden; i++) {
hiddenLayer[i] = new Neuron_Object();
}
hiddenLayer[hidden] = new Neuron_Object(bias1);
outputNeuron = new Neuron_Object();
//establishing the connection between each neuron in input layer
//and corresponding neurons in hidden layer via nested for loop
for (int i = 0; i < inputLayer.length; i++) {
for (int j = 0; j < hiddenLayer.length; j++) {
//makes connection b/w any two neurons in input and hidden layer
Connections c = new Connections(inputLayer[i],hiddenLayer[j]);
inputLayer[i].addConnections(c);
hiddenLayer[j].addConnections(c);
}
}
//establishing the connection between each neuron in hidden layer
//and the output
for (int i = 0; i < hiddenLayer.length; i++) {
Connections c = new Connections(hiddenLayer[i] ,outputNeuron);
hiddenLayer[i].addConnections(c);
outputNeuron.addConnections(c);
}
} //constructor ends
//so in a feed-forward neural net, there are two main steps;
//forward propagation(where inputs are multiplied with the weights, summed up and passed forward)
//and backward propagation (the phase where the weights are tweaked as per the error,
//which is the difference between the network's guess and the actual output)
double forwardProp(ArrayList<Integer> inputArray) {
for (int i = 0; i < inputArray.size(); i++) {
inputLayer[i].output = inputArray.get(i);
}
//Each neuron in the hidden layer sums up the product
//of each neuron's input value and weight of the corresponding connection to
//produce its output
for (int i = 0; i < hiddenLayer.length-1; i++) {
hiddenLayer[i].hidden_neuron_guess();
}
// Calculate the output of the output neuron
outputNeuron.output_neuron_guess();
// Return the final output
return (outputNeuron.output);
}
static int binaryOutput(double y) {
return y < 0 ? 0 : 1; //because tanh 'squashes' output between -1 and 1
}
static int textualOutput(double y) {
return y < 0 ? "Negative":"Positive";
}
//backPropagation phase starts
double backPropagation(ArrayList<Integer>inputs, int correct_ans) {
double forwardPropResult = forwardProp(inputs); //first considers the net's output
double error = (forwardPropResult - correct_ans);
//first we tweak the connections from hidden layer to output neuron
for(int i=0; i < hiddenLayer.length; i++) {
Neuron_Object neuronToTweak = hiddenLayer[i]; //we consider the connection of a neuron in hidden layer
double output = neuronToTweak.output; // we get its result i.e. the input for the output layer
//multiplying by tanh derivative
double tweakedWeight =error*(output)*(1-Math.pow(forwardPropResult,2));
//double tweakedWeight =error*(output)*(forwardPropResult)*(1-forwardPropResult);
//double tweakedBias = error* (forwardPropResult)*(1-forwardPropResult);
neuronToTweak.synapses.get(i).updateWeight(learning_rate*tweakedWeight);
}
// Now we adjust the connections between input layer and hidden layer
for (int i = 0; i < inputLayer.length; i++) {
for(int j=0; j < hiddenLayer.length; j++) {
Neuron_Object neuron = inputLayer[i];
//deltaWeight= amount by which to update weight
double deltaWeight = error*Neuron_Object.relu_deriv_func(neuron.output)*neuron.output;
//double deltaBias = error*Neuron_Object.relu_deriv_func(neuron.output);
neuron.synapses.get(j).updateWeight(learning_rate*deltaWeight);
}
}
return forwardPropResult;
} //backPropagation class ends here
public static void main(String[] args) throws IOException, InterruptedException {
//starting the training phase
wv.trainDataReader("C:\\Users\\zakir\\Desktop\\training_Tweets.csv");
//initializing neural net with vocab size input layer neurons, and 10 hidden layer neurons
NeuralNet nn = new NeuralNet(wv.bagOfWords.size() , 10);
System.out.println("\nInitializing training....");
for(int j=0; j < 10; j++) {
for(int i=0; i <6000; i++) {
nn.backPropagation(wv.input_matrix.get(i), wv.label_array.get(i));
}
}
//training via back propagation ends after 10 epochs, or iterations
System.out.println("\nFinished training!!");
//now testing
System.out.println("INITIALIZNG TESTING");
wv.testDataReader("C:\\Users\\zakir\\Desktop\\testTweets(600).csv");
for(int i=0; i < 600; i++) {
double error = 0.5*Math.pow(nn.forwardProp(wv.test_matrix.get(i))-wv.test_label_array.get(i), 2);
System.out.printf("---> %.2f\n", error);
//doing this because in order to compute its accuracy over the test data
if(error==0.0) {
count++;
}
}
//accuracy displayed based on how many times it classifies a sentence with >80% accuracy
System.out.println("ACCURACY: " + (count/6)+ "%");
}
} //class ends here