活动介绍

# 题目重述 基于 `data_HeartDisease.xlsx` 数据构建分类模型,要求: 1. 尝试选择不同的特征(自变量); 2. 使用多种机器学习算法(如决策树、随机森林、逻辑回归、KNN等)建模; 3. 对模型进行优化(如超参数调优、阈值调整等); 4. 使用最优模型对 `student_HD.xlsx` 数据进行预测; 5. 分析并确定具有最高预测准确率的算法与特征组合; 6. 提交完整 R 代码和预测结果的 Excel 文件。 --- # 详解 以下为完整可运行的 **R语言解决方案**,适用于课程作业提交。代码实现了从数据加载、预处理、多特征集与多算法对比、交叉验证评估、最优模型训练到对 `student_HD.xlsx` 进行预测并输出结果文件的全流程。 ```r # —————————————————————— 1. 加载必要包 —————————————————————— library(tidyverse) library(mlr3verse) library(readxl) library(writexl) # 注意:若未安装,请先运行: # install.packages(c("tidyverse", "mlr3verse", "readxl", "writexl")) # —————————————————————— 2. 读取并预处理训练数据 —————————————————————— # 读取原始数据 data_train <- read_excel("data_HeartDisease.xlsx") # 转换所有字符列为因子(factor) data_clean <- data_train %>% mutate(across(where(is.character), as.factor)) # 创建 mlr3 分类任务(目标变量:HeartDisease) task_full <- as_task_classif(data_clean, target = "HeartDisease") # —————————————————————— 3. 构造不同特征子集用于比较 —————————————————————— # 方案A:医学相关核心特征(分类变量为主) features_medical <- c("AgeCategory", "Sex", "Smoking", "Diabetic", "DiffWalking", "Stroke", "KidneyDisease", "GenHealth", "PhysicalActivity") task_medical <- task_full$select(features_medical) # 方案B:增强型特征(加入数值型指标) features_enhanced <- c(features_medical, "BMI", "PhysicalHealth", "MentalHealth", "SleepTime") task_enhanced <- task_full$select(features_enhanced) # 汇总所有任务 tasks <- list( full = task_full, medical = task_medical, enhanced = task_enhanced ) # —————————————————————— 4. 定义多个机器学习算法(学习器) —————————————————————— learners <- list( lrn("classif.rpart", predict_type = "prob"), # 决策树 lrn("classif.ranger", predict_type = "prob", num.threads = 1), # 随机森林 lrn("classif.log_reg", predict_type = "prob"), # 逻辑回归 lrn("classif.kknn", predict_type = "prob") # K近邻 ) # —————————————————————— 5. 设置5折交叉验证并执行基准测试 —————————————————————— design <- benchmark_grid( tasks = tasks, learners = learners, resamplings = rsmp("cv", folds = 5) ) # 执行基准测试(耗时操作,建议运行一次后保存结果) bmr <- benchmark(design) # —————————————————————— 6. 汇总性能并找出最佳模型 —————————————————————— performance <- bmr$aggregate(msrs(c("classif.acc", "classif.auc"))) # 按准确率排序 performance <- performance[order(-classif.acc), ] print(performance) # 获取最佳模型配置 best_model <- performance[1, ] cat("\n🏆 最佳模型配置:\n") cat("特征集:", best_model$task_id, "\n") cat("算法:", best_model$learner_id, "\n") cat("准确率:", round(best_model$classif.acc, 4), "\n") cat("AUC:", round(best_model$classif.auc, 4), "\n\n") # —————————————————————— 7. 在最优特征集上重新训练模型(可选调参) —————————————————————— best_task <- tasks[[best_model$task_id]] best_learner <- lrn(best_model$learner_id, predict_type = "prob") # 若是决策树,则启用自动调参 if (grepl("rpart", best_model$learner_id)) { library(mlr3tuning) at <- auto_tuner( tuner = tnr("random_search"), learner = best_learner, resampling = rsmp("cv", folds = 5), measure = msr("classif.acc"), search_space = ps(cp = p_dbl(0, 0.1), minsplit = p_int(2, 20)), term_evals = 20 ) best_learner <- at } # 训练最终模型 best_learner$train(best_task) # —————————————————————— 8. 读取学生数据并进行预测 —————————————————————— # 读取待预测数据 data_student <- read_excel("student_HD.xlsx") # 确保与训练数据结构一致 required_features <- best_task$feature_names # 处理缺失列或类型不一致问题 for (col in required_features) { if (!col %in% names(data_student)) { stop("缺少必要特征:", col) } data_student[[col]] <- as.factor(data_student[[col]]) } # 提取有效输入数据 X_new <- data_student[, required_features] # 进行预测 pred <- best_learner$predict_newdata(X_new) # 将预测结果合并回原始数据 result_df <- bind_cols( data_student, tibble( prediction = pred$response, prob_No = pred$prob[, "No"], prob_Yes = pred$prob[, "Yes"] ) ) # —————————————————————— 9. 导出预测结果到Excel —————————————————————— write_xlsx(result_df, "predicted_student_HD.xlsx") # 输出完成信息 cat("✅ 预测完成!\n") cat("📁 文件已保存:predicted_student_HD.xlsx\n") cat("📊 总样本数:", nrow(result_df), "\n") cat("🔍 使用特征数:", length(required_features), "\n") cat("🎯 最高准确率模型:", best_model$learner_id, "(", round(best_model$classif.acc, 4), ")\n") # 题目重述 基于 `data_HeartDisease.xlsx` 数据构建分类模型,要求: 1. 尝试选择不同的特征(自变量); 2. 使用多种机器学习算法(如决策树、随机森林、逻辑回归、KNN等)建模; 3. 对模型进行优化(如超参数调优、阈值调整等); 4. 使用最优模型对 `student_HD.xlsx` 数据进行预测; 5. 分析并确定具有最高预测准确率的算法与特征组合; 6. 提交完整 R 代码和预测结果的 Excel 文件。 --- # 详解 以下为完整可运行的 **R语言解决方案**,适用于课程作业提交。代码实现了从数据加载、预处理、多特征集与多算法对比、交叉验证评估、最优模型训练到对 `student_HD.xlsx` 进行预测并输出结果文件的全流程。 ```r # —————————————————————— 1. 加载必要包 —————————————————————— library(tidyverse) library(mlr3verse) library(readxl) library(writexl) # 注意:若未安装,请先运行: # install.packages(c("tidyverse", "mlr3verse", "readxl", "writexl")) # —————————————————————— 2. 读取并预处理训练数据 —————————————————————— # 读取原始数据 data_train <- read_excel("data_HeartDisease.xlsx") # 转换所有字符列为因子(factor) data_clean <- data_train %>% mutate(across(where(is.character), as.factor)) # 创建 mlr3 分类任务(目标变量:HeartDisease) task_full <- as_task_classif(data_clean, target = "HeartDisease") # —————————————————————— 3. 构造不同特征子集用于比较 —————————————————————— # 方案A:医学相关核心特征(分类变量为主) features_medical <- c("AgeCategory", "Sex", "Smoking", "Diabetic", "DiffWalking", "Stroke", "KidneyDisease", "GenHealth", "PhysicalActivity") task_medical <- task_full$select(features_medical) # 方案B:增强型特征(加入数值型指标) features_enhanced <- c(features_medical, "BMI", "PhysicalHealth", "MentalHealth", "SleepTime") task_enhanced <- task_full$select(features_enhanced) # 汇总所有任务 tasks <- list( full = task_full, medical = task_medical, enhanced = task_enhanced ) # —————————————————————— 4. 定义多个机器学习算法(学习器) —————————————————————— learners <- list( lrn("classif.rpart", predict_type = "prob"), # 决策树 lrn("classif.ranger", predict_type = "prob", num.threads = 1), # 随机森林 lrn("classif.log_reg", predict_type = "prob"), # 逻辑回归 lrn("classif.kknn", predict_type = "prob") # K近邻 ) # —————————————————————— 5. 设置5折交叉验证并执行基准测试 —————————————————————— design <- benchmark_grid( tasks = tasks, learners = learners, resamplings = rsmp("cv", folds = 5) ) # 执行基准测试(耗时操作,建议运行一次后保存结果) bmr <- benchmark(design) # —————————————————————— 6. 汇总性能并找出最佳模型 —————————————————————— performance <- bmr$aggregate(msrs(c("classif.acc", "classif.auc"))) # 按准确率排序 performance <- performance[order(-classif.acc), ] print(performance) # 获取最佳模型配置 best_model <- performance[1, ] cat("\n🏆 最佳模型配置:\n") cat("特征集:", best_model$task_id, "\n") cat("算法:", best_model$learner_id, "\n") cat("准确率:", round(best_model$classif.acc, 4), "\n") cat("AUC:", round(best_model$classif.auc, 4), "\n\n") # —————————————————————— 7. 在最优特征集上重新训练模型(可选调参) —————————————————————— best_task <- tasks[[best_model$task_id]] best_learner <- lrn(best_model$learner_id, predict_type = "prob") # 若是决策树,则启用自动调参 if (grepl("rpart", best_model$learner_id)) { library(mlr3tuning) at <- auto_tuner( tuner = tnr("random_search"), learner = best_learner, resampling = rsmp("cv", folds = 5), measure = msr("classif.acc"), search_space = ps(cp = p_dbl(0, 0.1), minsplit = p_int(2, 20)), term_evals = 20 ) best_learner <- at } # 训练最终模型 best_learner$train(best_task) # —————————————————————— 8. 读取学生数据并进行预测 —————————————————————— # 读取待预测数据 data_student <- read_excel("student_HD.xlsx") # 确保与训练数据结构一致 required_features <- best_task$feature_names # 处理缺失列或类型不一致问题 for (col in required_features) { if (!col %in% names(data_student)) { stop("缺少必要特征:", col) } data_student[[col]] <- as.factor(data_student[[col]]) } # 提取有效输入数据 X_new <- data_student[, required_features] # 进行预测 pred <- best_learner$predict_newdata(X_new) # 将预测结果合并回原始数据 result_df <- bind_cols( data_student, tibble( prediction = pred$response, prob_No = pred$prob[, "No"], prob_Yes = pred$prob[, "Yes"] ) ) # —————————————————————— 9. 导出预测结果到Excel —————————————————————— write_xlsx(result_df, "predicted_student_HD.xlsx") # 输出完成信息 cat("✅ 预测完成!\n") cat("📁 文件已保存:predicted_student_HD.xlsx\n") cat("📊 总样本数:", nrow(result_df), "\n") cat("🔍 使用特征数:", length(required_features), "\n") cat("🎯 最高准确率模型:", best_model$learner_id, "(", round(best_model$classif.acc, 4), ")\n") 错误于.__Task__select(self = self, private = private, super = super, : Assertion on 'cols' failed: Must be a subset of {'AgeCategory','Diabetic','DiffWalking','GenHealth','KidneyDisease','PhysicalActivity','Sex','Smoking','Stroke'}, but has additional elements {'BMI','PhysicalHealth','MentalHealth','SleepTime'}.

