Laden...

Texterkennunge mit neuronalem Netzwerk

Erstellt von webco vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.573 Views
W
webco Themenstarter:in
12 Beiträge seit 2010
vor 13 Jahren
Texterkennunge mit neuronalem Netzwerk

Hallo,
ich habe einen einfachen Code (mithilfe Aforge Framework) geschrieben, der mithilfe von neuronalen Netzwerken zunächst erkennen soll ob es sich bei einem Bitmap um ein A oder B handelt. Jetzt will ich wissen, ob mein Code prinzipiell funktionieren kann, oder warum nicht.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AForge;
using AForge.Neuro;
using AForge.Neuro.Learning;
using AForge.Math;
using System.Drawing;
namespace Prg1
{
    class Program
    {


        static void Main(string[] args)
        {
        
            Bitmap A= PRG1.Properties.Resources.A;
            
            Bitmap B = PRG1.Properties.Resources.B;

            List<double[]> inputs = new List<double[]>();
            double[] inputA = new double[A.Width * A.Height];
            double[] inputB = new double[A.Width * A.Height];
            
            int index=0;
            for (int x = 0; x < A.Width; x++)
            {
                for (int y = 0; y < A.Height; y++)
                {

                    inputA[index] = (A.GetPixel(x, y).A * A.GetPixel(x, y).B * A.GetPixel(x, y).G == 255 * 255 * 255) ? 0.0 : 1.0;
                    inputB[index] = (B.GetPixel(x, y).B * A.GetPixel(x, y).B * B.GetPixel(x, y).G == 255 * 255 * 255) ? 0.0 : 1.0;                    
                    
                    index++;
                }
            }
            inputs.Add(inputA);
            inputs.Add(inputB);
            
          
            List<double[]> outputs = new List<double[]>();
            outputs.Add(new double[]{1.0} );
            outputs.Add(new double[] { 0.0});
            


            ActivationNetwork network = new ActivationNetwork(new SigmoidFunction(), inputA.Length, 2, 1);
            BackPropagationLearning teacher = new BackPropagationLearning(network);
            network.Randomize();
            
            for (int y = 0; y < 5000; y++)
            {
                teacher.RunEpoch(inputs.ToArray(),outputs.ToArray());   
                Console.WriteLine(y.ToString());         
            }
            for (int x = 0; x < inputs.Count; x++)
            {
                Console.WriteLine("Output: {0} | Desired Output: {1}", Math.Round( network.Compute(inputs[x])[0],0), outputs[x][0]);
            }
            
            Console.ReadLine();
            
        }
    }
}

Die Ressourcen A und B sind Bitmaps (10*10 Pixel) die den Buchstaben A bzw. B in schwarzer Schrift und weißem Hintergrunde enthalten.
Der Code funktioniert nicht, da beide Outputs immer 0 sind..
Liegt das vielleicht an dieser Zeile?

ActivationNetwork network = new ActivationNetwork(new SigmoidFunction(), inputA.Length, 2, 1);

Für was steht der 2. Parameter? Für die Anzahl der hidden-Neurons? Müssen das immer 2 sein, oder woher weiß ich wie viele ich von denen brauch?

Kann mein Ansatz überhaupt funktionieren?

Vielen Dank für Hilfe 👍

N
335 Beiträge seit 2006
vor 13 Jahren

Hallo webco,

wofür die Parameter stehen, erfährst du in der Dokumentation 😉

Im Fall von ActivationNetwork stehen die Zahlen nach inputA.Length für die Anzahl an Neuronen in den Schichten (jede Zahl ist eine Schicht).

Dein Netzwerk hat also inputA.Length Eingabe-Neuronen, 2 Neuronen in einem Hidden-Layer und 1 Neuron in der Ausgabeschicht.

Ich bezweifle stark, dass du damit brauchbare Ergebnisse erreichst, insbesondere wenn die restlichen Buchstaben auch mal später hinzu kommen sollen.
Wieviele du brauchst, kann man nicht genau sagen. Das muss man häufig ausprobieren oder schätzen.

