深度学习网络入侵检测

前几天deepseek官网上老挂着“近期受到海量网络攻击”的提示,有点感兴趣,研究了一点基于深度学习的网络入侵检测方法。找了个开源代码,用CNN检测的,学习一下当入门吧。

1. 先让代码跑起来

训它10个epoch看看(源码图轴标签就是反的,跟我没关系)

  

预测结果

但是有个问题,原代码生成的训练数据是包含标签的,这个操作就很搞(数据第42个特征是标签,按原代码操作训练数据会包含标签,这样就很没有意义)

2. 把代码改的面目全非

训练结果,虽然不是inf,但是调试确定爆炸了

3. 换几个模型结构搞搞

换成两个块的resnet,数据归一化,加BatchNorm层


# 模型
import torch
from torch import nn
class MyAlexNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.ReLU = nn.ReLU()  # 实例化
        self.Softmax = nn.Softmax(dim=1)  #! CrossEntropyLoss损失函数包含Softmax层
        self.norm = nn.BatchNorm2d(16)  #? BatchNormal的作用为何这么大
        self.conv_in = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, padding=1, stride=1)
        self.conv = nn.Conv2d(in_channels=16, out_channels=16, kernel_size=3, padding=1, stride=1)
        self.conv_trans = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=1)  # 维度变换
        self.pool = nn.AvgPool2d(kernel_size=2, stride=2)
        self.flatten = nn.Flatten()
        self.line = nn.Linear(576, 5)

    def forward(self, img:torch.tensor):
        x1 = self.conv_in(img)
        x1 = self.norm(x1)
        x1 = self.ReLU(x1)
        x1 = self.conv(x1)
        x1 = self.norm(x1)
        y = self.conv_trans(img)
        y = self.norm(y)
        x1 = x1 + y
        x1 = self.ReLU(x1)
        x2 = self.conv(x1)
        x2 = self.norm(x2)
        x2 = self.ReLU(x2)
        x2 = self.conv(x2)
        x2 = self.norm(x2)
        x2 = self.norm(x2)
        x2 = x2 + x1
        x2 = self.ReLU(x2)
        x3 = self.pool(x2)
        x3 = self.flatten(x3)
        x3 = nn.functional.dropout(x3, 0.2) / 0.8
        x3 = self.line(x3)
        # x3 = self.Softmax(x3)
        return x3

    
# 数据特征
PROTOCOL = ('tcp', 'udp', 'icmp')
SERVICE = ('aol','auth','bgp','courier','csnet_ns','ctf','daytime','discard',
            'domain','domain_u','echo','eco_i','ecr_i','efs','exec','finger',
                  'ftp','ftp_data','gopher','harvest','hostnames','http','http_2784',
                  'http_443','http_8001','imap4','IRC','iso_tsap','klogin','kshell',
                  'ldap','link','login','mtp','name','netbios_dgm','netbios_ns','netbios_ssn',
                  'netstat','nnsp','nntp','ntp_u','other','pm_dump','pop_2','pop_3','printer',
                  'private','red_i','remote_job','rje','shell','smtp','sql_net','ssh',
                  'sunrpc','supdup','systat','telnet','tftp_u','tim_i','time','urh_i',
                  'urp_i','uucp','uucp_path','vmnet','whois','X11','Z39_50')
FLAG = ('OTH','REJ','RSTO','RSTOS0','RSTR','S0','S1','S2','S3','SF','SH')
CLASS = {'NORMAL':('normal'),
        'PROBE':('ipsweep','mscan','nmap','portsweep','saint','satan'),
         'DOS':('apache2','back','land','mailbomb','neptune','pod','processtable','smurf','teardrop','udpstorm'),
         'U2R':('buffer_overflow','httptunnel','loadmodule','perl','ps','rootkit','sqlattack','xterm'),
         'R2L':('ftp_write', 'guess_passwd', 'imap', 'multihop', 'named', 'phf', 'sendmail', 'snmpgetattack', 'snmpguess', 'spy', 'warezclient', 'warezmaster', 'worm', 'xlock', 'xsnoop')}

