[Octave]Использование fminunc не всегда дает последовательное решение

Я пытаюсь найти коэффициенты в уравнении для моделирования переходной характеристики двигателя, которая имеет форму 1-e^x. Уравнение, которое я использую для моделирования, имеет вид

a(1)*t^2 + a(2)*t^3 + a(3)*t^3 + ...

(Это получено в исследовательской статье, используемой для определения параметров двигателя)

Иногда использование fminunc для нахождения коэффициентов работает нормально, и я получаю хороший результат, и он достаточно хорошо соответствует обучающим данным. В других случаях возвращаемые коэффициенты ужасны (будут чрезвычайно выше, чем должен быть вывод, и на порядки). Это особенно происходит, когда я начал использовать термины более высокого порядка: использование любой модели, использующей x^8 или выше (x^9, x^10, x^11 и т. д.), всегда приводит к плохим результатам.

Поскольку иногда это работает, я не могу понять, почему моя реализация была бы неправильной. Я пробовал fminunc, предоставляя градиенты, а также не предоставляя градиенты, но разницы нет. Я рассматривал возможность использования других функций для расчета коэффициентов, таких как polyfit, но в этом случае у него должны быть члены, которые повышаются от 1 до члена высшего порядка, но модель, которую я использую, имеет наименьшую мощность при 2 .

Вот основной код:

clear;

%Overall Constants
max_power = 7;

%Loads in data
%data = load('TestData.txt');
load testdata.mat

%Sets data into variables
indep_x = data(:,1); Y = data(:,2);

%number of data points
m = length(Y);

%X is a matrix with the independant variable
exps = [2:max_power];
X_prime = repmat(indep_x, 1, max_power-1); %Repeats columns of the indep var
X = bsxfun(@power, X_prime, exps);

%Initializes theta to rand vals
init_theta = rand(max_power-1,1);

%Sets up options for fminunc
options = optimset( 'MaxIter', 400, 'Algorithm', 'quasi-newton');

%fminunc minimizes the output of the cost function by changing the theta paramaeters
[theta, cost] = fminunc(@(t)(costFunction(t, X, Y)), init_theta, options)

%
Y_line = X * theta;

figure;
hold on; plot(indep_x, Y, 'or');
hold on; plot(indep_x, Y_line, 'bx');

А вот и costFunction:

function [J, Grad] = costFunction (theta, X, Y)
   %# of training examples

   m = length(Y);

    %Initialize Cost and Grad-Vector
    J = 0;
    Grad = zeros(size(theta));

    %Poduces an output based off the current values of theta
    model_output = X * theta;

    %Computes the squared error for each example then adds them to get the total error
    squared_error = (model_output - Y).^2;
    J = (1/(2*m)) * sum(squared_error);

    %Computes the gradients for each theta t
    for t = 1:size(theta, 1)
        Grad(t) = (1/m) * sum((model_output-Y) .* X(:, t));
    end

endfunction

«Внезапно Хороший результат

Любая помощь или совет будут оценены.


person user3047023    schedule 23.10.2016    source источник
comment
Использование t^n во все более и более высоких степенях не является хорошей глобальной основой для функции, поэтому я ожидаю, что метод сломается, если вы попытаетесь использовать полиномы более высокого порядка.   -  person stephematician    schedule 23.10.2016
comment
Я бы использовал другую основу для вашего приблизительного ответа, если вы хотите использовать многочлен, полиномы Чебышева были бы хорошим началом.   -  person stephematician    schedule 23.10.2016
comment
С многочленами высокого порядка очень трудно иметь дело: они сильно колеблются. Я уже нервничаю, когда вижу x^4. Начните с гораздо более ограничительной модели и, если возможно, используйте хорошую отправную точку и примените хорошие границы для параметров, которые вы хотите оценить (для этого вам нужен решатель, который обрабатывает границы).   -  person Erwin Kalvelagen    schedule 24.10.2016


Ответы (1)


Попробуйте добавить регуляризацию в функцию costFunction:

function [J, Grad] = costFunction (theta, X, Y, lambda)
    m = length(Y);

    %Initialize Cost and Grad-Vector
    J = 0;
    Grad = zeros(size(theta));

    %Poduces an output based off the current values of theta
    model_output = X * theta;

    %Computes the squared error for each example then adds them to get the total error
    squared_error = (model_output - Y).^2;
    J = (1/(2*m)) * sum(squared_error);
    % Regularization
    J = J + lambda*sum(theta(2:end).^2)/(2*m);


    %Computes the gradients for each theta t
    regularizator = lambda*theta/m;
    % overwrite 1st element i.e the one corresponding to theta zero
    regularizator(1) = 0;
    for t = 1:size(theta, 1)
        Grad(t) = (1/m) * sum((model_output-Y) .* X(:, t)) + regularizator(t);
    end

endfunction

Термин регуляризации lambda используется для управления скоростью обучения. Начните с лямбда = 1. Чем больше значение лямбда, тем медленнее будет происходить обучение. Увеличьте лямбда, если описанное вами поведение сохраняется. Возможно, вам придется увеличить количество итераций, если лямбда становится высокой. Вы также можете рассмотреть возможность нормализации ваших данных и некоторую эвристику для инициализации тета - установка всех тета на 0,1 может быть лучше, чем случайная. По крайней мере, это обеспечит лучшую воспроизводимость от тренировки к тренировке.

person Iliyan Bobev    schedule 23.10.2016
comment
Добавление регуляризации, безусловно, помогло. Но все же в некоторых случаях это все еще терпит неудачу. Я включил выход и выход. Всякий раз, когда я получаю результаты, он имеет код выхода 1 (величина градиента меньше допуска) и выполняет только 2/3 итерации. Я думаю, это может быть показателем чего-то. - person user3047023; 24.10.2016
comment
Регулярная выборка и полиномы более высокого порядка не очень хорошо работают — хотя регуляризация может помочь, трудно избежать численно плохо обусловленной системы. Интерполяция может быть проблемой, отличной от того, что вы пытаетесь сделать, но она демонстрирует часть проблемы: en.wikipedia. org/wiki/многочлен_лагранжа. Я бы порекомендовал использовать другую процедуру выборки (то есть быть более осторожным в том, где вы пытаетесь сопоставить функцию) или использовать другой набор базовых функций. - person stephematician; 24.10.2016