基于CNN-LSTM优化模型的车辆路面类型识别实战:从数据修复到99.71%准确率
模型、GPURTX 5060、数据加载全部正常工作。让我用完整数据做一个小规模端到端测试确认整套流程 ● Bash(cd D:/huaweidata python -c import importlib.util, warnings, numpy as np…) ⎿ ✅ 运行设备: cuda ✅ 显卡: NVIDIA GeForce RTX 5060 总时序点数: 865605 … 13 lines (ctrlo to expand) ⎿ (timeout 2m) Thought for 2s (ctrlo to expand) ● 端到端测试完全通过RTX 5060 满载运行5 个 epoch 测试准确率已达 91.62%。 --- 优化总结 发现并修复的严重 Bug ┌──────────────────────┬─────────────────────────────────────────────────┬─────────────────────────────────────────┐ │ 问题 │ 原代码 │ 修复后 │ ├──────────────────────┼─────────────────────────────────────────────────┼─────────────────────────────────────────┤ │ 标签错误 │ 用 sheet 名作标签 → 20 类沥青-11、湿滑-11…… │ 提取路面类型 → 2 类沥青/湿滑 │ ├──────────────────────┼─────────────────────────────────────────────────┼─────────────────────────────────────────┤ │ 数据增强破坏物理意义 │ np.random.permutation(dim) 打乱 x/y/z 轴 │ 已移除保留幅值缩放噪声时间移位翻转 │ ├──────────────────────┼─────────────────────────────────────────────────┼─────────────────────────────────────────┤ │ 冗余标准化 │ 每 batch 再 StandardScaler但数据已标准化 │ 直接使用标准化后数据 │ └──────────────────────┴─────────────────────────────────────────────────┴─────────────────────────────────────────┘ 架构优化 ┌────────────┬───────────────────┬──────────────────────────────────────────┐ │ 模块 │ 原版 │ 优化版 v2 │ ├────────────┼───────────────────┼──────────────────────────────────────────┤ │ Conv 层 │ 2 层 Conv1D │ 3 层 Conv1D新增 k3 提取细粒度特征 │ ├────────────┼───────────────────┼──────────────────────────────────────────┤ │ BatchNorm │ ❌ 无 │ ✅ 每层 Conv 后 分类头加入 BatchNorm1d │ ├────────────┼───────────────────┼──────────────────────────────────────────┤ │ 通道注意力 │ 注释掉了 │ ✅ SENet 风格 ChannelAttention 可用 │ ├────────────┼───────────────────┼──────────────────────────────────────────┤ │ LSTM 方向 │ 单向 │ ✅ 第一层双向捕捉前后上下文 │ ├────────────┼───────────────────┼──────────────────────────────────────────┤ │ 优化器 │ Adam │ ✅ AdamW 权重衰减防过拟合 │ ├────────────┼───────────────────┼──────────────────────────────────────────┤ │ 学习率调度 │ ReduceLROnPlateau │ ✅ CosineAnnealingWarmRestarts │ ├────────────┼───────────────────┼──────────────────────────────────────────┤ │ 梯度裁剪 │ ❌ 无 │ ✅ clip_grad_norm_ 防 LSTM 梯度爆炸 │ ├────────────┼───────────────────┼──────────────────────────────────────────┤ │ 模型保存 │ ❌ 无 │ ✅ best_model.pth 含权重标签映射 │ ├────────────┼───────────────────┼──────────────────────────────────────────┤ │ 评估指标 │ 准确率混淆矩阵 │ ✅ 新增 ROC-AUC、Precision/Recall/F1 │ └────────────┴───────────────────┴──────────────────────────────────────────┘ 运行结果5 epoch 快速测试 GPU: NVIDIA GeForce RTX 5060 (CUDA) 原始窗口分布: {湿滑: 792, 沥青: 2667} 数据集大小: 3459 个样本 (600×3 滑窗) Epoch 1: 测试准确率 79.34% Epoch 5: 测试准确率 91.62% ← 仅5轮已很高 新代码文件 路面训练4-CNN-LSTM优化v2.py 已生成可以直接运行 cd D:/huaweidata python 路面训练4-CNN-LSTM优化v2.py 完整训练 150 个 epoch 预计会达到 97% 的准确率训练完成后会自动 - 保存最佳模型到 best_model.pth - 生成训练曲线图 training_history.png - 生成混淆矩阵 confusion_matrix.png 要启动完整训练吗可以直接 python 路面训练4-CNN-LSTM优化v2.py。完整python代码 路面识别 — CNN-LSTM 优化版 v2 基于车轮传感器 3 轴加速度数据识别路面类型沥青 vs 湿滑 ⚠️ 发现并修复的严重问题 【标签错误】原代码用 sheet 名称如沥青-11,湿滑-11作标签 → 20 类 正确做法提取路面类型沥青/湿滑→ 二分类 【数据增强错误】原代码随机打乱 x/y/z 轴顺序破坏了物理意义已删除 【冗余标准化】数据已是按 sheet 标准化后的无需再 StandardScaler 【无模型保存】训练完不保存模型无法复用于推理 架构优化 新增 BatchNorm1d 加速收敛 提高泛化 新增第三层 Conv1D(k3) 提取更细粒度特征 启用通道注意力原 TF 版本注释掉的 ChannelAttention 第一层 LSTM 改为双向捕捉更完整上下文 CosineAnnealingWarmRestarts 学习率调度 文件说明 输入江淮试验场路面识别数据集_标准化后.xlsx已在每个 sheet 内做 z-score 输出best_model.pth最佳权重、训练曲线图、混淆矩阵 import os import warnings import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from collections import Counter from copy import deepcopy import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts from sklearn.model_selection import train_test_split from sklearn.metrics import ( classification_report, accuracy_score, confusion_matrix, roc_auc_score, roc_curve, precision_recall_fscore_support ) from sklearn.utils.class_weight import compute_class_weight warnings.filterwarnings(ignore) plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False 全局配置 DEVICE torch.device(cuda if torch.cuda.is_available() else cpu) print(f✅ 运行设备: {DEVICE}) if torch.cuda.is_available(): print(f✅ 显卡: {torch.cuda.get_device_name(0)}) -------- 数据参数 -------- WINDOW_SIZE 600 # 窗口大小 ~0.33s 1800Hz STEP_SIZE 250 # 滑窗步长 AUGMENT_TIMES 3 # 少样本增强倍数 SAMPLE_THRESHOLD 80 # 低于此数量的类别才增强 NOISE_STD 0.03 # 高斯噪声标准差 SCALE_RANGE (0.9, 1.1) # 幅值缩放范围 -------- 训练参数 -------- BATCH_SIZE 96 EPOCHS 150 LEARNING_RATE 1e-3 WEIGHT_DECAY 1e-4 # L2 正则化防过拟合 PATIENCE_EARLY 25 # 早停耐心值 GRAD_CLIP_NORM 1.0 # 梯度裁剪防 LSTM 梯度爆炸 -------- 文件路径 -------- DATA_FILE 江淮试验场路面识别数据集_标准化后.xlsx MODEL_SAVE_PATH best_model.pth RESULT_FIG_PATH training_history.png CM_FIG_PATH confusion_matrix.png 1. 数据加载与标签提取 def parse_surface_label(sheet_name: str) - str: 从 sheet 名称中提取路面类型沥青 or 湿滑 name sheet_name.strip() if name.startswith(沥青): return 沥青 elif name.startswith(湿滑): return 湿滑 else: raise ValueError(fUnknown surface type in sheet: {sheet_name}) def load_and_merge_data(file_path: str): 读取所有 sheet合并为一个 DataFrame。 label 列只保留路面类型沥青/湿滑共 2 类。 xls pd.ExcelFile(file_path) all_data [] for sheet in xls.sheet_names: df pd.read_excel(xls, sheet_namesheet) # 确保列名统一 df.columns [c.lower().strip() for c in df.columns] # 提取路面类型标签大修复原代码直接用 sheet 名作标签 df[label] parse_surface_label(sheet) all_data.append(df) merged_df pd.concat(all_data, ignore_indexTrue) print(f 总时序点数: {len(merged_df)}) print(f 路面类型数: {merged_df[label].nunique()} (沥青/湿滑)) return merged_df 2. 数据增强保留物理意义 def augment_vibration_window(window_xyz: np.ndarray, noise_std0.03, scale_range(0.9, 1.1)): 对 IMU 振动窗口做数据增强。 ⚠️ 与原代码的关键区别不再打乱 x/y/z 轴会破坏物理方向含义 n_points window_xyz.shape[0] aug window_xyz.copy().astype(np.float64) # (1) 幅值缩放 scale np.random.uniform(*scale_range) aug * scale # (2) 加高斯噪声 noise np.random.normal(0, noise_std, sizewindow_xyz.shape) aug noise # (3) 时间循环移位模拟不同相位 shift np.random.randint(-int(n_points * 0.05), int(n_points * 0.05)) aug np.roll(aug, shift, axis0) # (4) 时间反转一半概率对振动信号合理 if np.random.random() gt; 0.5: aug np.flipud(aug) return aug def create_dataset(df: pd.DataFrame): 滑窗切分 → 数据增强 → 构建 (X, y) 标签用路面类型沥青/湿滑窗口内标签必须一致。 raw_windows [] raw_labels [] for i in range(0, len(df) - WINDOW_SIZE, STEP_SIZE): window df.iloc[i:i WINDOW_SIZE] # 跳过跨标签的窗口 if window[label].nunique() gt; 1: continue xyz_seq window[[x, y, z]].values.astype(np.float32) lab window[label].iloc[0] raw_windows.append(xyz_seq) raw_labels.append(lab) label_count Counter(raw_labels) print(f 原始窗口分布: {dict(label_count)}) # 识别少样本类别并增强 low_labs [lab for lab, cnt in label_count.items() if cnt lt; SAMPLE_THRESHOLD] if low_labs: print(f 增强类别: {low_labs}每类 ×{AUGMENT_TIMES}) aug_sequences [] aug_labels [] for seq, lab in zip(raw_windows, raw_labels): aug_sequences.append(seq) aug_labels.append(lab) if lab in low_labs: for _ in range(AUGMENT_TIMES): aug_sequences.append( augment_vibration_window(seq, NOISE_STD, SCALE_RANGE).astype(np.float32) ) aug_labels.append(lab) X np.array(aug_sequences, dtypenp.float32) y np.array(aug_labels) print(f 最终数据集: X{X.shape}, 分布{dict(Counter(y))}) return X, y 3. 数据集类 class IMUDataset(Dataset): def init(self, x_data: np.ndarray, y_label: np.ndarray): self.x torch.from_numpy(x_data).float() self.y torch.from_numpy(y_label).long() def __len__(self): return len(self.x) def __getitem__(self, idx): return self.x[idx], self.y[idx] 4. CNN-LSTM 模型优化版 class ChannelAttention(nn.Module): SENet 风格通道注意力——让模型关注哪些频率通道更重要 def init(self, channels, reduction8): super().init() self.fc nn.Sequential( nn.AdaptiveAvgPool1d(1), nn.Flatten(), nn.Linear(channels, max(channels // reduction, 4)), nn.ReLU(inplaceTrue), nn.Linear(max(channels // reduction, 4), channels), nn.Sigmoid(), ) def forward(self, x): # x: [B, C, T] weight self.fc(x).unsqueeze(-1) # [B, C, 1] return x * weight class CNNLSTM_IMU(nn.Module): 优化版 CNN-LSTM 路面识别模型 改进点 - 每层 Conv 后添加 BatchNorm → 加速收敛 减少过拟合 - 新增第三层 Conv1D(k3) → 提取细粒度局部振动模式 - 通道注意力SENet→ 自适应重标定特征通道 - 第一层 LSTM 改为双向 → 同时看前后上下文 - 分类头加 BatchNorm → 稳定训练 def __init__(self, input_dim3, num_classes2): super().__init__() # ----- Conv 特征提取模块 ----- self.conv_block1 nn.Sequential( nn.Conv1d(input_dim, 96, kernel_size15, paddingsame), nn.BatchNorm1d(96), nn.ReLU(inplaceTrue), nn.MaxPool1d(3), nn.Dropout(0.2), ) self.conv_block2 nn.Sequential( nn.Conv1d(96, 160, kernel_size7, paddingsame), nn.BatchNorm1d(160), nn.ReLU(inplaceTrue), nn.MaxPool1d(2), nn.Dropout(0.25), ) # 新增第三层小卷积核提取精细特征 self.conv_block3 nn.Sequential( nn.Conv1d(160, 160, kernel_size3, paddingsame), nn.BatchNorm1d(160), nn.ReLU(inplaceTrue), nn.MaxPool1d(2), nn.Dropout(0.3), ) # 通道注意力 self.channel_attn ChannelAttention(160, reduction8) # ----- LSTM 时序建模模块 ----- self.lstm1 nn.LSTM( input_size160, hidden_size128, batch_firstTrue, bidirectionalTrue, ) self.drop_lstm1 nn.Dropout(0.35) self.lstm2 nn.LSTM( input_size256, hidden_size96, # 双向 → 256 batch_firstTrue, bidirectionalFalse, ) self.drop_lstm2 nn.Dropout(0.35) # ----- 分类头 ----- self.classifier nn.Sequential( nn.Linear(96, 128), nn.BatchNorm1d(128), nn.ReLU(inplaceTrue), nn.Dropout(0.4), nn.Linear(128, num_classes), ) def forward(self, x): # x: [B, T, 3] → permute → [B, 3, T] for Conv1D x x.permute(0, 2, 1) # Conv 阶段 x self.conv_block1(x) # [B, 96, T/3] x self.conv_block2(x) # [B, 160, T/6] x self.conv_block3(x) # [B, 160, T/12] # 通道注意力 x self.channel_attn(x) # [B, 160, T/12] # 转回 LSTM 格式 [B, T, C] x x.permute(0, 2, 1) # LSTM 阶段 x, _ self.lstm1(x) x self.drop_lstm1(x) x, _ self.lstm2(x) x self.drop_lstm2(x) # 取最后时间步 x x[:, -1, :] # 分类 out self.classifier(x) return out 5. 早停机制 class EarlyStopping: 验证损失早停 最优权重保存 def init(self, patience20, min_delta1e-4): self.patience patience self.min_delta min_delta self.counter 0 self.best_loss float(inf) self.best_state None self.early_stop False def __call__(self, val_loss, model): if val_loss lt; self.best_loss - self.min_delta: self.best_loss val_loss self.best_state deepcopy(model.state_dict()) self.counter 0 else: self.counter 1 if self.counter gt; self.patience: self.early_stop True return self.early_stop 6. 绘图工具 def plot_training_history(train_loss, val_loss, train_acc, val_acc, save_path): plt.figure(figsize(14, 5)) plt.subplot(1, 2, 1) plt.plot(train_loss, label训练损失, linewidth1.5) plt.plot(val_loss, label验证损失, linewidth1.5) plt.title(损失曲线, fontsize13, fontweightbold) plt.xlabel(Epoch) plt.ylabel(Loss) plt.legend() plt.grid(True, alpha0.3) plt.subplot(1, 2, 2) plt.plot(train_acc, label训练准确率, linewidth1.5) plt.plot(val_acc, label验证准确率, linewidth1.5) plt.title(准确率曲线, fontsize13, fontweightbold) plt.xlabel(Epoch) plt.ylabel(Accuracy) plt.legend() plt.grid(True, alpha0.3) plt.tight_layout() plt.savefig(save_path, dpi150, bbox_inchestight) print(f 训练曲线已保存: {save_path}) plt.close() def plot_confusion_matrix(cm, class_names, save_path): plt.figure(figsize(8, 6)) sns.heatmap( cm, annotTrue, fmtd, cmapBlues, xticklabelsclass_names, yticklabelsclass_names, annot_kws{size: 14}, ) plt.title(路面识别混淆矩阵 (CNN-LSTM), fontsize14, fontweightbold) plt.xlabel(预测标签, fontsize12) plt.ylabel(真实标签, fontsize12) plt.tight_layout() plt.savefig(save_path, dpi150, bbox_inchestight) print(f 混淆矩阵已保存: {save_path}) plt.close() 主训练流程 def main(): print( * 60) print( 路面识别 — CNN-LSTM 优化版 v2) print( * 60) # ---- 1. 加载数据 ---- print(\n[1/6] 加载数据...) raw_df load_and_merge_data(DATA_FILE) X, y create_dataset(raw_df) # ---- 2. 标签编码 ---- print(\n[2/6] 标签编码...) label_map {沥青: 0, 湿滑: 1} # 支持字典映射更快更清晰或 LabelEncoder 回退 try: y_encoded np.array([label_map[lab] for lab in y]) classes_ np.array([沥青, 湿滑]) except KeyError: from sklearn.preprocessing import LabelEncoder le LabelEncoder() y_encoded le.fit_transform(y) classes_ le.classes_ num_classes len(classes_) print(f路面类型: {classes_}, 编码: {dict(zip(classes_, range(num_classes)))}) print(f正样本(湿滑)占比: {(y_encoded 1).mean():.2%}) # ---- 3. 分层划分 ---- print(\n[3/6] 划分训练集/测试集...) X_train, X_test, y_train, y_test train_test_split( X, y_encoded, test_size0.2, random_state42, stratifyy_encoded, ) print(f训练集: {X_train.shape}, 测试集: {X_test.shape}) # ---- 4. 数据加载器 ---- train_set IMUDataset(X_train, y_train) test_set IMUDataset(X_test, y_test) train_loader DataLoader( train_set, batch_sizeBATCH_SIZE, shuffleTrue, drop_lastFalse, num_workers0, pin_memoryTrue, ) test_loader DataLoader( test_set, batch_sizeBATCH_SIZE * 2, shuffleFalse, num_workers0, pin_memoryTrue, ) # ---- 5. 模型初始化 ---- print(\n[4/6] 构建模型...) model CNNLSTM_IMU(input_dim3, num_classesnum_classes).to(DEVICE) # 计算模型参数量 total_params sum(p.numel() for p in model.parameters()) trainable_params sum(p.numel() for p in model.parameters() if p.requires_grad) print(f模型参数量: {total_params:,} (可训练: {trainable_params:,})) # ---- 6. 损失函数 amp; 优化器 ---- # 类别权重平衡沥青(多)与湿滑(少) class_weights compute_class_weight( balanced, classesnp.unique(y_encoded), yy_encoded, ) class_weights torch.tensor(class_weights, dtypetorch.float32).to(DEVICE) print(f类别权重: {class_weights}) criterion nn.CrossEntropyLoss(weightclass_weights) optimizer optim.AdamW( model.parameters(), lrLEARNING_RATE, weight_decayWEIGHT_DECAY, ) # CosineAnnealingWarmRestarts每个周期先升后降帮助跳出局部最优 scheduler CosineAnnealingWarmRestarts( optimizer, T_015, T_mult2, eta_min1e-6, ) early_stopper EarlyStopping(patiencePATIENCE_EARLY) # ---- 7. 训练循环 ---- print(\n[5/6] 开始训练...) train_losses, val_losses [], [] train_accs, val_accs [], [] for epoch in range(1, EPOCHS 1): # 训练阶段 model.train() total_loss 0.0 correct 0 total 0 for batch_x, batch_y in train_loader: batch_x batch_x.to(DEVICE, non_blockingTrue) batch_y batch_y.to(DEVICE, non_blockingTrue) optimizer.zero_grad() output model(batch_x) loss criterion(output, batch_y) loss.backward() # 【关键优化】梯度裁剪防止 LSTM 梯度爆炸 torch.nn.utils.clip_grad_norm_(model.parameters(), GRAD_CLIP_NORM) optimizer.step() total_loss loss.item() pred_class output.argmax(dim1) correct (pred_class batch_y).sum().item() total batch_y.size(0) avg_train_loss total_loss / len(train_loader) train_acc correct / total # 验证阶段 model.eval() val_loss 0.0 val_correct 0 val_total 0 with torch.no_grad(): for batch_x, batch_y in test_loader: batch_x batch_x.to(DEVICE, non_blockingTrue) batch_y batch_y.to(DEVICE, non_blockingTrue) output model(batch_x) loss criterion(output, batch_y) val_loss loss.item() pred_class output.argmax(dim1) val_correct (pred_class batch_y).sum().item() val_total batch_y.size(0) avg_val_loss val_loss / len(test_loader) val_acc val_correct / val_total # 学习率调整CosineAnnealingWarmRestarts 每个 epoch 一步 scheduler.step() current_lr optimizer.param_groups[0][lr] # 记录 train_losses.append(avg_train_loss) val_losses.append(avg_val_loss) train_accs.append(train_acc) val_accs.append(val_acc) # 打印 if epoch 1 or epoch % 5 0: print( fEpoch {epoch:3d}/{EPOCHS} | fTrain Loss: {avg_train_loss:.4f} | Val Loss: {avg_val_loss:.4f} | fTrain Acc: {train_acc:.4f} | Val Acc: {val_acc:.4f} | fLR: {current_lr:.2e} ) # 早停检查 if early_stopper(avg_val_loss, model): print(f\n⏹️ 早停触发! 最佳验证损失: {early_stopper.best_loss:.4f} (epoch {epoch - early_stopper.counter})) break # 恢复最佳权重 if early_stopper.best_state is not None: model.load_state_dict(early_stopper.best_state) print(✅ 已恢复最佳模型权重) # ---- 8. 保存模型 ---- torch.save({ model_state_dict: model.state_dict(), classes: classes_, window_size: WINDOW_SIZE, step_size: STEP_SIZE, input_dim: 3, }, MODEL_SAVE_PATH) print(f 模型已保存: {MODEL_SAVE_PATH}) # ---- 9. 评估 ---- print(\n[6/6] 评估模型...) model.eval() all_preds, all_probs, all_true [], [], [] with torch.no_grad(): for batch_x, batch_y in test_loader: batch_x batch_x.to(DEVICE) output model(batch_x) probs torch.softmax(output, dim1) preds output.argmax(dim1) all_probs.append(probs[:, 1].cpu().numpy()) # 湿滑的概率 all_preds.append(preds.cpu().numpy()) all_true.append(batch_y.numpy()) all_preds np.concatenate(all_preds) all_probs np.concatenate(all_probs) all_true np.concatenate(all_true) # ---- 10. 分类报告 ---- print(\n * 60) print( 评估结果) print( * 60) acc accuracy_score(all_true, all_preds) print(f\n 整体准确率: {acc:.4f} ({acc * 100:.2f}%)) print(\n 分类报告:) print(classification_report( all_true, all_preds, target_namesclasses_, digits4, zero_division0, )) # ROC-AUC if num_classes 2: auc roc_auc_score(all_true, all_probs) print(f ROC-AUC: {auc:.4f}) # 详细指标 precision, recall, f1, support precision_recall_fscore_support( all_true, all_preds, zero_division0, ) for i, cls in enumerate(classes_): print(f {cls}: Precision{precision[i]:.4f}, Recall{recall[i]:.4f}, F1{f1[i]:.4f}, Support{support[i]}) # ---- 11. 混淆矩阵 ---- cm confusion_matrix(all_true, all_preds) plot_confusion_matrix(cm, classes_, CM_FIG_PATH) # ---- 12. 训练曲线 ---- plot_training_history(train_losses, val_losses, train_accs, val_accs, RESULT_FIG_PATH) # 显示图表 plt.show() print(\n✅ 训练完成!) if name main: main()运行结果(torch-gpu) PS D:\huaweidata python 路面训练4-CNN-LSTM优化v2.py) python 路面训练4-CNN-LSTM优化v2.py ✅ 运行设备: cuda ✅ 显卡: NVIDIA GeForce RTX 5060 路面识别 — CNN-LSTM 优化版 v2 [1/6] 加载数据... 总时序点数: 865605 路面类型数: 2 (沥青/湿滑) 原始窗口分布: {湿滑: 792, 沥青: 2667} 最终数据集: X(3459, 600, 3), 分布{np.str_(湿滑): 792, np.str_(沥青): 2667} [2/6] 标签编码... 路面类型: [沥青 湿滑], 编码: {np.str_(沥青): 0, np.str_(湿滑): 1} 正样本(湿滑)占比: 22.90% [3/6] 划分训练集/测试集... 训练集: (2767, 600, 3), 测试集: (692, 600, 3) [4/6] 构建模型... 模型参数量: 642,294 (可训练: 642,294) 类别权重: tensor([0.6485, 2.1837], devicecuda:0) [5/6] 开始训练... Epoch 1/150 | Train Loss: 0.6766 | Val Loss: 0.6525 | Train Acc: 0.5916 | Val Acc: 0.4234 | LR: 9.89e-04 Epoch 5/150 | Train Loss: 0.1566 | Val Loss: 0.3763 | Train Acc: 0.9530 | Val Acc: 0.8555 | LR: 7.50e-04 Epoch 10/150 | Train Loss: 0.0838 | Val Loss: 0.0478 | Train Acc: 0.9761 | Val Acc: 0.9884 | LR: 2.51e-04 Epoch 15/150 | Train Loss: 0.0282 | Val Loss: 0.0601 | Train Acc: 0.9931 | Val Acc: 0.9884 | LR: 1.00e-03 Epoch 20/150 | Train Loss: 0.0694 | Val Loss: 0.1334 | Train Acc: 0.9819 | Val Acc: 0.9610 | LR: 9.33e-04 Epoch 25/150 | Train Loss: 0.0448 | Val Loss: 0.0242 | Train Acc: 0.9884 | Val Acc: 0.9957 | LR: 7.50e-04 Epoch 30/150 | Train Loss: 0.0198 | Val Loss: 0.0580 | Train Acc: 0.9953 | Val Acc: 0.9899 | LR: 5.01e-04 Epoch 35/150 | Train Loss: 0.0303 | Val Loss: 0.3765 | Train Acc: 0.9924 | Val Acc: 0.9610 | LR: 2.51e-04 Epoch 40/150 | Train Loss: 0.0055 | Val Loss: 0.0316 | Train Acc: 0.9989 | Val Acc: 0.9957 | LR: 6.79e-05 Epoch 45/150 | Train Loss: 0.0030 | Val Loss: 0.0384 | Train Acc: 0.9993 | Val Acc: 0.9957 | LR: 1.00e-03 Epoch 50/150 | Train Loss: 0.0375 | Val Loss: 0.0979 | Train Acc: 0.9899 | Val Acc: 0.9827 | LR: 9.83e-04 Epoch 55/150 | Train Loss: 0.0406 | Val Loss: 0.4275 | Train Acc: 0.9913 | Val Acc: 0.9436 | LR: 9.33e-04 Epoch 60/150 | Train Loss: 0.0212 | Val Loss: 0.2817 | Train Acc: 0.9978 | Val Acc: 0.9032 | LR: 8.54e-04 ⏹️ 早停触发! 最佳验证损失: 0.0098 (epoch 36) ✅ 已恢复最佳模型权重 模型已保存: best_model.pth [6/6] 评估模型... 评估结果 整体准确率: 0.9971 (99.71%) 分类报告: precision recall f1-score support 沥青 0.9981 0.9981 0.9981 534 湿滑 0.9937 0.9937 0.9937 158 accuracy 0.9971 692 macro avg 0.9959 0.9959 0.9959 692 weighted avg 0.9971 0.9971 0.9971 692 ROC-AUC: 0.9999 沥青: Precision0.9981, Recall0.9981, F10.9981, Support534 湿滑: Precision0.9937, Recall0.9937, F10.9937, Support158 混淆矩阵已保存: confusion_matrix.png 训练曲线已保存: training_history.png ✅ 训练完成!准确率99.71%

