136 lines
12 KiB
Markdown
136 lines
12 KiB
Markdown
|
|
|||
|
# Лабораторная работа 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, который будет использоваться для хранения значений важности признаков.
|
|||
|
|
|||
|
```python
|
|||
|
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` для объединения названий признаков и округленных оценок важности признаков. Названия признаков становятся ключами словаря, а округленные оценки - значениями.
|
|||
|
|
|||
|
```python
|
|||
|
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` для обрезования данных в необходимый вид.
|
|||
|
|
|||
|
```python
|
|||
|
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()`.
|
|||
|
|
|||
|
```python
|
|||
|
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` являются ключами, а значениями являются округленные обратные значения рангов.
|
|||
|
```python
|
|||
|
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'*.
|
|||
|
|
|||
|
```python
|
|||
|
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*, а также, что порядок значимости параметров может немного различаться в зависимости от модели.
|