LLM引导进化算法实现零样本时间序列插补

📅 2026/6/22 3:44:00
LLM引导进化算法实现零样本时间序列插补
1. 项目概述与核心价值最近在折腾时间序列数据预处理时被缺失值问题折腾得不轻。传统方法要么对数据分布假设太强要么在零样本Zero-Shot场景下——也就是没有完整、干净的训练数据可供学习时——表现乏力。正好大语言模型LLM在理解和生成序列数据方面展现出的惊人能力给了我灵感能不能让LLM来引导一个进化算法智能地“想象”并填补时间序列里的那些空缺这个想法催生了“基于LLM引导进化的零样本时间序列插补算法”这个项目。简单说它不依赖任何历史完整数据进行训练只利用待插补序列自身的信息和LLM的常识推理能力通过模拟生物进化的过程迭代地生成并优化插补值。这玩意儿有什么用想象一下你手头有一段传感器采集的工业设备温度读数中间因为传输故障丢了几小时的数据。你没有这台设备其他时段的完整数据来训练模型但生产分析又急需连续的数据。这时候零样本插补的价值就凸显了。它尤其适合数据稀缺的冷启动场景、涉及隐私无法共享训练数据的领域或者像金融、物联网设备监测这种数据模式复杂多变、难以用单一模型概括的情况。核心就一句话给你一段有坑的序列利用算法自身的“想象力”和“进化力”把坑填上而且填得合理。2. 核心思路与架构设计2.1 为什么是“LLM引导”加“进化算法”传统时间序列插补比如用线性插值、移动平均或者更高级的KNN、MICE乃至深度学习模型如LSTM、Transformer大多有个前提要么数据缺失模式简单如随机缺失要么你有大量相似序列可以学习。但在零样本下这些方法要么太粗糙要么根本没法用。LLM的引入核心是解决“合理性”问题。时间序列不是随机数字它背后有物理过程、业务逻辑。LLM虽然不直接懂时间序列但它通过海量文本训练内化了丰富的关于趋势、周期、关联性的常识。我们可以通过精心设计的提示词Prompt让LLM扮演一个“序列合理性评判官”或“补全建议生成器”。例如给LLM看一段序列的前后文让它生成几个可能的延续片段或者让它判断某个插补候选序列是否“看起来自然”。但LLM生成的内容是离散的、一次性的且直接生成数值序列的效果并不稳定。这就需要进化算法EA出场了。进化算法擅长在连续或离散的空间中进行全局搜索和优化。我们将待插补的缺失位置视为需要优化的“基因”LLM则提供进化过程中的“环境选择压力”和“变异启发”。具体来说进化算法负责生成和维护一群插补方案种群LLM则被用来评估这些方案的合理性适应度计算或者指导如何产生新的、更合理的方案交叉和变异操作。这个组合的优势在于零样本性完全依赖待处理序列的上下文和LLM的通用知识无需额外训练数据。灵活性可以轻松整合领域知识通过提示词注入适应多种序列类型经济指标、传感器信号、医疗信号等。全局优化进化算法能避免陷入局部最优找到整体上更连贯的插补序列。2.2 整体算法流程设计整个算法的骨架是一个经典的进化算法循环但关键环节引入了LLM的引导。下图清晰地展示了这个迭代优化过程flowchart TD A[输入: 带缺失值的时间序列] -- B[初始化种群br随机生成或基于简单插补] B -- C{进化迭代开始} C -- D[适应度评估br利用LLM评估序列合理性] D -- E[选择操作br保留高适应度个体] E -- F[交叉与变异操作brLLM引导生成更合理的候选] F -- G{是否满足终止条件?br如达到最大迭代次数或适应度收敛} G -- 否 -- C G -- 是 -- H[输出最优插补序列]这个流程的核心在于两个LLM深度参与的环节适应度评估D这是LLM的核心作用之一。我们设计一个提示词将候选的完整序列已插补以某种形式如文本描述、数值列表附带上下文提交给LLM要求LLM对其连贯性、合理性、与上下文的一致性进行评分或排序。这个评分即为适应度。交叉与变异引导F除了随机变异我们可以使用LLM进行智能变异。例如将种群中表现较好的个体片段展示给LLM并询问“基于这些高质量片段如何改进另一个个体的某个片段使其更合理” LLM的文本生成能力可以转化为对数值调整方向的启发。2.3 关键技术组件选型LLM的选择与接入选择考虑到需要较强的推理和指令跟随能力优先选择开源或API易用的模型如Qwen系列Qwen2.5-7B/14B-Instruct、Llama 3.18B/70B-Instruct或DeepSeek-V2。对于快速原型可以使用OpenAI的GPT-4o/GPT-3.5-Turbo的API但需考虑成本和延迟。本项目示例将使用Qwen2.5-7B-Instruct的本地部署版本兼顾能力与可控性。提示词工程这是项目的灵魂。提示词需要将数值序列转化为LLM能理解的形式。一种有效方法是“文本化描述”不直接给一长串数字而是描述序列的走势、关键点、上下文并让LLM基于此进行推理。另一种是“格式化数值列表配合指令”要求LLM严格按给定格式输出评估分数。进化算法框架选择采用差分进化Differential Evolution, DE作为基础框架。DE在连续优化问题上表现鲁棒且参数较少。我们将每个缺失值位置视为一个连续变量基因整个插补方案就是一个个体染色体。也可以考虑遗传算法GA如果我们将插补值离散化到某个精度。但DE在处理连续值插补时通常更方便。序列表示与适应度函数表示一个个体是一个向量长度等于缺失值的总数每个基因值对应一个缺失点的插补数值。适应度函数这是连接数值优化和LLM语义评判的桥梁。基本思路是将个体基因值填充回原始序列形成完整的候选序列C。然后构建一个提示词Prompt(C)发送给LLM解析LLM的返回结果得到一个合理性分数Score LLM_Eval(Prompt(C))。这个分数就是适应度我们需要最大化它。3. 核心细节解析与实操要点3.1 如何让LLM“理解”并评估时间序列这是最大的挑战。LLM是文本模型对纯数字列表不敏感。我们需要进行巧妙的“数据转换”。方法一文本描述法推荐用于复杂模式将序列C转换成一段自然语言描述。例如“这是一段每小时记录的温度时间序列共24个点。前6小时数值平稳在22度左右。随后第7到18小时数据缺失。已知缺失期开始前是22度缺失期结束后是26度。整个序列的背景是夏季白天的室内温度。请评估我为你补全的中间12小时数据是否合理[23.1, 23.5, 24.0, 24.8, 25.2, 25.5, 25.7, 25.9, 26.0, 26.0, 25.8, 25.5]。请只输出一个0到10的合理性分数10分最合理。”这种方法利用了LLM对物理世界的常识如温度变化惯性、昼夜温差。但描述生成和结果解析需要额外处理。方法二结构化指令法推荐用于相对规整的序列设计一个严格的指令让LLM专注于数值关系。例如你是一个时间序列一致性检查器。请严格评估以下序列的合理性。 已知上下文序列的前5个值为[10.2, 11.0, 10.8, 11.5, 12.1]。序列的后5个值为[14.0, 13.5, 13.0, 12.8, 12.5]。 需要评估的中间缺失部分共5个值候选为[12.5, 13.2, 13.8, 14.2, 14.0]。 评估规则 1. 整体趋势是否平滑无剧烈跳变 2. 候选部分是否与前后上下文趋势衔接自然 3. 数值范围是否符合上下文暗示的范围 请基于以上三点给出一个综合评分0-10分可保留一位小数。只输出分数。这种方法更可控但要求序列模式本身能被几条简单规则概括。实操心得温度Temperature参数设置在调用LLM进行确定性评估时应将温度设为0或接近0以确保相同输入得到相同输出保证进化算法评估的稳定性。系统提示词System Prompt预先给LLM一个明确的角色定义如“你是一个严谨的时间序列分析专家”能显著提升评估的一致性。成本与延迟每次适应度评估都需要调用LLM这是主要开销。对于长序列或大种群可以考虑1对序列进行分段评估再聚合分数2使用较小的LLM如7B模型进行初步筛选再用大模型精评3缓存相同或相似序列的评估结果。3.2 进化算法的具体设计与调参我们以差分进化DE为例说明如何将其适配到本任务。个体编码假设原始序列长度为T有M个位置缺失。一个个体就是一个M维向量X [x1, x2, ..., xM]其中xi是对第i个缺失值的插补提议。初始种群可以随机生成在已知数据最小最大值范围内也可以用线性插值的结果加上随机扰动来初始化以加快收敛。适应度函数封装编写函数fitness(X)输入个体向量X。步骤将X中的值按顺序填回原序列的缺失位置得到完整候选序列C。调用get_llm_score(C)函数内部实现上述提示词构建与LLM调用。返回LLM给出的分数。DE通常最小化目标函数所以我们可以返回-score。DE关键参数种群大小NP一般设为5*M到10*M。M较小时如10NP可以大些50-100以增加多样性。缩放因子F控制变异步长通常在[0.4, 1.0]之间。可以从0.5开始尝试。交叉概率CR控制个体更新程度通常在[0.7, 0.9]之间。较高的CR有助于快速传播优良基因。最大迭代次数max_iter由于LLM调用昂贵需要设置一个合理的上限如50-200代。可以结合早停机制如连续10代最优适应度提升小于阈值。LLM引导的变异增强 这是区别于标准DE的地方。除了标准的“DE/rand/1”变异策略我们可以定期比如每5代进行一次“LLM启发式变异”从当前种群中选择适应度最高的几个个体精英。将这些精英个体对应的完整序列片段特别是缺失部分用文本描述给LLM。提问LLM“这些是当前找到的合理补全片段。如果我想让一个新片段在保持平滑过渡的前提下体现出一些符合常理的波动你有什么建议请输出一个通用的调整模式描述例如‘先小幅上升后平稳’或‘呈缓坡上升趋势’。”解析LLM返回的文本描述将其转化为一个简单的趋势函数如线性上升、正弦波并用这个趋势去修正新生成或表现较差的个体为其增加一个偏向合理趋势的扰动。注意LLM引导的变异是启发式的可能不稳定。建议将其作为一个辅助操作权重不宜过高并且要仔细设计提示词以确保LLM输出可解析的、有意义的趋势描述。4. 完整实现过程与代码解析下面我们使用Python结合deap进化算法库和qianfan用于调用千帆大模型此处以百度千帆为例亦可替换为openai、transformers等库来实现一个基础版本。4.1 环境准备与依赖安装首先确保你的Python环境建议3.9以上并安装必要库。pip install deap numpy pandas requests # 如果你使用本地部署的Qwen需要安装相应的LLM调用库例如 vllm 或 transformers # pip install vllm # 或者使用OpenAI API兼容的库 # pip install openai本例中我们将模拟一个LLM评分函数。在实际应用中你需要将其替换为真实的LLM API调用或本地模型调用。4.2 数据准备与问题定义假设我们有一段包含缺失值用np.nan表示的时间序列数据。import numpy as np import pandas as pd from deap import base, creator, tools, algorithms import random # 1. 定义原始序列示例一个带有缺失段的正弦波叠加趋势 np.random.seed(42) T 50 time np.arange(T) # 生成基础序列趋势 周期 噪声 trend 0.05 * time seasonal 5 * np.sin(2 * np.pi * time / 20) noise np.random.normal(0, 0.5, T) full_series trend seasonal noise # 人为制造缺失段索引从15到24缺失 missing_mask np.full(T, False) missing_mask[15:25] True # 缺失10个点 observed_series full_series.copy() observed_series[missing_mask] np.nan print(f序列长度: {T}) print(f缺失点数量: {missing_mask.sum()}) print(f缺失位置索引: {np.where(missing_mask)[0]})4.3 构建LLM模拟评估函数由于真实调用LLM成本高且慢我们先构建一个模拟函数。这个函数模拟了一个“理想”的LLM评判官它知道真实序列但算法不知道并基于插补值与真实值的接近程度以及平滑性给出分数。在实际部署时你需要用真实的API调用替换此函数。def llm_based_fitness(candidate_filled_series, observed_series, missing_mask, real_seriesNone): 模拟LLM评估插补序列的合理性。 在实际应用中此函数应包含 1. 将 candidate_filled_series 转换成提示词文本。 2. 调用LLM API。 3. 解析LLM返回的评分。 此处为演示使用一个综合评分模拟 - 若知道真实值则计算与真实值的均方误差MSE并转化为分数。 - 同时考虑序列的一阶差分平滑性。 # 模拟评分逻辑 score 10.0 # 基础分 # 惩罚1与已知观测点的差异如果算法错误修改了观测点但我们的编码应避免 # 这里我们只评估缺失部分 # 提取缺失部分 candidate_missing_part candidate_filled_series[missing_mask] # 计算平滑性惩罚缺失部分内部以及与前后的衔接 all_series candidate_filled_series # 计算一阶差分 diff np.diff(all_series) # 惩罚大的突变假设LLM不喜欢剧烈变化 smoothness_penalty np.sum(np.abs(diff) 2.0) # 假设变化大于2.0为剧烈突变 score - smoothness_penalty * 0.5 # 如果提供了真实序列用于模拟则计算准确性惩罚 if real_series is not None: real_missing_part real_series[missing_mask] mse np.mean((candidate_missing_part - real_missing_part) ** 2) # 将MSE映射到分数惩罚MSE越小越好所以惩罚越小 accuracy_penalty min(mse * 2, 5) # 限制最大惩罚 score - accuracy_penalty # 确保分数在合理范围 score max(score, 0) return score, # 注意DEAP要求适应度函数返回一个元组所以是 return score,4.4 定义进化算法问题使用DEAP库定义最大化问题因为我们要最大化LLM给出的合理性分数。# 定义问题类型最大化单一目标适应度 creator.create(FitnessMax, base.Fitness, weights(1.0,)) # 权重为正表示最大化 creator.create(Individual, list, fitnesscreator.FitnessMax) # 初始化工具箱 toolbox base.Toolbox() # 定义基因每个缺失点的值的生成函数 # 我们需要根据观测值的范围来估计基因的取值范围 observed_values observed_series[~np.isnan(observed_series)] value_min, value_max observed_values.min() - 3, observed_values.max() 3 def generate_gene(): 生成一个位于合理范围内的随机基因值插补值 return random.uniform(value_min, value_max) # 定义个体生成函数个体长度 缺失点数量 M int(missing_mask.sum()) toolbox.register(attr_float, generate_gene) toolbox.register(individual, tools.initRepeat, creator.Individual, toolbox.attr_float, nM) toolbox.register(population, tools.initRepeat, list, toolbox.individual) # 注册适应度评估函数 def evaluate(individual): 将个体插补值列表填充回原序列并调用LLM评估函数。 # 创建序列的副本 filled_series observed_series.copy() # 将个体的值填入缺失位置 filled_series[missing_mask] np.array(individual) # 调用模拟的LLM评估函数 # 注意此处传入了真实序列 full_series 仅用于模拟评分实际应用时应去掉此参数 fitness_value llm_based_fitness(filled_series, observed_series, missing_mask, real_seriesfull_series) return fitness_value toolbox.register(evaluate, evaluate) # 注册遗传算子这里使用差分进化常用的工具DEAP内置了差分进化算法 # 我们使用 tools.selBest 选择和 tools.cxSimulatedBinary 交叉 tools.mutGaussian 变异作为备选 # 但更标准的DE实现可以使用 algorithms.eaSimple 配合自定义的差分变异交叉 # 为了更贴近DE我们使用 DEAP 的 algorithms.eaSimple 并自定义变异交叉为差分策略 def mutDE(individual, F0.5): 差分变异对于每个个体随机选择三个不同的个体进行变异 pop toolbox.population(nlen(toolbox.population)) # 这需要访问种群稍后会在主循环中处理 # 这是一个简化示意实际DE变异需要种群上下文。我们将使用DEAP内置的tools.mutDE。 pass # 使用DEAP内置的差分进化算子需要从tools中导入 from deap import tools toolbox.register(select, tools.selRandom) # 差分进化需要随机选择 # 差分变异的注册稍复杂通常我们将主循环写出来而不是用eaSimple。 # 一个更直接的方式自己实现主循环以更清晰地控制差分进化过程。4.5 实现差分进化主循环由于DEAP的标准eaSimple不太适合标准的DE流程我们手动实现主循环。def differential_evolution(pop_size, F, CR, max_generations, toolbox): 实现差分进化主循环。 pop_size: 种群大小 F: 缩放因子 CR: 交叉概率 max_generations: 最大代数 toolbox: 包含evaluate和population的工具箱 # 初始化种群 pop toolbox.population(npop_size) # 评估初始种群 fitnesses list(map(toolbox.evaluate, pop)) for ind, fit in zip(pop, fitnesses): ind.fitness.values fit print(初始种群最佳适应度:, max([ind.fitness.values[0] for ind in pop])) for gen in range(max_generations): new_pop [] for i, target_ind in enumerate(pop): # 1. 变异随机选择三个不同的个体 candidates [idx for idx in range(pop_size) if idx ! i] a, b, c random.sample(candidates, 3) donor [pop[a][j] F * (pop[b][j] - pop[c][j]) for j in range(M)] # 2. 交叉生成试验个体 trial [] for j in range(M): if random.random() CR or j random.randint(0, M-1): trial.append(donor[j]) else: trial.append(target_ind[j]) # 边界处理将超出范围的基因拉回 for j in range(M): if trial[j] value_min: trial[j] value_min elif trial[j] value_max: trial[j] value_max # 3. 选择贪婪选择 trial_ind creator.Individual(trial) trial_fitness toolbox.evaluate(trial_ind) if trial_fitness[0] target_ind.fitness.values[0]: new_pop.append(trial_ind) else: new_pop.append(target_ind) # 更新种群 pop new_pop # 重新评估新种群中个体的适应度对于被替换的个体 for ind in pop: if not ind.fitness.valid: ind.fitness.values toolbox.evaluate(ind) # 记录并输出当前代信息 fits [ind.fitness.values[0] for ind in pop] if gen % 10 0: print(f第 {gen} 代, 最佳适应度: {max(fits):.4f}, 平均适应度: {np.mean(fits):.4f}) # 返回最终种群 return pop # 设置DE参数 POP_SIZE 30 # 种群大小 F 0.8 # 缩放因子 CR 0.9 # 交叉概率 MAX_GEN 100 # 最大迭代次数 print(\n开始差分进化优化...) final_pop differential_evolution(POP_SIZE, F, CR, MAX_GEN, toolbox) # 找出最优个体 best_ind tools.selBest(final_pop, k1)[0] print(f\n优化完成。最优个体适应度: {best_ind.fitness.values[0]:.4f}) print(f最优插补值: {best_ind})4.6 结果整合与可视化将最优个体的插补值填回序列并与真实序列如果已知对比。import matplotlib.pyplot as plt # 用最优个体插补 imputed_series observed_series.copy() imputed_series[missing_mask] np.array(best_ind) # 可视化 plt.figure(figsize(12, 6)) plt.plot(time, full_series, b-, label真实序列 (模拟), alpha0.7, linewidth2) plt.plot(time, observed_series, ko, label观测点 (含缺失), markersize8) plt.plot(time, imputed_series, r--, labelLLM引导进化插补结果, linewidth2) plt.fill_between(time, 0, 1, wheremissing_mask, colorgray, alpha0.3, transformplt.gca().get_xaxis_transform(), label缺失区间) plt.xlabel(时间步) plt.ylabel(值) plt.title(基于LLM引导进化的零样本时间序列插补结果) plt.legend() plt.grid(True, linestyle--, alpha0.5) plt.tight_layout() plt.show() # 计算插补误差仅在模拟环境下有意义 if full_series in locals(): mse np.mean((imputed_series[missing_mask] - full_series[missing_mask]) ** 2) print(f模拟环境下插补结果的均方误差 (MSE) 为: {mse:.6f})5. 常见问题、调优策略与避坑指南在实际操作中你会遇到各种问题。下面是我在实现和调试过程中总结的一些关键点和解决方案。5.1 LLM评估不稳定或分数无区分度问题LLM返回的评分波动大或者对所有候选都给出相似分数导致进化算法失去选择压力。排查与解决检查提示词确保你的提示词要求LLM进行相对比较或基于明确规则的绝对评分。例如“从0到10分打分”可能不如“从以下两个选项中选择更合理的一个A... B...”稳定。可以考虑让LLM对一批候选进行排序。温度参数务必设置temperature0或一个极低的值如0.1以确保输出的确定性。输出格式限制强制LLM以指定格式如“分数X”输出便于程序解析。使用系统提示词强调输出格式要求。评估维度细化在提示词中拆解评估标准如“平滑性0-3分、趋势一致性0-4分、上下文匹配度0-3分”让LLM分别打分再求和可能比单一综合评分更可靠。使用更强大的模型如果使用的小模型如7B能力不足可以考虑升级到更大参数量的模型如70B或使用专门在数学、推理任务上微调过的模型。5.2 进化算法收敛慢或陷入局部最优问题迭代很多代后适应度提升缓慢插补结果看起来仍不合理。排查与解决调整DE参数这是首要步骤。尝试不同的F和CR组合。F通常在[0.4, 1.0]CR在[0.7, 1.0]。一个经典的起始点是F0.5, CR0.9。F增大有助于探索CR增大有助于利用当前信息。增加种群多样性增大NP种群大小。也可以尝试在初始化时引入更多随机性或者定期如每20代向种群中注入一些随机新个体。引入重启机制如果连续多代没有改善保存当前最优解然后重新初始化种群除最优个体外从新的起点开始搜索。优化LLM引导变异的频率和强度如果使用了LLM引导变异降低其使用频率如每10代一次并确保其建议是方向性的、小幅度的调整而不是完全覆盖原有基因。混合策略在进化后期可以结合一些局部搜索方法。例如对最优个体进行小范围的随机扰动模拟退火思路再用LLM评估如果更好则接受。5.3 计算成本与时间过高问题每次适应度评估都调用LLM导致算法运行极慢无法处理长序列或需要大量迭代的情况。排查与解决分层评估不是对整个长序列进行评估而是将序列划分为包含缺失点的上下文窗口例如缺失点前后各取k个点只对这个子序列进行评估。这样可以显著减少提示词的长度和LLM的计算负担。代理模型训练一个轻量级的代理模型如一个小型神经网络来模拟LLM的评分行为。先用LLM评估少量样本几千个来生成训练数据训练代理模型然后在进化算法中使用快速的代理模型进行大部分评估仅定期用真实LLM校验。缓存机制对相同的或高度相似的候选序列的评估结果进行缓存。由于进化算法中个体会相似缓存命中率可能不错。并行评估种群中个体的适应度评估是独立的可以并行调用多个LLM实例如果有资源或利用LLM API的批处理功能来加速。降低迭代次数和种群大小在精度和效率间权衡。通过早停策略适应度平台期来减少不必要的迭代。5.4 序列表示与提示词工程难题问题对于某些极其复杂、高频或专业性强的时间序列简单的文本描述或格式化指令无法让LLM理解其内在模式。排查与解决特征工程不直接给原始值而是计算并给出序列的特征描述如“斜率由正转负”、“在点X处出现峰值幅度约为Y”、“具有约Z个时间步的周期性波动”。这些特征可以由传统信号处理方法提取再喂给LLM。多模态输入如果LLM支持视觉输入如GPT-4V可以将序列绘制成图让LLM“看”图评估合理性。图像往往比数字列表更直观。领域知识注入在提示词中明确加入领域知识。例如对于心电图ECG序列提示词可以写“这是一段心电图信号P波、QRS波群、T波应遵循特定形态和间期规则。请评估补全的片段是否符合医学上典型的心电图形态。”少样本示例在提示词中提供1-2个类似序列的“好”与“坏”的插补示例让LLM通过示例学习评估标准。5.5 结果合理性的人工校验无论算法多先进最终插补结果都需要结合业务常识进行人工校验。自动化算法可能生成数学上“平滑”但物理上不可能的序列例如温度瞬间跳变100度。建议始终将插补结果可视化直观检查。设置一些硬性规则过滤器例如插补值必须在物理可能的范围内变化率不能超过某个阈值。对于关键应用可以将LLM进化算法作为候选生成器生成多个合理的备选方案最后由领域专家进行选择或微调。这个项目将前沿的LLM与经典的进化算法结合为时间序列插补特别是零样本场景提供了一种新颖且富有潜力的思路。它不再仅仅是数学上的拟合而是引入了基于知识的推理和启发式搜索。虽然目前还存在计算成本高、提示词设计复杂等挑战但随着LLM效率的提升和专用化的发展这类方法在数据质量要求高、训练数据稀缺的领域如科学研究、高端制造、医疗诊断的应用前景非常广阔。