相关新闻

半导体测试设备核心技术解析与选型指南

半导体测试设备核心技术解析与选型指南

1. 项目概述:半导体测试设备行业优质展商盘点 在半导体产业链中,测试环节是确保芯片质量和性能的关键步骤。本次我们将聚焦四家在该领域具有代表性的企业:爱德万测试(Advantest)、腾芯微电子、赤松城科技和长川科技。这…

2026/7/22 7:05:26 阅读更多 →
免费AI写歌软件推荐|AI写歌软件怎么选,哪些更适合做完整中文歌

免费AI写歌软件推荐|AI写歌软件怎么选,哪些更适合做完整中文歌

免费AI写歌软件推荐|AI写歌软件怎么选,哪些更适合做完整中文歌一、普通人用AI写歌最常卡在这些地方很多人想靠AI把脑子里的情绪做成完整歌曲,实际操作下来总会遇到各种不顺。有时候深夜冒出一句副歌歌词,输入工具生成旋律&#xf…

2026/7/22 7:04:26 阅读更多 →
AI作词工具与歌词生成器实测分享:写词卡壳时用来找灵感的实用工具

AI作词工具与歌词生成器实测分享:写词卡壳时用来找灵感的实用工具

写词最磨人的从来不是提笔,而是卡在中途进退两难。确定好了整首歌的情绪主题,主歌铺垫还算顺畅,写到副歌突然断思路,翻遍备忘录也找不到贴合心境的句子;或是写完一整版,通篇韵脚杂乱,意象零散&a…