Oftmals funktionieren neuronale Netze besser, wenn man binäre Aktivierungen ({0, 1} oder {-1, 1} als Wertebereich der Neuronen) nimmt. Das heißt, es könnte helfen, wenn du dein Bild nach Graustufen konvertierst und auf eines der beiden Intervalle normierst.
Sicherlich ist es auch sinnvoll so viele Ausgabeneuronen zu haben wie die Anzahl an zu unterscheidenden Klassen (z.B. hier 26 fürs Alphabet).
Die Zwischenschicht sollte dann zwischen Anzahl Eingabe- und Anzahl Ausgabeneuronen liegen, damit eine Reduktion vorgenommen wird. Hier ist aber Vorsicht geboten, da zu groß dimensionierte Schichten das Auswendiglernen begünstigen und damit die Generalisierung verhindern können.

Mfg NeuroCoder

W
webco Themenstarter:in
12 Beiträge seit 2010
vor 13 Jahren

Hallo NeuroCoder,
danke erstmal für die Information. Das mit dem Output habe ich verstanden, ich werde später die Outputs auf 26 hochsetzten, jetzt geht es mir aber erstmal nur darum A von B , zu unterscheiden, damit ich das Prinzip verstehe.
Den zweiten Teil deiner Antwort habe ich noch nicht ganz verstanden

Oftmals funktionieren neuronale Netze besser, wenn man binäre Aktivierungen ({0, 1} oder {-1, 1} als Wertebereich der Neuronen) nimmt.
Das heißt, es könnte helfen, wenn du dein Bild nach Graustufen konvertierst und auf eines der beiden Intervalle normierst.

Warum sollte es bringen das Bild zu Graustufen konvertieren, wenn es schwarz-weiss ist? Dann würden doch immer noch gleiche Werte rauskommen, einer für weiss und einer für schwarz...?

Sry bin totaler Anfänger in dem Gebiet 😉

N
335 Beiträge seit 2006
vor 13 Jahren

Hallo webco,

wenn es sowieso schon Schwarz / Weiß ist, sind die Graustufen natürlich nicht nötig. Da habe ich geschlafen, sorry.


inputB[index] = (B.GetPixel(x, y).B * A.GetPixel(x, y).B * B.GetPixel(x, y).G == 255 * 255 * 255) ? 0.0 : 1.0;

Das A in A.GetPixel(x, y).B sollte sicher ein B sein. Überhaupt frage ich mich, warum du den Alpha-Kanal an der Stelle eingehen lässt und nicht den Rot-Kanal?

Die Überprüfung lässt sich bestimmt auch noch weiter vereinfachen. Wenn du immer nur Schwarz / Weiss hast, genügt auch:

inputB[index] = (B.GetPixel(x, y).B > 0 ? 0.0 : 1.0;

Du kannst dir zur Sicherheit die Werte in den beiden Arrays im Debugger mal anschauen, oder auf die Konsole ausgeben lassen.

Mfg NeuroCoder

Hinweis von herbivore vor 13 Jahren

@webco:

Sry bin totaler Anfänger in dem Gebiet

das ist keine Schande, zumindest solange du dich selber um eine Lösung bemühst. Einfach irgendwelchen halbherzigen Code hin zu klatschen und uns dann solange Fehler rauspuzzeln zu lassen, bis er läuft, ist nicht. Siehe [Hinweis] Wie poste ich richtig? Punkt 4a. Konkrete Fragen kannst du aber natürlich stellen.

P
10 Beiträge seit 2011
vor 13 Jahren

Hi,

noch einen Tipp. Dein Code beschränkt das Training des Netzes auf 5000 Iterationen. Woher weißt du, ob das ausreichend ist?

Besser ist es den Rückgabewert der "RunEpoch" Funktion auszuwerten. Dieser gibt den Fehler dh. bei Backpropagation die Differenz zwischen der gewünschten und der derzeitigen Ausgabe des Netzwerk dividiert durch 2 an.

Aber das alles ist in der Dokumentation zu AForge.NET sehr gut beschrieben inkl. Beispielen.

Mfg.

A
118 Beiträge seit 2009
vor 13 Jahren

Wieviele du brauchst, kann man nicht genau sagen. Das muss man häufig ausprobieren oder schätzen.

Um Herauszufinden wieviele Hidden-Layer man braucht verwendet man auch genetische Algorithmen.

Gruss Aratar