基于极限学习机(ELM)的电路故障模式分类MATLAB实现

%% 基于极限学习机(ELM)的电路故障模式分类
clear; clc; close all;

%% 主函数
function main_circuit_fault_elm()
    % 创建图形界面
    createCircuitFaultGUI();
end

%% 创建电路故障分类图形界面
function createCircuitFaultGUI()
    fig = figure('Name', '电路故障模式分类 - 极限学习机', ...
                'NumberTitle', 'off', ...
                'Position', [100, 100, 1400, 800], ...
                'MenuBar', 'none', ...
                'ToolBar', 'none');
    
    % 控制面板
    uicontrol('Style', 'text', 'String', '隐藏层节点:', ...
             'Position', [50, 750, 80, 20], 'HorizontalAlignment', 'left');
    hidden_nodes_edit = uicontrol('Style', 'edit', 'String', '100', ...
                                 'Position', [140, 750, 50, 25], ...
                                 'BackgroundColor', 'white');
    
    uicontrol('Style', 'text', 'String', '激活函数:', ...
             'Position', [210, 750, 60, 20], 'HorizontalAlignment', 'left');
    activation_popup = uicontrol('Style', 'popupmenu', ...
                                'String', {'sigmoid', 'sin', 'hardlim', 'radbas'}, ...
                                'Position', [280, 750, 80, 25], ...
                                'BackgroundColor', 'white');
    
    uicontrol('Style', 'text', 'String', '故障类型数:', ...
             'Position', [380, 750, 70, 20], 'HorizontalAlignment', 'left');
    num_faults_edit = uicontrol('Style', 'edit', 'String', '5', ...
                               'Position', [460, 750, 50, 25], ...
                               'BackgroundColor', 'white');
    
    uicontrol('Style', 'pushbutton', 'String', '生成数据', ...
             'Position', [530, 750, 80, 25], 'Callback', @generateData);
    uicontrol('Style', 'pushbutton', 'String', '训练ELM', ...
             'Position', [620, 750, 80, 25], 'Callback', @trainELM);
    uicontrol('Style', 'pushbutton', 'String', '测试分类', ...
             'Position', [710, 750, 80, 25], 'Callback', @testClassification);
    uicontrol('Style', 'pushbutton', 'String', '性能分析', ...
             'Position', [800, 750, 80, 25], 'Callback', @analyzePerformance);
    uicontrol('Style', 'pushbutton', 'String', '实时诊断', ...
             'Position', [890, 750, 80, 25], 'Callback', @realTimeDiagnosis);
    
    % 结果显示区域
    result_panel = uipanel('Title', '分类结果', 'Position', [0.02, 0.55, 0.3, 0.4]);
    result_text = uicontrol('Parent', result_panel, 'Style', 'text', ...
                           'String', '等待操作...', 'Position', [10, 10, 250, 300], ...
                           'HorizontalAlignment', 'left', 'FontSize', 10);
    
    % 创建绘图区域
    axes_data = axes('Parent', fig, 'Position', [0.35, 0.55, 0.3, 0.4]);
    axes_confusion = axes('Parent', fig, 'Position', [0.68, 0.55, 0.3, 0.4]);
    axes_roc = axes('Parent', fig, 'Position', [0.35, 0.05, 0.3, 0.45]);
    axes_features = axes('Parent', fig, 'Position', [0.68, 0.05, 0.3, 0.45]);
    
    % 存储数据
    handles = guidata(fig);
    handles.hidden_nodes_edit = hidden_nodes_edit;
    handles.activation_popup = activation_popup;
    handles.num_faults_edit = num_faults_edit;
    handles.result_text = result_text;
    handles.axes_data = axes_data;
    handles.axes_confusion = axes_confusion;
    handles.axes_roc = axes_roc;
    handles.axes_features = axes_features;
    handles.training_data = [];
    handles.testing_data = [];
    handles.elm_model = [];
    handles.fault_types = {};
    
    guidata(fig, handles);
    
    updateResultDisplay(handles, '电路故障分类系统已启动\n点击"生成数据"开始');
end

