IIS_2023_1/martysheva_tamara_lab_2/lab2.py

72 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from sklearn.linear_model import Lasso, LinearRegression
from sklearn.feature_selection import RFE, f_regression
from sklearn.preprocessing import MinMaxScaler
import numpy as np
import pandas as pd
from operator import itemgetter
#Генерируем исходные данные
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))
#Создаем и тренируем модели
lasso = Lasso(alpha=.05)
lasso.fit(X, Y)
#
lr = LinearRegression()
lr.fit(X, Y)
rfe = RFE(lr)
rfe.fit(X, Y)
#
f, pval = f_regression(X, Y, center=True)
# Функция для преобразования оценок признаков в словарь
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))
# Функция нахождения средних оценок по признакам
def average_ranks(ranks):
avg_ranks = {}
for key, value in ranks.items():
for item in value.items():
if (item[0] not in avg_ranks):
avg_ranks[item[0]] = 0
avg_ranks[item[0]] += item[1]
for key, value in avg_ranks.items():
res = value / len(ranks)
avg_ranks[key] = round(res, 2)
avg_ranks = sorted(avg_ranks.items(), key=itemgetter(1), reverse=True)
return avg_ranks
#Создаем список с именами признаков
names = ["x%s" % i for i in range(1, 15)]
ranks = dict()
#Применяем функцию к моделям
ranks["Lasso"] = rank_to_dict(lasso.coef_, names)
ranks["RFE"] = rank_to_dict(rfe.ranking_, names)
ranks["F_reg"] = rank_to_dict(f, names)
#Т.к. в RFE ранг "1" = признак важный, а если больше "1" - то менее важный
#поменяем оценки на противоположные
record_key = 'RFE'
for key, value in ranks[record_key].items():
ranks[record_key][key] = 1 - value
# Вывод оценок каждого признака
table_ranks = pd.DataFrame.from_dict(ranks, orient='columns')
print("Оценки важности признаков по моделям: Лассо, Рекурсивное сокращение признаков, Линейная корреляция:")
print(table_ranks)
# Вывод средних оценок каждого признака
table_avg_ranks = pd.DataFrame.from_records(average_ranks(ranks))
print("Средние оценки важности признаков")
print(table_avg_ranks.to_string(index=False, header=False))