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 }