Self organising map classifying everything to one coordinate

AI Thread Summary
The discussion revolves around issues encountered while implementing a Self-Organizing Map (SOM) based on instructions from the ai-junkie website. The primary concern is that the SOM classifies all input vectors to a single coordinate, specifically (4,5), regardless of the input data. The user suspects that the problem lies within the training loop, which was not clearly explained on the reference site. The code provided shows the structure of the SOM, including the training process and weight updates for nodes. Key functions include the calculation of the best matching unit (BMU) and the update of weights based on the neighborhood radius and learning factor. The user seeks assistance in diagnosing and resolving the classification issue, indicating a potential flaw in the training logic or weight adjustment mechanisms.
NotASmurf
Messages
150
Reaction score
2
Hey all,just coded this SOM based on the explination on the ai-junkie website, it seems to place all the input vectors in one single common coordinate, what am I doing wrong? I suspect its the training loop as that was the one part that the site was unclear about, Any help appreciated.

Code:
  static void Main(string[] args)
        {
            SOM som = new SOM(3, 5, 2, 0.1, new double[][] { new double[] {0,0,0 }, new double[] {0,0,0 } },0.00000001);
            List<string> lines = new List<string>();
            lines = System.IO.File.ReadAllLines("C:/Food.txt").ToList();
            som.training_data = new double[lines.Count][];
           
            for (int i = 0; i < som.training_data.Length; i++)
            {
                string[] h = lines[i].Split(',');
                som.training_data[i] = new double[h.Length-1];
                for (int j = 1; j < h.Length; j++)
                {
                    som.training_data[i][j - 1] = Convert.ToSingle(h[j]);
                }
            }

            som.Train();
            for (int i = 0; i < som.training_data.Length; i++)
            {
                var best = som.Classify(som.training_data[i]);
                Console.WriteLine(lines[i].Split(',')[0]+" "+best[0]+" "+best[1]);
            }
            Console.ReadLine();
           
        }
    }
    public class MathUtil
    {
        public static double Exp(double map_rad, double t, double lambda)
        {
            return map_rad * Math.Exp(-1 * (t / lambda));
        }
        public static double ExpLearn(double t, double lambda)
        {
            return Math.Exp(-1 * (t / lambda));
        }
        public static double Gaussian(int iteration, double distance, double neigh)
        {
            return Math.Exp(-1 * ((distance * distance) / 2 * neigh * neigh));
        }
    }
    public class Node
    {
        public double[] vec;
        public double error;
        Random r = new Random();
        public Node(int dim)
        {
            vec = new double[dim];
            for (int i = 0; i < dim; i++)
            {
                vec[i] = r.NextDouble();
            }
        }
        public double Distance(double[] vec)
        {
            double sum = 0;
            for (int i = 0; i < vec.Length; i++)
            {
                sum += Math.Pow(this.vec[i] - vec[i], 2);
            }
            return Math.Sqrt(sum);
        }
        public static double Distance(double[] vec,double[] vec2)
        {
            double sum = 0;
            for (int i = 0; i < vec.Length; i++)
            {
                sum += Math.Pow(vec[i] - vec2[i], 2);
            }
            return Math.Sqrt(sum);
        }
        public double UpdateWeight(double[] inp_vec, double learn, int iteration, double neigh)
        {
            double sum = 0;
            for (int i = 0; i < inp_vec.Length; i++)
            {
                double delta = learn * MathUtil.Gaussian(iteration, Distance(inp_vec), neigh) * (vec[i] - inp_vec[i]);
                vec[i] = vec[i] + delta;
                sum += delta;
            }
            error = sum / vec.Length;
            return sum / vec.Length;
        }

        public bool InRad(double radius, int[] pos_win, int[] pos_me)
        {
            double square_sum = 0;
            for (int i = 0; i < pos_me.Length; i++)
            {
                square_sum += Math.Pow(pos_me[i] - pos_win[i], 2);
            }
            if (Math.Sqrt(square_sum) < radius)
            {
                return true;
            }
            return false;
        }
    }

    public class SOM
    {
        public Node[,] nodes;
        public double width;
        public Random r = new Random();
        public double[][] training_data;
        public double height;
        public double Max_Error;
        public double learn_t0;

        public int[] Classify(double[] vec)
        {
            int[] best = new int[2];
            best = GetBMU(vec);
            return best;
        }
        public double GetError()
        {
            double error = 0;
            for (int i = 0; i < nodes.GetLength(0); i++)
            {
                for (int j = 0; j < nodes.GetLength(1); j++)
                {
                    error += nodes[i, j].error;
                }
            }
            return error;
        }
        public double neighboorhood_radius(int iteration)
        {
            return MathUtil.Exp(Map_Radius_t0, iteration, lambda(iteration));
        }
        public double LearnFac(int iteration)
        {
            return learn_t0 * MathUtil.ExpLearn(iteration, lambda(iteration));
        }
        public double lambda(int iteration)
        {
            return iteration / Math.Log(Map_Radius_t0);
        }
        public double Map_Radius_t0
        {
            get
            {
                return Math.Max(width, height) / 2;
            }
        }

        public int[] GetBMU(double[] ran_tr_vec)
        {
            int[] best = new int[2];
            double smallest = double.MaxValue;
            for (int i = 0; i < nodes.GetLength(0); i++)
            {
                for (int j = 0; j < nodes.GetLength(1); j++)
                {
                    if (Node.Distance(nodes[i, j].vec, ran_tr_vec) < smallest)
                    {
                        best[0] = i;
                        best[1] = j;
                    }
                }
            }
            return best;
        }
        public void Train()
        {
            for (int u = 0; u < 10000; u++)//while(GetError()>Max_Error)//
            {
                for (int ind = 0; ind < training_data.Length; ind++)
                {
                    int iter = u;
                    var inp_vec = training_data[ind];//r.Next(0, training_data.Length)];
                    int[] best = GetBMU(inp_vec);
                    #region Update_Weights
                    for (int i = 0; i < nodes.GetLength(0); i++)
                    {
                        for (int j = 0; j < nodes.GetLength(1); j++)
                        {
                            if (nodes[i, j].InRad(neighboorhood_radius(iter), best, new int[] { i, j }))
                            {
                                nodes[i, j].UpdateWeight(inp_vec, LearnFac(iter), iter, neighboorhood_radius(iter));
                            }
                        }
                    }
                    #endregion
                }
                Console.WriteLine(GetError());
            }
        }
        public SOM(int dim, int len, int bredth, double learn, double[][] tr_data, double Max_Error)
        {
            #region ini
            training_data = tr_data;
            learn_t0 = learn;
            width = bredth;
            height = len;
            this.Max_Error = Max_Error;
            nodes = new Node[len, bredth];
            for (int i = 0; i < nodes.GetLength(0); i++)
            {
                for (int j = 0; j < nodes.GetLength(1); j++)
                {
                    nodes[i, j] = new Node(dim);
                }
            }
            #endregion
          
        }
    }
}
 
Technology news on Phys.org
The exact glitch seems to be that it always classify things as the dimension vector - (1,1) if it has width 5 and length 6 it would classify everything as (4,5). Any ideas?
 
Dear Peeps I have posted a few questions about programing on this sectio of the PF forum. I want to ask you veterans how you folks learn program in assembly and about computer architecture for the x86 family. In addition to finish learning C, I am also reading the book From bits to Gates to C and Beyond. In the book, it uses the mini LC3 assembly language. I also have books on assembly programming and computer architecture. The few famous ones i have are Computer Organization and...
I have a quick questions. I am going through a book on C programming on my own. Afterwards, I plan to go through something call data structures and algorithms on my own also in C. I also need to learn C++, Matlab and for personal interest Haskell. For the two topic of data structures and algorithms, I understand there are standard ones across all programming languages. After learning it through C, what would be the biggest issue when trying to implement the same data...
Back
Top