时间: 2025-10-26 22:23:21 AIGC 浏览: 38
<think>我们遇到了一个错误:在创建增强特征集的任务时,尝试选择了一些在数据集中不存在的列。 错误信息指出:'cols'必须是{'AgeCategory','Diabetic','DiffWalking','GenHealth','KidneyDisease','PhysicalActivity','Sex','Smoking','Stroke'}的子集,但包含了额外的列{'BMI','PhysicalHealth','MentalHealth','SleepTime'}。 这意味着在我们的训练数据集中,并没有包含这些数值型指标:BMI, PhysicalHealth, MentalHealth, SleepTime。 因此,我们需要检查原始数据文件`data_HeartDisease.xlsx`中是否包含这些列。如果不包含,那么我们需要调整特征选择。 根据错误信息,原始数据中只包含以下列: 'AgeCategory','Diabetic','DiffWalking','GenHealth','KidneyDisease','PhysicalActivity','Sex','Smoking','Stroke' 所以,我们有两个选择: 1. 如果原始数据确实没有这些数值型特征,那么我们需要修改代码,只使用已有的特征。 2. 如果原始数据有这些特征,但名称不一致,我们需要修正特征名称。 由于题目中要求使用`data_HeartDisease.xlsx`,并且错误提示中并没有列出这些数值型特征,所以很可能是原始数据中不包含这些特征。 因此,我们调整特征集: 方案A(医学相关核心特征)不变。 方案B(增强型特征)无法实现,因为缺少那些数值型特征。所以我们只能使用方案A和全特征(实际上全特征就是所有列,但目标变量是HeartDisease,所以特征就是除了HeartDisease的所有列)。 但是,我们创建任务时使用的是整个数据集(除了目标变量),而在错误信息中列出的特征正是方案A的特征,所以全特征集应该就是方案A的特征(因为数据中只有这些特征)。 所以,我们重新定义特征集: 实际上,我们只有两个特征集: - 全特征集(实际上就是所有特征,即方案A的特征,因为数据中只有这些特征) - 方案A:医学相关核心特征(与全特征集相同?) 但注意:全特征集可能包含所有列,包括可能存在的其他列(比如ID等),但根据错误信息,数据中只有那些列。 因此,我们需要重新检查原始数据,并调整特征集。 步骤: 1. 打印原始数据的列名,确认可用特征。 2. 根据实际列名调整特征集。 由于无法直接查看数据,我们调整代码:先读取数据并查看列名,然后根据实际列名定义特征集。 但是,由于我们是在代码中解决问题,我们可以这样做: 将原来的特征集定义改为: 全特征:使用所有特征(除去目标变量HeartDisease,因为在创建任务时已经指定目标变量,任务会自动排除目标变量?实际上,在mlr3中,创建任务时指定目标变量,那么任务的特征就是除目标变量外的所有列) 所以,我们不需要手动选择全特征。因此,我们定义特征集: 方案A:医学相关核心特征(从所有可用特征中选取我们感兴趣的部分) 方案B:如果数据中有数值型特征,那么我们可以定义,否则就不定义。 通过查看数据,我们发现原始数据中并没有BMI等特征。因此,我们只能使用方案A作为特征子集,以及全特征集(但是全特征集和方案A可能是一样的,因为数据中只有这些特征)。 实际上,在错误信息中列出的特征就是方案A的特征,并且没有其他特征。所以,我们只能比较: - 全特征集(即所有特征,但这里所有特征就是方案A的特征) - 方案A:医学相关核心特征(这里就是全部特征,所以两个任务是一样的) 这显然没有意义。所以我们需要重新考虑。 根据题目要求,我们需要尝试不同的特征组合。因此,我们需要创建至少两个不同的特征子集。 既然没有额外的数值型特征,我们可以考虑: 方案A:部分医学特征(去掉一两个特征) 方案B:全部特征(即方案A的所有特征) 例如,我们可以定义: 方案A:去掉'GenHealth'和'PhysicalActivity' 方案B:全部特征 这样,我们就有两个不同的特征集。 或者,我们可以尝试其他拆分方式,比如: 方案A:仅包含人口统计特征(如AgeCategory, Sex) 方案B:包含所有特征 但为了满足题目要求,我们至少要有两个特征集。 因此,我们修改代码中的特征集定义部分: 假设原始数据列名为: c("AgeCategory", "Sex", "Smoking", "Diabetic", "DiffWalking", "Stroke", "KidneyDisease", "GenHealth", "PhysicalActivity", "HeartDisease") 我们定义: features_medical1 <- c("AgeCategory", "Sex", "Smoking", "Diabetic", "DiffWalking", "Stroke", "KidneyDisease") features_medical2 <- c("AgeCategory", "Sex", "Smoking", "Diabetic", "DiffWalking", "Stroke", "KidneyDisease", "GenHealth", "PhysicalActivity") # 全部特征 这样,我们就有两个特征集:一个包含全部特征(即原始所有特征),另一个只包含部分特征。 注意:在创建任务时,我们使用的是整个数据集,所以全特征任务就是包含所有特征(除了目标变量)。然后我们创建两个子集任务。 因此,调整代码: tasks <- list( full = task_full, # 全特征(所有可用特征) medical1 = task_full$select(features_medical1), medical2 = task_full$select(features_medical2) # 实际上这个就是全特征,因为features_medical2包含了所有特征 ) 但是,注意:我们的数据中只有9个特征(如错误信息所示),而features_medical2就是这9个特征。所以medical2和full是一样的。 为了避免重复,我们可以这样: tasks <- list( reduced = task_full$select(features_medical1), # 减少的特征集 full = task_full # 全部特征 ) 这样,我们就有了两个特征集:减少的特征集(7个特征)和全特征集(9个特征)。 修改后的代码: ```r # ... 前面的代码保持不变 ... # 方案A:减少特征集(去掉GenHealth和PhysicalActivity) features_reduced <- c("AgeCategory", "Sex", "Smoking", "Diabetic", "DiffWalking", "Stroke", "KidneyDisease") task_reduced <- task_full$select(features_reduced) # 方案B:全特征(即原始所有特征,我们不再额外定义,直接使用task_full) # 注意:task_full已经包含了所有特征(除了目标变量) # 汇总所有任务 tasks <- list( reduced = task_reduced, full = task_full ) # ... 后续代码保持不变 ... ``` 这样,我们就有了两个特征集:reduced和full。 另外,注意在基准测试中,我们使用了三个任务:原来有full, medical, enhanced,现在改为两个:reduced和full。 同时,我们修改最佳模型选择后的任务选择代码,因为任务列表名称变了。 重新运行代码,应该可以避免上述错误。 但是,我们还需要注意:在读取学生数据时,学生数据中可能也没有BMI等特征,所以我们的特征集只能基于已有的特征。 因此,我们按照上述修改代码。 由于我们无法实际运行,这里提供修改后的完整代码。 修改后的完整代码: </think>根据错误信息,问题出在创建 `task_enhanced` 时尝试使用了数据集中不存在的特征(BMI, PhysicalHealth, MentalHealth, SleepTime)。以下是修正后的完整解决方案: ```r # —————————————————————— 1. 加载必要包 —————————————————————— library(tidyverse) library(mlr3verse) library(readxl) library(writexl) # 若未安装,请先运行: # install.packages(c("tidyverse", "mlr3verse", "readxl", "writexl")) # —————————————————————— 2. 读取并预处理训练数据 —————————————————————— # 读取原始数据 data_train <- read_excel("data_HeartDisease.xlsx") # 检查实际存在的特征列 cat("实际存在的特征列:\n") print(names(data_train)) # 转换所有字符列为因子 data_clean <- data_train %>% mutate(across(where(is.character), as.factor)) # 创建 mlr3 分类任务 task_full <- as_task_classif(data_clean, target = "HeartDisease") # —————————————————————— 3. 修正特征子集(基于实际数据)—————————————————————— # 获取所有可用特征 all_features <- setdiff(names(data_clean), "HeartDisease") # 方案A:核心医学特征 features_medical <- c("AgeCategory", "Sex", "Smoking", "Diabetic", "DiffWalking", "Stroke", "KidneyDisease", "GenHealth", "PhysicalActivity") # 调整方案:仅保留数据集中实际存在的特征 features_medical <- intersect(features_medical, all_features) task_medical <- task_full$select(features_medical) # 方案B:随机选择不同特征组合(替代原增强方案) set.seed(123) features_random <- sample(all_features, size = length(all_features) - 2, replace = FALSE) task_random <- task_full$select(features_random) # 汇总所有任务 tasks <- list( full = task_full, medical = task_medical, random = task_random ) # —————————————————————— 4. 定义机器学习算法 —————————————————————— learners <- list( lrn("classif.rpart", predict_type = "prob"), # 决策树 lrn("classif.ranger", predict_type = "prob", num.threads = 1), # 随机森林 lrn("classif.log_reg", predict_type = "prob"), # 逻辑回归 lrn("classif.kknn", predict_type = "prob") # K近邻 ) # —————————————————————— 5. 设置5折交叉验证并执行基准测试 —————————————————————— design <- benchmark_grid( tasks = tasks, learners = learners, resamplings = rsmp("cv", folds = 5) ) # 执行基准测试 bmr <- benchmark(design) # —————————————————————— 6. 汇总性能并找出最佳模型 —————————————————————— performance <- bmr$aggregate(msrs(c("classif.acc", "classif.auc"))) # 按准确率排序 performance <- performance[order(-classif.acc), ] print(performance) # 获取最佳模型配置 best_model <- performance[1, ] cat("\n🏆 最佳模型配置:\n") cat("特征集:", best_model$task_id, "\n") cat("算法:", best_model$learner_id, "\n") cat("准确率:", round(best_model$classif.acc, 4), "\n") cat("AUC:", round(best_model$classif.auc, 4), "\n\n") # —————————————————————— 7. 训练优化后的最佳模型 —————————————————————— best_task <- tasks[[best_model$task_id]] best_learner <- lrn(best_model$learner_id, predict_type = "prob") # 添加超参数调优(所有模型类型) library(mlr3tuning) library(paradox) # 通用调优设置 tuner <- function(learner) { auto_tuner( tuner = tnr("random_search"), learner = learner, resampling = rsmp("cv", folds = 3), # 简化调优过程 measure = msr("classif.acc"), term_evals = 10 ) } # 根据算法类型设置特定搜索空间 if (grepl("rpart", best_learner$id)) { # 决策树调优 best_learner$param_set$values <- list( cp = to_tune(0.01, 0.1), minsplit = to_tune(5, 20), maxdepth = to_tune(5, 15) ) } else if (grepl("ranger", best_learner$id)) { # 随机森林调优 best_learner$param_set$values <- list( num.trees = to_tune(100, 500), mtry = to_tune(1, sqrt(length(best_task$feature_names))), min.node.size = to_tune(1, 10) ) } else if (grepl("kknn", best_learner$id)) { # KNN调优 best_learner$param_set$values <- list( k = to_tune(3, 15) ) } # 执行调优 tuned_learner <- tuner(best_learner) tuned_learner$train(best_task) # —————————————————————— 8. 预测学生数据 —————————————————————— # 读取待预测数据 data_student <- read_excel("student_HD.xlsx") # 确保与训练数据结构一致 required_features <- best_task$feature_names # 处理缺失列或类型不一致问题 for (col in required_features) { if (!col %in% names(data_student)) { stop("缺少必要特征:", col) } # 自动转换数据类型 if (is.factor(data_clean[[col]])) { data_student[[col]] <- as.factor(data_student[[col]]) } else { data_student[[col]] <- as.numeric(data_student[[col]]) } } # 提取有效输入数据 X_new <- data_student[, required_features, drop = FALSE] # 进行预测 pred <- tuned_learner$predict_newdata(X_new) # 创建结果数据框 result_df <- data_student %>% mutate( HeartDisease_Pred = pred$response, Probability_Yes = pred$prob[, "Yes"], Probability_No = pred$prob[, "No"] ) # —————————————————————— 9. 导出预测结果 —————————————————————— write_xlsx(result_df, "predicted_student_HD.xlsx") # 输出完成信息 cat("✅ 预测完成!\n") cat("📁 文件已保存:predicted_student_HD.xlsx\n") cat("📊 总样本数:", nrow(result_df), "\n") cat("🔍 使用特征:", paste(required_features, collapse = ", "), "\n") cat("🎯 最佳模型:", best_model$learner_id, " (准确率:", round(best_model$classif.acc, 4), ")\n") ``` ### 主要修正点解释: 1. **特征集调整**: - 添加了特征存在性检查:使用 `intersect(features_medical, all_features)` 确保只使用数据集中实际存在的特征 - 替代了原增强方案:使用随机特征选择(`features_random`)作为替代方案 - 增加了特征调试输出:打印实际存在的特征列帮助调试 2. **通用调优框架**: - 创建了统一的 `tuner()` 函数适用于所有算法类型 - 为不同算法设置特定超参数空间: * 决策树:复杂度参数(cp)、最小分裂样本(minsplit)、最大深度(maxdepth) * 随机森林:树数量(num.trees)、特征抽样数(mtry)、节点最小样本(min.node.size) * KNN:邻居数量(k) 3. **数据类型自动转换**: - 在预测阶段自动检测并转换数据类型:`if (is.factor(data_clean[[col]])) {...}` 4. **增强错误处理**: - 添加了更详细的错误信息:`stop("缺少必要特征:", col)` - 使用 `drop = FALSE` 防止单列时降维为向量 5. **结果格式优化**: - 更清晰的列命名:`HeartDisease_Pred`, `Probability_Yes`, `Probability_No` - 包含所有原始特征+预测结果 这个解决方案更健壮,能自动适应不同的特征组合,并为每种算法提供针对性的超参数优化。
阅读全文

相关推荐

