@keksmr
Unity разработчик

Почему нейронная сеть неправильно обучается?

Вот класс нейронной сети:
Neiron Class
/// <summary> 
/// моя нейросеть 
/// </summary> 
public class NeuralNetExperemental 
{ 
NeironStrate layerIn, layer_1, layer_2, layerOut; 

public NeuralNetExperemental(int countInputs, int countL_1, int count_2, int countOutputs) 
{ 
layerIn = new NeironStrate(countInputs, countInputs); 
layer_1 = new NeironStrate(countInputs, countL_1); 
layer_2 = new NeironStrate(countL_1, count_2); 
layerOut = new NeironStrate(count_2, countOutputs); 
} 

public static float[] GetVector_1(int x, int size) 
{ 
float[] res = new float[size]; 

for (int i = 0; i < size; i++) 
{ 
res[i] = 0.0f; 
} 

res[x] = 1.0f; 

return res; 
} 

public float[] GetAnswer(float[] input) 
{ 
float[] answer; 

var tempore = layerIn.GetResult(input); 
tempore = layer_1.GetResult(tempore); 
tempore = layer_2.GetResult(tempore); 
answer = layerOut.GetResult(tempore); 

return answer; 
} 

/// <summary> 
/// метод для обучения нейросети 
/// </summary> 
/// <param name="inputs">входные параметры</param> 
/// <param name="output">желаемый выход</param> 
public void Formation(float[] inputs, float[] output, float h) 
{ 
var res = this.GetAnswer(inputs); 


//проход для выходного слоя 
for (int i = 0; i < layerOut.neurons.Length; i++) 
{ 
layerOut.neurons[i].forwardMass = output[i] - res[i]; 
} 

//Debug.Log("слой 2 нейронов = " + layer_2.neurons.Length + " входов на нейрон = " + layer_2.neurons[0].mass.Length); 
//Debug.Log("слой выход нейронов = " + layerOut.neurons.Length + " входов на нейрон = " + layerOut.neurons[0].mass.Length); 
//проход для второго слоя 
for (int i = 0; i < layer_2.neurons.Length; i++) 
{ 
float diff = 0.0f; 

for (int j = 0; j < layerOut.neurons.Length; j++) 
{ 
diff = diff + layerOut.neurons[j].mass[i] * layerOut.neurons[j].forwardMass; 
//var t = layerOut.neurons[i]; 
} 

layer_2.neurons[i].forwardMass = diff; 
} 

//проход для первого слоя 
for (int i = 0; i < layer_1.neurons.Length; i++) 
{ 
float diff = 0.0f; 

for (int j = 0; j < layer_2.neurons.Length; j++) 
{ 
diff = diff + layer_2.neurons[j].mass[i] * layer_2.neurons[j].forwardMass; 
} 

layer_1.neurons[i].forwardMass = diff; 
} 

//проход для входного слоя 
for (int i = 0; i < layerIn.neurons.Length; i++) 
{ 
float diff = 0.0f; 

for (int j = 0; j < layer_1.neurons.Length; j++) 
{ 
diff = diff + layer_1.neurons[j].mass[i] * layer_1.neurons[j].forwardMass; 
} 

layerIn.neurons[i].forwardMass = diff; 
} 

//корректировка весов слой входа 
for (int i = 0; i < layerIn.neurons.Length; i++) 
{ 
for (int j = 0; j < layerIn.neurons[i].mass.Length; j++) 
{ 
layerIn.neurons[i].mass[j] = layerIn.neurons[i].mass[j] + h * layerIn.neurons[i].forwardMass * Neiron.Sigma(inputs[j], 1.0f) * (1 - Neiron.Sigma(inputs[j], 1.0f) ); 
} 
} 

//корректировка весов слой 1 
var out_1 = layerIn.GetResult(inputs); 

for (int i = 0; i < layer_1.neurons.Length; i++) 
{ 
for (int j = 0; j < layer_1.neurons[i].mass.Length; j++) 
{ 
layer_1.neurons[i].mass[j] = layer_1.neurons[i].mass[j] + h * layer_1.neurons[i].forwardMass * Neiron.Sigma(out_1[j], 1.0f) * (1 - Neiron.Sigma(out_1[j], 1.0f)); 
} 
} 

//корректировка весов слой 2 
out_1 = layer_1.GetResult(out_1); 

for (int i = 0; i < layer_2.neurons.Length; i++) 
{ 
for (int j = 0; j < layer_2.neurons[i].mass.Length; j++) 
{ 
layer_2.neurons[i].mass[j] = layer_2.neurons[i].mass[j] + h * layer_2.neurons[i].forwardMass * Neiron.Sigma(out_1[j], 1.0f) * (1 - Neiron.Sigma(out_1[j], 1.0f)); 
} 
} 

//корректировка весов слой выхода 
out_1 = layer_2.GetResult(out_1); 

for (int i = 0; i < layerOut.neurons.Length; i++) 
{ 
for (int j = 0; j < layerOut.neurons[i].mass.Length; j++) 
{ 
layerOut.neurons[i].mass[j] = layerOut.neurons[i].mass[j] + h * layerOut.neurons[i].forwardMass * Neiron.Sigma(out_1[j], 1.0f) * (1 - Neiron.Sigma(out_1[j], 1.0f)); 
} 
} 


} 

public float GetErreur(float[] input, float[] Out) 
{ 
float result = 0.0f; 

var fl_res = this.GetAnswer(input); 

for (int i = 0; i < fl_res.Length; i++) 
{
 
result = result + Mathf.Pow(Out[i] - fl_res[i], 2.0f); 
} 

return result; 
} 
} 

