基于机器学习检测恶意代码之数据预处理2

博主前言

本篇博客是对Kaggle上的基于机器学习对恶意代码检测的源码的设计思路进行解析,里面的解析,是提炼写代码人解决问题的方案与精髓,仅供学习,此外,里面的解析难免有不当的之处,敬请读者斧正

摘要

要想检测恶意代码,首先我们必须对其进行特征提取,但是恶意代码的特征向量的维度是非常高的,在计算机中处理起来,计算速度会非常的慢,但是也不必担心,能够检测出恶意代码是否恶意,影响较大的仅仅是几个特征,为此,在进行分类学习之前我们需要对其进行数据预处理,编写这一段代码的作者,采用预先剔除无关影响的特征向量,留下影响较大的特征向量!已达到分类准确的目的

数据预处理

代码作者的设计思路点拨:
删去不必要的特征,需要满足一下条件:
(1)缺失值:任取一个特征,缺失值的次数较为多,以至于所占的比重高达99%
(2)非缺失值:任取一个特征,在它们的非缺失值中,出现一种可能取值占所有可能取值比重较大的,以至于比重高达99%
(3)影响较小的特征,即无论该特征去什么值,它们出现的结果基本上一致

**

(1)建立一个空的删除名单列表

droppable_features = []

(2)筛选出要删除的特征列,按照开头所说的三点条件进行删除
a)缺失值:任取一个特征,缺失值的次数较为多,以至于所占的比重高达99%

# 在训练集每一列特征之中计算出缺失值占比,并按照降序的方式进行排序
sk_df1 = (train.isnull().sum()/train.shape[0]).sort_values(ascending=False)
print(sk_df1)
统计的结果:
PuaMode                                              0.999741
Census_ProcessorClass                                0.995894
DefaultBrowsersIdentifier                            0.951416
Census_IsFlightingInternal                           0.830440
Census_InternalBatteryType                           0.710468
Census_ThresholdOptIn                                0.635245
Census_IsWIMBootEnabled                              0.634390
SmartScreen                                          0.356108
OrganizationIdentifier                               0.308415
SMode                                                0.060277
CityIdentifier                                       0.036475
Wdft_IsGamer                                         0.034014
Wdft_RegionIdentifier                                0.034014
Census_InternalBatteryNumberOfCharges                0.030124
Census_FirmwareManufacturerIdentifier                0.020541
Census_IsFlightsDisabled                             0.017993
Census_FirmwareVersionIdentifier                     0.017949
Census_OEMModelIdentifier                            0.011459
Census_OEMNameIdentifier                             0.010702
Firewall                                             0.010239
Census_TotalPhysicalRAM                              0.009027
Census_IsAlwaysOnAlwaysConnectedCapable              0.007997
Census_OSInstallLanguageIdentifier                   0.006735
IeVerIdentifier                                      0.006601
Census_PrimaryDiskTotalCapacity                      0.005943
Census_SystemVolumeTotalCapacity                     0.005941
Census_InternalPrimaryDiagonalDisplaySizeInInches    0.005283
Census_InternalPrimaryDisplayResolutionHorizontal    0.005267
Census_InternalPrimaryDisplayResolutionVertical      0.005267
Census_ProcessorModelIdentifier                      0.004634
                                                       ...   
ProductName                                          0.000000
HasTpm                                               0.000000
OsBuild                                              0.000000
IsBeta                                               0.000000
OsSuite                                              0.000000
IsSxsPassiveMode                                     0.000000
HasDetections                                        0.000000
SkuEdition                                           0.000000
Census_OSInstallTypeName                             0.000000
Census_IsPenCapable                                  0.000000
Census_IsTouchEnabled                                0.000000
Census_IsSecureBootEnabled                           0.000000
Census_FlightRing                                    0.000000
Census_ActivationChannel                             0.000000
Census_GenuineStateName                              0.000000
Census_IsPortableOperatingSystem                     0.000000
Census_OSWUAutoUpdateOptionsName                     0.000000
Census_OSUILocaleIdentifier                          0.000000
Census_OSSkuName                                     0.000000
AutoSampleOptIn                                      0.000000
Census_OSEdition                                     0.000000
Census_OSBuildRevision                               0.000000
Census_OSBuildNumber                                 0.000000
Census_OSBranch                                      0.000000
Census_OSArchitecture                                0.000000
Census_OSVersion                                     0.000000
Census_HasOpticalDiskDrive                           0.000000
Census_DeviceFamily                                  0.000000
Census_MDC2FormFactor                                0.000000
MachineIdentifier                                    0.000000
Length: 83, dtype: float64

不难看出排在前两位的已经达到了99%以上,因此应该被剔除

# 将他们删除
droppable_features.append('PuaMode')
droppable_features.append('Census_ProcessorClass')

b)非缺失值:任取一个特征,在它们的非缺失值中,出现一种可能取值占所有可能取值比重较大的,以至于比重高达99%