%% 生成电路故障数据
function generateData(~, ~)
    fig = gcbf;
    handles = guidata(fig);
    
    % 获取参数
    num_faults = str2double(get(handles.num_faults_edit, 'String'));
    
    if isnan(num_faults) || num_faults < 2
        msgbox('故障类型数至少为2!', '错误');
        return;
    end
    
    % 生成模拟电路故障数据
    updateResultDisplay(handles, '正在生成电路故障数据...');
    
    [X_train, Y_train, X_test, Y_test, fault_names] = generateCircuitFaultData(num_faults);
    
    % 存储数据
    handles.training_data.X = X_train;
    handles.training_data.Y = Y_train;
    handles.testing_data.X = X_test;
    handles.testing_data.Y = Y_test;
    handles.fault_types = fault_names;
    
    % 显示数据分布
    plotDataDistribution(handles, X_train, Y_train, fault_names);
    
    % 显示数据信息
    result_str = sprintf('=== 电路故障数据生成完成 ===\n');
    result_str = [result_str sprintf('故障类型数: %d\n', num_faults)];
    result_str = [result_str sprintf('训练样本数: %d\n', size(X_train, 1))];
    result_str = [result_str sprintf('测试样本数: %d\n', size(X_test, 1))];
    result_str = [result_str sprintf('特征维度: %d\n\n', size(X_train, 2))];
    
    result_str = [result_str sprintf('故障类型:\n')];
    for i = 1:num_faults
        train_count = sum(Y_train == i);
        test_count = sum(Y_test == i);
        result_str = [result_str sprintf('  %s: 训练%d, 测试%d\n', ...
                                        fault_names{i}, train_count, test_count)];
    end
    
    set(handles.result_text, 'String', result_str);
    
    guidata(fig, handles);
    msgbox('数据生成完成!', '成功');
end

%% 生成电路故障数据
function [X_train, Y_train, X_test, Y_test, fault_names] = generateCircuitFaultData(num_faults)
    fprintf('生成电路故障数据...\n');
    
    % 定义故障类型
    fault_names = cell(num_faults, 1);
    for i = 1:num_faults
        fault_names{i} = sprintf('故障模式%d', i);
    end
    fault_names{1} = '正常状态';
    
    % 每种故障的样本数
    samples_per_fault = 200;
    total_samples = samples_per_fault * num_faults;
    
    % 特征维度 (模拟电路测量参数)
    num_features = 10;
    
    % 初始化数据
    X = zeros(total_samples, num_features);
    Y = zeros(total_samples, 1);
    
    % 生成每种故障的数据
    for fault_id = 1:num_faults
        start_idx = (fault_id-1) * samples_per_fault + 1;
        end_idx = fault_id * samples_per_fault;
        
        % 基础特征 (正常状态)
        base_features = generateNormalFeatures(samples_per_fault, num_features);
        
        % 根据故障类型添加特定模式
        fault_features = addFaultPattern(base_features, fault_id, num_faults);
        
        X(start_idx:end_idx, :) = fault_features;
        Y(start_idx:end_idx) = fault_id;
    end
    
    % 划分训练测试集
    rng(42); % 设置随机种子
    cv = cvpartition(Y, 'HoldOut', 0.3);
    
    X_train = X(training(cv), :);
    Y_train = Y(training(cv));
    X_test = X(test(cv), :);
    Y_test = Y(test(cv));
    
    fprintf('数据生成完成: %d个样本, %d个特征, %d种故障\n', ...
            total_samples, num_features, num_faults);
end

%% 生成正常状态特征
function features = generateNormalFeatures(num_samples, num_features)
    % 模拟正常电路的特征
    features = zeros(num_samples, num_features);
    
    % 不同的特征有不同的统计特性
    for i = 1:num_features
        switch mod(i, 5)
            case 0
                % 电压特征 - 正态分布
                features(:, i) = 5 + 0.1 * randn(num_samples, 1);
            case 1
                % 电流特征 - 正态分布
                features(:, i) = 2 + 0.05 * randn(num_samples, 1);
            case 2
                % 电阻特征 - 均匀分布
                features(:, i) = 100 + 5 * rand(num_samples, 1);
            case 3
                % 频率特征 - 正态分布
                features(:, i) = 50 + 0.5 * randn(num_samples, 1);
            case 4
                % 相位特征 - 均匀分布
                features(:, i) = 0 + 10 * rand(num_samples, 1);
        end
    end
end

