Merge pull request 'zhukova_alina_lab_4 is ready' (#159) from zhukova_alina_lab_4 into main

Reviewed-on: http://student.git.athene.tech/Alexey/IIS_2023_1/pulls/159
This commit is contained in:
Alexey 2023-12-07 15:12:25 +04:00
commit 2d1a2a6fb4
7 changed files with 20248 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
import pandas
from flask import Flask, render_template
from matplotlib import pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
app = Flask(__name__)
@app.route("/")
def home():
return "<html>" \
"<h1>Жукова Алина ПИбд-41</h1>" \
"<h1>Лабораторная работа №4</h1>" \
"<table>" \
"<td>" \
"<form Action='http://127.0.0.1:5000/k4_1_task_4' Method=get>" \
"<input type=submit value='Кластеризация'>" \
"</form>" \
"</td>" \
"</table>" \
"</html>"
# Кластеризация
# 4 Решите задачу кластеризации методом k-means
@app.route("/k4_1_task_4", methods=['GET'])
def k4_1_task_4():
data = pandas.read_csv('Data_chess_games.csv')
data = data.loc[data['created_at'] - data['last_move_at'] != 0]
data = data.drop_duplicates()
i = len(data)
data = data.sample(n=5000, replace=True, random_state=1)
count_klasters = 3
labels_clasters = ["Очень напряженная", "Напряженная", "Спокойная"]
# отбор нужных столбцов
corr = data[['rated', 'turns', 'white_rating', 'black_rating', 'created_at', 'last_move_at', 'increment_code']]
# Добавление времени игры
corr['time_game'] = corr['last_move_at'] - corr['created_at']
corr['middle_time_turn'] = corr['time_game'] / corr['turns']
def formatted_float(ch):
return float('{:.2f}'.format(ch))
corr['middle_time_turn'] = corr['middle_time_turn'].apply(formatted_float)
def true_false_changer(str_true_false):
if (str_true_false == True):
return 1
else:
if (str_true_false == False):
return 0
return 2
corr['new_rated'] = corr['rated'].apply(true_false_changer)
corr = corr[['new_rated', 'middle_time_turn', 'white_rating', 'black_rating', 'increment_code']]
corr = corr.loc[corr['middle_time_turn'] < 10000000]
# Преобразование системы учета времени к численным значениям
def new_code(code):
return (int(code.split("+")[1]) * 100) + int(code.split("+")[0])
corr['n_increment_code'] = corr['increment_code'].apply(new_code)
# Нормирование к 1
max_zn = corr['middle_time_turn'].max()
min_zn = corr['middle_time_turn'].min()
def normirovanie(elem):
return ((elem - min_zn) / (max_zn - min_zn))
weight = 1
def WeightAdd(elem):
return elem * weight
weight = 1
corr['new_rated'] = corr['new_rated'].apply(WeightAdd)
weight = 1
corr['middle_time_turn'] = corr['middle_time_turn'].apply(normirovanie).apply(WeightAdd)
max_zn = corr['white_rating'].max()
min_zn = corr['white_rating'].min()
corr['white_rating'] = corr['white_rating'].apply(normirovanie)
max_zn = corr['black_rating'].max()
min_zn = corr['black_rating'].min()
corr['black_rating'] = corr['black_rating'].apply(normirovanie)
max_zn = corr['n_increment_code'].max()
min_zn = corr['n_increment_code'].min()
weight = 1
corr['n_increment_code'] = corr['n_increment_code'].apply(normirovanie).apply(WeightAdd)
def ObratnoeNormirovanie(elem):
return 1 - elem
corr['n_increment_code'] = corr['n_increment_code'].apply(ObratnoeNormirovanie)
# Исключение из модели рейтинговой игры
corr = corr[['new_rated', 'middle_time_turn', 'white_rating', 'black_rating', 'n_increment_code']]
# создание и обучение алгоритма
kmeans = KMeans(n_clusters=count_klasters)
kmeans.fit(corr)
accuracy = silhouette_score(corr, kmeans.labels_, metric='euclidean')
colors_mass = ['blue', 'red', 'orange', 'green', 'black', 'gold', 'purple', 'pink', 'olive', 'gray',
'cyan', 'crimson', 'royalblue', 'greenyellow', 'maroon']
for klaster in range(count_klasters):
ind = 0
matr_x = []
matr_y = []
for label in kmeans.labels_:
if(label == klaster):
elem = corr.iloc[ind]
X = elem['white_rating']
Y = elem['new_rated'] + elem['middle_time_turn'] + elem['n_increment_code'] + elem['black_rating']
matr_x.append(X)
matr_y.append(Y)
ind += 1
plt.scatter(matr_x, matr_y, alpha=0.6, s=25, c=colors_mass[klaster])
plt.savefig('static/k4_1_4_klaster.png')
return "<html>" \
"<h1>Кластеризация</h1>" \
"<h2>Вариант 10. Задание 4 - метод Kmeans</h2>" \
"<h2> Точность модели по метрике Силуэт: " + str(accuracy) + "</h2>" \
"<div align='center'>" + render_template('4_1_l4_figure1.html') + "</div>" \
"</html>"
if __name__ == "__main__":
app.run(debug=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -0,0 +1,49 @@
## Задание
Использовать метод кластеризации по варианту для выбранных данных,
самостоятельно сформулировав задачу.
Интерпретировать результаты и оценить, насколько хорошо он подходит для
решения сформулированной вами задачи
Вариант №10
## Используемые технологии
В лабораторной были использованы библиотеки:
+ pandas - позволяет работать с наборами данных
+ matplotlib - используется для создания графиков
+ sklearn - используется для работы с моделями и методами машинного обучения
+ Flask - предоставляет способ быстрого создания веб-страниц для визуализации работы приложения
## Используемые компоненты
+ KMeans - библиотечная реализация метода k-средних, алгоритм
стремится минимизировать суммарное квадратичное отклонение точек кластеров от центров этих кластеров
+ silhouette_score - метрика "Силуэт" для определения качества кластеризации.
Вычисляется с помощью среднего внутрикластерного расстояния и среднего расстояния до ближайшего кластера по каждому образцу
## Как запустить
Запустить файл flask-server, который поднимет локальный сервер
и позволит обратиться к программе через браузер по ссылке [http://127.0.0.1:5000/](http://127.0.0.1:5000/)
## Что делает программа
Берет 5000 записей из датасета (датасет Chess Game Dataset
[https://www.kaggle.com/datasets/datasnaek/chess](https://www.kaggle.com/datasets/datasnaek/chess)),
Преобразует данные нечисловых столбцов в числовые значения, осуществляет нормализацию и взвешивание параметров.
Проводит кластеризацию с помощью метода KMeans на данных, количество кластеров выбрано вручную.
Оценивает качество кластеризации с помощью метрики "Силуэт"
## Анализ и скриншоты работы программы
С помощью кластеризации планировалось разбить все шахматные партии на группы
с учетом напряженности игры. Так, рейтинговые игры, с меньшими временными затратами
на ход и более высокими рейтингами игроков считаются более напряженными.
Наилучшие результаты по метрике "Силуэт" получаются, если задать количество кластеров,
равное двум. Но при этом всего лишь происходит разделение игр на рейтинговые и
не рейтинговые. Изменение веса этого параметра также не дает существенных результатов
![img.png](img_screen_2.png)
С другой стороны, разделение данных на 3 кластера визуально совпадает с ожидаемым
разделнием. Так, самые напряженные игры войдут в синий кластер, менее напряженные - в желтый.
Красный кластер соберет все наимее напряженные игры, так как они проходят вне рейтинга.
Однако оценка по метрике "Силуэт" будет существенно хуже.
![img.png](img_screen_1.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img src="{{url_for('static', filename='k4_1_4_klaster.png')}}" align="middle"/>
</body>
</html>