【机器学习】什么是DNN / MLP(全连接深度神经网络, Deep Neural Network / Multilayer Perceptron)?
什么是 DNN / MLP(全连接网络)
一句话:MLP 就是由多层“线性加权求和 + 非线性激活”堆起来的网络;层与层之间全连接,没有卷积、注意力或递归结构。
-
输入层:放入特征向量
x∈R^d
(如流量统计特征)。 -
隐藏层(Hidden Layers):每层做
z=W·h + b
,再过激活函数(ReLU/GELU/SiLU 等)。 -
输出层:
- 二分类:1 个单元 + Sigmoid;
- 多分类:K 个单元 + Softmax。
-
损失函数:
- 二分类:Binary Cross-Entropy;
- 多分类:Categorical / Sparse Categorical Cross-Entropy。
-
为什么叫“深度”:有多层(>1)隐藏层就是“深度神经网络(DNN)”;MLP 是 DNN 的一种具体结构(全连接)。
初学者直观理解(两个小比喻)
- 配方调味器:每一层像“调味”:先把原料(特征)线性混合,再通过非线性“调味”,层层叠加后能拟合很复杂的口味(函数)。
- 会学特征的逻辑回归:逻辑回归是“线性 + Sigmoid”;MLP 是把“学特征”的过程也参数化并端到端训练。
与 CNN 的差别
- MLP 不擅长“局部模式/平移不变”,但非常吃“优质特征”;
- CNN 能自动挖局部模式(适合时序/图像的结构性数据)。
- IoT 入侵检测:如果你有好的统计特征(tabular),MLP 往往是稳健基线;若用原始时序或窗口序列,CNN/TCN 更占优。
在 IoT 攻击检测中的数据喂法
常见两种输入给 MLP 的方式:
- 会话/流量的汇总统计(推荐给 MLP):如字节数、包数、持续时长、方向计数、TCP 标志位计数、平均/方差/峰度、端口/协议 One-Hot/嵌入等 → 拼成一个固定长度的特征向量。
- 将时间窗口展开为大向量:把
(window_len, n_features)
直接 flatten 成长度window_len×n_features
的向量(可行,但序列位置信息弱化)。
用 MLP 做你的研究题:二分类 vs 多分类
Research Question
How does binary classification performance compare with multiclass models in IoT cyber attack detection?
公平对比设计(核心要点)
-
同一数据/划分/预处理:同一 train/val/test;特征标准化用 train 集 的均值方差拟合再应用到 val/test,避免泄漏。
-
同一 MLP 主干:仅改输出层大小 + 损失函数(二 vs 多),其余结构/优化器/学习率/epoch/早停一致。
-
类别不平衡:使用
class_weight
或重采样;多分类可考虑 Focal Loss。 -
指标:
- Binary:Accuracy、Precision、Recall、F1、PR-AUC(precision 很受阈值影响,给出阈值-精召折中)。
- Multiclass:Macro-Precision / Macro-F1(更能反映小类),外加混淆矩阵。
-
统计置信:对 Macro-F1 做 bootstrap 置信区间;也可报告多次随机种子平均±方差。
-
报告:同一表格列出 Binary 与 Multiclass 的 Accuracy / (Macro)Precision / (Macro)F1;多分类给出主要混淆对(如 DoS↔DDoS)。
预期现象(可写成假设)
- H1:在相同条件下,Binary 的 Accuracy/Precision 通常高于 Multiclass 的 Macro-Precision/Macro-F1;
- H2:Multiclass 能区分具体类型,运维价值更高;若对长尾类做重加权/增广,Macro-Precision 会提升。
一个可复用的 MLP 基线(两套:scikit-learn 与 Keras)
A. scikit-learn(快速基线,适合表格特征)
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report
from sklearn.utils.class_weight import compute_class_weight
import numpy as np# X_train, y_train, X_val, y_val, X_test, y_test 需事先准备好(相同划分用于二/多分类)
is_binary = True # True=二分类;False=多分类
hidden = (256, 128) # 主干一致if is_binary:classes = np.array([0,1])
else:classes = np.unique(y_train)cw = compute_class_weight('balanced', classes=classes, y=y_train)
class_weight = {i:cw[i] for i in range(len(classes))}pipe = Pipeline([('scaler', StandardScaler()),('mlp', MLPClassifier(hidden_layer_sizes=hidden,activation='relu',solver='adam',alpha=1e-4, # L2batch_size=256,learning_rate_init=1e-3,max_iter=100,early_stopping=True,n_iter_no_change=10,random_state=42))
])# 注意:sklearn 的 MLPClassifier 不直接支持 class_weight
# 变通:对 y_train 做加权采样,或用 sample_weight 传给 fit(需要1.4+并用SGD);简单起见可先不加权
pipe.fit(X_train, y_train)y_pred = pipe.predict(X_test)
print(classification_report(y_test, y_pred, digits=3)) # 多分类含 macro avg
说明:sklearn 的
MLPClassifier
使用方便、适合跑基线;但在严重不平衡时,class_weight 支持有限,你可以用 加权采样 或换到 Keras 更灵活。
B. Keras(更灵活,class_weight/回调/自定义指标都好用)
import tensorflow as tf
from tensorflow.keras import layers, models
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report
from sklearn.utils.class_weight import compute_class_weight
import numpy as npis_binary = True
n_classes = 1 if is_binary else K # 把 K 换成类别数# 标准化(用 train 拟合)
scaler = StandardScaler().fit(X_train)
X_train_n = scaler.transform(X_train)
X_val_n = scaler.transform(X_val)
X_test_n = scaler.transform(X_test)inputs = layers.Input(shape=(X_train_n.shape[1],))
x = layers.Dense(256)(inputs); x = layers.ReLU()(x); x = layers.Dropout(0.3)(x)
x = layers.Dense(128)(x); x = layers.ReLU()(x); x = layers.Dropout(0.2)(x)if is_binary:outputs = layers.Dense(1, activation='sigmoid')(x)loss = 'binary_crossentropy'metrics = ['accuracy',tf.keras.metrics.Precision(name='precision'),tf.keras.metrics.Recall(name='recall')]
else:outputs = layers.Dense(n_classes, activation='softmax')(x)loss = 'sparse_categorical_crossentropy'metrics = ['accuracy'] # 训练后用 sklearn 计算 macro 指标更稳model = models.Model(inputs, outputs)
model.compile(optimizer=tf.keras.optimizers.Adam(1e-3), loss=loss, metrics=metrics)# 类别权重(建议)
if is_binary:classes = np.array([0,1])
else:classes = np.arange(n_classes)cw = compute_class_weight('balanced', classes=classes, y=y_train.reshape(-1))
class_weight = {int(i):float(w) for i,w in enumerate(cw)}cb = [tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=8, restore_best_weights=True)]
model.fit(X_train_n, y_train,validation_data=(X_val_n, y_val),epochs=200, batch_size=256,class_weight=class_weight,callbacks=cb, verbose=1)# 评估
if is_binary:y_prob = model.predict(X_test_n, verbose=0).ravel()y_pred = (y_prob >= 0.5).astype(int) # 也可按PR曲线选更优阈值
else:y_prob = model.predict(X_test_n, verbose=0)y_pred = y_prob.argmax(axis=1)print(classification_report(y_test, y_pred, digits=3))
指标与结果呈现(直接可用模板)
表 1:同一 MLP 主干下 Binary vs Multiclass 表现(测试集)
Setting | Accuracy | Precision / Macro-Precision | Recall / Macro-Recall | F1 / Macro-F1 |
---|---|---|---|---|
Binary (MLP) | … | … | … | … |
Multiclass (MLP) | … | … | … | … |
多分类再补一张混淆矩阵,并在文字里指出主要混淆对(如 DoS↔DDoS、PortScan↔BruteForce)。
实操建议(直接影响结论)
- 特征工程优先:MLP 对表格数据的表现强烈依赖特征质量;对时域统计 + 比例 + 对数变换常有帮助。
- 标准化:对连续特征做
StandardScaler
(按 train 统计量)。 - 不平衡:优先用
class_weight
;严重时配合 欠/过采样 或 Focal Loss。 - Binary 的阈值:precision 取决于阈值;报告 PR-AUC 与若干阈值下的 (P, R)。
- 泛化:加入 L2(weight decay)+ Dropout,早停;多次随机种子平均。
- 与树模型对照(可写在附录):在纯表格数据上,XGBoost/LightGBM 往往是强基线;但本研究重点是同一主干的二 vs 多对比,保持可比性即可。
什么是 DNN / MLP(Deep Neural Network / Multilayer Perceptron)
结论先行:
- **DNN(深度神经网络)**是多层神经网络的统称(>1 个隐藏层)。
- MLP(多层感知机)是一种全连接结构的 DNN:相邻两层每个神经元彼此相连,没有卷积、注意力或循环结构。
1) 初学者怎么理解?
最短定义
-
一层做的事:线性变换 + 非线性激活
hidden=σ(Wx+b) \text{hidden} = \sigma(Wx + b) hidden=σ(Wx+b)
-
多层堆叠后,网络可以逼近非常复杂的函数关系(“万能逼近”)。
两个直观比喻
- 会学特征的逻辑回归:逻辑回归 = “线性 + Sigmoid”;MLP = 多层“线性 + 非线性”,相当于把“造特征”的过程也学出来。
- 调味叠层:每层在上一层输出的“口味”上再加权、再非线性调味,越叠越能做出细腻风味(复杂决策边界)。
关键组件
-
层(Layer):Dense/全连接层(
Dense(units)
) -
激活(Activation):ReLU/SiLU/GELU(推荐 ReLU/SiLU 起步)
-
损失(Loss):
- 二分类:Binary Cross-Entropy(BCE)
- 多分类:Categorical / Sparse Categorical Cross-Entropy
-
正则化:Dropout、L2(weight decay)、Early Stopping
-
优化器:Adam(学习率 1e-3 起步)
2) DNN vs. MLP vs. 其它模型
- MLP 属于 DNN(全连接)。
- CNN 用卷积核捕捉“局部模式+平移不变”,适合序列/图像。
- **树模型(XGBoost/LightGBM)**在“表格”数据上常是强基线;MLP 优势在端到端联合学习与可与深度管线配合(如后续多任务/蒸馏)。
实用建议:
- 表格/会话统计特征:先用 MLP 做稳健基线(速度快、实现简单)。
- 窗口化时序(T×F):考虑 1D-CNN/TCN;若坚持 MLP,可先 flatten,但通常不如 1D-CNN 抓时序局部模式。
3) 迷你例子:为什么需要“多层”?
XOR(异或)用单层线性模型无法分开(线性不可分)。加一层隐藏层(非线性),MLP 便能轻松拟合。这说明隐藏层=自动构造可分特征。
4) 在你的课题里怎么用?
Research Question:
How does binary classification performance compare with multiclass models in IoT cyber attack detection?
Topic:Binary vs. Multiclass Evaluation of IoT Cyber Attacks
数据表示(两条常用路径)
-
表格/会话级统计(推荐给 MLP):
- 特征例子:字节数、包数、持续时长、方向计数、TCP 标志位统计、端口/协议(One-Hot/嵌入)、时间间隔的均值/方差/峰度等。
- 预处理:缺失值→填补;连续特征→标准化(只用 train 拟合);偏态→对数/分箱;类别→One-Hot/嵌入。
-
窗口化序列(T×F):如每 0.5–1s 聚合一次,得到固定长度序列;若用 MLP,先 flatten 成向量(简便但时序位置信息弱化;1D-CNN 往往更优)。
用同一 MLP 主干,公平比较 Binary vs. Multiclass
-
只改最后一层与损失函数,其余保持一致:
- Binary:输出维度 1 + Sigmoid,BCE
- Multiclass:输出维度 K + Softmax,(Sparse) CE
-
类不平衡:用
class_weight
或重采样;多分类可加 Focal Loss(可作为附加实验)。 -
指标:
- Binary:Accuracy、Precision、Recall、F1、PR-AUC(precision 受阈值影响,给出若干阈值下 P/R 或 PR 曲线)
- Multiclass:Macro-Precision / Macro-Recall / Macro-F1 + 混淆矩阵(Macro 能真实反映小类表现)
-
统计稳健:多随机种子均值±方差;或对(Macro)F1 做 bootstrap 置信区间。
可检验的预期
- Binary 往往更高的 Accuracy / Precision(任务更容易)。
- Multiclass 的 Macro-Precision / Macro-F1 常较低(长尾与类间混淆),但能提供具体攻击类型,运维价值更高。
- 工程建议:两段式(Binary 先筛,再 Multiclass 精细化)或对小类重加权/数据增广。
5) 一个极简可复用的 MLP 基线(Keras/TensorFlow)
把你的数据准备为:
X_*
形状为[样本数, 特征数]
;
y_*
:二分类为 0/1;多分类为 0…K-1。
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report
from sklearn.utils.class_weight import compute_class_weight# === 配置:切换二/多分类 ===
TASK_TYPE = 'binary' # 'binary' or 'multiclass'
N_CLASSES = 5 # 多分类类别数(示例)
INPUT_DIM = X_train.shape[1]# 标准化(仅用 train 拟合,避免泄漏)
scaler = StandardScaler().fit(X_train)
X_train_n = scaler.transform(X_train)
X_val_n = scaler.transform(X_val)
X_test_n = scaler.transform(X_test)# 构建同一主干 MLP,仅输出层不同
inputs = layers.Input(shape=(INPUT_DIM,))
x = layers.Dense(256)(inputs); x = layers.ReLU()(x); x = layers.Dropout(0.3)(x)
x = layers.Dense(128)(x); x = layers.ReLU()(x); x = layers.Dropout(0.2)(x)if TASK_TYPE == 'binary':outputs = layers.Dense(1, activation='sigmoid')(x)loss = 'binary_crossentropy'metrics = ['accuracy', tf.keras.metrics.Precision(name='precision'),tf.keras.metrics.Recall(name='recall')]classes = np.array([0,1])n_out = 1
else:outputs = layers.Dense(N_CLASSES, activation='softmax')(x)loss = 'sparse_categorical_crossentropy'metrics = ['accuracy'] # 训练后用 sklearn 计算 macro 指标更稳classes = np.arange(N_CLASSES)n_out = N_CLASSESmodel = models.Model(inputs, outputs)
model.compile(optimizer=tf.keras.optimizers.Adam(1e-3), loss=loss, metrics=metrics)# 类别权重(不平衡友好)
cw = compute_class_weight(class_weight='balanced', classes=classes, y=y_train.reshape(-1))
class_weight = {int(i): float(w) for i, w in enumerate(cw)}# 训练与早停
cb = [tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=8, restore_best_weights=True)]
model.fit(X_train_n, y_train, validation_data=(X_val_n, y_val),epochs=120, batch_size=256, class_weight=class_weight, callbacks=cb, verbose=1)# 评估
y_prob = model.predict(X_test_n, verbose=0)
if TASK_TYPE == 'binary':y_pred = (y_prob.ravel() >= 0.5).astype(int) # 可按PR曲线调阈值
else:y_pred = y_prob.argmax(axis=1)print(classification_report(y_test, y_pred, digits=3))
6) 实操清单(避免“翻车点”)
- 划分先于标准化:先切 train/val/test,再用 train 拟合 scaler。
- 去泄漏:时间序列按时间切;不要把同一会话的不同片段分到不同集合。
- 类不平衡:优先
class_weight
;严重时配合重采样或 Focal Loss。 - 阈值与业务(Binary):precision 随阈值变;结合代价(漏报/误报)选择运营阈值。
- 报告方式统一:同一主干、同一超参,表格并排给出 Binary vs. Multiclass 的 Accuracy /(Macro)Precision /(Macro)F1;多分类补混淆矩阵与主要混淆对(如 DoS↔DDoS)。
一句话小结
- DNN 是“多层神经网络”的大类,MLP 是其中“全连接”的基础款。
- 在 IoT 入侵检测 中,表格/会话统计特征 → MLP 是很好的起点;
- 用同一 MLP 主干,只改输出层与损失,就能公平比较 Binary 与 Multiclass 的 Accuracy /(Macro)Precision,并据此写出清晰、可复现的研究结论。