第一次被人问"生态系统服务到底怎么量化"的时候,我正对着一张土地利用图发呆。那是一片典型的南方丘陵区,有林地、有茶园、有水库,还有几片新开的果园。对方是地方上的规划人员,问题很直接:这片区域如果按现在的开发节奏走,水源涵养和土壤保持这两项功能会损失多少?换个方案能挽回多少?这个问题用文字回答很容易,用数字回答就很难。而这恰恰就是生态系统服务评估要干的事——把"森林能涵养水源""湿地能净化水质"这类定性描述,翻译成决策者能拿去比较、能放进方案里的可量化结果。InVEST模型就是目前被用得最多的一套工具,它把生态学和经济学之间那道鸿沟,用一系列空间化模型搭了座桥。这篇东西不打算讲太多理论,重点放在实操:怎么装、怎么准备数据、几个核心模型怎么跑、跑完怎么判断结果靠不靠谱。
1. 把"生态系统服务"从概念落到可计算的指标上
1.1 生态系统服务的分类逻辑和常见误解
生态系统服务这个概念听起来很虚,但分类其实很清晰,国际上通行的是按功能分成四类:供给服务(粮食、木材、淡水)、调节服务(气候调节、洪水调蓄、水质净化)、支持服务(土壤形成、养分循环、生境维持)、文化服务(休闲旅游、景观价值)。InVEST覆盖的主要是调节服务和支持服务里的可空间化部分,供给服务里也有木材、作物授粉、水电等模块。
一个特别常见的误解是:把生态系统服务等同于"生态价值"。这两者不是一回事。服务是流量,讲的是"每年这块地提供多少吨水、多少吨碳固定";价值是把这个流量用某种方法折算成钱。InVEST的前半段(生物物理模型)算的是流量,后半段(估值模块)才是折算。很多人拿着InVEST输出直接说"这片林子值三个亿",中间省略了估值方法的选择、贴现率、替代成本法还是支付意愿法这些关键讨论,结果被人一问就塌房。
还有一个误区是把模型输出当成真值。InVEST的所有模块本质上是"简化后的因果链",它告诉你的是相对变化和空间格局,而不是绝对精确的物理量。比如产水量模型用的是Budyko曲线简化式,它没法替代一个跑了十年的水文站。理解这一点,你才不会在答辩或者汇报时被专家一句话问倒。
1.2 为什么必须量化:决策场景倒逼出来的需求
纯定性的生态描述在决策桌上几乎没有分量。我参与过几次国土空间规划的讨论,当你只说"这片湿地很重要"的时候,它在一堆建设用地指标、GDP增长目标面前基本没有议价能力。但当你拿出"如果填掉这片湿地,下游洪峰流量将增加百分之多少,受影响的人口约多少人"的时候,讨论的性质就变了。
量化带来的另一个好处是可比性。三个不同的开发方案,各自对生境质量、碳储量、产水量的影响可以用同一套指标横向对比,这在方案比选里非常关键。InVEST的设计初衷就是服务这种"情景对比"——它要求你输入当前情景和未来情景,然后输出差异。这也是为什么大部分模块都强制要求至少一个当前LULC栅格和一个未来LULC栅格。
量化还有一个隐性价值:暴露信息缺口。当你开始收集碳库数据、土壤可蚀性数据的时候,会立刻发现研究区某些关键参数根本没有本地实测值,只能借用邻近区域或文献默认值。这个发现本身就是有价值的,它告诉你哪些地方的数据需要补。
2. InVEST模型家族:它能干什么,不能干什么
2.1 模块构成与各自的适用尺度
InVEST 3.x系列的模块大致可以分成几组。碳储量与封存模块是最简单的,只需要土地利用栅格加一张碳库表,但它的"简单"是建立在假设之上的:假设土地用途转换后碳库会瞬间达到新平衡,不考虑碳积累的时间过程。所以它更适合做长期情景对比,不适合分析短期的碳通量动态。
生境质量模块用威胁因子和敏感性来推算生境退化程度,输出0到1之间的生境质量指数。它本质是个"相对质量"指标,1代表最好的状态,而不是绝对意义上的生物多样性。做保护区规划、生态红线划定的时候用得多。
水文组包括产水量、土壤保持(SDR)、营养物传输比(NDR)、季节性产水。产水量基于降水和蒸散算水资源供给,SDR基于USLE算土壤流失和持留,NDR算氮磷从坡面到水体的输移和截留。这三个经常一起用,因为水土流失和养分流失本来就是同一个过程的不同侧面。
海岸带和城市组包括海岸带脆弱性、蓝碳、城市降温、城市洪水风险、城市暴雨管理等。城市降温模块这两年用得越来越多,做热岛效应和绿地规划的时候很实用。
还有授粉、休闲旅游、木材产量、波浪能、近海风能这些相对小众的模块。授粉模块需要蜂类活动范围和农田分布,国内用得少,主要卡在蜂类数据。
2.2 什么情况下不该用InVEST
这一点很少有人讲,但实际工作中很重要。如果你需要的是高精度的水文过程模拟,比如日尺度的径流过程线、洪水演进,那应该用SWAT、HEC-HMS这类分布式水文模型,InVEST的年尺度输出满足不了。如果你要做的是碳排放核算,尤其是涉及时间动态和分解过程,应该用CENTURY、RothC这类生物地球化学模型,InVEST碳模块的时间静态假设会让结果偏离很大。
如果研究区的空间异质性极高、微地形复杂,InVEST那种基于栅格和相对均一参数单元的假设就会失效。我见过有人在喀斯特地区直接套用默认土壤深度参数,结果产水量算得一塌糊涂,因为喀斯特的产流机制根本不遵循那个假设。
还有一个现实约束是数据。InVEST每个模块都要求一整套空间数据,缺一个就跑不动。如果研究区连像样的DEM和土地利用图都没有,硬上InVEST只会得到一堆看起来专业、实际上没有意义的结果图。这种情况下,先把基础数据补齐,比先跑模型重要得多。
3. 环境搭建与数据准备:八成报错都出在这里
3.1 软件安装和运行环境的坑
InVEST官方提供的是Workbench安装包,Windows和macOS都有,装完就是一个图形界面,双击模块、填参数、点运行。对不写代码的人来说这是最省事的路子。但这个安装包偶尔会出现模块加载失败、界面卡死的问题,尤其是Windows上路径里有中文的时候。
另一条路是用Python环境跑,通过conda装pygeoprocessing和invest,然后在脚本里调用。这条路适合要批量跑多个情景、或者要把模型嵌进自动化流程的人。缺点是依赖关系比较麻烦,GDAL、pygeoprocessing、numpy这些版本之间经常打架,我建议直接用一个干净的conda环境,别在已有的环境里硬装。
不管是哪种方式,有三个坑几乎是必踩的。第一是路径里有中文或空格,InVEST底层调用GDAL,对非ASCII路径经常处理不了,输入输出全部用英文短路径最稳。第二是文件被占用,尤其是结果文件正开在GIS软件里的时候,模型会写不进去。第三是内存,大栅格(比如整个省域的高分辨率数据)跑生境质量这种要算邻域衰减的模块,内存吃得很凶,建议先切小研究区测试。
提示:装完InVEST之后,先跑官方自带的样例数据(sample data),确认环境没问题再换自己的数据。官方样例在安装目录下有,跑通了说明环境和软件本身是好的,后面出问题就只可能是数据的问题。
3.2 输入数据的坐标、像元与命名规范
InVEST对输入栅格有一条硬性要求:所有栅格的坐标系必须完全一致,而且强烈建议用投影坐标系(等面积投影最好,比如Albers或UTM),不要用地理坐标系(WGS84那种经纬度)。原因是模块里涉及面积计算、距离衰减、像元邻域运算,经纬度下每个像元的实际面积不一样,算出来的碳储量、土壤流失量会系统性偏差。
像元大小也要统一。我一般把土地利用、DEM、降水、蒸散这些全部重采样到同一个像元尺寸,比如30米或90米,看研究区大小和数据精度定。重采样的时候分类栅格用最近邻法(nearest),连续栅格用双线性或三次卷积,千万别搞反——分类栅格用双线性会把土地利用类型插出小数来。
命名规范看起来是小事,实际上是减少返工的关键。我习惯把所有输入文件按"模块_变量_分辨率_年份.tif"的格式命名,比如carbon_lulc_30m_2020.tif、wy_precip_30m_2020.tif。参数表统一用CSV,编码用UTF-8,别用GBK。还有一条经验:LULC栅格的编码从1开始连续编号,不要跳号、不要用0(0一般留给nodata),不然后面填参数表很容易对不上。
3.3 数据准备清单与自检流程
下面这张表是我整理的各模块通用输入,按需求程度排的,可以先对照自己的数据情况看看缺口在哪。
| 数据类型 | 用途模块 | 常见来源 | 注意事项 |
|---|---|---|---|
| 土地利用/覆被栅格 | 全部 | 全国30米年度LULC产品、本地遥感解译 | 编码需连续,年份要与情景对应 |
| DEM | SDR、产水、城市模块 | 公开DEM产品 | 需填洼处理,投影坐标 |
| 降水栅格 | 产水、NDR | 气象站点插值、格点降水产品 | 年尺度,单位毫米 |
| 潜在蒸散栅格 | 产水 | 由气象数据计算 | 与降水同分辨率同投影 |
| 土壤深度与质地 | 产水、SDR | 土壤数据库、区域土壤图 | 深度单位毫米 |
| 流域/子流域矢量 | 产水、SDR、NDR | 由DEM水文分析生成 | 边界要与栅格范围匹配 |
| 碳库参数表 | 碳储量 | 文献、IPCC默认值、实测 | 分地上、地下、土壤、枯落物 |
| 威胁因子与敏感性表 | 生境质量 | 文献、专家打分 | 半衰距需说明依据 |
自检流程我总结成四步:先看坐标系和像元对不对齐,再用GIS把几个栅格叠在一起目视检查范围是否重合,然后检查nodata区域会不会把有效区挖出洞,最后用一个极小的子区(比如几平方公里)先跑一遍。这一步能省下大量时间,因为全量跑一次动辄半小时到几小时,小区域测试几分钟就能暴露参数错误。
4. 碳储量模型:最简单也最容易做错的模块
4.1 碳库表的构建逻辑与数据来源
碳储量模块的输入就两样:LULC栅格和碳库表。碳库表是CSV,字段包括lucode、LULC_name,以及四个碳库:C_above(地上生物量碳)、C_below(地下生物量碳)、C_soil(土壤碳)、C_dead(枯落物和枯死木碳),单位统一是吨碳每公顷(tC/ha)。
这里最容易出问题的是碳库值和土地利用分类不匹配。你的LULC分类如果是"有林地、灌木林、疏林地、草地、耕地、建设用地、水域"七类,碳库表就必须是这七类,lucode要一一对应。我见过有人直接用IPCC的六大类碳库值,结果自己的分类里有"果园"这种类别,只能硬塞一个接近的值进去,最后总碳储量偏差不小。
数据来源方面,最理想的是研究区实测或区域文献值。国内很多区域都有生态系统碳储量的研究,可以按植被类型查。如果实在找不到,用IPCC的默认值也能跑,但一定要在报告里说明这是默认值,并做敏感性分析——把碳库值上下浮动20%,看结果变化多大。如果浮动20%结论就翻盘了,说明你的结论本身不稳健。
土壤碳那部分特别容易被忽略。很多人只填地上和地下生物量,土壤碳留空或者填0,这会导致总碳储量严重低估,因为成熟森林的土壤碳往往和植被碳是一个量级甚至更大。枯落物碳在小尺度和短周期评估里可以近似忽略,但在长期情景对比里不能省。
4.2 参数配置逐项拆解
碳储量模块的配置界面其实很简洁,需要填的包括当前LULC栅格、未来LULC栅格(可选,但建议填)、碳库表、输出文件夹,还有一个"是否计算碳封存"的选项——勾上之后它会同时输出未来情景相对当前情景的碳储量变化。
有一个细节值得说:如果未来LULC栅格和当前栅格的范围、分辨率、nodata位置不完全一致,模型会报错或者输出错位。稳妥的做法是先用GIS把两个栅格的属性对齐(用当前栅格做模板,未来栅格重采样和裁剪到完全一致),再喂给模型。
还有一个小坑是碳库表里的LULC_name字段,虽然模型不强制要求,但填上能避免自己后面看输出时忘了编码对应关系。我一般还会在表里加一列"数据来源",记录每类的碳库值是从哪篇文献或哪个数据库来的,方便复核。
4.3 结果校验:怎么判断跑出来的数是对的
碳储量模块会输出一个碳储量栅格(每像元的总碳,单位tC/ha)和一个总量汇总(研究区总碳储量,单位吨)。校验的时候我通常做三件事。
第一件,把碳储量栅格和LULC栅格叠在一起看。每一种地类的碳储量应该是均一的(因为同一类用的是同一组参数),如果你发现同一类地类里数值忽高忽低,那多半是栅格对齐或者nodata处理出了问题。
第二件,用面积乘以碳库值手算一遍总量,和模型输出的总量对一下。比如林地面积1000公顷,四类碳库加起来150 tC/ha,那林地贡献就是1.5万吨碳。差得太多说明参数表或者分类有问题。
第三件,和已有研究对比。如果研究区或者邻近区域有已发表的碳储量估算,把数量级对一下。不同研究之间差个百分之二三十很正常(分类体系、碳库值来源、边界都不一样),但如果差了一个数量级,那肯定是哪一步错了。这套校验思路其实对后面所有模块都适用,核心就是"空间分布合理、总量可手算、数量级可对比"。
5. 生境质量模型:威胁因子和参数怎么定才算合理
5.1 威胁因子表与敏感性表的字段含义
生境质量模块的逻辑是:每一种威胁因子(比如建设用地、耕地、道路)会对其周围生境产生衰减影响,影响强度随距离衰减,不同生境类型对不同威胁因子的敏感程度不同。最后输出的是一个综合的退化程度,进而转成生境质量指数。
它需要两张参数表。威胁因子表(threats)的字段是:THREAT(威胁名称)、MAX_DIST(最大影响距离,单位公里)、WEIGHT(权重,0到1)、DECAY(衰减类型,linear或exponential)。敏感性表(sensitivity)的字段是:LULC编码、名称、HABITAT(是否生境,1或0),以及每个威胁因子对应一列敏感度值,最后是SENSITIVITY。
还有两个可选输入会影响结果:威胁因子栅格(如果威胁的分布不能直接从LULC推出来,比如道路需要单独输入)、可达性矢量(模拟人类进入的难易程度,会调低可达区域的生境质量)。
MAX_DIST和WEIGHT这两个参数没有标准答案,必须结合研究区和文献。我的经验是:建设用地的影响距离一般设1到5公里,道路设0.5到2公里,耕地设0.5到3公里,具体看区域尺度和物种关注对象。如果是关注两栖类,影响距离可以设小一点;关注大型哺乳动物,影响距离要放大。权重一般建设用地给1,耕地和道路按实际影响程度给0.5到0.8。
5.2 半衰距与衰减曲线的选择依据
DECAY参数控制的是影响随距离的衰减方式。linear是线性衰减,距离超过MAX_DIST就归零;exponential是指数衰减,理论上永远不为零但很快趋近于零。InVEST还允许你自定义衰减曲线,通过一个半衰距参数来定义。
选哪种衰减方式要看生态学过程。线性衰减适合假设影响均匀递减的场景,比如噪音、光污染这类;指数衰减更符合很多实际的生态过程,因为威胁的影响通常在近处急剧下降,远处趋于平缓。我个人的默认选择是指数衰减,因为对大多数干扰因子来说,它在近源处的衰减更符合实际观测。
参数选择的合理性最终要靠敏感性分析检验。做法很简单:把关键参数(MAX_DIST、WEIGHT、衰减类型)各自变动几个档次,跑几组结果,看生境质量的相对排序和空间格局是否稳定。如果换了参数之后,你原本想保护的"高生境质量区"位置大变,说明结论对参数太敏感,需要补充实地调查来约束参数。
5.3 结果解读与几个反直觉现象
生境质量模块的输出有两个主要栅格:生境质量(0到1,越高越好)和生境退化度(越高退化越严重)。解读的时候有几个反直觉的地方值得注意。
第一个,生境质量高不代表生物多样性高。它只是基于威胁-敏感性框架的一个相对指标,反映的是"受人类干扰少的程度"。一片远离人烟的单一草地也可能得到高生境质量分数,但它的物种丰富度可能远低于一片受到中等干扰的复杂森林。所以汇报的时候一定要说明这个指标的语义,别直接说成"生物多样性"。
第二个,大面积的保护区内部可能显示中等生境质量,而边缘反而高。这通常是因为大保护区中心靠近内部的某个村镇或道路(威胁源),导致中心退化。这种情况一定要回到威胁因子的空间分布上去核查,别被表面数字迷惑。
第三个,未来情景的改善往往集中在局部。如果未来规划里把某些建设用地转成林地,生境质量的提升会集中在这些转换点周围,而不是全区域均匀提升。所以做情景对比的时候,除了看总量的变化,更要看变化的空间格局,尤其是关键生态廊道是否被打通或阻断。
6. 水文类模型:参数更多、更容易翻车的地方
6.1 产水量模型的蒸散逻辑与Z参数
产水量模型的核心是Budyko曲线的简化形式,输出的是年尺度上的产水量(降水减去实际蒸散后的余量)。它的输入包括LULC、年降水栅格、年潜在蒸散栅格、土壤深度、植物可利用水含量(PAWC)、流域矢量,以及一张生物物理表(包含每个LULC类型的Kc系数、根系深度、是否为植被)。
模型里有个关键参数Z,叫Zhang系数,它反映的是降水的季节性分布和流域的持水特性。Z的取值范围一般在1到30之间,降水越集中在雨季、流域调蓄能力越弱,Z越大。这个参数没有普适的取值,官方建议用实测径流数据来率定——也就是调Z让模拟产水量和实测径流量吻合。
这一步是很多人跳过的地方,直接用默认值Z=1就跑了。结果在干旱区或者季风气候区偏差会非常大。我的做法是找研究区或者邻近水文站的多年平均径流数据,手动调Z跑几次,选拟合最好的那个。做不了率定的话,至少参考同气候带已发表研究里用过的Z值。
6.2 土壤保持模型里USLE各因子的获取途径
土壤保持模块基于通用土壤流失方程USLE:A = R × K × LS × C × P。它需要降雨侵蚀力R、土壤可蚀性K、坡长坡度LS、植被覆盖管理C、水土保持措施P这五个因子,加上DEM、流域和阈值流量累积。
R因子可以从降水数据算,国内有不少研究给出了基于年降水的经验公式。K因子从土壤质地和有机质含量算,土壤数据库里一般能查到基础属性。LS因子由DEM自动计算,这个模块内部会算,你只要给DEM就行。C和P因子来自生物物理表,按LULC类型赋值,C值反映植被对侵蚀的抑制,P值反映工程措施的作用。
C和P的取值是最容易出问题的。国内的C值研究比较分散,同一个地类在不同文献里可能差一倍。建议优先用研究区或邻近区域的实测/文献值,实在没有再用通用值。P值在缺乏明确水保措施信息的情况下,一般农地给0.5左右,林地草地给1(表示无额外措施),具体看实际情况。
模块输出包括土壤流失量(潜在)、实际土壤流失量、沉积物持留量、沉积物传输比(SDR)等。这里有个容易混淆的点:模型算的是"栅格尺度的流失"和"考虑下游截留后的输移",两个概念不一样。汇报的时候一定要说清楚你用的是哪个量。
6.3 参数敏感性测试的实操方法
水文类模型参数多,一上手很容易调花。我的习惯是先做单参数扫描:固定其他参数,只动一个,看输出变化幅度。具体操作是把模型跑几组,每组只改一个参数(比如只改Z),记录输出总量的变化。
据此可以画一张敏感性表,标出哪些参数是"高敏感"(动一点结果就大变)、哪些是"低敏感"。高敏感参数必须优先率定,低敏感参数可以用默认值。这样能把有限的实测数据用在刀刃上。
还有一点经验:先做最简单的情景——只跑当前场景,不做未来对比,确认当前情景的结果和实测/文献能对上,再加未来情景。很多人一上来就跑两套情景做对比,结果两套都有系统偏差,差值也就没什么意义了。
7. 出图、结果管理与常见报错排查
7.1 结果栅格的后续处理和制图
InVEST输出的栅格是标准的GeoTIFF,可以直接在QGIS或ArcGIS里打开。做图的时候有几点需要注意。生境质量、碳储量这类指标本身是绝对或相对数值,配色建议用连续渐变色带,并且把图例范围固定,方便多个情景放在一起对比。情景差异图(未来减当前)一定要用发散色带,并且把0点设成白色或中性色,让人一眼看出哪里增哪里减。
汇总统计方面,模型自带的汇总表是全域的,如果你需要按行政区、按子流域统计,得自己用分区统计工具(zonal statistics)再做一层。这一步很常见,因为决策者往往需要"某某乡镇的产水量变化"这种颗粒度的信息。
还有一个实用技巧:把栅格转成点或者按格网聚合,再叠加到规划底图上,比单给一张栅格图直观得多。尤其是做汇报的时候,决策者更容易理解"这几个片区是重点提升区"这种表达。
7.2 高频报错对照表与排查路径
下面这张表是我这些年踩坑攒下来的高频报错,基本覆盖了大部分情况。
| 报错或现象 | 最可能的原因 | 处理方向 |
|---|---|---|
| 程序闪退或模块加载失败 | 路径含中文/空格,或环境依赖冲突 | 换纯英文短路径,重建干净conda环境 |
| 提示坐标系不一致 | 输入栅格投影不同 | 统一到同一投影坐标系后重采样 |
| 结果栅格有大片空洞 | nodata设置或范围不重合 | 检查nodata值,统一裁剪范围 |
| 参数表报错找不到某编码 | LULC编码与表格列不匹配 | 核对编码,确保表格覆盖所有类别 |
| 模型跑很久最后失败 | 内存不足 | 切小研究区或降低分辨率 |
| 总量结果明显偏大偏小 | 单位错误(如毫米和米混用) | 逐项核对单位,尤其是降水、深度 |
| 未来情景输出全是nodata | 未来栅格范围与当前不一致 | 用当前栅格做模板对齐未来栅格 |
排查的思路是"从外到内":先确认环境和路径,再确认坐标系和范围,再确认参数表,最后才是参数取值。前面三层是机械错误,最容易也最该先排除;参数取值是科学判断,放最后调。
注意:不要在同一个失败的结果上反复调参数,先确认输入数据完全没问题。我见过太多人花一整天调模型参数,最后发现只是某个栅格的投影没统一。
排查的时候有个笨办法但特别有效:把输入数据全部用同一套GIS工程打开,逐个叠加,肉眼看是不是严丝合缝地对齐。很多"模型有问题"的情况,实际上就是数据没对齐或者在GIS里看着对齐、实际坐标系不同。
这个内容后续还可以往几个方向延伸。一是把生境质量和碳储量、产水量耦合起来,做多目标情景优化,找出兼顾各项服务的最优土地利用配置,这个用InVEST输出加简单的优化算法就能做。二是把评估结果和已有的生态补偿政策、生态红线数据叠起来,看看现有政策是否覆盖了高价值的服务供给区,这类分析在实际工作中很受欢迎。三是如果要做动态模拟,可以把InVEST的静态输出和系统动力学或者斑块尺度模型结合,弥补它对时间过程刻画不足的短板。我个人在实际操作中的体会是,模型本身不难,难的是数据准备和结果解释这两头,把这两头做扎实,中间跑模型反而是最省心的一步。