当前位置: 首页 > news >正文

多模型协同预测在风机故障预测的应用(demo)


  1. 数据加载和预处理的真实性

    • 下面的代码中,DummyDataset 和数据加载部分仍然是高度简化和占位的。为了让这个训练循环真正有效,您必须用您自己的数据加载逻辑替换它。
    • 这意味着您需要创建一个 torch.utils.data.Dataset 的子类,它能够正确地从您的数据源(例如CSV文件、数据库、文件夹中的原始信号文件)加载每个样本的多种传感器数据。
    • __getitem__ 方法中,您需要调用 DataProcessor 的相应 process_... 方法来提取特征,然后进行归一化(如果需要模型直接处理归一化后的特征,而不是在predict中才做),并将所有数据转换成模型期望的张量格式和形状。
    • fit_scalers 的调用时机DataProcessor 中的 fit_scalers 方法必须在创建 DataLoader 并开始训练之前,使用整个训练集提取出的特征进行调用。这一步至关重要。
  2. 特征准备的复杂性

    • 在批处理训练中,为每个模型(CNN, LSTM, Electrical)准备输入可能很复杂,特别是 LSTM 需要特征序列。您可能需要在 Dataset__getitem__ 中就准备好这些序列,或者设计一个高效的批处理函数。
    • 规则引擎在验证批次中的使用也需要仔细考虑,因为它通常处理单个样本的特征。
  3. 模型和融合权重的调优

    • 此代码提供了一个结构。要获得高准确率,您仍然需要对各个模型的超参数、model_weights(融合权重)进行仔细的实验和调优。
  4. 计算资源

    • 训练深度学习模型(尤其是多个模型)可能需要大量的计算资源(GPU)和时间。
