用Python和Matlab搞定东南大学齿轮箱数据集:从CSV读取到特征提取的保姆级教程
当你第一次打开东南大学齿轮箱数据集时,可能会被复杂的CSV文件结构和多通道信号搞得一头雾水。作为工程领域常用的基准数据集,它包含了齿轮和轴承的多种故障类型,但原始数据的配置信息和8通道信号对齐问题常常让初学者无从下手。本文将手把手带你用Python和Matlab两种工具链,从数据读取到特征提取,构建完整的数据处理流水线。
1. 数据集解析与准备工作
在开始写代码之前,我们需要先理解数据集的组成结构。下载解压后,你会发现两个主要文件夹:gearset(齿轮数据集)和bearingset(轴承数据集),每个文件夹下又包含不同故障类型的CSV文件。
每个CSV文件都包含两部分内容:
- 开头的配置信息(行数不固定)
- 实际的8通道振动信号数据
关键挑战在于:
- 配置信息行数不固定,无法直接跳过固定行数读取
- 8个通道需要正确对齐并理解其物理意义
- 不同故障类型需要建立统一的处理流程
提示:建议在处理前先手动查看几个CSV文件,了解配置信息的格式和位置,这对后续编写解析代码很有帮助。
2. Python数据处理全流程
Python凭借其丰富的数据科学生态系统,成为处理此类工程数据的利器。我们将使用Pandas和NumPy这两个核心库。
2.1 智能读取CSV文件
传统pd.read_csv()无法直接处理这种含配置信息的特殊CSV,我们需要更智能的读取方式:
import pandas as pd import numpy as np def read_gear_csv(filepath): # 先找到数据开始的行号 with open(filepath, 'r') as f: lines = f.readlines() data_start = 0 for i, line in enumerate(lines): if line.startswith(('0,', '0.')): # 数据行通常以0开头 data_start = i break # 读取数据部分 df = pd.read_csv(filepath, header=None, skiprows=data_start) return df # 示例用法 file_path = 'gearset/Health_working_state_20Hz_0V.csv' data_df = read_gear_csv(file_path)2.2 通道对齐与重命名
原始数据的8个通道需要正确命名以便后续分析:
def process_channels(df): # 定义通道名称 channel_names = [ 'motor_vibration', 'planetary_gear_x', 'planetary_gear_y', 'planetary_gear_z', 'motor_torque', 'reducer_x', 'reducer_y', 'reducer_z' ] # 重命名列 df.columns = channel_names # 添加时间戳列(采样率5120Hz) df['timestamp'] = np.arange(len(df)) / 5120.0 return df processed_df = process_channels(data_df)2.3 特征提取实战
时域和频域特征是故障诊断的基础。下面是一些常用特征的提取方法:
from scipy import stats from scipy.fft import fft def extract_features(signal): features = {} # 时域特征 features['mean'] = np.mean(signal) features['std'] = np.std(signal) features['kurtosis'] = stats.kurtosis(signal) features['skewness'] = stats.skew(signal) features['peak'] = np.max(np.abs(signal)) # 频域特征 fft_vals = np.abs(fft(signal)) features['dominant_freq'] = np.argmax(fft_vals) features['spectral_energy'] = np.sum(fft_vals**2) return features # 对每个通道提取特征 channel_features = {} for channel in processed_df.columns[:8]: # 前8列是信号数据 channel_features[channel] = extract_features(processed_df[channel])3. Matlab数据处理全流程
对于习惯使用Matlab的工程师,我们同样提供完整的解决方案。
3.1 灵活读取CSV文件
Matlab的readtable函数可以更灵活地处理含配置信息的CSV:
function data = readGearCSV(filename) % 读取整个文件内容 fid = fopen(filename); lines = {}; tline = fgetl(fid); while ischar(tline) lines{end+1} = tline; tline = fgetl(fid); end fclose(fid); % 找到数据开始行 dataStart = 1; for i = 1:length(lines) if startsWith(lines{i}, '0,') || startsWith(lines{i}, '0.') dataStart = i; break; end end % 读取数据部分 data = readtable(filename, 'HeaderLines', dataStart-1, 'ReadVariableNames', false); end3.2 数据处理与可视化
Matlab在信号处理和可视化方面有其独特优势:
% 通道重命名 data.Properties.VariableNames = { 'motor_vibration', 'planetary_gear_x', 'planetary_gear_y', 'planetary_gear_z', 'motor_torque', 'reducer_x', 'reducer_y', 'reducer_z' }; % 添加时间戳 fs = 5120; % 采样频率 data.timestamp = (0:height(data)-1)' / fs; % 绘制时域波形 figure; subplot(2,1,1); plot(data.timestamp, data.motor_vibration); title('电机振动信号时域波形'); xlabel('时间(s)'); ylabel('幅值'); % 计算并绘制频谱 subplot(2,1,2); L = height(data); Y = fft(data.motor_vibration); P2 = abs(Y/L); P1 = P2(1:L/2+1); P1(2:end-1) = 2*P1(2:end-1); f = fs*(0:(L/2))/L; plot(f,P1); title('电机振动信号频谱'); xlabel('频率(Hz)'); ylabel('幅值');4. 高级特征工程与批处理
无论是Python还是Matlab,处理整个数据集都需要建立批处理流程。
4.1 Python批处理实现
import os from tqdm import tqdm def process_dataset(folder_path): all_features = [] file_labels = [] for filename in tqdm(os.listdir(folder_path)): if filename.endswith('.csv'): # 提取故障类型标签 label = filename.split('_')[0] # 读取和处理数据 filepath = os.path.join(folder_path, filename) df = read_gear_csv(filepath) processed_df = process_channels(df) # 提取特征 features = {} for channel in processed_df.columns[:8]: features[channel] = extract_features(processed_df[channel]) all_features.append(features) file_labels.append(label) return all_features, file_labels # 处理整个齿轮数据集 gear_features, gear_labels = process_dataset('gearset')4.2 Matlab批处理实现
function [features, labels] = processDataset(folder) files = dir(fullfile(folder, '*.csv')); features = cell(length(files), 1); labels = cell(length(files), 1); for i = 1:length(files) % 提取标签 filename = files(i).name; parts = strsplit(filename, '_'); labels{i} = parts{1}; % 读取数据 filepath = fullfile(folder, filename); data = readGearCSV(filepath); % 提取特征 featureStruct = struct(); channelNames = data.Properties.VariableNames(1:8); for j = 1:length(channelNames) signal = data.(channelNames{j}); featureStruct.(channelNames{j}) = extractFeatures(signal); end features{i} = featureStruct; end end function features = extractFeatures(signal) features = struct(); % 时域特征 features.mean = mean(signal); features.std = std(signal); features.kurtosis = kurtosis(signal); features.skewness = skewness(signal); features.peak = max(abs(signal)); % 频域特征 L = length(signal); Y = fft(signal); P2 = abs(Y/L); P1 = P2(1:L/2+1); P1(2:end-1) = 2*P1(2:end-1); [~, idx] = max(P1); features.dominant_freq = idx - 1; % MATLAB索引从1开始 features.spectral_energy = sum(P1.^2); end5. 数据可视化与异常检测
高质量的可视化能帮助我们直观理解数据特征和潜在问题。
5.1 Python可视化示例
import matplotlib.pyplot as plt def plot_comparison(healthy_df, faulty_df, channel='planetary_gear_x'): fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8)) # 时域波形对比 ax1.plot(healthy_df['timestamp'], healthy_df[channel], label='健康状态') ax1.plot(faulty_df['timestamp'], faulty_df[channel], label='故障状态', alpha=0.7) ax1.set_title(f'{channel}时域波形对比') ax1.set_xlabel('时间(s)') ax1.set_ylabel('幅值') ax1.legend() # 频谱对比 def compute_spectrum(signal): fft_vals = np.abs(fft(signal)) freq = np.fft.fftfreq(len(signal), 1/5120) return freq[:len(freq)//2], fft_vals[:len(fft_vals)//2] freq_h, spec_h = compute_spectrum(healthy_df[channel]) freq_f, spec_f = compute_spectrum(faulty_df[channel]) ax2.semilogy(freq_h, spec_h, label='健康状态') ax2.semilogy(freq_f, spec_f, label='故障状态', alpha=0.7) ax2.set_title(f'{channel}频谱对比') ax2.set_xlabel('频率(Hz)') ax2.set_ylabel('幅值(log)') ax2.legend() plt.tight_layout() plt.show() # 示例使用 healthy_df = read_gear_csv('gearset/Health_working_state_20Hz_0V.csv') faulty_df = read_gear_csv('gearset/Chipped_tooth_20Hz_0V.csv') plot_comparison(healthy_df, faulty_df)5.2 特征空间可视化
将提取的特征降维可视化可以帮助我们评估特征的有效性:
from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler def visualize_features(features_list, labels): # 将特征转换为二维数组 X = [] for features in features_list: # 展平所有通道特征 flat_features = [] for channel in features.values(): flat_features.extend(list(channel.values())) X.append(flat_features) X = np.array(X) # 标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # PCA降维 pca = PCA(n_components=2) X_pca = pca.fit_transform(X_scaled) # 可视化 plt.figure(figsize=(10, 8)) for label in set(labels): idx = [i for i, l in enumerate(labels) if l == label] plt.scatter(X_pca[idx, 0], X_pca[idx, 1], label=label) plt.title('特征空间PCA可视化') plt.xlabel('主成分1') plt.ylabel('主成分2') plt.legend() plt.show() # 示例使用 visualize_features(gear_features, gear_labels)6. 性能优化与实用技巧
处理大型数据集时,性能优化至关重要。以下是几个实用技巧:
Python性能优化:
- 使用
dask库处理超出内存的大型CSV文件 - 对批处理使用多进程加速:
from multiprocessing import Pool def process_file(filename): # 处理单个文件的代码 pass with Pool(processes=4) as pool: results = pool.map(process_file, file_list) - 使用
parquet格式存储中间结果,节省空间和IO时间
Matlab性能优化:
- 预分配数组空间避免动态扩容
- 使用
parfor替代for循环实现并行计算 - 将频繁使用的代码编译为MEX文件
注意:无论使用哪种工具,都建议在处理前先对数据进行抽样检查,确保处理逻辑正确后再进行全量处理,避免浪费计算资源。
常见问题解决方案:
配置信息行数不一致:
- 解决方案:使用本文提供的智能检测方法,而非固定行数跳过
内存不足:
- Python:使用
chunksize参数分块读取 - Matlab:使用
datastore处理大型文件
- Python:使用
特征提取耗时:
- 对每个文件只提取必要特征
- 考虑使用更高效的特征提取库如
tsfresh
数据不平衡:
- 不同故障类型样本数可能不均
- 解决方法:在后续建模时使用类别权重或过采样技术