Merge pull request 'kochkareva_elizaveta_lab_2 is ready' (#194) from kochkareva_elizaveta_lab_2 into main
Reviewed-on: http://student.git.athene.tech/Alexey/IIS_2023_1/pulls/194
This commit is contained in:
commit
e64084bb6e
136
kochkareva_elizaveta_lab_2/README.md
Normal file
136
kochkareva_elizaveta_lab_2/README.md
Normal file
@ -0,0 +1,136 @@
|
||||
|
||||
# Лабораторная работа 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*, а также, что порядок значимости параметров может немного различаться в зависимости от модели.
|
88
kochkareva_elizaveta_lab_2/main.py
Normal file
88
kochkareva_elizaveta_lab_2/main.py
Normal file
@ -0,0 +1,88 @@
|
||||
from operator import itemgetter
|
||||
import numpy as np
|
||||
from sklearn.feature_selection import RFE, f_regression
|
||||
from sklearn.preprocessing import MinMaxScaler
|
||||
from sklearn.linear_model import Ridge
|
||||
from sklearn.linear_model import LinearRegression
|
||||
|
||||
# генерируем исходные данные: 750 строк-наблюдений и 14 столбцов-признаков
|
||||
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()
|
||||
|
||||
|
||||
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))
|
||||
|
||||
|
||||
# Модель: случайное Лассо (RandomizedLasso) - устаревшее, поэтому используем Ridge-регрессия (Ridge Regression)
|
||||
def ridge_regressions():
|
||||
# Создание экземпляра модели Ridge
|
||||
ridge_model = Ridge()
|
||||
ridge_model.fit(X, Y)
|
||||
ranks['Ridge'] = rank_to_dict(ridge_model.coef_, names)
|
||||
|
||||
|
||||
# Модель: рекурсивное сокращение признаков (Recursive Feature Elimination – 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)
|
||||
|
||||
|
||||
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)
|
||||
def linear_correlation():
|
||||
# вычисление линейной корреляции между X и y
|
||||
correlation, p_values = f_regression(X, Y)
|
||||
ranks['linear correlation'] = rank_to_dict(correlation, names)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ridge_regressions()
|
||||
recursive_feature_elimination()
|
||||
linear_correlation()
|
||||
|
||||
for key, value in ranks.items(): # Вывод нормализованных оценок важности признаков каждой модели
|
||||
ranks[key] = sorted(value.items(), key=itemgetter(1), reverse=True)
|
||||
for key, value in ranks.items():
|
||||
print(key)
|
||||
print(value)
|
||||
|
||||
mean = {} # - нахождение средних значений оценок важности по 3м моделям
|
||||
for key, value in ranks.items():
|
||||
for item in value:
|
||||
if item[0] not in mean:
|
||||
mean[item[0]] = 0
|
||||
mean[item[0]] += item[1]
|
||||
for key, value in mean.items():
|
||||
res = value / len(ranks)
|
||||
mean[key] = round(res, 2)
|
||||
mean = sorted(mean.items(), key=itemgetter(1), reverse=True)
|
||||
print("Mean")
|
||||
print(mean)
|
Loading…
Reference in New Issue
Block a user