C:\ProgramData\anaconda3\python.exe "C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py" 918条数据的年龄分箱分布: Age_bin 0 0 1 80 2 585 3 253 4 0 Name: count, dtype: int64 5110条数据的年龄分箱分布: Age_bin 0 966 1 1204 2 1564 3 1190 4 186 Name: count, dtype: int64 412条数据的年龄分箱分布: Age_bin 0 0 1 69 2 257 3 86 4 0 Name: count, dtype: int64 胆固醇分箱分布(标签0-1-2): Cholesterol_bin 0 318 1 237 2 363 Name: count, dtype: int64 胆固醇分箱分布(标签0-1-2): Cholesterol_bin 0 23 1 39 2 252 Name: count, dtype: int64 Sex ChestPainType FastingBS RestingECG ExerciseAngina ST_Slope HeartDisease RestingBP_bin MaxHR_bin Oldpeak_bin Age_bin Cholesterol_bin 0 M ATA 0 Normal N Up 0 1级高血压 高(85-100%) 无压低 2 2 1 F NAP 0 Normal N Flat 1 2级高血压 高(85-100%) 轻度压低 2 0 2 M ATA 0 ST N Up 0 升高前期 低(<60%) 无压低 1 2 3 F ASY 0 Normal Y Flat 1 1级高血压 中(60-85%) 中度压低 2 1 4 M NAP 0 Normal N Up 0 2级高血压 中(60-85%) 无压低 2 0 .. .. ... ... ... ... ... ... ... ... ... ... ... 913 M TA 0 Normal N Flat 1 正常 中(60-85%) 中度压低 2 2 914 M ASY 1 Normal N Flat 1 2级高血压 高(85-100%) 严重压低 3 0 915 M ASY 0 Normal Y Flat 1 升高前期 中(60-85%) 中度压低 2 0 916 F ATA 0 LVH N Flat 1 升高前期 极高(>100%) 无压低 2 1 917 M NAP 0 Normal N Up 0 1级高血压 高(85-100%) 无压低 1 0 [918 rows x 12 columns] ID N_Days Status Drug Sex Ascites Hepatomegaly Spiders Edema Bilirubin Albumin Stage Bilirubin_bin Albumin_bin Copper_bin Alk_Phos_bin SGOT_bin Tryglicerides_bin Platelets_bin Prothrombin_bin Age_bin Cholesterol_bin 0 1 400 D D-penicillamine F Y Y Y Y 14.5 2.60 4 显著升高 降低 升高 升高 升高 升高 正常 正常 2 2 1 2 4500 C D-penicillamine F N Y Y N 1.1 4.14 3 正常 正常 升高 升高 升高 正常 正常 正常 2 2 2 3 1012 D D-penicillamine M N N N S 1.4 3.48 4 轻度升高 降低 升高 升高 升高 正常 正常 正常 3 0 3 4 1925 D D-penicillamine F N Y Y S 1.8 2.54 4 轻度升高 降低 升高 升高 升高 正常 正常 正常 2 2 4 5 1504 CL Placebo F N Y Y N 3.4 3.53 3 显著升高 正常 升高 升高 升高 正常 减少 正常 1 2 .. ... ... ... ... .. ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 407 414 681 D D-penicillamine F N Y N N 1.2 2.96 3 正常 降低 升高 升高 正常 升高 正常 正常 3 NaN 408 415 1103 C D-penicillamine F N Y N N 0.9 3.83 4 正常 正常 升高 升高 正常 升高 正常 正常 1 NaN 409 416 1055 C D-penicillamine F N Y N N 1.6 3.42 3 轻度升高 降低 升高 升高 正常 升高 减少 正常 2 NaN 410 417 691 C D-penicillamine F N Y N N 0.8 3.75 3 正常 正常 升高 升高 正常 升高 正常 正常 2 NaN 411 418 976 C D-penicillamine F N Y N N 0.7 3.29 4 正常 降低 升高 升高 正常 升高 正常 正常 2 NaN [412 rows x 22 columns] id Sex hypertension heart_disease ever_married work_type Residence_type smoking_status stroke glucose_bin Age_bin bmi_bin 0 9046 M 0 1 Yes Private Urban formerly smoked 1 糖尿病 3 肥胖 1 51676 F 0 0 Yes Self-employed Rural never smoked 1 糖尿病 3 偏瘦 2 31112 M 0 1 Yes Private Rural never smoked 1 偏高 4 肥胖 3 60182 F 0 0 Yes Private Urban smokes 1 糖尿病前期 2 肥胖 4 1665 F 1 0 Yes Self-employed Rural never smoked 1 糖尿病前期 3 正常 ... ... .. ... ... ... ... ... ... ... ... ... ... 5105 18234 F 1 0 Yes Private Urban never smoked 0 正常 4 NaN 5106 44873 F 0 0 Yes Self-employed Urban never smoked 0 偏高 4 肥胖 5107 19723 F 0 0 Yes Self-employed Rural never smoked 0 正常 1 肥胖 5108 37544 M 0 0 Yes Private Rural formerly smoked 0 糖尿病前期 2 超重 5109 44679 F 0 0 Yes Govt_job Urban Unknown 0 正常 2 超重 [5110 rows x 12 columns] 处理后的数据形状:(918, 12)(无NaN) 处理后的数据形状:(5110, 12)(无NaN) 处理后的数据形状:(412, 22)(无NaN) Main already 处理 heart 数据集中的稀有类别(目标变量: HeartDisease) 处理 stroke 数据集中的稀有类别(目标变量: stroke) 处理 cirrhosis 数据集中的稀有类别(目标变量: Stage) C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:271: FutureWarning: Downcasting behavior in replace is deprecated and will be removed in a future version. To retain the old behavior, explicitly call result.infer_objects(copy=False). To opt-in to the future behavior, set pd.set_option('future.no_silent_downcasting', True) df['Oldpeak_bin'] = df['Oldpeak_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:271: FutureWarning: The behavior of Series.replace (and DataFrame.replace) with CategoricalDtype is deprecated. In a future version, replace will only be used for cases that preserve the categories. To change the categories, use ser.cat.rename_categories instead. df['Oldpeak_bin'] = df['Oldpeak_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:275: FutureWarning: Downcasting behavior in replace is deprecated and will be removed in a future version. To retain the old behavior, explicitly call result.infer_objects(copy=False). To opt-in to the future behavior, set pd.set_option('future.no_silent_downcasting', True) df['RestingBP_bin'] = df['RestingBP_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:275: FutureWarning: The behavior of Series.replace (and DataFrame.replace) with CategoricalDtype is deprecated. In a future version, replace will only be used for cases that preserve the categories. To change the categories, use ser.cat.rename_categories instead. df['RestingBP_bin'] = df['RestingBP_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:279: FutureWarning: Downcasting behavior in replace is deprecated and will be removed in a future version. To retain the old behavior, explicitly call result.infer_objects(copy=False). To opt-in to the future behavior, set pd.set_option('future.no_silent_downcasting', True) df['ST_Slope'] = df['ST_Slope'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:283: FutureWarning: Downcasting behavior in replace is deprecated and will be removed in a future version. To retain the old behavior, explicitly call result.infer_objects(copy=False). To opt-in to the future behavior, set pd.set_option('future.no_silent_downcasting', True) df['ChestPainType'] = df['ChestPainType'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:290: FutureWarning: Downcasting behavior in replace is deprecated and will be removed in a future version. To retain the old behavior, explicitly call result.infer_objects(copy=False). To opt-in to the future behavior, set pd.set_option('future.no_silent_downcasting', True) df['glucose_bin'] = df['glucose_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:290: FutureWarning: The behavior of Series.replace (and DataFrame.replace) with CategoricalDtype is deprecated. In a future version, replace will only be used for cases that preserve the categories. To change the categories, use ser.cat.rename_categories instead. df['glucose_bin'] = df['glucose_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:293: FutureWarning: Downcasting behavior in replace is deprecated and will be removed in a future version. To retain the old behavior, explicitly call result.infer_objects(copy=False). To opt-in to the future behavior, set pd.set_option('future.no_silent_downcasting', True) df['bmi_bin'] = df['bmi_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:293: FutureWarning: The behavior of Series.replace (and DataFrame.replace) with CategoricalDtype is deprecated. In a future version, replace will only be used for cases that preserve the categories. To change the categories, use ser.cat.rename_categories instead. df['bmi_bin'] = df['bmi_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:296: FutureWarning: Downcasting behavior in replace is deprecated and will be removed in a future version. To retain the old behavior, explicitly call result.infer_objects(copy=False). To opt-in to the future behavior, set pd.set_option('future.no_silent_downcasting', True) df['smoking_status'] = df['smoking_status'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:303: FutureWarning: Downcasting behavior in replace is deprecated and will be removed in a future version. To retain the old behavior, explicitly call result.infer_objects(copy=False). To opt-in to the future behavior, set pd.set_option('future.no_silent_downcasting', True) df['Bilirubin_bin'] = df['Bilirubin_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:303: FutureWarning: The behavior of Series.replace (and DataFrame.replace) with CategoricalDtype is deprecated. In a future version, replace will only be used for cases that preserve the categories. To change the categories, use ser.cat.rename_categories instead. df['Bilirubin_bin'] = df['Bilirubin_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:306: FutureWarning: Downcasting behavior in replace is deprecated and will be removed in a future version. To retain the old behavior, explicitly call result.infer_objects(copy=False). To opt-in to the future behavior, set pd.set_option('future.no_silent_downcasting', True) df['Albumin_bin'] = df['Albumin_bin'].replace( C:\Users\Diwith\Daily_Project\2023ES2\YataiBei_Bayesian Network.py:306: FutureWarning: The behavior of Series.replace (and DataFrame.replace) with CategoricalDtype is deprecated. In a future version, replace will only be used for cases that preserve the categories. To change the categories, use ser.cat.rename_categories instead. df['Albumin_bin'] = df['Albumin_bin'].replace( Config already 已为 heart 构建贝叶斯网络 [heart] 模型CPD验证: 节点 ChestPainType 的CPD: +------------------+----------+ | ChestPainType(0) | 0.542339 | +------------------+----------+ | ChestPainType(1) | 0.190188 | +------------------+----------+ | ChestPainType(2) | 0.221102 | +------------------+----------+ | ChestPainType(3) | 0.046371 | +------------------+----------+ 节点 HeartDisease 的CPD: +-----------------+-----+---------------------+ | Age_bin | ... | Age_bin(3) | +-----------------+-----+---------------------+ | ChestPainType | ... | ChestPainType(3) | +-----------------+-----+---------------------+ | RestingBP_bin | ... | RestingBP_bin(3) | +-----------------+-----+---------------------+ | ST_Slope | ... | ST_Slope(2) | +-----------------+-----+---------------------+ | HeartDisease(0) | ... | 0.6628959276018099 | +-----------------+-----+---------------------+ | HeartDisease(1) | ... | 0.33710407239819007 | +-----------------+-----+---------------------+ 节点 ST_Slope 的CPD: +-------------+-----------+ | ST_Slope(0) | 0.0689964 | +-------------+-----------+ | ST_Slope(1) | 0.513889 | +-------------+-----------+ | ST_Slope(2) | 0.417115 | +-------------+-----------+ 已为 stroke 构建贝叶斯网络 [stroke] 模型CPD验证: 节点 hypertension 的CPD: +-----------------+-----------+ | hypertension(0) | 0.905076 | +-----------------+-----------+ | hypertension(1) | 0.0949244 | +-----------------+-----------+ 节点 stroke 的CPD: +---------------+-----+------------------+ | Age_bin | ... | Age_bin(4) | +---------------+-----+------------------+ | glucose_bin | ... | glucose_bin(3) | +---------------+-----+------------------+ | heart_disease | ... | heart_disease(1) | +---------------+-----+------------------+ | hypertension | ... | hypertension(1) | +---------------+-----+------------------+ | stroke(0) | ... | 0.5 | +---------------+-----+------------------+ | stroke(1) | ... | 0.5 | +---------------+-----+------------------+ 节点 glucose_bin 的CPD: +----------------+-----------+ | glucose_bin(0) | 0.60798 | +----------------+-----------+ | glucose_bin(1) | 0.227794 | +----------------+-----------+ | glucose_bin(2) | 0.0777208 | +----------------+-----------+ | glucose_bin(3) | 0.0865056 | +----------------+-----------+ 已为 cirrhosis 构建贝叶斯网络 [cirrhosis] 模型CPD验证: 节点 Bilirubin_bin 的CPD: +------------------+----------+ | Bilirubin_bin(0) | 0.446411 | +------------------+----------+ | Bilirubin_bin(1) | 0.26647 | +------------------+----------+ | Bilirubin_bin(2) | 0.287119 | +------------------+----------+ 节点 Stage 的CPD: +---------------+-----+------------------+ | Age_bin | ... | Age_bin(3) | +---------------+-----+------------------+ | Albumin_bin | ... | Albumin_bin(1) | +---------------+-----+------------------+ | Ascites | ... | Ascites(Y) | +---------------+-----+------------------+ | Bilirubin_bin | ... | Bilirubin_bin(2) | +---------------+-----+------------------+ | Stage(1) | ... | 0.25 | +---------------+-----+------------------+ | Stage(2) | ... | 0.25 | +---------------+-----+------------------+ | Stage(3) | ... | 0.25 | +---------------+-----+------------------+ | Stage(4) | ... | 0.25 | +---------------+-----+------------------+ 节点 Albumin_bin 的CPD: +----------------+----------+ | Albumin_bin(0) | 0.477876 | +----------------+----------+ | Albumin_bin(1) | 0.522124 | +----------------+----------+ 已成功保存 heart 网络结构图 已成功保存 stroke 网络结构图 已成功保存 cirrhosis 网络结构图 [heart] 拟合度计算失败: Missing columns in data. Can't find values for the following variables: set() [heart] 推理失败样本过多(184条),无有效预测结果 [stroke] 拟合度计算失败: Missing columns in data. Can't find values for the following variables: set() [stroke] 推理失败样本过多(1022条),无有效预测结果 [cirrhosis] 拟合度计算失败: Missing columns in data. Can't find values for the following variables: set() [cirrhosis] 推理失败样本过多(83条),无有效预测结果 进程已结束,退出代码为 0 import pandas as pd import matplotlib.pyplot as plt import numpy as np from pgmpy.models import BayesianNetwork from pgmpy.estimators import MaximumLikelihoodEstimator from pgmpy.inference import VariableElimination import networkx as nx from sklearn.metrics import accuracy_score, confusion_matrix, classification_report from pgmpy.metrics import log_likelihood_score from pgmpy.estimators import BicScore from sklearn.model_selection import train_test_split from pgmpy.estimators import BayesianEstimator from sympy.solvers.diophantine.diophantine import equivalent plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False pd.set_option('display.max_columns', 500) pd.set_option('display.width', 1000) df_heart = pd.read_csv('heart_se.csv') df_stroke = pd.read_csv('stroke_se.csv') df_cirrhosis = pd.read_csv('cirrhosis_se.csv') df_stroke.columns = ['id', 'Sex', 'Age', 'hypertension', 'heart_disease', 'ever_married', 'work_type', 'Residence_type', 'avg_glucose_level', 'bmi', 'smoking_status', 'stroke'] df_stroke['Sex'] = df_stroke['Sex'].apply(lambda x: 'M' if x == 'Male' else 'F') df_cirrhosis['Age'] = (df_cirrhosis['Age'] / 365).astype(int) df_stroke['Age'] = df_stroke['Age'].astype(int) def preprocess_cirrhosis(df): """处理肝硬化数据集中的高基数特征,转为低基数类别变量""" # 1. 胆固醇(Cholesterol):医学标准分箱(mg/dL) # 正常:<200;边缘升高:200-239;升高:≥240(参考临床标准) # df['Cholesterol_bin'] = pd.cut( # df['Cholesterol'], # bins=[0, 200, 240, 1000], # labels=['正常', '临界高值', '高胆固醇血症'] # ) # 2. 胆红素(Bilirubin):反映肝脏排泄功能(mg/dL) # 正常:<1.2;轻度升高:1.2-3.0;显著升高:>3.0 df['Bilirubin_bin'] = pd.cut( df['Bilirubin'], bins=[-np.inf, 1.2, 3.0, np.inf], labels=['正常', '轻度升高', '显著升高'] ) # 3. 白蛋白(Albumin):肝脏合成功能指标(g/dL) # 正常:3.5-5.0;降低:<3.5(肝硬化典型表现) df['Albumin_bin'] = pd.cut( df['Albumin'], bins=[-np.inf, 3.5, 5.0, np.inf], labels=['降低', '正常', '升高'] # 升高临床意义较小,合并为一类 ) # 4. 铜(Copper):尿铜排泄(μg/天) # 正常:<50;升高:≥50(肝豆状核变性指标) df['Copper_bin'] = pd.cut( df['Copper'], bins=[-np.inf, 50, np.inf], labels=['正常', '升高'] ) # 5. 碱性磷酸酶(Alk_Phos):肝胆疾病指标(单位/升) # 正常范围:40-150;升高:>150 df['Alk_Phos_bin'] = pd.cut( df['Alk_Phos'], bins=[-np.inf, 150, np.inf], labels=['正常', '升高'] ) # 6. 转氨酶(SGOT):肝细胞损伤指标(单位/毫升) # 正常:<40;升高:≥40 df['SGOT_bin'] = pd.cut( df['SGOT'], bins=[-np.inf, 40, np.inf], labels=['正常', '升高'] ) # 7. 甘油三酯(Tryglicerides):血脂指标(mg/dL) # 正常:<150;升高:≥150 df['Tryglicerides_bin'] = pd.cut( df['Tryglicerides'], bins=[-np.inf, 150, np.inf], labels=['正常', '升高'] ) # 8. 血小板(Platelets):肝硬化脾功能亢进指标(×10^9/L) # 正常:150-450;减少:<150 df['Platelets_bin'] = pd.cut( df['Platelets'], bins=[-np.inf, 150, np.inf], labels=['减少', '正常'] ) # 9. 凝血酶原时间(Prothrombin):肝脏合成功能(秒) # 正常:11-13;延长:>13 df['Prothrombin_bin'] = pd.cut( df['Prothrombin'], bins=[-np.inf, 13, np.inf], labels=['正常', '延长'] ) # 移除原始高基数变量,保留离散化后的变量 df = df.drop( columns=['Copper', 'Alk_Phos', 'SGOT', 'Tryglicerides', 'Platelets', 'Prothrombin'], errors='ignore' ) return df df_stroke['glucose_bin'] = pd.cut( df_stroke['avg_glucose_level'], bins=[0, 100, 140, 200, 1000], labels=['正常', '偏高', '糖尿病前期', '糖尿病'] ) # 预处理cirrhosis(含离散化+类型转换) df_cirrhosis = preprocess_cirrhosis(df_cirrhosis) def preprocess_heart(df): """处理心脏病数据集中的高基数特征,转为低基数类别变量""" # 2. 静息血压(RestingBP):按高血压指南分箱 # 正常:<120;升高前期:120-129;1级高血压:130-139;2级高血压:≥140 df['RestingBP_bin'] = pd.cut( df['RestingBP'], bins=[0, 120, 130, 140, 300], labels=['正常', '升高前期', '1级高血压', '2级高血压'] ) # 3. 胆固醇(Cholesterol):按血脂异常标准分箱 # 正常:<200;临界高值:200-239;高胆固醇血症:≥240 # df['Cholesterol_bin'] = pd.cut( # df['Cholesterol'], # bins=[0, 200, 240, 1000], # labels=['正常', '临界高值', '高胆固醇血症'] # ) # 4. 最大心率(MaxHR):按年龄预测最大心率百分比分箱 # 计算预测最大心率 = 220 - 年龄 df['MaxHR_pct'] = df['MaxHR'] / (220 - df['Age']) df['MaxHR_bin'] = pd.cut( df['MaxHR_pct'], bins=[0, 0.6, 0.85, 1.0, 2.0], labels=['低(<60%)', '中(60-85%)', '高(85-100%)', '极高(>100%)'] ) df.drop(columns=['MaxHR_pct'], inplace=True) # 删除临时计算列 # 5. ST段压低(Oldpeak):反映心肌缺血程度 # 无压低:≤0;轻度压低:0-1;中度压低:1-2;严重压低:>2 df['Oldpeak_bin'] = pd.cut( df['Oldpeak'], bins=[-0.1, 0, 1, 2, 10.0], labels=['无压低', '轻度压低', '中度压低', '严重压低'] ) # 移除原始高基数变量,保留离散化后的变量 df = df.drop( columns=['RestingBP','MaxHR', 'Oldpeak'], errors='ignore' ) return df df_heart = preprocess_heart(df_heart) # 将目标变量转为分类类型(确保pgmpy能处理) df_heart['HeartDisease'] = df_heart['HeartDisease'].astype('category') df_stroke['stroke'] = df_stroke['stroke'].astype('category') df_cirrhosis['Stage'] = df_cirrhosis['Stage'].astype('category') def discretize_age_uniform(df, age_col='Age'): """ 为三个数据集统一年龄分箱,用0-4数字标签,覆盖0.05~82岁所有范围 分箱逻辑:按20年一个区间,兼顾医学年龄分组和数据覆盖 标签:0-4(数字越小表示年龄越小) """ df['Age_bin'] = pd.cut( df[age_col], bins=[-0.1, 19, 39, 59, 79, 120], # 覆盖0.05~82岁所有数据 labels=[0, 1, 2, 3, 4], # 数字标签(0:儿童青少年;1:青年;2:中年;3:老年;4:高龄) include_lowest=True # 包含最小值(0.05岁) ) # 检查分箱后的数据分布(确保无空区间) print(f"{df.shape[0]}条数据的年龄分箱分布:") print(df['Age_bin'].value_counts().sort_index()) # 按0-4排序输出 return df df_heart = discretize_age_uniform(df_heart) # 心脏病(28~77岁) df_stroke = discretize_age_uniform(df_stroke) # 中风(0.05~82岁) df_cirrhosis = discretize_age_uniform(df_cirrhosis) # 肝硬化(26~78岁) # 分箱后删除原始Age列,保留分箱列(数字标签) df_heart.drop(columns=['Age'], inplace=True) df_stroke.drop(columns=['Age'], inplace=True) df_cirrhosis.drop(columns=['Age'], inplace=True) def discretize_cholesterol(df, cholesterol_col='Cholesterol'): """ 胆固醇分箱:统一标准,标签0-1-2,覆盖两个数据集的胆固醇范围 分箱逻辑(医学标准): - 0: 正常(<200 mg/dL) - 1: 临界高值(200-239 mg/dL) - 2: 升高(≥240 mg/dL) """ if cholesterol_col not in df.columns: print("数据集中无胆固醇列,跳过分箱") return df df['Cholesterol_bin'] = pd.cut( df[cholesterol_col], bins=[-1, 199, 239, 10000], # 覆盖两个数据集的胆固醇范围(最高达3e6,设10000足够) labels=[0, 1, 2], # 数字标签(0-正常,1-临界,2-升高) include_lowest=True ) # 验证分箱分布(确保无空箱) print(f"胆固醇分箱分布(标签0-1-2):") print(df['Cholesterol_bin'].value_counts().sort_index()) # 按0-1-2排序 # 删除原始胆固醇列,保留分箱列 df.drop(columns=[cholesterol_col], inplace=True, errors='ignore') return df df_heart = discretize_cholesterol(df_heart, cholesterol_col='Cholesterol') df_cirrhosis = discretize_cholesterol(df_cirrhosis, cholesterol_col='Cholesterol') def discretize_stroke_continuous(df): # bmi分箱(按WHO标准) df['bmi_bin'] = pd.cut( df['bmi'], bins=[-1, 18.5, 24, 28, 100], labels=['偏瘦', '正常', '超重', '肥胖'] ) # 血糖分箱(复用之前的逻辑) df['glucose_bin'] = pd.cut( df['avg_glucose_level'], bins=[0, 100, 140, 200, 1000], labels=['正常', '偏高', '糖尿病前期', '糖尿病'] ) df.drop(columns=['bmi', 'avg_glucose_level'], inplace=True) return df df_stroke = discretize_stroke_continuous(df_stroke) # inner_join = pd.merge(df_heart, df_stroke, on=['Age']) print(df_heart) print(df_cirrhosis) print(df_stroke) # 在所有预处理后添加强制去NaN def drop_or_fill_nan(df): # 先尝试填充分类变量的NaN(用众数) for col in df.columns: if df[col].isna().any(): if df[col].dtype == 'category' or df[col].dtype == 'object': df[col] = df[col].fillna(df[col].mode()[0]) else: df[col] = df[col].fillna(df[col].median()) # 若仍有NaN,直接删除(确保数据干净) df = df.dropna() print(f"处理后的数据形状:{df.shape}(无NaN)") return df df_heart = drop_or_fill_nan(df_heart) df_stroke = drop_or_fill_nan(df_stroke) df_cirrhosis = drop_or_fill_nan(df_cirrhosis) # 心脏病:替换Oldpeak_bin、RestingBP_bin等中文标签 def replace_heart_labels(df): # Oldpeak_bin:0-3(无→轻→中→重) df['Oldpeak_bin'] = df['Oldpeak_bin'].replace( {'无压低':0, '轻度压低':1, '中度压低':2, '严重压低':3} ).astype(int) # RestingBP_bin:0-3(正常→升高前期→1级→2级) df['RestingBP_bin'] = df['RestingBP_bin'].replace( {'正常':0, '升高前期':1, '1级高血压':2, '2级高血压':3} ).astype(int) # ST_Slope:0-2(Down→Flat→Up) df['ST_Slope'] = df['ST_Slope'].replace( {'Down':0, 'Flat':1, 'Up':2} ).astype(int) # ChestPainType:0-3(ASY→ATA→NAP→TA) df['ChestPainType'] = df['ChestPainType'].replace( {'ASY':0, 'ATA':1, 'NAP':2, 'TA':3} ).astype(int) return df # 中风:替换glucose_bin、bmi_bin等 def replace_stroke_labels(df): df['glucose_bin'] = df['glucose_bin'].replace( {'正常':0, '偏高':1, '糖尿病前期':2, '糖尿病':3} ).astype(int) df['bmi_bin'] = df['bmi_bin'].replace( {'偏瘦':0, '正常':1, '超重':2, '肥胖':3} ).astype(int) df['smoking_status'] = df['smoking_status'].replace( {'never smoked':0, 'formerly smoked':1, 'smokes':2, 'Unknown':3} ).astype(int) return df # 肝硬化:替换Bilirubin_bin等 def replace_cirrhosis_labels(df): df['Bilirubin_bin'] = df['Bilirubin_bin'].replace( {'正常':0, '轻度升高':1, '显著升高':2} ).astype(int) df['Albumin_bin'] = df['Albumin_bin'].replace( {'降低':0, '正常':1, '升高':2} ).astype(int) # 其他标签类似替换为0-1-2 return df # 应用替换 df_heart = replace_heart_labels(df_heart) df_stroke = replace_stroke_labels(df_stroke) df_cirrhosis = replace_cirrhosis_labels(df_cirrhosis) #---------------------------------------------------------------------------------------------------- def build_bayesian_network(data, file_name, shared_variables=['age', 'gender'], # 保持参数名一致 local_shared_vars=None, # 新增局部共享变量参数 included_features=None, custom_edges=None, forbidden_edges=None): """为单个数据集构建贝叶斯网络模型,支持多个共享变量和自定义先验知识""" if data is None or data.empty: print(f"无有效数据,无法为 {file_name} 构建模型") return None # 将共享变量名统一转为小写(便于匹配) shared_variables = [var.lower() for var in shared_variables] # 如果指定了要包含的特征,则筛选数据 if included_features: # 确保所有共享变量被包含 for var in shared_variables: # 查找数据中匹配的列名(不区分大小写) matched_col = next((col for col in data.columns if col.lower() == var), None) if matched_col and matched_col not in included_features: included_features.append(matched_col) data = data[included_features] # 定义网络结构 edges = [] # 为每个共享变量添加边 # for shared_var in shared_variables: # # 查找数据中匹配的列名 # matched_col = next((col for col in data.columns if col.lower() == shared_var), None) # if matched_col: # for feature in data.columns: # if feature != matched_col: # edges.append((matched_col, feature)) # 共享变量→其他特征 # 原代码中共享变量生成边的部分修改为: for shared_var in shared_variables: matched_col = next((col for col in data.columns if col.lower() == shared_var), None) if matched_col: # 目标变量匹配时忽略大小写 target_vars = [col for col in data.columns if col.lower() in ['stroke', 'heartdisease']] # 修正为小写匹配 for feature in target_vars: if feature != matched_col and (matched_col, feature) not in edges: edges.append((matched_col, feature)) # 强制生成共享变量→目标变量的边 # 添加自定义边(领域知识) if custom_edges: edges.extend(custom_edges) # 移除禁止的边(领域知识) if forbidden_edges: edges = [edge for edge in edges if edge not in forbidden_edges] # 创建贝叶斯网络 model = BayesianNetwork(edges) # 使用最大似然估计器学习参数 model.fit(data, estimator=BayesianEstimator, prior_type = "BDeu", equivalent_sample_size = 10) print(f"已为 {file_name} 构建贝叶斯网络") return model # 可视化贝叶斯网络 def visualize_network(model, file_name): """ 可视化贝叶斯网络结构,增强鲁棒性处理各种布局异常 """ if model is None: print(f"警告: {file_name} 模型为空,无法可视化") return # 创建图的副本并转为无向图(简化布局计算) G = model.to_undirected() if hasattr(model, 'to_undirected') else model.copy() # 严格过滤无效边 valid_edges = [] for u, v in G.edges(): if u != v: # 排除自循环边 valid_edges.append((u, v)) # 清除无效边并检查是否还有剩余边 G.remove_edges_from(list(G.edges())) G.add_edges_from(valid_edges) if not G.edges(): print(f"错误: {file_name} 网络中没有有效边(可能所有边都是自循环),无法可视化") return # 尝试多种布局算法,按优先级选择 try: # 优先使用力导向布局(适合稀疏图) pos = nx.spring_layout(G, k=0.3, iterations=100, seed=42) except: try: # 备选:Kawai布局(适合密集图) pos = nx.kamada_kawai_layout(G, seed=42) except: try: # 备选:圆形布局 pos = nx.circular_layout(G) except: # 最后的备选:随机布局 pos = nx.random_layout(G, seed=42) print(f"警告: {file_name} 网络使用随机布局,可能效果不佳") # 检查节点位置是否有重叠(距离小于阈值) MIN_DISTANCE = 0.01 positions = list(pos.values()) has_overlap = False for i in range(len(positions)): for j in range(i + 1, len(positions)): dist = np.sqrt(((positions[i][0] - positions[j][0]) ** 2) + ((positions[i][1] - positions[j][1]) ** 2)) if dist < MIN_DISTANCE: has_overlap = True break if has_overlap: break # 如果有重叠,添加微小扰动 if has_overlap: print(f"警告: {file_name} 网络节点位置存在重叠,添加随机扰动") for node in pos: pos[node] = ( pos[node][0] + np.random.uniform(-0.02, 0.02), pos[node][1] + np.random.uniform(-0.02, 0.02) ) # 创建图形 plt.figure(figsize=(14, 12)) # 增大图形尺寸 # 绘制节点 nx.draw_networkx_nodes( G, pos, node_size=2800, # 增大节点尺寸 node_color='skyblue', alpha=0.8, edgecolors='black', # 添加节点边框 linewidths=1.0 ) # 绘制边(分批次处理,捕获异常) edges_to_draw = list(G.edges()) successful_edges = [] for edge in edges_to_draw: try: nx.draw_networkx_edges( G, pos, edgelist=[edge], arrows=True, arrowsize=20, width=1.5, alpha=0.7, edge_color='gray' ) successful_edges.append(edge) except Exception as e: print(f"警告: 无法绘制边 {edge}: {e}") if len(successful_edges) == 0: print(f"错误: {file_name} 网络中没有成功绘制的边") plt.close() return # 绘制节点标签 nx.draw_networkx_labels( G, pos, font_size=10, font_weight='bold', font_family='SimHei', # 确保中文显示 horizontalalignment='center', verticalalignment='center' ) # 设置标题和保存图形 plt.title(f'{file_name} 的贝叶斯网络结构', fontsize=14) plt.axis('off') # 关闭坐标轴 plt.tight_layout() # 调整布局 try: plt.savefig(f'{file_name}_bayesian_network.png', dpi=300, bbox_inches='tight') print(f"已成功保存 {file_name} 网络结构图") except Exception as e: print(f"保存图像时出错: {e}") plt.close() # 关闭图形以释放内存 # 执行跨网络推理 def cross_network_inference(models, file_names, global_shared_vars=['age', 'gender'], local_shared_vars=None, evidence=None): """基于共享变量进行跨网络推理,支持全局和局部共享变量""" results = {} if evidence is None: evidence = {'age': 50, 'gender': 'Male'} # 默认全局证据值 for model, file_name in zip(models, file_names): if model is None: continue # 映射全局证据中的变量名到模型中的实际列名 model_evidence = {} for var, value in evidence.items(): if var.lower() in [v.lower() for v in global_shared_vars]: matched_col = next((col for col in model.nodes() if col.lower() == var.lower()), None) if matched_col: model_evidence[matched_col] = value # 添加局部共享变量的证据(如果有) if local_shared_vars: for local_var_name, local_var_col in local_shared_vars.items(): if local_var_name in evidence and local_var_col in model.nodes(): model_evidence[local_var_col] = evidence[local_var_name] infer = VariableElimination(model) # 对每个模型中的关键变量进行推理 key_variables = [var for var in model.nodes() if var not in model_evidence] for var in key_variables: try: result = infer.query(variables=[var], evidence=model_evidence) results[f"{file_name}_{var}"] = result print(f"\n{file_name} 中,已知 {model_evidence} 时,{var} 的概率分布:") print(result) except Exception as e: print(f"\n{file_name} 推理 {var} 时错误: {e}") return results def merge_rare_classes(df, target_variable, min_samples=2): """ 合并样本数少于阈值的稀有类别 :param df: 数据集 :param target_variable: 目标变量列名 :param min_samples: 最小样本数阈值 :return: 处理后的数据集 """ if target_variable not in df.columns: return df # 统计每个类别的样本数 class_counts = df[target_variable].value_counts() rare_classes = class_counts[class_counts < min_samples].index.tolist() if not rare_classes: return df # 没有稀有类别,直接返回 print(f"检测到稀有类别: {rare_classes},样本数阈值: {min_samples}") # 创建映射:稀有类别→合并到的目标类别 # 策略:合并到最接近的类别(基于类别名称的数值或字母顺序) sorted_classes = sorted(df[target_variable].unique()) class_mapping = {} for rare_class in rare_classes: # 找到最接近的有效类别 idx = sorted_classes.index(rare_class) # 尝试向前或向后查找有效类别 for direction in [-1, 1]: new_idx = idx + direction if 0 <= new_idx < len(sorted_classes) and sorted_classes[new_idx] not in rare_classes: class_mapping[rare_class] = sorted_classes[new_idx] break # 应用映射 if class_mapping: print(f"类别合并映射: {class_mapping}") df[target_variable] = df[target_variable].replace(class_mapping) return df def evaluate_model(model, test_data, target_variable, file_name): """ 综合评估贝叶斯网络模型:预测性能 + 拟合度指标 :param model: 训练好的贝叶斯网络(pgmpy的BayesianNetwork对象) :param test_data: 预处理后的测试数据集(pd.DataFrame) :param target_variable: 目标预测变量(如"HeartDisease"、"stroke") :param file_name: 数据集名称(用于日志输出) :return: 评估结果字典 """ results = {} if model is None or test_data.empty: print(f"[{file_name}] 模型或测试数据为空,跳过评估") return results # ---------------------- # 1. 模型拟合度指标(BIC、对数似然) # ---------------------- try: bic_score = BicScore(test_data).score(model) # 越小越好(平衡拟合与复杂度) ll_score = log_likelihood_score(model, test_data) # 越大越好(数据拟合度) results.update({ "bic_score": bic_score, "log_likelihood": ll_score }) except Exception as e: print(f"[{file_name}] 拟合度计算失败: {e}") bic_score = ll_score = None # ---------------------- # 2. 预测性能评估(分类任务) # ---------------------- if target_variable not in model.nodes() or target_variable not in test_data.columns: print(f"[{file_name}] 目标变量 {target_variable} 不在模型或测试数据中") return results # 分离特征和标签 X_test = test_data.drop(columns=[target_variable], errors='ignore') y_test = test_data[target_variable].dropna() # 过滤标签缺失值 X_test = X_test.loc[y_test.index] # 保持索引一致 if len(y_test) < 10: # 避免样本过少导致无意义评估 print(f"[{file_name}] 有效样本不足(仅{len(y_test)}条),跳过预测评估") return results infer = VariableElimination(model) y_pred = [] fail_count = 0 for idx, row in X_test.iterrows(): # 构建证据(忽略缺失值,贝叶斯网络支持边际化) evidence = {} for var in model.nodes(): if var == target_variable: continue val = row.get(var) if not pd.isna(val): evidence[var] = val # 推理目标变量的后验分布 try: query = infer.query(variables=[target_variable], evidence=evidence, show_progress=False) pred_class = query.argmax()[0] # 取概率最大的类别 y_pred.append(pred_class) except Exception as e: fail_count += 1 y_pred.append(None) # 标记推理失败的样本 # 过滤无效预测结果 valid_mask = [p is not None for p in y_pred] y_test_valid = y_test[valid_mask] y_pred_valid = [p for p in y_pred if p is not None] if len(y_test_valid) == 0: print(f"[{file_name}] 推理失败样本过多({fail_count}条),无有效预测结果") return results # 计算分类指标 try: accuracy = accuracy_score(y_test_valid, y_pred_valid) cm = confusion_matrix(y_test_valid, y_pred_valid) report = classification_report(y_test_valid, y_pred_valid, zero_division=0) results.update({ "accuracy": accuracy, "confusion_matrix": cm, "classification_report": report }) except Exception as e: print(f"[{file_name}] 分类指标计算失败: {e}") accuracy = cm = report = None # ---------------------- # 3. 输出评估结果 # ---------------------- print("\n" + "=" * 40) print(f"[{file_name}] 模型评估报告") print("=" * 40) if bic_score is not None: print(f"• BIC评分: {bic_score:.2f}(越小越好,平衡复杂度与拟合度)") print(f"• 对数似然: {ll_score:.2f}(越大越好,数据拟合度)") if accuracy is not None: print(f"• 预测准确率: {accuracy:.4f}") print(f"• 混淆矩阵:\n{cm}") print(f"• 分类报告:\n{report}") print(f"• 有效样本数: {len(y_test_valid)} / {len(test_data)}") print(f"• 推理失败数: {fail_count}") return results def print_model_cpds(model, file_name, top_n=3): """打印模型的前N个节点的CPD,验证是否有效""" if model is None: return print(f"\n[{file_name}] 模型CPD验证:") for i, node in enumerate(model.nodes()): if i >= top_n: break cpd = model.get_cpds(node) if cpd: print(f"\n节点 {node} 的CPD:") print(cpd) else: print(f"节点 {node} 无有效CPD!") # 主函数 - 支持自定义配置 def main(): file_names = ['heart', 'stroke', 'cirrhosis'] print('Main already') df_heart['HeartDisease'] = df_heart['HeartDisease'].astype('category') df_stroke['stroke'] = df_stroke['stroke'].astype('category') df_cirrhosis['Stage'] = df_cirrhosis['Stage'].astype('category') target_mapping = { 'heart': 'HeartDisease', 'stroke': 'stroke', 'cirrhosis': 'Stage' } # 加载数据 datasets = [df_heart, df_stroke, df_cirrhosis] processed_datasets = [] for data, name in zip(datasets, file_names): target_var = target_mapping.get(name) if not target_var or target_var not in data.columns: processed_datasets.append(data) continue print(f"\n处理 {name} 数据集中的稀有类别(目标变量: {target_var})") # 使用合并稀有类别的方法(推荐) processed_data = merge_rare_classes(data, target_var, min_samples=5) # 确保目标变量是分类类型 processed_data[target_var] = processed_data[target_var].astype('category') processed_datasets.append(processed_data) train_datasets = [] test_datasets = [] for data in processed_datasets: train, test = train_test_split(data, test_size=0.2, random_state=42) train_datasets.append(train) test_datasets.append(test) # 为每个数据集定义自定义配置 # disease_configs = [ # { # "disease_name": "心脏病", # "local_shared_vars": {"cholesterol": "Cholesterol_bin"}, # "included_features": [ # "Age_bin", "Sex", "ChestPainType", "RestingBP_bin", "Cholesterol_bin", # "FastingBS", "ExerciseAngina", "Oldpeak_bin", "ST_Slope", "HeartDisease" # ], # "custom_edges": [ # # 核心直接风险因素 # ("ChestPainType", "HeartDisease"), # ("ST_Slope", "HeartDisease"), # ("Oldpeak_bin", "HeartDisease"), # ("Cholesterol_bin", "HeartDisease"), # ("RestingBP_bin", "HeartDisease"), # ("ExerciseAngina", "HeartDisease"), # ("Age_bin", "HeartDisease"), # # # 关键间接路径 # ("FastingBS", "Cholesterol_bin"), # 高血糖影响胆固醇 # ("Age_bin", "RestingBP_bin"), # 年龄影响血压 # ], # "forbidden_edges": [ # ("Sex", "HeartDisease"), # 性别通过其他因素间接影响 # ("HeartDisease", "*"), # 避免反向因果 # ("FastingBS", "HeartDisease"), # 血糖主要通过胆固醇间接影响 # ] # }, # { # "disease_name": "中风", # "local_shared_vars": {}, # "included_features": [ # "Age_bin", "Sex", "hypertension", "heart_disease", # "glucose_bin", "bmi_bin", "smoking_status", "stroke" # ], # "custom_edges": [ # # 核心直接风险因素 # ("hypertension", "stroke"), # ("heart_disease", "stroke"), # ("Age_bin", "stroke"), # ("glucose_bin", "stroke"), # # # 关键间接路径 # ("smoking_status", "heart_disease"), # 吸烟导致心脏病 # ("bmi_bin", "hypertension"), # 肥胖导致高血压 # ("bmi_bin", "glucose_bin"), # 肥胖影响血糖 # ], # "forbidden_edges": [ # ("Sex", "stroke"), # 性别通过其他因素间接影响 # ("stroke", "*"), # 避免反向因果 # ("bmi_bin", "stroke"), # BMI主要通过高血压和血糖间接影响 # ] # }, # { # "disease_name": "肝硬化", # "local_shared_vars": {"cholesterol": "Cholesterol_bin"}, # "included_features": [ # "Age_bin", "Sex", "Ascites", "Hepatomegaly", "Spiders", # "Edema", "Bilirubin_bin", "Albumin_bin", # "SGOT_bin", "Platelets_bin", "Prothrombin_bin", "Stage" # ], # "custom_edges": [ # # 肝功能指标→疾病阶段 # ("Bilirubin_bin", "Stage"), # 胆红素升高→肝硬化进展 # ("Albumin_bin", "Stage"), # 白蛋白降低→肝硬化进展 # ("Prothrombin_bin", "Stage"), # 凝血酶原时间延长→肝硬化 # ("Platelets_bin", "Stage"), # 血小板减少→肝硬化 # # # 体征→疾病阶段 # ("Ascites", "Stage"), # 腹水→肝硬化晚期 # ("Hepatomegaly", "Stage"), # 肝肿大→肝硬化 # # # 间接关联 # ("Age_bin", "Stage"), # 年龄→疾病进展 # ("Ascites", "Edema"), # 腹水→水肿 # ("Albumin_bin", "Ascites"), # 低白蛋白→腹水 # ], # "forbidden_edges": [ # ("ID", "*"), # ("Status", "*"), # ("Drug", "Stage"), # ("Sex", "Stage"), # 性别不直接影响肝硬化阶段 # ("Stage", "*"), # 避免反向因果 # ] # } # ] disease_configs = [ { "disease_name": "心脏病", "local_shared_vars": {"cholesterol": "Cholesterol_bin"}, "included_features": [ "Age_bin", "ChestPainType", "ST_Slope", "RestingBP_bin", # 4个核心父节点 "HeartDisease" # 目标变量 ], "custom_edges": [ # 仅保留4个直接影响心脏病的核心父节点 ("ChestPainType", "HeartDisease"), # 胸痛类型(最核心症状) ("ST_Slope", "HeartDisease"), # ST段斜率(诊断金标准) ("RestingBP_bin", "HeartDisease"), # 血压(直接风险) ("Age_bin", "HeartDisease") # 年龄(基础风险) ], "forbidden_edges": [] # 禁用禁止边,避免误删核心关联 }, { "disease_name": "中风", "local_shared_vars": {}, "included_features": [ "hypertension", "glucose_bin", "Age_bin", "heart_disease", # 4个核心父节点 "stroke" # 目标变量 ], "custom_edges": [ # 仅保留4个直接影响中风的核心父节点 ("hypertension", "stroke"), # 高血压(头号风险) ("glucose_bin", "stroke"), # 高血糖(独立风险) ("heart_disease", "stroke"), # 心脏病史(血栓风险) ("Age_bin", "stroke") # 年龄(累积风险) ], "forbidden_edges": [] }, { "disease_name": "肝硬化", "local_shared_vars": {"cholesterol": "Cholesterol_bin"}, "included_features": [ "Bilirubin_bin", "Albumin_bin", "Age_bin", "Ascites", # 4个核心父节点 "Stage" # 目标变量 ], "custom_edges": [ # 仅保留4个直接影响肝硬化阶段的核心父节点 ("Bilirubin_bin", "Stage"), # 胆红素(肝脏排泄功能) ("Albumin_bin", "Stage"), # 白蛋白(肝脏合成功能) ("Ascites", "Stage"), # 腹水(肝硬化晚期标志) ("Age_bin", "Stage") # 年龄(病程累积) ], "forbidden_edges": [] } ] print('Config already') # 3. 构建模型(传递全局共享变量和局部共享变量) models = [] for train_data, name, config in zip(train_datasets, file_names, disease_configs): model = build_bayesian_network( data=train_data, file_name=name, shared_variables=["age", "gender"], local_shared_vars=config["local_shared_vars"], included_features=config["included_features"], custom_edges=config["custom_edges"], forbidden_edges=config["forbidden_edges"] ) print_model_cpds(model, name) models.append(model) # 4. 可视化网络 for model, name in zip(models, file_names): visualize_network(model, name) for model, test_data, name, config in zip(models, test_datasets, file_names, disease_configs): # 根据疾病类型确定目标变量 target_mapping = { 'heart': 'HeartDisease', 'stroke': 'stroke', 'cirrhosis': 'Stage' } target_var = target_mapping.get(name) if not target_var: print(f"[{name}] 未知目标变量,跳过验证") continue # 执行评估 evaluate_model(model, test_data, target_var, name) # # 5. 跨网络推理(传递共享变量映射,确保证据匹配) # # 注意:证据中的变量名需与配置中的“逻辑名”一致,而非原始列名 # evidence = { # "age": 60, # 全局共享变量(年龄) # "gender": "男", # 全局共享变量(性别) # "cholesterol": 240 # 局部共享变量(胆固醇,逻辑名) # } # # cross_network_inference( # models=models, # file_names=file_names, # global_shared_vars=["age", "gender"], # 全局共享变量 # local_shared_vars={"cholesterol": "Cholesterol"}, # 局部共享变量映射(逻辑名→实际列名) # evidence=evidence # ) if __name__ == "__main__": main() 什么情况,你帮我看看,怎么解决

# 导入所有必要的库 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, roc_auc_score, roc_curve, confusion_matrix, auc import lightgbm as lgb import warnings # 设置可视化风格 sns.set_style("whitegrid") # 设置背景为白色网格 plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置绘图字体为中文黑体 plt.rcParams['axes.unicode_minus'] = False # 使用ASCII字符U+002D表示负号 # 读取数据部分 try: # 读取数据文件(文件地址) stroke_dataset = pd.read_csv(r'C:\Users\yuanx\Desktop\F题 疾病的预测与大数据分析\附件\stroke.csv') # 中风数据集 heart_dataset = pd.read_csv(r'C:\Users\yuanx\Desktop\F题 疾病的预测与大数据分析\附件\heart.csv') # 心脏病数据集 cirrhosis_dataset = pd.read_csv(r'C:\Users\yuanx\Desktop\F题 疾病的预测与大数据分析\附件\cirrhosis.csv') # 肝硬化数据集 except FileNotFoundError: # 如果文件没有找到,提示错误 print("请确保 stroke.csv, heart.csv, 和 cirrhosis.csv 文件在当前目录下。") # 输出错误提示 exit() # 终止程序运行 # 数据预处理和Exploratory Data Analysis(探索性数据分析) def preprocess_and_analyze(dataset, target_col, dataset_name): """ 一个通用的函数来预处理和分析每个数据集 参数: dataset:待处理的数据集 target_col:目标列的名称 dataset_name:数据集的名称(用于判断) """ # 对不同的数据集进行清洗 if dataset_name == 'stroke': # 如果是中风数据集,进行相应的清洗操作 if 'id' in dataset.columns: # 如果存在'id'列,删除 dataset.drop('id', axis=1, inplace=True) # axis指定列,inplace在原数据框上修改 if 'gender' in dataset.columns and 'Other' in dataset['gender'].unique(): # 如果性别列中有 'Other',删除此行 dataset = dataset[dataset['gender'] != 'Other'].copy() # 创建新的数据框副本,未直接修改原数据框 if 'bmi' in dataset.columns: # 对BMI列进行处理 bmi_median = dataset['bmi'].median() # 计算中位数 dataset['bmi'].fillna(bmi_median, inplace=True) # 填充缺失值为中位数 elif dataset_name == 'heart': # 如果是心脏病数据集,进行相应的清洗操作 cols_clean = ['RestingBP', 'Cholesterol'] # 需清理的列名的集合 for col in cols_clean: # 遍历并判断是否包含 if col in dataset.columns: dataset[col] = dataset[col].replace(0, np.nan) # 将0替换为NaN median = dataset[col].median() # 计算中位数 dataset[col].fillna(median, inplace=True) # 填充缺失值为中位数 elif dataset_name == 'cirrhosis': # 如果是肝硬化数据集,进行相应的清洗操作 if 'ID' in dataset.columns: # 如果存在'ID'列,删除 dataset.drop('ID', axis=1, inplace=True) # axis指定列,inplace在原数据框上修改 dataset.replace(['NA', 'N/A'], np.nan, inplace=True) # 替换 'NA' 和 'N/A' 为NaN # 将特定列转换为数值类型 numeric_type_conversion = ['Cholesterol', 'Tryglicerides', 'Platelets', 'Prothrombin', 'Stage', 'SGOT', 'Alk_Phos'] # 需要转化为数值类型的列名的列表 for col in numeric_type_conversion: # 遍历并判断是否包含 if col in dataset.columns: dataset[col] = pd.to_numeric(dataset[col], errors='coerce') # 强制转换为数值,无法转换的变为NaN # 填充缺失值 num_cols = dataset.select_dtypes(include=np.number).columns # 获取数值型列 for col in num_cols: dataset[col].fillna(dataset[col].median(), inplace=True) # 用中位数填充数值列的缺失值 cat_cols = dataset.select_dtypes(include='object').columns # 获取类别型列 for col in cat_cols: if col != 'Status': # 目标列 'Status' 不处理 dataset[col].fillna(dataset[col].mode()[0], inplace=True) # 用出现次数最多的值填充缺失值 if 'Status' in dataset.columns: # 将映射结果赋值给目标列 target_col dataset[target_col] = dataset['Status'].map({'C': 0, 'CL': 0, 'D': 1}) # 使用 .map() 函数对 'Status' 列的值进行转换 # 如果目标列不是Status本身,则删除Status if target_col != 'Status': dataset.drop('Status', axis=1, inplace=True) return dataset #可视化预测模型 def tree_model(x, y, dataset_name): scaler = StandardScaler() # 使用StandardScaler对数值特征进行标准化处理 x_scaled = scaler.fit_transform(x) # 训练并转换数据 x_train, x_test, y_train, y_test = train_test_split(x_scaled, y, test_size=0.2, random_state=42) # 划分训练集和测试集,8:2 model = RandomForestClassifier(class_weight='balanced', random_state=42) # 创建随机森林分类模型 model.fit(x_train, y_train) # 在训练集上训练模型 y_pred = model.predict(x_test) # 在测试集上进行预测 y_prob = model.predict_proba(x_test)[:, 1] # 获取正类概率 # ROC曲线与AUC评估 # 计算假正率(FPR)和真正率(TPR) fpr, tpr, thresholds = roc_curve(y_test, y_prob) # 计算AUC值(ROC曲线下面积) roc_auc = auc(fpr, tpr) # 绘制ROC曲线 plt.figure(figsize=(6, 5)) plt.plot(fpr, tpr, label=f"ROC Curve (AUC = {roc_auc:.2f})") # 绘制ROC曲线 plt.plot([0, 1], [0, 1], 'k--') # 绘制随机猜测的对角线 plt.xlabel("False Positive Rate") # X轴:假正率 plt.ylabel("True Positive Rate") # Y轴:真正率 plt.title(dataset_name+"随机森林的ROC曲线") # 图表标题 plt.legend(loc="lower right") # 显示AUC值的图例 plt.tight_layout() # 调整图表布局 plt.show() def build_predictive_model(dataset, target_col, dataset_name): """ 构建、训练、评估和可视化预测模型。 参数: dataset: 输入的数据框 target_col: 目标列(预测的标签) dataset_name: 数据集的名称,用于图表标题和日志 """ if dataset_name == 'stroke': dataset_encoded = dataset.copy() x = dataset_encoded.drop(['stroke','gender','heart_disease','ever_married','work_type','Residence_type','smoking_status'], axis=1) # 删除无关列,提取特征x y = dataset_encoded['stroke'] # 提取目标y return tree_model(x, y, dataset_name) elif dataset_name == 'heart': # 类别变量独热编码 dataset_encoded = dataset.copy() categorical_cols = ['ChestPainType','ST_Slope'] dataset_encoded = pd.get_dummies(dataset_encoded, columns=categorical_cols, drop_first=True) x = dataset_encoded.drop(['HeartDisease','Sex','Cholesterol','FastingBS','RestingECG','ExerciseAngina'], axis=1) # 删除无关列,提取特征x y = dataset_encoded['HeartDisease'] # 提取目标y return tree_model(x, y, dataset_name) # 1. 加载并预处理数据 processed_stroke_dataset = preprocess_and_analyze(stroke_dataset.copy(), 'stroke', 'stroke') # 中风数据集 processed_heart_dataset = preprocess_and_analyze(heart_dataset.copy(), 'HeartDisease', 'heart') # 心脏病数据集 processed_cirrhosis_dataset = preprocess_and_analyze(cirrhosis_dataset.copy(), 'Status', 'cirrhosis') # 肝硬化数据集 # 2. 构建、训练和评估模型 stroke_model, all_stroke_models = build_predictive_model(processed_stroke_dataset, 'stroke', 'stroke') heart_model, all_heart_models = build_predictive_model(processed_heart_dataset, 'HeartDisease', 'heart') cirrhosis_model, all_cirrhosis_models = build_predictive_model(processed_cirrhosis_dataset, 'Is_Deceased', 'cirrhosis') 修改,使heart的图像输出

import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, confusion_matrix, roc_curve from sklearn.preprocessing import LabelEncoder, OneHotEncoder from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline import shap import warnings warnings.filterwarnings('ignore') # 设置中文显示 plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"] plt.rcParams['axes.unicode_minus'] = False # 1. 数据加载与预处理 def load_and_preprocess(disease): if disease == "stroke": df = pd.read_csv("stroke.csv") # 特征选择 features = ['age', 'hypertension', 'heart_disease', 'avg_glucose_level', 'bmi', 'smoking_status'] target = 'stroke' # 处理缺失值 df['bmi'].fillna(df['bmi'].median(), inplace=True) # 分类变量编码 cat_features = ['smoking_status'] elif disease == "heart": df = pd.read_csv("heart.csv") features = ['Age', 'ChestPainType', 'Cholesterol', 'MaxHR', 'ExerciseAngina', 'ST_Slope'] target = 'HeartDisease' # 处理缺失值 df['Cholesterol'].replace(0, df['Cholesterol'].median(), inplace=True) cat_features = ['ChestPainType', 'ExerciseAngina', 'ST_Slope'] elif disease == "cirrhosis": df = pd.read_csv("cirrhosis.csv") features = ['Bilirubin', 'Albumin', 'Prothrombin', 'Edema', 'Stage', 'Platelets'] target = 'Status' # 假设Status中'D'表示患病(需根据实际数据调整) # 处理缺失值 for col in features: if df[col].dtype == 'float64': df[col].fillna(df[col].median(), inplace=True) else: df[col].fillna(df[col].mode()[0], inplace=True) # 目标变量处理(将状态转为二分类:患病=1,否则=0) df[target] = df[target].apply(lambda x: 1 if x == 'D' else 0) cat_features = ['Edema', 'Stage'] # 划分特征与目标 X = df[features] y = df[target] # 编码分类特征 preprocessor = ColumnTransformer( transformers=[('cat', OneHotEncoder(drop='first'), cat_features)], remainder='passthrough' ) X_processed = preprocessor.fit_transform(X) # 划分训练集与测试集 X_train, X_test, y_train, y_test = train_test_split(X_processed, y, test_size=0.2, random_state=42) return X_train, X_test, y_train, y_test, preprocessor, features # 2. 训练随机森林模型 def train_rf(X_train, y_train): model = RandomForestClassifier(n_estimators=100, max_depth=8, random_state=42) model.fit(X_train, y_train) return model # 3. 模型评估 def evaluate_model(model, X_test, y_test, disease): y_pred = model.predict(X_test) y_prob = model.predict_proba(X_test)[:, 1] # 评估指标 metrics = { '准确率': accuracy_score(y_test, y_pred), '精确率': precision_score(y_test, y_pred), '召回率': recall_score(y_test, y_pred), 'F1分数': f1_score(y_test, y_pred), 'AUC': roc_auc_score(y_test, y_prob) } print(f"\n{disease}模型评估指标:") for k, v in metrics.items(): print(f"{k}: {v:.4f}") # 混淆矩阵可视化 cm = confusion_matrix(y_test, y_pred) plt.figure(figsize=(6, 4)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['未患病', '患病'], yticklabels=['未患病', '患病']) plt.xlabel('预测标签') plt.ylabel('真实标签') plt.title(f'{disease}模型混淆矩阵') plt.show() # ROC曲线 fpr, tpr, _ = roc_curve(y_test, y_prob) plt.figure(figsize=(6, 4)) plt.plot(fpr, tpr, label=f'AUC = {metrics["AUC"]:.4f}') plt.plot([0, 1], [0, 1], 'k--') plt.xlabel('假阳性率') plt.ylabel('真阳性率') plt.title(f'{disease}模型ROC曲线') plt.legend() plt.show() return y_pred, y_prob # 4. SHAP灵敏度分析 import matplotlib.pyplot as plt import numpy as np import shap def shap_analysis(model, X_train, X_test, features, disease, preprocessor): # 提取特征名称(处理编码后的特征) # 注意:确保preprocessor是已拟合的,且X_test是预处理后的数据 cat_features = [f for f in features if f in preprocessor.transformers_[0][2]] num_features = [f for f in features if f not in cat_features] ohe = preprocessor.named_transformers_['cat'] cat_names = ohe.get_feature_names_out(cat_features) # 独热编码后的特征名 feature_names = list(cat_names) + num_features # 合并类别特征和数值特征名 # SHAP值计算(关键修正:处理分类模型的多类别结构) explainer = shap.TreeExplainer(model) shap_values = explainer.shap_values(X_test) # 分类模型需指定目标类别(如二分类取正类,多分类按需选择) # 若模型是回归模型,shap_values是二维数组,无需此步骤 if isinstance(shap_values, list): # 分类模型返回列表(每个元素对应一个类别) # 假设关注第一个类别(可根据实际需求调整索引,如二分类常用1表示正类) target_class = 1 if len(shap_values) == 2 else 0 # 示例逻辑,按需修改 shap_values = shap_values[target_class] # 验证特征维度匹配(避免因预处理导致特征数不一致) assert X_test.shape[1] == len(feature_names), \ f"特征维度不匹配:X_test有{X_test.shape[1]}列,feature_names有{len(feature_names)}个名称" # 摘要图(全局特征重要性) plt.figure(figsize=(10, 6)) # 修正:明确传递特征名,并确保shap_values维度为(n_samples, n_features) shap.summary_plot(shap_values, X_test, feature_names=feature_names, plot_type="bar") plt.title(f'{disease}模型SHAP特征重要性') plt.tight_layout() # 防止标签重叠导致显示不全 plt.show() # 计算前3个最敏感特征 shap_sum = np.abs(shap_values).mean(0) # 各特征SHAP绝对值的均值 top3_idx = np.argsort(shap_sum)[-3:] # 取重要性最大的3个特征索引(升序排序后取最后3个) assert np.issubdtype(top3_idx.dtype, np.integer), "Indices must be integers" top3_idx = np.array(top3_idx, dtype=int).flatten() top3_features = [feature_names[i] for i in top3_idx[::-1]] # 反转索引以按重要性降序排列 print(f"{disease}模型最敏感的3个因素(降序):{top3_features}") return top3_features ##def shap_analysis(model, X_train, X_test, features, disease, preprocessor): ## # 提取特征名称(处理编码后的特征) ## cat_features = [f for f in features if f in preprocessor.transformers_[0][2]] ## num_features = [f for f in features if f not in cat_features] ## ohe = preprocessor.named_transformers_['cat'] ## cat_names = ohe.get_feature_names_out(cat_features) ## feature_names = list(cat_names) + num_features ## ## # SHAP值计算 ## explainer = shap.TreeExplainer(model) ## shap_values = explainer.shap_values(X_test) ## ## # 摘要图(全局特征重要性) ## plt.figure(figsize=(10, 6)) ## shap.summary_plot(shap_values, X_test, feature_names=feature_names, plot_type="bar") ## plt.title(f'{disease}模型SHAP特征重要性') ## plt.show() ## ## # 前3个最敏感特征 ## shap_sum = np.abs(shap_values).mean(0) ## assert np.issubdtype(top3_idx.dtype, np.integer), "Indices must be integers" ## top3_idx = np.array(top3_idx, dtype=int).flatten() ## top3_features = [feature_names[i] for i in top3_idx] ## print(f"{disease}模型最敏感的3个因素:{top3_features}") ## ## return top3_features # 5. 主函数 def main(): diseases = ["stroke", "heart", "cirrhosis"] results = {} for disease in diseases: print(f"\n===== {disease}预测模型 =====") X_train, X_test, y_train, y_test, preprocessor, features = load_and_preprocess(disease) model = train_rf(X_train, y_train) y_pred, y_prob = evaluate_model(model, X_test, y_test, disease) top3 = shap_analysis(model, X_train, X_test, features, disease, preprocessor) # 保存预测结果(示例:前10个样本) results[disease] = { '预测值(前10)': y_pred[:10], '预测概率(前10)': y_prob[:10], '最敏感因素': top3 } return results if __name__ == "__main__": results = main() 解释以上代码为何在绘制SHAP摘要图时,有横纵坐标但是除坐标外图中没有任何图,折线,并给出对相应代码的改进措施以及修正修改过后的代码

import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import tkinter as tk from tkinter import font from sklearn.model_selection import train_test_split from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score from sklearn.naive_bayes import GaussianNB from pgmpy.models import DiscreteBayesianNetwork from pgmpy.estimators import MaximumLikelihoodEstimator from pgmpy.inference import VariableElimination # ================= 中文支持初始化 ================= # def init_gui(): """启动 Tkinter GUI 界面(仅用于测试字体支持)""" root = tk.Tk() custom_font = font.Font(family="SimHei", size=12) label = tk.Label(root, text="贝叶斯模型评估界面", font=custom_font) label.pack() return root # 设置 Matplotlib 支持中文显示 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False # ================= 数据加载与预处理 ================= # def load_data(file_path): """加载 CSV 数据,并对 heart.csv 进行浮点列离散化""" data = pd.read_csv(file_path) if 'target' in data.columns: for col in data.select_dtypes(include=['float64']).columns: data[col] = pd.cut(data[col], bins=5, labels=[0, 1, 2, 3, 4]) return data # ================= 模型评估函数 ================= # def evaluate_model(y_true, y_pred, model_name): """计算并输出模型性能指标,并绘制混淆矩阵""" cm = confusion_matrix(y_true, y_pred) acc = accuracy_score(y_true, y_pred) prec = precision_score(y_true, y_pred, average='weighted') rec = recall_score(y_true, y_pred, average='weighted') f1 = f1_score(y_true, y_pred, average='weighted') print(f"\n{model_name} 模型评估结果:") print(f"准确率: {acc:.4f}") print(f"精确率: {prec:.4f}") print(f"召回率: {rec:.4f}") print(f"F1分数: {f1:.4f}") plt.figure(figsize=(8, 6)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') plt.xlabel('预测标签') plt.ylabel('真实标签') plt.title(f'{model_name} 混淆矩阵') plt.show() return acc, prec, rec, f1 # ================= 数据离散化处理 ================= # def discretize_continuous_features(data, continuous_vars, bins=5): """ 对指定的连续变量进行离散化处理 """ for var in continuous_vars: if var in data.columns: data[var] = pd.cut(data[var], bins=bins, labels=False) return data # ================= 贝叶斯网络构建 ================= # def build_heart_bayesian_network(data): """构建基于医学知识的心脏病贝叶斯网络结构""" model_structure = [ ('age', 'trestbps'), ('age', 'chol'), ('age', 'thalach'), ('sex', 'trestbps'), ('sex', 'chol'), ('cp', 'trestbps'), ('cp', 'chol'), ('trestbps', 'target'), ('chol', 'target'), ('thalach', 'target'), ('oldpeak', 'target'), ('slope', 'target'), ('ca', 'target'), ('thal', 'target'), ('fbs', 'chol'), ('fbs', 'target'), ('restecg', 'trestbps'), ('restecg', 'target'), ('exang', 'target') ] cols = data.columns.tolist() invalid_edges = [(u, v) for u, v in model_structure if u not in cols or v not in cols] if invalid_edges: raise ValueError(f"以下边包含不存在的节点: {invalid_edges}") model = DiscreteBayesianNetwork(model_structure) model.fit(data, estimator=MaximumLikelihoodEstimator) return model def bayesian_network_classification(data, feature_cols, target_col): """使用贝叶斯网络进行分类推理""" model = build_heart_bayesian_network(data) infer = VariableElimination(model) def predict(row): evidence = row[feature_cols].to_dict() try: query = infer.map_query(variables=[target_col], evidence=evidence) return query[target_col] except: return data[target_col].mode()[0] predictions = [] for _, row in data.iterrows(): predictions.append(predict(row)) return evaluate_model(data[target_col], predictions, "贝叶斯网络") # ================= 朴素贝叶斯分类器 ================= # def naive_bayes_classification(X_train, X_test, y_train, y_test): """使用高斯朴素贝叶斯分类器""" model = GaussianNB() model.fit(X_train, y_train) y_pred = model.predict(X_test) return evaluate_model(y_test, y_pred, "朴素贝叶斯") # ================= 主程序入口 ================= # if __name__ == "__main__": # 初始化 GUI(可选) root = init_gui() # 文件路径(请根据实际路径修改) wine_file = r'E:\桌面\malearning\wine.csv' heart_file = r'E:\桌面\malearning\heart.csv' # 加载数据 wine_data = load_data(wine_file) heart_data = load_data(heart_file) # === 心脏病数据集特殊处理 === continuous_vars = ['age', 'trestbps', 'chol', 'thalach', 'oldpeak'] # 对连续变量进行离散化 heart_data = discretize_continuous_features(heart_data, continuous_vars) # 确保其余特征为字符串类型以适配贝叶斯网络 for col in heart_data.columns: if col != 'target': heart_data[col] = heart_data[col].astype(str) list=['Alcohol','Malic.acid','Ash','Acl','Mg','Phenols','Flavanoids','Nonflavanoid.phenols','Proanth','Color.int','Hue','OD','Proline'] wine_data = discretize_continuous_features(wine_data,list) # === 葡萄酒数据集 === X_wine = wine_data.drop(['Wine'], axis=1) y_wine = wine_data['Wine'] X_train, X_test, y_train, y_test = train_test_split(X_wine, y_wine, test_size=0.2, random_state=42) print("=== 朴素贝叶斯 - 葡萄酒数据集 ===") nb_acc, nb_prec, nb_rec, nb_f1 = naive_bayes_classification(X_train, X_test, y_train, y_test) print("\n=== 贝叶斯网络 - 葡萄酒数据集 ===") wine_features = wine_data.columns.tolist()[1:] wine_target = wine_data.columns.tolist()[0] wine_bn_structure = [(wine_target, feat) for feat in wine_features] wine_bn_model = DiscreteBayesianNetwork(wine_bn_structure) wine_bn_model.fit(wine_data, estimator=MaximumLikelihoodEstimator) infer = VariableElimination(wine_bn_model) def wine_predict(row): evidence = row[wine_features].to_dict() try: query = infer.map_query(variables=[wine_target], evidence=evidence) return query[wine_target] except: return wine_data[wine_target].mode()[0] wine_predictions = [wine_predict(row) for _, row in wine_data.iterrows()] bn_acc, bn_prec, bn_rec, bn_f1 = evaluate_model(wine_data[wine_target], wine_predictions, "贝叶斯网络") # === 心脏病数据集 === X_heart = heart_data.drop(['target'], axis=1) y_heart = heart_data['target'] X_h_train, X_h_test, y_h_train, y_h_test = train_test_split(X_heart, y_heart, test_size=0.2, random_state=42) print("\n=== 朴素贝叶斯 - 心脏病数据集 ===") heart_nb_acc, heart_nb_prec, heart_nb_rec, heart_nb_f1 = naive_bayes_classification( X_h_train, X_h_test, y_h_train, y_h_test ) print("\n=== 贝叶斯网络 - 心脏病数据集 ===") heart_bn_acc, heart_bn_prec, heart_bn_rec, heart_bn_f1 = bayesian_network_classification( heart_data, X_heart.columns.tolist(), 'target' ) # === 绘图比较两个模型在两个数据集上的表现 === models = ['朴素贝叶斯', '贝叶斯网络'] metrics = ['准确率', '精确率', '召回率', 'F1分数'] wine_scores = [[nb_acc, nb_prec, nb_rec, nb_f1], [bn_acc, bn_prec, bn_rec, bn_f1]] heart_scores = [[heart_nb_acc, heart_nb_prec, heart_nb_rec, heart_nb_f1], [heart_bn_acc, heart_bn_prec, heart_bn_rec, heart_bn_f1]] fig, axes = plt.subplots(1, 2, figsize=(14, 6)) x = np.arange(len(metrics)) width = 0.35 # 葡萄酒数据集 axes[0].bar(x - width/2, wine_scores[0], width, label='朴素贝叶斯') axes[0].bar(x + width/2, wine_scores[1], width, label='贝叶斯网络') axes[0].set_title('葡萄酒数据集表现') axes[0].set_ylabel('分数') axes[0].set_xticks(x, metrics) axes[0].legend() # 心脏病数据集 axes[1].bar(x - width/2, heart_scores[0], width, label='朴素贝叶斯') axes[1].bar(x + width/2, heart_scores[1], width, label='贝叶斯网络') axes[1].set_title('心脏病数据集表现') axes[1].set_ylabel('分数') axes[1].set_xticks(x, metrics) axes[1].legend() plt.tight_layout() plt.show()

%% 主程序 % 调用两个处理函数 process_stroke('stroke.csv'); process_heart('heart.csv'); %% 脑卒中数据集处理函数 function process_stroke(filename) % 读取数据 data = readtable(filename, 'TextType', 'string'); disp('Stroke数据集原始变量:'); disp(data.Properties.VariableNames); disp(['原始样本量:', num2str(height(data))]); % 1. 缺失值处理 % 1.1 BMI列N/A用中位数填充 bmi = data.bmi; % 确保bmi为字符串类型 if isnumeric(bmi) bmi = string(bmi); end % 将字符串'N/A'转换为NaN bmi(strcmp(bmi, 'N/A')) = "NaN"; bmi = str2double(bmi); % 计算非缺失值的中位数 bmi_median = median(bmi(~isnan(bmi)), 'omitnan'); % 填充缺失值 bmi(isnan(bmi)) = bmi_median; data.bmi = bmi; % 1.2 smoking_status的Unknown保留(不填充) disp('吸烟状态类别(含Unknown):'); disp(unique(data.smoking_status)); % 2. 异常值处理 % 2.1 修正age列的异常值 age = data.age; % 转换为数值(若原始为字符串) if isstring(age) || iscell(age) age = str2double(age); end % 更合理的年龄异常值处理: % - 年龄小于0或大于120视为异常 % - 小于1岁的保留(可能是婴儿) valid_age = age > 0 & age <= 120; age_median = median(age(valid_age)); % 修正异常值 age(age <= 0 | age > 120) = age_median; data.age = age; % 2.2 标记bmi异常值(使用更稳健的方法) % 计算四分位距(IQR) Q = quantile(data.bmi, [0.25, 0.75]); IQR = Q(2) - Q(1); lower_bound = Q(1) - 1.5 * IQR; upper_bound = Q(2) + 1.5 * IQR; data.is_outlier_bmi = (data.bmi < lower_bound) | (data.bmi > upper_bound); % 3. 数据类型转换 % 分类变量转为字符串 categorical_vars = {'gender', 'ever_married', 'work_type', 'Residence_type', 'smoking_status'}; for i = 1:length(categorical_vars) var = categorical_vars{i}; if ~isstring(data.(var)) data.(var) = string(data.(var)); end end % 数值变量确保为double numeric_vars = {'id', 'hypertension', 'heart_disease', 'avg_glucose_level', 'stroke'}; for i = 1:length(numeric_vars) var = numeric_vars{i}; if ~isnumeric(data.(var)) data.(var) = str2double(data.(var)); end end % 4. 基础统计输出 disp('处理后数值变量统计:'); disp(summary(data(:, {'age', 'avg_glucose_level', 'bmi'}))); % 5. 保存处理后的数据 writetable(data, 'stroke_processed.csv'); disp('Stroke数据集处理完成,已保存为stroke_processed.csv'); end %% 心脏病数据集处理函数 function process_heart(filename) % 1. 读取数据 heart_data = readtable(filename); disp('心脏病数据集原始变量:'); disp(heart_data.Properties.VariableNames); % 2. 缺失值处理(处理异常0值) % 2.1 RestingBP中的0值用中位数填充 bp = heart_data.RestingBP; % 排除0值计算中位数 bp_median = median(bp(bp ~= 0), 'omitnan'); heart_data.RestingBP(bp == 0) = bp_median; % 2.2 Cholesterol中的0值按心脏病分组填充 hd = heart_data.HeartDisease; cholesterol = heart_data.Cholesterol; for i = 0:1 % 获取当前组别非零值 group_values = cholesterol(hd == i & cholesterol ~= 0); if ~isempty(group_values) chol_median = median(group_values, 'omitnan'); % 填充当前组别的0值 zero_idx = (hd == i) & (cholesterol == 0); cholesterol(zero_idx) = chol_median; end end % 处理剩余0值(如果有) if any(cholesterol == 0) overall_median = median(cholesterol(cholesterol ~= 0), 'omitnan'); cholesterol(cholesterol == 0) = overall_median; end heart_data.Cholesterol = cholesterol; % 3. 保存处理后的数据 writetable(heart_data, 'heart_processed.csv'); disp('心脏病数据集处理完成,已保存为heart_processed.csv'); end 用MATLAB添加数据可视化画图

from sklearn.ensemble import RandomForestRegressor from sklearn.multioutput import MultiOutputRegressor import singlemodel import singlemodelheart import singlemodelcirrhosis import numpy as np import pandas as pd import tensorflow as tf from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestClassifier from sklearn.multioutput import MultiOutputClassifier from sklearn.metrics import roc_auc_score from sklearn.impute import SimpleImputer # 多输出随机森林 df = pd.concat([singlemodel.df, singlemodelheart.df], axis=1) imputer = SimpleImputer(strategy='mean') # 初始化填充器:数值用均值,分类用众数(mode) df_filled = imputer.fit_transform(df) # 自动填充NaN df_filled = pd.DataFrame(df_filled, columns=df.columns) # 转换回DataFrame X1 = df_filled[['age', 'bmi', 'avg_glucose_level']] X2 = df_filled[['ST_Slope', 'ExerciseAngina', 'Oldpeak']] y1 = df_filled[['stroke']] y2 = df_filled[['HeartDisease']] X = np.hstack([X1, X2]) y = np.column_stack([y1, y2]) # 3. 创建多输出随机森林模型 base_model = RandomForestRegressor(n_estimators=100, random_state=42) multi_rf = MultiOutputRegressor(base_model) # 4. 训练模型(同时使用两组特征和标签) multi_rf.fit(X, y) # 关键步骤:传入合并后的特征矩阵和标签矩阵 # 5. 预测(使用相同格式输入) X_new = np.hstack((X1[:3], X2[:3])) # 新样本特征 predictions = multi_rf.predict(X_new) # 输出二维预测结果 print("预测结果(第一列y1,第二列y2):\n", predictions) 写出对上述代码的灵敏度分析代码

from sklearn import tree #决策树模型 from sklearn.model_selection import train_test_split #训练集与测试集划分 import pandas as pd import numpy as np from matplotlib import pyplot as plt import graphviz data=pd.read_csv('heart.csv') data.info()data.sample(10)#对五个名义变量进行映射 data['ChestPainType'].value_counts() #统计变量值类型 ChestPainType_Map={'ASY':1,'NAP':2,'ATA':3,'TA':4} #建立 变量值类型:映射数值 的字典,就比如'ASY'这里映射成1. data['ChestPainType']=data['ChestPainType'].map(ChestPainType_Map) #进行 变量值替换 data['Sex'].value_counts() Sex_Map={'M':0,'F':1} data['Sex']=data['Sex'].map(Sex_Map) data['RestingECG'].value_counts() RestingECG_Map={'Normal':0,'LVH':1,'ST':2} data['RestingECG']=data['RestingECG'].map(RestingECG_Map) data['ExerciseAngina'].value_counts() ExerciseAngina_Map={'N':0,'Y':1} data['ExerciseAngina']=data['ExerciseAngina'].map(ExerciseAngina_Map) data['ST_Slope'].value_counts() Flat_Map={'Flat':0,'Up':1,'Down':2} data['ST_Slope']=data['ST_Slope'].map(Flat_Map) data['RestingBP'].value_counts()data=data.drop(data['RestingBP'][data['RestingBP']==0].index) plt.scatter(data.index,data['RestingBP'])def apply_Resting(RestingBP):#小于90,返回0,大于140,返回2,中间为1 if RestingBP<90: return 0 elif RestingBP>140: return 2 else:return 1 data['RestingBP']=data['RestingBP'].apply(apply_Resting)data=data.drop(data['Cholesterol'][data['Cholesterol']==0].index) data=data.drop(data['Cholesterol'][data['Cholesterol']>=400].index) data.reset_index(drop=True, inplace=True) plt.scatter(data.index,data['Cholesterol']) def apply_Cholesterol(Cholesterol):#小于110,返回0,大于230,返回2,中间为1 if Cholesterol<110: return 0 elif Cholesterol>230: return 2 else:return 1 data['Cholesterol']=data['Cholesterol'].apply(apply_Cholesterol)plt.plot(data.index,data['MaxHR'][data['MaxHR'].sort_values().index]) def apply_MaxHR(MaxHR): if MaxHR>80 and MaxHR<=202: return 1 else: return 0data=data.drop(data['Oldpeak'][data['Oldpeak']>4].index) def apply_Oldpeak(Oldpeak): if Oldpeak<=1: return 0 elif Oldpeak>1 and Oldpeak<=2: return 2 elif Oldpeak>2 and Oldpeak<=3: return 3 else: return 4 data['Oldpeak']=data['Oldpeak'].apply(apply_Oldpeak) def apply_Age(Age): if Age<=40: return 0 elif Age>40 and Age<=65: return 1 else:return 2 data['Age']=data['Age'].apply(apply_Age) #拟合 target=data['HeartDisease'] data=data.drop('HeartDisease',1) target=np.array(target)#转换为numpy数组 data=np.array(data) #划分数据集 Xtrain, Xtest, Ytrain, Ytest=train_test_split(data,target,test_size=0.3) clf = tree.DecisionTreeClassifier()# 载入决策树分类模型 clf = clf.fit(Xtrain, Ytrain)# 决策树拟合,得到模型 score = clf.score(Xtest, Ytest) #返回预测的准确度 print(score) %%time from sklearn.model_selection import GridSearchCV Xtrain, Xtest, Ytrain, Ytest=train_test_split(data,target,test_size=0.3) clf = tree.DecisionTreeClassifier()# 载入决策树分类模型 parameters = {'max_depth': [1,2,3,4,5,6,7,8,9], 'max_leaf_nodes':range(20), 'criterion':['gini','entropy'], 'min_samples_leaf':range(15)} gs = GridSearchCV(clf, parameters, refit = True, cv = 5, verbose = 1, n_jobs = -1) gs.fit(Xtrain, Ytrain) Xtrain, Xtest, Ytrain, Ytest=train_test_split(data,target,test_size=0.3) clf = tree.DecisionTreeClassifier(criterion='gini', max_depth=5, max_leaf_nodes=17, min_samples_leaf=12, ) clf = clf.fit(Xtrain, Ytrain)# 决策树拟合,得到模型 score = clf.score(Xtest, Ytest) #返回预测的准确度 import graphviz feature_name = ['Age','Sex','ChestPainType','RestingBP','Cholesterol','FastingBS','RestingECG','MaxHR','ExerciseAngina','Oldpeak','ST_Slope'] dot_data = tree.export_graphviz(clf, feature_names= feature_name, class_names=['yes','no'], filled=True, rounded=True) graph = graphviz.Source(dot_data)#画树 graph.render('D:tree.pdf') gs.best_params_帮我分析一下这些代码

大家在看

recommend-type

Dynamsoft SourceAnywhere for VSS 5.x Keygen 注册机

Keygen for Dynamsoft SourceAnywhere for VSS 5.x,SourceAnywhere 5.x Keygen 注册机,亲自测试可以注册成功。
recommend-type

宠物主题网页HTML+css+js共计8个页面

布局方式:div层布局 float浮动 使用技术:html+css+js 可支持软件:vscode,hbuilder,subline,dw等软件 【学生原创网、日期新鲜】 适合:网页作业学习等
recommend-type

Spring AI+Redis会话记忆存储[可运行源码]

本文详细介绍了如何利用Redis实现Spring AI项目的会话记忆持久化存储。作者在开发AI大模型应用时发现官方未提供Redis会话记忆实现,因此自行开发了一套解决方案。文章首先分析了Spring AI的源码结构,重点讲解了MessageChatMemoryAdvisor和ChatMemory接口的作用及实现原理。随后详细展示了如何通过RedisTemplate配置序列化,并实现ChatMemoryRepository接口以支持Redis存储。具体实现包括使用Redis的Set存储会话ID、List存储消息队列,以及处理消息的序列化与反序列化。最后通过Controller示例演示了实际调用流程,总结了请求从接收到存储的完整链路。该方案具有高性能、分布式友好、实时性强等优点,适合需要多轮对话记忆的AI应用场景。
recommend-type

U8+V15.0学习资料

最全用友U8+V15.0学习资料:U8+V15.0在系统功能上是U8+V13.0的升级版本,紧紧围绕企业经营管理热点,向广大客户提供财税一体化、新收入准则、多工厂计划协同、多组织购销业务协同、以及新零售、新电商等多项新应用。包括以下产品范围:企业门户、财务会计、管理会计、电商管理、供应链管理、生产制造、人力资源管理、决策支持、集团应用、企业应用集成、移动应用等。
recommend-type

matlab生成igs_MATLAB生成igs_matlab绘制igs图_matlab_

利用matlab进行格式转换,生成igs格式

最新推荐

recommend-type

基于Python3开发的插件化可扩展网络安全漏洞自动化扫描与检测框架_集成多种常见服务未授权访问漏洞检测如MongoDB_Redis_Memcached_Zookeeper以及高危.zip

基于Python3开发的插件化可扩展网络安全漏洞自动化扫描与检测框架_集成多种常见服务未授权访问漏洞检测如MongoDB_Redis_Memcached_Zookeeper以及高危.zip
recommend-type

WIFI热点连接搜索-下载即用.zip

下载方式:https://pan.quark.cn/s/e2e4dfd55716 该安卓应用源码旨在实现搜索并扫描周边WIFI网络,进而获取热点信息并支持直接连接至WIFI热点的功能。 用户可通过该应用直接在界面中开启WIFI功能,无需进入系统设置菜单进行操作。 该项目包含一个util类,该类提供了对安卓设备连接包括WEP、WPA、WEP2及无密码等不同类型热点的功能支持。 代码已附带详尽的注释说明,并经过必要的修正,确保整个项目能够稳定且无误地运行。 项目采用GBK编码,默认编译环境为版本4.1.2,最低系统兼容版本为4.0及以上。
recommend-type

基于Scrapy网络爬虫框架实时抓取各大招聘网站与行业数据平台信息的毕业生人才需求分析系统_结合Flask轻量级Web框架构建后端API接口与数据处理逻辑_集成Echarts数据可.zip

基于Scrapy网络爬虫框架实时抓取各大招聘网站与行业数据平台信息的毕业生人才需求分析系统_结合Flask轻量级Web框架构建后端API接口与数据处理逻辑_集成Echarts数据可.zip
recommend-type

霸王茶姬运营分析:数据驱动的销售与用户策略

资源摘要信息:"《霸王茶姬店铺运营分析》报告分析框架介绍" 报告的标题《霸王茶姬店铺运营分析》以及描述指出了报告的核心内容是针对新中式茶饮品牌“霸王茶姬”的运营状况进行深入分析,其目的在于通过数据分析提升销售业绩、优化产品组合、增强用户粘性,并为运营策略提供数据支持。以下为报告的详细知识点: 1. 市场分析: - 新中式茶饮品牌霸王茶姬在市场上拥有良好的口碑,原因在于其高品质原料和独特口感。 - 面临激烈的市场竞争和消费者需求多样化,霸王茶姬需要明确其市场定位,以及如何在竞争中脱颖而出。 2. 销售与用户研究: - 分析销售数据、用户画像、产品表现和市场营销效果,旨在精细化管理运营策略,促进持续发展。 - 用户画像分析包括会员用户占比、用户年龄和性别分布、复购率与用户忠诚度、购买渠道占比等。 3. 数据分析方法: - 使用Python作为主要分析工具,实现数据的描述性统计和可视化分析。 - 数据处理涵盖数据清洗、缺失值处理和异常值检测,以确保分析结果的准确性。 4. 销售数据可视化: - 通过日/周/月销售额趋势图、各门店销售额对比柱状图、订单量与客单价分析饼图等图表形式,直观展示销售数据。 5. 销售数据分析结果: - 日销售额趋势显示周末销售额显著高于工作日,尤其以周六为最高峰。 - 月度销售额在夏季(6-8月)达到高峰,冬季(12-2月)相对较低。 - A门店销售额最高,占比30%,B门店和C门店销售额相近,分别占25%和20%。 - 平均客单价为35元,订单量高峰出现在下午2-5点。 6. 产品销售分析: - 分析各产品销量排名、爆款产品与滞销产品,并探讨组合购买情况及季节性产品销量趋势。 7. 结论与建议: - 根据分析得出的核心发现,提出针对性的运营优化策略和市场营销建议。 - 针对如何增长销售额、提升用户粘性、优化产品组合、提高运营效率及市场策略优化等方面,给出明确的结论和建议。 报告的内容与结构突显了数据驱动决策的重要性,并展示了如何利用数据分析方法来解决实际业务问题,从而为企业决策层提供科学的决策依据。通过对霸王茶姬店铺运营的深入分析,报告意在帮助企业识别市场机会,规避风险,优化运营流程,并最终实现业绩的增长。
recommend-type

【Altium Designer从入门到精通】:揭秘9大核心模块与PCB设计底层逻辑(新手必看)

# Altium Designer:从设计启蒙到系统级协同的进阶之路 在今天这个电子产品迭代速度堪比摩尔定律的时代,一块PCB板早已不再是“连线+焊盘”的简单堆叠。它承载着高速信号、精密电源、严苛EMI控制和复杂热管理的多重使命。而Altium Designer(简称AD),正是这样一位能陪你从初学者成长为系统架构师的“电子设计伴侣”。 我们不妨先抛开那些教科书式的目录划分——什么“第1章”、“第2节”,真正重要的是**理解这套工具背后的工程思维**。它不只是让你画出一张漂亮的图纸,而是教会你如何构建一个**可验证、可复用、可量产**的完整设计体系。 所以,让我们以一种更自然的方式展开这
recommend-type

相位恢复算法

### 相位恢复算法概述 #### 原理 相位恢复是指从测量的幅度信息中恢复原始信号的相位信息的过程。这一过程通常涉及到复杂的优化问题,因为相位信息通常是不可直接获取的。基于迭代最近点 (ICP) 的全场相位恢复算法能够有效地解决相位 unwrapping 问题,并实现高精度、高效率的相位恢复[^1]。 对于具体的物理机制而言,相位梯度对应波前的倾斜,这会导致光能量在横向的重新分布。相位的变化会引发衍射效应,进而影响 \(z\) 方向上强度的变化[^4]。 #### 实现方法 一种常见的实现方式是通过迭代算法逐步逼近真实的相位分布。例如,在 MATLAB 中可以使用如下代码来实现 ICP
recommend-type

C#编程语言的全面教程:基础语法与面向对象编程

资源摘要信息:"C#语言教程介绍" C#(读作“C Sharp”)是由微软公司于2000年推出的一种现代化面向对象编程语言,其设计目的是为了能够开发出具有复杂功能的软件组件,并且能够在微软的.NET平台上运行。C#语言以其简洁、面向对象、类型安全等特点,迅速成为开发Windows应用程序、Web服务、游戏以及跨平台解决方案的热门选择。 一、环境搭建 在正式开始学习C#编程之前,必须首先搭建好开发环境。通常情况下,开发者会优先考虑使用微软官方提供的Visual Studio集成开发环境(IDE),它适合从简单的学习项目到复杂的应用开发。Visual Studio提供了代码编辑、调试以及多种工具集,极大地提高了开发效率。 除了IDE,还需要安装.NET软件开发工具包(SDK),它是运行和构建C#程序所必需的。.NET SDK不仅包括.NET运行时,还包含用于编译和管理C#项目的一系列命令行工具和库。 二、C#基础语法 1. 命名空间与类 C#使用`using`关键字来引入命名空间,这对于使用类库和模块化代码至关重要。例如,使用`using System;`可以让程序访问`System`命名空间下的所有类,比如`Console`类。 类是C#中定义对象蓝图的核心,使用`class`关键字来声明。类可以包含字段、属性、方法和其他类成员,这些成员共同定义了类的行为和数据。 2. 变量与数据类型 在C#中,变量是用于存储数据值的基本单元。在使用变量之前,必须声明它并指定数据类型。C#支持多种基本数据类型,如整数(`int`)、浮点数(`double`)、字符(`char`)和布尔值(`bool`)。此外,C#还支持更复杂的数据类型,比如字符串(`string`)和数组。 3. 控制流语句 控制流语句用于控制程序的执行路径。它们能够根据条件判断来决定执行哪部分代码,或者通过循环重复执行某段代码。常用的控制流语句有: - `if`语句,用于基于条件表达式的结果执行代码块。 - `for`循环,用于按照一定次数重复执行代码块。 - `while`循环,根据条件表达式的结果循环执行代码块。 - `switch`语句,用于根据不同的条件执行不同的代码块。 三、面向对象编程(OOP) C#是一种纯粹的面向对象编程语言,它提供了类和对象的概念来支持面向对象的编程范式。 1. 类与对象 类在C#中是对象的蓝图或模板。一个类定义了一个对象的结构(数据成员)和行为(方法成员)。对象是类的实际实例,通过调用类的构造函数来创建。 2. 构造函数 构造函数是一种特殊的方法,它的名称与类名相同,并且在创建类的新对象时自动调用。构造函数负责初始化对象的状态。 3. 封装、继承与多态 封装是指将对象的实现细节隐藏起来,并向外界提供访问对象状态和行为的接口。 继承允许一个类(称为子类)继承另一个类(称为父类)的属性和方法,以此来重用代码和实现层级结构。 多态允许不同类的对象以统一的接口进行交互,并且可以在运行时确定要调用的方法的具体实现。 四、高级特性 C#提供了丰富的高级特性,这些特性使得C#更加灵活和强大。 1. 泛型与集合 泛型允许开发者编写与特定数据类型无关的代码,这使得同一个算法或方法能够应用于不同的数据类型,同时还能保持类型安全。 C#提供了丰富的集合类型,比如数组、列表(`List<T>`)、队列(`Queue<T>`)、栈(`Stack<T>`)和字典(`Dictionary<TKey,TValue>`)等,这些集合类型帮助开发者更高效地管理数据集合。 2. 异常处理 C#通过异常处理机制为开发者提供了处理程序运行时错误的方法。异常可以在检测到错误时抛出,并且在程序的其他部分捕获和处理。 3. Lambda表达式与LINQ Lambda表达式提供了一种简洁的定义匿名方法的方式,它们在C#的许多高级特性中都有应用。 LINQ(语言集成查询)是C#的一个强大特性,它提供了一种一致的方法来查询和处理数据,无论数据是存储在数据库中、XML文件中还是内存中的集合。 五、并发编程 在多核处理器时代,并发编程变得异常重要。C#通过多种方式支持并发编程,例如提供线程的基础操作、线程池和任务并行库(TPL)等。 任务并行库简化了并行编程,它允许开发者轻松地执行并行任务和并行化循环操作。异步编程是C#的另一个重要特性,特别是async和await关键字的引入,它们使得异步代码的编写更加直观和简洁。 此外,C#还支持并发集合和原子操作,这些是实现线程安全集合和高效同步机制的重要工具。 总结而言,C#语言结合了面向对象的强大功能和现代编程语言的许多便捷特性,使其在各种类型的软件开发中成为了一个非常流行和实用的选择。通过不断学习和实践C#语言的基础和高级特性,开发者能够有效地创建各种高性能的应用程序。
recommend-type

【通达信行情推送机制揭秘】:基于回调的异步数据处理模型优化方案

# 通达信高频行情引擎:从回调机制到AI预知的全链路实战 在A股量化交易的“毫秒生死战”中,谁能更快地看到盘口异动、更早触发策略信号,谁就掌握了超额收益的钥匙。然而,当你的策略还在用轮询方式拉取数据时,对手早已通过**事件驱动 + 零拷贝 + 协程流水线**构建了微秒级响应系统——这正是我们今天要深挖的技术战场。 想象这样一个场景:某只股票突然出现连续大单扫货,从第一笔成交到你收到Tick推送,中间究竟经历了多少层“阻塞”?是SDK回调卡在主线程?还是解码过程反复`memcpy`拖慢节奏?亦或是因子计算和信号判定串行执行导致延迟堆积? 别急,这篇文章不讲空洞理论,咱们直接上硬核干货——带
recommend-type

卷积加速算法

### 卷积加速算法概述 在深度学习领域,卷积操作是卷积神经网络(CNNs)中最耗时的部分之一。为了提高效率,研究者们提出了多种卷积加速算法来优化这一过程。 #### Winograd 算法 Winograd 算法专门针对小尺寸卷积核设计,旨在减少计算复杂度。该方法通过重新排列输入矩阵和滤波器矩阵的方式减少了所需的乘法次数。具体来说,在标准卷积中,对于大小为 \(n \times n\) 的图像块与同样大小的卷积核做卷积需要执行大量的浮点数相乘累加运算;而采用 Winograd 变换后,则可以有效地降低这些冗余计算[^1]。 ```python import numpy as np
recommend-type

赵致琢教授探讨中国计算机科学教育的发展策略

资源摘要信息:《中国计算机科学专业教育发展道路的思考》 知识点一:计算机科学教育的发展与挑战 随着计算机科学的飞速发展,学科专业办学面临诸多挑战。例如,计算机科学从“前科学”时代向成熟学科的过渡使得学科知识体系日渐庞大且复杂。这要求高校在计算机科学教育过程中采用更加合理和科学的办学策略,适应社会多样化的需求。 知识点二:分层次分类办学的策略 报告提出了分层次分类办学作为应对当前教育挑战的关键策略。这一策略涉及在研究生教育和本科教育中设立不同的培养目标和课程体系,以培养不同类型的计算机科学人才,如创新人才、应用技术开发人才和职业技术人才。 知识点三:学科专业教育的重新定位 高等教育中存在办学定位模糊的问题,导致教育资源分配不合理。因此,赵教授建议高校需要明确自身定位,根据学科专业教学的要求,分类开展教学活动,避免盲目追求规模扩大而忽视教育质量。 知识点四:专业认证的重要性 赵教授强调专业认证的重要性。通过专业认证体系,可以保证教育质量,确保培养的人才满足社会的需求和标准,从而提升学科专业的社会认可度。 知识点五:教学改革实践经验 厦门大学在计算机科学本科教学改革方面提供了实践经验。例如,通过强化数学基础和增加实践课程的比重,厦门大学成功地提升了教育质量,并取得了显著成效。这些经验对其他高校具有借鉴意义。 知识点六:教育改革的本土化与国际合作 赵教授指出,中国高等教育改革应该立足本土文化,借鉴国外的先进经验和教育理念。通过校际协作,可以提升师资水平,推动教育质量的整体提升。这表明国际交流与合作对于学科建设与教学改革具有重要意义。 知识点七:构建学科人才培养的科学体系 为应对教育挑战,需要全面建立学科人才培养的科学体系,包括科学理论体系、示范教育基地和质量保障体系。这三个体系是确保教育质量和可持续发展的基础。 知识点八:问题根源的深入分析 报告进一步分析了当前计算机科学教育问题的根源,包括宏观决策上的缺失、微观运行中的混乱以及外部环境问题。这些问题导致了教育资源配置的不合理和教学效率的低下。 知识点九:师资队伍建设的重要性 赵教授提到,当前师资队伍存在不足,大部分高校需要提升师资的起点和质量。师资队伍的建设是提高教育质量的关键,需要从选拔、培养到评价等多方面进行系统的改革和创新。 知识点十:对未来的展望与选择 在总结前人经验和分析现状的基础上,赵教授呼吁对高等教育和科学技术未来的发展道路做出正确的选择,强调科学、理智和质量的重要性,并强调了中国高等教育改革需要立足本国传统文化根基,同时借鉴国外先进经验,进行系统的变革。 综合以上内容,赵致琢教授的报告不仅深入分析了当前中国计算机科学专业教育所面临的挑战,还提出了具有实践价值的应对策略,强调了教育改革的必要性和紧迫性。报告内容丰富,为当前和未来的计算机科学教育提供了宝贵的参考和指导。