import numpy as np
import torch
import torch.nn as nn
from scipy import signal as sig
from scipy.stats import kurtosis, skew
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
import pickle
from typing import Dict, List, Tuple, Optional, Any
import os # 用于创建目录# --- 配置常量 (根据需要调整) ---
VIBRATION_RAW_SEQ_LEN = 1024
VIBRATION_SAMPLING_RATE = 10000
PRESSURE_SAMPLING_RATE = 100
LSTM_FEATURE_SIZE = 10 # 温度(5) + 压力(4) + 电流单特征(1)
LSTM_SEQ_LEN = 5 # LSTM输入特征的示例序列长度
ELECTRICAL_FEATURE_SIZE = 2
NUM_FAULT_CLASSES = 10# 创建模型和结果保存目录
MODEL_SAVE_DIR = "saved_models"
SCALER_SAVE_PATH = os.path.join(MODEL_SAVE_DIR, "fitted_scalers.pkl")
BEST_CNN_PATH = os.path.join(MODEL_SAVE_DIR, "best_cnn.pth")
BEST_LSTM_PATH = os.path.join(MODEL_SAVE_DIR, "best_lstm.pth")
BEST_ELECTRICAL_PATH = os.path.join(MODEL_SAVE_DIR, "best_electrical.pth")if not os.path.exists(MODEL_SAVE_DIR):os.makedirs(MODEL_SAVE_DIR)class DataProcessor:"""全故障覆盖的数据处理模块"""def __init__(self):self.scalers = {'vibration_features': StandardScaler(),'temperature': StandardScaler(),'pressure': StandardScaler(),'blade_angle': StandardScaler(),'oil_particles': StandardScaler(),'current': StandardScaler()}self.fitted_scalers = {}self.fault_types = {0: "正常", 1: "叶轮不平衡", 2: "轴承失效", 3: "动叶卡涩",4: "喘振", 5: "积灰堵塞", 6: "电机绕组故障", 7: "传感器失效",8: "基础松动", 9: "密封失效"}assert len(self.fault_types) == NUM_FAULT_CLASSES, "NUM_FAULT_CLASSES 和 fault_types 长度不匹配"def fit_scalers(self, training_features_dict: Dict[str, List[np.ndarray]]):print("正在拟合缩放器...")for feature_type, features_list in training_features_dict.items():if feature_type in self.scalers and features_list:all_features_for_type = np.array(features_list)if all_features_for_type.ndim == 1:all_features_for_type = all_features_for_type.reshape(-1, 1)if all_features_for_type.shape[0] == 0:print(f"警告:未提供用于拟合 {feature_type} 缩放器的数据。")continuetry:self.scalers[feature_type].fit(all_features_for_type)self.fitted_scalers[feature_type] = Trueprint(f"{feature_type} 的缩放器已拟合,数据形状: {all_features_for_type.shape}")except Exception as e:print(f"拟合 {feature_type} 缩放器时出错 (形状 {all_features_for_type.shape}): {e}")elif feature_type not in self.scalers:print(f"未为特征类型定义缩放器: {feature_type}")def save_scalers(self, path=SCALER_SAVE_PATH):with open(path, 'wb') as f:pickle.dump(self.scalers, f)print(f"已拟合的缩放器保存至 {path}")def load_scalers(self, path=SCALER_SAVE_PATH):try:with open(path, 'rb') as f:self.scalers = pickle.load(f)for key in self.scalers.keys():self.fitted_scalers[key] = Trueprint(f"缩放器从 {path} 加载成功")except FileNotFoundError:print(f"缩放器文件 {path} 未找到。如果不是在训练阶段,则初始化新的缩放器。")except Exception as e:print(f"加载缩放器错误: {e}。如果不是在训练阶段,则初始化新的缩放器。")self.__init__()def process_vibration(self, vibration_signal: np.ndarray, sampling_rate: int = VIBRATION_SAMPLING_RATE) -> np.ndarray:if not isinstance(vibration_signal, np.ndarray) or vibration_signal.ndim != 1:raise ValueError("振动信号必须是一维numpy数组。")if len(vibration_signal) < 2:return np.zeros(8)rms = np.sqrt(np.mean(vibration_signal**2))peak = np.max(np.abs(vibration_signal))kurtosis_val = kurtosis(vibration_signal)skewness_val = skew(vibration_signal)nperseg_val = min(len(vibration_signal), 1024)if nperseg_val == 0:f, psd = np.array([]), np.array([])else:f, psd = sig.welch(vibration_signal, sampling_rate, nperseg=nperseg_val)def get_freq_component(freq_target):if f.size > 0 and psd.size > 0:idx = np.argmin(np.abs(f - freq_target))if np.min(np.abs(f - freq_target)) < ( (f[1]-f[0]) if len(f)>1 else sampling_rate/2 ):return psd[idx]return 0.0freq_1x = get_freq_component(50)freq_2x = get_freq_component(100)freq_3x = get_freq_component(150)low_freq_energy = 0.0if psd.size > 0 and np.sum(psd) > 0:relevant_psd = psd[(f >= 5) & (f <= 50)]if relevant_psd.size > 0:low_freq_energy = np.sum(relevant_psd) / np.sum(psd)return np.array([rms, peak, kurtosis_val, skewness_val, freq_1x, freq_2x, freq_3x, low_freq_energy])def process_temperature(self, temp_series: np.ndarray) -> np.ndarray:if not isinstance(temp_series, np.ndarray) or temp_series.ndim != 1 or len(temp_series) == 0:return np.zeros(5)current_temp = temp_series[-1]avg_temp = np.mean(temp_series)max_temp = np.max(temp_series)temp_rate = np.diff(temp_series).mean() if len(temp_series) > 1 else 0.0stator_temp = temp_series[1] if len(temp_series) > 1 else temp_series[0]return np.array([current_temp, avg_temp, max_temp, temp_rate, stator_temp])def process_pressure(self, pressure_series: np.ndarray, fs: int = PRESSURE_SAMPLING_RATE) -> np.ndarray:if not isinstance(pressure_series, np.ndarray) or pressure_series.ndim != 1 or len(pressure_series) == 0:return np.zeros(4)mean_pressure = np.mean(pressure_series)std_pressure = np.std(pressure_series)max_fluctuation = np.max(np.abs(np.diff(pressure_series))) if len(pressure_series) > 1 else 0.0low_freq_energy = self._calculate_low_freq_energy(pressure_series, fs, 0.5, 2.0)return np.array([mean_pressure, std_pressure, max_fluctuation, low_freq_energy])def process_blade_angle(self, angle_series: np.ndarray, target_angle: float) -> np.ndarray:if not isinstance(angle_series, np.ndarray) or angle_series.ndim != 1 or len(angle_series) == 0:return np.zeros(5)current_angle = angle_series[-1]angle_deviation = np.abs(current_angle - target_angle)angle_rate = np.abs(np.diff(angle_series)).mean() if len(angle_series) > 1 else 0.0stuck_points = np.sum(np.abs(np.diff(angle_series)) < 0.5) / len(angle_series) if len(angle_series) > 1 else 0.0return np.array([current_angle, target_angle, angle_deviation, angle_rate, stuck_points])def process_oil_analysis(self, particles: float, viscosity: float) -> np.ndarray:return np.array([particles, viscosity])def process_current(self, current_series: np.ndarray) -> np.ndarray:if not isinstance(current_series, np.ndarray) or len(current_series) == 0:return np.zeros(2)mean_curr = np.mean(current_series)if mean_curr == 0: return np.array([0.0, 0.0])if current_series.ndim == 1:harmonic_ratio = np.std(current_series) / mean_curr if mean_curr != 0 else 0unbalance_metric = np.max(np.abs(current_series - mean_curr)) / mean_curr if mean_curr != 0 else 0elif current_series.ndim == 0 and len(current_series.shape) == 1 and len(current_series) == 3:harmonic_ratio = 0unbalance_metric = (np.max(current_series) - np.min(current_series)) / mean_curr if mean_curr != 0 else 0else:harmonic_ratio = np.std(current_series.flatten()) / np.mean(current_series.flatten()) if np.mean(current_series.flatten()) !=0 else 0unbalance_metric = 0return np.array([harmonic_ratio, unbalance_metric])def _calculate_low_freq_energy(self, input_signal: np.ndarray, fs: float, f_low: float, f_high: float) -> float:if not isinstance(input_signal, np.ndarray) or len(input_signal) == 0: return 0.0nperseg_val = min(len(input_signal), 128)if nperseg_val < 2 : return 0.0f, psd = sig.welch(input_signal, fs=fs, nperseg=nperseg_val)if psd.size == 0 or np.sum(psd) == 0: return 0.0relevant_psd = psd[(f >= f_low) & (f <= f_high)]if relevant_psd.size == 0 : return 0.0return np.sum(relevant_psd) / np.sum(psd)def normalize_features(self, features: np.ndarray, feature_type: str) -> np.ndarray:if feature_type in self.scalers:if not self.fitted_scalers.get(feature_type):if "predicting_now" in globals() and globals()["predicting_now"]:raise RuntimeError(f"{feature_type} 的缩放器必须在预测前拟合。")return featuresif features.ndim == 1:features_reshaped = features.reshape(1, -1)elif features.ndim == 2 and features.shape[0] == 1:features_reshaped = featureselse:raise ValueError(f"{feature_type} 的特征形状对于缩放不符合预期: {features.shape}")return self.scalers[feature_type].transform(features_reshaped).flatten()return featuresclass CNNModel(nn.Module):def __init__(self, input_channels: int = 1, num_classes: int = NUM_FAULT_CLASSES, example_input_len: int = VIBRATION_RAW_SEQ_LEN):super(CNNModel, self).__init__()self.conv_layers = nn.Sequential(nn.Conv1d(input_channels, 32, kernel_size=7, stride=1, padding=3), nn.ReLU(),nn.MaxPool1d(kernel_size=2, stride=2),nn.Conv1d(32, 64, kernel_size=5, stride=1, padding=2), nn.ReLU(),nn.MaxPool1d(kernel_size=2, stride=2),nn.Conv1d(64, 128, kernel_size=3, stride=1, padding=1), nn.ReLU(),nn.MaxPool1d(kernel_size=2, stride=2))dummy_input = torch.randn(1, input_channels, example_input_len)with torch.no_grad():conv_output_size = self.conv_layers(dummy_input).view(1, -1).size(1)self.fc = nn.Sequential(nn.Linear(conv_output_size, 256), nn.ReLU(),nn.Dropout(0.5),nn.Linear(256, num_classes))def forward(self, x):x = self.conv_layers(x)x = x.view(x.size(0), -1)return self.fc(x)class LSTMModel(nn.Module):def __init__(self, input_size: int = LSTM_FEATURE_SIZE, hidden_size: int = 128, num_classes: int = NUM_FAULT_CLASSES):super(LSTMModel, self).__init__()self.lstm = nn.LSTM(input_size, hidden_size, num_layers=2, batch_first=True, dropout=0.3, bidirectional=True)self.fc = nn.Sequential(nn.Linear(hidden_size * 2, 256), nn.ReLU(),nn.Dropout(0.5),nn.Linear(256, num_classes))def forward(self, x):lstm_out, _ = self.lstm(x)x = lstm_out[:, -1, :]return self.fc(x)class DSEvidenceFusion:def __init__(self, num_classes: int = NUM_FAULT_CLASSES):self.num_classes = num_classesdef combine_evidence(self, evidences: List[np.ndarray], weights: Optional[List[float]] = None) -> np.ndarray:if not evidences:return np.ones(self.num_classes) / self.num_classesif weights is None:weights = [1.0 / len(evidences)] * len(evidences)else:if len(weights) != len(evidences):raise ValueError("权重数量必须与证据数量匹配。")weights = np.array(weights) / np.sum(weights)processed_evidences = []for e in evidences:if not isinstance(e, np.ndarray): e = np.array(e)if e.shape != (self.num_classes,):raise ValueError(f"证据形状不匹配。期望 ({self.num_classes},),得到 {e.shape}")processed_evidences.append(e)combined_belief = np.zeros(self.num_classes)for i, evidence in enumerate(processed_evidences):combined_belief += weights[i] * evidencereturn combined_beliefclass FaultDiagnosisSystem:def __init__(self, cnn_input_len=VIBRATION_RAW_SEQ_LEN, lstm_feat_size=LSTM_FEATURE_SIZE, electrical_feat_size=ELECTRICAL_FEATURE_SIZE):self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")self.data_processor = DataProcessor()self.num_classes = len(self.data_processor.fault_types)self.cnn_model = CNNModel(num_classes=self.num_classes, example_input_len=cnn_input_len).to(self.device)self.lstm_model = LSTMModel(input_size=lstm_feat_size, num_classes=self.num_classes).to(self.device)self.electrical_model = nn.Sequential(nn.Linear(electrical_feat_size, 32), nn.ReLU(),nn.Linear(32, self.num_classes),).to(self.device)self.fusion = DSEvidenceFusion(num_classes=self.num_classes)self.model_weights = [0.4, 0.3, 0.2, 0.1]self.design_pressure_default = 100.0def load_models(self, cnn_path=BEST_CNN_PATH, lstm_path=BEST_LSTM_PATH, electrical_path=BEST_ELECTRICAL_PATH, scalers_path=SCALER_SAVE_PATH):try:self.cnn_model.load_state_dict(torch.load(cnn_path, map_location=self.device))self.lstm_model.load_state_dict(torch.load(lstm_path, map_location=self.device))self.electrical_model.load_state_dict(torch.load(electrical_path, map_location=self.device))print("神经网络模型加载成功。")except Exception as e:print(f"加载神经网络模型时出错: {e}。请确保路径正确且模型匹配。")raiseself.cnn_model.eval()self.lstm_model.eval()self.electrical_model.eval()if scalers_path:self.data_processor.load_scalers(scalers_path)else:print("警告:未提供缩放器路径。除非单独拟合/加载缩放器,否则特征不会被归一化。")def save_models(self, cnn_path=BEST_CNN_PATH, lstm_path=BEST_LSTM_PATH, electrical_path=BEST_ELECTRICAL_PATH, scalers_path=SCALER_SAVE_PATH):torch.save(self.cnn_model.state_dict(), cnn_path)torch.save(self.lstm_model.state_dict(), lstm_path)torch.save(self.electrical_model.state_dict(), electrical_path)print(f"神经网络模型已保存至 {cnn_path}, {lstm_path}, {electrical_path}")if scalers_path:self.data_processor.save_scalers(scalers_path)def _rule_engine_predict(self, **kwargs) -> np.ndarray:fault_probs = np.zeros(self.num_classes)fault_probs[0] = 0.1v_feats = kwargs.get('vibration_features', np.zeros(8))t_feats = kwargs.get('temperature_features', np.zeros(5))p_feats = kwargs.get('pressure_features', np.zeros(4))b_feats = kwargs.get('blade_angle_features', np.zeros(5))o_feats = kwargs.get('oil_features', np.zeros(2))c_feats = kwargs.get('current_features', np.zeros(2))design_pressure = kwargs.get('design_pressure', self.design_pressure_default)if v_feats[2] > 5: fault_probs[self.data_processor.fault_types_str_to_int("轴承失效")] = max(fault_probs[self.data_processor.fault_types_str_to_int("轴承失效")], 0.7)if v_feats[7] > 0.1: fault_probs[self.data_processor.fault_types_str_to_int("基础松动")] = max(fault_probs[self.data_processor.fault_types_str_to_int("基础松动")], 0.6)if t_feats[0] > 85: fault_probs[self.data_processor.fault_types_str_to_int("轴承失效")] = max(fault_probs[self.data_processor.fault_types_str_to_int("轴承失效")], 0.7)if b_feats[2] > 5: fault_probs[self.data_processor.fault_types_str_to_int("动叶卡涩")] = max(fault_probs[self.data_processor.fault_types_str_to_int("动叶卡涩")], 0.8)if p_feats[3] > 0.2: fault_probs[self.data_processor.fault_types_str_to_int("喘振")] = max(fault_probs[self.data_processor.fault_types_str_to_int("喘振")], 0.7)if p_feats[0] > 1.1 * design_pressure : fault_probs[self.data_processor.fault_types_str_to_int("积灰堵塞")] = max(fault_probs[self.data_processor.fault_types_str_to_int("积灰堵塞")], 0.6)if c_feats[0] > 0.1: fault_probs[self.data_processor.fault_types_str_to_int("电机绕组故障")] = max(fault_probs[self.data_processor.fault_types_str_to_int("电机绕组故障")], 0.7)if c_feats[1] > 0.1: fault_probs[self.data_processor.fault_types_str_to_int("电机绕组故障")] = max(fault_probs[self.data_processor.fault_types_str_to_int("电机绕组故障")], 0.6)if o_feats[0] > 50:fault_probs[self.data_processor.fault_types_str_to_int("轴承失效")] = max(fault_probs[self.data_processor.fault_types_str_to_int("轴承失效")], 0.5)fault_probs[self.data_processor.fault_types_str_to_int("密封失效")] = max(fault_probs[self.data_processor.fault_types_str_to_int("密封失效")], 0.4)if o_feats[1] < 70:fault_probs[self.data_processor.fault_types_str_to_int("轴承失效")] = max(fault_probs[self.data_processor.fault_types_str_to_int("轴承失效")], 0.4)fault_probs[self.data_processor.fault_types_str_to_int("密封失效")] = max(fault_probs[self.data_processor.fault_types_str_to_int("密封失效")], 0.3)return self._normalize_prob(fault_probs)def _normalize_prob(self, probs: np.ndarray) -> np.ndarray:if np.sum(probs) == 0:norm_probs = np.ones_like(probs) / len(probs)return norm_probsreturn probs / np.sum(probs)def predict(self, vibration_raw: np.ndarray, temperature_series: np.ndarray, pressure_series: np.ndarray, blade_angle_series: np.ndarray, oil_particles_val: float, oil_viscosity_val: float, current_signal: np.ndarray,target_blade_angle: float, design_pressure: float,vibration_sampling_rate: int = VIBRATION_SAMPLING_RATE,pressure_sampling_rate: int = PRESSURE_SAMPLING_RATE) -> Dict[str, float]:global predicting_nowpredicting_now = Truevibration_features = self.data_processor.process_vibration(vibration_raw, vibration_sampling_rate)temperature_features = self.data_processor.process_temperature(temperature_series)pressure_features = self.data_processor.process_pressure(pressure_series, pressure_sampling_rate)blade_angle_features = self.data_processor.process_blade_angle(blade_angle_series, target_blade_angle)oil_features = self.data_processor.process_oil_analysis(oil_particles_val, oil_viscosity_val)current_features = self.data_processor.process_current(current_signal)norm_vibration_f = self.data_processor.normalize_features(vibration_features, 'vibration_features')norm_temperature_f = self.data_processor.normalize_features(temperature_features, 'temperature')norm_pressure_f = self.data_processor.normalize_features(pressure_features, 'pressure')norm_blade_angle_f = self.data_processor.normalize_features(blade_angle_features, 'blade_angle')norm_oil_f = self.data_processor.normalize_features(oil_features, 'oil_particles')norm_current_f = self.data_processor.normalize_features(current_features, 'current')if len(vibration_raw) < VIBRATION_RAW_SEQ_LEN:vibration_padded = np.pad(vibration_raw, (0, VIBRATION_RAW_SEQ_LEN - len(vibration_raw)), 'constant')else:vibration_padded = vibration_raw[:VIBRATION_RAW_SEQ_LEN]cnn_input = torch.tensor(vibration_padded.reshape(1, 1, -1), dtype=torch.float32).to(self.device)lstm_input_feats_combined = np.concatenate([norm_temperature_f, norm_pressure_f, norm_current_f[:1]])if lstm_input_feats_combined.shape[0] != LSTM_FEATURE_SIZE:raise ValueError(f"LSTM 输入特征大小不匹配。期望 {LSTM_FEATURE_SIZE}, 得到 {lstm_input_feats_combined.shape[0]}")lstm_input = torch.tensor(lstm_input_feats_combined.reshape(1, 1, -1), dtype=torch.float32).to(self.device)if norm_current_f.shape[0] != ELECTRICAL_FEATURE_SIZE:raise ValueError(f"电气模型输入特征大小不匹配。期望 {ELECTRICAL_FEATURE_SIZE}, 得到 {norm_current_f.shape[0]}")electrical_input = torch.tensor(norm_current_f.reshape(1, -1), dtype=torch.float32).to(self.device)with torch.no_grad():cnn_logits = self.cnn_model(cnn_input)cnn_output_probs = torch.softmax(cnn_logits, dim=1).cpu().numpy()[0]lstm_logits = self.lstm_model(lstm_input)lstm_output_probs = torch.softmax(lstm_logits, dim=1).cpu().numpy()[0]electrical_logits = self.electrical_model(electrical_input)electrical_output_probs = torch.softmax(electrical_logits, dim=1).cpu().numpy()[0]rule_output_probs = self._rule_engine_predict(vibration_features=norm_vibration_f,temperature_features=norm_temperature_f,pressure_features=norm_pressure_f,blade_angle_features=norm_blade_angle_f,oil_features=norm_oil_f,current_features=norm_current_f,design_pressure=design_pressure)evidences = [cnn_output_probs, lstm_output_probs, electrical_output_probs, rule_output_probs]fused_probs = self.fusion.combine_evidence(evidences, self.model_weights)predicting_now = Falsereturn {self.data_processor.fault_types[i]: float(fused_probs[i]) for i in range(len(fused_probs))}def train(self, train_loader, val_loader, epochs=10, lr=0.001):if not all(self.data_processor.fitted_scalers.get(s_type) for s_type in self.data_processor.scalers):print("警告:并非所有缩放器都已标记为已拟合。请确保在有代表性的训练数据上调用了 fit_scalers。")# raise RuntimeError("必须在训练前拟合所有数据缩放器。") # 可以选择更严格地在此处报错cnn_optimizer = torch.optim.Adam(self.cnn_model.parameters(), lr=lr)lstm_optimizer = torch.optim.Adam(self.lstm_model.parameters(), lr=lr)electrical_optimizer = torch.optim.Adam(self.electrical_model.parameters(), lr=lr)criterion = nn.CrossEntropyLoss()best_val_accuracy = 0.0for epoch in range(epochs):self.cnn_model.train()self.lstm_model.train()self.electrical_model.train()total_train_loss_cnn, total_train_loss_lstm, total_train_loss_elec = 0, 0, 0for batch_idx, batch_content in enumerate(train_loader):# 解包批次内容,假设 batch_content 是 (data_dict, labels_tensor)# data_dict 包含模型所需的各种输入数据# 例如: data_dict['vibration_raw'], data_dict['lstm_input_feature_sequence'], data_dict['electrical_features']# labels_tensor 是对应的故障类别标签# 确保所有张量都被移到正确的设备上 (self.device)# **您必须在此处实现从 train_loader 的 batch_content 中提取和准备数据到模型输入的逻辑**# 以下是概念性的数据准备,您需要用真实逻辑替换# -------------------------------------------------------------------if not isinstance(batch_content, (tuple, list)) or len(batch_content) != 2:print(f"警告: train_loader 的批次内容格式不符合预期。跳过批次 {batch_idx}。")continuedata_dict, labels_batch_cpu = batch_contentif not isinstance(data_dict, dict) or not isinstance(labels_batch_cpu, torch.Tensor):print(f"警告: train_loader 的 data_dict 或 labels 格式不符合预期。跳过批次 {batch_idx}。")continuelabels_batch = labels_batch_cpu.to(self.device)# CNN 输入准备 (假设 'vibration_raw' 在 data_dict 中)if 'vibration_raw' not in data_dict:print(f"警告: 批次 {batch_idx} 中缺少 'vibration_raw'。跳过CNN训练。")else:cnn_input_batch = data_dict['vibration_raw'].unsqueeze(1).to(self.device) # 添加通道维度cnn_optimizer.zero_grad()cnn_logits = self.cnn_model(cnn_input_batch)loss_cnn = criterion(cnn_logits, labels_batch)loss_cnn.backward()cnn_optimizer.step()total_train_loss_cnn += loss_cnn.item()# LSTM 输入准备 (假设 'lstm_input_feature_sequence' 在 data_dict 中)if 'lstm_input_feature_sequence' not in data_dict:print(f"警告: 批次 {batch_idx} 中缺少 'lstm_input_feature_sequence'。跳过LSTM训练。")else:lstm_input_batch = data_dict['lstm_input_feature_sequence'].to(self.device)lstm_optimizer.zero_grad()lstm_logits = self.lstm_model(lstm_input_batch)loss_lstm = criterion(lstm_logits, labels_batch)loss_lstm.backward()lstm_optimizer.step()total_train_loss_lstm += loss_lstm.item()# Electrical Model 输入准备 (假设 'electrical_features' 在 data_dict 中)if 'electrical_features' not in data_dict:print(f"警告: 批次 {batch_idx} 中缺少 'electrical_features'。跳过Electrical模型训练。")else:electrical_input_batch = data_dict['electrical_features'].to(self.device)electrical_optimizer.zero_grad()electrical_logits = self.electrical_model(electrical_input_batch)loss_electrical = criterion(electrical_logits, labels_batch)loss_electrical.backward()electrical_optimizer.step()total_train_loss_elec += loss_electrical.item()# -------------------------------------------------------------------if batch_idx > 0 and batch_idx % 50 == 0:print(f"Epoch {epoch+1}, Batch {batch_idx}/{len(train_loader)} | "f"CNN Loss: {total_train_loss_cnn/batch_idx:.4f} | "f"LSTM Loss: {total_train_loss_lstm/batch_idx:.4f} | "f"Elec Loss: {total_train_loss_elec/batch_idx:.4f}")avg_loss_cnn = total_train_loss_cnn / len(train_loader) if len(train_loader) > 0 else 0avg_loss_lstm = total_train_loss_lstm / len(train_loader) if len(train_loader) > 0 else 0avg_loss_elec = total_train_loss_elec / len(train_loader) if len(train_loader) > 0 else 0print(f"Epoch {epoch+1}/{epochs} Training Complete. Avg Losses: CNN={avg_loss_cnn:.4f}, LSTM={avg_loss_lstm:.4f}, Elec={avg_loss_elec:.4f}")# --- 验证阶段 ---self.cnn_model.eval()self.lstm_model.eval()self.electrical_model.eval()all_val_preds_fused_indices = []all_val_labels_list = []with torch.no_grad():for batch_val_content in val_loader:# **您必须在此处实现从 val_loader 的 batch_val_content 中提取和准备数据到模型输入的逻辑**# 同时,为规则引擎准备特征(这可能需要对批次中的每个样本单独处理)# -------------------------------------------------------------------if not isinstance(batch_val_content, (tuple, list)) or len(batch_val_content) != 2:print(f"警告: val_loader 的批次内容格式不符合预期。跳过验证批次。")continuedata_dict_val, labels_batch_val_cpu = batch_val_contentif not isinstance(data_dict_val, dict) or not isinstance(labels_batch_val_cpu, torch.Tensor):print(f"警告: val_loader 的 data_dict 或 labels 格式不符合预期。跳过验证批次。")continuelabels_batch_val = labels_batch_val_cpu.to(self.device)batch_size_val = labels_batch_val.size(0)# 获取神经网络模型概率cnn_probs_b = torch.zeros((batch_size_val, self.num_classes), device=self.device)if 'vibration_raw' in data_dict_val:cnn_input_val_batch = data_dict_val['vibration_raw'].unsqueeze(1).to(self.device)cnn_probs_b = torch.softmax(self.cnn_model(cnn_input_val_batch), dim=1)else: print("验证中缺少 'vibration_raw'")lstm_probs_b = torch.zeros((batch_size_val, self.num_classes), device=self.device)if 'lstm_input_feature_sequence' in data_dict_val:lstm_input_val_batch = data_dict_val['lstm_input_feature_sequence'].to(self.device)lstm_probs_b = torch.softmax(self.lstm_model(lstm_input_val_batch), dim=1)else: print("验证中缺少 'lstm_input_feature_sequence'")electrical_probs_b = torch.zeros((batch_size_val, self.num_classes), device=self.device)if 'electrical_features' in data_dict_val:electrical_input_val_batch = data_dict_val['electrical_features'].to(self.device)electrical_probs_b = torch.softmax(self.electrical_model(electrical_input_val_batch), dim=1)else: print("验证中缺少 'electrical_features'")# 为批次中的每个样本应用规则引擎和融合for i in range(batch_size_val):# **为规则引擎提取和归一化第 i 个样本的特征**# 这部分需要您根据 data_dict_val 的内容和您的 Dataset 实现来填充# 例如:# vibration_features_sample_i = self.data_processor.process_vibration(data_dict_val['vibration_raw_unprocessed'][i], ...)# norm_vibration_f_i = self.data_processor.normalize_features(vibration_features_sample_i, 'vibration_features')# ... 其他特征 ...# rule_output_probs_sample_i = self._rule_engine_predict(vibration_features=norm_vibration_f_i, ...)# 为了演示,我们使用一个虚拟的规则输出rule_output_probs_sample_i = self._normalize_prob(np.random.rand(self.num_classes))evidences_sample_i = [cnn_probs_b[i].cpu().numpy(), lstm_probs_b[i].cpu().numpy(), electrical_probs_b[i].cpu().numpy(), rule_output_probs_sample_i]fused_probs_sample_i = self.fusion.combine_evidence(evidences_sample_i, self.model_weights)all_val_preds_fused_indices.append(np.argmax(fused_probs_sample_i))all_val_labels_list.extend(labels_batch_val_cpu.numpy()) # 使用CPU上的标签# -------------------------------------------------------------------if all_val_labels_list: # 确保处理了至少一个验证批次val_accuracy = accuracy_score(all_val_labels_list, all_val_preds_fused_indices)print(f"Epoch {epoch+1}/{epochs}, 验证准确率 (融合后): {val_accuracy:.4f}")print(classification_report(all_val_labels_list, all_val_preds_fused_indices, target_names=[self.data_processor.fault_types[i] for i in range(self.num_classes)], zero_division=0))if val_accuracy > best_val_accuracy:best_val_accuracy = val_accuracyself.save_models() # 使用默认路径保存最佳模型print(f"新最佳模型已保存,验证准确率: {best_val_accuracy:.4f}")else:print(f"Epoch {epoch+1}/{epochs}, 验证: 未处理数据。")print(f"训练完成。最佳验证准确率: {best_val_accuracy:.4f}")def get_fault_type_int(fault_types_dict, fault_name_str):for i, name in fault_types_dict.items():if name == fault_name_str:return iraise ValueError(f"故障名称 '{fault_name_str}' 不在 fault_types 中。")
DataProcessor.fault_types_str_to_int = get_fault_type_intif __name__ == "__main__":globals()["predicting_now"] = Falsesystem = FaultDiagnosisSystem()print(f"系统已初始化。设备: {system.device}")print(f"故障类别数量: {system.num_classes}")print("\n--- (占位符) 准备数据并拟合缩放器 ---")num_training_samples = 100 # 增加样本量以更好地拟合# --- 准备用于拟合缩放器的数据 ---# 这一步至关重要:使用与训练模型时相同的特征提取方法raw_training_data_for_scalers = []for _ in range(num_training_samples):# 模拟从数据集中加载一个样本的所有原始传感器读数sample_data = {'vibration_raw_unprocessed': np.random.normal(0, 1, VIBRATION_RAW_SEQ_LEN + np.random.randint(-100,100)), # 长度可变'temperature_series_unprocessed': np.random.normal(60, 5, np.random.randint(5,15)),'pressure_series_unprocessed': np.random.normal(100, 10, np.random.randint(50,150)),'blade_angle_series_unprocessed': np.random.normal(45, 2, np.random.randint(10,30)),'oil_particles_val_unprocessed': np.random.uniform(10,100),'oil_viscosity_val_unprocessed': np.random.uniform(60,90),'current_signal_unprocessed': np.random.normal(50, 5, 3), # 假设是3相电流值'target_blade_angle_unprocessed': 45.0,'design_pressure_unprocessed': 100.0}raw_training_data_for_scalers.append(sample_data)# 从原始数据中提取特征以拟合缩放器features_for_scaler_fitting = {'vibration_features': [], 'temperature': [], 'pressure': [],'blade_angle': [], 'oil_particles': [], 'current': []}for sample_raw_data in raw_training_data_for_scalers:features_for_scaler_fitting['vibration_features'].append(system.data_processor.process_vibration(sample_raw_data['vibration_raw_unprocessed'][:VIBRATION_RAW_SEQ_LEN]) # 截取或填充到固定长度)features_for_scaler_fitting['temperature'].append(system.data_processor.process_temperature(sample_raw_data['temperature_series_unprocessed']))features_for_scaler_fitting['pressure'].append(system.data_processor.process_pressure(sample_raw_data['pressure_series_unprocessed'], fs=PRESSURE_SAMPLING_RATE))features_for_scaler_fitting['blade_angle'].append(system.data_processor.process_blade_angle(sample_raw_data['blade_angle_series_unprocessed'], sample_raw_data['target_blade_angle_unprocessed']))features_for_scaler_fitting['oil_particles'].append( # 注意:oil_particles的scaler将基于 [particles, viscosity] 数组system.data_processor.process_oil_analysis(sample_raw_data['oil_particles_val_unprocessed'], sample_raw_data['oil_viscosity_val_unprocessed']))features_for_scaler_fitting['current'].append(system.data_processor.process_current(sample_raw_data['current_signal_unprocessed']))system.data_processor.fit_scalers(features_for_scaler_fitting)system.data_processor.save_scalers()print("\n--- (占位符) 训练模型 ---")# --- DummyDataset 现在需要生成更接近真实场景的数据 ---class AdvancedDummyDataset(torch.utils.data.Dataset):def __init__(self, num_samples, num_classes, data_processor_ref: DataProcessor, for_scaler_data):self.num_samples = num_samplesself.num_classes = num_classesself.data_processor = data_processor_ref # 引用已拟合缩放器的 DataProcessorself.raw_sensor_data_list = for_scaler_data # 使用之前为scaler准备的原始数据作为基础# 生成标签self.labels = torch.randint(0, num_classes, (num_samples,))def __len__(self): return self.num_samplesdef __getitem__(self, idx):# 从预生成的原始数据中获取一个样本(循环使用如果 num_samples > len(raw_sensor_data_list))raw_sample_data = self.raw_sensor_data_list[idx % len(self.raw_sensor_data_list)]# 1. CNN的原始振动数据 (填充/截断)vib_raw_unpr = raw_sample_data['vibration_raw_unprocessed']if len(vib_raw_unpr) < VIBRATION_RAW_SEQ_LEN:cnn_vib_input_np = np.pad(vib_raw_unpr, (0, VIBRATION_RAW_SEQ_LEN - len(vib_raw_unpr)), 'constant')else:cnn_vib_input_np = vib_raw_unpr[:VIBRATION_RAW_SEQ_LEN]# 2. LSTM的特征序列#    为简单起见,我们这里为每个样本只生成一个时间步的特征,然后复制它形成序列#    在真实场景中,您需要处理真正的时序特征temp_f = self.data_processor.normalize_features(self.data_processor.process_temperature(raw_sample_data['temperature_series_unprocessed']), 'temperature')pres_f = self.data_processor.normalize_features(self.data_processor.process_pressure(raw_sample_data['pressure_series_unprocessed'], fs=PRESSURE_SAMPLING_RATE), 'pressure')curr_f_all = self.data_processor.normalize_features(self.data_processor.process_current(raw_sample_data['current_signal_unprocessed']), 'current')lstm_single_step_features_np = np.concatenate([temp_f, pres_f, curr_f_all[:1]]) # 5+4+1 = 10# 复制单步特征形成序列lstm_feature_sequence_np = np.tile(lstm_single_step_features_np, (LSTM_SEQ_LEN, 1))# 3. Electrical模型的特征electrical_features_np = curr_f_all # 使用完整的电流特征 (假设是2个)# 转换为张量processed_data_dict = {'vibration_raw': torch.tensor(cnn_vib_input_np, dtype=torch.float32),'lstm_input_feature_sequence': torch.tensor(lstm_feature_sequence_np, dtype=torch.float32),'electrical_features': torch.tensor(electrical_features_np, dtype=torch.float32)}return processed_data_dict, self.labels[idx]# 使用 AdvancedDummyDataset# 注意:data_processor 实例现在被传递给 Dataset,因为它包含了已拟合的 scalerstrain_dataset = AdvancedDummyDataset(num_training_samples, system.num_classes, system.data_processor, raw_training_data_for_scalers)# 对于验证集,理想情况下也应该有一组独立的原始数据val_dataset = AdvancedDummyDataset(num_training_samples // 2, system.num_classes, system.data_processor, raw_training_data_for_scalers[:num_training_samples//2]) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16 if num_training_samples >=16 else 1, shuffle=True, num_workers=0) # num_workers=0 for simplicityval_loader = torch.utils.data.DataLoader(val_dataset, batch_size=16 if num_training_samples//2 >=16 else 1, num_workers=0)print("\n--- 开始实际训练(使用虚拟数据) ---")system.train(train_loader, val_loader, epochs=3) # 仅训练几个epoch作为演示print("\n--- 加载最佳模型 (如果训练中保存了) 并进行预测 ---")system_for_prediction = FaultDiagnosisSystem()try:system_for_prediction.load_models() # 使用默认路径加载except Exception as e:print(f"无法加载已训练的模型 (可能是因为验证准确率未提高,未保存最佳模型): {e}")print("为了预测结构演示,继续使用新初始化的模型 (需要加载scaler)。")system_for_prediction.data_processor.load_scalers() # 确保scaler被加载print("\n--- 对新样本数据进行预测 ---")new_vibration_raw = np.random.normal(0.5, 0.2, VIBRATION_RAW_SEQ_LEN - 50) # 测试填充new_temperature_series = np.array([70, 72, 130, 73, 74.5])new_pressure_series = np.random.normal(105, 12, 200)new_blade_angle_series = np.array([44, 44.5, 45, 45.1, 44.8])new_oil_particles = 55.0new_oil_viscosity = 78.0new_current_signal = np.array([51.0, 48.5, 50.5])target_angle_setting = 45.0current_design_pressure = 100.0try:prediction_result = system_for_prediction.predict(vibration_raw=new_vibration_raw,temperature_series=new_temperature_series,pressure_series=new_pressure_series,blade_angle_series=new_blade_angle_series,oil_particles_val=new_oil_particles,oil_viscosity_val=new_oil_viscosity,current_signal=new_current_signal,target_blade_angle=target_angle_setting,design_pressure=current_design_pressure)print("\n预测的故障概率:")for fault_name, probability in sorted(prediction_result.items(), key=lambda item: -item[1]):if probability > 0.001:print(f"  {fault_name}: {probability:.4f}")predicted_fault_idx = np.argmax(list(prediction_result.values()))print(f"主要预测故障: {system_for_prediction.data_processor.fault_types[predicted_fault_idx]}")except RuntimeError as e:if "的缩放器必须在预测前拟合" in str(e):print(f"预测失败: {e}。如果缩放器未正确拟合/加载,这是预期的。")else:print(f"预测期间发生运行时错误: {e}")except Exception as e:import tracebackprint(f"预测期间发生意外错误:\n{traceback.format_exc()}")