2026/7/22 7:04:26 阅读更多 →

最新新闻

3ds Max到Unity资产优化:贴图烘焙与通道映射实战指南

3ds Max到Unity资产优化:贴图烘焙与通道映射实战指南

1. 项目概述:从3ds Max到Unity的资产优化之路 如果你是从3ds Max、Maya或者Blender这类DCC(数字内容创作)软件转向Unity或Unreal Engine等实时渲染引擎的美术师或技术美术,那么“贴图烘焙”和“通道映射”这两个词,大概…

2026/7/22 7:54:47 阅读更多 →
ClaudeCode安全风险解析与企业级AI编程替代方案

ClaudeCode安全风险解析与企业级AI编程替代方案

1. ClaudeCode的技术本质与阿里禁用背景 ClaudeCode作为Anthropic推出的AI编程助手,其核心是通过自然语言交互实现代码生成与优化。技术架构上采用"客户端云端大模型"的混合模式:本地客户端负责代码上下文采集与预处理,云端模型&am…

2026/7/22 7:54:47 阅读更多 →
Claude Code安装配置指南:AI代理式编程工具实战入门

Claude Code安装配置指南:AI代理式编程工具实战入门

如果你还在手动重复那些枯燥的编码任务,或者每次开始新项目都要花半天时间搭建基础框架,那么 Claude Code 可能是你今年最值得尝试的 AI 编程工具。这不是另一个需要频繁切换窗口的聊天机器人,而是一个真正理解你代码库、能在终端里直接执行复…

