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 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
| import numpy as np import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report from typing import Dict, List
class CognitiveDeclineDetector: """ 车载传感器认知衰退检测器 论文1: Multimedia Tools Appl., 2024 - 传感器数据分析 论文2: arXiv:2507.05463 - 大视觉模型+场景识别 核心指标: 驾驶行为数字指纹 """ COGNITIVE_INDICATORS = { 'speed_variability': '速度变异性(认知负荷下不稳定)', 'lane_departures': '车道偏离频率(注意力下降)', 'braking_patterns': '制动模式异常(判断力下降)', 'steering_corrections': '方向盘纠偏频率(运动控制衰退)', 'intersection_stops': '交叉口停车行为(过度谨慎/犹豫)', 'route_errors': '路线错误次数(空间记忆衰退)', 'navigation_hesitation': '导航犹豫时间(决策能力下降)', 'wrong_turns': '错误转弯频率(方向感丧失)', 'gaze_distribution': '注视分布熵(视觉搜索策略退化)', 'mirror_check_freq': '后视镜检查频率(情境意识下降)', 'fixation_duration': '注视时长变化(处理速度变慢)', 'saccade_patterns': '眼跳模式异常(执行功能衰退)', 'hazard_response_time': '危险响应时间(反应速度)', 'traffic_sign_recognition': '交通标志识别延迟', 'following_distance': '跟车距离变化(判断力)', } def __init__(self): self.model = RandomForestClassifier( n_estimators=200, max_depth=15, min_samples_leaf=5, random_state=42 ) self.feature_columns = list(self.COGNITIVE_INDICATORS.keys()) def extract_driving_features(self, driving_session: pd.DataFrame) -> Dict[str, float]: """ 从驾驶会话数据中提取认知指标 Args: driving_session: 包含以下列的DataFrame: - timestamp, speed, lat, lon, heading - lane_position, steering_angle, brake_pressure - gaze_x, gaze_y, gaze_z - scenario_type (intersection/highway/residential) Returns: features: 认知指标字典 """ features = {} features['speed_variability'] = np.std(driving_session['speed']) lane_departs = np.sum(np.abs(driving_session['lane_position']) > 0.3) distance_km = self._calculate_distance(driving_session) / 1000 features['lane_departures'] = lane_departs / max(distance_km, 0.1) brake_events = driving_session[driving_session['brake_pressure'] > 0.1] features['braking_patterns'] = np.std(brake_events['brake_pressure']) if len(brake_events) > 0 else 0 steering_changes = np.sum(np.abs(np.diff(driving_session['steering_angle'])) > 5) features['steering_corrections'] = steering_changes / max(distance_km, 0.1) intersection_data = driving_session[driving_session['scenario_type'] == 'intersection'] if len(intersection_data) > 0: stops = intersection_data[intersection_data['speed'] < 1.0] features['intersection_stops'] = len(stops) else: features['intersection_stops'] = 0 gaze = driving_session[['gaze_x', 'gaze_y']].dropna() if len(gaze) > 10: hist, _ = np.histogram2d(gaze['gaze_x'], gaze['gaze_y'], bins=10) hist = hist / hist.sum() features['gaze_distribution'] = -np.sum(hist * np.log(hist + 1e-10)) else: features['gaze_distribution'] = 0 mirror_checks = np.sum( (driving_session['gaze_x'] > 0.7) & (driving_session['gaze_y'] < -0.2) ) features['mirror_check_freq'] = mirror_checks / max(distance_km, 0.1) fixation_durations = self._calculate_fixations(gaze) features['fixation_duration'] = np.mean(fixation_durations) if fixation_durations else 0 return features def classify_cognitive_status(self, features: Dict[str, float]) -> dict: """ 分类认知状态 Returns: { 'status': 'normal' | 'MCI_suspected' | 'dementia_risk', 'confidence': float, 'key_indicators': [...], 'recommendation': str } """ feature_vector = np.array([features.get(f, 0) for f in self.feature_columns]) prediction = self.model.predict(feature_vector.reshape(1, -1))[0] proba = self.model.predict_proba(feature_vector.reshape(1, -1))[0] key_indicators = [] for name, value in features.items(): threshold = self._get_abnormal_threshold(name) if value > threshold: key_indicators.append(f"{name}={value:.2f} (阈值={threshold})") status_map = {0: 'normal', 1: 'MCI_suspected', 2: 'dementia_risk'} status = status_map.get(prediction, 'unknown') recommendations = { 'normal': '继续定期检查', 'MCI_suspected': '建议进行MoCA评估', 'dementia_risk': '建议立即神经科就诊' } return { 'status': status, 'confidence': float(np.max(proba)), 'key_indicators': key_indicators, 'recommendation': recommendations.get(status, '未知') } def _calculate_distance(self, df: pd.DataFrame) -> float: """计算行驶距离(米)""" lat = np.radians(df['lat'].values) lon = np.radians(df['lon'].values) dlat = np.diff(lat) dlon = np.diff(lon) a = np.sin(dlat/2)**2 + np.cos(lat[:-1]) * np.cos(lat[1:]) * np.sin(dlon/2)**2 return np.sum(6371000 * 2 * np.arctan2(np.sqrt(a), np.sqrt(1-a))) def _calculate_fixations(self, gaze: pd.DataFrame) -> List[float]: """计算注视持续时间""" if len(gaze) < 2: return [] velocities = np.sqrt(np.diff(gaze['gaze_x'])**2 + np.diff(gaze['gaze_y'])**2) fixation_mask = velocities < 0.05 durations = [] current = 0 for m in fixation_mask: if m: current += 1 else: if current > 0: durations.append(current * 0.033) current = 0 return durations def _get_abnormal_threshold(self, indicator: str) -> float: """获取指标异常阈值""" thresholds = { 'speed_variability': 5.0, 'lane_departures': 2.0, 'braking_patterns': 0.3, 'steering_corrections': 10.0, 'intersection_stops': 5, 'gaze_distribution': 3.0, 'mirror_check_freq': 3.0, } return thresholds.get(indicator, float('inf'))
if __name__ == "__main__": detector = CognitiveDeclineDetector() np.random.seed(42) n_points = 1800 normal_data = pd.DataFrame({ 'timestamp': np.arange(n_points) * 0.033, 'speed': 50 + np.random.normal(0, 2, n_points), 'lat': 26.3643 + np.cumsum(np.random.normal(0, 0.00001, n_points)), 'lon': -80.1025 + np.cumsum(np.random.normal(0, 0.00001, n_points)), 'heading': np.cumsum(np.random.normal(0, 0.5, n_points)), 'lane_position': np.random.normal(0, 0.1, n_points), 'steering_angle': np.random.normal(0, 2, n_points), 'brake_pressure': np.random.choice([0, 0, 0, 0.1], n_points), 'gaze_x': np.random.normal(0, 0.3, n_points), 'gaze_y': np.random.normal(0, 0.2, n_points), 'gaze_z': np.random.normal(1, 0.1, n_points), 'scenario_type': np.random.choice(['highway', 'residential', 'intersection'], n_points), }) features = detector.extract_driving_features(normal_data) print("=== 正常老年驾驶员特征 ===") for k, v in features.items(): print(f" {k}: {v:.3f}") mci_data = normal_data.copy() mci_data['speed'] = 50 + np.random.normal(0, 5, n_points) mci_data['lane_position'] = np.random.normal(0, 0.25, n_points) mci_data['steering_angle'] = np.random.normal(0, 4, n_points) mci_features = detector.extract_driving_features(mci_data) print("\n=== MCI驾驶员特征 ===") for k, v in mci_features.items(): print(f" {k}: {v:.3f}") print("\n=== 对比分析 ===") print("MCI vs 正常差异:") for k in features: diff = mci_features[k] - features[k] if abs(diff) > 0.01: print(f" {k}: +{diff:.3f} ({'↑' if diff > 0 else '↓'}异常)")
|