相关文章:

多模型协同预测在风机故障预测的应用(demo)

数据加载和预处理的真实性&#xff1a; 下面的代码中&#xff0c;DummyDataset 和数据加载部分仍然是高度简化和占位的。为了让这个训练循环真正有效&#xff0c;您必须用您自己的数据加载逻辑替换它。这意味着您需要创建一个 torch.utils.data.Dataset 的子类&#xff0c;它能…...

韩媒聚焦Lazarus攻击手段升级,CertiK联创顾荣辉详解应对之道

近日&#xff0c;韩国知名科技媒体《韩国IT时报》&#xff08;Korea IT Times&#xff09;刊文引述了CertiK联合创始人兼CEO顾荣辉教授的专业见解&#xff0c;聚焦黑客组织Lazarus在Web3.0领域攻击手段的持续升级&#xff0c;分析这一威胁的严峻性&#xff0c;并探讨了提升行业…...

5.9-selcct_poll_epoll 和 reactor 的模拟实现

5.9-select_poll_epoll 本文演示 select 等 io 多路复用函数的应用方法&#xff0c;函数具体介绍可以参考我过去写的博客。 先绑定监听的文件描述符 int sockfd socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(struc…...

图上思维:基于知识图的大型语言模型的深层可靠推理

摘要 尽管大型语言模型&#xff08;LLM&#xff09;在各种任务中取得了巨大的成功&#xff0c;但它们经常与幻觉问题作斗争&#xff0c;特别是在需要深入和负责任的推理的场景中。这些问题可以通过在LLM推理中引入外部知识图&#xff08;KG&#xff09;来部分解决。在本文中&am…...

