如何合并CIC DDoS 2019数据集并训练IDS深度学习模型?
解决CIC DDoS 2019数据集合并与IDS模型训练方案
一、先搞定数据集合并问题
1. 排查合并失败的核心原因
合并CIC DDoS 2019的7个CSV常踩的坑:
- 列名不统一:不同文件的列名可能大小写、空格、字段数量不一致,比如有的叫
Flow Duration,有的是flow_duration,甚至少了个别特征列。 - 数据类型冲突:同一列在不同文件里类型不一样,比如某列在A文件是整数,B文件存成了字符串,合并时直接报错。
- 编码问题:部分CSV用了非UTF-8编码(比如latin-1),读取时乱码导致合并失败。
- 空值格式混乱:有的文件用
NaN标记空值,有的用NULL或空字符串,系统无法识别统一标记。
2. 分步合并操作(用Python Pandas实现)
第一步:写预处理函数统一处理单个文件
import pandas as pd import glob def preprocess_csv(file_path): # 读取文件,编码报错就换'latin-1'试试 df = pd.read_csv(file_path, encoding='utf-8', low_memory=False) # 统一列名:全转小写,空格换下划线 df.columns = [col.lower().replace(' ', '_') for col in df.columns] # 统一数据类型:把流量时长列转成数值型,转失败的设为NaN if 'flow_duration' in df.columns: df['flow_duration'] = pd.to_numeric(df['flow_duration'], errors='coerce') # 统一空值标记:把所有空的、'NULL'都转成NaN df = df.replace(['NULL', ''], pd.NA) return df # 替换成你的实际文件路径 file_paths = glob.glob('/your/path/to/cic_ddos_2019/*.csv')
第二步:批量处理+合并
processed_dfs = [] for path in file_paths: try: df = preprocess_csv(path) processed_dfs.append(df) print(f"处理完成:{path}") except Exception as e: print(f"处理{path}出错:{str(e)}") # 合并时只保留所有文件都有的列,避免列不匹配 merged_cic_df = pd.concat(processed_dfs, axis=0, join='inner', ignore_index=True) # 合并你自己的两个DDoS数据集,同样用预处理函数处理 your_df1 = preprocess_csv('/your/path/your_dataset1.csv') your_df2 = preprocess_csv('/your/path/your_dataset2.csv') final_dataset = pd.concat([merged_cic_df, your_df1, your_df2], axis=0, ignore_index=True)
第三步:合并后清洗收尾
- 删除重复行:
final_dataset = final_dataset.drop_duplicates() - 处理空值:要么删缺失值过多的行,要么填充:
# 删除缺失值超过90%的行 final_dataset = final_dataset.dropna(thresh=int(len(final_dataset)*0.9)) # 数值列用中位数填充 num_cols = final_dataset.select_dtypes(include=['int64', 'float64']).columns final_dataset[num_cols] = final_dataset[num_cols].fillna(final_dataset[num_cols].median()) - 统一标签:把所有攻击类型标为
ddos,正常流量标为benign:# 假设标签列是'label',根据实际列名调整 final_dataset['label'] = final_dataset['label'].apply(lambda x: 'ddos' if x != 'BENIGN' else 'benign')
二、基于合并后的数据集训练IDS深度学习模型
1. 训练前的数据预处理
- 筛选有效特征:删掉无关特征(比如
timestamp如果不用时序)、高度相关的特征(相关系数>0.9的留一个即可) - 标准化特征:将数值特征缩放到均值0、方差1:
from sklearn.preprocessing import StandardScaler num_features = final_dataset.select_dtypes(include=['int64', 'float64']).tolist() num_features.remove('label') # 排除标签列 scaler = StandardScaler() final_dataset[num_features] = scaler.fit_transform(final_dataset[num_features]) - 标签转数值:把分类标签转成模型可识别的数值:
from sklearn.preprocessing import LabelEncoder le = LabelEncoder() final_dataset['label'] = le.fit_transform(final_dataset['label']) - 划分训练/测试集:
from sklearn.model_selection import train_test_split X = final_dataset.drop('label', axis=1) y = final_dataset['label'] # 分层抽样,保证训练/测试集标签比例一致 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
2. 训练深度学习模型
示例1:用MLP(多层感知机)做二分类
适合纯特征输入的场景:
import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout model = Sequential([ Dense(64, activation='relu', input_shape=(X_train.shape[1],)), Dropout(0.3), # 防止过拟合 Dense(32, activation='relu'), Dropout(0.2), Dense(1, activation='sigmoid') # 二分类输出用sigmoid ]) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 用10%的训练集做验证 history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_split=0.1)
示例2:用CNN处理时序流量特征
如果要利用流量的时序性,先把数据转成序列形式再训练:
# 假设每个样本是10个连续数据包的特征,调整数据形状为(样本数, 序列长度, 特征数) # 需根据实际数据结构调整,比如先做会话分割 X_train_seq = X_train.values.reshape(-1, 10, X_train.shape[1]//10) X_test_seq = X_test.values.reshape(-1, 10, X_test.shape[1]//10) model = Sequential([ tf.keras.layers.Conv1D(32, kernel_size=3, activation='relu', input_shape=(X_train_seq.shape[1], X_train_seq.shape[2])), tf.keras.layers.MaxPooling1D(pool_size=2), tf.keras.layers.Flatten(), Dense(16, activation='relu'), Dense(1, activation='sigmoid') ]) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) history = model.fit(X_train_seq, y_train, epochs=10, batch_size=32, validation_split=0.1)
3. 模型评估与优化
- 在测试集上评估效果:
test_loss, test_acc = model.evaluate(X_test, y_test) print(f"测试集准确率:{test_acc:.4f}") - 优化方向:
- 调整模型层数、神经元数量,或换用LSTM处理时序数据
- 尝试不同优化器(比如SGD、RMSprop)
- 添加L1/L2正则化防止过拟合
- 样本不平衡时,用SMOTE生成少数类样本
内容的提问来源于stack exchange,提问作者Abhijit
相关产品推荐
相关产品推荐

