Merge pull request 'gordeeva_anna_lab_2' (#42) from gordeeva_anna_lab_2 into main

Reviewed-on: http://student.git.athene.tech/Alexey/IIS_2023_1/pulls/42
This commit is contained in:
Alexey 2023-10-17 17:25:29 +04:00
commit 41e0e8598f
5 changed files with 153 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -0,0 +1,97 @@
import streamlit as st
import numpy as np
from sklearn.linear_model import Lasso
from sklearn.preprocessing import MinMaxScaler
from sklearn.linear_model import LassoCV
from sklearn.feature_selection import SelectFromModel
from sklearn.feature_selection import RFE
st.header("Лабораторная работа 2. Вариант 7. Лассо, случайное лассо, рекурсивное сокращение признаков")
# генерируем исходные данные: 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)] # Список имен признаков
def random_lasso(X, Y, n_subsets=100):
n_samples, n_features = X.shape
selected_features = np.zeros(n_features)
for _ in range(n_subsets):
# Создаем случайное подмножество признаков
subset_indices = np.random.choice(n_features, int(n_features * 0.7), replace=False)
X_subset = X[:, subset_indices]
# Создаем LassoCV модель
lasso_cv = LassoCV(alphas=[0.05])
# Обучаем модель на подмножестве признаков
lasso_cv.fit(X_subset, Y)
# Определяем, какие признаки были выбраны
selected_features[subset_indices] += (lasso_cv.coef_ != 0)
# Вычисляем, какие признаки были выбраны чаще всего
most_selected_features = np.where(selected_features > n_subsets / 2)[0]
return most_selected_features
def rank_to_dict(ranks, name):
ranks = np.abs(ranks)
minmax = MinMaxScaler()
ranks = minmax.fit_transform(np.array(ranks).reshape(-1, 1)).ravel()
ranks = list(map(lambda x: round(x, 2), ranks))
ranked_features = list(zip(name, ranks))
return ranked_features
def mean_rank(ranks):
total = sum(rank for _, rank in ranks)
return total / len(ranks)
# Переключатели
lasso_check = st.checkbox("Лассо")
random_lasso_check = st.checkbox("Случайное лассо")
RFE_check = st.checkbox("Рекурсивное сокращение признаков")
# Результаты
if lasso_check:
model_lasso = Lasso(alpha=.05)
model_lasso.fit(X, Y)
rank = rank_to_dict(model_lasso.coef_, names)
mean = mean_rank(rank)
st.write("Получившиеся оценки для каждого признака")
st.table(rank)
st.write("Средняя оценка: ", mean)
if random_lasso_check:
selected_features = random_lasso(X, Y)
X_subset = X[:, selected_features]
lasso_cv = LassoCV(alphas=[0.05])
lasso_cv.fit(X_subset, Y)
rank = rank_to_dict(lasso_cv.coef_, [names[i] for i in selected_features])
mean = mean_rank(rank)
st.write("Получившиеся оценки")
st.table(rank)
st.write("Средняя оценка: ", mean)
if RFE_check:
model_lasso = Lasso(alpha=0.05)
rfe = RFE(model_lasso, n_features_to_select=4)
rfe.fit(X, Y)
selected_feature_indices = rfe.support_
selected_feature_names = [name for i, name in enumerate(names) if selected_feature_indices[i]]
rank = rank_to_dict(rfe.ranking_, selected_feature_names)
mean = mean_rank(rank)
st.write("Получившиеся оценки")
st.table(rank)
st.write("Средняя оценка: ", mean)

View File

@ -0,0 +1,56 @@
## Задание
Модели:
* Лассо (Lasso)
* Случайное лассо (RandomizedLasso)
* Рекурсивное сокращение признаков (Recursive Feature Elimination RFE)
## В чем различие каждой модели
Лассо (Lasso) автоматически отбирает наиболее важные признаки и уменьшает влияние менее важных.
Случайное лассо (RandomizedLasso) случайным образом выбирает подмножества признаков из исходных данных и применяет Лассо к каждому из них. Затем он объединяет результаты и определяет, какие признаки были выбраны чаще всего.
Рекурсивное сокращение признаков (Recursive Feature Elimination RFE) оценивает важность каждого признака. Затем он удаляет наименее важный признак и повторяет процесс, пока не останется желаемое количество признаков.
## Библиотеки
Streamlit. Предоставляет простой способ создания веб-приложений для визуализации данных.
Numpy. Предоставляет возможность работать с массивами и матрицами.
Sklearn. Предоставляет инструменты и алгоритмы, которые упрощают задачи, связанные с машинным обучением.
## Функционал
* Генерация исходных данных из 750 строк-наблюдений и 14 столбцов-признаков
* Создание и обучение таких моделей, как лассо, случайное лассо и рекурсивное сокращение признаков.
* Вывод получившихся оценок для признаков и средней оценки.
## Запуск
Перед запуском необходимо запустить виртуальную среду venv. Так как я использую streamlit, то для запуска необходимо в терминал прописать следующую строку:
```
streamlit run lab1.py
```
Приложение развернется на локальном сервере и автоматически откроется в браузере.
## Скриншоты работы программы
Лассо (Lasso)
![Alt text](Lasso_screen.png "Optional Title")
Случайное лассо (RandomizedLasso)
![Alt text](RandLasso_screen.png "Optional Title")
Рекурсивное сокращение признаков (Recursive Feature Elimination RFE)
![Alt text](RFE_screen.png "Optional Title")
## Вывод
Модель лассо выводит все 14 признаков, наиболее важными признаками оказались под индексом
1, 2, 4 и 5. Самый важный признак под номером 4. Средняя оценка по всем признакам 0.19.
Модель случайное лассо выводит наиболее важные признаки, такими признаками являются 1, 2, 4 и 5. Средняя оценка же по этим признакам равна 0.53. Она выше, так как мы исключаем маловажные признаки.
Модель рекурсивного сокращения признаков выводит 4 признака, так как я указала именно вывод 4 признаков в коде программы. Таким образом, модель отсекает маловажные признаки. Самым важным признаком оказался под номером 4. Средняя оценка: 0.25.
Как итог, можно сказать, что наиболее важными признаками являются 1, 2, 4 и 5. А самым важным из них является признак под номером 4.