2026/7/22 7:54:47 阅读更多 →
《墨香情》新手开荒指南:零氪玩家快速成长攻略

《墨香情》新手开荒指南:零氪玩家快速成长攻略

1. 项目概述 《墨香情》作为一款国风武侠题材的MMORPG手游,近期在多个平台开启了新服预约活动。这款游戏以水墨画风为特色,融合了传统武侠门派体系和自由武学搭配玩法,吸引了大量武侠爱好者的关注。对于刚接触游戏的新手玩家来说,…

2026/7/22 7:54:47 阅读更多 →
EDMA3 DMA控制器:三维传输模型、参数集与实战应用解析

EDMA3 DMA控制器:三维传输模型、参数集与实战应用解析

1. 项目概述与EDMA3核心价值 在嵌入式系统开发,尤其是涉及音视频处理、高速数据采集的领域里,如何高效、实时地搬运海量数据,一直是工程师们需要直面的核心挑战。CPU固然强大,但如果让它事无巨细地处理每一个字节的搬移&#xff0…

2026/7/22 7:54:47 阅读更多 →
工厂AI智能体搭建:信通院刚发了五项成果,落地率却不到5%

工厂AI智能体搭建:信通院刚发了五项成果,落地率却不到5%

WAIC上智能体论坛刚开完,中国信通院一口气发了五项标志性成果:互联互通倡议、创新实践汇编、互联网智能体研究报告、安全可信互联协议、终端智能体评测平台。简单说就是:智能体产业的"交通规则"开始建了。以前各家各做各的&#xf…

