炼铁高炉向来被称为冶金行业的黑箱,炉内上千度的还原反应无法直接观察,操作人员只能依靠传感器数据和生产经验来判断炉况。随着智慧冶金概念的普及,越来越多的钢厂开始尝试用数据驱动的方式替代纯经验操作。R语言在统计分析、时间序列建模和可视化方面的能力非常成熟,配合工业数据采集协议,完全可以搭建一套从传感器数据采集、清洗、建模到参数优化建议的完整闭环。本文将从数据采集、特征工程与预测建模、冶炼过程优化三个层面展开,给出可直接复用的R代码实现。

一、高炉传感器数据的采集与接入方案
高炉现场的数据源非常分散:炉身各层的热电偶温度、炉顶压力、冷风流量、富氧率、喷煤量、煤气成分分析仪、铁水温度等,分别来自不同的PLC和DCS系统。常见的接入方式有两种:一是通过OPC UA协议直接读取实时数据库,二是从厂级的实时数据库(如PI、InfluxDB)定时抽取。R生态中opcuadata包和httr、jsonlite组合可以覆盖这两条路径。
对于支持REST接口的实时数据库,用httr拉取数据最简单。下面的代码演示了每隔固定周期读取一批测点数据并追加到本地数据的做法:
library(httr)
library(jsonlite)
library(dplyr)
# 从实时数据库拉取高炉关键测点数据
fetch_blast_furnace_data <- function() {
resp <- GET("http://192.168.0.1:8086/api/v1/query",
query = list(db = "bf_process",
q = "SELECT mean(*) FROM sensors WHERE time > now() - 5m GROUP BY time(1m)"))
content(resp, as = "parsed", encoding = "UTF-8")
}
# 轮询采集并落盘
collect_loop <- function(interval_secs = 300, n = 100) {
for (i in seq_len(n)) {
raw <- fetch_blast_furnace_data()
df <- tryCatch(fromJSON(toJSON(raw)), error = function(e) NULL)
if (!is.null(df)) {
write.table(df, file = "C:\\BF_DATA\\raw_sensor.csv",
sep = ",", append = TRUE, row.names = FALSE, col.names = FALSE)
}
Sys.sleep(interval_secs)
}
}
采集到的原始数据往往带有工程值越限、通讯中断造成的缺失和重复记录,直接建模会引入大量噪声。清洗环节建议按三条规则处理:物理量程外的值置为NA(例如炉顶压力不可能为负)、连续缺失超过阈值的时间段整段剔除、重复时间戳只保留最后一条。R中用dplyr配合imputeTS可以快速完成:
library(imputeTS)
library(lubridate)
clean_sensor_data <- function(df) {
df %>%
mutate(
timestamp = ymd_hms(timestamp),
# 物理量程校验:炉顶压力 0~350 kPa,超出置为NA
top_pressure = ifelse(top_pressure < 0 | top_pressure > 350, NA, top_pressure),
# 铁水温度合理区间 1450~1600 摄氏度
tap_temp = ifelse(tap_temp < 1450 | tap_temp > 1600, NA, tap_temp)
) %>%
distinct(timestamp, .keep_all = TRUE) %>%
arrange(timestamp) %>%
# 短缺失用线性插值,长缺失保留NA交由下游剔除
mutate(across(where(is.numeric),
~ na_interpolation(.x, option = "linear", maxgap = 10)))
}
清洗后建议增加一个数据质量看板,统计各测点的完整率、异常率和采集延迟,用shiny做一个轻量页面,让工艺人员能第一时间发现某支热电偶失灵之类的硬件问题,避免脏数据污染后续模型。
二、时间序列特征提取与炉况预测建模
高炉过程的大滞后特性决定了不能只看瞬时值。炉温变化往往由一到两个小时之前的送风参数、配料结构累积作用引起,因此特征工程的核心是把原始时序数据扩展成带滞后和平滑窗口的特征矩阵。常用的特征包括:各参数的1~3小时滞后值、2小时滑动均值、滑动标准差、变化斜率,以及煤气利用率CO/(CO+CO2)这类衍生指标。
library(tsfeatures)
library(data.table)
build_features <- function(df, lags = c(60, 120, 180)) {
setDT(df)
# 以分钟级数据为例,构造滞后特征
for (v in c("blast_volume", "oxygen_rate", "coal_injection", "top_pressure")) {
for (k in lags) {
df[, paste0(v, "_lag", k) := shift(get(v), k)]
}
df[, paste0(v, "_ma120") := frollmean(get(v), 120, fill = NA)]
df[, paste0(v, "_sd120") := frollapply(get(v), 120, sd, fill = NA)]
}
# 煤气利用率
df[, gas_util := CO / (CO + CO2 + 1e-6)]
# 目标变量:2小时后的铁水硅含量(炉温的间接指标)
df[, target_Si := shift(Si_content, -120)]
df <- na.omit(df)
return(df)
}
铁水硅含量是判断炉温走向的关键指标,硅含量上升通常意味着炉子趋热,反之趋凉。预测未来两小时的硅含量可以为工长争取宝贵的调整时间。模型选择上,随机森林和XGBoost在高炉数据这种非线性强、特征交互多的场景表现稳定,而且输出变量重要性排序,便于工艺人员理解。下面是建模与交叉验证的完整示例:
library(randomForest)
library(xgboost)
library(caret)
set.seed(42)
train_idx <- createDataPartition(df$target_Si, p = 0.8, list = FALSE)
train <- df[train_idx]; test <- df[-train_idx]
x_cols <- grep("lag|ma|sd|gas_util|rate|volume", names(df), value = TRUE)
# 随机森林基线模型
rf_model <- randomForest(x = train[, ..x_cols], y = train$target_Si,
ntree = 500, importance = TRUE)
# XGBoost对比模型
dtrain <- xgb.DMatrix(as.matrix(train[, ..x_cols]), label = train$target_Si)
xgb_model <- xgb.train(params = list(objective = "reg:squarederror",
eta = 0.05, max_depth = 6,
subsample = 0.8, colsample_bytree = 0.8),
data = dtrain, nrounds = 800,
early_stopping_rounds = 50,
watchlist = list(val = dtrain))
pred <- predict(xgb_model, as.matrix(test[, ..x_cols]))
postResample(pred, test$target_Si) # 输出RMSE与R2
模型上线后不要一次性固化,高炉在大修、换矿种之后数据分布会漂移。建议每月用滚动窗口重新评估RMSE,一旦精度下降超过设定阈值就触发重训练。同时用randomForest的importance()输出做特征重要性分析,把喷煤量滞后两小时、风温滑动均值这类高重要性变量反馈给工艺工程师,往往能揭示一些被忽略的操作规律。
三、基于预测结果的冶炼参数寻优与决策闭环
预测模型解决的是提前感知问题,真正的价值落点在于参数优化。以炉温控制为例,当模型预测硅含量将超出目标区间时,系统需要给出喷煤量、富氧率或焦炭负荷的调整建议。一种务实的做法是基于历史数据建立反向优化:在所有与当前炉况相似的历史时段中,搜索那些最终硅含量落在目标区间的操作参数组合,取其中位数作为建议值。R中可以用FNN包快速实现近邻检索:
library(FNN)
recommend_action <- function(current_state, history, target_range = c(0.35, 0.55)) {
# 在历史库中找当前炉况的近邻片段
nn <- get.knnx(history$state_matrix, t(current_state), k = 200)
neighbors <- history$records[nn$nn.index, ]
# 只保留最终硅含量达标的近邻
good <- neighbors %>%
filter(between(next_Si, target_range[1], target_range[2]))
if (nrow(good) < 20) return(list(action = "hold", reason = "相似样本不足"))
list(
action = "adjust",
coal_injection = median(good$coal_injection),
oxygen_rate = median(good$oxygen_rate),
coke_rate = median(good$coke_rate),
confidence = nrow(good) / nrow(neighbors)
)
}
优化建议需要通过接口推送给操作端。用plumber包可以把模型和建议逻辑包装成REST服务,供DCS旁边的操作终端或MES系统调用:
library(plumber)
# model.R 放在plumber目录下即可启动
#* @apiTitle 高炉炉况优化建议服务
#* 预测未来两小时硅含量
#* @param state_json 当前测点JSON字符串
#* @post /predict
function(state_json) {
x <- jsonlite::fromJSON(state_json)
as.numeric(predict(xgb_model, as.matrix(x)))
}
#* 返回参数调整建议
#* @post /recommend
function(state_json) {
x <- jsonlite::fromJSON(state_json)
recommend_action(as.numeric(x))
}
最后需要强调的是闭环中人的角色。模型建议只能作为参考值,最终调整权必须留给工长,系统要做的是把建议值、置信度和依据的历史案例一并展示出来,用shinydashboard搭建决策支持看板是常见选择。上线初期采用建议值与实际操作值的偏差统计来评估采纳率,随着偏差逐渐收敛,再逐步提高自动化的比重。这种渐进式的落地路径在多个钢厂的实践中被证明风险最低,既能验证模型可靠性,也能让一线操作人员逐步建立对数据驱动决策的信任,最终实现稳定炉况、降低燃料比和减少质量波动的优化目标。