一、问题背景:传统方法的局限与数据驱动价值
混凝土是建筑和基础设施工程中最常用的材料之一,其抗压强度是评估混凝土质量和结构承载能力的重要指标。准确预测混凝土抗压强度对于设计和施工过程至关重要,有助于确保结构的安全性和可靠性。
过去,混凝土抗压强度的预测主要依赖于经验公式和试验数据。然而,这些方法存在一些局限性,例如需要大量实验数据、无法考虑复杂的相互作用关系和非线性效应。随着机器学习和数据分析技术的发展,利用数据驱动的方法对混凝土抗压强度进行预测成为可能。
二、数据分析
整个数据中共包含1030条数据,共计9列,对数据进行初步分析,主要查看其中是否有很多空缺信息、数据类型是否统一、是否有异常值等问题。若存在上述问题直接用这些数据进行相关分析,会使最终预测估价结果不准确,所以要先进行数据预处理,主要分为五大步骤完成。
第一步查看是否有空缺值,使用isnull()函数进行检测,其是一个用于检测缺失值的函数,用于判断数据中的每个元素是否为缺失值。它返回一个与原始数据结构相同的布尔类型的DataFrame或Series,其中缺失值位置为True,非缺失值位置为False。
# 统计每列的空值数量
null_counts = data.isnull().sum()
# 遍历输出列名和空值数量
for column, count in null_counts.items():
print(f"列名: {column},空值数量: {count}")
图1 空缺值检测代码图
第二步查看数据类型是否统一,使用表格的dtypes属性,用于获取数据的每列的数据类型。它返回每列的名称和对应的数据类型,结果显示数据均为数值型。
第三步异常值分析,使用使用箱线图方法和Z-score方法综合检测异常值,箱线图方法和Z-score方法都是常用的异常值检测方法,用于识别数据中的异常值。它们基于不同的原理和计算方法。
箱线图方法:
箱线图方法基于数据的分位数和四分位距离(IQR)来检测异常值。它的原理如下:箱线图通过绘制数据的箱体和须线来展示数据的分布情况。箱体表示数据的四分位数范围,其中箱体的上边缘是第三四分位数(Q3),下边缘是第一四分位数(Q1),箱体内部是中位数(Q2)。
须线表示数据的整体分布范围,一般由上须和下须表示。根据箱线图的定义,异常值通常被定义为位于上下须之外的数据点,可以使用箱线图中的上下须的长度和分位数的差异来确定异常值的界限,箱线图如图3所示。
Z-score方法:Z-score方法基于数据的标准差和均值来检测异常值。它的原理如下:Z-score是一种标准化的分数,表示一个数据点与均值之间的偏离程度,以标准差为单位。
Z-score计算公式为:Z = (X - μ) / σ,其中X是数据点的值,μ是数据的均值,σ是数据的标准差。根据正态分布的性质,大部分数据点的Z-score应该在-3到+3之间(约占99.7%),如果一个数据点的Z-score超过3或小于-3,则被认为是异常值。
使用这两种方法可以检测到不同类型的异常值。箱线图方法更侧重于检测数据的分布范围内的异常值,而Z-score方法更侧重于检测与数据的均值偏离较大的异常值,结果如图4所示。综合两种方法,将两种方法检测到的相同的异常值使用该列的中位数进行填充。
# 异常值分析
import matplotlib.pyplot as plt
def detect_outliers(data):
outliers = []
for column in data.columns:
# 使用箱线图检测异常值
Q1 = np.percentile(data[column], 25)
Q3 = np.percentile(data[column], 75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
column_outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)]
# 使用Z-score方法检测异常值
z_scores = (data[column] - data[column].mean()) / data[column].std()
z_score_outliers = data[np.abs(z_scores) > 3]
# 将异常值记录到列表中
outliers.append({
'Column': column,
'Boxplot Outliers': column_outliers.index.tolist(),
'Z-score Outliers': z_score_outliers.index.tolist()
})
return outliers
# 执行异常值分析
outliers = detect_outliers(data)
# 打印异常值结果
for result in outliers:
column = result['Column']
boxplot_outliers = result['Boxplot Outliers']
z_score_outliers = result['Z-score Outliers']
print(f"Column: {column}")
print(f"Boxplot Outliers: {boxplot_outliers}")
print(f"Z-score Outliers: {z_score_outliers}")
print("========================")
# 绘制箱线图
plt.figure(figsize=(12, 8))
data.boxplot()
plt.title('Boxplot of Data')
# plt.xticks(rotation=45)
# 设置全局字体大小
plt.rcParams['font.size'] = 15
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体为黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 处理列名显示
column_names = [col.split('(')[0].strip() for col in data.columns]
plt.xticks(range(1, len(column_names) + 1), column_names, rotation=45)
plt.savefig('Boxplot of Data.png',dpi=300, bbox_inches='tight')
plt.show()
三、相关性分析:热力图揭示组分影响规律
# 热力图生成代码(DOC2)
corr_matrix = data.corr(method='spearman')
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')
核心发现:
强正相关:龄期(Age, r=0.60)> 水泥用量(Cement, r=0.49)> 减水剂(Superplasticizer, r=0.46)
关键负相关:用水量(Water, r=-0.31)——印证水灰比定律
意外现象:粉煤灰(Fly Ash)与强度相关性仅0.02,需进一步研究配比优化
四、模型构建:三类回归算法实现细节对比
模型 |
MSE |
MAE |
R² |
---|---|---|---|
线性回归 |
95.64 |
7.87 |
0.64 |
随机森林 |
187.91 |
10.59 |
0.29 |
决策树 |
51.87 |
5.05 |
0.80 |
原因解读:
非线性捕捉:决策树通过多级分裂(如Age>56天且Cement>300kg/m³)精准建模强度跃迁
过拟合控制:随机森林因特征子集选择不当(忽略Age主导性)导致性能下降
五、研究展望:
引入时间序列特征:分析不同养护阶段的强度增长规律
集成学习优化:用GBDT替代随机森林,强化Age特征权重
物理约束融合:将水灰比经验公式作为模型正则项
致工程师:当数据显示龄期贡献度超60%时,或许我们该重新审视——加速养护实验能否真正替代自然养护?