赞
踩
这是机器学习的一个大作业,主要用到了逻辑斯蒂算法、KNN算法、随机森林算法。
数据集是糖尿病的数据集。
import pandas as pd import numpy as np import warnings import math import lightgbm as lgb import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV,cross_val_score from sklearn.preprocessing import StandardScaler, LabelEncoder from sklearn.linear_model import LogisticRegression from sklearn.neighbors import KNeighborsClassifier from sklearn.ensemble import RandomForestClassifier, StackingClassifier from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score from sklearn.decomposition import PCA from sklearn.metrics import roc_curve from matplotlib import rcParams warnings.filterwarnings('ignore') #步骤1 todo:读取数据 df = pd.read_csv('diabetes_data_upload.csv', delimiter=',') df.columns = ['Age', 'Gender', 'Polyuria', 'Polydipsia', 'sudden weight loss', 'weakness', 'Polyphagia', 'Genital thrush', 'visual blurring', 'Itching', 'Irritability', 'delayed healing', 'partial paresis', 'muscle stiffness', 'Alopecia', 'Obesity', 'class'] #步骤1.1 了解数据基本信息 print(df.head()) print(df.describe()) #步骤1.2 查看数据是否有缺失值情况 print('数据缺失值情况:\n', df.isna().sum()) # 数据清洗,去掉weakness # data.drop(columns=['weakness'],axis=1,inplace=True) #步骤1.3 对数据进行处理 df['Gender'] = df['Gender'].map({'Male': 1, 'Female': 0}) # 步骤1.4 目标变量中为字符串型数据,使用labelEncoder处理编码(spam-1,ham-0) le = LabelEncoder()#转换成数值数据,对定型特征多值化 for col in df.columns: if df[col].dtype == 'object': df[col] = le.fit_transform(df[col]) # 步骤1.5 标准化处理,使用StandardScaler #对 DataFrame 中的除最后一列外的所有数值类型的特征进行标准化处理,即将每个特征减去其均值后再除以标准差。 scaler = StandardScaler() df[df.columns[:-1]] = scaler.fit_transform(df[df.columns[:-1]]) # 步骤1.6 特征工程 X = df[df.columns[:-1]] y = df['class'] #步骤1.7 todo:对整体数据按照train_size进行划分,得到训练集和测试集, random_state确保结果的一致性 X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.66) # 步骤2 todo:可视化分析 # 统计年龄变量的分布情况 plt.figure(figsize=(8, 5)) # 将年龄划分为10个区间 age_bins = pd.cut(df['Age'], bins=10,labels=['{}-{}'.format(i*6+30, i*6+35) for i in range(10)]) # 统计每个区间的样本数量 age_counts = age_bins.value_counts().sort_index() plt.bar(x=age_counts.index.astype(str), height=age_counts.values) plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 plt.title('年龄特征分布与异常值', fontsize=15) plt.xlabel('年龄') plt.ylabel('Count') plt.savefig('./results/Age characteristic_distribution_and_outliers.png') plt.show() #统计不同性别糖尿病的情况 #将数据集 df 中的所有样本根据 'Gender' 列的取值进行分类, # 并计算每个分类中 'class' 列的计数,最后将不同分类的计数以柱状图的形式绘制出来 plt.figure(figsize=(8, 5)) sns.countplot(x='Gender', data=df, hue='class') plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 plt.title('不同性别糖尿病的情况', fontsize=15) plt.xticks(ticks=[0, 1], labels=['Female', 'Male']) plt.savefig('./results/Diabetes_mellitus_of_different_genders.png') plt.show() #统计Polydipsia(过度口渴)对糖尿病的情况 plt.figure(figsize=(8, 5)) sns.countplot(x='Polydipsia', data=df, hue='class') plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 plt.title('过度口渴对糖尿病的情况', fontsize=15) plt.xticks(ticks=[0, 1], labels=['Female', 'Male']) plt.savefig('./results/Excessive_thirst_in_the_case_of_diabetes.png') plt.show() #统计Polyuria(多尿症)对糖尿病的情况 plt.figure(figsize=(8, 5)) sns.countplot(x='Polyuria', data=df, hue='class') plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 plt.title('多尿症对糖尿病的情况', fontsize=15) plt.xticks(ticks=[0, 1], labels=['Female', 'Male']) plt.savefig('./results/Polyuria_is_a_case_of_diabetes.png') plt.show() # PCA 降维可视化 pca = PCA(n_components=2) X_pca = pca.fit_transform(X) df_pca = pd.DataFrame(X_pca, columns=['PC1', 'PC2']) df_pca['class'] = y sns.set(font_scale=1.2) sns.scatterplot(x='PC1', y='PC2', hue='class', data=df_pca) plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 plt.title('主成分可视化', fontsize=10) plt.savefig('./results/PCA_Visualization.png') plt.show() # 相关性分析 corr = df.corr()#计算相关性矩阵 #创建矩阵掩码以隐藏重复值 mask = np.triu(np.ones_like(corr, dtype=bool)) # 设置全局图形风格 plt.figure(figsize=(9, 6)) # 绘制相关性热图 sns.heatmap(corr, mask=mask, cmap='coolwarm', annot=True, fmt='.2f', annot_kws={'size': 5}) plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 plt.title('相关性热图', fontsize=15) plt.savefig('./results/Correlation_Matrix.png') plt.show() # 步骤3 todo:模型训练、测试、评估 # 步骤3.1 todo:模型训练和评估 #定义基分类器 lr = LogisticRegression() knn = KNeighborsClassifier() rf = RandomForestClassifier() # 建立五种模型并交叉验证,使用sklearn中的不同分类器,LogisticRegression, KNeighborsClassifier, RandomForestClassifier, models = [lr, knn, rf] names = ['Logistic Regression', 'KNN', 'Random Forest'] scores = [] for model in models: score = cross_val_score(model, X, y, cv=5, scoring='accuracy').mean() scores.append(score) cv_test=score # 输出各模型预测平均得分 results = pd.DataFrame({'Model': names, 'Score': scores}) print(results) # 使用Stacking集成学习(LR),定义元分类器 stack = StackingClassifier(estimators=[('lr', lr), ('knn', knn), ('rf', rf)], final_estimator=LogisticRegression()) params = { 'lr__C': [0.1,0.5], 'knn__n_neighbors': [3,5], 'rf__n_estimators': [50,100], 'rf__max_depth': [5,7], 'final_estimator__C': [1.0,10] } grid = GridSearchCV(stack, params, cv=5, scoring='accuracy', n_jobs=-1) grid.fit(X, y) # 打印出最佳的模型参数 print(grid.best_params_) ## 最佳模型已经通过网格搜索得到了,不需要再次拟合,直接使用即可 best_model = grid.best_estimator_ best_model.fit(X_train, y_train) # 步骤3.2 todo: 计算分类评价指标:测试集的准确率accuracy、精确率precision、召回率recall和综合评价指标 F1 值 y_pred = grid.predict(X_test)#利用最优模型来预测 accuracy = accuracy_score(y_test, y_pred) # 准确率 precision = precision_score(y_test, y_pred, average='macro') # 精确率 recall = recall_score(y_test, y_pred, average='macro') # 召回率 f1 = f1_score(y_test, y_pred, average='macro') # F1值 print('Accuracy: {:.6f}'.format(accuracy)) print('Precision: {:.6f}'.format(precision)) print('Recall: {:.6f}'.format(recall)) print('F1 score: {:.6f}'.format(f1)) print('cv_test: {:.6f}'.format(cv_test)) # 将评价指标保存到本地 df = pd.DataFrame({'Accuracy': [accuracy], 'Precision': [precision], 'Recall': [recall], 'F1 score': [f1], 'cv_test': [cv_test]}) file_name_csv = 'evaluation_results.csv' df.to_csv(file_name_csv, index=False) # 步骤3.3 todo: 绘制ROC曲线,计算auc,度量分类模型的预测能力 #计算预测概率值 y_prob = grid.predict_proba(X_test)[:, 1] #计算假正率(fpr)、真正率(tpr)以及阈值(thresholds) fpr, tpr, thresholds = roc_curve(y_test, y_prob) #计算auc值 auc_score = roc_auc_score(y_test, y_prob) #绘制ROC曲线 plt.plot(fpr, tpr, color='blue', label='ROC curve (area = %0.2f)' % auc_score) plt.plot([0, 1], [0, 1], color='red', linestyle='--', label='Random Guess') plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.04]) plt.xlabel('假正例率') plt.ylabel('真正例率(召回率)') plt.title('Receiver operating characteristic (ROC) Curve') plt.legend(loc="lower right") plt.savefig('./results/ROC_Curve.png') plt.show() # 步骤3.4 todo:特征重要性分析(RF) feature_importances = grid.best_estimator_.named_estimators_['rf'].feature_importances_ # 获取特征名称 feature_names = X.columns # 对数据框进行排序 feature_df = pd.DataFrame({'Feature': feature_names, 'Importance': feature_importances}) feature_df.sort_values(by='Importance', ascending=False, inplace=True) # 归一化特征重要性 total_importance = feature_df['Importance'].sum() feature_df['Importance_perc'] = feature_df['Importance'] / total_importance * 100 #使用 seaborn 绘制条形图展示特征的重要性 plt.figure(figsize=(9,6)) ax = sns.barplot(x='Feature', y='Importance_perc', data=feature_df) ax.set_xticklabels(ax.get_xticklabels(), rotation=90, fontsize=8) ax.set_ylabel('Importance (%)', fontsize=8) plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 ax.set_title("随机森林特征分析", fontsize=15, pad=10) plt.savefig('./results/Random_Forest_Feature_Importance.png') plt.show() print("模型结束")
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。