View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math4.neuralnet;
19  
20  import java.util.List;
21  
22  import org.apache.commons.math4.neuralnet.internal.NeuralNetException;
23  
24  /**
25   * Utilities for network maps.
26   *
27   * @since 3.3
28   */
29  public final class MapUtils {
30      /**
31       * Class contains only static methods.
32       */
33      private MapUtils() {}
34  
35      /**
36       * Computes the quantization error.
37       * The quantization error is the average distance between a feature vector
38       * and its "best matching unit" (closest neuron).
39       *
40       * @param data Feature vectors.
41       * @param neurons List of neurons to scan.
42       * @param distance Distance function.
43       * @return the error.
44       * @throws IllegalArgumentException if {@code data} is empty.
45       */
46      public static double computeQuantizationError(Iterable<double[]> data,
47                                                    Iterable<Neuron> neurons,
48                                                    DistanceMeasure distance) {
49          final MapRanking rank = new MapRanking(neurons, distance);
50  
51          double d = 0;
52          int count = 0;
53          for (final double[] f : data) {
54              ++count;
55              d += distance.applyAsDouble(f, rank.rank(f, 1).get(0).getFeatures());
56          }
57  
58          if (count == 0) {
59              throw new NeuralNetException(NeuralNetException.NO_DATA);
60          }
61  
62          return d / count;
63      }
64  
65      /**
66       * Computes the topographic error.
67       * The topographic error is the proportion of data for which first and
68       * second best matching units are not adjacent in the map.
69       *
70       * @param data Feature vectors.
71       * @param net Network.
72       * @param distance Distance function.
73       * @return the error.
74       * @throws IllegalArgumentException if {@code data} is empty.
75       */
76      public static double computeTopographicError(Iterable<double[]> data,
77                                                   Network net,
78                                                   DistanceMeasure distance) {
79          final MapRanking rank = new MapRanking(net, distance);
80  
81          int notAdjacentCount = 0;
82          int count = 0;
83          for (final double[] f : data) {
84              ++count;
85              final List<Neuron> p = rank.rank(f, 2);
86              if (!net.getNeighbours(p.get(0)).contains(p.get(1))) {
87                  // Increment count if first and second best matching units
88                  // are not neighbours.
89                  ++notAdjacentCount;
90              }
91          }
92  
93          if (count == 0) {
94              throw new NeuralNetException(NeuralNetException.NO_DATA);
95          }
96  
97          return ((double) notAdjacentCount) / count;
98      }
99  }