CNN-BiLSTM 分心驾驶检测框架:电动公交车知识迁移方案

论文信息

项目 内容
标题 A Distracted Driving Detection Framework for Electric Buses with Hybrid CNN-BiLSTM and Knowledge Transfer
期刊 International Journal of Automotive Technology (2026)
DOI 10.1007/s12239-026-00538-3
关键词 CNN, BiLSTM, Knowledge Transfer, Electric Bus, Distracted Driving

核心创新

混合 CNN-BiLSTM + 知识迁移的电动公交车分心驾驶检测框架。

与乘用车DMS的差异

方面 乘用车DMS 电动公交车DMS
驾驶员距离 50-70cm 80-120cm
光照变化 中等 极端(日间强光/夜间)
驾驶姿势 相对固定 变化大(公交车操作)
振动 小 大(公交车底盘振动)
操作多样性 驾驶为主 驾驶+票务+广播+乘客交互
数据量 大 小(专用场景)

架构设计

核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
import torch
import torch.nn as nn
import torch.nn.functional as F
from transformers import ViTModel

class CNNBiLSTMDistractionDetector(nn.Module):
"""
CNN-BiLSTM 混合分心检测框架

架构:
1. CNN (MobileNetV3) 提取空间特征
2. BiLSTM 建模时序动态
3. 注意力机制聚焦关键帧
4. 知识迁移从乘用车预训练模型

适用场景:电动公交车驾驶员
"""

def __init__(self, n_classes=10, hidden_dim=256, n_layers=2,
pretrained=True):
super().__init__()
self.n_classes = n_classes
self.hidden_dim = hidden_dim

# 1. CNN特征提取 (MobileNetV3轻量化)
self.cnn = MobileNetV3Encoder(pretrained=pretrained)
feat_dim = self.cnn.output_dim # 576

# 2. 投影层(知识迁移适配)
self.proj = nn.Sequential(
nn.Linear(feat_dim, hidden_dim),
nn.LayerNorm(hidden_dim),
nn.GELU(),
nn.Dropout(0.1)
)

# 3. BiLSTM时序建模
self.bilstm = nn.LSTM(
input_size=hidden_dim,
hidden_size=hidden_dim,
num_layers=n_layers,
batch_first=True,
bidirectional=True,
dropout=0.2
)

# 4. 时序注意力
self.temporal_attention = nn.Sequential(
nn.Linear(hidden_dim * 2, hidden_dim),
nn.Tanh(),
nn.Linear(hidden_dim, 1)
)

# 5. 分类头
self.classifier = nn.Sequential(
nn.Linear(hidden_dim * 2, hidden_dim),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(hidden_dim, n_classes)
)

# 知识迁移权重
self.kd_alpha = nn.Parameter(torch.tensor(0.5))

def forward(self, x):
"""
Args:
x: (B, T, 3, H, W) 视频帧序列

Returns:
logits: (B, n_classes)
attention_weights: (B, T) 注意力权重
"""
B, T, C, H, W = x.shape

# 1. CNN逐帧提取
x = x.view(B * T, C, H, W)
cnn_feat = self.cnn(x) # (B*T, feat_dim)
cnn_feat = self.proj(cnn_feat) # (B*T, hidden_dim)
cnn_feat = cnn_feat.view(B, T, -1) # (B, T, hidden_dim)

# 2. BiLSTM时序建模
lstm_out, _ = self.bilstm(cnn_feat) # (B, T, 2*hidden_dim)

# 3. 时序注意力
attn_scores = self.temporal_attention(lstm_out) # (B, T, 1)
attn_weights = F.softmax(attn_scores, dim=1) # (B, T, 1)

# 加权求和
weighted = (lstm_out * attn_weights).sum(dim=1) # (B, 2*hidden_dim)

# 4. 分类
logits = self.classifier(weighted)

return logits, attn_weights.squeeze(-1)

def knowledge_distillation_loss(self, student_logits,
teacher_logits, labels,
temperature=4.0):
"""知识蒸馏损失"""
alpha = torch.sigmoid(self.kd_alpha)

# 硬标签损失
hard_loss = F.cross_entropy(student_logits, labels)

# 软标签损失 (KL散度)
soft_student = F.log_softmax(student_logits / temperature, dim=1)
soft_teacher = F.softmax(teacher_logits / temperature, dim=1)
soft_loss = F.kl_div(soft_student, soft_teacher,
reduction='batchmean') * (temperature ** 2)

# 总损失
total_loss = alpha * hard_loss + (1 - alpha) * soft_loss
return total_loss, {'hard': hard_loss.item(),
'soft': soft_loss.item(),
'alpha': alpha.item()}


class MobileNetV3Encoder(nn.Module):
"""轻量化CNN编码器"""

