Оптимизация параметров FIS с перекрестной валидацией k-Fold

Этот пример показывает, как оптимизировать параметры системы нечеткого вывода (FIS) с помощью перекрестной валидации k-fold. Этот пример использует оптимизацию оптимизации генетического алгоритма (GA).

Избыточная комплектация данных при настройке параметров FIS

Сверхподбор кривой данных является распространенной проблемой при оптимизации параметров управления FIS. Когда сверхподбор кривой происходит, настроенный FIS производит оптимизированные результаты для обучающих данных набора, но плохо работает для тестовых данных набора. Из-за перестройки оптимизированные значения параметров FIS улавливают шум из обучающих данных набора и теряют способность обобщаться на новые наборы данных. Различие между обучающей и тестовой эффективностью увеличений с увеличением смещения обучающего набора данных.

Чтобы преодолеть проблему избыточного набора данных, можно остановить процесс настройки раньше на основе объективной оценки модели с помощью отдельного набора данных валидации. Однако такой набор данных валидации может также увеличить смещение, если он не точно представляет пространство задач. Чтобы преодолеть смещение из набора данных валидации, обычно используется подход перекрестной валидации k-fold. Здесь обучающие данные случайным образом перетасовываются и затем делятся на k разделы, как показано на следующем рисунке. Для каждой итерации проверки обучения вы используете другой раздел для валидации и используете оставшиеся данные для тестирования. Поэтому каждый раздел данных используется один раз для валидации и k-1 время для обучения.

Каждая итерация проверки обучения выполняется для n циклы. Однако итерация может остановиться раньше и перейти к следующей итерации, если увеличение стоимости валидации превысит предопределенное пороговое значение. Оптимизированная модель в конце kth итерация используется в качестве выхода процесса перекрестной валидации k-fold.

В этом примере показано, как использовать перекрестную валидацию k-fold с tunefis функция препятствует сверхподбору кривой данных по сравнению с настройкой параметра, которая не использует перекрестную валидацию k-fold.

Настройка FIS без валидации типа K-Fold

Этот пример описывает задачу избыточной подгонки данных для предсказания потребления топлива в автомобиле. Он использует несколько атрибутов профиля автомобиля, чтобы предсказать расход топлива. Обучающие данные доступны в Калифорнийском университете в Irvine Machine Learning Repository и содержат данные, собранные с автомобилей различных марок и моделей.

Этот пример использует следующие шесть атрибутов входных данных для предсказания атрибута выходных данных MPG с FIS.

  • Количество цилиндров

  • Смещение

  • Лошадиная сила

  • Вес

  • Ускорение

  • Модельный год

Загрузите данные с помощью loaddata Служебная функция, показанная в конце примера. Эта функция создает наборы обучающих и тестовых данных.

[data,varName,trnX,trnY,testX,testY] = loadData;

Создайте начальный FIS на основе атрибутов входных и выходных данных с помощью constructFIS Служебная функция.

fisin = constructFIS(data,varName);

Создайте набор опций для настройки FIS. Набор опций по умолчанию использует GA для оптимизации.

options = tunefisOptions;

Если у вас есть программное обеспечение Parallel Computing Toolbox™, можно улучшить скорость процесса настройки, установив options.UseParallel на true. Если у вас нет программного обеспечения Parallel Computing Toolbox, установите options.UseParallel на false.

Чтобы продемонстрировать проблему избыточного набора данных, этот пример использует максимум 100 генерацию для настройки правил.

options.MethodOptions.MaxGenerations = 100;

Настройте FIS, используя указанные данные настройки и опции. Настройка правил с помощью tunefis функция занимает несколько минут. Этот пример использует флаг, runtunefis, для запуска tunefis функция или загрузка предварительно обученных результатов. Чтобы загрузить предварительно обученные результаты, установите runtunefis на false.

runtunefis = false;

Чтобы продемонстрировать проблему избыточной комплектации данных, используйте следующие показатели эффективности:

  • Ошибка обучения - корневая средняя квадратичная невязка (RMSE) между ожидаемым выходом обучения и фактическим выходом обучения, полученным из настроенной FIS.

  • Ошибка тестирования - RMSE между ожидаемым тестовым выходом и фактическим тестовым выходом, полученным из настроенного FIS.

  • Количество функций - Общее количество вычислений функции затрат для настройки FIS.