# 预处理
'''每条数据包含43个元素,其中第2、3、4、42个元素为字符串'''
PROTOCOL_IND, SERVICE_IND, FLAG_IND, CLASS_IND = 1, 2, 3, 41
def seq2img(dat:list[str]):
    # 独热码编码
    lal = [0 for i in range(len(CLASS))]  # 数据标签
    for ind, clas in enumerate(CLASS):  #先分类,再编码
        if dat[CLASS_IND] in CLASS[clas]:
            lal[ind] = 1
            break
    lal = torch.Tensor(lal)
    
    protocol_encod = [0 for i in range(len(PROTOCOL))]
    protocol_encod[PROTOCOL.index(dat[PROTOCOL_IND])] = 1

    service_encod = [0 for i in range(len(SERVICE))]
    service_encod[SERVICE.index(dat[SERVICE_IND])] = 1

    flag_encod = [0 for i in range(len(FLAG))]
    flag_encod[FLAG.index(dat[FLAG_IND])] = 1

    # 替换拼接
    dat = list(map(float, dat[:PROTOCOL_IND])) + protocol_encod +\
            list(map(float, dat[PROTOCOL_IND+1:SERVICE_IND])) + service_encod +\
                list(map(float, dat[SERVICE_IND+1:FLAG_IND])) + flag_encod +\
                    list(map(float, dat[FLAG_IND+1:-2]))
    #print(dat)
    # 归一化
    dat[0] = dat[0] / 54451
    dat[4+74] = dat[4+74] / 1379963888
    dat[5+74] = dat[5+74] / 309937401
    dat[7+74] = dat[7+74] / 3
    dat[8+74] = dat[8+74] / 3
    dat[9+74] = dat[9+74] / 101
    dat[10+74] = dat[10+74] / 4
    dat[12+74] = dat[12+74] / 7479
    dat[14+74] = dat[14+74] / 2
    dat[15+74] = dat[15+74] / 7468
    dat[16+74] = dat[16+74] / 100
    dat[17+74] = dat[17+74] / 2
    dat[18+74] = dat[18+74] / 9
    dat[22+74] = dat[22+74] / 511
    dat[23+74] = dat[23+74] / 511
    dat[31+74] = dat[31+74] / 255
    dat[32+74] = dat[32+74] / 255

    # 格式转换 
    '''41 + 3 + 70 + 11 - 3 = 122 补零到12^2=144'''
    dat = torch.Tensor(np.asarray(dat + [0 for i in range(144-122)]) * 255)
    img = torch.reshape(dat, (1, 12, 12))
    # plt.imshow(img.squeeze())
    # plt.show()
    return img, lal


# 数据载入
from torch.utils.data import Dataset, DataLoader
import numpy as np
class myDataset(Dataset):  # 重写Dataset
    def __init__(self, data_pth):
        self.data = np.loadtxt(data_pth, dtype=str, delimiter=',')

    def __getitem__(self, index):
        return seq2img(self.data[index])

    def __len__(self):
        return len(self.data)  # 行数

# 模型训练
if __name__ == '__main__':
    BATCH_SIZE = 10
    # 载入数据
    pth = 'DataSet/NSL-KDD/KDDTrain+.txt'
    dataset = myDataset(pth)
    data = DataLoader(dataset=dataset, batch_size=BATCH_SIZE, shuffle=True)
    # print(data.__len__())
    # 准备
    dev = 'cuda' if torch.cuda.is_available() else 'cpu'
    print(dev + ' is ready!')
    net = MyAlexNet().to(dev)  # 模型
    los = nn.CrossEntropyLoss()  # 损失
    opt = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9)  # 优化器
    lr = torch.optim.lr_scheduler.StepLR(opt, step_size=1, gamma=0.5)  # lr更新
    # 训练
    EPOCH_NUM = 10
    for epoch in range(EPOCH_NUM):
        print('#'+str(epoch))
        record = 0
        for n, (img, lab) in enumerate(data):
            img, lab = img.to(dev), lab.to(dev)
            opt.zero_grad()  # 梯度归零
            outp = net(img)
            # print(outp)
            # print(lab)
            loss = los(outp, lab) # 计算损失
            loss.backward()  # 反向传播
            opt.step()  # 更新
            record += loss.item()
        lr.step()  # 调整学习率
        print('Loss:'+str(record / (n+1)))
    # 保存模型
    torch.save(net.state_dict(), 'Mould/net.pth')

    # 载入数据
    #pth = 'DataSet/NSL-KDD/KDDTrain+.txt'
    pth = 'DataSet/NSL-KDD/KDDTest+.txt'
    dataset = myDataset(pth)
    data = DataLoader(dataset=dataset, batch_size=BATCH_SIZE, shuffle=True)
    # print(data.__len__())
    # 准备ceshi
    dev = 'cuda' if torch.cuda.is_available() else 'cpu'
    print(dev + ' is ready!')
    net = MyAlexNet()
    net.load_state_dict(torch.load("Mould/net.pth", weights_only=True))
    net.to(dev)
    net.eval()
    # 训练
    acc = 0
    with torch.no_grad():
        for n, (img, lab) in enumerate(data):
            img, lab = img.to(dev), lab.to(dev)
            outp = net(img)
            _, pred = torch.max(outp, axis=1)
            _, real = torch.max(lab, axis=1)
            acc += torch.sum(pred == real) / BATCH_SIZE
        print(acc / (n+1))

结果:训练10个批次,banch_size为10,然后测试训练集准确率50%;测试集准确率45.2%。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值