运行出现“function signals = generate_pqd_signals(num_samples, fs, N) ↑ 错误: 函数定义在此上下文中不受支持。函数只能作为代码文件中的局部函数或嵌套函数创建。”请帮我修正后发送完整代码
时间: 2025-08-03 10:59:24 浏览: 3
<think>我们注意到用户要求提供完整的可运行代码,并且之前遇到了函数定义错误。在MATLAB中,函数定义必须放在独立的.m文件中,或者在脚本的末尾(MATLAB R2016b及以上版本支持局部函数)。为了确保代码可运行,我们将采用以下结构:
1. 主脚本:包含数据生成、处理、网络训练和评估的流程。
2. 将生成PQD信号的函数和快速S变换函数作为局部函数放在主脚本末尾(适用于MATLAB R2016b及以上版本)。
如果用户使用的是较早版本的MATLAB,需要将函数单独保存为.m文件。但为了方便,我们在同一个脚本中提供局部函数。
步骤:
1. 生成100个PQD电压暂升信号(含正常信号作为负样本,共200个样本,正负各半)。
2. 对每个信号计算分段改进快速S变换时频图。
3. 划分数据集(训练集160,验证集20,测试集20)。
4. 构建双分支神经网络:1D CNN分支处理时序信号,2D CNN分支处理时频图,然后特征融合,全连接层和Softmax分类。
5. 训练网络,使用验证集监控,保存最佳模型。
6. 在测试集上评估。
注意:由于计算时频图比较耗时,我们使用分段S变换以提高效率。
代码结构:
- 主程序
- 局部函数:
generatePQDSignal: 生成单个PQD电压暂升信号(含正常信号)
generateNormalSignal: 生成正常信号(也可以合并到generatePQDSignal中通过参数控制)
fastST: 分段改进快速S变换
由于样本数不多,我们可以在一个循环中生成所有样本。
另外,为了平衡数据集,我们将生成100个暂升信号和100个正常信号,共200个样本。
修改计划:
1. 生成100个暂升信号(正样本)和100个正常信号(负样本)。
2. 为每个信号生成时频图(160x640,频率轴321点,因为N=640,频率点数为N/2+1=321)。
3. 构建网络:输入为1x640(信号)和321x640(时频图,单通道灰度图)。
注意:在构建网络时,时频图输入为[321,640,1],即高度(频率)321,宽度(时间)640,通道数1。
由于训练数据量不大,我们使用较小的网络结构以防止过拟合。
我们按照用户要求,设置采样频率3200Hz,采样点数640(即0.2秒)。
代码实现:</think>以下是一个完整的MATLAB解决方案,包含PQD信号生成、时频图生成、神经网络建模和评估的全流程代码:
```matlab
%% 主程序:PQD信号生成与时频图处理
clear; clc; close all;
% 参数设置
fs = 3200; % 采样频率(Hz)
N = 640; % 采样点数
num_samples = 100; % 总样本数
f0 = 50; % 基波频率(Hz)
t = (0:N-1)/fs; % 时间向量
% 生成PQD电压暂升信号
signals = zeros(num_samples, N);
for i = 1:num_samples
% 随机生成扰动参数
alpha = 0.1 + 0.8*rand(); % 暂升幅度(0.1~0.9pu)
t1 = 0.04 + 0.12*rand(); % 起始时间(0.04~0.16s)
duration = 0.01 + 0.03*rand(); % 持续时间(0.01~0.04s)
t2 = min(t1 + duration, 0.19);
% 生成基波信号
base_wave = sin(2*pi*f0*t);
% 添加电压暂升
disturbance = alpha * (t >= t1 & t < t2);
signal = (1 + disturbance) .* base_wave;
% 添加噪声(SNR=30dB)
noise = 0.01*randn(size(signal));
signals(i, :) = signal + noise;
end
% 生成正常信号作为负样本
normal_signals = zeros(num_samples, N);
for i = 1:num_samples
normal_signals(i, :) = sin(2*pi*f0*t) + 0.01*randn(size(t));
end
% 生成时频图数据集
tfr_dataset = zeros(num_samples, 321, 640); % 时频图维度
for i = 1:num_samples
tfr_dataset(i, :, :) = fastST(signals(i, :), fs);
end
% 生成正常信号的时频图
normal_tfr = zeros(num_samples, 321, 640);
for i = 1:num_samples
normal_tfr(i, :, :) = fastST(normal_signals(i, :), fs);
end
% 创建标签:1=电压暂升, 0=正常信号
labels = [ones(num_samples, 1); zeros(num_samples, 1)];
% 合并数据集
all_signals = [signals; normal_signals];
all_tfr = cat(1, tfr_dataset, normal_tfr);
% 划分数据集(8:1:1)
rng(42); % 固定随机种子
total_samples = 2*num_samples;
indices = randperm(total_samples);
train_idx = indices(1:round(0.8*total_samples));
val_idx = indices(round(0.8*total_samples)+1:round(0.9*total_samples));
test_idx = indices(round(0.9*total_samples)+1:end);
% 准备训练数据
train_signals = all_signals(train_idx, :);
train_tfr = all_tfr(train_idx, :, :);
train_labels = categorical(labels(train_idx));
% 准备验证数据
val_signals = all_signals(val_idx, :);
val_tfr = all_tfr(val_idx, :, :);
val_labels = categorical(labels(val_idx));
% 准备测试数据
test_signals = all_signals(test_idx, :);
test_tfr = all_tfr(test_idx, :, :);
test_labels = categorical(labels(test_idx));
%% 构建双分支神经网络
% 分支1: 1D CNN处理时序信号
input1 = imageInputLayer([1, N], 'Name', 'signal_input', 'Normalization', 'zscore');
conv1 = convolution1dLayer(3, 32, 'Padding', 'same', 'Name', 'conv1');
bn1 = batchNormalizationLayer('Name', 'bn1');
relu1 = reluLayer('Name', 'relu1');
pool1 = maxPooling1dLayer(2, 'Stride', 2, 'Name', 'pool1');
conv2 = convolution1dLayer(3, 64, 'Padding', 'same', 'Name', 'conv2');
bn2 = batchNormalizationLayer('Name', 'bn2');
relu2 = reluLayer('Name', 'relu2');
pool2 = maxPooling1dLayer(2, 'Stride', 2, 'Name', 'pool2');
% 分支2: 2D CNN处理时频图
input2 = imageInputLayer([321, N, 1], 'Name', 'tfr_input', 'Normalization', 'zscore');
conv2d1 = convolution2dLayer(3, 32, 'Padding', 'same', 'Name', 'conv2d1');
bn2d1 = batchNormalizationLayer('Name', 'bn2d1');
relu2d1 = reluLayer('Name', 'relu2d1');
pool2d1 = maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool2d1');
conv2d2 = convolution2dLayer(3, 64, 'Padding', 'same', 'Name', 'conv2d2');
bn2d2 = batchNormalizationLayer('Name', 'bn2d2');
relu2d2 = reluLayer('Name', 'relu2d2');
pool2d2 = maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool2d2');
% 特征融合
concat = concatenationLayer(3, 2, 'Name', 'concat');
% 公共分类层
fc1 = fullyConnectedLayer(128, 'Name', 'fc1');
relu3 = reluLayer('Name', 'relu3');
dropout = dropoutLayer(0.5, 'Name', 'dropout');
soft_threshold = functionLayer(@softThreshold, 'Name', 'soft_threshold');
fc2 = fullyConnectedLayer(2, 'Name', 'fc2');
softmax = softmaxLayer('Name', 'softmax');
output = classificationLayer('Name', 'output');
% 组装网络
lgraph = layerGraph();
% 添加分支1
lgraph = addLayers(lgraph, input1);
lgraph = addLayers(lgraph, conv1);
lgraph = addLayers(lgraph, bn1);
lgraph = addLayers(lgraph, relu1);
lgraph = addLayers(lgraph, pool1);
lgraph = addLayers(lgraph, conv2);
lgraph = addLayers(lgraph, bn2);
lgraph = addLayers(lgraph, relu2);
lgraph = addLayers(lgraph, pool2);
lgraph = addLayers(lgraph, flattenLayer('Name', 'flatten1'));
% 添加分支2
lgraph = addLayers(lgraph, input2);
lgraph = addLayers(lgraph, conv2d1);
lgraph = addLayers(lgraph, bn2d1);
lgraph = addLayers(lgraph, relu2d1);
lgraph = addLayers(lgraph, pool2d1);
lgraph = addLayers(lgraph, conv2d2);
lgraph = addLayers(lgraph, bn2d2);
lgraph = addLayers(lgraph, relu2d2);
lgraph = addLayers(lgraph, pool2d2);
lgraph = addLayers(lgraph, flattenLayer('Name', 'flatten2'));
% 添加融合层和分类层
lgraph = addLayers(lgraph, concat);
lgraph = addLayers(lgraph, fc1);
lgraph = addLayers(lgraph, relu3);
lgraph = addLayers(lgraph, dropout);
lgraph = addLayers(lgraph, soft_threshold);
lgraph = addLayers(lgraph, fc2);
lgraph = addLayers(lgraph, softmax);
lgraph = addLayers(lgraph, output);
% 连接分支
lgraph = connectLayers(lgraph, 'signal_input', 'conv1');
lgraph = connectLayers(lgraph, 'conv1', 'bn1');
lgraph = connectLayers(lgraph, 'bn1', 'relu1');
lgraph = connectLayers(lgraph, 'relu1', 'pool1');
lgraph = connectLayers(lgraph, 'pool1', 'conv2');
lgraph = connectLayers(lgraph, 'conv2', 'bn2');
lgraph = connectLayers(lgraph, 'bn2', 'relu2');
lgraph = connectLayers(lgraph, 'relu2', 'pool2');
lgraph = connectLayers(lgraph, 'pool2', 'flatten1');
lgraph = connectLayers(lgraph, 'tfr_input', 'conv2d1');
lgraph = connectLayers(lgraph, 'conv2d1', 'bn2d1');
lgraph = connectLayers(lgraph, 'bn2d1', 'relu2d1');
lgraph = connectLayers(lgraph, 'relu2d1', 'pool2d1');
lgraph = connectLayers(lgraph, 'pool2d1', 'conv2d2');
lgraph = connectLayers(lgraph, 'conv2d2', 'bn2d2');
lgraph = connectLayers(lgraph, 'bn2d2', 'relu2d2');
lgraph = connectLayers(lgraph, 'relu2d2', 'pool2d2');
lgraph = connectLayers(lgraph, 'pool2d2', 'flatten2');
% 连接融合层
lgraph = connectLayers(lgraph, 'flatten1', 'concat/in1');
lgraph = connectLayers(lgraph, 'flatten2', 'concat/in2');
lgraph = connectLayers(lgraph, 'concat', 'fc1');
lgraph = connectLayers(lgraph, 'fc1', 'relu3');
lgraph = connectLayers(lgraph, 'relu3', 'dropout');
lgraph = connectLayers(lgraph, 'dropout', 'soft_threshold');
lgraph = connectLayers(lgraph, 'soft_threshold', 'fc2');
lgraph = connectLayers(lgraph, 'fc2', 'softmax');
lgraph = connectLayers(lgraph, 'softmax', 'output');
% 显示网络结构
analyzeNetwork(lgraph)
%% 训练网络
options = trainingOptions('adam', ...
'MaxEpochs', 50, ...
'MiniBatchSize', 16, ...
'ValidationData', {{reshape(val_signals', [1, N, 1, numel(val_idx)]), val_tfr}, val_labels}, ...
'ValidationFrequency', 30, ...
'Verbose', true, ...
'Plots', 'training-progress', ...
'ExecutionEnvironment', 'auto', ...
'OutputNetwork', 'best-validation-loss');
% 训练网络
net = trainNetwork({reshape(train_signals', [1, N, 1, numel(train_idx)]), train_tfr}, ...
train_labels, lgraph, options);
%% 评估模型
% 测试集预测
test_signals_input = reshape(test_signals', [1, N, 1, numel(test_idx)]);
[pred_labels, scores] = classify(net, {test_signals_input, test_tfr});
% 计算准确率
accuracy = sum(pred_labels == test_labels) / numel(test_labels);
fprintf('测试集准确率: %.2f%%\n', accuracy*100);
% 混淆矩阵
figure
confusionchart(test_labels, pred_labels);
title('混淆矩阵');
% 计算其他指标
confMat = confusionmat(test_labels, pred_labels);
TP = confMat(2,2);
TN = confMat(1,1);
FP = confMat(1,2);
FN = confMat(2,1);
precision = TP/(TP+FP);
recall = TP/(TP+FN);
f1_score = 2*(precision*recall)/(precision+recall);
fprintf('精确率: %.2f%%\n', precision*100);
fprintf('召回率: %.2f%%\n', recall*100);
fprintf('F1分数: %.2f%%\n', f1_score*100);
%% 辅助函数定义
function tfr = fastST(signal, fs)
% 分段改进快速S变换
N = length(signal);
f = (0:N/2)*(fs/N); % 频率向量
% 分段计算(每段128点)
segment_length = 128;
num_segments = ceil(N/segment_length);
tfr = zeros(length(f), N);
for seg = 1:num_segments
start_idx = (seg-1)*segment_length + 1;
end_idx = min(seg*segment_length, N);
segment = signal(start_idx:end_idx);
seg_len = length(segment);
% 对分段进行S变换
for k = 1:length(f)
if f(k) > 0
% 构造高斯窗
window = (f(k)/sqrt(2*pi)) * exp(-(f(k)^2 * (-floor(seg_len/2):floor(seg_len/2)-1).^2)/(2*fs^2));
window = window(1:seg_len);
% 卷积计算
conv_result = conv(segment, window, 'same');
tfr(k, start_idx:end_idx) = abs(conv_result);
end
end
end
% 归一化处理
tfr = tfr/max(tfr(:));
end
function Y = softThreshold(X)
% 软阈值去噪函数
threshold = 0.1; % 阈值参数
Y = sign(X).*max(0, abs(X) - threshold);
end
```
### 关键功能说明
1. **PQD信号生成**:
- 使用$v(t) = [1 + \alpha \cdot u(t-t_1) - u(t-t_2)] \cdot \sin(2\pi f t) + n(t)$模型
- 参数随机化:$\alpha \in [0.1,0.9]$,$t_1 \in [0.04,0.16]$s,持续时间$ \in [0.01,0.04]$s
- 添加30dB高斯白噪声$n(t)$
2. **分段改进S变换**:
```matlab
function tfr = fastST(signal, fs)
% 分段计算提高效率
for seg = 1:num_segments
% 构造高斯窗:$w(t,f) = \frac{|f|}{\sqrt{2\pi}} e^{-\frac{t^2 f^2}{2}}$
window = (f(k)/sqrt(2*pi)) * exp(-(f(k)^2 * ... )/(2*fs^2));
% 卷积计算:$S(\tau,f) = \int h(t) w(\tau-t,f) e^{-i2\pi ft} dt$
conv_result = conv(segment, window, 'same');
end
end
```
3. **双分支神经网络**:
- **时序分支**:1D CNN提取时间特征
- **频域分支**:2D CNN提取时频特征
- **特征融合**:连接两个分支的特征向量
- **软阈值去噪**:`functionLayer(@softThreshold)`实现
```matlab
function Y = softThreshold(X)
threshold = 0.1;
Y = sign(X).*max(0, abs(X) - threshold); % 软阈值函数
end
```
4. **模型训练与评估**:
- 使用Adam优化器
- 监控训练损失和验证准确率
- 保存最佳验证性能的模型
- 计算准确率、精确率、召回率和F1分数
### 使用说明
1. **运行要求**:
- MATLAB R2018b或更高版本
- Deep Learning Toolbox
- Signal Processing Toolbox
2. **执行流程**:
- 运行主程序生成数据集
- 网络自动训练并保存最佳模型
- 在测试集上评估性能指标
- 结果包含混淆矩阵和分类指标
3. **参数调整**:
- 修改`MaxEpochs`和`MiniBatchSize`控制训练时间
- 调整`threshold`参数优化软阈值去噪效果
- 修改网络层数和通道数优化模型容量
> 此方案完整实现了电压暂升信号的生成、时频特征提取和双分支神经网络分类的全流程。分段S变换策略提高了计算效率[^4],软阈值去噪增强了特征鲁棒性[^1],双分支结构有效融合了时序和频域特征[^3]。
阅读全文
相关推荐
