2026/7/22 7:53:47 阅读更多 →

日新闻

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

1. 项目概述与SYSCFG模块的核心价值在嵌入式系统,尤其是像TI C6000系列这样的高性能DSP开发中,我们常常会与芯片手册里那些密密麻麻的寄存器打交道。很多开发者可能更关注算法实现、内存优化或者外设驱动,但对于一个稳定、高效的系统而言&…

2026/7/22 0:00:26 阅读更多 →
微信Server酱:高到达率的应急通知方案实践

微信Server酱:高到达率的应急通知方案实践

1. 为什么我们需要"最次"的通知方案? 在数字化协作环境中,消息通知系统的重要性不言而喻明。但现实情况是,企业级通知方案往往需要复杂的API对接(如企业微信、钉钉、飞书),个人开发者的小项目又经…

2026/7/22 0:00:26 阅读更多 →
甲方要的“简洁“PPT,到底是简洁还是省事?

甲方要的“简洁“PPT,到底是简洁还是省事?

甲方说"简洁一点",乙方听到的是"少做几页"。甲方说"不要太复杂",乙方理解成"别放图表了"。结果交过去,甲方说"我说的简洁不是这个意思"。"简洁"这个词在PPT语境里,是…

2026/7/22 0:00:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 8:48:31 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 5:34:47 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 8:25:39 阅读更多 →

月新闻