В этом примере используйте только настройки параметров правила для настройки FIS.

Поскольку оптимизация GA использует случайный поиск, для получения воспроизводимых результатов инициализируйте генератор случайных чисел в его строение по умолчанию.

if runtunefis    
    % Get rule parameter settings.
    [~,~,rule] = getTunableSettings(fisin);
    
    % Set default random number generator.    
    rng('default')    

    % Tune rule parameters.
    [outputFIS,optimData] = tunefis(fisin,rule,trnX,trnY,options);

    % Get the training error.
    trnErrNoKFold = optimData.tuningOutputs.fval
    
    % Calculate the test error.
    evalOptions = evalfisOptions("EmptyOutputFuzzySetMessage","none", ...
        "NoRuleFiredMessage","none","OutOfRangeInputValueMessage","none");
    actY = evalfis(outputFIS,testX,evalOptions);
    del = actY - testY;
    testErrNoKFold = sqrt(mean(del.^2))
    
    % Get the function count.
    fcnCountNoKFold = optimData.totalFcnCount
    
    save tuningWithoutKFoldValidation trnErrNoKFold testErrNoKFold fcnCountNoKFold
else
    % Load the pretrained results.
    results = load('tuningWithoutKFoldValidation.mat');
    trnErrNoKFold = results.trnErrNoKFold
    testErrNoKFold = results.testErrNoKFold
    fcnCountNoKFold = results.fcnCountNoKFold
end
trnErrNoKFold = 2.4952
testErrNoKFold = 2.8412
fcnCountNoKFold = 19210

Более высокое значение тестовой ошибки по сравнению с ошибкой обучения указывает, что обученная FIS более смещена к обучающим данным.

Настройка параметров FIS с помощью K-образной валидации

Можно использовать перекрестную валидацию k-fold в оптимизации параметров управления FIS путем установки options.KFoldValue к значению, большему или равному 2. В данном примере установите значение k-складки равным 4.

options.KFoldValue = 4;

Чтобы задать значение допуска, используйте, чтобы остановить процесс настройки k-fold раньше, установите options.ValidationTolerance свойство. В данном примере установите значение допуска 0,02. Это значение допуска конфигурирует процесс настройки k-fold, чтобы остановить, если текущие затраты на валидацию увеличиваются более чем на 2% от минимальных затрат на валидацию, найденных до этого момента в процессе настройки.

options.ValidationTolerance = 0.02;

Для набора зашумленных данных можно вычислить скользящее среднее значение затрат на валидацию, установив options.ValidationWindowSize свойство к значению больше 1. В данном примере установите размер окна валидации равным 2.

options.ValidationWindowSize = 2;

Ограничьте максимальное количество поколений в каждом процессе настройки 25, чтобы общее количество поколений в 4-кратном процессе настройки было таким же, как и в предыдущем случае.

options.MethodOptions.MaxGenerations = 25;

Настройте FIS с помощью валидации типа k-fold.

if runtunefis    
    % Set default random number generator.
    rng('default')
    
    % Tune the FIS.
    [outputFIS,optimData] = tunefis(fisin,rule,trnX,trnY,options);
    
    % Get the training error.
    trnErrWithKFold = optimData.tuningOutputs(end).fval
    
    % Calculate the test error.
    actY = evalfis(outputFIS,testX,evalOptions);
    del = actY - testY;
    testErrWithKFold = sqrt(mean(del.^2))
    
    % Get the function count.
    fcnCountWithKFold = optimData.totalFcnCount
    
    save tuningWithKFoldValidation trnErrWithKFold testErrWithKFold fcnCountWithKFold
else
    % Load the pretrained results.
    results = load('tuningWithKFoldValidation.mat');
    trnErrWithKFold = results.trnErrWithKFold
    testErrWithKFold = results.testErrWithKFold
    fcnCountWithKFold = results.fcnCountWithKFold
end
trnErrWithKFold = 2.7600
testErrWithKFold = 2.9082
fcnCountWithKFold = 5590

Постройте график различий ошибок между тестами и обучением для обучения как с, так и без k-кратных случаев.

figure
cats = categorical({'Without k-fold','With k-fold'});
cats = reordercats(cats,{'Without k-fold','With k-fold'});
data = [trnErrNoKFold testErrNoKFold testErrNoKFold-trnErrNoKFold; ...
    trnErrWithKFold testErrWithKFold testErrWithKFold-trnErrWithKFold];
