本文将在上一篇文章的基础上(上一篇文章完成了项意图数据处理及统计学剖析),持续完善数据预处理部分、模型建立、模型练习等过程。
本项目运用Jupyter Notebook进行操作,运用PaddlePaddle结构进行实战操作
1 项目回忆 ✅
为了有用保护企业敏感数据,饯别企业安全操作行为准则,杜绝由反常操作行为导致的企业敏感数据走漏安全事件产生,用户反常行为剖析与识别成为重难点技术之一。
本项目将运用Paddle建立人工神经网络,经过机器学习的手段猜测用户上网反常评分,本项目包括数据处理与剖析、数据预处理、模型建立、模型练习、模型猜测、模型评价等完整流程,测验建立三种不同的网络处理该问题。
2. 数据预处理
2.1 数据编码
- 在数据处理进程中,咱们有时需求对不连续的数字或者文本进行数字化处理。
- 其间,咱们选取了
'account', 'group', 'IP', 'url', 'switchIP'
这五个object类型的特征字段进行了编码。
from sklearn.preprocessing import LabelEncoder
for feat in ['account', 'group', 'IP', 'url', 'switchIP']:
labelencoder = LabelEncoder()
train_data[feat] = labelencoder.fit_transform(train_data[feat])
检查编码后的数据集
# 检查编码后的数据集
train_data.head()
编码后的成果如下图所示:
- 能够发现曾经的object字段都变成了数字编码
2.2 区分练习集与测验集
- 选取了
'account', 'group', 'IP', 'url', 'port', 'vlan', 'switchIP', 'hour', 'weekday', 'year', 'month', 'day'
字段作为练习的特征(features)。 -
'ret'
字段为想要猜测的目标值/标签值(label)。 - 咱们将数据集区分为:练习集:测验集 = 0.75:0.25
先结构全体数据的特征值与标签值。
data_X = train_data.loc[train_data.index[:], ['account', 'group', 'IP', 'url', 'port', 'vlan', 'switchIP', 'hour', 'weekday', 'year', 'month', 'day']]
data_Y = train_data['ret']
然后,运用sklearn库中的数据集切分API进行对练习集和测验集进行切分。
from sklearn.model_selection import train_test_split
# 数据集区分
x_train, x_test, y_train, y_test = train_test_split(data_X, data_Y, test_size=0.25, random_state=6)
print("练习集的特征值:\n", x_train, x_train.shape)
print("测验集的标签值:\n", y_test, y_test.shape)
print("The length of original data X is:", data_X.shape[0])
print("The length of train Data is:", x_train.shape[0])
print("The length of test Data is:", x_test.shape[0])
部分运转成果如下图所示:
2.3 标签值数组维度转化
练习集的特征数组(features)为二维数组,而练习集的标签数据(label)是一维数组,需求将其转变为二维数组再传入神经网络练习,坚持维度共同,不然会报错
首要转化字段类型,然后对数组维度进行转化
- (-1,1):后一个1表明指定数组维度为1列,前一个-1表明依据指定好的数组维度1列主动调整行数
x_train = np.array(x_train, dtype='float32')
y_train = np.array(y_train, dtype='float32')
y_train = y_train.reshape(-1,1)
y_train
x_test = np.array(x_test, dtype='float32')
y_test = np.array(y_test, dtype='float32')
y_test = y_test.reshape(-1,1)
y_test
2.4 归一化(标准化)
咱们对练习集和测验集的特征值进行了标准化
- 意图是将一切特征放缩在一个数量级下,这样就不会导致某个特征对模型的影响过大
# 标准化
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import StandardScaler
# 1. 实例化一个转化器类
transfer = StandardScaler()
# 2. 标准化
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
2.5 设置随机数种子
import random
import paddle
seed = 666
# 设置随机种子 固定成果
def set_seed(seed):
np.random.seed(seed)
random.seed(seed)
paddle.seed(seed)
set_seed(seed)
3. 模型组网
运用飞桨PaddlePaddle进行组网,激活函数能够挑选:
- tanh(x)=2(2x)−1tanh(x) = 2(2x) − 1
- ReLU(x)=Max(0,x)ReLU(x) = Max(0, x)
躲藏层层数能够测验运用1层,2层,3层。
3.1 建立神经网络
测验运用 12643216811264321681
-
'account', 'group', 'IP', 'url', 'port', 'vlan', 'switchIP', 'hour', 'weekday', 'year', 'month', 'day'
:共12个特征(features)进行输入 -
'ret'
:作为回归输出的标签(label) - 激活函数运用的是Tanh
- 共4层躲藏层
paddle.nn.Dropout(p=0.5, axis=None, mode="upscale_in_train”, name=None)
- Dropout 是一种正则化手段,该算子依据给定的丢掉概率 p,在练习进程中随机将一些神经元输出设置为 0,经过阻止神经元节点间的相关性来削减过拟合。
import paddle
import paddle.nn as nn
# 界说动态图
class Classification(paddle.nn.Layer):
def __init__(self):
super(Classification, self).__init__()
nn.Tanh
nn.PReLU
self.drop = paddle.nn.Dropout(p=0.5)
self.fc1 = paddle.nn.Linear(12, 64)
self.fc2 = paddle.nn.Linear(64, 32)
self.fc3 = paddle.nn.Linear(32, 16)
self.fc4 = paddle.nn.Linear(16, 8)
self.fc5 = paddle.nn.Linear(8, 1)
self.Tanh = nn.Tanh()
self.PReLU = nn.PReLU()
# 网络的前向核算函数
def forward(self, inputs):
x = self.Tanh(self.fc1(inputs))
x = self.drop(x)
x = self.PReLU(self.fc2(x))
x = self.drop(x)
x = self.PReLU(self.fc3(x))
x = self.drop(x)
x = self.PReLU(self.fc4(x))
x = self.drop(x)
pred = self.fc5(x)
return pred
4. 模型练习
4.1 界说可视化函数
- 在练习后能够运转可视化函数,对练习丢失进行可视化
- 可视化函数界说如下,重点是取得iter与cost之间的改变联系
# 界说制作练习进程的丢失值改变趋势的办法draw_train_process
train_nums = []
train_costs = []
def draw_train_process(iters,train_costs):
title="training cost"
plt.title(title, fontsize=24)
plt.xlabel("iter", fontsize=14)
plt.ylabel("cost", fontsize=14)
plt.plot(iters, train_costs,color='red',label='training cost')
plt.grid()
plt.show()
4.2 界说丢失函数
- 丢失函数运用的是k1丢失,需求自己界说一下丢失函数。
- 当然,也能够测验运用其他的丢失函数,例如均方差错丢失。
- k1丢失函数界说如下:
import paddle
import paddle.nn.functional as F
class kl_loss(paddle.nn.Layer):
def __init__(self):
super(kl_loss, self).__init__()
def forward(self, p, q, label):
ce_loss = 0.5 * (F.mse_loss(p, label=label)) + F.mse_loss(q, label=label)
kl_loss = self.compute_kl_loss(p, q)
# carefully choose hyper-parameters
loss = ce_loss + 0.3 * kl_loss
return loss
def compute_kl_loss(self, p, q):
p_loss = F.kl_div(F.log_softmax(p, axis=-1), F.softmax(q, axis=-1), reduction='none')
q_loss = F.kl_div(F.log_softmax(q, axis=-1), F.softmax(p, axis=-1), reduction='none')
# You can choose whether to use function "sum" and "mean" depending on your task
p_loss = p_loss.sum()
q_loss = q_loss.sum()
loss = (p_loss + q_loss) / 2
return loss
4.3 模型练习
模型参数设置如下:
- 练习轮数:5
- batch_size:64
- 丢失函数:kl_loss
如果内存空间不是很大,batch_size也不适合挑选太大,能够设置稍微少一些
import paddle.nn.functional as F
y_preds = []
labels_list = []
BATCH_SIZE = 64
train_data = x_train
train_data_y = y_train
test_data = x_test
test_data_y = y_test
compute_kl_loss = kl_loss()
CET_loss = paddle.nn.CrossEntropyLoss()
def train(model):
print('start training ... ')
# 敞开模型练习模式
model.train()
EPOCH_NUM = 5
train_num = 0
scheduler = paddle.optimizer.lr.CosineAnnealingDecay(learning_rate=0.001, T_max=int(train_data.shape[0]/BATCH_SIZE*EPOCH_NUM), verbose=False)
optimizer = paddle.optimizer.Adam(learning_rate=scheduler, parameters=model.parameters())
for epoch_id in range(EPOCH_NUM):
# 在每轮迭代开端之前,将练习数据的次序随机的打乱
np.random.shuffle(train_data)
# 将练习数据进行拆分,每个batch包括64条数据
mini_batches = [np.append(train_data[k: k+BATCH_SIZE], train_data_y[k: k+BATCH_SIZE], axis = 1) for k in range(0, len(train_data), BATCH_SIZE)]
for batch_id, data in enumerate(mini_batches):
features_np = np.array(data[:, :12], np.float32)
labels_np = np.array(data[:, -1:], np.float32)
features = paddle.to_tensor(features_np)
labels = paddle.to_tensor(labels_np)
#前向核算
# y_pred = model(features)
y_pred1 = model(features)
y_pred2 = model(features)
cost = compute_kl_loss(y_pred1, y_pred2, label=labels)
# cost = CET_loss(y_pred, labels)
# cost = F.mse_loss(y_pred, label=labels)
train_cost = cost.numpy()[0]
#反向传达
cost.backward()
#最小化loss,更新参数
optimizer.step()
# 清除梯度
optimizer.clear_grad()
if batch_id % 500 == 0 and epoch_id % 1 == 0:
print("Pass:%d,Cost:%0.5f"%(epoch_id, train_cost))
train_num = train_num + BATCH_SIZE
train_nums.append(train_num)
train_costs.append(train_cost)
model = Classification()
train(model)
运转练习函数,神经网络模型就能够练习起来了。部分练习成果如下图所示:
5. 模型猜测
测验集样本量较大,能够挑选猜测一个样本,也能够猜测部分样本值。
- 界说猜测函数,然后运用猜测函数对测验集杨嫩
train_data = x_train
train_data_y = y_train
test_data = x_test
test_data_y = y_test
def predict(model):
print('start evaluating ... ')
model.eval()
outputs = []
mini_batches = [np.append(test_data[k: k+BATCH_SIZE], test_data_y[k: k+BATCH_SIZE], axis = 1) for k in range(0, len(test_data), BATCH_SIZE)]
for data in mini_batches:
features_np = np.array(data[:, :12], np.float32)
features = paddle.to_tensor(features_np)
pred = model(features)
out = paddle.argmax(pred, axis=1)
outputs.extend(out.numpy())
return outputs
outputs = predict(model)
6. 核算目标
6.1 Mean Squared Error(MSE) 均方差错
- 关于猜测的成果,咱们能够进行模型评价
- 咱们挑选MSE目标进行评价
from sklearn.metrics import mean_squared_error
print(mean_squared_error(test_data_y,outputs))
7. 总结
本文持续上一篇文章,完成了用户上网反常剖析项意图数据预处理,模型建立,模型猜测,模型评价过程。对上网反常数据进行了猜测。
-
本项目建立神经网络实现了对UEBA用户上网反常回归猜测。
-
往后能够测验的改善方向总结如下:
- 持续挖掘特征与目标值的联系
- 由于数据集特征有限,能够考虑进一步丰厚数据特征。
- 能够考虑运用其他网络模型,例如卷积网络,对该数据集进行回归猜测,剖析其作用。
- 另外,能够测验运用不同的丢失函数对模型进一步优化。
本文正在参与「金石计划 . 分割6万现金大奖」