1. 课程导入与问题界定
作物产量预测是农业数字化中最具经济价值、也最容易被低估难度的一类问题。它要回答的并不是"今年收成好不好"这种模糊判断,而是在收获前若干周甚至若干月,给出一个可量化、可解释、可复盘的产量估计值,例如"某县冬小麦平均单产 6350 kg/hm²,误差不超过 ±5%"。这个数字向下游传导,会影响收购计划、仓储调度、期货套保、保险理赔与政策补贴测算。因此,本课程从一开始就把问题定位为带时间约束的回归预测任务,而不是单纯的数据分析练习。
一、业务场景决定了建模的边界
不同使用方对"预测"的要求差异很大,这直接决定了特征选择与评估口径。下面这张图把四类典型场景与它们对时间提前量、空间粒度、精度要求的差异并列呈现,便于在动手写代码前先锁定目标。
二、核心挑战:不是算法难,而是数据与时间对齐难
作物产量受品种、土壤、管理、气象、病虫害共同影响,其中气象又表现为"累积效应"与"关键期效应"两种形态。真正让初学者受挫的通常不是模型选择,而是以下四类问题:
- 样本量小且维度高。一个地级市往往只有十余年、几十个县的记录,样本量在数百量级,而气象可展开为逐旬、逐月的温度、降水、日照等上百个变量,极易过拟合。
- 时空错配。气象站点数据、遥感栅格、统计年鉴三者的空间单元与时间粒度都不一致,需要先统一到"县-年"或"县-旬"的公共面板上。
- 趋势与波动混杂。单产长期随技术进步上升,年际间又因天气大幅波动。若不分离趋势项,模型会把"技术进步"误学成"某类天气更好"。
- 评估方式失真。随机划分训练集与测试集会因相邻年份高度相关而高估精度,必须采用按时间顺序的滚动回测。
三、Python 技术栈选型
本课程的技术栈围绕"能读数据、能对齐时空、能建模、能解释、能交付"五件事组织,全部为成熟开源库,避免引入过重框架。
| 环节 | 主要库 | 在本课程中的具体用途 |
|---|---|---|
| 数据处理 | pandas、numpy | 构建县-年面板,做滞后、滑动累积、同比等特征衍生 |
| 时空数据 | geopandas、rasterio、xarray | 按县界裁剪遥感栅格,提取 NDVI 等指数的区域均值 |
| 建模 | scikit-learn、xgboost / lightgbm | 基线回归、树模型、交叉验证与超参数搜索 |
| 解释与检验 | shap、statsmodels、matplotlib | 特征贡献分析、趋势项分解、残差与误差可视化 |
| 交付 | joblib、fastapi(可选) | 模型持久化,封装为按县查询的预测接口 |
四、整体开发流程与一个可运行的开端
流程上建议按"问题界定 → 数据面板构建 → 特征工程 → 基线模型 → 树模型与调参 → 滚动回测 → 解释与交付"推进,每一步都以可验证的中间产物收尾。下面给出第一步的实际操作:把原始表整理成建模用的面板,并明确目标列与时间列。
import pandas as pd
# 示例数据:县-年 面板,字段为合理假设,非实测
raw = pd.DataFrame({
"county": ["A县", "A县", "A县", "B县", "B县", "B县"],
"year": [2019, 2020, 2021, 2019, 2020, 2021],
"yield_kg_ha": [6120, 5980, 6410, 5730, 5560, 5890],
"sown_area_ha": [32000, 31500, 32800, 21000, 20500, 21400],
"ndvi_jun": [0.62, 0.55, 0.68, 0.58, 0.51, 0.60],
"precip_mm_jun": [88, 42, 105, 76, 39, 92],
})
# 1) 明确目标与时间键,按县、年排序,保证滞后特征正确
panel = raw.sort_values(["county", "year"]).reset_index(drop=True)
# 2) 构造滞后特征:上一年的单产,用于分离趋势与波动
panel["yield_lag1"] = panel.groupby("county")["yield_kg_ha"].shift(1)
# 3) 构造同比特征:当年 6 月 NDVI 相对上年的变化
panel["ndvi_jun_diff"] = panel.groupby("county")["ndvi_jun"].diff()
print(panel[["county", "year", "yield_kg_ha", "yield_lag1", "ndvi_jun_diff"]])
运行后应看到每个县的首年 yield_lag1 为 NaN,这是正常现象,说明滞后构造生效;建模时需删除这些行或单独处理。这一步看似简单,却决定了后续所有特征是否"在预测时点可得"——例如 yield_lag1 在预测当年产量时是已知的,而当年的最终统计单产则不可用。
最后需要强调,作物产量预测的成败往往在建模之前就已决定。把业务场景翻译成明确的时间约束与空间粒度,把多源数据对齐成干净的面板,再用滚动回测诚实地评估,这三件事做扎实,即便使用线性回归也能得到可用的结果;反之,再复杂的模型也只会给出漂亮却无法落地的数字。