b = bar(cats,data);
ylabel('Root mean squared error (RMSE)')
text(b(3).XEndPoints,b(3).YEndPoints,string(b(3).YData),'HorizontalAlignment','center',...
    'VerticalAlignment','bottom')
legend('Training error','Test error','Test-to-training error difference', ...
    'Location','northoutside')

Figure contains an axes. The axes contains 5 objects of type bar, text. These objects represent Training error, Test error, Test-to-training error difference.

Тестовая эффективность ошибки аналогична в обоих случаях. Однако различие в ошибках обучения и тестирования с k-кратной валидацией меньше, чем без k-кратной валидации. Поэтому валидация типа k-fold уменьшает смещение обучающих данных и создает лучшие обобщенные значения параметров FIS. Общее количество функций во время валидации k-fold меньше, чем количество без валидации k-fold.

disp(table(fcnCountNoKFold,fcnCountWithKFold, ...
    'VariableNames',["Without k-fold" "With k-fold"], ...
    'RowName',"Function counts"))
                       Without k-fold    With k-fold
                       ______________    ___________

    Function counts        19210            5590    

Поэтому валидация типа k-fold уменьшает количество поколений в каждом цикле оптимизации GA, уменьшая сверхподбор кривой параметра FIS. Общие результаты k-кратной валидации могут быть дополнительно улучшены путем экспериментов с различными значениями k-кратного, допуска и размера окна.

В целом используйте следующий процесс для оптимизации параметров управления FIS с k-кратной валидацией:

  1. Начните с допуска валидации 0 и размера окна 1, которые обеспечивают минимальную эффективность в k-кратном порядке.

  2. Увеличьте значение k-кратного для достижения желаемой эффективности. В целом используйте k-кратное значение, меньше или равное 10.

  3. Увеличьте значение допуска, чтобы достичь желаемой эффективности.

  4. Увеличьте размер окна, чтобы достичь желаемой эффективности.

  5. При необходимости завершите шаги 3 и 4 в цикле.

Высокие значения допуска, размера окна и k-кратного значения вводят избыточную подгонку данных в оптимизированные значения параметров FIS. Поэтому используйте меньшие значения, чтобы достичь желаемой эффективности настройки.

Локальные функции

function [data,varName,trnX,trnY,testX,testY] = loadData

% Load the data. Each row of the dataset obtained from the repository represents 
% a different automobile profile. Data contains 7 columns, where the first six 
% columns contain the following input attributes.
%   - Number of cylinders
%   - Displacement
%   - Horsepower
%   - Weight
%   - Acceleration
%   - Model year
% The seventh column contains the output attribute, MPG.
[data,name] = loadGasData;

% Remove leading and trailing whitespace from the attribute names.
varName = strtrim(string(name));

% Create input and output data sets.
n = size(data,2);
x = data(:,1:n-1);
y = data(:,n);

% Create training and test data sets.
trnX = x(1:2:end,:);
trnY = y(1:2:end,:);
testX = x(2:2:end,:);
testY = y(2:2:end,:);

end

function fisin = constructFIS(data,varName)

% Create a Sugeno FIS.
fisin = sugfis;

% Add input and output variables to the FIS, where each variable represents
% one of the data attributes. For each variable, use the corresponding
% attribute name and range. To reduce the number of rules, use two MFs for
% each input variable, which results in 2^6=64 input MF combinations.
% Therefore, the FIS uses a maximum of 64 rules corresponding to the input
% MF combinations. Both input and output variables use default triangular
% MFs, which are uniformly distributed over the variable ranges.
dataRange = [min(data)' max(data)'];
numINputs = size(data,2)-1;
numInputMFs = 2;
numOutputMFs = numInputMFs^numINputs;
for i = 1:numINputs
    fisin = addInput(fisin,dataRange(i,:),'Name',varName(i),'NumMFs',numInputMFs);
end

% To improve data generalization, use 64 MFs for the output variable.
% Doing so allows the FIS to use a different output MF for each rule.
fisin = addOutput(fisin,dataRange(end,:),'Name',varName(end),'NumMFs',numOutputMFs);
fisin.Rules = repmat(fisrule,[1 numOutputMFs]);

end

См. также

|

Похожие темы