37-智慧医疗服务平台(在线接诊/问诊)

系统功能特点&#xff1a; 技术栈: springBootVueMysql 功能点: 医生端 用户端 管理员端 医生端: 科室信息管理、在线挂号管理、预约体检管理、体检报告管理、药品信息管理、处方信息管理、缴费信息管理、病历信息管理、智能导诊管理、在线接诊患者功能 (和患者1V1沟通) 用户…...

【新品发布】VXI可重构信号处理系统模块系列

VXI可重构信号处理系统模块概述 VXI可重构信号处理系统模块包括了 GPU 模块&#xff0c;CPU 模块&#xff0c;射频模块、IO 模块、DSP模块、高速存储模块、交换模块&#xff0c;采集处理模块、回放处理模块等&#xff0c;全套组件为单体3U VPX架构&#xff0c;可自由组合到多槽…...

React 第三十八节 Router 中useRoutes 的使用详解及注意事项

前言 useRoutes 是 React Router v6 引入的一个钩子函数&#xff0c;允许通过 JavaScript 对象&#xff08;而非传统的 JSX 语法&#xff09;定义路由配置。这种方式更适合复杂路由结构&#xff0c;且代码更简洁易维护。 一、基础使用 1.1、useRoutes路由配置对象 useRoute…...

Redhat 系统详解

