十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

图像回归实战:用机器学习从叶片图像预测叶绿素含量

图像回归实战:用机器学习从叶片图像预测叶绿素含量 简介基于机器学习的图像数据预测叶绿素含量是人工智能在农业精细管理中的典型落地场景。这份ZIP压缩包资料适合正在学习机器学习回归建模的开发者以及需要快速验证图像特征对农情指标预测效果的研究者。压缩包共7个文件大小140KB包含2个Python脚本googlenet和VGG特征提取/建模代码、2个Excel数据表、2个MATLAB数据文件叶绿素原始数据以及1份Git说明文档从原始数据到特征工程再到模型实现均有覆盖。目前已有90人浏览学习。除常用的深度特征提取脚本外资料还提供偏最小二乘判别分析的MATLAB实现便于与线性回归结果对照Excel文件可辅助查看标注数据与中间结果。整体体量轻但环节完整适合希望在一周内快速跑通图像回归预测、深入理解特征工程与模型评估流程的读者。1. 用图像数据预测叶绿素含量一个被低估的机器学习回归任务作物叶片叶绿素含量直接关联光合作用效率和氮素营养状况传统测量靠SPAD-502叶绿素仪夹着叶片读个数一个样点一个样点地测一亩地测几十个点就得弯腰半天。而基于机器学习的图像数据预测本质上是让模型从RGB图像里学出叶片颜色、纹理与叶绿素含量之间的映射关系把“夹叶片”变成“拍张照”。这个zip压缩包里装的通常就是一套完整流程作物图像数据集、特征提取脚本、模型训练代码和预测结果示例。它解决的问题很具体——用手机或普通相机拍摄的叶片/冠层图像替代接触式仪器做无损、快速的叶绿素估测特别适合育种表型筛选、田间氮肥管理和病害监测场景。适合谁农业遥感、植物表型、智慧农业方向的学生和工程师以及想把手头图像数据变成回归模型的机器学习入门者。这个任务和常见的猫狗分类不同它是个高难度的回归问题——输入是图像输出是连续数值评价指标不是准确率而是R²和RMSE很多熟悉分类的人第一次做会翻车。2. 数据准备与预处理图像质量直接决定模型上限2.1 从zip里拿到原始数据后先做质量审查解压这个zip后常见做法是先建立一个数据清单表格记录每张图像的文件名、拍摄日期、对应叶绿素实测值SPAD值或单位面积叶绿素含量mg/m²以及拍摄条件。不要急着训练先花一小时把图像翻一遍你会立刻发现问题有的图像带阴影、有的叶片反光、有的背景土壤裸露面积过大、有的对焦模糊。这些“脏数据”比模型结构更影响最终R²。我一般会先写一个Python脚本把每张图的平均亮度、饱和度、清晰度拉普拉斯方差跑出来做一个粗筛。拉普拉斯方差低于某个阈值的图像直接标记为模糊这些图留到后面测试集里会让模型不明所以。import cv2 import numpy as np import pandas as pd from pathlib import Path img_dir Path(./leaf_images) records [] for img_path in img_dir.glob(*.jpg): img cv2.imread(str(img_path)) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 拉普拉斯方差值越小图像越模糊 laplacian_var cv2.Laplacian(gray, cv2.CV_64F).var() # HSV空间的饱和度均值识别偏色和过曝 hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) sat_mean hsv[:, :, 1].mean() bright_mean hsv[:, :, 2].mean() records.append({ filename: img_path.name, laplacian_var: laplacian_var, sat_mean: sat_mean, bright_mean: bright_mean, }) df pd.DataFrame(records) # 模糊图像拉普拉斯方差小于80的剔除 blurred df[df[laplacian_var] 80] print(f发现 {len(blurred)} 张模糊图像: {blurred[filename].tolist()})这里拉普拉斯方差80是个经验阈值不同分辨率下要重新标定。如果你的图像是1200万像素手机拍的方差值普遍在200以上低于80基本就是糊成一团的废图。饱和度均值用于排查过曝——叶绿素含量高的叶片应该是深绿如果一张图饱和度过低偏灰白要么是光照不对要么是叶片失水这类样本放进训练集只会让模型学出错误的颜色映射。2.2 ROI裁剪与背景分割把模型注意力锁在叶片上原始图像往往包含大量背景——土壤、杂草、手掌、白板。如果不做分割模型会偷偷学习“图片里土壤面积大叶绿素低”这种伪相关换一个拍摄环境直接失效。这是图像回归任务里最常见的隐藏陷阱。最实用的方案是颜色空间阈值分割。绿色叶片在HSV空间的H通道集中在35~85之间S通道偏高。写一个批量裁剪脚本import cv2 import numpy as np from pathlib import Path def extract_leaf_roi(img_path, output_path): img cv2.imread(str(img_path)) hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 叶片绿色掩膜Hue 35-85Saturation 40Value 40 mask cv2.inRange(hsv, (35, 40, 40), (85, 255, 255)) # 形态学闭运算去噪点 kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) mask cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations2) # 找最大连通域排除背景零散绿色噪点 contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if not contours: return largest max(contours, keycv2.contourArea) x, y, w, h cv2.boundingRect(largest) roi img[y:yh, x:xw] # 缩放到统一尺寸避免模型被叶片面积干扰 resized cv2.resize(roi, (224, 224), interpolationcv2.INTER_AREA) cv2.imwrite(str(output_path), resized) img_dir Path(./leaf_images) out_dir Path(./leaf_roi) out_dir.mkdir(exist_okTrue) for p in img_dir.glob(*.jpg): extract_leaf_roi(p, out_dir / p.name)这段代码做了三件事HSV阈值把绿色叶片从背景里分离出来、形态学闭运算把叶片内部因反光产生的孔洞补上、最大连通域锁定主叶片区域。统一缩放到224×224是为了适配后续的CNN模型输入——MobileNetV2和ResNet的默认输入就是这个尺寸。注意不要把整张原图直接resize因为那样会把背景的土壤纹理也一起塞进224×224里叶片的颜色信息会被严重压缩。2.3 数据增强策略既要增产又不能改变颜色语义图像分类里常用的随机亮度扰动、随机色彩抖动在叶绿素回归任务里要格外谨慎。叶片颜色就是你的特征本身你不能让模型认为“亮度降低一半”仍然对应同一个叶绿素值。常见的做法是只用几何增强——水平翻转、垂直翻转、随机旋转10度以内、轻微缩放裁剪这些操作不会改变叶片的颜色统计信息。病害图像数据集和工业图像数据集里常用的Cutout、Mixup这类强增强在颜色回归任务上会直接毁掉模型——因为叶绿素和颜色是强耦合的你把叶片的一部分挖掉或者跟另一张图混合标签就失去了物理意义。训练时我用torchvision的transforms这样配置import torchvision.transforms as T train_transform T.Compose([ T.RandomHorizontalFlip(p0.5), T.RandomVerticalFlip(p0.1), T.RandomRotation(degrees10, fill0), T.RandomResizedCrop(size224, scale(0.85, 1.0), ratio(0.9, 1.1)), T.ToTensor(), T.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) val_transform T.Compose([ T.Resize((224, 224)), T.ToTensor(), T.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ])RandomResizedCrop的scale设为0.85-1.0而不是默认的0.08-1.0这是关键参数。scale下限设到0.08意味着会把叶片的一个极小局部放大到全图那个局部的颜色可能恰好是叶脉的浅黄色或者阴影区标签是整个叶片的平均叶绿素两者根本不对应。把scale下限拉到0.85保证裁剪出来的区域仍然覆盖大部分叶片面积颜色分布和全图接近。Normalize用的ImageNet均值和标准差是迁移学习的标准做法因为预训练模型是在这个分布下学的特征。3. 特征工程与模型选型传统机器学习与深度学习的分水岭3.1 手工特征的边界颜色直方图、统计矩和纹理特征能打吗如果数据集规模不到500张图像深度学习模型的优势发挥不出来这时候传统机器学习模型配合手工特征反而是可靠方案。我一般会提取三类特征RGB/HSV三个通道的均值、标准差、偏度颜色直方图每个通道32个bin灰度共生矩阵GLCM的对比度、能量、熵、相关性。然后把这些特征拼成一个向量喂给随机森林或XGBoost回归。import numpy as np from skimage import color, feature import cv2 def extract_handcrafted_features(img): # img是已经ROI裁剪并resize到224x224的RGB图像 features [] hsv cv2.cvtColor(img, cv2.COLOR_RGB2HSV) for ch in [img[:, :, 0], img[:, :, 1], img[:, :, 2], hsv[:, :, 0], hsv[:, :, 1], hsv[:, :, 2]]: features.extend([ np.mean(ch), np.std(ch), float(np.mean((ch - np.mean(ch))**3)) / (np.std(ch)**3 1e-6) ]) # RGB三通道直方图32bin for i in range(3): hist cv2.calcHist([img], [i], None, [32], [0, 256]) features.extend(hist.flatten() / (224 * 224)) # GLCM纹理特征取绿色通道 gray color.rgb2gray(img) glcm feature.graycomatrix((gray * 255).astype(np.uint8), distances[1, 3], angles[0, np.pi/4, np.pi/2], levels256, symmetricTrue, normedTrue) for d_idx in range(glcm.shape[0]): for a_idx in range(glcm.shape[1]): g glcm[d_idx, a_idx] features.append(feature.graycoprops(glcm, contrast)[d_idx, a_idx]) features.append(feature.graycoprops(glcm, energy)[d_idx, a_idx]) features.append(feature.graycoprops(glcm, correlation)[d_idx, a_idx]) return np.array(features) # 对每个ROI图像提取特征拼成特征矩阵X和标签y # 然后用sklearn的RandomForestRegressor训练 from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import cross_val_score # 假设 X 是 (N, feature_dim) 的矩阵y 是 SPAD 值 rf RandomForestRegressor(n_estimators300, max_depth12, min_samples_leaf3, n_jobs-1) scores cross_val_score(rf, X, y, cv5, scoringr2) print(f随机森林5折R²: {scores.mean():.3f} (/- {scores.std():.3f}))手工特征方案的上限通常R²在0.75~0.85之间瓶颈在于颜色直方图丢失了空间位置信息——一张叶片上半部发黄、下半部深绿和一张整片均匀浅绿的图像可能得到相似直方图但叶绿素含量差异很大。GLCM能补一部分纹理信息但对颜色的空间渐变依然无力。这套方案最大的价值是稳定计算快、不需要GPU、可解释性强适合做基线模型验证数据本身的质量。如果手工特征RFR的R²连0.6都不到先别急着上深度学习回去检查标注数据和图像质量。3.2 深度学习回归为什么CNN是图像预测叶绿素的更优解当图像数量达到几千张级别卷积神经网络开始体现优势。CNN通过卷积核自动学习从像素到语义的层次化特征——浅层卷积关注边缘和颜色块深层卷积关注叶片斑点和纹理模式最后通过全局平均池化把空间信息压缩成一个特征向量接一个全连接层输出预测值。对比传统机器学习模型CNN不需要人工设计特征而且对叶片颜色不均匀、叶脉遮挡这类空间分布问题有天然鲁棒性。选择预训练模型时我的原则是优先用MobileNetV2或EfficientNet-Lite。ResNet50在ImageNet上表现好但对农业图像这种颜色敏感型任务来说参数冗余太大容易在几千张小数据集上过拟合。MobileNetV2的深度可分离卷积大幅减少参数量配合ImageNet预训练权重做迁移学习在小数据集上收敛快、泛化好。import torch import torch.nn as nn import torchvision.models as models class ChlorophyllRegressor(nn.Module): def __init__(self, pretrainedTrue, dropout0.3): super().__init__() # 载入MobileNetV2预训练权重 self.backbone models.mobilenet_v2(pretrainedpretrained) # MobileNetV2最后一层是1x1卷积输出1280通道 self.backbone.classifier nn.Identity() # 去除原始分类头换成回归头 self.reg_head nn.Sequential( nn.Linear(1280, 256), nn.ReLU(inplaceTrue), nn.Dropout(dropout), nn.Linear(256, 1) # 输出SPAD值或叶绿素含量 ) def forward(self, x): feat self.backbone(x) # feat形状: (B, 1280, 7, 7)做全局平均池化 feat feat.mean(dim[2, 3]) return self.reg_head(feat).squeeze(-1)这里有个容易踩的坑MobileNetV2的原始classifier是(Dropout, Linear(1280, 1000))如果直接替换成Linear(1280, 1)也可以但效果没有先展开到256维再接ReLU好。因为叶绿素预测是个平滑的映射函数中间加一个非线性层能让模型拟合颜色到含量的非线性关系——比如低叶绿素时颜色变化对含量敏感高叶绿素时趋于饱和。Dropout设为0.3是个安全默认值如果训练集只有几百张建议调到0.5。3.3 传统机器学习与深度学习的选型决策表维度传统机器学习RFR/XGBoost深度学习CNN迁移学习最小数据量200张即可出结果建议1000张以上特征工程需要手动提取颜色/纹理特征自动学习无需手动设计训练硬件纯CPU几分钟GPU训练30分钟到几小时泛化能力对光照变化敏感对光照变化更鲁棒可解释性特征重要性可直接输出需Grad-CAM等工具辅助最佳场景快速验证、固定光源环境田间复杂环境、大规模应用这个表可以当作项目初期的决策参考。我的习惯是数据集低于500张先用手工特征RFR拿到基线R²同时把数据质量排查完超过1000张且基线R²稳定在0.7以上再投入精力做CNN微调。如果一上来就训练CNN模型可能跑出好看的训练集R²但在独立测试集上崩塌——数据量不够时迁移学习的优势发挥不出来。4. 模型训练与验证回归任务的评价体系和参数调优4.1 数据集划分按叶片而不是按图像来分一个常见的错误是把同一株植物拍的多张图像随机划分进训练集和测试集。因为同一株或同一片叶子的图像高度相似模型实际上在记忆叶片个体而不是学习普遍规律测试集R²虚高。正确的做法是按叶片或植株分组划分同一植株的所有图像必须同属训练集或测试集。from sklearn.model_selection import GroupKFold # 假设 leaf_ids 是每个样本对应的叶片编号 gkf GroupKFold(n_splits5) for train_idx, val_idx in gkf.split(X, y, groupsleaf_ids): X_train, X_val X[train_idx], X[val_idx] y_train, y_val y[train_idx], y[val_idx] break # 取第一折作为示例GroupKFold的groups参数传叶片ID保证同一个叶片的图像永远不会同时出现在训练集和验证集中。如果你的zip包里每个叶片的图像已经按文件夹组织好了可以从路径中解析出叶片ID。这一步如果漏了后面的所有评价指标都不可信这是回归任务和分类任务最容易被忽视的差别。4.2 损失函数与评价指标MAE、MSE、R²分别盯什么叶绿素预测通常是连续值回归损失函数用MSE均方误差作为训练目标最直接。MSE会对大误差样本给更高权重——预测值偏了10个SPAD值的样本损失是偏了5个的4倍。这在叶绿素范围20~50 SPAD的场景下是合理的行为因为大误差意味着模型在个别样本上完全失效应该被重点纠正。评价指标不能只看R²。R²对数据的变异程度敏感——如果你的样本叶绿素值全集中在45~48这个窄区间即使模型预测误差只有1.5 SPADR²也可能只有0.4看起来很难看但实际精度已经够用。反过来样本范围20~60R²到0.9但RMSE可能还是很大平均误差3个SPAD以上对精确施肥来说不够。我的做法是同时输出RMSE和MAER²作为参考from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score import numpy as np # y_true: 真实SPAD值, y_pred: 模型预测值 rmse np.sqrt(mean_squared_error(y_true, y_pred)) mae mean_absolute_error(y_true, y_pred) r2 r2_score(y_true, y_pred) print(fRMSE{rmse:.2f} SPAD, MAE{mae:.2f} SPAD, R²{r2:.3f})RMSE和MAE的差值能反映误差分布的稳定性。如果RMSE约等于MAE说明误差均匀如果RMSE明显大于MAE说明存在几个极端误差样本拉高了均方差这时候去检查那些样本——通常是对焦不准、叶片重叠、或者实测SPAD值记录错误。4.3 学习率策略与训练轮数迁移学习微调的三个阶段迁移学习微调最稳妥的学习率策略是分层设置backbone的预训练参数用较小学习率1e-4~1e-5新加的回归头用较大学习率1e-3。因为回归头的参数是从零开始训练需要更快的更新速度backbone的参数已经能提取通用特征只需要微调学习率太大会把预训练权重破坏。import torch.optim as optim model ChlorophyllRegressor(pretrainedTrue) optimizer optim.AdamW([ {params: model.backbone.parameters(), lr: 1e-4}, {params: model.reg_head.parameters(), lr: 1e-3} ], weight_decay1e-4) scheduler optim.lr_scheduler.ReduceLROnPlateau( optimizer, modemin, factor0.5, patience8, verboseTrue ) # 训练循环中 for epoch in range(60): # train_epoch(model, train_loader, optimizer, criterion) val_loss validate(model, val_loader, criterion) scheduler.step(val_loss) # 验证loss连续8轮不降学习率减半 # 保存checkpoint torch.save({ epoch: epoch, model_state: model.state_dict(), optimizer_state: optimizer.state_dict(), val_loss: val_loss }, f./checkpoints/ckpt_epoch{epoch}.pth)ReduceLROnPlateau的patience设为8在这个任务上比CosineAnnealing更实用。叶绿素训练的验证loss曲线通常不是平滑下降而是阶梯式——先快速下降几个epoch然后进入平台期patience太小会频繁减半学习率导致收敛不充分。总轮数60~80轮足够如果数据量在2000张左右超过这个轮数还没收敛就不是轮数问题而是数据或模型结构问题。训练曲线要盯两条训练loss持续下降但验证loss反弹上升这是过拟合信号加Dropout或数据增强训练loss和验证loss都下不去检查标签质量——如果你的SPAD值记录仪没有校准那模型的预测上限就被标签噪声锁死了再怎么调模型也没用。5. 避坑指南图像预测叶绿素最容易翻车的五个细节5.1 光照不一致导致模型学到的是“亮度特征”而不是“颜色特征”现象模型在训练集上R²高达0.95拿到室外新拍的照片直接预测出负值或者明显偏离测试集R²掉到0.4以下。原因训练图像里包含了阴天、晴天、遮阳等多种光照条件模型发现亮度和SPAD值之间存在某种统计相关比如采集时碰巧晴天拍的叶片更绿于是把光照当作主要特征学习了。解决用ColorChecker色卡做颜色校正。每张图像里放一张标准色卡拍摄后用色卡上的已知色块值做线性回归校正所有像素。如果没有色卡至少要在训练时按拍摄批次划分GroupKFold让模型不能靠批次信息作弊。5.2 ROI分割误伤病斑和枯叶区域现象预处理时HSV阈值分割把黄化叶片当成背景剔除ROI区域里只剩下健康绿色部分预测值整体偏高或者病斑的褐色区域被当成叶片包含进来预测值偏低。原因叶片颜色分布广黄化叶片或感病叶片的H通道值超出35~85的范围固定阈值分割不适用。解决把HSV阈值放宽然后用形态学操作补洞检查ROI面积占整个连通域的比例——如果单个叶片被分割成多个碎块减小闭运算的核尺寸。对于病斑严重的样本宁可保留病斑区域因为叶绿素预测就是要反映整片叶子的健康状况把病斑裁掉等于篡改标签。5.3 标签噪声SPAD实测值本身的一致性现象模型训练loss下降很快但验证R²在0.7附近卡住无论怎么调参都提升不了。原因SPAD-502的实测值本身存在测量误差——同一片叶子不同位置测出来的SPAD值可以差3~5个单位比如叶片边缘和主叶脉附近差异明显。如果你的标注流程是在叶片上测了3个点取平均但拍摄时图像包含了整个叶片那标签和图像内容本身就存在不一致。解决标注时在叶片上选择固定测量点比如避开主叶脉、距叶尖三分之一处并在记录表里同时记录测量点的图像坐标。训练时对每张叶片的多个SPAD值做中位数而不是平均——中位数对个别异常测量点更鲁棒。5.4 回归头输出层缺少约束预测负值现象模型在叶片黄化严重或图像过暗的样本上输出-5.2 SPAD这样的荒谬值。原因输出层是线性层Linear(256, 1)理论上可以输出任意实数。SPAD值的物理范围是0~100左右模型在数据分布边缘外推时容易跑偏。解决在输出后加Sigmoid或ReLU约束。常见做法是把标签归一化到0~1然后输出层接Sigmoid激活预测时反归一化回SPAD值或者直接对输出做torch.clamp(pred, min0, max100)硬截断。我用的是归一化Sigmoid方案它同时带来了一个好处模型输出的数值天然在合法区间内不会出现负值这种让田间用户直接质疑模型可靠性的问题。5.5 训练集和测试集图像采集时间相隔太久现象模型在秋季采集的图像上训练表现良好但用春季的叶片图像预测时误差明显变大。原因叶片颜色不仅受叶绿素影响还受花青素、类胡萝卜素含量以及叶片厚度影响不同生长季节这些组分的比例会变同样的叶绿素含量在不同季节呈现的颜色不同。解决采集策略上让训练集覆盖至少两个生长季或生育期或者对已有的预训练模型用目标季节的小样本几十张做一次快速微调。如果项目周期不允许跨季节采集至少要在模型使用说明里明确标注适用生育期范围。6. 落地技巧把训练好的模型封装成一条可复用的预测流水线模型训练完成只是第一步真正的价值在于别人能拿着你的模型对新的图像一键预测。我习惯把整个流程封装成一个predict脚本输入一张原始图像路径输出SPAD预测值内部自动完成ROI分割、尺寸归一化、颜色空间转换和模型推理。这里有一个关键技巧用ONNX格式导出模型这样部署时不需要依赖PyTorch环境在纯CPU的便携电脑上也能跑。import torch import onnxruntime as ort import numpy as np import cv2 from model_def import ChlorophyllRegressor # 复用之前的模型定义 # 1. 导出ONNX model ChlorophyllRegressor(pretrainedFalse) ckpt torch.load(./checkpoints/best_model.pth, map_locationcpu) model.load_state_dict(ckpt[model_state]) model.eval() dummy_input torch.randn(1, 3, 224, 224) torch.onnx.export( model, dummy_input, ./chlorophyll_predictor.onnx, input_names[image], output_names[spad_value], opset_version11, dynamic_axes{image: {0: batch_size}} ) # 2. 推理 sess ort.InferenceSession(./chlorophyll_predictor.onnx) def predict_spad(img_path): img cv2.imread(img_path) # BGR格式 img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 复用extract_leaf_roi做ROI提取这里简写 roi extract_leaf_roi_single(img) roi cv2.resize(roi, (224, 224)) # 归一化必须和训练时完全一致 from torchvision import transforms tf transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) tensor tf(roi).unsqueeze(0).numpy() # onnxruntime推理 spad sess.run([spad_value], {image: tensor})[0][0, 0] return spad print(f预测结果: {predict_spad(./test_images/leaf_001.jpg):.1f} SPAD)这里最容易被忽略的是归一化参数必须和训练时完全一致——Normalize的mean和std如果错一个像素值预测结果可能偏1~3个SPAD。所幸这套封装方案把这个风险锁死在了代码里不管谁拿到项目目录只要按顺序跑export和inference得到的结果是一致的。回看这个项目最重要的教训是叶绿素预测的精度瓶颈多半不在模型而在数据和标注。我见过有人花三周调ResNet结构R²从0.72提到0.75结果发现只是SPAD测量时手劲大小不同带来的标签抖动也见过有人老老实实先用色卡校正再训练一个普通的MobileNetV2直接跑到0.85。建议拿到任何图像预测叶绿素的zip包先别急着解压训练花一天时间把数据按拍摄条件分成组用分组交叉验证评估数据本身的稳定性——如果不同拍摄条件下模型的误差差异很大说明问题在数据而不在模型。这条经验在多个作物图像数据集水稻、小麦、玉米上都成立。希望帮到你。本文还有配套的精品资源点击获取
返回列表