Этот пример показывает, как оптимизировать параметры системы нечеткого вывода (FIS) с помощью перекрестной валидации k-fold. Этот пример использует оптимизацию оптимизации генетического алгоритма (GA).
Сверхподбор кривой данных является распространенной проблемой при оптимизации параметров управления FIS. Когда сверхподбор кривой происходит, настроенный FIS производит оптимизированные результаты для обучающих данных набора, но плохо работает для тестовых данных набора. Из-за перестройки оптимизированные значения параметров FIS улавливают шум из обучающих данных набора и теряют способность обобщаться на новые наборы данных. Различие между обучающей и тестовой эффективностью увеличений с увеличением смещения обучающего набора данных.
Чтобы преодолеть проблему избыточного набора данных, можно остановить процесс настройки раньше на основе объективной оценки модели с помощью отдельного набора данных валидации. Однако такой набор данных валидации может также увеличить смещение, если он не точно представляет пространство задач. Чтобы преодолеть смещение из набора данных валидации, обычно используется подход перекрестной валидации k-fold. Здесь обучающие данные случайным образом перетасовываются и затем делятся на разделы, как показано на следующем рисунке. Для каждой итерации проверки обучения вы используете другой раздел для валидации и используете оставшиеся данные для тестирования. Поэтому каждый раздел данных используется один раз для валидации и время для обучения.
Каждая итерация проверки обучения выполняется для циклы. Однако итерация может остановиться раньше и перейти к следующей итерации, если увеличение стоимости валидации превысит предопределенное пороговое значение. Оптимизированная модель в конце итерация используется в качестве выхода процесса перекрестной валидации k-fold.
В этом примере показано, как использовать перекрестную валидацию k-fold с tunefis
функция препятствует сверхподбору кривой данных по сравнению с настройкой параметра, которая не использует перекрестную валидацию 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 более смещена к обучающим данным.
Можно использовать перекрестную валидацию 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')
Тестовая эффективность ошибки аналогична в обоих случаях. Однако различие в ошибках обучения и тестирования с 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-кратной валидацией:
Начните с допуска валидации 0 и размера окна 1, которые обеспечивают минимальную эффективность в k-кратном порядке.
Увеличьте значение k-кратного для достижения желаемой эффективности. В целом используйте k-кратное значение, меньше или равное 10.
Увеличьте значение допуска, чтобы достичь желаемой эффективности.
Увеличьте размер окна, чтобы достичь желаемой эффективности.
При необходимости завершите шаги 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