Red Hat 系统深度解析&#xff1a;从企业级架构到核心组件 一、Red Hat 概述&#xff1a;企业级 Linux 的标杆 Red Hat 是全球领先的开源解决方案供应商&#xff0c;其核心产品 Red Hat Enterprise Linux&#xff08;RHEL&#xff09; 是企业级 Linux 的黄金标准。RHEL 以 稳…...

docker常用命令总结

常用命令含义docker info查看docker 服务的信息-------------------------镜像篇docker pull XXX从官网上拉取名为XXX的镜像docker login -u name登录自己的dockerhub账号docker push XXX将XXX镜像上传到自己的dockerhub账户中&#xff08;XXX的命名必须是用户名/镜像名&#x…...

【el-admin】el-admin关联数据字典

数据字典使用 一、新增数据字典1、新增【图书状态】和【图书类型】数据字典2、编辑字典值 二、代码生成配置1、表单设置2、关联字典3、验证关联数据字典 三、查询操作1、模糊查询2、按类别查询&#xff08;下拉框&#xff09; 四、数据校验 一、新增数据字典 1、新增【图书状态…...

component :is是什么?

问&#xff1a; component &#xff1a;is是什么&#xff1f; 是组件&#xff1f; 那我们是不是就不需要自己创建组件了&#xff1f;还是什么意思&#xff1f;component &#xff1a;is和什么功能是类似的&#xff0c;同时和类似功能相比对什么时候用component &#xff1a;is…...

