Translate

пятница, 5 декабря 2014 г.

Нормируем входные данные


Нормировка входных данных в нерокомпьютинге применяется давно. Основная её цель — это привести все разнородные (различные единицы измерений) входные сигналы к единому формату. Но если в отдельных случаях для обучения искусственного нейрона можно обойтись и без нормирования, то в случае VMR, этот фокус не пройдёт. Дело в том, что предварительное нормирование входных данных к диапазоно от -1 до 1 включительно является обязательной подготовкой к последующей инвариантности.

Формулы для нормирования в LibVMR линейные, т.к. нелинейность достигается с помощью ядерных преобразований. Сначала для каждой объясняющей переменной находим максимальное (max) и минимальное (min) значения, а потом уже взяв конкретное значение переменной, загоняем его в диапазон от -1 до 1 включительно:

v' = 2 * (v – min) / (max – min) – 1

где:

v' – нормированное значение ненормированной переменной v

Помимо самого нормирования входных данных нам ещё необходимо отделить значения объясняющих переменных и зависимой переменной, разнеся их по разным массивам.

Создадим код на Java:

package libvmr;

/**
 * Векторная машина Решетова
 * @author Yury V. Reshetov
 * @version 1.0
 */
public class VMR {
 
    /**
     * Максимумы столбцов обучающей выборки
     */
    private double[] maxs = null;
    /**
     * Минимумы столбцов обучающей выборки
     */
    private double[] mins = null;
    /**
     * Значения зависимых переменных
     */
    private double[] ideals = null;

 
    /**
     * Нормирование обучающей выборки
     * @param samples ненормированная обучающая выборка
     * @return Нормированная обучающая выборка
     */
    private double[][] normSetting(double[][] samples) {
        // Вытаскиваем последний столбец обучающей выборки - результаты
        this.ideals = new double[samples.length];
        for (int i = 0; i < samples.length; i++) {
            this.ideals[i] = this.convertToRange(samples[i][samples[0].length - 1], 1d, 0d);
        }
        double[][] normsamples = new double[samples.length][samples[0].length - 1];

        // Ищем максимумы и минимумы
        this.maxs = new double[normsamples[0].length];
        this.mins = new double[normsamples[0].length];
        for (int j = 0; j < normsamples[0].length; j++) {
            double max = samples[0][j];
            double min = max;
            for (int i = 1; i < normsamples.length; i++) {
                if (samples[i][j] > max) {
                    max = samples[i][j];
                }
                if (samples[i][j] < min) {
                    min = samples[i][j];
                }
            }
            this.maxs[j] = max;
            this.mins[j] = min;
        }
        // Нормализуем
        for (int i = 0; i < normsamples.length; i++) {
            for (int j = 0; j < normsamples[0].length; j++) {
                normsamples[i][j] = this.convertToRange(samples[i][j],this.maxs[j],this.mins[j]);
            }
        }
        return normsamples;
    }
    
    /**
     * Преобразование переменных из диапазона от минимального значения до максимального включительно к диапазону от -1 до 1 включительно
     * @param value значение переменной
     * @param maximmumvalue максимальное значение переменной
     * @param minimumvalue минимальное значение переменной
     * @return нормированное значение переменной в диапазоне от -1 до 1 включительно
     */
    private double convertToRange(double value, double maximmumvalue, double minimumvalue) {
        return 2d * (value - minimumvalue) / (maximmumvalue - minimumvalue) - 1d;
    }
 
}

Комментариев нет:

Отправить комментарий