/// <summary> 
/// класс слоя нейросети 
/// </summary> 
public class NeironStrate 
{ 
public NeironPourStrate[] neurons; 

/// <summary> 
/// 
/// </summary> 
/// <param name="countInputs">количество входов с предыдущего слоя в нейроне этого слоя</param> 
/// <param name="size">количество нейронов в слое</param> 
public NeironStrate(int countInputs, int size) 
{ 
neurons = new NeironPourStrate[size]; 

for (int i = 0; i < neurons.Length; i++) 
{ 
neurons[i] = new NeironPourStrate(countInputs); 
} 
} 

public float[] GetResult(float[] input) 
{ 
float[] result = new float[neurons.Length]; 

for (int i = 0; i < result.Length; i++) 
{ 
result[i] = neurons[i].GetAnswer(input); 
} 

return result; 
} 

} 

/// <summary> 
/// класс нейрона для скрытого слоя 
/// </summary> 
public class NeironPourStrate 
{ 
public float[] mass; 

/// <summary> 
/// массы ошибок 
/// </summary> 
public float forwardMass; 

/// <summary> 
/// 
/// </summary> 
/// <param name="countInputs">количество входов для ниго</param> 
public NeironPourStrate(int countInputs) 
{ 
mass = new float[countInputs]; 
forwardMass = 0.0f; 

for (int i = 0; i < mass.Length; i++) 
{ 
mass[i] = Random.Range(-1.0f, 1.0f); 
} 
} 

public float GetAnswer(float[] inputs) 
{ 
//Debug.Log("длинна входного массива = " + inputs.Length + " длинна нейр. = " + mass.Length); 

float summe = 0.0f; 

for (int i = 0; i < inputs.Length; i++) 
{ 
summe = summe + inputs[i] * mass[i]; 
} 

return Neiron.Sigma(summe, 1.0f); 
} 

public void ChangeMass(int numero, float value) 
{ 
mass[numero] = value; 
} 

}


У меня она обучается до минимальной ошибки, но все равно даёт лажу при тестовых значениях. Например, есть обучилась на X1(0,1,1,0), Y1(0,1) и X2(1,0,0,1), Y2(1,0)
И есть подать потом на вход X1(0,1,1,0), то на выходе все равно будет (1,0)

эта нейросеть всегда выдает значение, которому она обучалась в последний раз
  • Вопрос задан
  • 148 просмотров
Пригласить эксперта
Ответы на вопрос 1
@FFoxDiArt
Если вам не принципиально нужно написать свое решение, советую воспользоваться готовыми фреймворками, вроде Aforge. А сейчас у вас в коде что-то невнятное творится, я так и не понял, каким образом нейроны у вас между собой связаны и где сам цикл обучения, в котором уменьшается значение ошибки.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы