0

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

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 

Sudden Bad Result "Good" Result

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

+0

Использование t^n для высших и высших степеней не является хорошей функцией _global_ для функции, поэтому я ожидаю, что метод будет разрушаться при попытке использовать многочлены более высокого порядка. – stephematician

+0

Я бы использовал другую основу для вашего приблизительного ответа, если вы хотите использовать многочлен, многочлены чебышева были бы хорошим началом. – stephematician

+0

Полиномы высокого порядка очень трудно справиться: они качаются вокруг. Я уже нервничаю, когда вижу «x^4». Начните с гораздо более ограничительной модели и, если возможно, используйте хорошую отправную точку и примените хорошие оценки параметров, которые вы хотите оценить (вам нужен решатель, который обрабатывает ограничения для этого). –

ответ

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 может быть лучше, чем случайная. Если ничто другое не обеспечит лучшую воспроизводимость от обучения к обучению.

+0

Добавление регуляризации, безусловно, помогло. Но в некоторых случаях все еще не удается. Я включил выходной флаг и вывел его. Всякий раз, когда я получаю результаты, у него есть код выхода 1 (величина градиента меньше допуска) и выполняется только 2/3 итераций. Я думаю, что это может показаться чем-то. – user3047023

+0

Регулярные выборки и полиномы более высокого порядка не играют очень хорошо - хотя регуляризация может помочь, избегая системы с плохой системой кондиционирования. Интерполяция может быть другой проблемой для того, что вы пытаетесь, и она демонстрирует часть проблемы: https://en.wikipedia.org/wiki/Lagrange_polynomial. Я бы рекомендовал использовать другую процедуру выборки (т. Е. Быть более осторожным в том, где вы пытаетесь сопоставить функцию) или использовать другой набор базовых функций. – stephematician