Я реализовал обратную нейронную сеть и обучил ее своим данным. Данные чередуются между предложениями на английском языке & Africa. Предполагается, что нейронная сеть идентифицирует язык ввода.Ошибка нейронной сети с каждым примером обучения
Структура сети 27 * 16 * 2 Входной слой содержит 26 входов для каждой буквы алфавита плюс блок смещения.
Моя проблема заключается в том, что ошибка бросается бурно в противоположных направлениях, так как каждый новый пример обучения встречается. Как я уже упоминал, примеры обучения читаются чередующимся образом (английский, африканский, английский ...)
Я могу обучить сеть, чтобы идентифицировать всех англичан или всех африканцев, но не идентифицировать ни один (оба) в тот же проход.
Ось ниже - это ошибка выходного сигнала для каждого из двух выходных узлов (английский и африканец), а ось x - номер примера обучения. В некотором смысле, он делает именно то, что я запрограммировал для этого; когда пример является английским, он меняет вес, чтобы лучше идентифицировать английский. Однако, делая это, это делает сеть хуже при прогнозировании африканцев. Вот почему ошибка идет между положительными и отрицательными значениями.
Очевидно, что это не так, как должно работать, но я застрял.
Я чувствую, как будто ошибка концептуальное с моей стороны, но вот соответствующий код:
public void train() throws NumberFormatException, IOException{
// Training Accuracy
double at = 0;
//epoch
int epoch = 0;
int tNum = 0;
for(; epoch < epochMax; epoch++){
// Reads stock files from TestPackage package in existing project
BufferedReader br = new BufferedReader(new InputStreamReader(this.getClass().
getResourceAsStream("/TrainingData/" + trainingData.getName())));
while ((line = br.readLine()) != null) {
Boolean classified = false;
tNum++;
// Set the correct classification Tk
t[0] = Integer.parseInt(line.split("\t")[0]); //Africaans
t[1] = (t[0] == 0) ? 1 : 0; // English
// Convert training string to char array
char trainingLine[] = line.split("\t")[1].toLowerCase().toCharArray();
// Increment idx of input layer z, that matches
// the position of the char in the alphabet
// a == 0, b == 2, etc.....
for(int l = 0; l < trainingLine.length; l++){
if((int)trainingLine[l] >= 97 && (int)trainingLine[l] <= 122)
z[(int)trainingLine[l] % 97]++;
}
/*System.out.println("Z " + Arrays.toString(z));
System.out.println();*/
// Scale Z
for(int i = 0; i < z.length-1; i++){
z[i] = scale(z[i], 0, trainingLine.length, -Math.sqrt(3),Math.sqrt(3));
}
/*----------------------------------------------------------------
* SET NET HIDDEN LAYER
* Each ith unit of the hidden Layer =
* each ith unit of the input layer
* multiplied by every j in the ith level of the weights matrix ij*/
for(int j = 0; j < ij.length; j++){ // 3
double[] dotProduct = multiplyVectors(z, ij[j]);
y[j] = sumVector(dotProduct);
}
/*----------------------------------------------------------------
* SET ACTIVATION HIDDEN LAYER
*/
for(int j = 0; j < y.length-1; j++){
y[j] = sigmoid(y[j], .3, .7);
}
/*----------------------------------------------------------------
* SET NET OUTPUT LAYER
* Each jth unit of the hidden Layer =
* each jth unit of the input layer
* multiplied by every k in the jth level of the weights matrix jk*/
for(int k = 0; k < jk.length; k++){ // 3
double[] dotProduct = multiplyVectors(y, jk[k]);
o[k] = sumVector(dotProduct);
}
/*----------------------------------------------------------------
* SET ACTIVATION OUTPUT LAYER
*/
for(int k = 0; k < o.length; k++){
o[k] = sigmoid(o[k], .3, .7);
}
/*----------------------------------------------------------------
* SET OUTPUT ERROR
* For each traing example, evalute the error.
* Error is defined as (Tk - Ok)
* Correct classifications will result in zero error:
* (1 - 1) = 0
* (0 - 0) = 0
*/
for(int k = 0; k < o.length; k++){
oError[k] = t[k] - o[k];
}
/*----------------------------------------------------------------
* SET TRAINING ACCURACY
* If error is 0, then a 1 indicates a succesful prediction.
* If error is 1, then a 0 indicates an unsucessful prediction.
*/
if(quantize(o[0],.3, .7) == t[0] && quantize(o[1], .3, .7) == t[1]){
classified = true;
at += 1;
}
// Only compute errors and change weiths for classification errors
if(classified){
continue;
}
/*----------------------------------------------------------------
* CALCULATE OUTPUT SIGNAL ERROR
* Error of ok = -(tk - ok)(1 - ok)ok
*/
for(int k = 0; k < o.length; k++){
oError[k] = outputError(t[k], o[k]);
}
/*----------------------------------------------------------------
* CALCULATE HIDDEN LAYER SIGNAL ERROR
*
*/
// The term (1-yk)yk is expanded to yk - yk squared
// For each k-th output unit, multiply it by the
// summed dot product of the two terms (1-yk)yk and jk[k]
for(int j = 0; j < y.length; j++){
for(int k = 0; k < o.length; k++){
/*System.out.println(j+"-"+k);*/
yError[j] += oError[k] * jk[k][j] * (1 - y[j]) * y[j];
}
}
/*----------------------------------------------------------------
* CALCULATE NEW WIGHTS FOR HIDDEN-JK-OUTPUT
*
*/
for(int k = 0; k < o.length; k++){
for(int j = 0; j < y.length; j++){
djk[k][j] = (-1*learningRate)*oError[k]*y[j] + momentum*djk[k][j];
// Old weights = themselves + new delta weight
jk[k][j] += djk[k][j];
}
}
/*----------------------------------------------------------------
* CALCULATE NEW WIGHTS FOR INPUT-IJ-HIDDEN
*
*/
for(int j = 0; j < y.length-1; j++){
for(int i = 0; i < z.length; i++){
dij[j][i] = (-1*learningRate)*yError[j]*z[i] + momentum*dij[j][i];
// Old weights = themselves + new delta weight
ij[j][i] += dij[j][i];
}
}
}
}
// Accuracy Percentage
double at_prec = (at/tNum) * 100;
System.out.println("Training Accuracy: " + at_prec);
}
Не имея возможности увидеть весь ваш код, моим первым предложением было бы уменьшить ваш показатель скорости обучения ('learningRate'). – bogatron
Я пробовал много разных параметров, но я не думаю, что это проблема с параметрами. – COOLBEANS
Не совсем понятно, что вы рисуете, но поскольку ваши примеры чередуются между двумя классами, не кажется необоснованным, что и результаты будут чередоваться. Было бы лучше построить функцию потерь. – cfh