import pandas as pd import numpy as np from matplotlib import pyplot as plt from sklearn import metrics from sklearn.cluster import DBSCAN from sklearn.linear_model import LinearRegression filein = "P:\\ULSTU\\ИИС\\Datasets\\heart_2020_norm.csv" fileout = "P:\\ULSTU\\ИИС\\Datasets\\heart_2020_classified.csv" # Метод устранения шумов и кластеризации данных алгоритмом DBSCAN def dbscan(): df = pd.read_csv(filein, sep=',').iloc[0:10000] # Считывание датасета x = df.drop("HeartDisease", axis=1) # Определение кластеризуемых параметров eps_opt = (x.max().values.mean() + x.min().values.mean()) / 2 # Рассчёт опционального радиуса окрестности методом средней плотности developed_data = [] # Подбор значения минимального количества точек в окрестности for i in range(len(x)): # - Начинаем с одной точки if i == 0: continue # - Увеличиваем значение кол-ва точек на 1 dbscan = DBSCAN(eps=eps_opt, min_samples=i) # - Обучаем модель и получаем массив кластеров clusters = dbscan.fit_predict(x.values) if len(set(clusters)) <= 7: # - Прекращаем увеличивать значение точек, если кол-во кластеров уменьшилось до требуемого developed_data = clusters break if list(clusters).count(-1) / len(clusters) >= 0.1: # - Или если "шум" превышает 10% от данных developed_data = clusters break make_plot(x, developed_data) df["DBSCAN"] = developed_data df.to_csv(fileout, index=False) # Сохраняем полученные кластеры как доп. столбец датасета # Метод оценки эффективности кластеризации DBSCAN def linear_reg(): # Создаём две выборки данных df = pd.read_csv(fileout, sep=',') # В 1й избавляемся от "шумов" и используем столбец кластеров как признак df_mod = df.loc[df["DBSCAN"] != -1] x_train_mod = df_mod.drop("HeartDisease", axis=1).iloc[0:round(len(df) / 100 * 99)] y_train_mod = df_mod["HeartDisease"].iloc[0:round(len(df) / 100 * 99)] x_test_mod = df_mod.drop("HeartDisease", axis=1).iloc[round(len(df) / 100 * 99):len(df)] y_test_mod = df_mod["HeartDisease"].iloc[round(len(df) / 100 * 99):len(df)] # Во 2й оставляем обычные данные x_train = df.drop(["HeartDisease", "DBSCAN"], axis=1).iloc[0:round(len(df) / 100 * 99)] y_train = df["HeartDisease"].iloc[0:round(len(df) / 100 * 99)] x_test = df.drop(["HeartDisease", "DBSCAN"], axis=1).iloc[round(len(df) / 100 * 99):len(df)] y_test = df["HeartDisease"].iloc[round(len(df) / 100 * 99):len(df)] lr_mod = LinearRegression() # Обучаем модель без "шума" и с признаком кластеров lr_mod.fit(x_train_mod.values, y_train_mod.values) y_mod_pred = lr_mod.predict(x_test_mod.values) err = pred_errors(y_mod_pred, y_test_mod.values) make_plots(y_test_mod.values, y_mod_pred, err[0], err[1], "Регрессия с кластеризацией dbscan") lr = LinearRegression() # Обучаем модель на исходных данных lr.fit(x_train.values, y_train.values) y_pred = lr.predict(x_test.values) err = pred_errors(y_pred, y_test.values) make_plots(y_test.values, y_pred, err[0], err[1], "Чистая линейная регрессия") # Метод рассчёта ошибок def pred_errors(y_predict, y_test): mid_square = np.round(np.sqrt(metrics.mean_squared_error(y_test, y_predict)),3) # Рассчёт среднеквадратичной ошибки модели det_kp = np.round(metrics.r2_score (y_test, y_predict), 2) # Рассчёт коэфициента детерминации модели return mid_square, det_kp # Метод отрисовки графиков def make_plots(y_test, y_predict, mid_sqrt, det_kp, title): plt.plot(y_test, c="red", label="\"y\" исходная") # Создание графика исходной функции plt.plot(y_predict, c="green", label="\"y\" предсказанная \n" "Ср^2 = " + str(mid_sqrt) + "\n" "Кд = " + str(det_kp)) # Создание графика предсказанной функции plt.legend(loc='lower left') plt.title(title) plt.savefig('static/' + title + '.png') plt.close() # Метод построения графика кластеризации def make_plot(x, c): plt.scatter(x.values[:, 0], x.values[:, 13], c=c, cmap='viridis') plt.xlabel('BMI') plt.ylabel('SleepTime') plt.colorbar() plt.title('DBSCAN Clustering') plt.savefig('static/dbscan.png') plt.close() if __name__ == '__main__': dbscan() linear_reg()