基于随机森林回归预测葡萄酒质量
- 1.作者介绍
- 2.随机森林算法与数据集介绍
- 2.1定义
- 2.2核心思想
- 2.3主要步骤
- 2.4数据集介绍
- 3.算法实现
- 3.1数据加载与探索
- 3.2数据可视化
- 3.3数据预处理(标准化、划分训练/测试集)
- 3.4模型训练与优化(随机森林回归 + 超参数搜索)
- 3.5模型评估(MSE、R²、混淆矩阵、准确率)
- 3.6特征重要性分析
- 3.7模型保存与加载
- 4.结果分析
- 5.完整代码
基于随机森林回归预测葡萄酒质量
1.作者介绍
朱亚彬, 男 ,西安工程大学电子信息学院 , 2024级研究生
研究方向:任务卸载与边缘计算
电子邮件:2292036787@qq.com
王晓睿,男,西安工程大学电子信息学院,2024级研究生,张宏伟人工智能课题组
研究方向:智能视觉检测与工业自动化技术
电子邮件:3234002295@qq.com
2.随机森林算法与数据集介绍
2.1定义
随机森林回归(Random Forest Regression)是一种基于集成学习的回归算法,通过组合多个决策树来提高预测的准确性和稳定性。
2.2核心思想
随机森林回归通过构建多棵决策树,并将它们的预测结果进行平均(或加权平均)来得到最终的回归结果。每棵决策树在训练时使用随机抽样的数据和特征,从而减少过拟合的风险。
2.3主要步骤
数据采样(Bootstrap Sampling):从训练集中随机抽取样本(有放回抽样),形成多个子集。每个子集用于训练一棵决策树。
特征随机选择:在每棵树的节点分裂时,随机选择一部分特征(而不是所有特征)来寻找最佳分割点。这增加了模型的多样性。
构建决策树:对每个子集数据,构建一棵决策树。树的生长通常不进行剪枝,直到达到最大深度或节点中的样本数小于某个阈值。
集成预测:对于回归问题,将所有树的预测结果取平均值,作为最终的预测值。
(1)随机选择一个样本子集作为该决策树的训练集。
(2)随机选择一部分特征(总特征数的平方根)作为该决策树的特征集。
(3)基于训练集和特征集构建决策树,直到达到预定的叶子节点数或无法分割为止。
(4)重复以上步骤,建立多颗决策树。
(5)对于一个新的样本,将它输入到每棵决策树中,得到多个预测结果。
(6)对多个预测结果进行平均,得到最终的预测结果。
算法公式基于决策树回归模型,每个预测树的预测函数为:
多棵决策树的预测函数可以表示为:
该部分参考链接:https://blog.csdn.net/m0_61399808/article/details/130733650
2.4数据集介绍
名称:Wine Quality Dataset(葡萄酒质量数据集):
数据集地址:https://archive.ics.uci.edu/dataset/186/wine+quality
数据集包含红葡萄酒和白葡萄酒两个子集(分别有1599和4898个样本)。每个样本有11个特征,包括固定酸度、挥发性酸度、柠檬酸、残糖、氯化物等。目标是一个回归任务,预测葡萄酒的质量评分(0到10分)。本次实验使用的是红葡萄酒数据集进行测试。
3.算法实现
基于红酒质量数据集,使用随机森林回归模型进行质量预测。主要步骤包括:数据加载与探索、数据可视化(散点图、热力图、直方图等)、数据预处理(标准化、划分训练/测试集)、模型训练与优化(随机森林回归 + 超参数搜索)、模型评估(MSE、R²、混淆矩阵、准确率)、特征重要性分析、模型保存与加载。
3.1数据加载与探索
(1)程序从指定路径加载红酒质量数据集:数据文件为 CSV 格式,分隔符为 ;使用 pandas.read_csv 读取数据,编码格式为 utf-8。
(2)数据探索。
3.2数据可视化
程序通过多个图表展示数据特征与质量之间的关系。
(1)特征与质量的散点图
(2)相关性热力图
(3)不同品质红酒的分布
(4)不同品质的酒精含量直方图
3.3数据预处理(标准化、划分训练/测试集)
(1)特征和标签划分:将数据集分为特征(X)和目标变量(y),其中 y 是红酒的质量评分。
(2)划分训练集和测试集:使用 train_test_split 将数据划分为训练集(80%)和测试集(20%)。
random_state=42 确保结果可重复,stratify=y 保持训练集和测试集中 y 的分布一致。
(3)数据标准化
使用 StandardScaler 对特征进行标准化(均值为 0,方差为 1)。在训练集上拟合并转换,在测试集上仅转换。
3.4模型训练与优化(随机森林回归 + 超参数搜索)
创建随机森林回归模型,设置 100 棵树,随机种子为 42。
使用 10 折交叉验证评估模型在训练集上的性能。
计算均方误差(MSE)和 R² 分数。neg_mean_squared_error 返回负值,故取反。
使用 GridSearchCV 搜索最佳超参数组合。
搜索的参数包括 max_features(特征选择方式)和 max_depth(树的最大深度)。
同样采用 10 折交叉验证。
重新训练模型:使用搜索到的最佳参数重新训练模型。
3.5模型评估(MSE、R²、混淆矩阵、准确率)
3.6特征重要性分析
3.7模型保存与加载
4.结果分析
(1)图表可视化
图中的横轴表示的是真实品质,纵坐标表示的是预测品质。对角线表示预测值与完全值完全一样,品质为6时准确率最高。
从混淆矩阵中可以看出,品质为6,7的时候预测的准确率最高。
(2)MSE,准确率等评估指标
MSE的值越小,模型的预测性能越好。R²的值范围在0到1之间。R²值越接近1,表示模型对目标变量的解释能力越强,模型的预测性能越好。结果表明模型在测试集上的性能超过了训练集。
图为特征重要性的排列,从图中可以看出,alochol的特征是最重要的。表明alochol的含量越高,葡萄酒的质量品质越高。
5.完整代码
# 导入必要的库
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import make_pipeline
from sklearn.metrics import mean_squared_error, r2_score, confusion_matrix
from sklearn.model_selection import GridSearchCV
import joblib
# 设置中文字体
plt.rcParams["font.sans-serif"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False
# #加载数据
# dataset_url = 'wine+quality/winequality-red.csv'
# data = pd.read_csv(dataset_url)
# #查看数据的前五行
# print( data.head() )
# 加载数据
dataset_url = 'wine+quality/winequality-red.csv'
data = pd.read_csv(dataset_url, sep=';', encoding="utf-8")
# 查看数据的基本信息
print(data.head())
print(data.shape)
print(data.describe())
# 绘制特征与质量的关系图
plt.figure(figsize=(12, 5))
plt.subplot(121)
sns.scatterplot(x='volatile acidity', y='quality', data=data)
plt.title('Volatile Acidity vs Quality')
plt.subplot(122)
sns.scatterplot(x='alcohol', y='quality', data=data)
plt.title('Alcohol vs Quality')
plt.savefig("results/quality.png", dpi=300)
plt.show()
# 绘制相关性热力图
correlation = data.corr()
plt.figure(figsize=(12, 10))
sns.heatmap(correlation, annot=True)
plt.title("Correlation Matrix")
plt.savefig("results/Correlation_Matrix.png", dpi=400)
plt.show()
# 绘制不同品质的红酒分布
sns.catplot(data=data, x="quality", kind='count')
plt.title('不同品质的红酒的分布')
plt.xlabel('品质')
plt.ylabel('数量')
plt.show()
# 提取品质为 4、5、6、7 的数据
data_quality_4 = data.loc[data["quality"] == 4, :]
data_quality_5 = data.loc[data["quality"] == 5, :]
data_quality_6 = data.loc[data["quality"] == 6, :]
data_quality_7 = data.loc[data["quality"] == 7, :]
# 绘制不同品质的酒精含量直方图
plt.figure(figsize=(9, 7), dpi=80)
plt.subplot(2, 2, 1)
plt.hist(data_quality_4["alcohol"], bins=50)
plt.xlabel("酒精含量")
plt.ylabel("数量")
plt.title("品质为4的酒精度数量直方图")
plt.subplot(2, 2, 2)
plt.hist(data_quality_5["alcohol"], bins=50)
plt.xlabel("酒精含量")
plt.ylabel("数量")
plt.title("品质为5的酒精度数量直方图")
plt.subplot(2, 2, 3)
plt.hist(data_quality_6["alcohol"], bins=50)
plt.xlabel("酒精含量")
plt.ylabel("数量")
plt.title("品质为6的酒精度数量直方图")
plt.subplot(2, 2, 4)
plt.hist(data_quality_7["alcohol"], bins=50)
plt.xlabel("酒精含量")
plt.ylabel("数量")
plt.title("品质为7的酒精度数量直方图")
plt.tight_layout()
plt.savefig("results/quality_4567_vs.png", dpi=300)
plt.show()
# 特征和标签
X = data.drop('quality', axis=1) # 特征,去除 'quality' 列
y = data['quality'] # 标签,仅保留 'quality' 列
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# 数据标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 创建随机森林回归模型
model = RandomForestRegressor(n_estimators=100, random_state=42)
# 使用10折交叉验证评估模型在训练集上的性能
cv_mse = -cross_val_score(model, X_train_scaled, y_train, cv=10, scoring='neg_mean_squared_error').mean()
cv_r2 = cross_val_score(model, X_train_scaled, y_train, cv=10, scoring='r2').mean()
print(f'交叉验证的均方误差 (MSE): {cv_mse}')
print(f'交叉验证的R²分数: {cv_r2}')
# 超参数优化
pipeline = make_pipeline(RandomForestRegressor(random_state=42))
hyperparameters = {
'randomforestregressor__max_features': ['sqrt', 'log2'],
'randomforestregressor__max_depth': [None, 5, 3, 1]
}
clf = GridSearchCV(pipeline, hyperparameters, cv=10)
clf.fit(X_train_scaled, y_train)
print(f'最佳超参数: {clf.best_params_}')
# 使用最佳参数重新训练模型
best_model = clf.best_estimator_
best_model.fit(X_train_scaled, y_train)
# 评估模型在测试集上的性能
y_pred = best_model.predict(X_test_scaled)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f'测试集的均方误差 (MSE): {mse}')
print(f'测试集的R²分数: {r2}')
# 绘制真实值与预测值的散点图
plt.scatter(y_test, y_pred, alpha=0.5)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
plt.xlabel('True Quality')
plt.ylabel('Predicted Quality')
plt.title('Predicted vs True Quality Scores')
plt.savefig("results/Predicted_vs_True_Quality_Scores.png", dpi=400)
plt.show()
# 计算混淆矩阵
cm = confusion_matrix(y_test, np.round(y_pred))
# 绘制混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, cmap='Blues', fmt='d', xticklabels=[4, 5, 6, 7], yticklabels=[4, 5, 6, 7])
plt.xlabel('预测品质')
plt.ylabel('实际品质')
plt.title('混淆矩阵')
plt.savefig("results/混淆矩阵.png", dpi=400)
plt.show()
# 显示特征重要性
feature_names = X.columns
importances = best_model.named_steps['randomforestregressor'].feature_importances_
sorted_indices = np.argsort(importances)[::-1]
print("特征重要性(从高到低):")
for i in range(len(feature_names)):
print(f"{feature_names[sorted_indices[i]]:<20} | {importances[sorted_indices[i]]}")
# 绘制特征重要性条形图
plt.figure(figsize=(10, 6))
sns.barplot(x=importances[sorted_indices], y=feature_names[sorted_indices])
plt.title('Feature Importances')
plt.xlabel('Importance')
plt.ylabel('Features')
plt.savefig("results/Feature Importances.png", dpi=400)
plt.show()
# 保存模型
joblib.dump(best_model, 'rf_regressor.pkl')
# 加载模型并进行预测
rf_regressor_loaded = joblib.load('rf_regressor.pkl')
y_pred_loaded = rf_regressor_loaded.predict(X_test_scaled)
# 计算预测准确率
accuracy = np.mean(np.round(y_pred_loaded) == y_test)
print("预测准确率: {:.2f}%".format(accuracy * 100))