%% 添加故障模式
function fault_features = addFaultPattern(features, fault_id, num_faults)
    fault_features = features;
    [num_samples, num_features] = size(features);
    
    switch fault_id
        case 1 % 正常状态
            % 保持原样
            return;
            
        case 2 % 短路故障
            % 电压下降,电流上升
            fault_features(:, 1) = features(:, 1) * 0.3 + 0.5 * randn(num_samples, 1);
            fault_features(:, 2) = features(:, 2) * 3.0 + 0.2 * randn(num_samples, 1);
            fault_features(:, 3) = features(:, 3) * 0.1 + 2 * rand(num_samples, 1);
            
        case 3 % 开路故障
            % 电压上升,电流为零
            fault_features(:, 1) = features(:, 1) * 1.5 + 0.3 * randn(num_samples, 1);
            fault_features(:, 2) = 0.01 + 0.05 * randn(num_samples, 1);
            fault_features(:, 6) = features(:, 6) + 20 * rand(num_samples, 1);
            
        case 4 % 元件老化
            % 参数缓慢漂移
            drift = 0.5 + 0.3 * randn(num_samples, 1);
            for i = 1:num_features
                fault_features(:, i) = features(:, i) .* (0.8 + 0.4 * rand(num_samples, 1));
            end
            
        case 5 % 噪声干扰
            % 高频噪声
            for i = 1:num_features
                noise = 0.2 * randn(num_samples, 1) .* (1 + 0.5 * sin(2*pi*(1:num_samples)'/10));
                fault_features(:, i) = features(:, i) + noise;
            end
            
        otherwise % 其他故障
            % 随机扰动
            for i = 1:num_features
                scale = 0.3 + 0.4 * rand();
                fault_features(:, i) = features(:, i) .* (1 + scale * randn(num_samples, 1));
            end
    end
    
    % 添加一些随机性
    fault_features = fault_features + 0.05 * randn(size(fault_features));
end

%% 绘制数据分布
function plotDataDistribution(handles, X, Y, fault_names)
    axes(handles.axes_data);
    
    % 使用PCA降维可视化
    [coeff, score] = pca(X);
    projected_data = score(:, 1:2);
    
    num_classes = length(fault_names);
    colors = hsv(num_classes);
    markers = 'osd^v><ph+*x';
    
    hold off;
    for i = 1:num_classes
        class_idx = (Y == i);
        marker = markers(mod(i-1, length(markers)) + 1);
        scatter(projected_data(class_idx, 1), projected_data(class_idx, 2), ...
                50, colors(i, :), marker, 'filled', 'DisplayName', fault_names{i});
        hold on;
    end
    
    xlabel('第一主成分');
    ylabel('第二主成分');
    title('电路故障数据分布 (PCA可视化)');
    legend('show', 'Location', 'best');
    grid on;
end

%% 训练ELM模型
function trainELM(~, ~)
    fig = gcbf;
    handles = guidata(fig);
    
    if isempty(handles.training_data)
        msgbox('请先生成数据!', '警告');
        return;
    end
    
    % 获取参数
    hidden_nodes = str2double(get(handles.hidden_nodes_edit, 'String'));
    activation_type = get(handles.activation_popup, 'Value');
    
    if isnan(hidden_nodes) || hidden_nodes < 10
        msgbox('隐藏层节点数至少为10!', '错误');
        return;
    end
    
    % 训练ELM模型
    updateResultDisplay(handles, '正在训练极限学习机...');
    
    tic;
    elm_model = trainELMModel(handles.training_data.X, handles.training_data.Y, ...
                             hidden_nodes, activation_type);
    training_time = toc;
    
    handles.elm_model = elm_model;
    
    % 在训练集上评估
    train_predictions = predictELM(handles.elm_model, handles.training_data.X);
    train_accuracy = sum(train_predictions == handles.training_data.Y) / ...
                    length(handles.training_data.Y);
    
    % 显示训练结果
    result_str = sprintf('=== ELM模型训练完成 ===\n');
    result_str = [result_str sprintf('隐藏层节点: %d\n', hidden_nodes)];
    result_str = [result_str sprintf('激活函数: %s\n', getActivationName(activation_type))];
    result_str = [result_str sprintf('训练时间: %.3f 秒\n', training_time)];
    result_str = [result_str sprintf('训练准确率: %.2f%%\n\n', train_accuracy * 100)];
    
    result_str = [result_str sprintf('模型参数:\n')];
    result_str = [result_str sprintf('  输入维度: %d\n', size(elm_model.input_weights, 2))];
    result_str = [result_str sprintf('  输出维度: %d\n', size(elm_model.output_weights, 1))];
    result_str = [result_str sprintf('  正则化参数: %.2e\n', elm_model.C)];
    
    set(handles.result_text, 'String', result_str);
    
    % 绘制特征重要性
    plotFeatureImportance(handles, elm_model);
    
    guidata(fig, handles);
    msgbox('ELM训练完成!', '成功');
end

%% 获取激活函数名称
function name = getActivationName(activation_type)
    switch activation_type
        case 1
            name = 'sigmoid';
        case 2
            name = 'sin';
        case 3
            name = 'hardlim';
        case 4
            name = 'radbas';
        otherwise
            name = 'unknown';
    end
end

%% 训练ELM模型
function elm_model = trainELMModel(X, Y, hidden_nodes, activation_type)
    fprintf('训练ELM模型...\n');
    
    [num_samples, num_features] = size(X);
    num_classes = max(Y);
    
    % 转换为one-hot编码
    Y_onehot = zeros(num_samples, num_classes);
    for i = 1:num_samples
        Y_onehot(i, Y(i)) = 1;
    end
    
    % 随机初始化输入权重和偏置
    input_weights = randn(hidden_nodes, num_features) * 2 - 1;
    bias = randn(hidden_nodes, 1);
    
    % 计算隐藏层输出
    H = computeHiddenLayer(X, input_weights, bias, activation_type);
    
    % 使用正则化最小二乘法计算输出权重
    C = 1e-3; % 正则化参数
    output_weights = (H' * H + eye(size(H,2)) / C) \ (H' * Y_onehot);
    
    % 存储模型参数
    elm_model.input_weights = input_weights;
    elm_model.bias = bias;
    elm_model.output_weights = output_weights;
    elm_model.activation_type = activation_type;
    elm_model.hidden_nodes = hidden_nodes;
    elm_model.C = C;
    elm_model.num_classes = num_classes;
    
    fprintf('ELM训练完成: %d个隐藏节点, %d个类别\n', hidden_nodes, num_classes);
end

%% 计算隐藏层输出
function H = computeHiddenLayer(X, input_weights, bias, activation_type)
    [num_samples, ~] = size(X);
    hidden_nodes = size(input_weights, 1);
    
    H = zeros(num_samples, hidden_nodes);
    
    for i = 1:num_samples
        for j = 1:hidden_nodes
            net_input = input_weights(j, :) * X(i, :)' + bias(j);
            H(i, j) = activationFunction(net_input, activation_type);
        end
    end
end

%% 激活函数
function output = activationFunction(x, activation_type)
    switch activation_type
        case 1 % sigmoid
            output = 1 ./ (1 + exp(-x));
        case 2 % sin
            output = sin(x);
        case 3 % hardlim
            output = double(x >= 0);
        case 4 % radbas
            output = exp(-x.^2);
        otherwise
            output = 1 ./ (1 + exp(-x)); % 默认sigmoid
    end
end

%% 预测ELM输出
function predictions = predictELM(elm_model, X)
    % 计算隐藏层输出
    H = computeHiddenLayer(X, elm_model.input_weights, elm_model.bias, ...
                          elm_model.activation_type);
    
    % 计算输出层
    outputs = H * elm_model.output_weights;
    
    % 转换为类别预测
    [~, predictions] = max(outputs, [], 2);
end

%% 绘制特征重要性
function plotFeatureImportance(handles, elm_model)
    axes(handles.axes_features);
    
    % 计算特征重要性 (基于输入权重的绝对值之和)
    feature_importance = sum(abs(elm_model.input_weights), 1);
    
    % 归一化
    feature_importance = feature_importance / sum(feature_importance);
    
    bar(feature_importance, 'FaceColor', [0.3, 0.6, 0.9], 'EdgeColor', 'blue');
    
    xlabel('特征索引');
    ylabel('重要性权重');
    title('ELM特征重要性分析');
    grid on;
    
    % 标记最重要的特征
    [~, top_idx] = max(feature_importance);
    hold on;
    plot(top_idx, feature_importance(top_idx), 'ro', 'MarkerSize', 8, ...
         'MarkerFaceColor', 'red');
    text(top_idx, feature_importance(top_idx), ' 最重要特征', ...
         'FontSize', 10, 'Color', 'red');
end

%% 测试分类
function testClassification(~, ~)
    fig = gcbf;
    handles = guidata(fig);
    
    if isempty(handles.elm_model) || isempty(handles.testing_data)
        msgbox('请先训练模型并生成数据!', '警告');
        return;
    end
    
    updateResultDisplay(handles, '正在进行故障分类测试...');
    
    % 预测测试集
    test_predictions = predictELM(handles.elm_model, handles.testing_data.X);
    true_labels = handles.testing_data.Y;
    
    % 计算性能指标
    test_accuracy = sum(test_predictions == true_labels) / length(true_labels);
    
    % 计算混淆矩阵
    confusion_mat = confusionmat(true_labels, test_predictions);
    
    % 计算每类指标
    num_classes = handles.elm_model.num_classes;
    precision = zeros(1, num_classes);
    recall = zeros(1, num_classes);
    f1_score = zeros(1, num_classes);
    
    for i = 1:num_classes
        tp = confusion_mat(i,i);
        fp = sum(confusion_mat(:,i)) - tp;
        fn = sum(confusion_mat(i,:)) - tp;
        
        precision(i) = tp / (tp + fp + eps);
        recall(i) = tp / (tp + fn + eps);
        f1_score(i) = 2 * (precision(i) * recall(i)) / (precision(i) + recall(i) + eps);
    end
    
    % 显示分类结果
    result_str = sprintf('=== 故障分类测试结果 ===\n');
    result_str = [result_str sprintf('测试集准确率: %.2f%%\n\n', test_accuracy * 100)];
    
    result_str = [result_str sprintf('各类别性能:\n')];
    for i = 1:num_classes
        result_str = [result_str sprintf('  %s:\n', handles.fault_types{i})];
        result_str = [result_str sprintf('    精确率: %.2f%%, 召回率: %.2f%%, F1: %.2f%%\n', ...
                                        precision(i)*100, recall(i)*100, f1_score(i)*100)];
    end
    
    set(handles.result_text, 'String', result_str);
    
    % 绘制混淆矩阵
    plotConfusionMatrix(handles, confusion_mat, handles.fault_types);
    
    % 绘制ROC曲线
    plotROCCurve(handles, handles.testing_data, handles.elm_model);
    
    guidata(fig, handles);
    msgbox(sprintf('测试完成!准确率: %.1f%%', test_accuracy*100), '测试结果');
end

%% 绘制混淆矩阵
function plotConfusionMatrix(handles, confusion_mat, class_names)
    axes(handles.axes_confusion);
    
    imagesc(confusion_mat);
    colormap(flipud(gray));
    colorbar;
    
    % 添加数值标签
    [n_classes, ~] = size(confusion_mat);
    for i = 1:n_classes
        for j = 1:n_classes
            text(j, i, num2str(confusion_mat(i,j)), ...
                 'HorizontalAlignment', 'center', ...
                 'Color', 'red', 'FontWeight', 'bold');
        end
    end
    
    set(gca, 'XTick', 1:n_classes, 'XTickLabel', class_names, 'XTickLabelRotation', 45);
    set(gca, 'YTick', 1:n_classes, 'YTickLabel', class_names);
    xlabel('预测类别');
    ylabel('真实类别');
    title('混淆矩阵');
end

%% 绘制ROC曲线
function plotROCCurve(handles, test_data, elm_model)
    axes(handles.axes_roc);
    
    X_test = test_data.X;
    Y_test = test_data.Y;
    num_classes = elm_model.num_classes;
    
    % 计算隐藏层输出
    H = computeHiddenLayer(X_test, elm_model.input_weights, elm_model.bias, ...
                          elm_model.activation_type);
    outputs = H * elm_model.output_weights;
    
    % 计算每个类别的ROC曲线
    colors = ['r', 'g', 'b', 'm', 'c', 'y', 'k'];
    
    hold off;
    for i = 1:num_classes
        % 获取当前类别的分数
        scores = outputs(:, i);
        
        % 二分类标签
        binary_labels = (Y_test == i);
        
        % 计算ROC曲线
        [X_roc, Y_roc, ~, auc] = perfcurve(binary_labels, scores, true);
        
        color = colors(mod(i-1, length(colors)) + 1);
        plot(X_roc, Y_roc, [color, '-'], 'LineWidth', 2, ...
             'DisplayName', sprintf('%s (AUC=%.3f)', handles.fault_types{i}, auc));
        hold on;
    end
    
    % 绘制对角线
    plot([0, 1], [0, 1], 'k--', 'LineWidth', 1, 'DisplayName', '随机分类器');
    
    xlabel('假正例率');
    ylabel('真正例率');
    title('多分类ROC曲线');
    legend('show', 'Location', 'southeast');
    grid on;
    axis equal;
    xlim([0, 1]);
    ylim([0, 1]);
end

%% 性能分析
function analyzePerformance(~, ~)
    fig = gcbf;
    handles = guidata(fig);
    
    if isempty(handles.elm_model)
        msgbox('请先训练模型!', '警告');
        return;
    end
    
    updateResultDisplay(handles, '正在进行性能分析...');
    
    % 分析不同隐藏节点数的影响
    hidden_nodes_range = [10, 50, 100, 200, 500];
    accuracies = zeros(size(hidden_nodes_range));
    training_times = zeros(size(hidden_nodes_range));
    
    for i = 1:length(hidden_nodes_range)
        hidden_nodes = hidden_nodes_range(i);
        
        tic;
        temp_model = trainELMModel(handles.training_data.X, handles.training_data.Y, ...
                                  hidden_nodes, 1); % 使用sigmoid激活函数
        training_times(i) = toc;
        
        predictions = predictELM(temp_model, handles.testing_data.X);
        accuracies(i) = sum(predictions == handles.testing_data.Y) / ...
                       length(handles.testing_data.Y);
    end
    
    % 绘制性能分析图
    plotPerformanceAnalysis(handles, hidden_nodes_range, accuracies, training_times);
    
    % 显示分析结果
    result_str = sprintf('=== ELM性能分析 ===\n\n');
    result_str = [result_str sprintf('隐藏节点数对性能的影响:\n')];
    for i = 1:length(hidden_nodes_range)
        result_str = [result_str sprintf('  %d节点: 准确率=%.2f%%, 时间=%.2fs\n', ...
                                        hidden_nodes_range(i), accuracies(i)*100, training_times(i))];
    end
    
    [best_accuracy, best_idx] = max(accuracies);
    result_str = [result_str sprintf('\n最佳配置: %d隐藏节点\n', hidden_nodes_range(best_idx))];
    result_str = [result_str sprintf('最佳准确率: %.2f%%\n', best_accuracy * 100)];
    
    set(handles.result_text, 'String', result_str);
    
    msgbox('性能分析完成!', '成功');
end

%% 绘制性能分析图
function plotPerformanceAnalysis(handles, hidden_nodes_range, accuracies, training_times)
    figure('Name', 'ELM性能分析', 'Position', [200, 200, 1000, 600]);
    
    % 子图1: 准确率vs隐藏节点数
    subplot(1, 2, 1);
    plot(hidden_nodes_range, accuracies * 100, 'bo-', 'LineWidth', 2, 'MarkerSize', 8);
    xlabel('隐藏层节点数');
    ylabel('测试准确率 (%)');
    title('隐藏节点数对准确率的影响');
    grid on;
    
    % 标记最佳点
    [best_accuracy, best_idx] = max(accuracies);
    hold on;
    plot(hidden_nodes_range(best_idx), best_accuracy * 100, 'ro', ...
         'MarkerSize', 10, 'MarkerFaceColor', 'red');
    text(hidden_nodes_range(best_idx), best_accuracy * 100, ...
         sprintf('  最佳: %.1f%%', best_accuracy * 100), 'Color', 'red');
    
    % 子图2: 训练时间vs隐藏节点数
    subplot(1, 2, 2);
    plot(hidden_nodes_range, training_times, 'rs-', 'LineWidth', 2, 'MarkerSize', 8);
    xlabel('隐藏层节点数');
    ylabel('训练时间 (秒)');
    title('隐藏节点数对训练时间的影响');
    grid on;
end

%% 实时诊断
function realTimeDiagnosis(~, ~)
    fig = gcbf;
    handles = guidata(fig);
    
    if isempty(handles.elm_model)
        msgbox('请先训练模型!', '警告');
        return;
    end
    
    % 创建实时诊断界面
    createRealtimeDiagnosisGUI(handles);
end

%% 创建实时诊断界面
function createRealtimeDiagnosisGUI(handles)
    diag_fig = figure('Name', '电路故障实时诊断', ...
                     'NumberTitle', 'off', ...
                     'Position', [300, 200, 800, 600], ...
                     'MenuBar', 'none');
    
    % 诊断结果显示
    uicontrol('Style', 'text', 'String', '实时诊断状态:', ...
             'Position', [50, 550, 100, 20], 'FontWeight', 'bold');
    status_text = uicontrol('Style', 'text', 'String', '等待数据...', ...
                           'Position', [160, 550, 200, 20], ...
                           'BackgroundColor', 'white', 'FontSize', 11);
    
    % 故障概率显示
    uicontrol('Style', 'text', 'String', '故障概率分布:', ...
             'Position', [50, 500, 100, 20], 'FontWeight', 'bold');
    
    % 创建概率条
    prob_bars = gobjects(handles.elm_model.num_classes, 1);
    for i = 1:handles.elm_model.num_classes
        uicontrol('Style', 'text', 'String', handles.fault_types{i}, ...
                 'Position', [50, 470 - (i-1)*30, 80, 20]);
        prob_bars(i) = axes('Parent', diag_fig, ...
                           'Position', [140, 470 - (i-1)*30, 200, 20]);
    end
    
    % 控制按钮
    uicontrol('Style', 'pushbutton', 'String', '开始模拟', ...
             'Position', [50, 400, 100, 30], ...
             'Callback', @startSimulation);
    uicontrol('Style', 'pushbutton', 'String', '停止模拟', ...
             'Position', [160, 400, 100, 30], ...
             'Callback', @stopSimulation);
    
    % 存储诊断界面数据
    diag_handles = guidata(diag_fig);
    diag_handles.elm_model = handles.elm_model;
    diag_handles.fault_types = handles.fault_types;
    diag_handles.status_text = status_text;
    diag_handles.prob_bars = prob_bars;
    diag_handles.is_running = false;
    diag_handles.timer = [];
    
    guidata(diag_fig, diag_handles);
end

%% 开始模拟
function startSimulation(~, ~)
    fig = gcbf;
    handles = guidata(fig);
    
    if handles.is_running
        return;
    end
    
    handles.is_running = true;
    guidata(fig, handles);
    
    set(handles.status_text, 'String', '实时诊断中...', 'BackgroundColor', [0.8, 1, 0.8]);
    
    % 创建定时器进行实时诊断
    handles.timer = timer('ExecutionMode', 'fixedRate', ...
                         'Period', 2.0, ... % 每2秒更新一次
                         'TimerFcn', @(~,~) updateDiagnosis(fig));
    start(handles.timer);
    
    guidata(fig, handles);
end

%% 停止模拟
function stopSimulation(~, ~)
    fig = gcbf;
    handles = guidata(fig);
    
    if ~isempty(handles.timer)
        stop(handles.timer);
        delete(handles.timer);
        handles.timer = [];
    end
    
    handles.is_running = false;
    set(handles.status_text, 'String', '诊断已停止', 'BackgroundColor', [1, 0.8, 0.8]);
    
    guidata(fig, handles);
end

%% 更新诊断显示
function updateDiagnosis(fig)
    handles = guidata(fig);
    
    % 生成模拟实时数据
    [real_time_data, true_fault] = generateRealtimeData(handles.elm_model);
    
    % 进行故障诊断
    [predicted_fault, probabilities] = diagnoseFault(handles.elm_model, real_time_data);
    
    % 更新显示
    if predicted_fault == true_fault
        status_color = [0.8, 1, 0.8]; % 绿色 - 正确诊断
        status_msg = sprintf('诊断正确: %s', handles.fault_types{predicted_fault});
    else
        status_color = [1, 0.8, 0.8]; % 红色 - 错误诊断
        status_msg = sprintf('诊断错误: %s (应为%s)', ...
                            handles.fault_types{predicted_fault}, handles.fault_types{true_fault});
    end
    
    set(handles.status_text, 'String', status_msg, 'BackgroundColor', status_color);
    
    % 更新概率条
    for i = 1:length(probabilities)
        prob_bar = handles.prob_bars(i);
        cla(prob_bar);
        
        barh(prob_bar, probabilities(i), 'FaceColor', [0.3, 0.6, 0.9], 'EdgeColor', 'blue');
        xlim(prob_bar, [0, 1]);
        ylim(prob_bar, [0, 1]);
        set(prob_bar, 'XTick', [], 'YTick', []);
        
        % 添加概率文本
        text(prob_bar, probabilities(i)/2, 0.5, sprintf('%.1f%%', probabilities(i)*100), ...
             'HorizontalAlignment', 'center', 'FontWeight', 'bold');
    end
    
    drawnow;
end

%% 生成实时数据
function [real_time_data, true_fault] = generateRealtimeData(elm_model)
    % 随机选择一种故障类型
    true_fault = randi(elm_model.num_classes);
    
    % 生成该故障类型的模拟数据
    num_features = size(elm_model.input_weights, 2);
    base_features = generateNormalFeatures(1, num_features);
    real_time_data = addFaultPattern(base_features, true_fault, elm_model.num_classes);
    
    % 添加实时噪声
    real_time_data = real_time_data + 0.1 * randn(size(real_time_data));
end

%% 故障诊断
function [predicted_fault, probabilities] = diagnoseFault(elm_model, data)
    % 计算隐藏层输出
    H = computeHiddenLayer(data, elm_model.input_weights, elm_model.bias, ...
                          elm_model.activation_type);
    
    % 计算输出层
    outputs = H * elm_model.output_weights;
    
    % 转换为概率 (softmax)
    probabilities = exp(outputs) ./ sum(exp(outputs));
    probabilities = probabilities(:)'; % 转换为行向量
    
    % 预测故障类型
    [~, predicted_fault] = max(probabilities);
end

%% 更新结果显示
function updateResultDisplay(handles, message)
    current_text = get(handles.result_text, 'String');
    if ischar(current_text)
        new_text = sprintf('%s\n%s', current_text, message);
    else
        new_text = message;
    end
    set(handles.result_text, 'String', new_text);
    drawnow;
end

%% 运行主程序
main_circuit_fault_elm();

系统特点与功能

主要功能

  1. 完整的电路故障诊断流程

    • 故障数据生成与模拟
    • ELM模型训练与优化
    • 实时故障诊断
    • 性能评估分析
  2. 多种故障模式支持

    • 正常状态
    • 短路故障
    • 开路故障
    • 元件老化
    • 噪声干扰
  3. 先进的ELM算法

    • 多种激活函数选择
    • 自适应隐藏层节点
    • 正则化优化

极限学习机理论基础

ELM算法优势

  • 训练速度快:单次矩阵运算完成训练
  • 泛化能力强:随机特征映射增强多样性
  • 避免局部最优:无需迭代优化

数学模型

隐藏层输出: H = g(XW + b)
输出权重: β = (HᵀH + λI)⁻¹HᵀY
预测: Y_pred = Hβ

核心算法实现

ELM训练过程

function elm_model = trainELMModel(X, Y, hidden_nodes, activation_type)
    % 随机初始化权重和偏置
    input_weights = randn(hidden_nodes, num_features);
    bias = randn(hidden_nodes, 1);
    
    % 计算隐藏层输出
    H = computeHiddenLayer(X, input_weights, bias, activation_type);
    
    % 正则化最小二乘求解
    output_weights = (H'*H + eye(size(H,2))/C) \ (H'*Y_onehot);
end

实时诊断机制

function [predicted_fault, probabilities] = diagnoseFault(elm_model, data)
    H = computeHiddenLayer(data, elm_model.input_weights, elm_model.bias);
    outputs = H * elm_model.output_weights;
    probabilities = softmax(outputs);
    [~, predicted_fault] = max(probabilities);
end

参考代码 实现电路的不同故障模式进行分类,极限学习机 www.3dddown.com/cna/78753.html

性能指标

系统提供全面的性能评估:

  1. 分类准确率:总体和各类别准确率
  2. 混淆矩阵:可视化分类结果
  3. ROC曲线:多分类性能分析
  4. 特征重要性:识别关键故障特征

使用指南

  1. 数据生成

    • 设置故障类型数量
    • 生成模拟电路故障数据
    • 查看数据分布特征
  2. 模型训练

    • 选择隐藏层节点数
    • 选择激活函数类型
    • 监控训练过程
  3. 性能测试

    • 测试集分类准确率
    • 混淆矩阵分析
    • ROC曲线评估
  4. 实时诊断

    • 启动实时模拟
    • 查看故障概率分布
    • 监控诊断准确性

应用场景

这个系统适用于:

  1. 工业自动化

    • 生产线电路故障检测
    • 预防性维护
    • 质量控制
  2. 电力系统

    • 电网故障诊断
    • 变压器状态监测
    • 配电系统保护
  3. 电子制造

    • PCB板测试
    • 元器件故障检测
    • 产品质量分类
  4. 科研教育

    • 故障诊断算法研究
    • 机器学习教学
    • 电路分析实验

扩展功能

系统还支持以下高级功能:

  1. 自适应参数优化

    • 自动选择最佳隐藏节点数
    • 交叉验证调参
    • 早停法防止过拟合
  2. 多传感器融合

    • 结合电压、电流、温度等多源数据
    • 特征级和决策级融合
    • 提高诊断可靠性
  3. 在线学习

    • 增量式模型更新
    • 适应电路老化变化
    • 持续性能改进
posted @ 2025-12-16 10:48  令小飞  阅读(7)  评论(0)    收藏  举报