复习日
回顾一下之前14天的内容:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
data=pd.read_csv('ObesityDataSet.csv')
data.head()
#分离连续变量与离散变量
discrete_features=['Gender','family_history_with_overweight','FAVC','CAEC','SMOKE','SCC','CALC','MTRANS']
print(discrete_features)
continuous_features=data.select_dtypes(include=['float64','int64']).columns.tolist()
print(continuous_features)
for feature in discrete_features:
print(f"\n{feature}的唯一值:")
print(data[feature].value_counts())
设置全局字体为支持中文的字体 (例如 SimHei)
plt.rcParams['font.sans-serif'] = ['SimHei']
解决负号'-'显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
#查看标签分布
sns.histplot(x=data['NObeyesdad'])
plt.title('NObeyesdad 的箱线图')
plt.xticks(rotation=45, ha='right')
plt.xlabel('NObeyesdad')
plt.show()
discrete features
for col in discrete_features:
#对没有顺序的离散变量进行独热编码
找到离散变量,排除 NObeyesdad 列
discrete_lists = [] # 新建一个空列表,用于存放离散变量名
for discrete_features in data.columns:
if data[discrete_features].dtype == 'object' and discrete_features != 'NObeyesdad':
discrete_lists.append(discrete_features)
离散变量独热编码
data = pd.get_dummies(data, columns=discrete_lists)
data.columns
对比独热编码前后的列名 即可
data2 = pd.read_csv("ObesityDataSet.csv")
list_final = [] # 新建一个空列表,用于存放独热编码后新增的特征名
for i in data.columns:
if i not in data2.columns:
list_final.append(i) # 这里打印出来的就是独热编码后的特征名
for i in list_final:
data[i]=data[i].astype(int)#将bool型转换为数值型
print(list_final)
print(data.head())
#对数值较大的连续变量进行归一化
from sklearn.preprocessing import StandardScaler,MinMaxScaler
st=MinMaxScaler()
data['Age']=st.fit_transform(data[['Age']])
data['Height']=st.fit_transform(data[['Height']])
data['Weight']=st.fit_transform(data[['Weight']])
data.head()
from sklearn.ensemble import RandomForestClassifier #随机森林分类器
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score # 用于评估分类器性能的指标
from sklearn.metrics import classification_report, confusion_matrix #用于生成分类报告和混淆矩阵
import warnings #用于忽略警告信息
warnings.filterwarnings("ignore") # 忽略所有警告信息
--- 1. 默认参数的随机森林 ---
评估基准模型,这里确实不需要验证集
print("--- 1. 默认参数随机森林 (训练集 -> 测试集) ---")
import time # 这里介绍一个新的库,time库,主要用于时间相关的操作,因为调参需要很长时间,记录下会帮助后人知道大概的时长
start_time = time.time() # 记录开始时间
rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(x_train, y_train) # 在训练集上训练
rf_pred = rf_model.predict(x_test) # 在测试集上预测
end_time = time.time() # 记录结束时间
print(f"训练与预测耗时: {end_time - start_time:.4f} 秒")
print("\n默认随机森林 在测试集上的分类报告:")
print(classification_report(y_test, rf_pred))
print("默认随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred))
from skopt import BayesSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
import time
定义超参数搜索空间
param_space = {
'n_estimators': (10, 200), # 决策树数量
'max_depth': (3, 20), # 树的最大深度
'min_samples_split': (2, 20), # 内部节点再划分所需最小样本数
'min_samples_leaf': (1, 20), # 叶子节点最少样本数
'max_features': ['sqrt', 'log2', None] # 每次分裂时考虑的特征数量
}
初始化随机森林分类器
rf_model = RandomForestClassifier(random_state=42)
使用贝叶斯优化进行超参数搜索
bayes_search = BayesSearchCV(
estimator=rf_model,
search_spaces=param_space,
n_iter=32, # 搜索的迭代次数
scoring='accuracy', # 评估指标
cv=3, # 交叉验证折数
random_state=42,
n_jobs=-1 # 并行运行
)
开始计时
start_time = time.time()
在训练集上进行超参数搜索
bayes_search.fit(x_train, y_train)
结束计时
end_time = time.time()
输出最佳参数和最佳得分
print(f"贝叶斯优化耗时: {end_time - start_time:.4f} 秒")
print("最佳参数:", bayes_search.best_params_)
print("最佳得分:", bayes_search.best_score_)
使用最佳参数在测试集上评估模型
best_rf_model = bayes_search.best_estimator_
rf_pred = best_rf_model.predict(x_test)
输出分类报告和混淆矩阵
print("\n随机森林 (贝叶斯优化) 在测试集上的分类报告:")
print(classification_report(y_test, rf_pred))
print("随机森林 (贝叶斯优化) 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred))
import shap
import matplotlib.pyplot as plt
# 初始化 SHAP 解释器
explainer = shap.Explainer(best_rf_model, x_train)
# 计算 SHAP 值,禁用加性检查
shap_values = explainer(x_test, check_additivity=False)
# 绘制特征重要性图
shap.summary_plot(shap_values, x_test)
# --- 1. SHAP 特征重要性条形图 (Summary Plot - Bar) ---
print("--- 1. SHAP 特征重要性条形图 ---")
shap.summary_plot(shap_values[:, :, 0], x_test, plot_type="bar",show=False) # 这里的show=False表示不直接显示图形,这样可以继续用plt来修改元素,不然就直接输出了
plt.title("SHAP Feature Importance (Bar Plot)")
plt.show()
shap.summary_plot(shap_values[:, :, 0], x_test)
对于数据集的思考:
现在可以发现,其实掌握流程后,机器学习项目流程是比较固定的,对于掌握的同学来说,工作量非常少。所以这也是很多论文被懂的认为比较水的原因所在。所以这类研究真正核心的地方集中在以下几点:
在学习机器学习算法的过程中,我们经常需要数据来学习和试验算法,常用一下开源数据集
UCI数据集
类型:比较全面,各类型数据都有涉及
网址:http://archive.ics.uci.edu/ml/datasets.php
Kaggle竞赛数据集
类型:比较全面,各类型数据都有涉及
网址:https://www.kaggle.com/datasets
@浙大疏锦行