IIS_2023_1/kochkareva_elizaveta_lab_2/README.md
2023-11-24 15:23:08 +04:00

12 KiB
Raw Blame History

Лабораторная работа 2. Вариант 15

Задание

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

3 модели:

  • Случайное Лассо (RandomizedLasso)
  • Рекурсивное сокращение признаков (Recursive Feature Elimination RFE)
  • Линейная корреляция (f_regression)

Как запустить лабораторную работу

Для запуска программы необходимо с помощью командной строки в корневой директории файлов прокета прописать:

python main.py

Какие технологии использовали

  • Библиотека numpy для работы с массивами.
  • Библиотека itemgetter для использования функции для выбора элементов из коллекции.
  • Библиотека sklearn:
    • LinearRegression для создания и работы с моделью Линейной регрессии.
    • Ridge для создания и работы с моделью линейной регрессии с регуляризацией
    • MinMaxScaler - для нормализации данных путем масштабирования значений признаков в диапазоне от 0 до 1.
    • RFE, f_regression - RFE используется для рекурсивного отбора признаков, а f_regression - для вычисления корреляции между каждым признаком и целевой переменной.

Описание лабораторной работы

Генерация данных

Создаем массив X размером (750, 14), где каждый элемент выбирается случайным образом из равномерного распределения на интервале от 0 до 1. Затем вычисляем массив Y, используя формулу, отрадающую зависимость значения Y от значений в массиве X и состоящую из случайного шума. Изменяем значения последних четырех столбцов массива X. Значения этих столбцов становятся суммой первых четырех столбцов и случайного шума. Создаем список names, который содержит названия признаков, и пустой словарь ranks, который будет использоваться для хранения значений важности признаков.

np.random.seed(0)
size = 750
X = np.random.uniform(0, 1, (size, 14))
# Задаем функцию-выход: регрессионную проблему Фридмана
Y = (10 * np.sin(np.pi*X[:, 0]*X[:, 1]) + 20*(X[:, 2] - .5)**2 + 10*X[:, 3] + 5*X[:, 4]**5 + np.random.normal(0, 1))
# Добавляем зависимость признаков
X[:, 10:] = X[:, :4] + np.random.normal(0, .025, (size, 4))
names = ["x%s" % i for i in range(1, 15)]  # - список признаков вида ['x1', 'x2', 'x3', ..., 'x14']
ranks = dict()

Обработка результатов

Создаем функцию rank_to_dict, которая принимает два аргумента: ranks (оценки важности признаков) и names (названия признаков). В данной функции создается словарь, используя zip для объединения названий признаков и округленных оценок важности признаков. Названия признаков становятся ключами словаря, а округленные оценки - значениями.

def rank_to_dict(ranks, names):
     # получение абсолютных значений оценок(модуля)
     ranks = np.abs(ranks)
     minmax = MinMaxScaler()
     # преобразование данных
     ranks = minmax.fit_transform(np.array(ranks).reshape(14, 1)).ravel()
     # округление элементов массива
     ranks = map(lambda x: round(x, 2), ranks)
     # преобразование данных
     return dict(zip(names, ranks))

Модель Ridge

Так как по заданию необходимо работать с устаревшей моделью случайное Лассо (RandomizedLasso), воспользуемся Ridge-регрессией (Ridge Regression). Создадим экземпляр модели Ridge, которая используется для выполнения регрессии с использованием линейной комбинации признаков, которая применяет регуляризацию L2 для уменьшения влияния мультиколлинеарности в данных. Обучаем модель Ridge с использованием метода .fit(X, Y). Здесь X представляет собой матрицу признаков (независимые переменные), а Y - вектор целевой переменной (зависимая переменная). Модель обучается на этих данных, чтобы найти оптимальные значения коэффициентов регрессии. Далее отправляем полученные коэффициенты в метод rank_to_dict для обрезования данных в необходимый вид.

ridge_model = Ridge()
ridge_model.fit(X, Y)
ranks['Ridge'] = rank_to_dict(ridge_model.coef_, names)

Модель рекурсивное сокращение признаков (Recursive Feature Elimination RFE)

Для работы с моделью рекурсивного сокрщения признаков создадим две функции: recursive_feature_elimination() и rank_to_dict_rfe(ranking, names).

