第18期:制造业Hadoop应用实践 - 从数据到智能的完整闭环
导言:制造业是Hadoop大数据技术最重要的应用领域之一。本期结合真实的智能制造场景,深入讲解生产质量分析、设备预测性维护、工艺参数优化、能源管理等典型应用,从业务需求到技术实现,完整呈现Hadoop在制造业的落地实践。
18.1 制造业大数据平台整体架构
18.1.1 工业大数据平台架构设计
┌────────────────────────────────────────────────────────────────────────┐
│ 制造业Hadoop平台架构 │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ 数据采集层 │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │ PLC │ │ SCADA │ │ MES │ │ WMS │ │ APS │ │ │
│ │ └────┬───┘ └───┬────┘ └───┬────┘ └───┬────┘ └───┬────┘ │ │
│ │ │ │ │ │ │ │ │
│ └───────┼─────────┼─────────┼─────────┼─────────┼──────────────────┘ │
│ │ │ │ │ │ │
│ └─────────┼─────────┼─────────┼─────────┘ │
│ │ │ │ │
│ ┌─────────────────┼─────────┼─────────┼────────────────────────────┐│
│ │ ▼ ▼ ▼ ││
│ │ ┌────────────────────────────┐ ││
│ │ │ Apache Kafka │ ││
│ │ │ 消息总线 │ ││
│ │ └──────────┬─────────────────┘ ││
│ │ │ ││
│ └───────────────────────┼────────────────────────────────────────────┘│
│ │ │
│ ┌───────────────────────┼────────────────────────────────────────────┐│
│ │ ┌─────┴─────┐ ││
│ │ ┌────┴────┐ ┌────┴────┐ ││
│ │ │ Flink │ │ Spark │ ││
│ │ │ 实时处理 │ │ 离线处理 │ ││
│ │ └────┬────┘ └────┬────┘ ││
│ │ │ │ ││
│ └─────────────────┼───────────┼──────────────────────────────────────┘│
│ │ │ │
│ ┌─────────────────┼───────────┼──────────────────────────────────────┐│
│ │ ▼ ▼ ││
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ││
│ │ │ HDFS │ │ Iceberg │ │ HBase │ │ ES │ ││
│ │ │ 数据湖 │ │ 数据湖 │ │ KV存储 │ │ 搜索 │ ││
│ │ └────────┘ └────────┘ └────────┘ └────────┘ ││
│ └────────────────────────────────────────────────────────────────────┘│
│ │
└────────────────────────────────────────────────────────────────────────┘
#mermaid-svg-3K229wAqmZXevkDE{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3K229wAqmZXevkDE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3K229wAqmZXevkDE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3K229wAqmZXevkDE .error-icon{fill:#552222;}#mermaid-svg-3K229wAqmZXevkDE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3K229wAqmZXevkDE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3K229wAqmZXevkDE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3K229wAqmZXevkDE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3K229wAqmZXevkDE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3K229wAqmZXevkDE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3K229wAqmZXevkDE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3K229wAqmZXevkDE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3K229wAqmZXevkDE .marker.cross{stroke:#333333;}#mermaid-svg-3K229wAqmZXevkDE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3K229wAqmZXevkDE p{margin:0;}#mermaid-svg-3K229wAqmZXevkDE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-3K229wAqmZXevkDE .cluster-label text{fill:#333;}#mermaid-svg-3K229wAqmZXevkDE .cluster-label span{color:#333;}#mermaid-svg-3K229wAqmZXevkDE .cluster-label span p{background-color:transparent;}#mermaid-svg-3K229wAqmZXevkDE .label text,#mermaid-svg-3K229wAqmZXevkDE span{fill:#333;color:#333;}#mermaid-svg-3K229wAqmZXevkDE .node rect,#mermaid-svg-3K229wAqmZXevkDE .node circle,#mermaid-svg-3K229wAqmZXevkDE .node ellipse,#mermaid-svg-3K229wAqmZXevkDE .node polygon,#mermaid-svg-3K229wAqmZXevkDE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3K229wAqmZXevkDE .rough-node .label text,#mermaid-svg-3K229wAqmZXevkDE .node .label text,#mermaid-svg-3K229wAqmZXevkDE .image-shape .label,#mermaid-svg-3K229wAqmZXevkDE .icon-shape .label{text-anchor:middle;}#mermaid-svg-3K229wAqmZXevkDE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3K229wAqmZXevkDE .rough-node .label,#mermaid-svg-3K229wAqmZXevkDE .node .label,#mermaid-svg-3K229wAqmZXevkDE .image-shape .label,#mermaid-svg-3K229wAqmZXevkDE .icon-shape .label{text-align:center;}#mermaid-svg-3K229wAqmZXevkDE .node.clickable{cursor:pointer;}#mermaid-svg-3K229wAqmZXevkDE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3K229wAqmZXevkDE .arrowheadPath{fill:#333333;}#mermaid-svg-3K229wAqmZXevkDE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3K229wAqmZXevkDE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3K229wAqmZXevkDE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3K229wAqmZXevkDE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3K229wAqmZXevkDE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3K229wAqmZXevkDE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3K229wAqmZXevkDE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3K229wAqmZXevkDE .cluster text{fill:#333;}#mermaid-svg-3K229wAqmZXevkDE .cluster span{color:#333;}#mermaid-svg-3K229wAqmZXevkDE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3K229wAqmZXevkDE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3K229wAqmZXevkDE rect.text{fill:none;stroke-width:0;}#mermaid-svg-3K229wAqmZXevkDE .icon-shape,#mermaid-svg-3K229wAqmZXevkDE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3K229wAqmZXevkDE .icon-shape p,#mermaid-svg-3K229wAqmZXevkDE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3K229wAqmZXevkDE .icon-shape .label rect,#mermaid-svg-3K229wAqmZXevkDE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3K229wAqmZXevkDE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3K229wAqmZXevkDE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3K229wAqmZXevkDE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Kafka
数据湖
应用层
质量分析
预测维护
工艺优化
能源管理
处理层
Flink实时处理
Spark离线处理
数据源
PLC控制器
SCADA系统
MES系统
ERP系统
18.1.2 制造业核心业务场景
┌────────────────────────────────────────────────────────────────────┐
│ 制造业大数据应用场景矩阵 │
├──────────────┬──────────────┬──────────────┬───────────────────────┤
│ 场景 │ 数据规模 │ 实时性 │ 价值 │
├──────────────┼──────────────┼──────────────┼───────────────────────┤
│ 质量分析 │ GB/天 │ 分钟级 │ 减少次品率30% │
│ 预测维护 │ TB/月 │ 小时级 │ 降低停机50% │
│ 工艺优化 │ GB/天 │ 批处理 │ 提升良率2-5% │
│ 能源管理 │ GB/天 │ 分钟级 │ 节能10-15% │
│ 供应链优化 │ TB/月 │ 天级 │ 降低库存20% │
│ 追溯体系 │ TB/年 │ 秒级 │ 100%召回能力 │
└──────────────┴──────────────┴──────────────┴───────────────────────┘
18.2 质量分析系统
18.2.1 质量分析系统架构
#mermaid-svg-HgLH34xRlZzjZ94g{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HgLH34xRlZzjZ94g .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HgLH34xRlZzjZ94g .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HgLH34xRlZzjZ94g .error-icon{fill:#552222;}#mermaid-svg-HgLH34xRlZzjZ94g .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HgLH34xRlZzjZ94g .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HgLH34xRlZzjZ94g .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HgLH34xRlZzjZ94g .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HgLH34xRlZzjZ94g .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HgLH34xRlZzjZ94g .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HgLH34xRlZzjZ94g .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HgLH34xRlZzjZ94g .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HgLH34xRlZzjZ94g .marker.cross{stroke:#333333;}#mermaid-svg-HgLH34xRlZzjZ94g svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HgLH34xRlZzjZ94g p{margin:0;}#mermaid-svg-HgLH34xRlZzjZ94g .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-HgLH34xRlZzjZ94g .cluster-label text{fill:#333;}#mermaid-svg-HgLH34xRlZzjZ94g .cluster-label span{color:#333;}#mermaid-svg-HgLH34xRlZzjZ94g .cluster-label span p{background-color:transparent;}#mermaid-svg-HgLH34xRlZzjZ94g .label text,#mermaid-svg-HgLH34xRlZzjZ94g span{fill:#333;color:#333;}#mermaid-svg-HgLH34xRlZzjZ94g .node rect,#mermaid-svg-HgLH34xRlZzjZ94g .node circle,#mermaid-svg-HgLH34xRlZzjZ94g .node ellipse,#mermaid-svg-HgLH34xRlZzjZ94g .node polygon,#mermaid-svg-HgLH34xRlZzjZ94g .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HgLH34xRlZzjZ94g .rough-node .label text,#mermaid-svg-HgLH34xRlZzjZ94g .node .label text,#mermaid-svg-HgLH34xRlZzjZ94g .image-shape .label,#mermaid-svg-HgLH34xRlZzjZ94g .icon-shape .label{text-anchor:middle;}#mermaid-svg-HgLH34xRlZzjZ94g .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HgLH34xRlZzjZ94g .rough-node .label,#mermaid-svg-HgLH34xRlZzjZ94g .node .label,#mermaid-svg-HgLH34xRlZzjZ94g .image-shape .label,#mermaid-svg-HgLH34xRlZzjZ94g .icon-shape .label{text-align:center;}#mermaid-svg-HgLH34xRlZzjZ94g .node.clickable{cursor:pointer;}#mermaid-svg-HgLH34xRlZzjZ94g .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HgLH34xRlZzjZ94g .arrowheadPath{fill:#333333;}#mermaid-svg-HgLH34xRlZzjZ94g .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HgLH34xRlZzjZ94g .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HgLH34xRlZzjZ94g .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HgLH34xRlZzjZ94g .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HgLH34xRlZzjZ94g .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HgLH34xRlZzjZ94g .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HgLH34xRlZzjZ94g .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HgLH34xRlZzjZ94g .cluster text{fill:#333;}#mermaid-svg-HgLH34xRlZzjZ94g .cluster span{color:#333;}#mermaid-svg-HgLH34xRlZzjZ94g div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HgLH34xRlZzjZ94g .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HgLH34xRlZzjZ94g rect.text{fill:none;stroke-width:0;}#mermaid-svg-HgLH34xRlZzjZ94g .icon-shape,#mermaid-svg-HgLH34xRlZzjZ94g .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HgLH34xRlZzjZ94g .icon-shape p,#mermaid-svg-HgLH34xRlZzjZ94g .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HgLH34xRlZzjZ94g .icon-shape .label rect,#mermaid-svg-HgLH34xRlZzjZ94g .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HgLH34xRlZzjZ94g .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HgLH34xRlZzjZ94g .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HgLH34xRlZzjZ94g :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 质量看板
实时大屏
报表
告警
分析引擎
规则引擎
机器学习
统计分析
大数据平台
Kafka
Flink
Hive
质量数据源
视觉检测
传感器
工序日志
18.2.2 质量分析核心代码
python
# quality_analysis.py
from pyspark.sql import SparkSession
from pyspark.sql.functions import *
from pyspark.ml.classification import GBTClassifier
from pyspark.ml.feature import VectorAssembler
import mlflow
class QualityAnalysisSystem:
"""质量分析系统"""
def __init__(self, spark: SparkSession):
self.spark = spark
def build_quality_features(self):
"""
构建质量分析特征
"""
# 读取工单数据
workorder_df = self.spark.table("manufacturing.workorder")
# 读取检测数据
inspection_df = self.spark.table("manufacturing.inspection")
# 读取工艺参数
params_df = self.spark.table("manufacturing.process_params")
# 关联工单和检测结果
quality_df = workorder_df.join(
inspection_df,
"workorder_id"
).join(
params_df,
"workorder_id"
)
# 特征工程
feature_df = quality_df \
.withColumn("temp_std", stddev("temperature").over(
Window.partitionBy("product_id").orderBy("timestamp").rowsBetween(-10, 0)
)) \
.withColumn("pressure_trend",
(col("pressure_current") - col("pressure_initial")) / col("pressure_initial")
) \
.withColumn("is_defect",
when(col("defect_level") > 0, 1).otherwise(0)
)
return feature_df
def train_defect_prediction_model(self, train_df):
"""
训练缺陷预测模型
"""
# 特征列
feature_cols = [
"temperature", "pressure", "speed",
"humidity", "temp_std", "pressure_trend"
]
# 向量化
assembler = VectorAssembler(
inputCols=feature_cols,
outputCol="features"
)
train_data = assembler.transform(train_df).select(
"features", "is_defect"
)
# GBT分类器
gbt = GBTClassifier(
featuresCol="features",
labelCol="is_defect",
maxIter=100,
maxDepth=6
)
# 训练
model = gbt.fit(train_data)
# 记录到MLflow
with mlflow.start_run():
mlflow.spark.log_model(model, "quality_model")
return model
def real_time_quality_check(self, batch_df, model):
"""
实时质量检测
"""
# 特征工程
features = self.build_realtime_features(batch_df)
# 预测
predictions = model.transform(features)
# 质量分级
result = predictions.withColumn(
"quality_level",
when(col("probability") > 0.9, "A")
.when(col("probability") > 0.7, "B")
.when(col("probability") > 0.5, "C")
.otherwise("D")
)
return result
18.2.3 质量分析SQL查询
sql
-- quality_analytics.sql
-- 1. 实时质量统计
CREATE MATERIALIZED VIEW quality_stats_hourly AS
SELECT
window_start,
product_line,
COUNT(*) as total_count,
SUM(CASE WHEN is_defect = 1 THEN 1 ELSE 0 END) as defect_count,
ROUND(SUM(CASE WHEN is_defect = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2) as defect_rate,
AVG(quality_score) as avg_score
FROM quality_stream
WHERE is_valid = 1
GROUP BY
TUMBLE(process_time, INTERVAL '1' HOUR),
product_line;
-- 2. 缺陷类型分析
SELECT
defect_type,
COUNT(*) as count,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(), 2) as percentage,
AVG(rework_cost) as avg_cost
FROM inspection_records
WHERE inspection_date >= CURRENT_DATE - INTERVAL '30' DAY
GROUP BY defect_type
ORDER BY count DESC;
-- 3. 质量趋势分析
SELECT
inspection_date,
product_line,
defect_rate,
LAG(defect_rate, 7) OVER (PARTITION BY product_line ORDER BY inspection_date) as prev_week_rate,
defect_rate - LAG(defect_rate, 7) OVER (PARTITION BY product_line ORDER BY inspection_date) as rate_change
FROM daily_quality_stats
ORDER BY inspection_date DESC;
-- 4. 关联规则挖掘 - 找出导致缺陷的工艺参数组合
SELECT
param_set,
confidence,
lift,
support
FROM (
SELECT
CONCAT('温度:', temp_range, '|压力:', pressure_range) as param_set,
COUNT(*) / SUM(CASE WHEN is_defect = 0 THEN 1 ELSE 0 END) as support,
COUNT(CASE WHEN is_defect = 1 THEN 1 END) * 1.0 / COUNT(*) as confidence,
confidence / (SELECT AVG(defect_rate) FROM manufacturing_data) as lift
FROM manufacturing_data
GROUP BY temp_range, pressure_range
)
WHERE lift > 1.5
ORDER BY lift DESC;
18.3 预测性维护系统
18.3.1 预测性维护架构
#mermaid-svg-VGW5O21howJyBuVn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VGW5O21howJyBuVn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VGW5O21howJyBuVn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VGW5O21howJyBuVn .error-icon{fill:#552222;}#mermaid-svg-VGW5O21howJyBuVn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VGW5O21howJyBuVn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VGW5O21howJyBuVn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VGW5O21howJyBuVn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VGW5O21howJyBuVn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VGW5O21howJyBuVn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VGW5O21howJyBuVn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VGW5O21howJyBuVn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VGW5O21howJyBuVn .marker.cross{stroke:#333333;}#mermaid-svg-VGW5O21howJyBuVn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VGW5O21howJyBuVn p{margin:0;}#mermaid-svg-VGW5O21howJyBuVn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VGW5O21howJyBuVn .cluster-label text{fill:#333;}#mermaid-svg-VGW5O21howJyBuVn .cluster-label span{color:#333;}#mermaid-svg-VGW5O21howJyBuVn .cluster-label span p{background-color:transparent;}#mermaid-svg-VGW5O21howJyBuVn .label text,#mermaid-svg-VGW5O21howJyBuVn span{fill:#333;color:#333;}#mermaid-svg-VGW5O21howJyBuVn .node rect,#mermaid-svg-VGW5O21howJyBuVn .node circle,#mermaid-svg-VGW5O21howJyBuVn .node ellipse,#mermaid-svg-VGW5O21howJyBuVn .node polygon,#mermaid-svg-VGW5O21howJyBuVn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VGW5O21howJyBuVn .rough-node .label text,#mermaid-svg-VGW5O21howJyBuVn .node .label text,#mermaid-svg-VGW5O21howJyBuVn .image-shape .label,#mermaid-svg-VGW5O21howJyBuVn .icon-shape .label{text-anchor:middle;}#mermaid-svg-VGW5O21howJyBuVn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VGW5O21howJyBuVn .rough-node .label,#mermaid-svg-VGW5O21howJyBuVn .node .label,#mermaid-svg-VGW5O21howJyBuVn .image-shape .label,#mermaid-svg-VGW5O21howJyBuVn .icon-shape .label{text-align:center;}#mermaid-svg-VGW5O21howJyBuVn .node.clickable{cursor:pointer;}#mermaid-svg-VGW5O21howJyBuVn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VGW5O21howJyBuVn .arrowheadPath{fill:#333333;}#mermaid-svg-VGW5O21howJyBuVn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VGW5O21howJyBuVn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VGW5O21howJyBuVn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VGW5O21howJyBuVn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VGW5O21howJyBuVn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VGW5O21howJyBuVn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VGW5O21howJyBuVn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VGW5O21howJyBuVn .cluster text{fill:#333;}#mermaid-svg-VGW5O21howJyBuVn .cluster span{color:#333;}#mermaid-svg-VGW5O21howJyBuVn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VGW5O21howJyBuVn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VGW5O21howJyBuVn rect.text{fill:none;stroke-width:0;}#mermaid-svg-VGW5O21howJyBuVn .icon-shape,#mermaid-svg-VGW5O21howJyBuVn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VGW5O21howJyBuVn .icon-shape p,#mermaid-svg-VGW5O21howJyBuVn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VGW5O21howJyBuVn .icon-shape .label rect,#mermaid-svg-VGW5O21howJyBuVn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VGW5O21howJyBuVn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VGW5O21howJyBuVn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VGW5O21howJyBuVn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 决策支持
维护计划
备件预测
告警通知
分析引擎
健康评估
剩余寿命预测
故障诊断
数据存储
时序存储
机器学习
数据采集
振动传感器
温度传感器
电流传感器
油液传感器
18.3.2 设备健康评估模型
python
# predictive_maintenance.py
import numpy as np
from pyspark.ml.regression import GBTRegressor
from pyspark.sql.functions import col, window
class PredictiveMaintenanceSystem:
"""预测性维护系统"""
def __init__(self, spark):
self.spark = spark
def extract_vibration_features(self, vibration_data):
"""
从振动信号中提取特征
"""
from scipy import signal
def extract_features(signal_array):
features = {}
# 时域特征
features['mean'] = np.mean(signal_array)
features['std'] = np.std(signal_array)
features['rms'] = np.sqrt(np.mean(signal_array**2))
features['peak'] = np.max(np.abs(signal_array))
features['crest_factor'] = features['peak'] / features['rms']
features['kurtosis'] = np.mean((signal_array / features['std'])**4) - 3
# 频域特征
freqs, psd = signal.welch(signal_array, fs=10000)
# 频谱重心
features['spectral_centroid'] = np.sum(freqs * psd) / np.sum(psd)
# 能量分布
low_freq_energy = np.sum(psd[freqs < 1000])
mid_freq_energy = np.sum(psd[(freqs >= 1000) & (freqs < 5000)])
high_freq_energy = np.sum(psd[freqs >= 5000])
features['low_freq_ratio'] = low_freq_energy / np.sum(psd)
features['mid_freq_ratio'] = mid_freq_energy / np.sum(psd)
features['high_freq_ratio'] = high_freq_energy / np.sum(psd)
return features
# 窗口特征提取
window_spec = Window.orderBy("timestamp").rowsBetween(-1000, 0)
return (vibration_data
.withColumn("features", extract_features_udf(col("vibration_signal")))
.select("machine_id", "timestamp", "features.*"))
def calculate_rul(self, machine_df):
"""
计算设备剩余使用寿命
使用特征: 振动RMS, 温度趋势, 功率波动
"""
# 构建特征
feature_cols = ["vibration_rms", "temp_increase", "power_fluctuation"]
assembler = VectorAssembler(
inputCols=feature_cols,
outputCol="features"
)
# 标注RUL
labeled_df = machine_df.withColumn(
"rul",
when(col("health_status") == "failed", 0)
.when(col("maintenance_date").isNotNull(),
datediff(col("maintenance_date"), col("timestamp")))
.otherwise(lit(365)) # 未故障假设剩余365天
)
# 过滤异常值
clean_df = labeled_df.filter(col("rul") >= 0)
# 训练RUL预测模型
train_data = assembler.transform(clean_df).select("features", "rul")
gbt = GBTRegressor(
featuresCol="features",
labelCol="rul",
maxIter=100,
maxDepth=5
)
model = gbt.fit(train_data)
return model
def generate_maintenance_recommendation(self, machine_id, rul_prediction):
"""
生成维护建议
"""
if rul_prediction < 7:
return {
"priority": "CRITICAL",
"action": "立即停机检修",
"estimated_duration": "4-8小时"
}
elif rul_prediction < 30:
return {
"priority": "HIGH",
"action": "计划本周维护",
"estimated_duration": "2-4小时"
}
elif rul_prediction < 90:
return {
"priority": "MEDIUM",
"action": "列入下月维护计划",
"estimated_duration": "1-2小时"
}
else:
return {
"priority": "LOW",
"action": "正常巡检",
"estimated_duration": "30分钟"
}
18.4 能源管理系统
18.4.1 能源管理数据模型
┌────────────────────────────────────────────────────────────────────┐
│ 能源管理数据模型 │
├────────────────────────────────────────────────────────────────────┤
│ │
│ 能源消费实体 (Energy_Consumption) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Field │ Type │ Description │ │
│ ├────────────────────┼────────────┼──────────────────────────┤ │
│ │ consumption_id │ BIGINT PK │ 消费记录ID │ │
│ │ machine_id │ STRING │ 设备ID │ │
│ │ meter_id │ STRING │ 电表ID │ │
│ │ timestamp │ TIMESTAMP │ 采集时间 │ │
│ │ power_kw │ DOUBLE │ 瞬时功率 (kW) │ │
│ │ energy_kwh │ DOUBLE │ 累计能耗 (kWh) │ │
│ │ voltage_v │ DOUBLE │ 电压 (V) │ │
│ │ current_a │ DOUBLE │ 电流 (A) │ │
│ │ power_factor │ DOUBLE │ 功率因数 │ │
│ │ production_count │ INT │ 产出数量 │ │
│ └────────────────────┴────────────┴──────────────────────────┘ │
│ │
│ 能源成本实体 (Energy_Cost) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Field │ Type │ Description │ │
│ ├────────────────────┼────────────┼──────────────────────────┤ │
│ │ time_period │ STRING │ 时段 (峰/平/谷) │ │
│ │ unit_price │ DOUBLE │ 单价 (元/kWh) │ │
│ │ demand_price │ DOUBLE │ 需量单价 (元/kW) │ │
│ │ peak_start │ STRING │ 峰时段开始 │ │
│ │ peak_end │ STRING │ 峰时段结束 │ │
│ └────────────────────┴────────────┴──────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────┘
18.4.2 能源分析代码
sql
-- energy_analysis.sql
-- 1. 能耗统计报表
CREATE MATERIALIZED VIEW energy_daily_report AS
SELECT
DATE(tr.timestamp) as date,
e.machine_id,
m.machine_type,
m.production_line,
SUM(e.energy_kwh) as total_energy,
SUM(e.energy_kwh) / NULLIF(SUM(e.production_count), 0) as unit_energy,
AVG(e.power_kw) as avg_power,
MAX(e.power_kw) as peak_power,
CASE
WHEN HOUR(tr.timestamp) BETWEEN 8 AND 11 THEN 'peak'
WHEN HOUR(tr.timestamp) BETWEEN 6 AND 8 OR BETWEEN 11 AND 22 THEN 'flat'
ELSE 'valley'
END as time_period
FROM energy_consumption e
JOIN machine_master m ON e.machine_id = m.machine_id
GROUP BY
DATE(tr.timestamp), e.machine_id, m.machine_type, m.production_line;
-- 2. 能耗异常检测
SELECT
machine_id,
timestamp,
power_kw,
AVG(power_kw) OVER (PARTITION BY machine_id ORDER BY timestamp
ROWS BETWEEN 60 PRECEDING AND 1 PRECEDING) as avg_power_1h,
power_kw - AVG(power_kw) OVER (PARTITION BY machine_id ORDER BY timestamp
ROWS BETWEEN 60 PRECEDING AND 1 PRECEDING) as power_deviation,
STDDEV(power_kw) OVER (PARTITION BY machine_id ORDER BY timestamp
ROWS BETWEEN 60 PRECEDING AND 1 PRECEDING) as power_std_1h
FROM energy_consumption
WHERE ABS(power_kw - (
SELECT AVG(power_kw)
FROM energy_consumption prev
WHERE prev.machine_id = energy_consumption.machine_id
AND prev.timestamp >= energy_consumption.timestamp - INTERVAL '1' HOUR
)) > 3 * (
SELECT STDDEV(power_kw)
FROM energy_consumption prev
WHERE prev.machine_id = energy_consumption.machine_id
AND prev.timestamp >= energy_consumption.timestamp - INTERVAL '1' HOUR
)
AND timestamp >= CURRENT_DATE - 7;
-- 3. 需量预测与优化
WITH demand_data AS (
SELECT
DATE(timestamp) as date,
MAX(power_kw) as max_demand,
AVG(power_kw) as avg_demand
FROM energy_consumption
WHERE timestamp >= CURRENT_DATE - 30
GROUP BY DATE(timestamp)
),
demand_forecast AS (
SELECT
date,
max_demand,
AVG(max_demand) OVER (ORDER BY date ROWS BETWEEN 7 PRECEDING AND 1 PRECEDING) as rolling_avg_demand,
MAX(max_demand) OVER (ORDER BY date ROWS BETWEEN 7 PRECEDING AND 1 PRECEDING) as rolling_max_demand
FROM demand_data
)
SELECT
date,
max_demand,
rolling_avg_demand,
rolling_max_demand,
CASE
WHEN max_demand > rolling_avg_demand * 1.1 THEN 'REDUCE_DEMAND'
WHEN max_demand > rolling_avg_demand * 1.05 THEN 'MONITOR'
ELSE 'NORMAL'
END as demand_status,
CASE
WHEN max_demand > rolling_avg_demand * 1.1
THEN ROUND((max_demand - rolling_avg_demand) * 0.8, 2)
ELSE 0
END as recommended_load_reduction_kw
FROM demand_forecast
ORDER BY date DESC;
-- 4. 设备能效排名
SELECT
machine_id,
machine_name,
production_line,
total_energy,
total_production,
unit_energy,
RANK() OVER (PARTITION BY production_line ORDER BY unit_energy ASC) as efficiency_rank,
CASE
WHEN unit_energy < avg_unit_energy * 0.8 THEN 'HIGH_EFFICIENCY'
WHEN unit_energy > avg_unit_energy * 1.2 THEN 'LOW_EFFICIENCY'
ELSE 'NORMAL'
END as efficiency_status
FROM (
SELECT
m.machine_id,
m.machine_name,
m.production_line,
SUM(e.energy_kwh) as total_energy,
SUM(e.production_count) as total_production,
SUM(e.energy_kwh) / NULLIF(SUM(e.production_count), 0) as unit_energy,
AVG(SUM(e.energy_kwh) / NULLIF(SUM(e.production_count), 0))
OVER (PARTITION BY m.production_line) as avg_unit_energy
FROM energy_consumption e
JOIN machine_master m ON e.machine_id = m.machine_id
WHERE e.timestamp >= CURRENT_DATE - 30
GROUP BY m.machine_id, m.machine_name, m.production_line
) t
ORDER BY production_line, efficiency_rank;
18.5 完整应用案例
18.5.1 某汽车零部件工厂案例
┌────────────────────────────────────────────────────────────────────┐
│ 某汽车零部件工厂Hadoop应用案例 │
├────────────────────────────────────────────────────────────────────┤
│ │
│ 项目背景: │
│ - 工厂: 3个车间,20条产线,500+台设备 │
│ - 年产值: 10亿元 │
│ - 主要产品: 发动机缸体、变速箱壳体、底盘件 │
│ │
│ 痛点问题: │
│ 1. 设备综合效率(OEE)仅65%,低于行业平均水平80% │
│ 2. 质量问题追溯困难,平均追溯时间4小时 │
│ 3. 能源成本占比高,年能耗费用8000万元 │
│ 4. 计划外停机频繁,年停机损失2000万元 │
│ │
│ 技术方案: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 数据层: Kafka + HDFS + HBase + Iceberg │ │
│ │ 处理层: Flink实时处理 + Spark离线分析 │ │
│ │ 应用层: 质量分析 + 预测维护 + 能源管理 + 追溯系统 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 实施效果: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 指标 │ 实施前 │ 实施后 │ 提升 │ │
│ ├───────────────────┼───────────┼───────────┼────────────────┤ │
│ │ OEE │ 65% │ 82% │ +17% │ │
│ │ 缺陷率 │ 3.5% │ 1.2% │ -66% │ │
│ │ 追溯时间 │ 4小时 │ 5分钟 │ -98% │ │
│ │ 设备可用率 │ 90% │ 96% │ +6% │ │
│ │ 能源成本 │ 8000万 │ 6800万 │ -15% │ │
│ │ 停机损失 │ 2000万 │ 600万 │ -70% │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ROI: 投资回报周期18个月,年度综合收益3200万元 │
│ │
└────────────────────────────────────────────────────────────────────┘
18.6 知识体系总结
#mermaid-svg-BEmp8ftKVlU6hDtt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BEmp8ftKVlU6hDtt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BEmp8ftKVlU6hDtt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BEmp8ftKVlU6hDtt .error-icon{fill:#552222;}#mermaid-svg-BEmp8ftKVlU6hDtt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BEmp8ftKVlU6hDtt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BEmp8ftKVlU6hDtt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BEmp8ftKVlU6hDtt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BEmp8ftKVlU6hDtt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BEmp8ftKVlU6hDtt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BEmp8ftKVlU6hDtt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BEmp8ftKVlU6hDtt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BEmp8ftKVlU6hDtt .marker.cross{stroke:#333333;}#mermaid-svg-BEmp8ftKVlU6hDtt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BEmp8ftKVlU6hDtt p{margin:0;}#mermaid-svg-BEmp8ftKVlU6hDtt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BEmp8ftKVlU6hDtt .cluster-label text{fill:#333;}#mermaid-svg-BEmp8ftKVlU6hDtt .cluster-label span{color:#333;}#mermaid-svg-BEmp8ftKVlU6hDtt .cluster-label span p{background-color:transparent;}#mermaid-svg-BEmp8ftKVlU6hDtt .label text,#mermaid-svg-BEmp8ftKVlU6hDtt span{fill:#333;color:#333;}#mermaid-svg-BEmp8ftKVlU6hDtt .node rect,#mermaid-svg-BEmp8ftKVlU6hDtt .node circle,#mermaid-svg-BEmp8ftKVlU6hDtt .node ellipse,#mermaid-svg-BEmp8ftKVlU6hDtt .node polygon,#mermaid-svg-BEmp8ftKVlU6hDtt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BEmp8ftKVlU6hDtt .rough-node .label text,#mermaid-svg-BEmp8ftKVlU6hDtt .node .label text,#mermaid-svg-BEmp8ftKVlU6hDtt .image-shape .label,#mermaid-svg-BEmp8ftKVlU6hDtt .icon-shape .label{text-anchor:middle;}#mermaid-svg-BEmp8ftKVlU6hDtt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BEmp8ftKVlU6hDtt .rough-node .label,#mermaid-svg-BEmp8ftKVlU6hDtt .node .label,#mermaid-svg-BEmp8ftKVlU6hDtt .image-shape .label,#mermaid-svg-BEmp8ftKVlU6hDtt .icon-shape .label{text-align:center;}#mermaid-svg-BEmp8ftKVlU6hDtt .node.clickable{cursor:pointer;}#mermaid-svg-BEmp8ftKVlU6hDtt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BEmp8ftKVlU6hDtt .arrowheadPath{fill:#333333;}#mermaid-svg-BEmp8ftKVlU6hDtt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BEmp8ftKVlU6hDtt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BEmp8ftKVlU6hDtt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BEmp8ftKVlU6hDtt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BEmp8ftKVlU6hDtt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BEmp8ftKVlU6hDtt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BEmp8ftKVlU6hDtt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BEmp8ftKVlU6hDtt .cluster text{fill:#333;}#mermaid-svg-BEmp8ftKVlU6hDtt .cluster span{color:#333;}#mermaid-svg-BEmp8ftKVlU6hDtt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BEmp8ftKVlU6hDtt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BEmp8ftKVlU6hDtt rect.text{fill:none;stroke-width:0;}#mermaid-svg-BEmp8ftKVlU6hDtt .icon-shape,#mermaid-svg-BEmp8ftKVlU6hDtt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BEmp8ftKVlU6hDtt .icon-shape p,#mermaid-svg-BEmp8ftKVlU6hDtt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BEmp8ftKVlU6hDtt .icon-shape .label rect,#mermaid-svg-BEmp8ftKVlU6hDtt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BEmp8ftKVlU6hDtt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BEmp8ftKVlU6hDtt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BEmp8ftKVlU6hDtt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 制造业应用
质量分析
预测维护
能源管理
追溯系统
SPC统计
缺陷预测
根因分析
振动分析
RUL预测
健康评估
能耗统计
需量优化
设备排名
批次追溯
全链路追踪
| 应用场景 | 核心算法 | 技术栈 | 业务价值 |
|---|---|---|---|
| 质量分析 | GBT分类, 关联规则 | Spark MLlib | 缺陷率降低66% |
| 预测维护 | LSTM, XGBoost | TensorFlow | 停机损失降低70% |
| 能源管理 | 时序分析, 需量预测 | Flink SQL | 能耗降低15% |
| 追溯系统 | 图数据库, 全文检索 | Neo4j, ES | 追溯时间从4h→5min |
下期预告
第19期我们将深入探讨《能源行业Hadoop应用实践》,讲解电力、石油、煤炭等能源行业的Hadoop大数据解决方案。敬请期待!
作者:高炉炼铁智能化技术研究者,专注钢铁冶金与人工智能 交叉领域。
👍 如果觉得有帮助,请点赞、收藏、转发!
版权归作者所有,未经许可请勿抄袭,套用,商用(或其它具有利益性行为) 。
🔔 关注专栏,不错过后续精彩内容!