# 设定数据的精度值,这里每一个数据保留4位小数
pd.options.display.float_format = '{:,.4f}'.format

# 建立一个每一个特征值可能取值所占比例最大的列表,并显示他们所占的百分比
sk_df2 = pd.DataFrame([{'column': c, 'uniq': train[c].nunique(), 'skewness': train[c].value_counts(normalize=True).values[0] * 100} for c in train.columns])
sk_df2 = sk_df.sort_values('skewness', ascending=False)

# 将结果输出
print(sk_df2)

# 知识补充:
# value_counts(normalize=True):每个特征值的计数占比,默认降序排序
# value_counts(normalize=True).values[0]:返回计数占比最大的特征值的计数占比

**

统计结果:
在这里插入图片描述

# 将比重大于99%的列入被删除的名单
droppable_features.extend(sk_df[sk_df.skewness > 99].column.tolist())

# 知识补充:
# append()函数一次只能添加一个元素
# extend()函数一次能够添加多个元素

# 先将这一些删除名单上的特征列删除
train.drop(droppable_features, axis=1, inplace=True)

c)影响较小的特征,即无论该特征去什么值,它们出现的结果基本上一致
在这里我们也许要进行预处理,它的基本思路:
(1)将缺失值所占的百分比>10%的特征列中的缺失值用0进行填充

# 统计一下每一个特征列缺失值的总数
null_counts = train.isnull().sum()

# 计算特征列缺失值所占的百分比
null_counts = null_counts / train.shape[0]

# 筛选出特征列缺失值百分比超过10%的列
print(null_counts[null_counts > 0.1])
结果如下:
DefaultBrowsersIdentifier    0.9514
OrganizationIdentifier       0.3084
SmartScreen                  0.3561
Census_InternalBatteryType   0.7105
dtype: float64

接下来是需要对着4个特征所出现的缺失值以不同的方式进行替换
1)DefaultBrowsersIdentifier

# 用0将缺失值进行填充填充
train.DefaultBrowsersIdentifier.fillna(0, inplace=True)
print(train.SmartScreen.value_counts())

2)OrganizationIdentifier

print(train.SmartScreen.value_counts())
显示的结果:
RequireAdmin    4316183
ExistsNotSet    1046183
Off              186553
Warn             135483
Prompt            34533
Block             22533
off                1350
On                  731
              416
              335
on                  147
requireadmin         10
OFF                   4
0                     3
Promt                 2
requireAdmin          1
Enabled               1
prompt                1
warn                  1
00000000              1
                1
Name: SmartScreen, dtype: int64
# 替换方式:
trans_dict = 
{
    'off': 'Off', '': '2', '': '1', 'on': 'On', 'requireadmin': 'RequireAdmin', 'OFF': 'Off', 
    'Promt': 'Prompt', 'requireAdmin': 'RequireAdmin', 'prompt': 'Prompt', 'warn': 'Warn', 
    '00000000': '0', '': '3', np.nan: 'NoExist'
}
train.replace({'SmartScreen': trans_dict}, inplace=True)

3)SmartScreen

# 统计该特征不同取值出现的次数
print(train.OrganizationIdentifier.value_counts())
输出结果:
27.0000    4196457
18.0000    1764175
48.0000      63845
50.0000      45502
11.0000      19436
37.0000      19398
49.0000      13627
46.0000      10974
14.0000       4713
32.0000       4045
36.0000       3909
52.0000       3043
33.0000       2896
2.0000        2595
5.0000        1990
40.0000       1648
28.0000       1591
4.0000        1385
10.0000       1083
51.0000        917
20.0000        915
1.0000         893
8.0000         723
22.0000        418
39.0000        413
6.0000         412
31.0000        398
21.0000        397
47.0000        385
3.0000         331
16.0000        242
19.0000        172
26.0000        160
44.0000        150
29.0000        135
42.0000        132
7.0000          98
41.0000         77
45.0000         73
30.0000         64
43.0000         60
35.0000         32
23.0000         20
15.0000         13
25.0000         12
12.0000          7
34.0000          2
38.0000          1
17.0000          1
Name: OrganizationIdentifier, dtype: int64
# 填充方式(将缺失值用0填充)
train.replace({'OrganizationIdentifier': {np.nan: 0}}, inplace=True)

4)Census_InternalBatteryType

# 这里是指最多显示行数为99行
pd.options.display.max_rows = 99