В функции recursive_feature_elimination() создаем экземпляр модели LinearRegression под именем estimator. Далее создаем экземпляр модели RFE (Recursive Feature Elimination) под именем rfe_model, передавая estimator в качестве аргумента конструктора. Обучаем rfe_model на данных X и Y. Затем добавляем ранги признаков, полученные от rfe_model, в словарь ranks под ключом 'Recursive Feature Elimination', используя функцию rank_to_dict_rfe().

def recursive_feature_elimination():
    # создание модели LinearRegression
    estimator = LinearRegression()
    # создание модели RFE
    rfe_model = RFE(estimator)
    rfe_model.fit(X, Y)
    ranks['Recursive Feature Elimination'] = rank_to_dict_rfe(rfe_model.ranking_, names)

В функции rank_to_dict_rfe(ranking, names) находит обратные значения рангов признаков, делим 1 на каждый ранг. Округляем элементы полученного массива до двух знаков после запятой, используя функцию round(). И возвращаем словарь, где имена признаков из names являются ключами, а значениями являются округленные обратные значения рангов.

def rank_to_dict_rfe(ranking, names):
    # нахождение обратных значений рангов
    n_ranks = [float(1 / i) for i in ranking]
    # округление элементов массива
    n_ranks = map(lambda x: round(x, 2), n_ranks)
    # преобразование данных
    return dict(zip(names, n_ranks))

Линейная корреляция (f_regression)

Для работы с линейной корреляцией выполним линейную корреляцию между признаками в матрице X и целевой переменной Y. Для этого используем функцию f_regression() для выполнения линейной регрессии между каждым признаком в матрице X и целевой переменной Y. После этого возвращается два массива: correlation содержит значения коэффициентов корреляции между признаками и Y, а p_values содержит соответствующие p-значения для каждого коэффициента корреляции. После чего создаем новую запись в словаре ranks с ключом 'linear correlation'.

correlation, p_values = f_regression(X, Y)
ranks['linear correlation'] = rank_to_dict(correlation, names)

Вывод

Согласно условию задания значимыми параметрами были: x1, x2, x3, x4, x5. А зависимыми от них x10, x11, x12, x13, x14.

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

Ridge
[('x4', 1.0), ('x1', 0.98), ('x2', 0.8), ('x14', 0.61), ('x5', 0.54), ('x12', 0.39), ('x3', 0.25), ('x13', 0.19), ('x11', 0.16), ('x6', 0.08), ('x8', 0.07), ('x7', 0.02), ('x10', 0.02), ('x9', 0.0)]
Recursive Feature Elimination
[('x1', 1.0), ('x2', 1.0), ('x3', 1.0), ('x4', 1.0), ('x5', 1.0), ('x11', 1.0), ('x13', 1.0), ('x12', 0.5), ('x14', 0.33), ('x8', 0.25), ('x6', 0.2), ('x10', 0.17), ('x7', 0.14), ('x9', 0.12)]
linear correlation
[('x4', 1.0), ('x14', 0.98), ('x2', 0.45), ('x12', 0.44), ('x1', 0.3), ('x11', 0.29), ('x5', 0.04), ('x8', 0.02), ('x7', 0.01), ('x9', 0.01), ('x3', 0.0), ('x6', 0.0), ('x10', 0.0), ('x13', 0.0)]

Как можно заметить в модели Ridge параметры x1, x2, x4, x5 имеют наибольшую значимость, что соответстует исходному условию задания, однако был потерян признак x3, значимость которого была показана низкой.

Модель Recursive Feature Elimination правильно показала все наиболее значиме признаки x1, x2, x3, x4, x5.

В модели линейной корреляции параметры 'x4' и 'x14' имеют наибольшую корреляцию, равную 1.0. Параметры 'x3', 'x6', 'x10' и 'x13' имеют наименьшую корреляцию, равную 0.0. Таким образом, показав наихудний результат среди трех моделей.

В среднем по работе трех моделей имеем следующий результат, где параметр 'x4' имеет наибольшую значимость, равную 1.0, параметр 'x9' имеет наименьшую значимость, равную 0.04.:

Mean
[('x4', 1.0), ('x1', 0.76), ('x2', 0.75), ('x14', 0.64), ('x5', 0.53), ('x11', 0.48), ('x12', 0.44), ('x3', 0.42), ('x13', 0.4), ('x8', 0.11), ('x6', 0.09), ('x7', 0.06), ('x10', 0.06), ('x9', 0.04)]

Таким образом, можно сделать вывод о том, лучше всех справилась модель Recursive Feature Elimination, а также, что порядок значимости параметров может немного различаться в зависимости от модели.