适老化洗浴辅具产业:在技术迭代与需求升级中重塑银发经济新生态

随着中国人口老龄化程度的不断加深&#xff0c;老年群体对于适老化产品的需求日益增长。 适老化洗浴辅具作为保障老年人洗浴安全与舒适的关键产品&#xff0c;其发展状况备受关注。 深入剖析中国适老化洗浴辅具的发展现状&#xff0c;并探寻助力产业发展的有效路径&#xff0…...

『Python学习笔记』ubuntu解决matplotlit中文乱码的问题!

ubuntu解决matplotlit中文乱码的问题&#xff01; 文章目录 simhei.ttf字体下载链接&#xff1a;http://xiazaiziti.com/210356.html将字体放到合适的地方 sudo cp SimHei.ttf /usr/share/fonts/(base) zkfzkf:~$ fc-list | grep -i "SimHei" /usr/local/share/font…...

从AI到新能源:猎板PCB的HDI技术如何定义高端制造新标准?

2025年&#xff0c;随着AI服务器、新能源汽车、折叠屏设备等新兴领域的爆发式增长&#xff0c;高密度互连&#xff08;HDI&#xff09;电路板成为电子制造业的“必争之地”。HDI板凭借微孔、细线宽和高层间对位精度&#xff0c;能够实现电子设备的高集成化与微型化&#xff0c;…...

