Merge pull request 'malkova_anastasia_lab_2 ready' (#147) from malkova_anastasia_lab_2 into main

Reviewed-on: http://student.git.athene.tech/Alexey/IIS_2023_1/pulls/147
This commit is contained in:
Alexey 2023-12-05 23:02:56 +04:00
commit 131cb584dd
14 changed files with 146 additions and 0 deletions

View File

@ -0,0 +1,57 @@
# Лабораторная работа №2
> Ранжирование признаков
### Как запустить лабораторную работу
1. Установить python, numpy, sklearn
2. Запустить команду `python main.py` в корне проекта
### Использованные технологии
* Язык программирования `python`
* Библиотеки `numpy, sklearn`
* Среда разработки `PyCharm`
### Что делает программа?
Выполняет ранжирование 14 признаков для регрессионной проблемы Фридмана с помощью моделей:
- Лассо (Lasso)
- Рекурсивное сокращение признаков (Recursive Feature Elimination RFE)
- Линейная корреляция (f_regression)
Было проведено несколько экспериментов с разными параметрами моделей, чтобы оценить их влияние на итоговый результат:
#### Тест 1
![alt text](exp_1.png "Experiment 1")
![alt text](exp_console_1.png "Result 1")
#### Тест 2
![alt text](exp_2.png "Experiment 2")
![alt text](exp_console_2.png "Result 2")
#### Тест 3
![alt text](exp_3.png "Experiment 3")
![alt text](exp_console_3.png "Result 3")
#### Тест 4
![alt text](exp_4.png "Experiment 4")
![alt text](exp_console_4.png "Result 4")
Первые 2 эксперимента выявили, что признаки x4, x2, x1, x5 оказались самыми важными по среднему значению.
Другие 2 эксперимента выявили, что признаки x4, x2, x1, x11 оказались самыми важными по среднему значению.
Так как мы изначально знаем, что от признаков x1, x2, x3, x4 зависит наша функция и x11, x12, x13, x14 соответсвенно зависят от них, то лучшим исходом будут эти признаки.
Но ни один эксперимент не смог точно их выявить. Лучшими оказались эксперименты 3 и 4, так как в отличии от 1-го и 2-го они выявили ещё признак x11 вместо x5, который не влияет на нашу функцию вообще.
Из данных моделей лучше всего определила признаки модель Lasso с alpha=0.001

View File

@ -0,0 +1,5 @@
LASSO_TITLE = 'LASSO'
RFE_TITLE = 'RFE'
F_REGRESSION_TITLE = 'f_regression'
FEATURES_AMOUNT = 14

View File

@ -0,0 +1,14 @@
import config
import numpy as np
def generate_dataset():
np.random.seed(0)
size = 750
x = np.random.uniform(0, 1, (size, config.FEATURES_AMOUNT))
# Задаем функцию-выход: регрессионную проблему Фридмана
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))
return x, y

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -0,0 +1,15 @@
from sklearn.linear_model import Lasso
from sklearn.linear_model import LinearRegression
from sklearn.feature_selection import RFE, f_regression
def fit_models(x, y):
lasso = Lasso(alpha=0.001)
lasso.fit(x, y)
rfe = RFE(lasso, step=2)
rfe.fit(x, y)
f, val = f_regression(x, y, center=False)
return lasso, rfe, f

View File

@ -0,0 +1,13 @@
from dataset import generate_dataset
from fit import fit_models
from ranks import calc_mean, get_ranks
x, y = generate_dataset()
lasso, rfe, f = fit_models(x, y)
ranks = get_ranks(lasso, rfe, f)
mean = calc_mean(ranks)
print("MEAN", mean)

View File

@ -0,0 +1,42 @@
import config
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from operator import itemgetter
def rank_to_dict(ranks, names):
ranks = np.abs(ranks)
minmax = MinMaxScaler()
ranks = minmax.fit_transform(
np.array(ranks).reshape(config.FEATURES_AMOUNT, 1)).ravel()
ranks = map(lambda x: round(x, 2), ranks)
return dict(zip(names, ranks))
def flip_array(arr):
return-1 * arr + np.max(arr)
def get_ranks(lasso, rfe, f):
ranks = dict()
names = ["x%s" % i for i in range(1, config.FEATURES_AMOUNT+1)]
ranks[config.LASSO_TITLE] = rank_to_dict(lasso.coef_, names)
ranks[config.RFE_TITLE] = rank_to_dict(flip_array(rfe.ranking_), names)
ranks[config.F_REGRESSION_TITLE] = rank_to_dict(f, names)
return ranks
def calc_mean(ranks):
mean = {}
for key, value in ranks.items():
print(key, value)
for item in value.items():
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)
return sorted(mean.items(), key=itemgetter(1), reverse=True)