ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

STL分解+残差自回归:构建可解释的时间序列预测系统

STL分解+残差自回归:构建可解释的时间序列预测系统 简介一份基于季节性趋势分解STL与残差自回归的可解释时间序列预测完整项目实例适合具有Python及Pandas、Statsmodels基础的数据分析、算法开发与业务系统人员。资源围绕零售、电力、交通、制造等场景的中短期预测需求系统讲解STL将序列拆分为趋势、季节和残差后再对残差建立自回归模型的完整流程并重点覆盖滚动时间窗口验证、参数自动搜索、异常值处理、预测区间生成及GUI交互式建模。压缩包内含1个docx格式的完整文档容量142KB从项目背景、模型架构、代码示例、可视化到应用领域均有详细展开同时给出工程化部署方案与界面扩展设计便于读者直接对照实现。目前该文档已有86人学习浏览对于希望建立业务可解释预测体系、自动完成参数选择与评估的研发及管理人员是一份兼具理论讲解与代码实操价值的参考资料。1. 时间序列预测的翻车现场为什么多数模型上线后就失灵时间序列预测的场景太常见了零售要预测下个月销量、电力要预估明天负荷、运营要判断客流趋势。可现实是很多模型在离线测试时误差很漂亮上线跑一阵就崩——缺货、超储、排班不准业务侧开始怀疑算法。问题往往出在数据治理和验证方式上时间索引不连续、随机切分训练集泄露未来信息、季节周期设错任何一个都足以让预测失真。这份基于 STL 分解与残差自回归的可解释预测系统解决的正是这一连串落地问题。它把序列拆成趋势、季节、残差三项残差再用 AutoReg 建模配合滚动时间窗口验证和候选参数搜索最终输出带置信区间的预测结果与 GUI 可视化界面。适合做数据分析、算法开发或运营管理的从业者尤其是想把预测结果讲给业务听的人。下面按从理论到实现、再到踩坑的顺序完整拆一遍。2. 项目架构与建模流程为什么是 STL 叠加残差自回归2.1 分解结构与预测结果统一建模的设计思路STL 全称 Seasonal-Trend decomposition using LOESS基于局部加权回归实现。它将原始序列拆成趋势项、季节项、残差项三部分。趋势项描述长期平滑变化比如销售额逐年增长、设备效率逐步下降季节项描述固定周期内的重复模式比如工作日与周末的客流差异、夏季与冬季的用电负荷差异残差项则是趋势和季节解释不了的部分可能包含随机扰动、促销冲击、采集噪声或真实异常信号。很多序列的预测难点在于长期趋势和周期规律同时存在且互相干扰。只拿最近几个观测值做预测容易把短期噪声当趋势而用全局季节因子拟合又无法适应季节强度随时间变化的序列——电商早期促销影响弱、后来峰值逐渐增强就是典型例子。STL 的局部加权机制正好应对这种非平稳的季节性它不需要假设季节模式长期恒定这是传统季节分解做不到的。残差项的处理是这个项目的关键设计。STL 分解完成后残差不一定是白噪声很多业务序列会保留短期惯性某日订单突然增加后续几天可能持续偏高设备温度上升后短时间内不会立刻回落。项目在这里引入 AutoReg 自回归模型将当前残差表示为过去若干个残差的线性组合把短期依赖关系显式建模。趋势预测、季节延拓、残差预测三者相加得到最终预测值。这份资源选择 STL 而非直接上 ARIMA 或 LSTM核心考量是业务解释性。ARIMA 虽成熟但差分、阶数选择对业务人员不透明LSTM 精度可能更高但黑匣子式的输出很难用于决策沟通。STL 的三项分解天然对应业务归因涨是长期趋势驱动、还是季节规律驱动、还是短期事件冲击拆开就能讲清楚。2.2 滚动时间窗口验证避免未来信息泄漏的关键设计时间序列建模最忌讳的是随机切分数据。随机抽样会把未来样本混入训练集模型在验证时偷看了答案离线误差虚低上线后真实误差立刻暴露。项目中采用滚动时间窗口验证模拟真实业务场景在某个历史时点前完成训练再预测该时点之后的一段区间计算预测值与真实值的误差随后把预测起点向后移动重复多个窗口。每个窗口的误差用 RMSE 衡量。RMSE 对大误差的惩罚更重符合预测偏差影响业务决策的现实——一次大幅偏差造成的缺货或超储损失通常远大于多次小幅偏差。若预测步长为 14则每次训练完成后预测未来 14 个时间点记录该窗口 RMSE。多窗口平均 RMSE 较低的参数组合说明在不同业务时期都保持稳定而不是只在某段历史表现好。滚动验证不仅是参数选择的依据也是判断模型是否失稳的工具。如果多个窗口的误差差异很大说明序列结构随时间发生了变化这时可能需要缩短训练窗口、引入外生变量或触发模型重训。项目将滚动验证与候选参数搜索结合每一组季节周期和滞后阶数都完整跑一遍全部窗口而不是只验证最优参数避免参数选择本身过拟合。2.3 模型整体流程与各模块职责划分项目的工程路线按五层组织每一层解决一类具体问题。数据输入与时间索引规范层负责读取 CSV、治理日期格式、处理重复与缺失、推断频率并规则化重采样STL 季节性趋势分解层输出三项分解结果残差自回归建模层刻画短期依赖滚动时间窗口验证层做参数选择与误差评估预测输出与业务服务层生成预测值、置信区间与结构化结果文件。各模块之间存在明确的依赖关系数据质量直接影响分解质量分解质量决定残差是否适合自回归建模建模效果又通过滚动验证反馈到参数选择。项目将这一链路做成自动化流程用户只需准备带时间字段和数值字段的 CSV设置候选周期和候选滞后阶数系统即可完成从数据治理到预测结果导出的全流程。层核心职责关键输出数据输入层日期转换、排序去重、频率推断、缺失插值连续时间索引的单变量序列STL 分解层趋势、季节、残差三项拆分结构化分解结果残差建模层AutoReg 拟合残差短期依赖残差预测值与滞后参数滚动验证层多窗口训练预测、RMSE 评估最优参数组合与误差报告输出层未来区间预测、置信区间计算、结果保存CSV 结果文件与可视化图表个人实践中我通常把数据输入层和验证层视为项目的质量闸门。前者决定了模型看到的数据是否真实可信后者决定了参数是否经得起时间考验。图层划分的意义在于出现问题时能快速定位到具体环节而不是面对整个黑匣子无从下手。3. 数据治理与核心预测算法可复现的关键代码3.1 运行环境与全局参数配置项目基于 Python 实现依赖 Pandas 做数据处理、Statsmodels 提供 STL 和 AutoReg、Matplotlib 负责可视化。运行环境建议 Python 3.8 及以上版本Statsmodels 版本需支持 STL 接口0.12 及以上稳定版本。GUI 部分使用 Tkinter 内嵌 Matplotlib 图形无需额外安装重型框架。全局参数配置在脚本开头集中管理包括候选季节周期、候选滞后阶数、预测步长、验证窗口数等。项目给出 7、12、24、52 等周期候选值分别适用于周度、月度、小时级、年度周期明显的业务数据。滞后阶数候选集合根据序列长度设定短序列用小阶数长序列可适当加大搜索范围。配置集中放置后续替换数据集时只需要改这部分不必动核心算法代码。# config.py —— 全局参数集中管理 import pandas as pd # 数据参数 DATA_FILE data/timeseries.csv # 输入数据文件路径 DATE_COL date # 日期字段名 VALUE_COL value # 数值字段名 # STL 分解参数 SEASONAL_CANDIDATES [7, 12, 24, 52] # 候选季节周期 ROBUST True # 是否启用稳健分解 LOESS_SPAN None # LOESS 窗口跨度, None 表示自动 # 残差自回归参数 LAG_CANDIDATES [1, 2, 3, 5, 7] # 候选滞后阶数 # 滚动验证参数 FORECAST_HORIZON 14 # 预测步长: 每个窗口预测多少步 N_WINDOWS 5 # 验证窗口数量: 滑动测试几个起点 # 输出参数 OUTPUT_DIR output/ # 结果输出目录 MODEL_FILE output/best_model.pkl # 模型保存路径这里要注意几个参数的联动关系。ROBUST 参数对应 Statsmodels STL 接口中的 robust 选项置为 True 时算法会降低极端观测值的权重防止促销峰值或系统故障把趋势和季节项拉偏。LOESS_SPAN 控制局部回归的窗口长度设置为 None 让算法按序列长度自动适配避免手动调参引入的主观偏差。3.2 时间序列读取与质量治理真实业务数据几乎不可能直接建模。日期格式混用、同一时间点重复记录、缺失日期导致周期识别失真、数值列混入空值或字符这些都在数据处理阶段解决。项目采用读取—排序—去重—频率推断—重采样—插值补全的治理链路确保进入 STL 分解的数据具有一致的时间间隔。# data_prep.py —— 时间序列读取与质量治理 import pandas as pd import numpy as np def load_and_clean_series(file_path, date_col, value_col): 加载 CSV 并对时间索引做规范化处理 df pd.read_csv(file_path) df[date_col] pd.to_datetime(df[date_col]) # 统一日期格式 df df.sort_values(date_col) # 按时间升序排序 df df.drop_duplicates(subsetdate_col, keeplast) # 重复时间点保留最后一条 df df.set_index(date_col)[value_col].astype(float) # 转数值类型 # 频率推断: 无法自动识别时用户需手动指定 freq pd.infer_freq(df.index) if freq is None: raise ValueError(无法推断时间频率, 请检查数据是否存在大段缺失) # 按统一频率重建索引, 缺失时间点显式补 NaN full_index pd.date_range(df.index.min(), df.index.max(), freqfreq) series df.reindex(full_index) # 缺失值处理: 时间插值优先, 边界用前后值填充 series series.interpolate(methodtime) # 按时间间隔线性插值 series series.fillna(methodbfill).fillna(methodffill) return series逻辑说明drop_duplicates 保留最后一条记录是项目推荐的默认策略适用于同一时间点多次上报、以最新值为准的业务场景若业务语义是重复记录应累加则需改为求和或取平均。reindex 按完整时间轴重建索引使得原本隐式缺失的日期被显式标为 NaN这是 STL 能准确识别季节周期的前置条件。插值方法选择 time 而非线性插值区别在于 time 模式会按时间戳的实际间隔计算权重对时间间隔不均匀的数据更公平。需要注意边界情况。interpolate 只能填充序列中间位置首尾缺失需要用 fillna 的 bfill 和 ffill 组合兜底。实际操作中我发现数据治理的多数问题出在看起来能跑但实际上有隐患——比如某数据源把月末日期统一记为当月最后一天infer_freq 会报错再比如业务系统漏传了某天数据但不做重采样直接建模模型会把隔天数据当成连续日看待季节周期被错误压缩导致季节项估计失真。3.3 STL 分解与残差自回归的核心预测逻辑模型核心算法分三段推进先做 STL 分解再对趋势项做外推、季节项做延拓、残差项做自回归预测最后把三部分组合成最终预测值。趋势外推通常采用局部线性回归拟合最近一段趋势的斜率季节延拓直接将最新一个周期的季节均值复制到未来对应位置残差预测则由 AutoReg 模型完成。# stl_forecast.py —— STL 分解与残差自回归核心算法 import numpy as np import pandas as pd from statsmodels.tsa.seasonal import STL from statsmodels.tsa.ar_model import AutoReg def stl_decompose(series, period, robustTrue): 执行 STL 分解, 返回趋势、季节、残差三部分 stl STL(series, periodperiod, robustrobust) result stl.fit() trend result.trend seasonal result.seasonal resid result.resid return trend, seasonal, resid def forecast_with_stl(series, period, lag, horizon): 趋势外推 季节延拓 残差自回归的组合预测 # 第一步: STL 分解 trend, seasonal, resid stl_decompose(series, period) # 第二步: 趋势外推 —— 用最近 period 个点的趋势拟合直线 recent_trend trend.dropna().iloc[-period:] x np.arange(len(recent_trend)) slope, intercept np.polyfit(x, recent_trend.values, deg1) trend_forecast slope * np.arange(horizon) intercept recent_trend.iloc[-1] # 第三步: 季节延拓 —— 取最后一个完整周期的季节均值 last_season seasonal.dropna().iloc[-period:] seasonal_forecast np.tile(last_season.values, int(np.ceil(horizon / period)))[:horizon] # 第四步: 残差自回归预测 resid_clean resid.dropna() if len(resid_clean) lag 5: ar_model AutoReg(resid_clean, lagslag).fit() resid_forecast ar_model.forecast(stepshorizon) else: resid_forecast np.zeros(horizon) # 残差样本不足时退化为 0 # 组合最终预测: 趋势 季节 残差 forecast trend_forecast seasonal_forecast resid_forecast return forecast, resid_forecast逻辑说明趋势外推部分用 np.polyfit 对最近一个周期的趋势值拟合一次直线参数 deg1 表示线性拟合。为什么只取最近 period 个点因为趋势项本身是平滑后的结果近期趋势比远期趋势更能反映当前业务状态用整段趋势拟合反而会被历史涨跌干扰。季节延拓用 np.tile 复制最后一周期的季节模式选择最后周期而非历史平均周期是因为 STL 允许季节强度随时间变化最新周期最接近当前状态。残差预测的 AutoReg 部分需要特别说明滞后阶数 lag 的物理含义。以日数据为例lag3 表示当前残差受前 1 天、前 2 天、前 3 天残差的影响系统会估计每个滞后项的系数并延伸到未来。lag 太小会遗漏短期依赖lag 太大会出现参数不稳定所以项目把滞后阶数也纳入搜索空间而不是固定一个值。3.4 季节周期与滞后阶数的自动搜索参数选择如果全靠人工经验面对不同数据集就得反复试错。项目的做法是把季节周期和滞后阶数组成候选组合在滚动时间窗口上逐组验证误差最终选择平均 RMSE 最小的组合。这套机制让模型在面对新数据集时具备自适应能力。# param_search.py —— 滚动验证与网格搜索 import numpy as np from itertools import product def rolling_validate(series, period, lag, horizon, n_windows): 滚动时间窗口验证: 返回平均 RMSE 与各窗口误差序列 errors [] total_len len(series) step max(horizon, n_windows) for i in range(n_windows): # 训练与预测切分点: 保证有足够历史且留出验证区间 train_end total_len - horizon * (i 1) - step train_end max(train_end, period * 3) # 训练集至少要有 3 个周期 if train_end horizon total_len: break train series.iloc[:train_end] actual series.iloc[train_end:train_end horizon] # 用当前参数组合训练并预测 pred, _ forecast_with_stl(train, period, lag, horizon) # 对齐长度并计算 RMSE aligned_len min(len(pred), len(actual)) rmse np.sqrt(np.mean((pred[:aligned_len] - actual.values[:aligned_len]) ** 2)) errors.append(rmse) return np.mean(errors), errors def search_best_params(series, periods, lags, horizon, n_windows): 网格搜索: 遍历所有候选参数组合, 选择平均 RMSE 最小的一组 results [] for period in periods: for lag in lags: avg_rmse, _ rolling_validate(series, period, lag, horizon, n_windows) results.append({period: period, lag: lag, rmse: avg_rmse}) best min(results, keylambda x: x[rmse]) return best, results滚动切分是本段代码的关键点。train_end 的取值逻辑是从序列尾部反向预留验证区间每个窗口的训练集末尾依次向前移动越靠后的窗口训练数据越少。ensuring train_end 不小于 period * 3 是为了保证训练集至少包含 3 个完整周期STL 分解才有足够的季节信息。如果序列太短滚动窗口数量会自动减少避免训练集被切得只剩零头。搜索完成后项目用最优参数组合重新训练一次完整模型并对未来区间生成预测值与置信区间。置信区间宽度根据滚动验证误差估计误差大的业务序列区间自动放宽反映其真实不确定性。这里有个容易被忽略的细节——最终训练用的是全量历史数据而不是验证阶段最后一段的训练集。因为验证的目的是选参数选好参数后让模型看到尽可能多的数据预测精度才有保障。4. GUI 设计与工程落地从脚本到可操作的预测工具4.1 界面功能布局与文件组织项目在核心算法基础上构建了完整的 Tkinter GUI让不熟悉命令行的人员也能操作。界面按功能分四个区域顶部工具栏负责任务触发左侧参数控制面板集中管理数据文件、周期、滞后阶数、预测步长等输入右侧图形选项卡展示分解图、预测图、残差图底部是预测结果表格与运行日志区域。四区布局让配置—训练—查看—导出的链路一目了然。GUI 层与算法层通过模块化设计解耦。界面代码只负责交互和数据展示核心算法放在独立的模型模块中通过函数调用完成训练、预测、保存。这样设计的好处是算法升级不影响界面逻辑命令行跑批和 GUI 操作共用同一套核心代码测试成本降低一半。文件组织大致分为数据加载模块、STL 模型模块、参数搜索模块、可视化模块和主界面类各模块职责单一。组件功能说明关键交互工具栏触发数据加载、模型训练、未来预测、结果导出按钮点击事件绑定参数面板设置 CSV 路径、周期候选、滞后候选、预测步长输入框与下拉选择图形区域分解图、预测区间图、残差分布图、参数热力图Matplotlib 嵌入画布结果表格展示未来预测值与置信区间Treeview 表格控件日志区域输出训练进度、误差指标、异常信息滚动文本框追加写入4.2 参数控制、训练触发与结果可视化参数面板对应实战中最常调整的几个字段数据文件路径、数值列名、候选季节周期、候选滞后阶数、预测步长、训练窗口数。界面在触发训练前会先做数据校验检查日期列可解析性、数值列完整性、序列长度是否满足最小周期要求。校验失败会弹出明确提示指明具体问题所在而不是让模型在异常数据上空跑。训练过程采用异步执行避免界面卡死。长时间运行的滚动验证和参数搜索放在后台线程中推进主界面实时显示当前正在评估的参数组合和已验证窗口数。训练完成后图形区域自动刷新四张图STL 分解图展示趋势、季节、残差各自的形态预测区间图叠加真实值、预测值与置信带残差分析图检查残差是否仍有明显结构参数热力图展示不同周期与滞后组合下的误差分布帮助理解为什么选中这组参数。# gui_core.py —— GUI 训练触发与结果更新核心逻辑 import tkinter as tk from tkinter import ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg class ForecastGUI: def __init__(self, root): self.root root self.data_series None self.best_params None self.forecast_result None self._build_layout() def _build_layout(self): 构建四区布局: 工具栏 参数面板 图形区 结果表格 # 顶部工具栏 toolbar ttk.Frame(self.root) ttk.Button(toolbar, text加载数据, commandself.load_data).pack(sideleft) ttk.Button(toolbar, text训练模型, commandself.train_model).pack(sideleft) ttk.Button(toolbar, text未来预测, commandself.predict_future).pack(sideleft) ttk.Button(toolbar, text导出结果, commandself.export_results).pack(sideleft) # 左侧参数面板 params ttk.LabelFrame(self.root, text模型参数) self.file_var tk.StringVar() self.period_var tk.StringVar(value7,12,24,52) self.lag_var tk.StringVar(value1,2,3,5,7) # ... 参数输入框创建省去这段 GUI 代码展示了主界面类的核心骨架。四个按钮分别对应数据加载、模型训练、未来预测、结果导出四类操作每个事件绑定到独立处理方法中。参数面板的输入框用 StringVar 绑定变量训练时从变量读取用户输入再拆分解析。需要注意 Tkinter 的 StringVar 读取到的是字符串周期和滞后候选需要 split 加 int 转换否则后续函数会因类型不匹配报错。4.3 预测结果导出与模型复用GUI 模块的训练完成后预测结果支持导出为 CSV 文件包含时间点、预测值、置信区间上下界三列。同时支持模型参数保存把最优周期、滞后阶数、训练窗口数、RMSE 指标等记录到 JSON 文件方便复盘或迁移到其他数据。模型对象本身用 Joblib 或 Pickle 序列化保存下次使用时直接加载跳过训练阶段。导出功能对业务落地很关键。业务部门需要的不是模型结构而是一张可以直接用的预测表。项目保证导出的 CSV 表头明确、字段无歧义预测值保留合理小数位置信区间按业务习惯同时给出上下界。结果文件命名带上生成日期、数据版本信息后续追溯时能确认这份预测是基于哪份数据、哪个参数组合生成的。模型复用方面我建议把训练好的参数组合视为模型的记忆。同一业务序列每周重跑时可以用上次选择的最优周期和滞后阶数作为本轮搜索的候选中心缩小搜索范围既保证参数自适应又没有全量搜索的计算开销。这种做法在项目落地阶段比每次都从头搜索的体验好很多。5. 避坑手册真实业务里最容易翻车的六个细节5.1 时间索引不连续导致季节周期失真现象日销售数据缺少某个周末的记录模型把周规律识别错误季节项出现畸形波动。原因STL 的季节周期以观测步数为单位。缺失日期不补全原本 7 天的周循环被压缩成更短步数算法无法识别真实周期。解决数据规范化阶段必须按推断频率重建完整时间轴缺失位置显式补 NaN再走插值流程。频率推断失败时优先人工指定不要放任数据带着洞进模型。5.2 随机切分训练集导致未来信息泄漏现象离线验证 RMSE 很低上线预测误差翻倍。原因随机抽样把未来样本混入训练集模型在验证时见过未来离线成绩虚低上线后失去这种作弊条件误差回到真实水平。解决强制使用滚动时间窗口验证。训练集永远只包含预测起点之前的数据多个窗口的预测起点向后滑动模拟真实业务中持续预测的过程。5.3 季节周期与业务频率不对应现象月度数据中明显有一年 12 个月的规律但模型季节项在 3 个月位置出现假周期。原因周期设置为 3 而不是 12。STL 把短周期内的波动当成季节规律实际是月度随机波动被过拟合为季节。解决周期候选值必须覆盖业务真实规律。日数据放 7月数据放 12小时数据放 24候选集合宁多勿少交给滚动验证用误差判断而不是拍脑袋猜。5.4 异常值把趋势和季节项拉偏现象某次促销带来 5 倍于平时的销量之后几周趋势项和季节项都被这个峰值污染。原因STL 默认的分解过程对极端值敏感一个极端观测会通过局部加权机制拉偏邻域内部的趋势和季节估计。解决开启 robust 模式。该模式在迭代过程会自动降低大残差观测的权重促销峰值不再主导邻域拟合。业务上要把真实现象与数据错误区分开避免把真实事件清洗掉。5.5 训练集太短导致 STL 分解失效现象滚动验证报错或分解结果全为 NaN。原因STL 分解要求序列长度至少包含数个完整周期。周期为 52 的年度数据训练集不足 156 个点就很难得到稳定的季节项。解决滚动窗口切分时约束训练集长度下限至少保留 3 个完整周期。序列整体太短时缩小候选周期或直接改用季节性朴素法作为基线不要硬上 STL。5.6 外推趋势斜率被极端端点绑架现象趋势外推使用全量历史拟合直线斜率被早期异常值控制未来预测偏离当前业务正常水平。原因np.polyfit 对全段趋势做线性拟合早期高点与近期低点之间的连线不能代表近期走向。解决只取最近一个周期或最近 N 个观测的趋势值拟合直线让斜率反映近期状态。趋势外推要承认不确定性配合置信区间一起交付不要强求趋势线一定精确。6. 让模型真正跑起来从单次预测到滚动更新的实战习惯模型的落地价值在于持续运行而不是一次性交付。我在实际项目中的习惯是把滚动验证脚本固化下来每周末用最新数据刷新一次预测结果。刷新过程分三步加载近三个月新增数据并做质量治理以当前最优参数组合为搜索中心做小范围搜索确认参数是否仍适用重训全量模型并生成未来 14 天的预测与置信区间。这套流程把项目从一次预测变成滚动更新的预测服务。预测结果进入业务决策前还要做一次合理性检查。将预测值与去年同期对比确认季节模式没有突变将预测均值与最近实际值对比确认趋势外推没有明显跳变。任何超出业务常识的结果都要回到数据层排查多数问题出在新增数据的时间索引治理上而不是算法本身。置信区间的使用也要落到操作层面。业务方需要的不是下个月销量是多少这个点而是下个月销量的合理范围是多少什么时候该紧张。我在输出预测表时会把区间上下界加粗标注并在附注中写清楚实际值连续三个点超出上界启动异常复核连续五个点超出触发模型重训。这种规则让预测结果变成运营动作的依据而不是躺在线上的数字。从那以后我每次搭建时间序列预测系统都强制走一遍完整链路——数据治理、滚动验证、参数搜索、区间输出、异常触发规则。有过一次跳过重采样直接建模导致季节项崩溃的经历后这套流程再也不省步骤了。项目中的代码和 GUI 界面在这个链路里省了不少重复工作希望帮到你。本文还有配套的精品资源点击获取
返回列表