# 统计该特征各个取值的总数
print(train.Census_InternalBatteryType.value_counts())
结果如下:
lion        2028256
li-i         245617
#            183998
lip           62099
liio          32635
li p           8383
li             6708
nimh           4614
real           2744
bq20           2302
pbac           2274
vbox           1454
unkn            533
lgi0            399
lipo            198
lhp0            182
4cel            170
lipp             83
ithi             79
batt             60
ram              35
bad              33
virt             33
pad0             22
lit              16
ca48             16
a132             10
ots0              9
lai0              8
ÿÿÿÿ              8
lio               5
4lio              4
lio              4
asmb              4
li-p              4
0x0b              3
lgs0              3
icp3              3
3ion              2
a140              2
h00j              2
5nm1              2
lhpo              2
a138              2
lilo              1
li-h              1
lp                1
li?               1
ion              1
pbso              1
3500              1
6ion              1
@i              1
li               1
sams              1
ip               1
8                 1
#TAB#             1
l&#TAB#          1
lio              1
˙˙˙              1
l                1
cl53              1
liÿÿ              1
pa50              1
í-i              1
÷ÿóö              1
li-l              1
h4°s              1
d                 1
lgl0              1
4ion              1
0ts0              1
sail              1
p-sn              1
a130              1
2337              1
lÿÿÿ              1
Name: Census_InternalBatteryType, dtype: int64
#填充方式:
trans_dict =
 {
    '˙˙˙': 'unknown', 'unkn': 'unknown', np.nan: 'unknown'
}

(2)将缺失值所占的百分比<10%的特征列中的数据删除

train.dropna(inplace=True)

基于(1)(2)两点我们进行一个小小的总结,我们选取缺失值<10%并将其进行删除原因是少量的缺失值并不影响实验的结果,然而如果删除大量 缺失值(>10%)会使得分类的结果不准确

然而MachineIdentifier也对检测结果影响不大,因此我们也将这一个特征值将其删去

train.drop('MachineIdentifier', axis=1, inplace=True)

接下来我们需要将将这一些处理好的数据集进行编码

# 使用机器学习模型的时候,一般情况选择将所有的数据转换为category的类型
train['SmartScreen'] = train.SmartScreen.astype('category')
train['Census_InternalBatteryType'] = train.Census_InternalBatteryType.astype('category')

# 选择是该数据类型的特征列,并将它们列入一个列表中
cate_cols = train.select_dtypes(include='category').columns.tolist()

# 初始化标签编码对象
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()

# 将category的类型的特征列进行编码
for col in cate_cols:
    train[col] = le.fit_transform(train[col])

现在正式开始进行关联性分析

# 将训练集的特征放入一个列表
cols = train.columns.tolist()

##第1轮
# 将特征存放在一个列表当中
cols = train.columns.tolist()

# 导入一个绘制相关性的表格
import seaborn as sns

# 确定这一个表格的规格
plt.figure(figsize=(10,10))

# 采集数据的样本
co_cols = cols[:10]

# 将目标值加入此列表当中
co_cols.append('HasDetections')

# 绘制关联图
sns.heatmap(train[co_cols].corr(), cmap='RdBu_r', annot=True, center=0.0)
plt.title('Correlation between 1 ~ 10th columns')
plt.show()

# 知识补充
corr()这是一个求变量之间相关联的函数
##第2轮
# 建立一个要删除关联性较大的特征值空列表
corr_remove = []

# 采集数据的样本
co_cols = cols[10:20]

# 将目标值加入此列表当中
co_cols.append('HasDetections')

# 绘制图
plt.figure(figsize=(10,10))
sns.heatmap(train[co_cols].corr(), cmap='RdBu_r', annot=True, center=0.0)
plt.title('Correlation between 11 ~ 20th columns')
plt.show()

在这里发现两个特征相关性超过99%,需要删除其中一个:需要比较那个稳定,也就是比较哪一个的出现次数比较多

print(train.Platform.nunique())
print(train.OsVer.nunique())
结果如下:
3
45

显然需要将Platform删除掉

corr_remove.append('Platform')

同理每10个特征向量进行选取,每一次都需要把选出符合要求的特征选出来加入删除列表当中

# 将关联性较大的特征列表中列删除
train.drop(corr_remove, axis=1, inplace=True)

# 整体进行相关联,并绘制相关图
corr = train.corr()
high_corr = (corr >= 0.99).astype('uint8')
plt.figure(figsize=(15,15))
sns.heatmap(high_corr, cmap='RdBu_r', annot=True, center=0.0)
plt.show()
# 同分部检查先关性一样
print(train.Census_OSArchitecture.nunique())
print(train.Processor.nunique())
结果如下:
3
3

然而发现出现次数都相同,现在就对’Census_OSArchitecture’, ‘Processor’, 'HasDetections’进行相关联的运算

train[['Census_OSArchitecture', 'Processor', 'HasDetections']].corr()
结果如下:
                       Census_OSArchitecture	Processor	HasDetections
Census_OSArchitecture	1.0000	                0.9951   	-0.0758
Processor	            0.9951	                1.0000	    -0.0758
HasDetections       	-0.0758	               -0.0758	     1.0000
发布了7 篇原创文章 · 获赞 5 · 访问量 875

猜你喜欢

转载自blog.csdn.net/weixin_44944722/article/details/97388074