MapUtils.java

  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. package org.apache.commons.math4.neuralnet;

  18. import java.util.List;

  19. import org.apache.commons.math4.neuralnet.internal.NeuralNetException;

  20. /**
  21.  * Utilities for network maps.
  22.  *
  23.  * @since 3.3
  24.  */
  25. public final class MapUtils {
  26.     /**
  27.      * Class contains only static methods.
  28.      */
  29.     private MapUtils() {}

  30.     /**
  31.      * Computes the quantization error.
  32.      * The quantization error is the average distance between a feature vector
  33.      * and its "best matching unit" (closest neuron).
  34.      *
  35.      * @param data Feature vectors.
  36.      * @param neurons List of neurons to scan.
  37.      * @param distance Distance function.
  38.      * @return the error.
  39.      * @throws IllegalArgumentException if {@code data} is empty.
  40.      */
  41.     public static double computeQuantizationError(Iterable<double[]> data,
  42.                                                   Iterable<Neuron> neurons,
  43.                                                   DistanceMeasure distance) {
  44.         final MapRanking rank = new MapRanking(neurons, distance);

  45.         double d = 0;
  46.         int count = 0;
  47.         for (final double[] f : data) {
  48.             ++count;
  49.             d += distance.applyAsDouble(f, rank.rank(f, 1).get(0).getFeatures());
  50.         }

  51.         if (count == 0) {
  52.             throw new NeuralNetException(NeuralNetException.NO_DATA);
  53.         }

  54.         return d / count;
  55.     }

  56.     /**
  57.      * Computes the topographic error.
  58.      * The topographic error is the proportion of data for which first and
  59.      * second best matching units are not adjacent in the map.
  60.      *
  61.      * @param data Feature vectors.
  62.      * @param net Network.
  63.      * @param distance Distance function.
  64.      * @return the error.
  65.      * @throws IllegalArgumentException if {@code data} is empty.
  66.      */
  67.     public static double computeTopographicError(Iterable<double[]> data,
  68.                                                  Network net,
  69.                                                  DistanceMeasure distance) {
  70.         final MapRanking rank = new MapRanking(net, distance);

  71.         int notAdjacentCount = 0;
  72.         int count = 0;
  73.         for (final double[] f : data) {
  74.             ++count;
  75.             final List<Neuron> p = rank.rank(f, 2);
  76.             if (!net.getNeighbours(p.get(0)).contains(p.get(1))) {
  77.                 // Increment count if first and second best matching units
  78.                 // are not neighbours.
  79.                 ++notAdjacentCount;
  80.             }
  81.         }

  82.         if (count == 0) {
  83.             throw new NeuralNetException(NeuralNetException.NO_DATA);
  84.         }

  85.         return ((double) notAdjacentCount) / count;
  86.     }
  87. }