Попытка определить степень полинома для полиномиальной регрессии

Вопрос или проблема

Я пытаюсь предсказать вес новорожденного, используя полиномиальную регрессионную модель. Сначала мне нужно понять, какая степень полинома лучше всего подходит для моих данных. Для этого я разделил свой набор данных на обучающую выборку (70%) и выборку перекрестной проверки (30%) и затем строю график ошибки по степени полинома. Я запускал свой скрипт 4 раза, случайным образом выбирая данные, но каждый раз получал столь различные кривые, как вы можете видеть

введите описание изображения здесь

Я не знаю, почему это происходит и что я делаю неправильно.

Вы можете увидеть мой код ниже:

главный скрипт

%========== Начало - объявление констант ==========% 
x_training_percent = 0.7;
cv_set_percent = 0.3;
%========== Конец - объявление констант ==========% 

load('data/dataset.m');
[m, n] = size(X);% m: количество примеров, n: количество признаков.

%========== Начало - получение обучающих и CV наборов ==========% 
training_set_size = round(m * x_training_percent);
cv_set_size = round(m * cv_set_percent);
test_set_size = round(m * test_set_percent);

random_order_idx = randperm(m);

indexes = random_order_idx(1:training_set_size);
random_order_idx(1:training_set_size) = []; % Удаление использованных индексов
x_training_o = X(indexes, :); % Оригинальный обучающий набор X
y_training = y(indexes, :);   % Оригинальный обучающий набор y

indexes = random_order_idx(1:cv_set_size);
random_order_idx(1:cv_set_size) = []; % Удаление использованных индексов
x_cv_o = X(indexes, :); % Оригинальный набор перекрестной проверки X
y_cv = y(indexes, :);   % Оригинальный набор перекрестной проверки y

%========== Конец - получение обучающих и CV наборов ==========% 

max_p = 10; % максимальная степень полинома

cv_error = zeros(max_p, 1);
training_error = zeros(max_p, 1);

for p = 1:max_p

  % Обработка обучающей выборки
  x_training = x_training_o;
  x_training = polyFeatures(x_training, p); % Добавление полиномиальных членов от 1 до p
  [x_training, mu, sigma] = featureNormalize(x_training);
  x_training = [ones(training_set_size, 1) x_training];

  % Обработка выборки перекрестной проверки
  x_cv = x_cv_o;
  x_cv = polyFeatures(x_cv, p); % Добавление полиномиальных членов от 1 до p
  x_cv = bsxfun(@minus, x_cv, mu);
  x_cv = bsxfun(@rdivide, x_cv, sigma);
  x_cv = [ones(cv_set_size, 1) x_cv];

  %========== Начало - Обучение ==========% 
  lambda = 0;
  theta = trainLinearReg(x_training, y_training, lambda);
  %========== Конец - Обучение ==========% 

  %========== Начало - Вычисление ошибок предсказания с полиномиальной степенью p ==========% 
    predictions = x_training * theta; % Предсказания с обучающей выборкой
    training_error(p, :) = (1 / (2 * training_set_size)) * sum((predictions - y_training) .^ 2);

    cv_predictions = x_cv * theta; % Предсказания с выборкой перекрестной проверки
    cv_error(p, :) = (1 / (2 * cv_set_size)) * sum((cv_predictions - y_cv) .^ 2);
  %========== Конец - Вычисление ошибок предсказания ==========% 

end

plot(1:p, training_error, 1:p, cv_error);

title(sprintf('Кривая обучения для линейной регрессии с lambda = %f', lambda));
legend('Обучение', 'Перекрестная проверка')
xlabel('степень полинома')
ylabel('Ошибка')

polyFeatures

function [X_poly] = polyFeatures(X, p)
%POLYFEATURES Отображает X (вектор 1D) в p-ю степень
%   [X_poly] = POLYFEATURES(X, p) принимает матрицу данных X (размер m x 1) и
%   отображает каждый пример в его полиномиальные признаки, где
%   X_poly(i, :) = [X(i) X(i).^2 X(i).^3 ...  X(i).^p];
%

X_poly = X; % Для p = 1

for i = 2:p
    X_poly = [X_poly (X .^ i)];
end

end

featureNormalize

function [X_norm, mu, sigma] = featureNormalize(X)
%FEATURENORMALIZE Нормализует признаки в X 
%   FEATURENORMALIZE(X) возвращает нормализованную версию X, где
%   среднее значение каждого признака равно 0, а стандартное отклонение
%   равно 1. Это часто является хорошим этапом предварительной обработки при
%   работе с алгоритмами обучения.