汽车制造行业的数字化转型

嘿&#xff0c;大家好&#xff01;今天来和大家聊聊汽车制造行业的数字化转型&#xff0c;这可是当下非常热门的话题哦&#xff01; 随着科技的飞速发展&#xff0c;传统的汽车制造行业正经历着一场深刻的变革。数字化技术已经不再是“锦上添花”&#xff0c;而是车企能否在未…...

Redis 常见数据类型

Redis 常见数据类型 一、基本全局命令详解与实操 1. KEYS 命令 功能&#xff1a;按模式匹配返回所有符合条件的键&#xff08;生产环境慎用&#xff0c;可能导致阻塞&#xff09;。 语法&#xff1a; KEYS pattern 模式规则&#xff1a; h?llo&#xff1a;匹配 hello, ha…...

【计算机网络-传输层】传输层协议-TCP核心机制与可靠性保障

&#x1f4da; 博主的专栏 &#x1f427; Linux | &#x1f5a5;️ C | &#x1f4ca; 数据结构 | &#x1f4a1;C 算法 | &#x1f152; C 语言 | &#x1f310; 计算机网络 上篇文章&#xff1a;传输层协议-UDP 下篇文章&#xff1a; 网络层 我们的讲解顺序是&…...

对golang中CSP的理解

概念&#xff1a; CSP模型&#xff0c;即通信顺序进程模型&#xff0c;是由英国计算机科学家C.A.R. Hoare于1978年提出的。该模型强调进程之间通过通道&#xff08;channel&#xff09;进行通信&#xff0c;并通过消息传递来协调并发执行的进程。CSP模型的核心思想是“不要通过…...

嵌入式openharmony标准系统中HDF框架底层原理分析

1、案例简介 该程序是基于OpenHarmony标准系统编写的基础外设类:简易HDF驱动。 2、基础知识 2.1、OpenHarmony HDF开发简介 HDF(Hardware Driver Foundation)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理、驱动消息机制和配置管理。旨在构建统一…...

238.除自身以外数组的乘积

给你一个数组&#xff0c;求出第 i 个元素以外的数组元素的乘积&#xff0c;不能使用除法&#xff0c;且时间复杂度O(n), 对于一个数&#xff0c;如果知道了前缀元素的乘积和后缀元素的乘积&#xff0c;就知道了这个元素以外的数组元素的乘积&#xff0c;所以现在的问题是如何…...

AI文旅|暴雨打造旅游新体验

今年"五一"假期&#xff0c;全国文旅市场迎来爆发式增长&#xff0c;从丈崖瀑布的磅礴水雾到城市商区的璀璨霓虹&#xff0c;从山野民宿的静谧悠然到主题乐园的欢腾喧嚣&#xff0c;处处人潮涌动。在这火热的景象背后&#xff0c;一股“无形之力”正悄然改变旅游体验…...

学习心得《How Global AI Policy and Regulations Will Impact Your Enterprise》Gartner

AI时代来临,然而与之对应的是海量的数据的安全性和合规性如何保障,如何平衡个人与智能体的利益,恰巧,最近Gartner发布了《How Global AI Policy and Regulations Will Impact Your Enterprise》,我们就其中的观点一起进行探讨。 战略规划假设 我们首先关注的是关键的战略…...

JAVA将一个同步方法改为异步执行

目的&#xff1a; 这么做的目的就是为了使一个高频率执行的方法能不阻塞整个程序&#xff0c;将该方法丢入到线程池中让线程去做异步执行&#xff0c;既提高了程序整体运行速度&#xff0c;也使得在高并发环境下程序能够更加健壮&#xff08;同步执行可能会使得请求堆积以致系…...

对遗传算法思想的理解与实例详解

目录 一、概述 二、实例详解 1&#xff09;问题描述与分析 2&#xff09;初始化种群 3&#xff09;计算种群适应度 4&#xff09;遗传操作 5&#xff09;基因交叉操作 6&#xff09;变异操作 三、计算结果 四、总结 一、概述 遗传算法在求解最优解的问题中最为常用&a…...

数据可视化大屏——物流大数据服务平台(二)

代码分析&#xff1a; 物流大数据平台代码分析 这是一个基于 Bootstrap 和 ECharts 构建的物流大数据平台前端页面&#xff0c;设计采用了经典的三栏布局&#xff0c;主要展示河南省及全国的物流数据可视化内容。下面从多个维度进行分析&#xff1a; 1. 页面结构分析 整体采…...

MindSpore框架学习项目-ResNet药物分类-构建模型