def __init__(self, pretrained=True):
super().__init__()
# 简化版MobileNetV3
self.features = nn.Sequential(
# Stem
nn.Conv2d(3, 16, 3, stride=2, padding=1),
nn.BatchNorm2d(16),
nn.Hardswish(),

# Blocks
self._make_block(16, 16, 3, 1),
self._make_block(16, 24, 3, 2),
self._make_block(24, 24, 3, 1),
self._make_block(24, 40, 5, 2),
self._make_block(40, 40, 5, 1),
self._make_block(40, 80, 3, 2),
self._make_block(80, 80, 3, 1),
self._make_block(80, 112, 3, 1),
self._make_block(112, 160, 5, 2),
self._make_block(160, 160, 5, 1),

# Final
nn.Conv2d(160, 576, 1),
nn.BatchNorm2d(576),
nn.Hardswish(),
nn.AdaptiveAvgPool2d(1),
)
self.output_dim = 576

def _make_block(self, in_ch, out_ch, kernel_size, stride):
return nn.Sequential(
nn.Conv2d(in_ch, out_ch, kernel_size, stride=stride,
padding=kernel_size//2, groups=in_ch),
nn.BatchNorm2d(out_ch),
nn.Hardswish(),
nn.Conv2d(out_ch, out_ch, 1),
nn.BatchNorm2d(out_ch),
nn.Hardswish(),
)

def forward(self, x):
return self.features(x).flatten(1)


# 分心行为类别(公交车特定)
BUS_DISTRACTION_CLASSES = {
0: 'safe_driving', # 安全驾驶
1: 'phone_call_right', # 右手打电话
2: 'phone_call_left', # 左手打电话
3: 'texting_right', # 右手发短信
4: 'texting_left', # 左手发短信
5: 'adjusting_radio', # 调收音机/广播
6: 'drinking', # 喝水
7: 'talking_passenger', # 与乘客交谈
8: 'operating_tickets', # 操作票务系统
9: 'reaching_back', # 向后取物
}

# 测试
if __name__ == "__main__":
B, T = 4, 16 # 4个样本, 16帧
model = CNNBiLSTMDistractionDetector(n_classes=10)

# 模拟视频输入
video = torch.randn(B, T, 3, 224, 224)

logits, attn = model(video)

print(f"输入视频: {video.shape}")
print(f"输出logits: {logits.shape}")
print(f"注意力权重: {attn.shape}")
print(f"参数量: {sum(p.numel() for p in model.parameters())/1e6:.2f}M")

# 模拟知识蒸馏
teacher_logits = torch.randn(B, 10)
labels = torch.randint(0, 10, (B,))
loss, info = model.knowledge_distillation_loss(logits, teacher_logits, labels)
print(f"\n知识蒸馏损失: {loss.item():.4f}")
print(f" 硬标签: {info['hard']:.4f}")
print(f" 软标签: {info['soft']:.4f}")
print(f" alpha: {info['alpha']:.4f}")

知识迁移方案

乘用车→公交车迁移

知识类型 共享部分 差异部分
面部特征 EAR/MAR/眨眼 驾驶员距离更远
手部位置 手机/饮水检测 操作对象不同
头部姿态 视线方向 振动基线不同
行为类别 打电话/发短信 票务/广播/乘客交互

迁移策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
KNOWLEDGE_TRANSFER_STRATEGY = {
'stage1': {
'action': '预训练',
'source': '乘用车DMS数据集 (如State Farm Distracted Driver)',
'target': 'CNN特征提取器',
'method': '标准分类训练',
},
'stage2': {
'action': '微调',
'source': '公交车标注数据 (少量, ~1000样本)',
'target': '全网络微调 + 知识蒸馏',
'method': '教师(乘用车) → 学生(公交车)',
},
'stage3': {
'action': '部署',
'source': '微调后模型',
'target': '边缘设备 (QCS8255)',
'method': 'INT8量化 + TensorRT',
}
}

性能对比

方法 准确率 F1 推理速度 参数量
纯CNN (ResNet50) 85.2% 84.1% 45fps 25.6M
CNN+LSTM 87.5% 86.8% 32fps 28.3M
CNN-BiLSTM+KD (本文) 90.8% 89.9% 28fps 12.2M
ViT-Base 89.1% 88.2% 15fps 86M

关键优势: 知识蒸馏使小模型(12.2M)性能接近大模型(86M),推理速度保持28fps。

公交车DMS特殊挑战

挑战 方案 效果
强光逆光 IR摄像头+RGB融合 提升15%
底盘振动 时序模型平滑+振动补偿 降低误报30%
距离远 高分辨率摄像头+crop 等效拉近
乘客干扰 注意力机制聚焦驾驶员 减少误检
数据少 知识迁移+数据增强 1000样本达标

Euro NCAP 关联

虽然公交车不直接受Euro NCAP约束,但对应法规体系:

  • 欧盟 Directive 2003/59/EC — 商用车驾驶员培训
  • UN Regulation 152 — 商用车AEB
  • 公交车DMS是主动安全新趋势

IMS 开发启示

  1. 知识迁移可大幅降低数据需求 — 1000样本+KD即可达到90%+准确率
  2. BiLSTM+注意力优于纯CNN — 时序信息对分心检测至关重要
  3. 小模型可替代大模型 — 12.2M参数,适合边缘部署
  4. 公交车DMS有独立需求 — 不能直接复用乘用车方案
  5. 振动补偿是新课题 — 乘用车没有这个问题

参考链接: