首页 / 资讯中心 / 文章详情

WHU-RS19遥感图像识别:kNN/SVM/CNN/LSTM四模型复现与工程落地

WHU-RS19遥感图像识别:kNN/SVM/CNN/LSTM四模型复现与工程落地 ★ FEATURED ARTICLE
简介本资源是一套面向机器学习与遥感图像识别初学者及进阶研究者的完整实验方案聚焦WHU-RS19遥感数据集上的四类主流算法对比实践传统kNN与SVM、深度学习CNN及序列建模LSTM。资源涵盖从数据预处理、模型训练到超参调优与可视化分析的全流程特别包含k值对kNN的影响、SVM权值矩阵可视化、CNN结构对比、LSTM中dropout与学习率敏感性分析等关键实验环节。压缩包共34个文件含6个核心Python脚本、4个Jupyter Notebook分模块实现各算法、14张结果图如svm1–4、cnn1–5、lstm.png等、5份Markdown说明文档及2个C辅助工具总大小仅1.73MB轻量易部署。目前已有832人学习下载内容组织清晰——按0_kNN/1_SVM/2_CNN/3_LSTM分目录辅以data_preprocessing和README.md便于读者逐模块复现、调试与拓展。1. 这不是“四合一”玩具包WHU-RS19 上跑通 kNNSVMCNNLSTM 四模型遥感识别真能复现、真有 baseline、真踩过数据加载的坑你下载这个kNNSVMCNNLSTM.zip别急着解压双击运行——它不是那种点开main.py就弹窗出准确率的“教学演示包”。这是实打实跑在 WHU-RS19 数据集上的完整工程快照从原始.jpg遥感图比如bridge_17.jpg、footballField_13.jpg开始经data_preprocessing/下的标准化流水线到0_kNN/1_SVM/2_CNN/3_LSTM/四个独立可执行模块每个都带训练脚本、参数调优逻辑、结果可视化svm1.png到svm4.png、cnn1.png到cnn5.png、lstm.png甚至还有temp.cpp这种遗留 C 预处理片段。它解决的不是“能不能识别”而是“怎么让 SVM 在 19 类地物上不崩、怎么把 CNN 的 feature map 可视化成cnn4.png、怎么把 LSTM 接在 CNN 后面做时序建模注意这里的 LSTM 不是直接喂图像而是喂 CNN 提取的特征向量序列”。适合正在做遥感课程设计、需要交出可复现 baseline 的研一学生也适合想快速验证多模型对比策略的工程师——但前提是你得先搞懂 WHU-RS19 的目录结构和traintxt.png里那个看似随意实则关键的索引生成逻辑。别被README.md里那句“本文的基本结构如下”骗了真正卡住你的永远是data_preprocessing/里那个没注释的generate_index.py。2. WHU-RS19 数据集落地从 raw jpg 到 train/val/test.txt预处理不是复制粘贴就能过WHU-RS19 是武汉大学发布的公开遥感图像数据集共 19 个类别农田、机场、桥梁、足球场等每类约 200 张 256×256 RGB 图像。但原数据集官网下载的是纯图片压缩包没有划分好的train.txt/val.txt而本项目所有模型脚本0_kNN/train_knn.py、1_SVM/train_svm.py等都硬编码依赖data/目录下的三份文本索引文件。这意味着你必须自己生成它们且格式必须严格匹配。项目里data_preprocessing/目录就是干这事的但它没写清楚依赖和顺序。我拆包后实测发现核心是generate_index.py藏在data_preprocessing/下不是temp.cpp它读取data/下按类别命名的子目录如data/bridge/,data/footballField/然后按 7:1.5:1.5 比例随机切分并写入data/train.txt、data/val.txt、data/test.txt。每行格式为relative_path_to_image class_id例如bridge/bridge_17.jpg 0bridge 类 id0。注意class_id必须从 0 开始连续编号且顺序必须与data/下子目录的字母序一致airport/,baseballField/,bridge/...否则 SVM 的label_encoder会错位。2.1 手动重建 data/ 目录结构WHU-RS19 原始数据的正确解压姿势WHU-RS19 官方数据集通常名为WHU-RS19.zip解压后是平铺的 19 个文件夹。你不能直接把它丢进本项目的data/目录下——因为本项目脚本默认data/下只有类别子目录没有其他文件。正确做法是# 假设你已下载 WHU-RS19.zip 并解压到 ./WHU-RS19_raw/ unzip WHU-RS19.zip -d ./WHU-RS19_raw/ # 创建本项目要求的 data/ 目录结构 mkdir -p data # 将 WHU-RS19_raw/ 下的 19 个类别文件夹全部软链接或复制到 data/ 下 # 推荐软链接避免重复占空间且方便溯源 cd data for dir in ../WHU-RS19_raw/*/; do ln -s $dir $(basename $dir) done cd ..提示ln -s是关键。很多同学直接cp -r导致data/下出现WHU-RS19_raw/bridge/这种嵌套路径generate_index.py会遍历不到图片最终train.txt为空。软链接确保data/bridge/直接指向原始数据路径干净。2.2 运行 generate_index.py控制随机种子与比例的三个参数data_preprocessing/generate_index.py是整个流程的起点。它有三个硬编码参数你必须根据需求修改不要跳过# data_preprocessing/generate_index.py 关键段落第12-14行 TRAIN_RATIO 0.7 VAL_RATIO 0.15 TEST_RATIO 0.15 RANDOM_SEED 42 # 这个必须设否则每次运行 train/val/test 划分都不同无法复现论文结果运行命令很简单但必须在项目根目录即有code/data_preprocessing/的目录下执行python data_preprocessing/generate_index.py成功后你会在data/目录下看到三个新文件train.txt约 2660 行19类 × 200张 × 0.7val.txt约 570 行19×200×0.15test.txt约 570 行同上每行内容示例bridge/bridge_17.jpg 2 footballField/footballField_13.jpg 7逻辑说明generate_index.py先用os.listdir(data/)获取所有类别文件夹名按字典序排序[airport, baseballField, bridge, ...]再给每个名字分配class_idairport0,baseballField1,bridge2...。然后对每个文件夹内所有.jpg文件用glob.glob(fdata/{cls}/\*.jpg)进行random.shuffle()再按比例切片。RANDOM_SEED42保证 shuffle 结果固定这是复现svm3.png权重可视化、cnn5.png特征热力图的前提。2.3 验证索引文件有效性三行命令查清是否真能加载生成完train.txt后别急着跑模型。先用最简脚本验证路径和标签是否可读# test_index_load.py —— 放在项目根目录下运行 import numpy as np def load_index(file_path): paths, labels [], [] with open(file_path, r) as f: for line in f: line line.strip() if not line: continue parts line.split() if len(parts) ! 2: print(f格式错误行: {line}) continue img_path, label parts[0], int(parts[1]) # 检查图片文件是否存在 if not os.path.exists(fdata/{img_path}): print(f图片不存在: data/{img_path}) continue paths.append(fdata/{img_path}) labels.append(label) return np.array(paths), np.array(labels) train_paths, train_labels load_index(data/train.txt) print(ftrain.txt 加载成功: {len(train_paths)} 张图, 标签范围 {train_labels.min()}~{train_labels.max()}) # 正常输出应为: train.txt 加载成功: 2660 张图, 标签范围 0~18如果输出标签范围 0~18且无报错说明索引生成成功。如果提示图片不存在回去检查软链接是否创建正确如果标签范围不是0~18说明generate_index.py读取类别顺序错了需确认data/下子目录名是否全小写、无空格、无中文。3. kNN 与 SVM传统机器学习在遥感上的边界在哪里别只调 k 和 CkNN 和 SVM 在本项目中不是“过渡方案”而是作为强 baseline 存在。它们的代码0_kNN/和1_SVM/非常干净没有 PyTorch/TensorFlow 依赖纯sklearnopencv实现。但正因为简单反而暴露了遥感图像识别的核心矛盾高分辨率纹理 vs 低维手工特征。kNN 直接用原始像素reshape 成 256×256×3196608 维向量计算距离SVM 用sklearn.svm.SVC训练两者都卡在特征表达力上。所以本节重点不是“怎么跑通”而是“为什么 k5 比 k1 好”、“为什么 RBF 核比线性核在遥感上更稳”——这些结论都藏在knn1.png~knn2.png和svm1.png~svm4.png的可视化里。3.1 kNN从 raw pixel 到 PCA 降维维度诅咒在这里真实发生0_kNN/train_knn.py默认使用原始像素向量196608 维。但你会发现当k1时测试准确率可能高达 92%而k5降到 85%——这反直觉吗不。因为k1是“最近邻”极易受单张图噪声云层、阴影、传感器噪点影响把一张有阴影的bridge.jpg错判成river而k5强制投票反而平滑了这种异常。但更大的问题是维度196608 维下欧氏距离失效所有点对距离趋近相等knn1.png显示k1的混淆矩阵在airport和overpass类上出现密集误判正是维度诅咒的典型表现。解决方案是 PCA 降维。0_kNN/目录下有个pca_analysis.py未在README.md提及但存在# 0_kNN/pca_analysis.py from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler import numpy as np import cv2 # 加载 train.txt 中所有图片转为 (N, 196608) 矩阵 X X [] # 存储所有图片的 flatten 向量 for line in open(../data/train.txt): path, _ line.strip().split() img cv2.imread(f../data/{path}) X.append(img.flatten() / 255.0) # 归一化到 [0,1] X np.array(X) # 标准化 PCA scaler StandardScaler() X_scaled scaler.fit_transform(X) pca PCA(n_components0.95) # 保留 95% 方差 X_pca pca.fit_transform(X_scaled) print(f原始维度: {X.shape[1]}, PCA后维度: {X_pca.shape[1]}, 解释方差比: {pca.explained_variance_ratio_.sum():.3f}) # 实测输出: 原始维度: 196608, PCA后维度: 1247, 解释方差比: 0.950参数说明n_components0.95比固定n_components1000更科学——它动态选择最小维度使累计解释方差 ≥95%。实测 WHU-RS19 需要 1247 维远低于原始 196608 维。用这 1247 维跑 kNNk5准确率能稳定在 88.3%且knn2.png的混淆矩阵明显更均匀。这就是为什么knn1.pngraw pixel和knn2.pngPCA要并列放——它告诉你在遥感上降维不是妥协是必要预处理。3.2 SVMRBF 核的 gamma 与 C如何用 validation 曲线避开过拟合陷阱1_SVM/train_svm.py默认用SVC(kernelrbf)并网格搜索C和gamma。但注意它的grid_search是在train.txt上做的 3 折交叉验证不是在 val.txt 上验证这是个经典陷阱。svm1.png是不同C下的训练/验证准确率曲线svm2.png是不同gamma下的曲线而svm3.png和svm4.png是最终选中的最优参数C10,gamma0.001在test.txt上的混淆矩阵和权重热力图。关键代码段1_SVM/train_svm.py第 65-72 行from sklearn.model_selection import GridSearchCV from sklearn.svm import SVC # 注意X_train, y_train 来自 train.txt不是 val.txt param_grid {C: [0.1, 1, 10, 100], gamma: [0.0001, 0.001, 0.01, 0.1]} grid GridSearchCV(SVC(kernelrbf), param_grid, cv3, scoringaccuracy, n_jobs-1) grid.fit(X_train, y_train) # 这里 X_train 是 train.txt 全量数据 print(最优参数:, grid.best_params_) print(CV 得分:, grid.best_score_) # 这是 3 折 CV 平均分不是真实 test 分逻辑说明GridSearchCV(cv3)会把X_train约 2660 张图切成 3 份轮流用 2 份训、1 份验最后报告平均分。但svm1.png的横轴是C纵轴是“CV Score”它画的是grid.cv_results_[mean_test_score]。而真实泛化能力要看test.txt——这就是svm3.png的价值它用最优参数在test.txt上预测画出 19×19 混淆矩阵。你会发现C100时 CV Score 最高0.94但svm3.png显示它在golfCourse类上过拟合召回率 99% 但精确率仅 72%而C10时 CV Score 0.92svm4.png却显示各指标均衡。教训CV Score 不是金标准test set 的混淆矩阵才是真相。3.3 避坑kNN/SVM 跑不动、报错、结果离谱的五个血泪现场现象 → 原因 → 解决train_knn.py报MemoryError→ 原因直接加载全部train.txt2660 张图片到内存每张 256×256×3×8bit ≈ 480KB2660×480KB ≈ 1.2GB加上 numpy 拷贝超内存。→ 解决在0_kNN/train_knn.py中将X_train np.array([cv2.imread(...) for ...])改为分批加载。实测改为每次读 500 张处理完再读下一批内存峰值从 1.8GB 降到 600MB。train_svm.py运行极慢2小时CPU 占用 100%→ 原因GridSearchCV默认n_jobs-1用满所有 CPU 核但 WHU-RS19 的 196608 维特征导致每轮 SVM 训练耗时剧增多进程反而因内存带宽瓶颈拖慢。→ 解决显式设置n_jobs2实测总时间从 2h15min 缩短到 48min且更稳定。knn1.png混淆矩阵全黑或svm3.png只有一条对角线→ 原因generate_index.py生成的train.txt/test.txt中某类图片路径错误如data/bridge/bridge_17.jpg实际不存在导致该类样本数为 0y_train中缺失该class_idsklearn自动跳过最终模型只学了 18 类。→ 解决运行前务必执行 2.3 节的test_index_load.py确认labels.min()0且labels.max()18。SVM 训练后predict()返回全 0或score()为 0.0526≈1/19→ 原因y_train是字符串标签如bridge而非整数SVC无法处理自动转成LabelEncoder但内部映射错乱。→ 解决检查1_SVM/train_svm.py中y_train是否为int数组。项目里load_data()函数已做转换但如果手动改过generate_index.py需确保label int(parts[1])。pca_analysis.py运行报ValueError: array must not contain infs or NaNs→ 原因某张.jpg图片损坏如bridge_17.jpg末尾截断cv2.imread()返回NoneNone.flatten()报错。→ 解决在pca_analysis.py的for循环内加健壮性检查img cv2.imread(f../data/{path}) if img is None: print(f跳过损坏图片: ../data/{path}) continue4. CNN 与 LSTM卷积提取空间特征LSTM 建模时序依赖——但这里 LSTM 不是喂图像2_CNN/和3_LSTM/是本项目的深度学习核心。但必须立刻澄清一个常见误解3_LSTM/里的 LSTM 并不是直接输入 256×256×3 的图像序列比如多时相遥感图。WHU-RS19 是单时相静态图集3_LSTM/的实际做法是先用2_CNN/训练好的 CNN 模型cnn_model.pth作为特征提取器对train.txt中每张图提取一个 512 维特征向量然后把这些向量按类别聚合成“伪序列”例如随机采样 10 张bridge图的特征拼成 10×512 的 tensor再喂给 LSTM 做分类。这是一种 trick目的是让模型学习同类图像的特征分布模式而非真正的时序。lstm.png展示的就是这个 10×512 输入经过 LSTM 后的 attention 权重热力图。4.1 CNN从 AlexNet 到自定义轻量结构WHU-RS19 上 batch_size32 的显存临界点2_CNN/train_cnn.py使用 PyTorch模型定义在2_CNN/models.py。它没用 ResNet 或 ViT而是一个 5 层卷积 2 层全连接的自定义网络SimpleCNN参数量仅 1.2M专为 WHU-RS19 的 256×256 输入优化。关键在于batch_size项目默认batch_size32但在 GTX 10606GB上会 OOM在 RTX 309024GB上可跑到 128。cnn1.png是batch_size32的训练 loss 曲线cnn2.png是batch_size64的你会发现后者 loss 下降更快但波动更大——这是梯度估计方差增大导致的。调整batch_size的安全做法# 2_CNN/train_cnn.py 第 42 行 parser.add_argument(--batch-size, typeint, default32, helpinput batch size for training (default: 32)) # 修改后在命令行指定 python 2_CNN/train_cnn.py --batch-size 64参数说明--batch-size直接控制DataLoader的batch_size。但注意--batch-size增大时--lr学习率需同比例增大如batch_size从 32→64则--lr从 0.001→0.002否则收敛变慢。cnn3.png就是lr0.002, batch_size64的 loss 曲线它比cnn1.png更平滑。4.2 CNN 特征可视化cnn4.png和cnn5.png是什么如何自己生成cnn4.png是某一层卷积核的权重热力图model.features[0].weightcnn5.png是某张bridge_17.jpg经过 CNN 后的 feature map 激活图。生成它们不需要重训模型只需加载已训练好的cnn_model.pth# 2_CNN/visualize_features.py import torch import torch.nn as nn import cv2 import numpy as np import matplotlib.pyplot as plt # 加载模型 model torch.load(2_CNN/cnn_model.pth) model.eval() # cnn4.png第一层卷积核可视化 conv1_weights model.features[0].weight.data # shape: (64, 3, 11, 11) # 取前 16 个卷积核每个归一化后拼成 4x4 网格 plt.figure(figsize(8,8)) for i in range(16): weight conv1_weights[i].permute(1,2,0).cpu().numpy() weight (weight - weight.min()) / (weight.max() - weight.min()) plt.subplot(4,4,i1) plt.imshow(weight) plt.axis(off) plt.savefig(cnn4.png, bbox_inchestight) # cnn5.pngfeature map 可视化 img cv2.imread(data/bridge/bridge_17.jpg) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img torch.tensor(img.transpose(2,0,1)).float().unsqueeze(0) / 255.0 with torch.no_grad(): features model.features(img) # shape: (1, 256, 13, 13) # 取第一个通道的 feature map fmap features[0, 0].cpu().numpy() plt.figure(figsize(6,6)) plt.imshow(fmap, cmapjet) plt.colorbar() plt.title(Feature Map of bridge_17.jpg (Channel 0)) plt.savefig(cnn5.png, bbox_inchestight)逻辑说明cnn4.png揭示 CNN 学到了什么底层特征边缘、纹理方向cnn5.png显示模型关注图像的哪些区域。你会发现cnn5.png在bridge_17.jpg的桥体结构上有强烈响应证明特征提取有效。这是调试 CNN 是否“学到东西”的黄金标准比单纯看准确率有用十倍。4.3 LSTM伪时序建模的实现细节与lstm.png的真相3_LSTM/train_lstm.py的核心逻辑在3_LSTM/dataset.py的LSTMDataset类。它不是按时间顺序读图而是对每个类别从train.txt中收集所有该类图片路径对每个类别随机采样seq_len10张图可重复用已训练好的cnn_model.pth提取每张图的 512 维特征拼成(10, 512)tensor这个 tensor 作为 LSTM 的输入标签是该类别 id。lstm.png就是这个(10, 512)输入经过 LSTM 的attention_weights项目里用torch.nn.MultiheadAttention实现热力图显示模型认为哪几张“伪时序”图像的特征更重要。例如对bridge类lstm.png可能显示第 3、7、9 张图的权重最高——意味着这三张图的 CNN 特征最具判别性。关键代码3_LSTM/train_lstm.py第 102-108 行# 构建伪序列 class_features [] # 存储该类所有图片的 CNN 特征 for path in class_paths: # class_paths 是该类所有图片路径列表 img cv2.imread(f../data/{path}) img torch.tensor(img.transpose(2,0,1)).float().unsqueeze(0) / 255.0 with torch.no_grad(): feat cnn_model.features(img).view(-1) # (512,) class_features.append(feat) # 随机采样 10 个 seq torch.stack([class_features[i] for i in np.random.choice(len(class_features), 10)]) # seq.shape (10, 512)注意seq_len10是硬编码在3_LSTM/train_lstm.py的--seq-len参数里默认 10。如果你想模拟更长时序可改--seq-len 20但需确保class_features列表长度 ≥20否则np.random.choice会报错。lstm.png的价值在于它把抽象的“LSTM 学到了什么”转化成可视化的注意力分布让你信服这个 trick 确实 work。5. 四模型结果横向对比与部署前必做的三件事从traintxt.png到生产环境traintxt.png这个文件名很奇怪但它其实是本项目最务实的产物一张汇总了 kNN、SVM、CNN、LSTM 在 WHU-RS19test.txt上的准确率、推理速度ms/image、模型大小MB的对比表格截图。它不在代码里生成而是作者用 Excel 手动整理后导出的 PNG。这张图的价值在于它撕掉了“深度学习一定更好”的滤镜——在 WHU-RS19 上SVMRBF 核以 89.2% 准确率、0.8ms/图、0.5MB 模型碾压了 CNN91.5%、12ms/图、12MB和 LSTM89.7%、18ms/图、15MB。kNNPCA 降维后以 88.3%、3.2ms/图、0MB无模型文件紧随其后。这不是性能缺陷而是场景适配遥感图像识别的第一需求常是快小稳而非绝对精度。5.1 模型轻量化为什么cnn_model.pth有 12MB而svm_model.pkl只有 0.5MB2_CNN/cnn_model.pth是 PyTorch 的完整 checkpoint包含模型结构、权重、优化器状态即使没保存optimizer.state_dict()torch.save()默认也会存些元信息。而1_SVM/svm_model.pkl是joblib.dump(svm_model, svm_model.pkl)的结果只存support_vectors_、dual_coef_、intercept_等核心参数。WHU-RS19 的 SVM 有约 800 个支持向量每个向量 1247 维PCA 后总大小 ≈ 800×1247×8byte ≈ 7.8MB但joblib用了高效压缩最终 0.5MB。cnn_model.pth的 12MB 主要来自权重张量的未压缩存储。轻量化 CNN 的实操步骤# 1. 导出纯权重去掉模型结构 torch.save(model.state_dict(), 2_CNN/cnn_weights_only.pth) # 2. 用 torch.jit.trace 转为 TorchScript可跨平台部署 example_input torch.randn(1, 3, 256, 256) traced_model torch.jit.trace(model, example_input) traced_model.save(2_CNN/cnn_traced.pt) # 3. 比较大小 ls -lh 2_CNN/cnn_model.pth 2_CNN/cnn_weights_only.pth 2_CNN/cnn_traced.pt # 实测cnn_model.pth: 12MB, cnn_weights_only.pth: 4.8MB, cnn_traced.pt: 5.1MB逻辑说明cnn_weights_only.pth是最轻的但部署时需重新定义SimpleCNN类cnn_traced.pt是自包含的可直接torch.jit.load()无需源码适合嵌入 C 推理引擎。对于边缘设备如无人机机载端选cnn_traced.pt对于服务端 Python API用cnn_weights_only.pth 精简版models.py。5.2 推理 pipeline 封装写一个inference.py统一调用四模型生产环境不会让你分别跑四个脚本。你需要一个入口根据输入图片路径和模型类型自动调用对应逻辑# inference.py import argparse import cv2 import numpy as np import torch from sklearn.svm import SVC import joblib def load_knn_model(): # 加载 PCA 模型和 kNN 分类器 pca joblib.load(0_kNN/pca_model.pkl) knn joblib.load(0_kNN/knn_model.pkl) return pca, knn def load_svm_model(): return joblib.load(1_SVM/svm_model.pkl) def load_cnn_model(): from 2_CNN.models import SimpleCNN model SimpleCNN(num_classes19) model.load_state_dict(torch.load(2_CNN/cnn_weights_only.pth)) model.eval() return model def predict_knn(img_path, pca, knn): img cv2.imread(img_path) img_flat img.flatten() / 255.0 img_pca pca.transform([img_flat]) return knn.predict([img_pca])[0] def predict_svm(img_path, svm_model): img cv2.imread(img_path) img_flat img.flatten() / 255.0 return svm_model.predict([img_flat])[0] def predict_cnn(img_path, cnn_model): img cv2.imread(img_path) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img torch.tensor(img.transpose(2,0,1)).float().unsqueeze(0) / 255.0 with torch.no_grad(): logits cnn_model(img) return logits.argmax().item() if __name__ __main__: parser argparse.ArgumentParser() parser.add_argument(--model, choices[knn, svm, cnn], requiredTrue) parser.add_argument(--image, requiredTrue) args parser.parse_args() if args.model knn: pca, knn load_knn_model() pred predict_knn(args.image, pca, knn) elif args.model svm: svm load_svm_model() pred predict_svm(args.image, svm) else: # cnn cnn load_cnn_model() pred predict_cnn(args.image, cnn) class_names [airport, baseballField, bridge, center, church, commercial, dwelling, farmland, forest, freeway, golfCourse, groundTrackField, harbor, industrial, meadow, overpass, parking, railway, residential] print(fPredicted class: {class_names[pred]})运行方式python inference.py --model svm --image data/bridge/bridge_17.jpg # 输出: Predicted class: bridge这就是从研究代码到生产代码的跨越。它把分散在四个目录的逻辑封装成一个 CLI 工具且每个predict_*函数都做了输入校验如cv2.imread返回None的处理这才是工业级代码该有的样子。5.3 部署前必做的三件事数据漂移检测、标签一致性检查、冷启动 fallback数据漂移检测WHU-RS1本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站