目录 2.构建模型 2.1定义模型类 2.1.1 基础块ResidualBlockBase ResidualBlockBase代码解析 2.1.2 瓶颈块ResidualBlock ResidualBlock代码解释 2.1.3 构建层 构建层代码说明 2.1.4 定义不同组合(block&#xff0c;layer_nums)的ResNet网络实现 ResNet组建类代码解析…...

ChatTempMail - AI驱动的免费临时邮箱服务

在当今数字世界中&#xff0c;保护在线隐私的需求日益增长。ChatTempMail应运而生&#xff0c;作为一款融合人工智能技术的新一代临时邮箱服务&#xff0c;它不仅提供传统临时邮箱的基本功能&#xff0c;还通过AI技术大幅提升了用户体验。 核心功能与特性 1. AI驱动的智能邮件…...

(leetcode) 力扣100 9.找到字符串中所有字母异位词(滑动窗口)

题目 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 数据范围 1 < s.length, p.length < 3 * 104 s 和 p 仅包含小写字母 样例 示例 1: 输入: s "cbaebabacd", p &quo…...

深入了解 Stable Diffusion:AI 图像生成的奥秘

一、引言 AI 艺术与图像生成技术的兴起改变了我们创造和体验视觉内容的方式。在过去几年里&#xff0c;深度学习模型已经能够创造出令人惊叹的艺术作品&#xff0c;这些作品不仅模仿了人类艺术家的风格&#xff0c;甚至还能创造出前所未有的新风格。在这个领域&#xff0c;Sta…...

场外期权平值期权 实值期权 虚值期权有什么区别?收益如何计算?

​​期权汇 场外期权按价值状态分为平值、虚值、实值期权。 01&#xff5c;实值期权对于看涨期权而言&#xff0c;如果行权价格低于标的市场价格&#xff0c;则该期权处于实值状态&#xff1b;对于看跌期权&#xff0c;如果行权价格高于标的市场价格&#xff0c;则处于实值状态…...

微软系统 红帽系统 网络故障排查:ping、traceroute、netstat

在微软&#xff08;Windows&#xff09;和红帽&#xff08;Red Hat Enterprise Linux&#xff0c;RHEL&#xff09;等系统中&#xff0c;网络故障排查是确保系统正常运行的重要环节。 ping、traceroute&#xff08;在Windows中为tracert&#xff09;和netstat是三个常用的网络…...

HOT 100 | 【子串】76.最小覆盖子串、【普通数组】53.最大子数组和、【普通数组】56.合并区间

一、【子串】76.最小覆盖子串 1. 解题思路 定义两个哈希表分别用于 t 统计字符串 t 的字符个数&#xff0c;另一个sub_s用于统计字符串 t 在 s 的子串里面字符出现的频率。 为了降低时间复杂度&#xff0c;定义一个变量t_count用于统计 t 哈希表中元素的个数。哈希表sub_s是一…...

基于CNN的猫狗图像分类系统

一、系统概述 本系统是基于PyTorch框架构建的智能图像分类系统&#xff0c;专门针对CIFAR-10数据集中的猫&#xff08;类别3&#xff09;和狗&#xff08;类别5&#xff09;进行分类任务。系统采用卷积神经网络&#xff08;CNN&#xff09;作为核心算法&#xff0c;结合图形用…...

《时序数据库全球格局:国产与国外主流方案的对比分析》

引言 时序数据库&#xff08;Time Series Database, TSDB&#xff09;是专门用于存储、查询和分析时间序列数据的数据库系统&#xff0c;广泛应用于物联网&#xff08;IoT&#xff09;、金融、工业监控、智能运维等领域。近年来&#xff0c;随着大数据和物联网技术的发展&…...

力扣-2.两数相加

题目描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都…...

富乐德传感技术盘古信息 | 锚定“未来工厂”新坐标,开启传感器制造行业数字化转型新征程

在数字化浪潮下&#xff0c;制造业正经历深刻变革。 传感器作为智能制造的核心基础部件&#xff0c;正面临着质量精度要求升级、交付周期缩短、成本管控严苛等多重挑战。传统依赖人工纸质管理、设备数据孤岛化的生产模式&#xff0c;已成为制约高端传感器制造突破“高精度、高…...

RT-Thread 深入系列 Part 2:RT-Thread 内核核心机制深度剖析

摘要&#xff1a; 本文从线程管理、调度器原理、中断处理与上下文切换、IPC 同步机制、内存管理五大核心模块出发&#xff0c;深入剖析 RT-Thread 内核实现细节&#xff0c;并辅以源码解读、流程图、时序图与性能数据。 目录 线程管理与调度器原理 1.1 线程控制块&#xff08;T…...

uni-app,小程序自定义导航栏实现与最佳实践

文章目录 前言为什么需要自定义导航栏&#xff1f;基本实现方案1. 关闭原生导航栏2. 自定义导航栏组件结构3. 获取状态栏高度4. 样式设置 内容区域适配跨平台适配要点iOS与Android差异处理 常见导航栏效果实现1. 透明导航栏2. 滚动渐变导航栏3. 自定义返回逻辑 解决常见问题1. …...

小程序消息订阅的整个实现流程

以下是微信小程序消息订阅的完整实现流程&#xff0c;分为 5个核心步骤 和 3个关键注意事项&#xff1a; 一、消息订阅完整流程 步骤1&#xff1a;配置订阅消息模板 登录微信公众平台进入「功能」→「订阅消息」选择公共模板或申请自定义模板&#xff0c;获取模板ID&#xff…...

istio in action之Gateway流量入口与安全

入口网关&#xff0c;简单来说&#xff0c;就是如何让外部世界和我们精心构建的集群内部服务顺畅地对话。在网络安全领域&#xff0c;有一个词叫流量入口&#xff0c;英文叫Ingress。这指的是那些从我们自己网络之外&#xff0c;比如互联网&#xff0c;发往我们内部网络的流量。…...

LeetCode 1722. 执行交换操作后的最小汉明距离 题解

示例&#xff1a; 输入&#xff1a;source [1,2,3,4], target [2,1,4,5], allowedSwaps [[0,1],[2,3]] 输出&#xff1a;1 解释&#xff1a;source 可以按下述方式转换&#xff1a; - 交换下标 0 和 1 指向的元素&#xff1a;source [2,1,3,4] - 交换下标 2 和 3 指向的元…...

区块链详解

1. 引言 1.1 背景 在数字化时代&#xff0c;信息的存储、传输和验证面临诸多挑战&#xff0c;如数据篡改、信任缺失、中心化风险等。区块链技术应运而生&#xff0c;作为一种分布式账本技术&#xff0c;它通过去中心化、去信任化、不可篡改等特性&#xff0c;为解决这些问题提…...

申能集团笔试1

目录 注意 过程 注意 必须开启摄像头和麦克风 只能用网页编程&#xff0c;不能用本地环境 可以用Index进行测试 过程 我还以为是编程&#xff0c;没想到第一次是企业人际关系、自我评价的选择题&#xff0c;哈哈哈有点轻松&#xff0c;哦对他要求不能泄漏题目&#xff0c…...

机器人手臂的坐标变换:一步步计算齐次矩阵过程 [特殊字符]

大家好!今天我们来学习如何计算机器人手臂的坐标变换。别担心,我会用最简单的方式解释这个过程,就像搭积木一样简单! 一、理解问题 我们有一个机器人手臂,由多个关节组成。每个关节都有自己的坐标系,我们需要计算从世界坐标系(W)到末端执行器(P₃)的完整变换。 二、已…...

神经元和神经网络定义

在深度学习中&#xff0c;神经元和神经网络是构成神经网络模型的基本元素。让我们从基础开始&#xff0c;逐步解释它们的含义和作用。 1️⃣ 神经元是什么&#xff1f; 神经元是神经网络中的基本计算单元&#xff0c;灵感来自于生物神经系统中的神经元。每个人的脑中有数以亿…...

Vue——Axios

一、Axios 是什么 Axios 是一个基于 promise 网络请求库&#xff0c;作用于 node.js 和浏览器中。 它是 isomorphic 的 ( 即同一套代 码可以运行在浏览器和 node.js 中 ) 。在服务端它使用原生 node.js http 模块 , 而在客户端 ( 浏览端 ) 则使 用 XMLHttpRequest…...

力扣:轮转数组

题目 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 例子 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5…...

TCP/IP协议的体系结构

文章目录 前言数据链路层网络层传输层应用层 前言 TCP/IP通信体系主要分为四个层次&#xff0c;从底至上分别为&#xff1a; 数据链路层 >网络层 > 传输层 >应用层 该体系的工作原理主要依靠封装与分用的使用完成对信息的传递与解析。 1. 所谓封装&#xff0c;就是上层…...

Vue3 中 ref 与 reactive 的区别及底层原理详解

一、核心区别 1. 数据类型与使用场景 • ref 可定义基本类型&#xff08;字符串、数字、布尔值&#xff09;和对象类型的响应式数据。对于对象类型&#xff0c;ref 内部会自动调用 reactive 将其转换为响应式对象。 语法特点&#xff1a;需通过 .value 访问或修改数据&#…...

MySQL 与 Elasticsearch 数据一致性方案

MySQL 与 Elasticsearch 数据一致性方案 前言一、同步双写&#xff08;Synchronous Dual Write&#xff09;&#x1f504;二、异步双写&#xff08;Asynchronous Dual Write&#xff09;&#x1f4e4;三、定时同步&#xff08;Scheduled Synchronization&#xff09;&#x1f5…...