mu = mean(X);
X_norm = bsxfun(@minus, X, mu);

sigma = std(X_norm);
X_norm = bsxfun(@rdivide, X_norm, sigma);

end

trainingLinearReg

function [theta] = trainLinearReg(X, y, lambda)
%TRAINLINEARREG Обучает линейную регрессию, учитывая набор данных (X, y) и
%параметр регуляризации lambda
%   [theta] = TRAINLINEARREG (X, y, lambda) обучает линейную регрессию с использованием
%   набора данных (X, y) и параметра регуляризации lambda. Возвращает
%   обученные параметры theta.
%

% Инициализация Theta
initial_theta = zeros(size(X, 2), 1); 

% Создание "сокращенной записи" для функции стоимости, которую нужно минимизировать
costFunction = @(t) linearRegCostFunction(X, y, t, lambda);

% Теперь costFunction - это функция, которая принимает только один аргумент
options = optimset('MaxIter', 400, 'GradObj', 'on');

% Минимизация с использованием fmincg
theta = fmincg(costFunction, initial_theta, options);

end

linearRegCostFunction

function [J, grad] = linearRegCostFunction(X, y, theta, lambda)
%LINEARREGCOSTFUNCTION Вычисляет стоимость и градиент для регуляризированной линейной 
%регрессии с несколькими переменными
%   [J, grad] = LINEARREGCOSTFUNCTION(X, y, theta, lambda) вычисляет 
%   стоимость использования theta в качестве параметра для линейной регрессии для 
%   подгонки точек данных в X и y. Возвращает стоимость в J и градиент в grad

% Инициализация некоторых полезных значений
m = length(y); % количество обучающих примеров

% Необходимо правильно вернуть следующие переменные 
J = 0;
grad = zeros(size(theta));

hx = X * theta; % Предсказание

J = (1 / (2 * m)) * sum((hx - y) .^ 2) + (lambda / (2 * m)) * sum([ 0; theta(2:end, :) ] .^ 2);

grad = (1 / m) * (hx - y)' * X + (lambda / m) * [ 0; theta(2:end, :) ]';

grad = grad(:);

end

Может кто-нибудь помочь мне?

Вы, похоже, реализуете многие части этого процесса. Если вы переключитесь на установленные пакеты, вы сможете получить надежные результаты. Затем сравните надежные результаты с вашими, чтобы увидеть, есть ли у вас ошибка в реализации.

Ответ или решение

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

Вот несколько предложений и рекомендаций, которые помогут вам улучшить модель:

1. Увеличение количества повторений

Случайный выбор данных может привести к высокой вариации в полученных кривых ошибок из-за малой выборки (особенно если у вас мало данных). Рассмотрите возможность увеличения количества повторений (например, 10-кратная кросс-валидация), которая поможет вам получить более стабильные оценки ошибки.

2. Визуализация распределения мощности

Обратите внимание на визуализацию распределения мощности и ошибок для различных степеней полиномов. Иногда полезно визуально оценить, насколько ваш набор данных "гладкий" или "шумный". Если данные содержат много шумов, то использование сложных полиномов может привести к переобучению.

3. Регуляризация

Вы используете регуляризацию (параметр lambda в вашей функции trainLinearReg). Поиграйте с различными значениями lambda, особенно если вы используете высокие степени полиномов. Слишком высокое значение lambda может также привести к недообучению, в то время как слишком низкое значение может привести к переобучению.

4. Стандартизация/нормализация признаков

Убедитесь, что вы правильно нормализуете признаки как в обучающем, так и в валидационном наборах данных. Ваш код для нормализации выглядит корректным, но важно также убедиться, что вы используете одинаковые параметры (mu и sigma) для обеих выборок.

5. Параметры контроля

Убедитесь в использовании проверок на наличие поврежденных данных в вашем наборе данных, так как выбросы могут сильно повлиять на качество вашей модели. Это может объяснить некоторые неожиданности в вашем анализе.

6. Использование других методов

Далее, помимо полиномиальной регрессии, существует множество других методов, которые могут лучше захватывать структуру ваших данных, такие как Lasso, Ridge регрессия или методы бустинга.

7. Построение графиков

Для лучшего понимания используйте интерактивные графики, которые montrent ошибки обучения и валидации по различным степеням полинома. Это может помочь визуально оценить, где начинается переобучение и какое значение степени оптимально.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...