我正在尝试处理一个具有以下形状的网络攻击的数据集:
df.shape
(1074992, 42)
攻击和正常行为的标签如下:
df['Label'].value_counts()
normal 812814
neptune 242149
satan 5019
ipsweep 3723
portsweep 3564
smurf 3007
nmap 1554
back 968
teardrop 918
warezclient 893
pod 206
guesspasswd 53
bufferoverflow 30
warezmaster 20
land 19
imap 12
rootkit 10
loadmodule 9
ftpwrite 8
multihop 7
phf 4
perl 3
spy 2
Name: Label, dtype: int64
接下来,我将数据集拆分为特征和标签。
labels = df['Label']
features = df.loc[:, df.columns != 'Label'].astype('float64')
然后尝试平衡我的数据集。
print("Before UpSampling, counts of label Normal: {}".format(sum(labels == "normal")))
print("Before UpSampling, counts of label Attack: {} n".format(sum(labels != "normal")))
Before UpSampling, counts of label Normal: 812814
Before UpSampling, counts of label Attack: 262178
因此,正如你所注意到的,攻击的数量与正常行为的数量不成比例。
我尝试使用SMOTE将少数类(Attack(设置为与多数类(Normal(相同的值。
sm = SMOTE(k_neighbors = 1,random_state= 42) #Synthetic Minority Over Sampling Technique
features_res, labels_res = sm.fit_resample(features, labels)
features_res.shape ,labels_res.shape
((18694722, 41), (18694722,))
我不明白的是,这就是为什么我在应用SMOTE后得到18694722个值。
print("After UpSampling, counts of label Normal: {}".format(sum(labels_res == "normal")))
print("After UpSampling, counts of label Attack: {} n".format(sum(labels_res != "normal")))
After UpSampling, counts of label Normal: 812814
After UpSampling, counts of label Attack: 17881908
就我的情况而言,是对普通类进行下采样更好,还是对攻击类进行上采样更好?关于如何正确地做这件事,有什么想法吗?
非常感谢。
默认情况下,SMOTE的sampling_strategy
为not majority
,
"不是多数":对除多数类之外的所有类重新采样
因此,如果多数类的样本是812814,则您将获得
(812814 * 23) = 18694722
样品。
尝试为少数类传递一个具有所需样本数的dict。从文档
dict时,键对应于目标类。这些值对应于每个目标类别所需的样本数量。
示例
根据文档改编,在本例中,我们对少数类中的一个进行了上采样,使其具有与多数类相同数量的样本。
from sklearn.datasets import make_classification
from collections import Counter
from imblearn.over_sampling import SMOTE
X, y = make_classification(n_classes=5,
class_sep=2,
weights=[0.15, 0.15, 0.1, 0.1, 0.5],
n_informative=4,
n_redundant=1,
flip_y=0,
n_features=20,
n_clusters_per_class=1,
n_samples=1000,
random_state=10)
sample_strategy = {4: 500, 0: 500, 1: 150, 2: 100, 3: 100}
sm = SMOTE(sampling_strategy=sample_strategy, random_state=0)
X_res, y_res = sm.fit_resample(X, y)
from collections import Counter
print('Resampled dataset shape %s' % Counter(y_res))
>>>
Resampled dataset shape Counter({4: 500, 0: 500, 1: 150, 3: 100, 2: 100})