简介:这是一份面向油气行业算法工程师、地质与油藏研究人员及能源AI方向学习者的技术方案文档,围绕DeepSeek大模型在油气开采场景中的落地路径展开。内容从行业痛点与技术瓶颈剖析入手,依次覆盖多源异构数据采集与预处理、大模型因果推断理论基础、多模态特征提取适配性分析、数据标注体系与数据集构建、领域词典与知识图谱搭建、预训练数据筛选增强、基础训练框架选型与部署优化,并深入讲解因果推断算法改进、地震与测井及生产数据特征融合、LoRA轻量化微调及微调后的效果评估方法,共55个大章节。资源为1个PDF文件,压缩包约15.38MB,支持目录章节跳转、左侧书签大纲显示与章节快速定位,图文目录显示正常。已有75人学习,适合系统性掌握油气开采工艺参数与因果变量映射建模、多模态特征融合选型调参等实操要点,也可作为技术方案撰写与工程落地的参考依据。
1. 从一个 504 页 PDF 标题说起
有件事在采油厂反复上演:把近五年注水量和产油量拉出来做相关性,两条曲线几乎同步向上,于是有人主张全线提注。三个月后含水率从六成冲到八成,产油量反而掉了。问题不在数据,在于把相关当成了因果——注水量本身是被产量目标驱动的,还受地层压力、井网结构、含水阶段共同影响。这个标题要解决的正是这类问题:把开采工艺参数当成可干预变量,用因果推断回答"如果调了会怎样",用多模态特征提取把测井、示功图、时序传感器和工艺文本拧进同一个特征空间,再借 DeepSeek 做推理编排与工程化落地。它面向油气数字化团队、工业算法工程师,以及想把大模型接进真实生产系统而不是停留在 Demo 的人。
2. 开采工艺优化为什么必须先立住因果推断
2.1 把注水量当自变量做回归,会踩的三个坑
第一个坑是干预混淆。注水量不是随机分配的,它由配注方案决定,而配注方案又参考了地层压力和产量目标。这种"按结果反向调参"的机制,会让普通回归把因果方向搞反。第二个坑是时变混杂。同一口井在低含水期提注可能增产,在高含水期提注只出水,把两段数据混在一起训练,系数会被平均掉,失去指导意义。第三个坑是选择偏差。现场往往只对"看起来有潜力"的井上措施,这批井本身就比其他井好,直接比较措施井和非措施井会高估效果。
这三点决定了预测模型和优化模型是两码事。预测模型只要拟合准就行,优化模型必须能回答反事实,也就是在没有实施这个措施的反事实世界里产量会是多少。这就要求把变量明确分成三类:干预 T(注水量增量、压裂规模、举升频率)、结果 Y(产油增量、含水率变化)、混杂 X(地层渗透率、井深、井距、历史含水)。只有 X 被正确控制,估计出来的效应才可信。
2.2 干预、混杂与 CATE:一套能落到油田数据上的定义
把符号落到业务上会更清楚。T 通常取离散化的处理档位,比如注水量增量分成 0、5、10、15 方/日四档,或者取连续值做连续处理。Y 取措施后 30 天相对措施前 30 天的日均产油差,这样能抵消季节性影响。X 是措施的分配机制里涉及的所有变量,漏掉一个强混杂因子,估计就会偏。
接下来是 ATE 和 CATE 的区别。ATE 是全油田平均处理效应,告诉你"整体上提注 10 方/日能增产多少";CATE 是条件平均处理效应,告诉你"对这类井、这个含水阶段提注 10 方/日能增产多少"。工艺优化真正需要的是 CATE,因为油田不可能整体提注,只能挑井提注。CATE 的估计本质上是一个异质性建模问题,把 T 和 X 的交互项交给模型去学,学习目标不是拟合 Y,而是拟合去掉混杂后的效应。
这里要强调三个识别假设。可忽略性,即给定 X 后处理分配与潜在结果独立;重叠性,即任意 X 取值下都有一定概率被处理或不被处理;SUTVA,即一口井的处理不影响另一口井的结果。第三条在井网密集的区块尤其容易被破坏,必要时要把井组作为分析单元而不是单井。
2.3 估计器怎么选:DML、T-Learner、因果森林的取舍
| 估计器 | 适用场景 | 样本量要求 | 主要风险 |
|---|---|---|---|
| 线性 DML | 处理为连续值,效应近似线性 | 中 | 非线性效应被压平 |
| T-Learner | 处理组与对照组差异大 | 大 | 两组样本不均时方差大 |
| X-Learner | 处理组样本远少于对照组 | 中 | 实现复杂,调参成本高 |
| 因果森林 | 高维 X,需要 CATE 排序 | 大 | 外推到无重叠区域不可靠 |
| 双重稳健估计 | X 维度中等,想要置信区间 | 中 | 依赖倾向得分模型质量 |
我一般先用线性 DML 跑一版基线,拿到 ATE 和置信区间,确认方向和量级是否符合工艺常识;再用因果森林算 CATE,做井的排序。如果两版结论打架,大概率是重叠性被破坏,需要先检查倾向得分分布,而不是急着换模型。
2.4 识别假设的自检代码
import numpy as np from sklearn.ensemble import GradientBoostingClassifier from sklearn.model_selection import cross_val_predict # X: 混杂特征矩阵; T_bin: 二值化后的处理标记(如是否提注超过10方/日) ps = cross_val_predict( GradientBoostingClassifier(n_estimators=200, max_depth=3, random_state=0), X, T_bin, method="predict_proba", cv=5 )[:, 1] # 重叠性检查:倾向得分落在极端区间的样本占比 extreme = np.mean((ps < 0.05) | (ps > 0.95)) print(f"极端倾向得分占比: {extreme:.3f}") # 若超过 5%,建议裁剪样本或改用井组作为分析单元 mask = (ps >= 0.05) & (ps <= 0.95) X_trim, T_trim, Y_trim = X[mask], T_bin[mask], Y[mask]这段代码先用梯度提升树估计倾向得分,再做重叠性诊断。参数上n_estimators=200和max_depth=3是保守配置,倾向得分模型不需要太强,过强反而会把真实重叠区域切掉,这是常见误用。extreme阈值取 0.05 是经验值,油气数据处理量不大,可以放宽到 0.1。裁剪样本会改变估计目标人群,写报告时要注明结论只覆盖裁剪后的子人群,不能直接外推到全油田。
3. 多模态特征提取:把测井、示功图、时序、文本塞进同一张宽表
3.1 四类模态各自的特征化路线
| 模态 | 原始形态 | 特征化方式 | 典型特征 |
|---|---|---|---|
| 测井曲线 | 深度采样序列 | 重采样 + 分段统计 | GR/RT/DEN 均值、方差、斜率 |
| 示功图 | 载荷-位移闭合曲线 | 几何 + 频域描述 | 面积、载荷差、傅里叶系数 |
| 时序传感器 | 分钟级压力流量 | 滑动窗口统计 | 均值、方差、峰度、趋势斜率 |
| 工艺文本 | 作业日报记录 | 大模型抽取标签 | 措施类型、施工参数、异常描述 |
四条线的采样率差了几个数量级,不能简单拼接。我的做法是统一到"井-月"粒度:测井按生产层段取加权均值,示功图取当月代表性的一张做几何特征,时序做 30 天窗口统计,文本抽成结构化字段。粒度统一之后,再和 T、Y 对齐成一张宽表。
3.2 示功图转特征的最小实现
import numpy as np from scipy.fft import rfft def pump_card_features(load, disp): """load: 载荷序列(kN); disp: 位移序列(m), 长度与 load 一致""" load, disp = np.asarray(load), np.asarray(disp) area = np.trapz(load, disp) # 闭合曲线面积,反映做功 feat = { "max_load": load.max(), "min_load": load.min(), "load_range": load.max() - load.min(), "area": abs(area), "stroke": disp.max() - disp.min(), } # 归一化后取前 8 个傅里叶幅值,描述曲线形状 amp = np.abs(rfft(load - load.mean()))[:8] for i, a in enumerate(amp): feat[f"fft_{i}"] = a / (len(load) + 1e-6) # 上下冲程斜率,用于识别泵况异常 half = len(load) // 2 feat["slope_up"] = np.polyfit(disp[:half], load[:half], 1)[0] feat["slope_down"] = np.polyfit(disp[half:], load[half:], 1)[0] return feat函数把一张示功图压成 13 维特征。np.trapz算的是载荷对位移的积分,物理含义是单冲程做功,泵况变差时这个值会明显下降。傅里叶幅值前 8 项按序列长度归一化,是为了消除不同采样点数带来的量纲差异,这一步如果漏掉,同一口井换采集设备后特征会整体偏移。上下冲程斜率用最小二乘拟合,游动阀漏失时上冲程斜率会变缓,这是现场老师傅也在看的指标。注意位移序列要和载荷严格同步,现场常见的坑是两者时间戳错位半分钟,算出来的面积完全是噪声。
3.3 时间窗口对齐与工艺文本结构化
时序特征的对齐原则是"措施前窗口"和"措施后窗口"必须等长且不重叠,中间留出 7 天缓冲期,因为措施效果不会当天显现。缓冲期怎么定,取决于工艺类型:酸化、压裂的响应更快,注水调配的响应可能滞后两三周,这个参数应该由采油工程师给,而不是算法自己猜。
工艺文本的结构化可以直接调 DeepSeek API 完成,把作业日报原文连同字段定义一起放进提示词,要求输出 JSON。相比自己训一个抽取模型,这种方式冷启动成本低,遇到新措施类型时改提示词就行,不需要重新标注。代价是每次调用有成本,所以只对增量文本调用,历史文本抽取一次就落库。抽取结果作为特征入模前要做基数处理,措施类型做独热编码,施工参数做分段离散化,否则大模型输出的自由文本会污染特征矩阵。
4. CATE 建模与 DeepSeek 接入的完整实操
4.1 宽表字段与工艺参数定义
| 字段 | 角色 | 类型 | 说明 |
|---|---|---|---|
| well_id | 主键 | string | 井号 |
| month | 时间 | date | 分析月份 |
| delta_water | 干预 T | float | 注水增量(方/日) |
| oil_gain | 结果 Y | float | 日均产油增量(吨/日) |
| water_cut | 混杂 X | float | 措施前含水率 |
| perm | 混杂 X | float | 渗透率(mD) |
| net_pay | 混杂 X | float | 有效厚度(m) |
| well_space | 混杂 X | float | 井距(m) |
| pump_area | 混杂 X | float | 示功图面积特征 |
| press_std | 混杂 X | float | 井口压力 30 天标准差 |
这张表的关键点是 X 里同时包含地质静态量和生产动态量。只放静态量会漏掉含水和压力这类强混杂,而它们恰好随时间变化,是最容易造成时变混杂的来源。用因果推断做开采工艺优化时,动态混杂必须按月对齐到同一时点,不能用年末汇总值。
4.2 用 DML 估计单井注水增量效应
from econml.dml import LinearDML, CausalForestDML from sklearn.ensemble import RandomForestRegressor import numpy as np # Y: 产油增量; T: 注水增量; X: 需要估计异质性效应的特征; W: 普通混杂 model_y = RandomForestRegressor(n_estimators=300, min_samples_leaf=5, random_state=0) model_t = RandomForestRegressor(n_estimators=300, min_samples_leaf=5, random_state=0) dml = LinearDML(model_y=model_y, model_t=model_t, discrete_treatment=False, cv=5, random_state=0) dml.fit(Y, T, X=X_hetero, W=W_confound) ate = dml.ate(X=X_hetero) lb, ub = dml.ate_interval(X=X_hetero, alpha=0.05) print(f"平均处理效应 {ate:.3f} 吨/日, 95% CI [{lb:.3f}, {ub:.3f}]") # 单井 CATE 排序,用于挑井提注 cate = dml.effect(X=X_hetero) order = np.argsort(-cate)这里用了双重机器学习框架,核心是用两个辅助模型分别拟合 Y 和 T 对混杂的依赖,再对残差做因果估计,这样即使辅助模型有偏,主效应估计仍能保持一致性。cv=5是交叉拟合,防止过拟合导致效应被低估,这个参数不能省。X_hetero放的是希望看异质性的变量,比如含水率区间和井距;W_confound放的是需要控制但不关心异质性的变量。ate_interval给出的置信区间是挑井的依据,后文会讲怎么用它设门槛。换CausalForestDML可以得到非线性的 CATE,但样本少于两千条时置信区间会明显变宽,这种时候宁可回到线性版本。
4.3 DeepSeek API 如何调用、什么时候本地部署 DeepSeek
估计出 CATE 只是半成品,现场要的是"这口井该怎么调"。这一步可以把 CATE 和井况喂给 DeepSeek 生成初稿建议,再由工艺人员审核。调用方式走开放平台兼容接口,几行代码就能跑通。
import os from openai import OpenAI client = OpenAI( api_key=os.environ["DEEPSEEK_API_KEY"], base_url=os.environ["DEEPSEEK_BASE_URL"], # 开放平台控制台提供的兼容地址 ) prompt = f"""你是采油工艺工程师。基于以下因果推断结果给建议: 井号 {well_id}, 建议注水增量 {delta:.1f} 方/日, 估计产油增量 CATE={cate:.2f} 吨/日, 95% CI [{lb:.2f}, {ub:.2f}], 措施前含水率 {wc:.1f}%, 渗透率 {perm:.1f} mD。 要求: 给出 3 条可执行调整建议, 每条注明适用条件和风险, 不要输出无依据的数字。""" resp = client.chat.completions.create( model="deepseek-chat", messages=[{"role": "user", "content": prompt}], temperature=0.2, # 工程场景压低随机性 max_tokens=800, ) print(resp.choices[0].message.content)temperature=0.2是工程建议场景的经验值,再高会出现自造参数的情况。max_tokens=800对应三条建议加风险说明的长度,设太大会让模型开始编造不存在的历史数据。提示词里明确写了"不要输出无依据的数字",这一句能显著降低幻觉率。
如果要接内网数据,就得考虑本地部署 DeepSeek。常见做法是用推理框架加载量化后的模型,起一个兼容 OpenAI 协议的服务,然后把base_url指向内网地址,上层代码一行不用改。选本地部署的判断标准不是数据敏感程度这么简单,还要看调用量和响应延迟要求:日均调用量小、只做文本抽取的场景,调 API 更省事;需要把 CATE 结果实时推到每口井、且数据不出园区,才值得上本地部署。另外本地部署要额外准备 GPU 显存和模型更新流程,这部分运维成本常被低估。
5. 现场落地排错:因果图校验、漂移监控与缺失处理
5.1 因果图要和采油工程师对一遍
模型跑出来的 CATE 如果和工艺常识相反,比如高含水井提注被算出正效应,先别改模型,去核对因果图。最常见的错误是把"含水率"既当成混杂又当成中介:提注导致含水上升,含水上升又影响产油,这时含水是中介变量,把它放进混杂会挡住一部分真实效应。判断方法很简单,问一句"这个变量是在措施之后才变化的吗",是就是中介,该用中介分析而不是直接控制。
因果图还要标出不可观测混杂。地层非均质性、井下设备状态这类量往往没有完整记录,如果它们同时影响配注决策和产量,可忽略性就不成立。可行的补救是找工具变量,比如同区块其他井的配注变化,或者用断点回归,利用配注方案调整的时点做准自然实验。这类方法对数据质量要求高,小样本下置信区间会很宽,要在报告里如实写明。
5.2 上线后盯哪几个数
| 监控项 | 计算方式 | 告警阈值 | 处置动作 |
|---|---|---|---|
| 特征 PSI | 当前月 vs 训练集分布 | > 0.2 | 检查数据源,考虑重训 |
| 倾向得分均值漂移 | 月度均值变化 | > 0.05 | 复核处理分配机制 |
| CATE 分布偏移 | 分位数对比 | 中位数偏移 > 20% | 分区块重估 |
| 建议采纳率 | 现场实际执行比例 | < 40% | 回访工艺人员 |
| 预测残差自相关 | 滞后 1 期相关 | > 0.3 | 检查时序特征对齐 |
import numpy as np def psi(base, curr, bins=10): """Population Stability Index, 衡量特征分布漂移""" breakpoints = np.quantile(base, np.linspace(0, 1, bins + 1)) breakpoints[0], breakpoints[-1] = -np.inf, np.inf b = np.histogram(base, breakpoints)[0] / len(base) + 1e-6 c = np.histogram(curr, breakpoints)[0] / len(curr) + 1e-6 return np.sum((c - b) * np.log(c / b)) # 对每个入模特征算 PSI, 超过 0.2 的特征单独列出 for col in feature_cols: v = psi(train_df[col].values, curr_df[col].values) if v > 0.2: print(f"{col} PSI={v:.3f}, 需检查数据源")psi的分箱基于训练集分位数,这样保证基准分布和当前分布用同一套边界,直接对当前数据分箱会导致结果不可比。1e-6是防止某箱为空时对数发散,这个平滑项在大样本下影响可忽略。阈值 0.2 来自风控领域经验,油气数据波动更大,建议对压力、流量这类动态特征放宽到 0.25,避免频繁误报。特征 PSI 报警不等于模型失效,但如果同时出现 CATE 分布偏移,基本可以确定需要重训。
5.3 数据缺失与报错排查
油气数据缺失有两种,一种是设备离线造成的随机缺失,一种是低产井长期不计量造成的结构性缺失。前者可以插值,后者不能,因为缺失本身就和处理分配相关,插值会引入偏差。识别方法是看缺失率与产量是否相关,相关就不能简单填补,应该把缺失当成一个单独的类别入模。
常见的接口报错里,连接类问题多出在网络策略或密钥环境变量没加载,先确认DEEPSEEK_API_KEY和DEEPSEEK_BASE_URL在运行环境里能读到,而不是写死在代码里。返回内容被截断一般是max_tokens太小,长文本抽取场景要给到 2000 以上。如果返回的 JSON 解析失败,通常是提示词里没给输出示例,补一个字段完整的样例能解决大部分情况。
6. 把 504 页方案压成两周能跑通的最小验证
再完整的方案也要先做出一个能验证的小闭环,否则评审会上永远说不清效果。我的做法是砍到单区块、单工艺、单干预类型:只选一个注采井组,只研究注水量调配,只预测 30 天产油增量。数据范围缩到三年,井数控制在几十口,这样两周内能完成从特征到 CATE 的全流程。
第一步是确认数据能对齐。把测井、示功图、时序、日报四类数据按井-月聚合,统计有多少口井在三年里同时具备四类数据。如果只剩个位数,说明特征体系要简化,优先保留测井和时序,示功图可以退化成月度汇总值。这一步花一天,能省掉后面两周的返工。
第二步是跑通因果估计的最小版本,先用线性 DML 加五六个核心混杂特征,拿到 ATE 和置信区间,和领域专家给的预期范围比对。如果方向对但量级差一个数量级,多半是 Y 的单位或时间窗口定义有问题。这一步的产出不是模型,而是一张"哪些井值得提注"的排序表。
第三步是把排序表交给工艺人员盲评。挑出模型排名前 10 的井和他们凭经验选的井做对比,重合度能到六成以上,说明模型学到了业务逻辑;重合度低就要回到 2.1 那三个坑里找原因。这个对比比任何离线指标都有说服力。
最后一步是设定推荐门槛。我通常用 CATE 下界而不是点估计做门槛:只有当 CATE 的 95% 置信区间下界大于 0.5 吨/日时才进入推荐清单,上界与下界跨度超过点估计两倍的井直接排除,因为这种井的异质性估计不稳定。这套门槛会在初期过滤掉大量井,但换来的是采纳率和现场信任度,对后续要扩大范围的项目来说,这比多推几口井重要得多。
本文还有配套的精品资源,点击获取