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
57
malkova_anastasia_lab_2/README.md
Normal 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
|
5
malkova_anastasia_lab_2/config.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
LASSO_TITLE = 'LASSO'
|
||||||
|
RFE_TITLE = 'RFE'
|
||||||
|
F_REGRESSION_TITLE = 'f_regression'
|
||||||
|
|
||||||
|
FEATURES_AMOUNT = 14
|
14
malkova_anastasia_lab_2/dataset.py
Normal 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
|
BIN
malkova_anastasia_lab_2/exp_1.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
malkova_anastasia_lab_2/exp_2.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
malkova_anastasia_lab_2/exp_3.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
malkova_anastasia_lab_2/exp_4.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
malkova_anastasia_lab_2/exp_console_1.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
malkova_anastasia_lab_2/exp_console_2.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
malkova_anastasia_lab_2/exp_console_3.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
malkova_anastasia_lab_2/exp_console_4.png
Normal file
After Width: | Height: | Size: 33 KiB |
15
malkova_anastasia_lab_2/fit.py
Normal 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
|
13
malkova_anastasia_lab_2/main.py
Normal 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)
|
42
malkova_anastasia_lab_2/ranks.py
Normal 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)
|