diff --git a/LYZ/BiLSTM.py b/LYZ/BiLSTM.py new file mode 100644 index 0000000..32f1078 --- /dev/null +++ b/LYZ/BiLSTM.py @@ -0,0 +1,185 @@ +""" +Task: 基于Bi-LSTM和注意力机制的文本情感分类 +Author: ChengJunkai @github.com/Cheng0829 +Email: chengjunkai829@gmail.com +Date: 2022/09/14 +Reference: Tae Hwan Jung(Jeff Jung) @graykode +""" + +import numpy as np +import torch, time, os, sys +import torch.nn as nn +import torch.optim as optim +import torch.nn.functional as F +import matplotlib.pyplot as plt + +'''1.数据预处理''' + + +def pre_process(sentences): + word_sequence = " ".join(sentences).split() + word_list = [] + ''' + 如果用list(set(word_sequence))来去重,得到的将是一个随机顺序的列表(因为set无序), + 这样得到的字典不同,保存的上一次训练的模型很有可能在这一次不能用 + (比如上一次的模型预测碰见i:0,love:1,就输出you:2,但这次模型you在字典3号位置,也就无法输出正确结果) + ''' + for word in word_sequence: + if word not in word_list: + word_list.append(word) + word_dict = {w: i for i, w in enumerate(word_list)} + word_dict["''"] = len(word_dict) + word_list = word_list.append("''") + vocab_size = len(word_dict) # 词库大小16 + max_size = 0 + for sen in sentences: + if len(sen.split()) > max_size: + max_size = len(sen.split()) # 最大长度3 + for i in range(len(sentences)): + if len(sentences[i].split()) < max_size: + sentences[i] = sentences[i] + " ''" * (max_size - len(sentences[i].split())) + + return sentences, word_list, word_dict, vocab_size, max_size + + +def make_batch(sentences): + # 对于每个句子,返回包含句子内每个单词序号的列表 + inputs = [np.array([word_dict[n] for n in sen.split()]) for sen in sentences] # [6,3] + targets = [out for out in labels] + inputs = torch.LongTensor(np.array(inputs)).to(device) + targets = torch.LongTensor(np.array(targets)).to(device) + '''情感分类构建嵌入矩阵,没有eye()''' + return inputs, targets + + +class BiLSTM_Attention(nn.Module): + def __init__(self): + super(BiLSTM_Attention, self).__init__() + '''情感分类构建嵌入矩阵,没有eye()''' + self.embedding = nn.Embedding(vocab_size, embedding_dim) + self.lstm = nn.LSTM(embedding_dim, n_hidden, bidirectional=True) + self.out = nn.Linear(2 * n_hidden, num_classes) + + def forward(self, X): # X: [6, 3] + # input : [batch_size, n_step, embedding_dim] [6,3,2] + input = self.embedding(X) + # input : [n_step, batch_size, embedding_dim] [3,6,2] + # input : [输入序列长度(时间步长度),样本数,嵌入向量维度] + input = input.permute(1, 0, 2) + # hidden_state : [num_layers(=1)*num_directions(=2), batch_size, n_hidden] + # hidden_state : [层数*网络方向,样本数,隐藏层的维度(隐藏层神经元个数)] + hidden_state = torch.zeros(1 * 2, len(X), n_hidden).to(device) + # cell_state : [num_layers*num_directions, batch_size, hidden_size] + # cell_state : [层数*网络方向,样本数,隐藏层的维度(隐藏层神经元个数)] + cell_state = torch.zeros(1 * 2, len(X), n_hidden).to(device) + # final_hidden_state, final_cell_state : [num_layers(=1)*num_directions(=2), batch_size, n_hidden] + ltsm_output, (final_hidden_state, final_cell_state) = self.lstm(input, (hidden_state, cell_state)) + # ltsm_output : [batch_size, n_step, n_hidden*num_directions(=2)] + ltsm_output = ltsm_output.permute(1, 0, 2) + attn_output, attention = self.attention_net(ltsm_output, final_hidden_state) + # model : [batch_size, num_classes], attention : [batch_size, n_step] + return self.out(attn_output), attention + + '''两次bmm加权求和,相当于两次for循环''' + + # lstm_output : [batch_size, n_step, n_hidden*num_directions(=2)] [6,3,16] + # final_hidden_state : [num_layers(=1)*num_directions(=2), batch_size, n_hidden] [2,6,8] + def attention_net(self, lstm_output, final_hidden_state): + # final_hidden_state : [batch_size, n_hidden*num_directions(=2), 1(=n_layer)] [6,16,1] + final_hidden_state = final_hidden_state.view(-1, 2 * n_hidden, 1) + + '''第一次bmm加权求和:: lstm_output和final_hidden_state生成注意力权重attn_weights''' + # [6,3,16]*[6,16,1] -> [6,3,1] -> attn_weights : [batch_size, n_step] [6,3] + attn_weights = torch.bmm(lstm_output, final_hidden_state).squeeze(2) # 第3维度降维 + softmax_attn_weights = F.softmax(attn_weights, 1) # 按列求值 [6,3] + + '''第二次bmm加权求和 : lstm_output和注意力权重attn_weights生成上下文向量context,即融合了注意力的模型输出''' + # [batch_size, n_hidden*num_directions, n_step] * [batch_size,n_step,1] \ + # = [batch_size, n_hidden*num_directions, 1] : [6,16,3] * [6,3,1] -> [6,16,1] -> [6,16] + context = torch.bmm(lstm_output.transpose(1, 2), softmax_attn_weights.unsqueeze(2)).squeeze(2) + softmax_attn_weights = softmax_attn_weights.to('cpu') # numpy变量只能在cpu上 + + '''各个任务求出context之后的步骤不同,LSTM的上下文不需要和Seq2Seq中的一样和decoder_output连接''' + return context, softmax_attn_weights.data.numpy() + + +if __name__ == '__main__': + chars = 30 * '*' + embedding_dim = 3 # embedding size + n_hidden = 8 # number of hidden units in one cell + num_classes = 2 # 0 or 1 + '''GPU比CPU慢的原因大致为: + 数据传输会有很大的开销,而GPU处理数据传输要比CPU慢, + 而GPU在矩阵计算上的优势在小规模神经网络中无法明显体现出来 + ''' + device = ['cuda:0' if torch.cuda.is_available() else 'cpu'][0] + # 3 words sentences (=sequence_length is 3) + sentences = ["i love you", "he loves me", "don't leave", + "i hate you", "sorry for that", "this is awful"] + labels = [1, 1, 1, 0, 0, 0] # 1 is good, 0 is not good. + + '''1.数据预处理''' + sentences, word_list, word_dict, vocab_size, max_size = pre_process(sentences) + inputs, targets = make_batch(sentences) + + '''2.构建模型''' + model = BiLSTM_Attention() + print(model) + model.to(device) + criterion = nn.CrossEntropyLoss() # 交叉熵损失 + optimizer = optim.Adam(model.parameters(), lr=0.001) + + if os.path.exists('model_param.pt'): + # 加载模型参数到模型结构 + model.load_state_dict(torch.load('model_param.pt', map_location=device)) + + '''3.训练''' + print('{}\nTrain\n{}'.format('*' * 30, '*' * 30)) + loss_record = [] + for epoch in range(10000): + optimizer.zero_grad() + output, attention = model(inputs) + output = output.to(device) + loss = criterion(output, targets) + loss.backward() + optimizer.step() + # print(loss) + if loss >= 0.001: # 连续30轮loss小于0.01则提前结束训练 + loss_record = [] + else: + loss_record.append(loss.item()) + if len(loss_record) == 30: + torch.save(model.state_dict(), 'model_param.pt') + break + + if (epoch + 1) % 1000 == 0: + print('Epoch:', '%04d' % (epoch + 1), 'Loss = {:.6f}'.format(loss)) + torch.save(model.state_dict(), 'model_param.pt') + + '''4.测试''' + print('{}\nTest\n{}'.format('*' * 30, '*' * 30)) + test_text = 'sorry i hate you' + # 返回包含每个单词序号的列表矩阵(为了有2个维度,还要加一个中括号升维) + tests = [np.array([word_dict[n] for n in test_text.split()])] + test_batch = torch.LongTensor(np.array(tests)).to(device) + predict, attn_test = model(test_batch) + predict = predict.data.max(1, keepdim=True)[1] + print('The emotion of "%s" is ' % test_text, end='') + if predict[0][0] == 0: + print('bad!') + else: + print('good!') + + '''5.可视化注意力权重矩阵''' + fig = plt.figure(figsize=(0.5 * len(sentences), 0.5 * len(sentences[0]))) # [batch_size, n_step] + ax = fig.add_subplot(1, 1, 1) + # attention : (6, 3) + ax.matshow(attention, cmap='viridis') + word_show = ['单词'] * len(sentences[0]) + word_show = [word_show[i] + str(i + 1) for i in range(len(sentences[0]))] # ['word_1', 'word_2', 'word_3'] + ax.set_xticklabels([''] + word_show, fontdict={'fontsize': 14}, fontproperties='SimSun') + sentence_show = ['句子'] * len(sentences) + sentence_show = [sentence_show[i] + str(i + 1) for i in range( + len(sentence_show))] # ['sentence_1', 'sentence_2', 'sentence_3', 'sentence_4', 'sentence_5', 'sentence_6'] + ax.set_yticklabels([''] + sentence_show, fontdict={'fontsize': 14}, fontproperties='SimSun') + plt.show() diff --git a/LYZ/FCN_Transformer.py b/LYZ/FCN_Transformer.py new file mode 100644 index 0000000..e56962c --- /dev/null +++ b/LYZ/FCN_Transformer.py @@ -0,0 +1,530 @@ +# -*- coding: utf-8 -*- +""" +Transformer编码器网络并行构建两个并行卷积神经网络(CNN)来对流量数据进行识别。将CNN用于空间特征表示, Transformer用于时间特征表示。 + +由于数据的顺序性质, 我们还将使用Transformer尝试尽可能准确地模拟情绪中音调转换之间的时间关系。 + +堆叠的CNN网络结合了来自变压器编码器的多头自关注层。 + +**利用CNN在空间特征表示方面的优势和Transformer在序列编码方面的优势 + +改进:并行化CNN,或者借鉴bert双向结构 +#### Setup +""" + +import torch +import torch.nn as nn +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import os, glob, time +import pickle +from timeit import default_timer as timer + +# matplot lib complains about librosa +import warnings +warnings.filterwarnings('ignore') + + +# classes index +traffic_dict ={ + 0: 'Normal', + 1: 'BFSSH', + 2: 'Infilt', + 3: 'HttpDoS', + 4: 'DDoS' +} + +# network traffic attributes +traffic_attributes = { + '01': 'normal', # 正常流量 + '02': 'anomaly' # abnormal +} + +"""## Load Data +""" + +# path to data for glob +DATA_DIR = 'D:\\PyProject\\malware_traffic\\3_Packet\\' + +def load_data(): + """ + 加载数据 + :return: + """ + t1 = timer() + sessions = [] + labels = [] + num_pkls = len(glob.glob(DATA_DIR + 'ISCX2012_labels_*.pkl')) # 匹配路径 + for i in range(num_pkls): + # if i != 1: + # continue + session_pkl = DATA_DIR + 'ISCX2012_pcaps_' + str(i) + '.pkl' + session_lists = pickle.load(open(session_pkl, 'rb')) # 反序列化对象 + sessions.extend(session_lists.values.tolist()) # 追加元素 + + label_pkl = DATA_DIR + 'ISCX2012_labels_' + str(i) + '.pkl' + label_lists = pickle.load(open(label_pkl, 'rb')) + labels.extend(label_lists.values.tolist()) + print(i) + t2 = timer() + print("load data tims: ", t2 - t1) + + labels = np.array(labels) + normal_indices = np.where(labels == 0)[0] # 结果所在的 行, 是个array + # 数据量太大, 不好训练。以下注释代码可以选择100000条正常流量进入训练(建议在数据预处理阶段选择一定数量的正常数据——节约内存开支) + normal_indices = np.random.choice(normal_indices, 100000, replace=False) # 注释代码 + attack_indices = [np.where(labels == i)[0] for i in range(1, 5)] # label 1~4 所在行, 是个 list + # np.random.choice 会重复抽样, 若想不重复, 增加参数:replace=False + test_normal_indices = np.random.choice(normal_indices, int(len(normal_indices) * 0.4), replace=False) + test_attack_indices = np.concatenate( # 模态融合 + [np.random.choice(attack_indices[i], int(len(attack_indices[i]) * 0.4), replace=False) for i in range(4)]) + test_indices = np.concatenate([test_normal_indices, test_attack_indices]).astype(int) + # train_indices = np.array(list(set(np.arange(len(labels))) - set(test_indices))) + attack_indices = np.concatenate(attack_indices).astype(int) # 注释代码 + indices = np.concatenate([normal_indices, attack_indices]).astype(int) # 注释代码 + train_indices = np.array(list(set(indices) - set(test_indices))) # 注释代码 + + return sessions, labels, train_indices, test_indices + + + +"""# Architecture Overview + +# CNN Motivation +** 构建两个并行卷积神经网络(CNN)来对流量数据进行空间特征表示 + +# Transformer-Encoder Motivation +**使用了Transformer-Encoder层 +**I maxpool 映射到Transformer, 以大大减少网络需要学习的参数数量 +""" + + +class ByteBlock(nn.Module): + """ + 1D FCN: 1维全卷积神经网络 + + in_channels:输入通道数, 在一维卷积中由于不存在通道数, 因此in_channels的数值为词向量的维度, 如果一个单词用128维向量表示, 那么in_channels = 128 + + out_channels:输出通道数, 表示经过卷积之后, 一个词向量嵌入维度应该为多少。如果out_channels = 64, 那么经过本次卷积之后的每个词的嵌入维度为64。 + + kernel_size:卷积核大小, 表示本次卷积核的维度, 一般是赋值为int类型。kernel_size=3, 表示每次卷积计算操作涉及到3个词, 也就是卷积核维度被设为(in_channels, kernel_size)。 + - 在Pytorch中, 对于一条语句序列数据的每个词都是用一个列向量表示 + + stride:滑动步长, 表示在卷积方向上滑动的步长。stride=2, 表示在当前卷积的范围为123, 下一个卷积范围就是345。 + + padding:填补操作, 表示在对特征矩阵剩余部分不足卷积时的操作。 + - str --> padding =“valid”:表示不填充, 剩余部分丢弃。 padding =“same”:表示在右侧填充之后要求输入输出序列长度一致 + - int --> padding = k: 表示在右侧填充k列 + """ + def __init__(self, in_channels, nb_filter=(64, 100), filter_length=(3, 3), + subsample=(2, 1), pool_length=(2, 2)): + super(ByteBlock, self).__init__() + + layers = [] + for i in range(len(nb_filter)): + layers.append(nn.Conv1d(in_channels, nb_filter[i], kernel_size=filter_length[i], + padding=0, stride=subsample[i])) + layers.append(nn.Tanh()) + if pool_length[i]: + layers.append(nn.MaxPool1d(pool_length[i])) + in_channels = nb_filter[i] + + self.block = nn.Sequential(*layers) + self.global_pool = nn.AdaptiveMaxPool1d(1) + + + def forward(self, x): + x = self.block(x) + x = self.global_pool(x).squeeze(dim=2) + x = torch.nn.functional.leaky_relu(x) + return x + +class FCN_Transformer(nn.Module): + # Define all layers present in the network + def __init__(self,num_emotions): + super().__init__() + + ################ TRANSFORMER BLOCK ############################# + self.transformer_maxpool = nn.MaxPool1d(2) + + # define single transformer encoder layer + transformer_layer = nn.TransformerEncoderLayer( + d_model=128, # 输入特征维度 + nhead=4, # 注意力头数 + dim_feedforward=512, # 前馈神经网络中隐藏层的维度。 + dropout=0.2, + activation='relu' + ) + + # Using 4 identical stacked encoder layers + self.transformer_encoder = nn.TransformerEncoder(transformer_layer, num_layers=4) + + # 1 sequential conv1D layers + self.conv1Dblock1 = ByteBlock(128, (128, 256), (5, 5), (1, 1), (2, 2)) + self.conv1Dblock2 = ByteBlock(128, (192, 320), (7, 5), (1, 1), (2, 2)) + + self.fc1_linear = nn.Linear(512*2+40,num_emotions) + + ### Softmax layer for the n output logits from final FC linear layer + self.softmax_out = nn.Softmax(dim=1) + + # define one complete parallel fwd pass of input feature tensor thru 2*conv+1*transformer blocks + def forward(self,x): + + conv1d_embedding1 = self.conv1Dblock1(x) # x == N/batch * channel * freq * time + + conv1d_embedding1 = torch.flatten(conv1d_embedding1, start_dim=1) + + conv1d_embedding2 = self.conv1Dblock2(x) + + conv1d_embedding2 = torch.flatten(conv1d_embedding2, start_dim=1) + + + ########## 4-encoder-layer Transformer block ############## + x_maxpool = self.transformer_maxpool(x) + + x_maxpool_reduced = torch.squeeze(x_maxpool,1) + + # convert maxpooled feature map format: batch * freq * time ---> time * batch * freq format + # because transformer encoder layer requires tensor in format: time * batch * embedding (freq) + x = x_maxpool_reduced.permute(2,0,1) + # print("x_maxpool_reduced: ",x_maxpool_reduced.shape) + + transformer_output = self.transformer_encoder(x) + + transformer_embedding = torch.mean(transformer_output, dim=0) # dim + + complete_embedding = torch.cat([conv1d_embedding1, conv1d_embedding2,transformer_embedding], dim=1) + + output_logits = self.fc1_linear(complete_embedding) + + output_softmax = self.softmax_out(output_logits) + + return output_logits, output_softmax + + +"""# 查看模型结构 +""" +from torchsummary import summary + +# need device to instantiate model +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +# instantiate model for 8 emotions and move to CPU for summary +model = FCN_Transformer(len(traffic_dict)).to(device) +print("\nmodel: \n", model) +# include input feature map dims in call to summary() +summary(model, input_size=(128,200,512)) + + +"""## Define Loss/Criterion +""" +# define loss function; CrossEntropyLoss() fairly standard for multiclass problems +def criterion(predictions, targets): + return nn.CrossEntropyLoss()(input=predictions, target=targets) + +"""## Choose Optimizer +https://github.com/IliaZenkov/transformer-cnn-emotion-recognition/blob/main/Parallel_is_All_You_Want.py +有说为什么选SGD +# optimizer = torch.optim.SGD(model.parameters(),lr=0.01, weight_decay=1e-3, momentum=0.8) +""" +optimizer = torch.optim.Adam(model.parameters(), lr=0.001) + + +"""## Define Training Step +定义了一个函数来返回单个训练步骤, 定义了模型的一次迭代。 + 1、正向传递输出logits和softmax概率。 + 2、记录softmax概率以跟踪准确性。 + 3、将输出logits传递给损失函数以计算损失。 + 4、调用带损失函数的反向传递(反向传播错误)。 + 5、告诉优化器对网络参数应用一个更新步骤。 + 6、为下一次迭代将优化器中的累积梯度归零。 +""" +# define function to create a single step of the training phase +def make_train_step(model, criterion, optimizer): + + # define the training step of the training phase + def train_step(X,Y): + + # forward pass + output_logits, output_softmax = model(X) + predictions = torch.argmax(output_softmax,dim=1) + accuracy = torch.sum(Y==predictions)/float(len(Y)) + + # compute loss on logits because nn.CrossEntropyLoss implements log softmax + loss = criterion(output_logits, Y) + + # compute gradients for the optimizer to use + loss.backward() + + # update network parameters based on gradient stored (by calling loss.backward()) + optimizer.step() + + # zero out gradients for next pass + # pytorch accumulates gradients from backwards passes + optimizer.zero_grad() + + return loss.item(), accuracy*100 + return train_step + +"""## Define Validation Step +定义一个函数, 在10%的X,y张量对上返回一个验证步骤, 以了解模型在训练时的泛化性, 以便确定是否以及何时停止它并调整超参数。 +通过将model设置为验证模式来确保在验证过程中不更新网络参数。不要在验证阶段通过设置torch.no_grad()来浪费资源计算梯度。 +""" +def make_validate_fnc(model,criterion): + def validate(X,Y): + + # don't want to update any network parameters on validation passes: don't need gradient + # wrap in torch.no_grad to save memory and compute in validation phase: + with torch.no_grad(): + + # set model to validation phase i.e. turn off dropout and batchnorm layers + model.eval() + + # get the model's predictions on the validation set + output_logits, output_softmax = model(X) + predictions = torch.argmax(output_softmax,dim=1) + + # calculate the mean accuracy over the entire validation set + accuracy = torch.sum(Y==predictions)/float(len(Y)) + + # compute error from logits (nn.crossentropy implements softmax) + loss = criterion(output_logits,Y) + + return loss.item(), accuracy*100, predictions + return validate + +"""# Make Checkpoint Functions +在每个epoch之后保存模型状态的检查点。当对模型的性能感到满意时, 可以中断训练并加载适当的模型二进制文件。 + +-硬件/软件故障恢复培训 +-通过调整后从检查点进行训练来保存计算重新训练 +-通过保持模型最高性能版本的快照, 轻松实现早期停止 +""" +def make_save_checkpoint(): + def save_checkpoint(optimizer, model, epoch, filename): + checkpoint_dict = { + 'optimizer': optimizer.state_dict(), + 'model': model.state_dict(), + 'epoch': epoch + } + torch.save(checkpoint_dict, filename) + return save_checkpoint + +def load_checkpoint(optimizer, model, filename): + checkpoint_dict = torch.load(filename) + epoch = checkpoint_dict['epoch'] + model.load_state_dict(checkpoint_dict['model']) + if optimizer is not None: + optimizer.load_state_dict(checkpoint_dict['optimizer']) + return epoch + +"""# Build Training Loop +使用训练和验证步骤函数构建完整的训练循环。 + +
+训练循环逻辑: + + --Setup-- + 实例化 model. + 实例化模型训练和验证步骤, loss function 和 optimizer. + Move model to GPU. + + --Epoch-- + 在每个epoch后验证阶段完成后, 将模型设置为训练模式。 + Shuffle 每个epoch的训练集, 重置epoch损失和精度。 + + --Iteration-- + 维每次迭代创建 mini_batch 的 X_train, y_train 张量, 并将张量移动到GPU。 + Take 1 train step with X_train, y_train minibatch tensors. + 汇总每次迭代的准确性和损失, 但只在每个epoch之后记录。 + + --Epoch-- + 计算并记录整个epoch的验证精度, 以跟踪学习进度。 + 在每个epoch之后打印训练指标。 +""" + +# get training set size to calculate # iterations and minibatch indices +train_size = X_train.shape[0] + +# pick minibatch size (of 32... always) +minibatch = 32 + +# set device to GPU +device = 'cuda' if torch.cuda.is_available() else 'cpu' +print(f'{device} selected') + +# instantiate model and move to GPU for training +model = FCN_Transformer(num_emotions=len(traffic_dict)).to(device) +print('Number of trainable params: ',sum(p.numel() for p in model.parameters()) ) + +# instantiate the checkpoint save function +save_checkpoint = make_save_checkpoint() + +# instantiate the training step function +train_step = make_train_step(model, criterion, optimizer=optimizer) + +# instantiate the validation loop function +validate = make_validate_fnc(model,criterion) + +# instantiate lists to hold scalar performance metrics to plot later +train_losses=[] +valid_losses = [] + +# create training loop for one complete epoch (entire training set) +def train(optimizer, model, num_epochs, X_train, Y_train, X_valid, Y_valid): + + for epoch in range(num_epochs): + + # set model to train phase + model.train() + + # shuffle entire training set in each epoch to randomize minibatch order + ind = np.random.permutation(train_size) + + # shuffle the training set for each epoch: + X_train = X_train[ind,:,:,:] + Y_train = Y_train[ind] + + # instantiate scalar values to keep track of progress after each epoch so we can stop training when appropriate + epoch_acc = 0 + epoch_loss = 0 + num_iterations = int(train_size / minibatch) + + # create a loop for each minibatch of 32 samples: + for i in range(num_iterations): + + # we have to track and update minibatch position for the current minibatch + # if we take a random batch position from a set, we almost certainly will skip some of the data in that set + # track minibatch position based on iteration number: + batch_start = i * minibatch + # ensure we don't go out of the bounds of our training set: + batch_end = min(batch_start + minibatch, train_size) + # ensure we don't have an index error + actual_batch_size = batch_end-batch_start + + # get training minibatch with all channnels and 1D feature dims + X = X_train[batch_start:batch_end,:,:,:] + # get training minibatch labels + Y = Y_train[batch_start:batch_end] + + # instantiate training tensors + X_tensor = torch.tensor(X, device=device).float() + Y_tensor = torch.tensor(Y, dtype=torch.long,device=device) + + # Pass input tensors thru 1 training step (fwd+backwards pass) + loss, acc = train_step(X_tensor,Y_tensor) + + # aggregate batch accuracy to measure progress of entire epoch + epoch_acc += acc * actual_batch_size / train_size + epoch_loss += loss * actual_batch_size / train_size + + # keep track of the iteration to see if the model's too slow + print('\r'+f'Epoch {epoch}: iteration {i}/{num_iterations}',end='') + + # create tensors from validation set + X_valid_tensor = torch.tensor(X_valid,device=device).float() + Y_valid_tensor = torch.tensor(Y_valid,dtype=torch.long,device=device) + + # calculate validation metrics to keep track of progress; don't need predictions now + valid_loss, valid_acc, _ = validate(X_valid_tensor,Y_valid_tensor) + + # accumulate scalar performance metrics at each epoch to track and plot later + train_losses.append(epoch_loss) + valid_losses.append(valid_loss) + + # Save checkpoint of the model + checkpoint_filename = './checkpoints/FCN_TransformerFINAL-{:03d}.pkl'.format(epoch) + save_checkpoint(optimizer, model, epoch, checkpoint_filename) + + # keep track of each epoch's progress + print(f'\nEpoch {epoch} --- loss:{epoch_loss:.3f}, Epoch accuracy:{epoch_acc:.2f}%, Validation loss:{valid_loss:.3f}, Validation accuracy:{valid_acc:.2f}%') + +# choose number of epochs higher than reasonable so we can manually stop training +num_epochs = 100 + +# train it! +train(optimizer, model, num_epochs, X_train, y_train, X_valid, y_valid) + +"""# Check the Loss Curve's Behaviour +Let's see if we missed something egregious during training. +""" +plt.title('Loss Curve for Model') +plt.ylabel('Loss', fontsize=16) +plt.xlabel('Epoch', fontsize=16) +plt.plot(train_losses[:],'b') +plt.plot(valid_losses[:],'r') +plt.legend(['Training loss','Validation loss']) +plt.show() + + +""" +# 加载训练好的模型进行验证 +""" +# pick load folder +load_folder = './checkpoints' + +# pick the epoch to load +epoch = '60' +model_name = f'FCN_TransformerFINAL-{epoch}.pkl' + +# make full load path +load_path = os.path.join(load_folder, model_name) + +## instantiate empty model and populate with params from binary +model = FCN_Transformer(len(traffic_dict)) +load_checkpoint(optimizer, model, load_path) + +print(f'Loaded model from {load_path}') + +"""# Evaluate the Model on Hold-Out Test Set +""" + +# reinitialize validation function with model from chosen checkpoint +validate = make_validate_fnc(model,criterion) + +# Convert 4D test feature set array to tensor and move to GPU +X_test_tensor = torch.tensor(X_test,device=device).float() +# Convert 4D test label set array to tensor and move to GPU +y_test_tensor = torch.tensor(y_test,dtype=torch.long,device=device) + +# Get the model's performance metrics using the validation function we defined +test_loss, test_acc, predicted_emotions = validate(X_test_tensor,y_test_tensor) + +print(f'Test accuracy is {test_acc:.2f}%') + +""" +# Analyze Performance on Test Set +""" + +from sklearn.metrics import confusion_matrix +import seaborn as sn + +# because model tested on GPU, move prediction tensor to CPU then convert to array +predicted_emotions = predicted_emotions.cpu().numpy() +# use labels from test set +emotions_groundtruth = y_test + +# build confusion matrix and normalized confusion matrix +conf_matrix = confusion_matrix(emotions_groundtruth, predicted_emotions) +conf_matrix_norm = confusion_matrix(emotions_groundtruth, predicted_emotions,normalize='true') + +# set labels for matrix axes from emotions +emotion_names = [emotion for emotion in traffic_dict.values()] + +# make a confusion matrix with labels using a DataFrame +confmatrix_df = pd.DataFrame(conf_matrix, index=emotion_names, columns=emotion_names) +confmatrix_df_norm = pd.DataFrame(conf_matrix_norm, index=emotion_names, columns=emotion_names) + +# plot confusion matrices +plt.figure(figsize=(16,6)) +sn.set(font_scale=1.8) # emotion label and title size +plt.subplot(1,2,1) +plt.title('Confusion Matrix') +sn.heatmap(confmatrix_df, annot=True, annot_kws={"size": 18}) #annot_kws is value font +plt.subplot(1,2,2) +plt.title('Normalized Confusion Matrix') +sn.heatmap(confmatrix_df_norm, annot=True, annot_kws={"size": 13}) #annot_kws is value font + +plt.show() diff --git a/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/ChangeLog.txt b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/ChangeLog.txt new file mode 100644 index 0000000..4ed8402 --- /dev/null +++ b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/ChangeLog.txt @@ -0,0 +1,14 @@ +2013-11-09 SplitCap 2.1 + + * Support for reading PCAP data from stdin with "-r -", for example in order to run: + tcpdump -i eth0 -w - | mono SplitCap.exe -r - + +2013-06-25 SplitCap 2.0 + + * Changed from "\\" to System.IO.Path.DirectorySeparatorChar in order to run better + on Linux and other non-Windows platforms. + Hint: use Mono framework to run SplitCap in Linux. + Installation in Ubuntu with: apt-get install libmono2.0-cil + + * Added "-s seconds " and "-s packets " to split pcap files based on + time or packet count (much like editcap). \ No newline at end of file diff --git a/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/LICENSE-SplitCap.txt b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/LICENSE-SplitCap.txt new file mode 100644 index 0000000..e1ec0e5 --- /dev/null +++ b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/LICENSE-SplitCap.txt @@ -0,0 +1,19 @@ +Copyright 2008-2011, Erik Hjelmvik +SplitCap is available from http://www.netresec.com/?page=SplitCap + +SOFTWARE LICENSE + +SplitCap is licensed under the GNU General Public License Version 3. +http://www.gnu.org/licenses/gpl.html + +SplitCap uses the assemblies PacketParser and PcapFileHandler, which both stem +from the NetworkMiner open source network forensics application available at: +http://networkminer.sourceforge.net/ + +The SplitCap open source project space is available on SourceForge: +http://sourceforge.net/projects/splitcap/ + + +SplitCap was initially created as part of the Statistical Protocol IDentification +research project carried out by Erik Hjelmvik with fundings from .SE. +More info on .SE is available at: http://www.iis.se/en/ \ No newline at end of file diff --git a/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/NetworkWrapper.dll b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/NetworkWrapper.dll new file mode 100644 index 0000000..dc4a758 Binary files /dev/null and b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/NetworkWrapper.dll differ diff --git a/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/PacketParser.dll b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/PacketParser.dll new file mode 100644 index 0000000..241d55c Binary files /dev/null and b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/PacketParser.dll differ diff --git a/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/PcapFileHandler.dll b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/PcapFileHandler.dll new file mode 100644 index 0000000..877d8a2 Binary files /dev/null and b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/PcapFileHandler.dll differ diff --git a/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/SplitCap.exe b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/SplitCap.exe new file mode 100644 index 0000000..f0ce620 Binary files /dev/null and b/LYZ/Pacp-deal/0_Tool/SplitCap_2-1/SplitCap.exe differ diff --git a/LYZ/Pacp-deal/0_Tool/finddupe.exe b/LYZ/Pacp-deal/0_Tool/finddupe.exe new file mode 100644 index 0000000..479854c Binary files /dev/null and b/LYZ/Pacp-deal/0_Tool/finddupe.exe differ diff --git a/LYZ/Pacp-deal/1-1_ProcessFlow.py b/LYZ/Pacp-deal/1-1_ProcessFlow.py new file mode 100644 index 0000000..41475a8 --- /dev/null +++ b/LYZ/Pacp-deal/1-1_ProcessFlow.py @@ -0,0 +1,55 @@ +# Author: @vinesmsuic +# +# + +import os +import shutil +from tqdm import tqdm +import random +import argparse + +def parser(): + parser = argparse.ArgumentParser(description="Copying files") + parser.add_argument("--limit", type=int, required=False, default=-1, help="only copy a number of files each folder") + return parser.parse_args() + +def main(): + args = parser() + + src_dir = os.path.join('2_Flow','AllLayers') + dst_dir = os.path.join('2_Flow_Processed','AllLayers') + + if not os.path.exists(dst_dir): + os.makedirs(dst_dir) + + folders = os.listdir(src_dir) + for folder in folders: + + if not os.path.exists(os.path.join(dst_dir,folder)): + os.makedirs(os.path.join(dst_dir,folder)) + + if(os.path.isdir(os.path.join(dst_dir,folder))): + + print("Now Processing Folder: ", folder) + + copying_folders = os.listdir(os.path.join(src_dir,folder)) + + random.seed(72) + random.shuffle(copying_folders) + + if(args.limit!= -1): + if(len(copying_folders) > args.limit): + copying_folders = copying_folders[:args.limit] + elif(len(copying_folders) < args.limit): + print("Folder "+str(folder), "does not have required "+str(args.limit) + "files. Folder only has "+str(len(copying_folders)) + " files.") + + + + for f in tqdm(copying_folders): + full_file_name = os.path.join(src_dir, folder, f) + if os.path.isfile(full_file_name): + shutil.copy(full_file_name, os.path.join(dst_dir, folder)) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/LYZ/Pacp-deal/1_Pcap/Facetime.pcap b/LYZ/Pacp-deal/1_Pcap/Facetime.pcap new file mode 100644 index 0000000..0ee8a28 Binary files /dev/null and b/LYZ/Pacp-deal/1_Pcap/Facetime.pcap differ diff --git a/LYZ/Pacp-deal/1_Pcap2Flow.ps1 b/LYZ/Pacp-deal/1_Pcap2Flow.ps1 new file mode 100644 index 0000000..5e1c981 --- /dev/null +++ b/LYZ/Pacp-deal/1_Pcap2Flow.ps1 @@ -0,0 +1,17 @@ +foreach($f in gci 1_Pcap *.pcap) +{ + echo "Now processing file : $f" + 0_Tool\SplitCap_2-1\SplitCap -p 100000 -b 100000 -r $f.FullName -s flow -o 2_Flow\AllLayers\$($f.BaseName)-ALL + #0_Tool\SplitCap_2-1\SplitCap -p 100000 -b 100000 -r $f.FullName -s flow -o 2_Flow\L7\$($f.BaseName)-L7 -y L7 + + echo "Done Spliting! Now Clearing 0KB size files..." + # Delete pcap files length equal to 0 + gci 2_Flow\AllLayers\$($f.BaseName)-ALL | ?{$_.Length -eq 0} | del + echo "-------------------------------------------------" +} + +echo "Now Eliminating duplicate flows..." +# Eliminate duplicate Flows +0_Tool\finddupe -del 2_Flow\AllLayers +echo "-------------------------------------------------" +echo "Finished" diff --git a/LYZ/Pacp-deal/2_Flow/.gitkeep b/LYZ/Pacp-deal/2_Flow/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-117_16403_1-2-0-211_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-117_16403_1-2-0-211_16403.pcap new file mode 100644 index 0000000..c4c56b6 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-117_16403_1-2-0-211_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-122_16403_1-2-1-2_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-122_16403_1-2-1-2_16403.pcap new file mode 100644 index 0000000..33bd884 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-122_16403_1-2-1-2_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-12_16403_1-2-0-120_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-12_16403_1-2-0-120_16403.pcap new file mode 100644 index 0000000..0737a51 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-12_16403_1-2-0-120_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-133_16403_1-2-0-227_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-133_16403_1-2-0-227_16403.pcap new file mode 100644 index 0000000..c79680f Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-133_16403_1-2-0-227_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-140_16403_1-2-0-249_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-140_16403_1-2-0-249_16403.pcap new file mode 100644 index 0000000..eeec342 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-140_16403_1-2-0-249_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-147_16403_1-2-181-5_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-147_16403_1-2-181-5_16403.pcap new file mode 100644 index 0000000..7c547a1 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-147_16403_1-2-181-5_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-149_16403_1-2-0-244_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-149_16403_1-2-0-244_16403.pcap new file mode 100644 index 0000000..9675651 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-149_16403_1-2-0-244_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-153_16403_1-2-1-177_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-153_16403_1-2-1-177_16403.pcap new file mode 100644 index 0000000..e349e8a Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-153_16403_1-2-1-177_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-153_16403_1-2-181-17_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-153_16403_1-2-181-17_16403.pcap new file mode 100644 index 0000000..3d45d0f Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-153_16403_1-2-181-17_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-160_16403_1-2-0-254_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-160_16403_1-2-0-254_16403.pcap new file mode 100644 index 0000000..4b3dce5 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-160_16403_1-2-0-254_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-176_16403_1-2-1-202_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-176_16403_1-2-1-202_16403.pcap new file mode 100644 index 0000000..8c89364 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-176_16403_1-2-1-202_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-182_16403_1-2-1-20_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-182_16403_1-2-1-20_16403.pcap new file mode 100644 index 0000000..951331d Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-182_16403_1-2-1-20_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-182_16403_1-2-1-34_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-182_16403_1-2-1-34_16403.pcap new file mode 100644 index 0000000..2606044 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-182_16403_1-2-1-34_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-199_16403_1-2-1-52_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-199_16403_1-2-1-52_16403.pcap new file mode 100644 index 0000000..cea6e2e Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-199_16403_1-2-1-52_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-19_16403_1-2-0-113_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-19_16403_1-2-0-113_16403.pcap new file mode 100644 index 0000000..c763436 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-19_16403_1-2-0-113_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-21_16403_1-2-0-129_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-21_16403_1-2-0-129_16403.pcap new file mode 100644 index 0000000..3652731 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-21_16403_1-2-0-129_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-234_16403_1-2-1-100_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-234_16403_1-2-1-100_16403.pcap new file mode 100644 index 0000000..84990f7 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-234_16403_1-2-1-100_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-248_16403_1-2-1-86_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-248_16403_1-2-1-86_16403.pcap new file mode 100644 index 0000000..b232955 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-248_16403_1-2-1-86_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-37_16403_1-2-180-146_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-37_16403_1-2-180-146_16403.pcap new file mode 100644 index 0000000..d423549 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-37_16403_1-2-180-146_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-43_16403_1-2-180-168_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-43_16403_1-2-180-168_16403.pcap new file mode 100644 index 0000000..9ae1e15 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-43_16403_1-2-180-168_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-45_16403_1-2-180-153_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-45_16403_1-2-180-153_16403.pcap new file mode 100644 index 0000000..1eb02a2 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-45_16403_1-2-180-153_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-58_16403_1-2-0-152_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-58_16403_1-2-0-152_16403.pcap new file mode 100644 index 0000000..38cf532 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-58_16403_1-2-0-152_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-74_16403_1-2-0-182_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-74_16403_1-2-0-182_16403.pcap new file mode 100644 index 0000000..e636b97 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-74_16403_1-2-0-182_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-77_16403_1-2-0-171_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-77_16403_1-2-0-171_16403.pcap new file mode 100644 index 0000000..7573349 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-77_16403_1-2-0-171_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-7_16403_1-2-180-145_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-7_16403_1-2-180-145_16403.pcap new file mode 100644 index 0000000..682dd96 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-7_16403_1-2-180-145_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-80_16403_1-2-0-174_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-80_16403_1-2-0-174_16403.pcap new file mode 100644 index 0000000..1525fbb Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-80_16403_1-2-0-174_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-87_16403_1-2-0-192_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-87_16403_1-2-0-192_16403.pcap new file mode 100644 index 0000000..5166335 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-87_16403_1-2-0-192_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-96_16403_1-2-0-235_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-96_16403_1-2-0-235_16403.pcap new file mode 100644 index 0000000..3d5deb6 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-96_16403_1-2-0-235_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-99_16403_1-2-0-207_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-99_16403_1-2-0-207_16403.pcap new file mode 100644 index 0000000..8690ba8 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-0-99_16403_1-2-0-207_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-128_16403_1-2-181-234_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-128_16403_1-2-181-234_16403.pcap new file mode 100644 index 0000000..3092014 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-128_16403_1-2-181-234_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-142_16403_1-2-2-17_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-142_16403_1-2-2-17_16403.pcap new file mode 100644 index 0000000..c4c997c Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-142_16403_1-2-2-17_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-181_16403_1-2-182-33_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-181_16403_1-2-182-33_16403.pcap new file mode 100644 index 0000000..f6b97d1 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-181_16403_1-2-182-33_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-200_16403_1-2-182-41_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-200_16403_1-2-182-41_16403.pcap new file mode 100644 index 0000000..bc82353 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-200_16403_1-2-182-41_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-209_16403_1-2-2-78_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-209_16403_1-2-2-78_16403.pcap new file mode 100644 index 0000000..6362bb3 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-209_16403_1-2-2-78_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-212_16403_1-2-182-66_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-212_16403_1-2-182-66_16403.pcap new file mode 100644 index 0000000..490cf07 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-212_16403_1-2-182-66_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-216_16403_1-2-2-52_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-216_16403_1-2-2-52_16403.pcap new file mode 100644 index 0000000..356ab12 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-216_16403_1-2-2-52_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-217_16403_1-2-2-53_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-217_16403_1-2-2-53_16403.pcap new file mode 100644 index 0000000..7d4e291 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-217_16403_1-2-2-53_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-223_16403_1-2-182-221_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-223_16403_1-2-182-221_16403.pcap new file mode 100644 index 0000000..5bc08dc Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-223_16403_1-2-182-221_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-228_16403_1-2-182-92_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-228_16403_1-2-182-92_16403.pcap new file mode 100644 index 0000000..992f92d Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-228_16403_1-2-182-92_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-27_16403_1-2-181-137_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-27_16403_1-2-181-137_16403.pcap new file mode 100644 index 0000000..126614b Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-27_16403_1-2-181-137_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-33_16403_1-2-181-141_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-33_16403_1-2-181-141_16403.pcap new file mode 100644 index 0000000..8ac311d Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-33_16403_1-2-181-141_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-72_16403_1-2-1-166_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-72_16403_1-2-1-166_16403.pcap new file mode 100644 index 0000000..e35015b Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-72_16403_1-2-1-166_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-88_16403_1-2-1-196_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-88_16403_1-2-1-196_16403.pcap new file mode 100644 index 0000000..5e72160 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-88_16403_1-2-1-196_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-91_16403_1-2-1-185_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-91_16403_1-2-1-185_16403.pcap new file mode 100644 index 0000000..5d08770 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-1-91_16403_1-2-1-185_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-101_16403_1-2-10-209_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-101_16403_1-2-10-209_16403.pcap new file mode 100644 index 0000000..17ca860 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-101_16403_1-2-10-209_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-109_16403_1-2-10-220_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-109_16403_1-2-10-220_16403.pcap new file mode 100644 index 0000000..a3eb6de Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-109_16403_1-2-10-220_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-109_16403_1-2-11-113_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-109_16403_1-2-11-113_16403.pcap new file mode 100644 index 0000000..ae18b9a Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-109_16403_1-2-11-113_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-130_16403_1-2-190-236_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-130_16403_1-2-190-236_16403.pcap new file mode 100644 index 0000000..340736d Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-130_16403_1-2-190-236_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-131_16403_1-2-10-225_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-131_16403_1-2-10-225_16403.pcap new file mode 100644 index 0000000..4a0a526 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-131_16403_1-2-10-225_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-132_16403_1-2-10-226_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-132_16403_1-2-10-226_16403.pcap new file mode 100644 index 0000000..3468a2d Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-132_16403_1-2-10-226_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-148_16403_1-2-11-0_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-148_16403_1-2-11-0_16403.pcap new file mode 100644 index 0000000..68d5852 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-148_16403_1-2-11-0_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-14_16403_1-2-10-120_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-14_16403_1-2-10-120_16403.pcap new file mode 100644 index 0000000..60b0258 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-14_16403_1-2-10-120_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-160_16403_1-2-10-254_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-160_16403_1-2-10-254_16403.pcap new file mode 100644 index 0000000..52dea6c Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-160_16403_1-2-10-254_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-161_16403_1-2-11-176_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-161_16403_1-2-11-176_16403.pcap new file mode 100644 index 0000000..b814533 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-161_16403_1-2-11-176_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-185_16403_1-2-191-26_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-185_16403_1-2-191-26_16403.pcap new file mode 100644 index 0000000..162e05c Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-185_16403_1-2-191-26_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-204_16403_1-2-11-59_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-204_16403_1-2-11-59_16403.pcap new file mode 100644 index 0000000..f6222dd Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-204_16403_1-2-11-59_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-207_16403_1-2-191-71_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-207_16403_1-2-191-71_16403.pcap new file mode 100644 index 0000000..d4143b4 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-207_16403_1-2-191-71_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-20_16403_1-2-10-146_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-20_16403_1-2-10-146_16403.pcap new file mode 100644 index 0000000..8051b4f Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-20_16403_1-2-10-146_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-220_16403_1-2-11-58_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-220_16403_1-2-11-58_16403.pcap new file mode 100644 index 0000000..ef960c6 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-220_16403_1-2-11-58_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-238_16403_1-2-11-76_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-238_16403_1-2-11-76_16403.pcap new file mode 100644 index 0000000..75ee008 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-238_16403_1-2-11-76_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-244_16403_1-2-11-97_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-244_16403_1-2-11-97_16403.pcap new file mode 100644 index 0000000..da2d550 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-244_16403_1-2-11-97_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-252_16403_1-2-11-90_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-252_16403_1-2-11-90_16403.pcap new file mode 100644 index 0000000..173528e Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-252_16403_1-2-11-90_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-2_16403_1-2-10-113_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-2_16403_1-2-10-113_16403.pcap new file mode 100644 index 0000000..4e8a04e Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-2_16403_1-2-10-113_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-45_16403_1-2-10-153_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-45_16403_1-2-10-153_16403.pcap new file mode 100644 index 0000000..71e20a3 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-45_16403_1-2-10-153_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-47_16403_1-2-10-155_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-47_16403_1-2-10-155_16403.pcap new file mode 100644 index 0000000..951e840 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-47_16403_1-2-10-155_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-86_16403_1-2-10-178_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-86_16403_1-2-10-178_16403.pcap new file mode 100644 index 0000000..63cced2 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-10-86_16403_1-2-10-178_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-11_16403_1-2-100-119_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-11_16403_1-2-100-119_16403.pcap new file mode 100644 index 0000000..e0dfbca Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-11_16403_1-2-100-119_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-128_16403_1-2-209-143_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-128_16403_1-2-209-143_16403.pcap new file mode 100644 index 0000000..ebcac36 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-128_16403_1-2-209-143_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-130_16403_1-2-100-224_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-130_16403_1-2-100-224_16403.pcap new file mode 100644 index 0000000..9ba679f Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-130_16403_1-2-100-224_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-134_16403_1-2-100-244_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-134_16403_1-2-100-244_16403.pcap new file mode 100644 index 0000000..c9001fa Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-134_16403_1-2-100-244_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-135_16403_1-2-100-245_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-135_16403_1-2-100-245_16403.pcap new file mode 100644 index 0000000..43a28d6 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-135_16403_1-2-100-245_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-160_16403_1-2-101-12_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-160_16403_1-2-101-12_16403.pcap new file mode 100644 index 0000000..c4cb98c Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-160_16403_1-2-101-12_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-160_16403_1-2-209-1_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-160_16403_1-2-209-1_16403.pcap new file mode 100644 index 0000000..eed9fa5 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-160_16403_1-2-209-1_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-165_16403_1-2-209-33_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-165_16403_1-2-209-33_16403.pcap new file mode 100644 index 0000000..895f731 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-165_16403_1-2-209-33_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-194_16403_1-2-209-47_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-194_16403_1-2-209-47_16403.pcap new file mode 100644 index 0000000..abca031 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-194_16403_1-2-209-47_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-214_16403_1-2-101-209_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-214_16403_1-2-101-209_16403.pcap new file mode 100644 index 0000000..24d8742 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-214_16403_1-2-101-209_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-216_16403_1-2-209-66_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-216_16403_1-2-209-66_16403.pcap new file mode 100644 index 0000000..4b0d26e Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-216_16403_1-2-209-66_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-245_16403_1-2-101-83_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-245_16403_1-2-101-83_16403.pcap new file mode 100644 index 0000000..fb602d5 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-245_16403_1-2-101-83_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-32_16403_1-2-208-141_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-32_16403_1-2-208-141_16403.pcap new file mode 100644 index 0000000..6705d1b Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-32_16403_1-2-208-141_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-41_16403_1-2-100-135_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-41_16403_1-2-100-135_16403.pcap new file mode 100644 index 0000000..dca458e Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-41_16403_1-2-100-135_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-44_16403_1-2-100-168_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-44_16403_1-2-100-168_16403.pcap new file mode 100644 index 0000000..c0a3f52 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-44_16403_1-2-100-168_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-48_16403_1-2-100-142_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-48_16403_1-2-100-142_16403.pcap new file mode 100644 index 0000000..6f79756 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-48_16403_1-2-100-142_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-62_16403_1-2-208-172_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-62_16403_1-2-208-172_16403.pcap new file mode 100644 index 0000000..d8ce127 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-62_16403_1-2-208-172_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-69_16403_1-2-208-179_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-69_16403_1-2-208-179_16403.pcap new file mode 100644 index 0000000..c7ad7ad Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-69_16403_1-2-208-179_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-72_16403_1-2-208-179_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-72_16403_1-2-208-179_16403.pcap new file mode 100644 index 0000000..9f8d9b1 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-72_16403_1-2-208-179_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-86_16403_1-2-100-194_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-86_16403_1-2-100-194_16403.pcap new file mode 100644 index 0000000..538f759 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-100-86_16403_1-2-100-194_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-14_16403_1-2-101-108_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-14_16403_1-2-101-108_16403.pcap new file mode 100644 index 0000000..c05a4f0 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-14_16403_1-2-101-108_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-165_16403_1-2-102-171_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-165_16403_1-2-102-171_16403.pcap new file mode 100644 index 0000000..351f844 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-165_16403_1-2-102-171_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-16_16403_1-2-101-124_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-16_16403_1-2-101-124_16403.pcap new file mode 100644 index 0000000..b788fa5 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-16_16403_1-2-101-124_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-170_16403_1-2-102-9_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-170_16403_1-2-102-9_16403.pcap new file mode 100644 index 0000000..ab24167 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-170_16403_1-2-102-9_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-182_16403_1-2-102-20_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-182_16403_1-2-102-20_16403.pcap new file mode 100644 index 0000000..8640769 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-182_16403_1-2-102-20_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-185_16403_1-2-102-23_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-185_16403_1-2-102-23_16403.pcap new file mode 100644 index 0000000..75789ae Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-185_16403_1-2-102-23_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-187_16403_1-2-102-38_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-187_16403_1-2-102-38_16403.pcap new file mode 100644 index 0000000..e2de0d6 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-187_16403_1-2-102-38_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-195_16403_1-2-210-47_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-195_16403_1-2-210-47_16403.pcap new file mode 100644 index 0000000..aa2b04c Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-195_16403_1-2-210-47_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-214_16403_1-2-102-68_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-214_16403_1-2-102-68_16403.pcap new file mode 100644 index 0000000..eecbd5d Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-214_16403_1-2-102-68_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-227_16403_1-2-102-82_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-227_16403_1-2-102-82_16403.pcap new file mode 100644 index 0000000..3cf7214 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-227_16403_1-2-102-82_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-230_16403_1-2-102-216_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-230_16403_1-2-102-216_16403.pcap new file mode 100644 index 0000000..5c52cf3 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-230_16403_1-2-102-216_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-232_16403_1-2-102-100_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-232_16403_1-2-102-100_16403.pcap new file mode 100644 index 0000000..c57c86f Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-232_16403_1-2-102-100_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-234_16403_1-2-102-72_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-234_16403_1-2-102-72_16403.pcap new file mode 100644 index 0000000..7c64d53 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-234_16403_1-2-102-72_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-236_16403_1-2-210-102_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-236_16403_1-2-210-102_16403.pcap new file mode 100644 index 0000000..a37528e Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-236_16403_1-2-210-102_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-47_16403_1-2-101-159_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-47_16403_1-2-101-159_16403.pcap new file mode 100644 index 0000000..c8a8630 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-47_16403_1-2-101-159_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-47_16403_1-2-209-175_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-47_16403_1-2-209-175_16403.pcap new file mode 100644 index 0000000..0230a3f Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-47_16403_1-2-209-175_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-59_16403_1-2-101-153_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-59_16403_1-2-101-153_16403.pcap new file mode 100644 index 0000000..1de7c23 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-59_16403_1-2-101-153_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-68_16403_1-2-209-165_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-68_16403_1-2-209-165_16403.pcap new file mode 100644 index 0000000..9084002 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-68_16403_1-2-209-165_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-8_16403_1-2-101-116_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-8_16403_1-2-101-116_16403.pcap new file mode 100644 index 0000000..7741b3f Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-101-8_16403_1-2-101-116_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-114_16403_1-2-102-209_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-114_16403_1-2-102-209_16403.pcap new file mode 100644 index 0000000..9ed8a0d Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-114_16403_1-2-102-209_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-115_16403_1-2-102-223_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-115_16403_1-2-102-223_16403.pcap new file mode 100644 index 0000000..7eba0e5 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-115_16403_1-2-102-223_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-120_16403_1-2-102-228_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-120_16403_1-2-102-228_16403.pcap new file mode 100644 index 0000000..8df004e Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-120_16403_1-2-102-228_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-155_16403_1-2-211-24_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-155_16403_1-2-211-24_16403.pcap new file mode 100644 index 0000000..c4affb7 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers - 副本/Facetime-ALL/Facetime.pcap.UDP_1-1-102-155_16403_1-2-211-24_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow/AllLayers/Facetime-ALL/Facetime.pcap.UDP_1-1-0-7_16403_1-2-180-145_16403.pcap b/LYZ/Pacp-deal/2_Flow/AllLayers/Facetime-ALL/Facetime.pcap.UDP_1-1-0-7_16403_1-2-180-145_16403.pcap new file mode 100644 index 0000000..682dd96 Binary files /dev/null and b/LYZ/Pacp-deal/2_Flow/AllLayers/Facetime-ALL/Facetime.pcap.UDP_1-1-0-7_16403_1-2-180-145_16403.pcap differ diff --git a/LYZ/Pacp-deal/2_Flow2Packet.py b/LYZ/Pacp-deal/2_Flow2Packet.py new file mode 100644 index 0000000..b540c5a --- /dev/null +++ b/LYZ/Pacp-deal/2_Flow2Packet.py @@ -0,0 +1,160 @@ +# Author: @vinesmsuic +# +# + +import dpkt +import numpy as np +import pandas as pd +import os +from tqdm import tqdm +import argparse +import random + +def parser(): + parser = argparse.ArgumentParser(description="Selecting Parameter of Packets and Bytes.") + parser.add_argument("--packet", type=int, required=True, help="number of required packets") + parser.add_argument("--byte", type=int, required=True, help="number of trimmed byte") + parser.add_argument("--limit", type=int, required=False, default=-1, help="only extract packets from the largest N flows") + return parser.parse_args() + +# Sanitization +def zero_mask_packet(eth_packet): + + #Mask MAC Address to 00:00:00:00:00:00 + eth_packet.src = b'\x00\x00\x00\x00\x00\x00' + eth_packet.dst = b'\x00\x00\x00\x00\x00\x00' + + if(eth_packet.data.__class__.__name__ == 'IP6'): + #Mask IPv6 Address to 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 + eth_packet.data.src = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + eth_packet.data.dst = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + else: + #Mask IPv4 Address to 0.0.0.0 + eth_packet.data.src = b'\x00\x00\x00\x00' + eth_packet.data.dst = b'\x00\x00\x00\x00' + + return eth_packet + +# Extract Information +def get_packets(pcap, packetnum, target_length): + + r_num = 0 + packetlist = [] + + # For each packet in the pcap process the contents + for ts, buf in pcap: + + r_num += 1 + + eth_packet = dpkt.ethernet.Ethernet(buf) + eth_packet = zero_mask_packet(eth_packet) + + byte_buf = bytes(eth_packet) + + trimmed_buf = trimming(byte_buf, target_length=target_length) + + packetlist.append(trimmed_buf) + + if(r_num == packetnum): + break + + # If number of packets is lesser than our requirements, pad a whole packet of zeros + if(r_num < packetnum): + for _ in range(packetnum - r_num): + paddings = bytes(target_length) + packetlist.append(paddings) + + return packetlist + + +def trimming(byte, target_length): + + # Appending zeros in a packet if byte length < target length + if(len(byte) < target_length): + needed_length = target_length - len(byte) + zeros = bytearray(needed_length) + return (byte+zeros) + + # Trim byte in a packet if byte length > target length + elif(len(byte) > target_length): + return (byte[:target_length]) + + # Else byte length = target length. Do nothing. + else: + return byte + + +def packet_from_file(file, packetnum, target_length): + with open(file, 'rb') as f: + pcap = dpkt.pcap.Reader(f) + packets = get_packets(pcap, packetnum=packetnum, target_length=target_length) + #print(np.shape(packets)) + return packets + + +def main(): + args = parser() + + directory = os.path.join('2_Flow', 'AllLayers') + + for folder in os.listdir(directory): + + if(os.path.isdir(os.path.join(directory,folder))): + + + print("Now Processing Folder: ", folder) + + # Create Dataframe Object + folder_df = pd.DataFrame(columns = ['Path','Bytes']) + + searching_folders = os.listdir(os.path.join(directory,folder)) + + ##################################### + # TODO: + # + # + ##if(args.sort == 1): + #Sort the searching folders by size (largerst to smallest) + ##searching_folders = sorted(searching_folders, key=lambda f: os.path.getsize(os.path.abspath(os.path.join(directory, folder, f))), reverse=True) + ##else: + random.seed(72) + random.shuffle(searching_folders) + + ###################################### + + + if(args.limit!= -1): + if(len(searching_folders) > args.limit): + searching_folders = searching_folders[:args.limit] + elif(len(searching_folders) < args.limit): + print("Folder "+str(folder), "does not have required "+str(args.limit) + "files. Folder only has "+str(len(searching_folders)) + " files.") + + + + for f in tqdm(searching_folders): + + if f.endswith(".pcap"): + # print(os.path.join(directory, folder, f)) + path_to_file = os.path.join(directory, folder, f) + packets = packet_from_file(path_to_file, packetnum=args.packet, target_length=args.byte) + # Create Dataframe Object + folder_df = folder_df.append({'Path' : path_to_file, 'Bytes' : packets}, ignore_index = True) + + continue + else: + continue + + print("Row entries of "+str(folder)+": ",folder_df.shape[0]) + + save_path = os.path.join('3_Packet' , folder)+"-p"+str(args.packet)+"-b"+str(args.byte)+"-l"+str(abs(args.limit))+".pkl" + + folder_df.to_pickle(save_path) + print("Saved to file: ", save_path) + print("-"*20) + + continue + else: + continue + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/LYZ/Pacp-deal/3_Packet/Facetime-ALL-p2-b300-l1.pkl b/LYZ/Pacp-deal/3_Packet/Facetime-ALL-p2-b300-l1.pkl new file mode 100644 index 0000000..6415926 Binary files /dev/null and b/LYZ/Pacp-deal/3_Packet/Facetime-ALL-p2-b300-l1.pkl differ diff --git a/LYZ/Pacp-deal/3_Packet/Facetime-ALL-p5-b500-l1.pkl b/LYZ/Pacp-deal/3_Packet/Facetime-ALL-p5-b500-l1.pkl new file mode 100644 index 0000000..ba500c2 Binary files /dev/null and b/LYZ/Pacp-deal/3_Packet/Facetime-ALL-p5-b500-l1.pkl differ diff --git a/LYZ/Pacp-deal/3_Packet2Image.py b/LYZ/Pacp-deal/3_Packet2Image.py new file mode 100644 index 0000000..7b5aede --- /dev/null +++ b/LYZ/Pacp-deal/3_Packet2Image.py @@ -0,0 +1,65 @@ +# Author: @vinesmsuic +# +# +import numpy as np +import pandas as pd +import os +import pickle +from PIL import Image +import binascii +from tqdm import tqdm + +def to_hex(byte_list): + bytelist = [] + for b in byte_list: + bytelist.append(binascii.hexlify(bytes(b))) + + return bytelist + +def matrix_from_hex(hex_list): + matrice = [] + for hex_str in hex_list: + matrix = np.array([int(hex_str[i:i+2],16) for i in range(0, len(hex_str), 2)]) + matrix = np.uint8(matrix) + matrice.append(matrix) + + matrice = np.stack(matrice, axis=0) + return matrice + +def get_save_path(one_row_df, save_folder): + base = os.path.basename(one_row_df['Path']) + filename = os.path.splitext(base)[0] + + ImagePath = os.path.join(save_folder,filename) + return ImagePath + + +def main(): + searching_folder = "3_Packet" + saving_folder = "4_Image" + + for f in os.listdir(searching_folder): + if f.endswith(".pkl"): + + folder = os.path.join(saving_folder, os.path.splitext(f)[0]) + if not os.path.exists(folder): + os.makedirs(folder) + + print("Saving to: " + str(folder)) + + file = open(os.path.join(searching_folder, f), 'rb') + df = pickle.load(file) + file.close() + + df['Hex'] = df['Bytes'].apply(to_hex) + df['Matrice'] = df['Hex'].apply(matrix_from_hex) + + for index, row in tqdm(df.iterrows()): + ImagePath = get_save_path(row, folder) + im = Image.fromarray(row['Matrice']) + im.save(str(ImagePath)+".png") + + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/LYZ/Pacp-deal/README.md b/LYZ/Pacp-deal/README.md new file mode 100644 index 0000000..33fd51f --- /dev/null +++ b/LYZ/Pacp-deal/README.md @@ -0,0 +1,58 @@ +# Pcap-To-Img +A Modified version of USTC-TK2016 Tools +* For Windows only + +# Before Preprocessing + +## Convert PcapNG Files to Pcap Files +If you are using PcapNG (`.pcapng`) Files +> Sometimes pcapng will also shown as `.pcap` file. + +* `editcap` program is available from [Wireshark](https://www.wireshark.org/). +* [Usage of editcap](https://www.wireshark.org/docs/man-pages/editcap.html) + +```powershell +editcap -F libpcap dump.pcapng dump.pcap +``` + +* Please see [How To handle PcapNG files](https://www.netresec.com/?page=Blog&month=2012-12&post=HowTo-handle-PcapNG-files) for more detail. + + +## Usage of Tools + +* `SplitCap` : [https://www.netresec.com/?page=SplitCap](https://www.netresec.com/?page=SplitCap) +* `finddupe` : [https://www.sentex.ca/~mwandel/finddupe/](https://www.sentex.ca/~mwandel/finddupe/) + + +## Run Powershell as Administrator + +```Powershell +set-ExecutionPolicy RemoteSigned +``` + +# Preprocessing + +Split Pcap files into Flows +```Powershell +.\1_Pcap2Flow.ps1 +``` + +```Powershell +python .\2_Flow2Packet.py +``` + +``` +usage: 2_Flow2Packet.py [-h] --packet PACKET --byte BYTE [--limit LIMIT] + +Selecting Parameter of Packets and Bytes. + +optional arguments: + -h, --help show this help message and exit + --packet PACKET number of required packets + --byte BYTE number of trimmed byte + --limit LIMIT only extract packets from the largest N flows +``` + +```Powershell +python .\3_Packet2Image.py +``` \ No newline at end of file diff --git a/LYZ/a.py b/LYZ/a.py new file mode 100644 index 0000000..0ca6f64 --- /dev/null +++ b/LYZ/a.py @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- + +import torch +import torch.nn as nn +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import os, glob, time +import pickle +from timeit import default_timer as timer + +# matplot lib complains about librosa +import warnings +warnings.filterwarnings('ignore') + + +# classes index +traffic_dict ={ + 0: 'Normal', + 1: 'BFSSH', + 2: 'Infilt', + 3: 'HttpDoS', + 4: 'DDoS' +} + +# network traffic attributes +traffic_attributes = { + '01': 'normal', # 正常流量 + '02': 'anomaly' # abnormal +} + +"""## Load Data +""" + +# path to data for glob +DATA_DIR = 'D:\\PyProject\\malware_traffic\\3_Packet\\' + +def load_data(): + """ + 加载数据 + :return: + """ + t1 = timer() + sessions = [] + labels = [] + num_pkls = len(glob.glob(DATA_DIR + 'ISCX2012_labels_*.pkl')) # 匹配路径 + for i in range(num_pkls): + # if i != 1: + # continue + session_pkl = DATA_DIR + 'ISCX2012_pcaps_' + str(i) + '.pkl' + session_lists = pickle.load(open(session_pkl, 'rb')) # 反序列化对象 + sessions.extend(session_lists.values.tolist()) # 追加元素 + + label_pkl = DATA_DIR + 'ISCX2012_labels_' + str(i) + '.pkl' + label_lists = pickle.load(open(label_pkl, 'rb')) + labels.extend(label_lists.values.tolist()) + print(i) + t2 = timer() + print("load data tims: ", t2 - t1) + + labels = np.array(labels) + normal_indices = np.where(labels == 0)[0] # 结果所在的 行, 是个array + # 数据量太大, 不好训练。以下注释代码可以选择100000条正常流量进入训练(建议在数据预处理阶段选择一定数量的正常数据——节约内存开支) + normal_indices = np.random.choice(normal_indices, 100000, replace=False) # 注释代码 + attack_indices = [np.where(labels == i)[0] for i in range(1, 5)] # label 1~4 所在行, 是个 list + # np.random.choice 会重复抽样, 若想不重复, 增加参数:replace=False + test_normal_indices = np.random.choice(normal_indices, int(len(normal_indices) * 0.4), replace=False) + test_attack_indices = np.concatenate( # 模态融合 + [np.random.choice(attack_indices[i], int(len(attack_indices[i]) * 0.4), replace=False) for i in range(4)]) + test_indices = np.concatenate([test_normal_indices, test_attack_indices]).astype(int) + # train_indices = np.array(list(set(np.arange(len(labels))) - set(test_indices))) + attack_indices = np.concatenate(attack_indices).astype(int) # 注释代码 + indices = np.concatenate([normal_indices, attack_indices]).astype(int) # 注释代码 + train_indices = np.array(list(set(indices) - set(test_indices))) # 注释代码 + + return sessions, labels, train_indices, test_indices + + + +"""# Architecture Overview + +# CNN Motivation +** 构建两个并行卷积神经网络(CNN)来对流量数据进行空间特征表示 + +# Transformer-Encoder Motivation +**使用了Transformer-Encoder层 +**I maxpool 映射到Transformer, 以大大减少网络需要学习的参数数量 +""" + + +class ByteBlock(nn.Module): + """ + 1D FCN: 1维全卷积神经网络 + + in_channels:输入通道数, 在一维卷积中由于不存在通道数, 因此in_channels的数值为词向量的维度, 如果一个单词用128维向量表示, 那么in_channels = 128 + + out_channels:输出通道数, 表示经过卷积之后, 一个词向量嵌入维度应该为多少。如果out_channels = 64, 那么经过本次卷积之后的每个词的嵌入维度为64。 + + kernel_size:卷积核大小, 表示本次卷积核的维度, 一般是赋值为int类型。kernel_size=3, 表示每次卷积计算操作涉及到3个词, 也就是卷积核维度被设为(in_channels, kernel_size)。 + - 在Pytorch中, 对于一条语句序列数据的每个词都是用一个列向量表示 + + stride:滑动步长, 表示在卷积方向上滑动的步长。stride=2, 表示在当前卷积的范围为123, 下一个卷积范围就是345。 + + padding:填补操作, 表示在对特征矩阵剩余部分不足卷积时的操作。 + - str --> padding =“valid”:表示不填充, 剩余部分丢弃。 padding =“same”:表示在右侧填充之后要求输入输出序列长度一致 + - int --> padding = k: 表示在右侧填充k列 + """ + def __init__(self, in_channels, nb_filter=(64, 100), filter_length=(3, 3), + subsample=(2, 1), pool_length=(2, 2)): + super(ByteBlock, self).__init__() + + layers = [] + for i in range(len(nb_filter)): + layers.append(nn.Conv1d(in_channels, nb_filter[i], kernel_size=filter_length[i], + padding=0, stride=subsample[i])) + layers.append(nn.Tanh()) + if pool_length[i]: + layers.append(nn.MaxPool1d(pool_length[i])) + in_channels = nb_filter[i] + + self.block = nn.Sequential(*layers) + self.global_pool = nn.AdaptiveMaxPool1d(1) + + + def forward(self, x): + x = self.block(x) + x = self.global_pool(x).squeeze(dim=2) + x = torch.nn.functional.leaky_relu(x) + return x + +class FCN_Transformer(nn.Module): + # Define all layers present in the network + def __init__(self,num_emotions): + super().__init__() + + ################ TRANSFORMER BLOCK ############################# + # maxpool the input feature map/tensor to the transformer + # a rectangular kernel worked better here for the rectangular input spectrogram feature map/tensor + self.transformer_maxpool = nn.MaxPool1d(2) + + # define single transformer encoder layer + # self-attention + feedforward network from "Attention is All You Need" paper + # Input size: sequence length, batch size, feature size = 128 + transformer_layer = nn.TransformerEncoderLayer( + d_model=128, # input feature (frequency) dim after maxpooling 128*y -> 64*140 (freq*time) 输入特征维度 + nhead=4, # 4 self-attention layers in each multi-head self-attention layer in each encoder block 注意力头数 + dim_feedforward=512, # 2 linear layers in each encoder block's feedforward network: dim 64-->512--->64 前馈神经网络中隐藏层的维度。 + dropout=0.4, + activation='relu' # ReLU: avoid saturation/tame gradient/reduce compute time + ) + + # Using 4 instead of the 6 identical stacked encoder layrs used in Attention is All You Need paper + # Complete transformer block contains 4 full transformer encoder layers (each w/ multihead self-attention+feedforward) + self.transformer_encoder = nn.TransformerEncoder(transformer_layer, num_layers=4) + + ############### 1ST PARALLEL 1D CONVOLUTION BLOCK ############ + # 1 sequential conv1D layers: (1,128,282) --> (x, y, z) + self.conv1Dblock1 = ByteBlock(128, (128, 256), (5, 5), (1, 1), (2, 2)) + ############### 2ND PARALLEL 1D CONVOLUTION BLOCK ############ + # 1 sequential conv1D layers: (1,128,282) --> (x, y, z) + self.conv1Dblock2 = ByteBlock(128, (192, 320), (7, 5), (1, 1), (2, 2)) + ################# FINAL LINEAR BLOCK #################### + # Linear softmax layer to take final concatenated embedding tensor + # from parallel 1D convolutional and transformer blocks, output classes logits + self.fc1_linear = nn.Linear(512*2+40,num_emotions) + + ### Softmax layer for the 8 output logits from final FC linear layer + self.softmax_out = nn.Softmax(dim=1) # dim==1 is the freq embedding + + # define one complete parallel fwd pass of input feature tensor thru 2*conv+1*transformer blocks + def forward(self,x): + + ############ 1st parallel Conv1D block: 4 Convolutional layers ############################ + # create final feature embedding from 1st convolutional layer + # input features pased through 4 sequential 1D convolutional layers + print("x: ",x.type()) + conv1d_embedding1 = self.conv1Dblock1(x) # x == N/batch * channel * freq * time + + # flatten final 64*1*4 feature map from convolutional layers to length 256 1D array + # skip the 1st (N/batch) dimension when flattening + conv1d_embedding1 = torch.flatten(conv1d_embedding1, start_dim=1) + + ############ 2nd parallel Conv1D block: 4 Convolutional layers ############################# + # create final feature embedding from 2nd convolutional layer + # input features pased through 4 sequential 1D convolutional layers + conv1d_embedding2 = self.conv1Dblock2(x) # x == N/batch * channel * freq * time + + # flatten final 64*1*4 feature map from convolutional layers to length 256 1D array + # skip the 1st (N/batch) dimension when flattening + conv1d_embedding2 = torch.flatten(conv1d_embedding2, start_dim=1) + + + ########## 4-encoder-layer Transformer block w/ 64-->512-->64 feedfwd network ############## + # maxpool input feature map: 1*40*282 w/ 1*4 kernel --> 1*40*70 + x_maxpool = self.transformer_maxpool(x) + + # remove channel dim: 1*x*y --> x*y + x_maxpool_reduced = torch.squeeze(x_maxpool,1) + + # convert maxpooled feature map format: batch * freq * time ---> time * batch * freq format + # because transformer encoder layer requires tensor in format: time * batch * embedding (freq) + x = x_maxpool_reduced.permute(2,0,1) + print("x_maxpool_reduced: ",x_maxpool_reduced.shape) + # finally, pass reduced input feature map x into transformer encoder layers + transformer_output = self.transformer_encoder(x) + + # create final feature emedding from transformer layer by taking mean in the time dimension (now the 0th dim) + # transformer outputs 64*140 (freq embedding*time) feature map, take mean of all columns i.e. take time average + transformer_embedding = torch.mean(transformer_output, dim=0) # dim + + ############# concatenate freq embeddings from convolutional and transformer blocks ###### + # concatenate embedding tensors output by parallel 2*conv and 1*transformer blocks + complete_embedding = torch.cat([conv1d_embedding1, conv1d_embedding2,transformer_embedding], dim=1) + + ######### final FC linear layer, need logits for loss ######################### + output_logits = self.fc1_linear(complete_embedding) + + ######### Final Softmax layer: use logits from FC linear, get softmax for prediction ###### + output_softmax = self.softmax_out(output_logits) + + # need output logits to compute cross entropy loss, need softmax probabilities to predict class + return output_logits, output_softmax + + +"""# 查看模型结构 +""" +from torchsummary import summary + +# need device to instantiate model +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +# instantiate model for 8 emotions and move to CPU for summary +model = FCN_Transformer(len(traffic_dict)).to(device) + +# print("\nmodel: \n", model,"\n") +data = torch.randint(255, size=(128, 128, 100)) # batch_size, flow_len, packet_len +print("data: ", data.type()) +model(data) + +# include input feature map dims in call to summary() +# summary(model, input_size=(128,282)) + + + + diff --git a/LYZ/b.py b/LYZ/b.py new file mode 100644 index 0000000..ceade97 --- /dev/null +++ b/LYZ/b.py @@ -0,0 +1,359 @@ +# -*- coding: utf-8 -*- + + +import torch +import torch.nn as nn +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import os, glob +import warnings; warnings.filterwarnings('ignore') #matplot lib complains about librosa + + +# RAVDESS native sample rate is 48k +sample_rate = 48000 + +# Mel Spectrograms are not directly used as a feature in this model +# Mel Spectrograms are used in calculating MFCCs, which are a higher-level representation of pitch transition +# MFCCs work better - left the mel spectrogram function here in case anyone wants to experiment +def feature_melspectrogram( + waveform, + sample_rate, + fft = 1024, + winlen = 512, + window='hamming', + hop=256, + mels=128, + ): + + # Produce the mel spectrogram for all STFT frames and get the mean of each column of the resulting matrix to create a feature array + # Using 8khz as upper frequency bound should be enough for most speech classification tasks + melspectrogram = librosa.feature.melspectrogram( + y=waveform, + sr=sample_rate, + n_fft=fft, + win_length=winlen, + window=window, + hop_length=hop, + n_mels=mels, + fmax=sample_rate/2) + + # convert from power (amplitude**2) to decibels + # necessary for network to learn - doesn't converge with raw power spectrograms + melspectrogram = librosa.power_to_db(melspectrogram, ref=np.max) + + return melspectrogram + +def feature_mfcc( + waveform, + sample_rate, + n_mfcc = 40, + fft = 1024, + winlen = 512, + window='hamming', + #hop=256, # increases # of time steps; was not helpful + mels=128 + ): + + # Compute the MFCCs for all STFT frames + # 40 mel filterbanks (n_mfcc) = 40 coefficients + mfc_coefficients=librosa.feature.mfcc( + y=waveform, + sr=sample_rate, + n_mfcc=n_mfcc, + n_fft=fft, + win_length=winlen, + window=window, + #hop_length=hop, + n_mels=mels, + fmax=sample_rate/2 + ) + + return mfc_coefficients + +def get_features(waveforms, features, samplerate): + + # initialize counter to track progress + file_count = 0 + + # process each waveform individually to get its MFCCs + for waveform in waveforms: + mfccs = feature_mfcc(waveform, sample_rate) + features.append(mfccs) + file_count += 1 + # print progress + print('\r'+f' Processed {file_count}/{len(waveforms)} waveforms',end='') + + # return all features from list of waveforms + return features + +def get_waveforms(file): + + # load an individual sample audio file + # read the full 3 seconds of the file, cut off the first 0.5s of silence; native sample rate = 48k + # don't need to store the sample rate that librosa.load returns + waveform, _ = librosa.load(file, duration=3, offset=0.5, sr=sample_rate) + + # make sure waveform vectors are homogenous by defining explicitly + waveform_homo = np.zeros((int(sample_rate*3,))) + waveform_homo[:len(waveform)] = waveform + + # return a single file's waveform + return waveform_homo + +# RAVDESS dataset emotions +# shift emotions left to be 0 indexed for PyTorch +emotions_dict ={ + '0':'surprised', + '1':'neutral', + '2':'calm', + '3':'happy', + '4':'sad', + '5':'angry', + '6':'fearful', + '7':'disgust' +} + +# Additional attributes from RAVDESS to play with +emotion_attributes = { + '01': 'normal', + '02': 'strong' +} + +class parallel_all_you_want(nn.Module): + # Define all layers present in the network + def __init__(self,num_emotions): + super().__init__() + + ################ TRANSFORMER BLOCK ############################# + # maxpool the input feature map/tensor to the transformer + # a rectangular kernel worked better here for the rectangular input spectrogram feature map/tensor + self.transformer_maxpool = nn.MaxPool2d(kernel_size=[1,4], stride=[1,4]) + + # define single transformer encoder layer + # self-attention + feedforward network from "Attention is All You Need" paper + # 4 multi-head self-attention layers each with 64-->512--->64 feedforward network + transformer_layer = nn.TransformerEncoderLayer( + d_model=40, # input feature (frequency) dim after maxpooling 128*563 -> 64*140 (freq*time) + nhead=4, # 4 self-attention layers in each multi-head self-attention layer in each encoder block + dim_feedforward=512, # 2 linear layers in each encoder block's feedforward network: dim 64-->512--->64 + dropout=0.4, + activation='relu' # ReLU: avoid saturation/tame gradient/reduce compute time + ) + + # I'm using 4 instead of the 6 identical stacked encoder layrs used in Attention is All You Need paper + # Complete transformer block contains 4 full transformer encoder layers (each w/ multihead self-attention+feedforward) + self.transformer_encoder = nn.TransformerEncoder(transformer_layer, num_layers=4) + + ############### 1ST PARALLEL 2D CONVOLUTION BLOCK ############ + # 3 sequential conv2D layers: (1,40,282) --> (16, 20, 141) -> (32, 5, 35) -> (64, 1, 8) + self.conv2Dblock1 = nn.Sequential( + + # 1st 2D convolution layer + nn.Conv2d( + in_channels=1, # input volume depth == input channel dim == 1 + out_channels=16, # expand output feature map volume's depth to 16 + kernel_size=3, # typical 3*3 stride 1 kernel + stride=1, + padding=1 + ), + nn.BatchNorm2d(16), # batch normalize the output feature map before activation + nn.ReLU(), # feature map --> activation map + nn.MaxPool2d(kernel_size=2, stride=2), #typical maxpool kernel size + nn.Dropout(p=0.3), #randomly zero 30% of 1st layer's output feature map in training + + # 2nd 2D convolution layer identical to last except output dim, maxpool kernel + nn.Conv2d( + in_channels=16, + out_channels=32, # expand output feature map volume's depth to 32 + kernel_size=3, + stride=1, + padding=1 + ), + nn.BatchNorm2d(32), + nn.ReLU(), + nn.MaxPool2d(kernel_size=4, stride=4), # increase maxpool kernel for subsequent filters + nn.Dropout(p=0.3), + + # 3rd 2D convolution layer identical to last except output dim + nn.Conv2d( + in_channels=32, + out_channels=64, # expand output feature map volume's depth to 64 + kernel_size=3, + stride=1, + padding=1 + ), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(kernel_size=4, stride=4), + nn.Dropout(p=0.3), + ) + ############### 2ND PARALLEL 2D CONVOLUTION BLOCK ############ + # 3 sequential conv2D layers: (1,40,282) --> (16, 20, 141) -> (32, 5, 35) -> (64, 1, 8) + self.conv2Dblock2 = nn.Sequential( + + # 1st 2D convolution layer + nn.Conv2d( + in_channels=1, # input volume depth == input channel dim == 1 + out_channels=16, # expand output feature map volume's depth to 16 + kernel_size=3, # typical 3*3 stride 1 kernel + stride=1, + padding=1 + ), + nn.BatchNorm2d(16), # batch normalize the output feature map before activation + nn.ReLU(), # feature map --> activation map + nn.MaxPool2d(kernel_size=2, stride=2), #typical maxpool kernel size + nn.Dropout(p=0.3), #randomly zero 30% of 1st layer's output feature map in training + + # 2nd 2D convolution layer identical to last except output dim, maxpool kernel + nn.Conv2d( + in_channels=16, + out_channels=32, # expand output feature map volume's depth to 32 + kernel_size=3, + stride=1, + padding=1 + ), + nn.BatchNorm2d(32), + nn.ReLU(), + nn.MaxPool2d(kernel_size=4, stride=4), # increase maxpool kernel for subsequent filters + nn.Dropout(p=0.3), + + # 3rd 2D convolution layer identical to last except output dim + nn.Conv2d( + in_channels=32, + out_channels=64, # expand output feature map volume's depth to 64 + kernel_size=3, + stride=1, + padding=1 + ), + nn.BatchNorm2d(64), + nn.ReLU(), + nn.MaxPool2d(kernel_size=4, stride=4), + nn.Dropout(p=0.3), + ) + + ################# FINAL LINEAR BLOCK #################### + # Linear softmax layer to take final concatenated embedding tensor + # from parallel 2D convolutional and transformer blocks, output 8 logits + # Each full convolution block outputs (64*1*8) embedding flattened to dim 512 1D array + # Full transformer block outputs 40*70 feature map, which we time-avg to dim 40 1D array + # 512*2+40 == 1064 input features --> 8 output emotions + self.fc1_linear = nn.Linear(512*2+40,num_emotions) + + ### Softmax layer for the 8 output logits from final FC linear layer + self.softmax_out = nn.Softmax(dim=1) # dim==1 is the freq embedding + + # define one complete parallel fwd pass of input feature tensor thru 2*conv+1*transformer blocks + def forward(self,x): + + ############ 1st parallel Conv2D block: 4 Convolutional layers ############################ + # create final feature embedding from 1st convolutional layer + # input features pased through 4 sequential 2D convolutional layers + conv2d_embedding1 = self.conv2Dblock1(x) # x == N/batch * channel * freq * time + + # flatten final 64*1*4 feature map from convolutional layers to length 256 1D array + # skip the 1st (N/batch) dimension when flattening + conv2d_embedding1 = torch.flatten(conv2d_embedding1, start_dim=1) + + ############ 2nd parallel Conv2D block: 4 Convolutional layers ############################# + # create final feature embedding from 2nd convolutional layer + # input features pased through 4 sequential 2D convolutional layers + conv2d_embedding2 = self.conv2Dblock2(x) # x == N/batch * channel * freq * time + + # flatten final 64*1*4 feature map from convolutional layers to length 256 1D array + # skip the 1st (N/batch) dimension when flattening + conv2d_embedding2 = torch.flatten(conv2d_embedding2, start_dim=1) + + + ########## 4-encoder-layer Transformer block w/ 64-->512-->64 feedfwd network ############## + # maxpool input feature map: 1*40*282 w/ 1*4 kernel --> 1*40*70 + x_maxpool = self.transformer_maxpool(x) + + # remove channel dim: 1*40*70 --> 40*70 + x_maxpool_reduced = torch.squeeze(x_maxpool,1) + + # convert maxpooled feature map format: batch * freq * time ---> time * batch * freq format + # because transformer encoder layer requires tensor in format: time * batch * embedding (freq) + x = x_maxpool_reduced.permute(2,0,1) + + # finally, pass reduced input feature map x into transformer encoder layers + transformer_output = self.transformer_encoder(x) + + # create final feature emedding from transformer layer by taking mean in the time dimension (now the 0th dim) + # transformer outputs 64*140 (freq embedding*time) feature map, take mean of all columns i.e. take time average + transformer_embedding = torch.mean(transformer_output, dim=0) # dim 40x70 --> 40 + + ############# concatenate freq embeddings from convolutional and transformer blocks ###### + # concatenate embedding tensors output by parallel 2*conv and 1*transformer blocks + complete_embedding = torch.cat([conv2d_embedding1, conv2d_embedding2,transformer_embedding], dim=1) + + ######### final FC linear layer, need logits for loss ######################### + output_logits = self.fc1_linear(complete_embedding) + + ######### Final Softmax layer: use logits from FC linear, get softmax for prediction ###### + output_softmax = self.softmax_out(output_logits) + + # need output logits to compute cross entropy loss, need softmax probabilities to predict class + return output_logits, output_softmax + +"""## 网络张量分析 +We zero-pad 1 the input feature map to each convolutional layer to get back from the layer the same shape tensor as we input: zero-pad 1 adds 2 to each of (H, W) dims, and the 3x3, stride 1 kernels cuts off (kernel - stride == 2) dims from each of (H,W). **Zero-pad 1 --> 3x3 stride 1 kernel effectively throws away the zero pads to get same input/output shape from each conv2D block.** + +At the end of first convolutional layer in each block we have a maxpool kernel of size 2x2, stride 2 which will take 1 of 4 pixels in its winddow. For the input feature map the maxpool kernel will progress 128/2 = 64 times over the rows and 563/2=281 times over the columns. **Nonoverlapping maxpool kernel reduces each output dim to input dim/kernel size.** We then expand the output channels to 16 making an output feature map of (16x64x281). + +The next two convolutional layers in each block have a maxpool kernel size 8x8, stride 8. Same math as above, maxpool reduces each dim/8. 2nd conv layer takes (16x64x281) --> (32x8x35). 3rd and final conv layer takes (32x8x35) --> (64x1x4). + +**Note that in (N,C,H,W) format, for MFCCs H = MFCC (pitch), W = time step.** + +**Complete flow through each convolutional block (C,H,W):** + + Layer 1 ---> 1x128x563 --> PAD-1 --> 1x130x565 --> FILTER --> 16x128x563 --> MAXPOOL 2x2 stride 2 --> 16x64x281 + + Layer 2 ---> 16x64x281 --> PAD-1 --> 16x66x283 --> FILTER --> 32x64x281 --> MAXPOOL 8x8 stride 8 --> 32x8x35 + + Layer 3 ---> 32x8x35 --> PAD-1 --> 32x10x37 --> FILTER --> 64x8x35 --> MAXPOOL 8x8 stride 8 --> 64x1x4 + + Flatten ---> 64x1x4 --> Final convolutional embedding length 256 1D array + + +**Complete flow through transformer encoder block (C,H,W):** + + Maxpool 2x4 stride 2x4 ---> 1x128x563 --> 1x64x140 + + Drop channel ---> 1x64x140 --> 64x140 (H,W) + + Change dims ---> 64x140 --> 140x64 (W,H) + + 4*Transformer encoder ---> 140x64 --> 2x64 (W,H) + + Time average ---> 2x64 --> 1x64 --> Final transformer embedding length 64 1D array + +**FC Linear network (C,H,W):** + + Concatenate ---> 256x256x64 --> 576 + + FC Linear layer ---> 576 --> Final linear logits output length 8 1D array + + Softmax layer: 8 ----> 1 predicted emotion / max probability class + + +We can confirm our network's tensor shapes and flow using the excellent torchsummary package which provides a PyTorch implementation of Keras' model.summary method: +""" + +from torchsummary import summary + +# need device to instantiate model +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +# instantiate model for 8 emotions and move to CPU for summary +model = parallel_all_you_want(len(emotions_dict)).to(device) + + +data = torch.randint(255, size=(2, 1, 40, 282)).float() +print("data: ", data.type()) +model(data) + +# include input feature map dims in call to summary() +summary(model, input_size=(1,40,282)) + + diff --git a/LYZ/cnn_gru.py b/LYZ/cnn_gru.py new file mode 100644 index 0000000..8cbffde --- /dev/null +++ b/LYZ/cnn_gru.py @@ -0,0 +1,414 @@ + +# 主网络 +import torch +import torch.nn as nn +import torch.optim as optim +import torch.utils.data as data +import numpy as np +import pickle +import glob +from timeit import default_timer as timer +import time +import warnings + +# 用 BiGRU 网络试试 +from model import * + +# 不输出“Warning”信息 +# warnings.filterwarnings("ignore") +""" +出现过错误的地方,反映了基础不牢 +交叉熵:https://blog.csdn.net/dss_dssssd/article/details/84036913 +label 转 one-hot:https://blog.csdn.net/qq_34914551/article/details/88700334 +""" + +LSTM_UNITS = 92 +MINI_BATCH = 10 +TRAIN_STEPS_PER_EPOCH = 12000 +VALIDATION_STEPS_PER_EPOCH = 800 +DATA_DIR = 'D:\\PyProject\\malware_traffic\\3_Packet\\' +CHECKPOINTS_DIR = './checkpoints/' + +dict_5class = {0: 'Normal', 1: 'BFSSH', 2: 'Infilt', 3: 'HttpDoS', 4: 'DDoS'} + +PACKET_NUM_PER_SESSION = 14 +PACKET_LEN = 100 + + +class ByteBlock(nn.Module): + """ + 卷积神经网络 + """ + def __init__(self, in_channels, nb_filter=(64, 100), filter_length=(3, 3), + subsample=(2, 1), pool_length=(2, 2)): + super(ByteBlock, self).__init__() + + layers = [] + for i in range(len(nb_filter)): + layers.append(nn.Conv1d(in_channels, nb_filter[i], kernel_size=filter_length[i], + padding=0, stride=subsample[i])) + layers.append(nn.Tanh()) + if pool_length[i]: + layers.append(nn.MaxPool1d(pool_length[i])) + in_channels = nb_filter[i] + + self.block = nn.Sequential(*layers) + self.global_pool = nn.AdaptiveMaxPool1d(1) + self.fc = nn.Linear(nb_filter[-1], 128) + + def forward(self, x): + x = self.block(x) + x = self.global_pool(x).squeeze(dim=2) + x = torch.nn.functional.relu(self.fc(x)) + return x + + +class FlowDataset(data.Dataset): + def __init__(self, sessions, labels, indices): + self.sessions = sessions[indices] + self.labels = labels[indices] + self.indices = indices + + def __len__(self): + return len(self.indices) + + def __getitem__(self, index): + idx = self.indices[index] + session = torch.tensor(self.sessions[idx], dtype=torch.int64) + label = torch.tensor(self.labels[idx], dtype=torch.int64) + return session, label + + +def update_confusion_matrix(confusion_matrix, actual_lb, predict_lb): + for idx, value in enumerate(actual_lb): + p_value = predict_lb[idx] + confusion_matrix[value, p_value] += 1 + return confusion_matrix + + +def truncate(f, n): + trunc_f = np.math.floor(f * 10 ** n) / 10 ** n + return '{:.2f}'.format(trunc_f) + + +def binarize(x, sz=256): + return torch.nn.functional.one_hot(x, sz).float() + + +class OneHotEncodingLayer(nn.Module): + def __init__(self, sz=256): + super(OneHotEncodingLayer, self).__init__() + self.size = sz + + def forward(self, x): + return torch.nn.functional.one_hot(x, num_classes=self.size).float() + + +""" +# 可以改为 FlowDataLoader 中数据 +def mini_batch_generator(dataset, batch_size): + data_loader = data.DataLoader(dataset, batch_size=batch_size, shuffle=True) + while True: + for sessions, labels in data_loader: + Xbatch = torch.ones((batch_size, PACKET_NUM_PER_SESSION, PACKET_LEN), dtype=torch.int64) * -1 + Ybatch = torch.ones((batch_size, 5), dtype=torch.int64) * -1 + for batch_idx, (session, label) in enumerate(zip(sessions, labels)): + for i, packet in enumerate(session): + if i < PACKET_NUM_PER_SESSION: + for j, byte in enumerate(packet[:PACKET_LEN]): + Xbatch[batch_idx, i, (PACKET_LEN - 1 - j)] = byte + Ybatch[batch_idx] = torch.nn.functional.one_hot(label, num_classes=5)[0] + yield Xbatch, Ybatch +""" + + +class MyDataset(data.Dataset): + """ + 数据转换编码(独热编码) + """ + def __init__(self, sessions, labels, indices): + self.sessions = sessions + self.labels = labels + self.indices = indices + self.packet_num_per_session = PACKET_NUM_PER_SESSION + self.packet_len = PACKET_LEN + + def __getitem__(self, index): + idx = self.indices[index] + X = torch.ones((self.packet_num_per_session, self.packet_len), dtype=torch.int64) * -1 + + for i, packet in enumerate(self.sessions[idx]): + if i < self.packet_num_per_session: + for j, byte in enumerate(packet[:self.packet_len]): + X[i, (self.packet_len - 1 - j)] = byte + + # label = self.labels[idx].astype(np.int64) # CrossEntropyLoss 会自动把标签转换成onehot形式 + # y = torch.nn.functional.one_hot(torch.from_numpy(label), num_classes=5)[0] + y = self.labels[idx][0].astype(np.int64) + return X, y + + def __len__(self): + return len(self.indices) + + +class MyModel(nn.Module): + """ + 模型定义 + """ + def __init__(self, flow_len, packet_len, gru_units): + super(MyModel, self).__init__() + self.packet_len = packet_len + self.flow_len = flow_len + self.batch_size = 10 + self.gru_hidden_size = gru_units + + self.embedding = OneHotEncodingLayer(sz=256) # 独热编码 + self.block2 = ByteBlock(self.packet_len, (128, 256), (5, 5), (1, 1), (2, 2)) + self.block3 = ByteBlock(self.packet_len, (192, 320), (7, 5), (1, 1), (2, 2)) + + self.lstm_layer = nn.GRU(256, self.gru_hidden_size, dropout=0.1, bidirectional=True) + self.dense_layer = nn.Linear(self.gru_hidden_size * 2, 5) # # 其实像特征聚类,输出聚类数 + # self.output = nn.Softmax(dim=1) + + def forward(self, x): # x: [batch_size, flow_len, packet_len] = [10, 14, 100] + embeddings_list = self.embedding(x) # [10, 14, 100, 256] + encoder_list = torch.zeros((self.batch_size, self.flow_len, 256)) + for ix, embeddings in enumerate(embeddings_list): # [14, 100, 256] + # print("embeddings 1: ", embeddings.shape) + # embeddings = embeddings.permute(0, 2, 1) + # print("embeddings 2: ", embeddings.shape) + encoder1 = self.block2(embeddings) # [14, 128] + # print("encoder 1: ", encoder1.shape) + encoder2 = self.block3(embeddings) # [14, 128] + # print("encoder 2: ", encoder2.shape) + encoder = torch.cat([encoder1, encoder2], 1) # [14, 256] + # print("encoder : ", encoder.shape) + encoder_list[ix] = encoder + + # rnn 网络输入:[seq_len, batch_size, hidden_size] + encoder_list = encoder_list.permute(1, 0, 2) # [10, 14, 256] -> [14, 10 ,256] + biLSTM, final_hidden_state = self.lstm_layer(encoder_list) # [14, 10, 184], [2, 10, 92] + biLSTM = biLSTM.permute(1, 0, 2) # [10, 14, 184] + # print("biLSTM: ", biLSTM.shape) + attn_output, attention = self.attention_net(biLSTM, final_hidden_state) + dense = self.dense_layer(attn_output) + # out = self.output(dense) + # out = dense[:, -1, :] + return dense + + # lstm_output : [batch_size, n_step, self.byte_hidden_size * num_directions(=2)], F matrix + def attention_net(self, lstm_output, final_state): + # print("lstm_output: ", lstm_output.shape) + # print("final_state: ", final_state.shape) + # hidden : [batch_size, self.byte_hidden_size * num_directions(=2), 1(=n_layer)] + hidden = final_state.view(-1, self.gru_hidden_size * 2, 1) # Tensor维度的重构,-1表示该维度取决于其他维度 + # attn_weights : [batch_size, n_step] + attn_weights = torch.bmm(lstm_output, hidden).squeeze(2) # 加权求和,第三维降维 + soft_attn_weights = torch.nn.functional.softmax(attn_weights, 1) + # [batch_size, self.byte_hidden_size * num_directions(=2), n_step] * [batch_size, n_step, 1] + # = [batch_size, self.byte_hidden_size * num_directions(=2), 1] + context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2) + return context, soft_attn_weights # context : [batch_size, self.byte_hidden_size * num_directions(=2)] + + +def save_result(cf_ma, len_test, epochs=8): + """ + 计算metrics_list,保存测试/训练结果 + :param cf_ma: + :param len_test: + :param epochs: + :return: + """ + metrics_list = [] + for i in range(5): + if i == 0: + metrics_list.append( + [dict_5class[i], str(i), str(cf_ma[i, 0]), str(cf_ma[i, 1]), str(cf_ma[i, 2]), str(cf_ma[i, 3]), + str(cf_ma[i, 4]), '--', '--', '--']) + else: + acc = truncate((float(len_test - cf_ma[:, i].sum() - cf_ma[i, :].sum() + cf_ma[i, i] * 2) / len_test) * 100, + 2) + tpr = truncate((float(cf_ma[i, i]) / cf_ma[i].sum()) * 100, 2) + fpr = truncate((float(cf_ma[0, i]) / cf_ma[0].sum()) * 100, 2) + metrics_list.append( + [dict_5class[i], str(i), str(cf_ma[i, 0]), str(cf_ma[i, 1]), str(cf_ma[i, 2]), str(cf_ma[i, 3]), + str(cf_ma[i, 4]), str(acc), str(tpr), str(fpr)]) + overall_acc = truncate( + (float(cf_ma[0, 0] + cf_ma[1, 1] + cf_ma[2, 2] + cf_ma[3, 3] + cf_ma[4, 4]) / len_test) * 100, 2) + overall_tpr = truncate((float(cf_ma[1, 1] + cf_ma[2, 2] + cf_ma[3, 3] + cf_ma[4, 4]) / cf_ma[1:].sum()) * 100, 2) + overall_fpr = truncate((float(cf_ma[0, 1:].sum()) / cf_ma[0, :].sum()) * 100, 2) + + with open('iscx12_cnn_rnn_5class_attn.txt', 'a') as f: + f.write("\n") + t = time.strftime('%Y-%m-%d %X', time.localtime()) + f.write(t + "\n") + f.write('CLASS_NUM: 5\n') + f.write('PACKET_LEN: ' + str(PACKET_LEN) + "\n") + f.write('PACKET_NUM_PER_SESSION: ' + str(PACKET_NUM_PER_SESSION) + "\n") + f.write('MINI_BATCH: ' + str(MINI_BATCH) + "\n") + f.write('TRAIN_EPOCHS: ' + str(epochs) + "\n") + f.write('DATA_DIR: ' + DATA_DIR + "\n") + f.write("label\tindex\t0\t1\t2\t3\t4\tACC\tTPR\tFPR\n") + for metrics in metrics_list: + f.write('\t'.join(metrics) + "\n") + f.write('Overall accuracy: ' + str(overall_acc) + "\n") + f.write('Overall TPR: ' + str(overall_tpr) + "\n") + f.write('Overall FPR: ' + str(overall_fpr) + "\n") + # f.write('Train time(second): ' + str(int(train_time)) + "\n") + # f.write('Test time(second): ' + str(int(test_time)) + "\n\n") + f.write("\n\n") + + +def train(model, dataloader, criterion, optimizer, device): + model.train() + running_loss = 0.0 + num = 0 + for inputs, labels in dataloader: + inputs = inputs.to(device) + labels = labels.to(device) + + optimizer.zero_grad() # 梯度清零 + + outputs = model(inputs) + num += 1 + # print(“ {}/{} outputs & label shape: ".format(num,len(dataloader.data_loader)), outputs.shape, labels.shape) + loss = criterion(outputs, labels) + + loss.backward() + optimizer.step() + + running_loss += loss.item() * inputs.size(0) + + return running_loss / len(dataloader.dataset) + + +def evaluate(model, dataloader, criterion, device): + model.eval() + running_loss = 0.0 + cf_ma = np.zeros((5, 5), dtype=int) + num = 0 + with torch.no_grad(): + for inputs, labels in dataloader: + inputs = inputs.to(device) + labels = labels.to(device) + + outputs = model(inputs) + loss = criterion(outputs, labels) + + running_loss += loss.item() * inputs.size(0) + predicted_labels = torch.argmax(outputs, dim=1).cpu().numpy() + true_labels = labels.cpu().numpy() + + cf_ma = update_confusion_matrix(cf_ma, true_labels, predicted_labels) + num += predicted_labels.shape[0] + + print("num len: ", num) + save_result(cf_ma, num) + return running_loss / len(dataloader.dataset), cf_ma + + +def load_data(): + """ + 加载数据 + :return: + """ + t1 = timer() + sessions = [] + labels = [] + num_pkls = len(glob.glob(DATA_DIR + 'ISCX2012_labels_*.pkl')) # 匹配路径 + for i in range(num_pkls): + # if i != 1: + # continue + session_pkl = DATA_DIR + 'ISCX2012_pcaps_' + str(i) + '.pkl' + session_lists = pickle.load(open(session_pkl, 'rb')) # 反序列化对象 + sessions.extend(session_lists.values.tolist()) # 追加元素 + + label_pkl = DATA_DIR + 'ISCX2012_labels_' + str(i) + '.pkl' + label_lists = pickle.load(open(label_pkl, 'rb')) + labels.extend(label_lists.values.tolist()) + print(i) + t2 = timer() + print("load data tims: ", t2 - t1) + + labels = np.array(labels) + normal_indices = np.where(labels == 0)[0] # 结果所在的 行,是个array + # 数据量太大,不好训练。以下注释代码可以选择100000条正常流量进入训练(建议在数据预处理阶段选择一定数量的正常数据——节约内存开支) + normal_indices = np.random.choice(normal_indices, 100000, replace=False) # 注释代码 + attack_indices = [np.where(labels == i)[0] for i in range(1, 5)] # label 1~4 所在行,是个 list + # np.random.choice 会重复抽样, 若想不重复,增加参数:replace=False + test_normal_indices = np.random.choice(normal_indices, int(len(normal_indices) * 0.4), replace=False) + test_attack_indices = np.concatenate( # 模态融合 + [np.random.choice(attack_indices[i], int(len(attack_indices[i]) * 0.4), replace=False) for i in range(4)]) + test_indices = np.concatenate([test_normal_indices, test_attack_indices]).astype(int) + # train_indices = np.array(list(set(np.arange(len(labels))) - set(test_indices))) + attack_indices = np.concatenate(attack_indices).astype(int) # 注释代码 + indices = np.concatenate([normal_indices, attack_indices]).astype(int) # 注释代码 + train_indices = np.array(list(set(indices) - set(test_indices))) # 注释代码 + + return sessions, labels, train_indices, test_indices + + +# 定义超参数 +NUM_EPOCHS = 8 +LEARNING_RATE = 0.001 + +# 创建模型实例 +model = MyModel(PACKET_NUM_PER_SESSION, PACKET_LEN, LSTM_UNITS) +# model = PLA_Attention_Model(100, 100, 50, 100, 14) + +# 将模型移到GPU上(如果可用) +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") +model.to(device) + +# 定义损失函数和优化器 +criterion = nn.CrossEntropyLoss() +optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE) + +# 创建训练集和验证集的数据加载器 +sessions, labels, train_indices, test_indices = load_data() + +train_dataset = MyDataset(sessions, labels, train_indices) # # num_workers=2,Windows不允许多个进程加载数据 +train_dataloader = data.DataLoader(train_dataset, batch_size=MINI_BATCH, shuffle=True, drop_last=True) + +val_dataset = MyDataset(sessions, labels, test_indices) # 丢弃不成 batch 数据,否则会报错 +val_dataloader = data.DataLoader(val_dataset, batch_size=MINI_BATCH, shuffle=False, drop_last=True) + +# 开始训练 +start_time = timer() + +for epoch in range(NUM_EPOCHS): + # 训练模型 + train_loss = train(model, train_dataloader, criterion, optimizer, device) + # print(f"Train Loss: {truncate(train_loss, 4)}") + # 在验证集上评估模型 + val_loss, confusion_matrix = evaluate(model, val_dataloader, criterion, device) + + # 输出训练和验证的损失以及混淆矩阵 + print(f"Epoch {epoch + 1}/{NUM_EPOCHS}") + print(f"Train Loss: {truncate(train_loss, 4)}") + print(f"Validation Loss: {truncate(val_loss, 4)}") + print("Confusion Matrix:") + for i in range(5): + for j in range(5): + print(confusion_matrix[i][j], end="\t") + print() + print("---------------------------------") + +end_time = timer() +training_time = end_time - start_time + +print(f"Training Time: {truncate(training_time, 2)} seconds") + +""" +Epoch 7/10 +Train Loss: 0.35 +Validation Loss: 0.35 +Confusion Matrix: +39794 43 45 20 98 +472 2272 1 0 0 +3832 1 31 3 0 +1166 0 0 136 0 +56 0 1 0 8219 +--------------------------------- +Train Loss: 0.35 +""" diff --git a/LYZ/cnn_gru_clutering.py b/LYZ/cnn_gru_clutering.py new file mode 100644 index 0000000..32f07e2 --- /dev/null +++ b/LYZ/cnn_gru_clutering.py @@ -0,0 +1,422 @@ + +# 主网络 +import torch +import torch.nn as nn +import torch.optim as optim +import torch.utils.data as data +from torch.nn.functional import normalize +import numpy as np +import pickle +import glob +from timeit import default_timer as timer +import time +import warnings + +# 用 BiGRU 网络试试 +from model import * + +# 不输出“Warning”信息 +# warnings.filterwarnings("ignore") +""" +出现过错误的地方,反映了基础不牢 +交叉熵:https://blog.csdn.net/dss_dssssd/article/details/84036913 +label 转 one-hot:https://blog.csdn.net/qq_34914551/article/details/88700334 + +实验自适应据类 +""" + +LSTM_UNITS = 92 +MINI_BATCH = 10 +TRAIN_STEPS_PER_EPOCH = 12000 +VALIDATION_STEPS_PER_EPOCH = 800 +DATA_DIR = 'D:\\PyProject\\malware_traffic\\3_Packet\\' +CHECKPOINTS_DIR = './checkpoints/' + +dict_5class = {0: 'Normal', 1: 'BFSSH', 2: 'Infilt', 3: 'HttpDoS', 4: 'DDoS'} +class_num = 5 + +PACKET_NUM_PER_SESSION = 14 +PACKET_LEN = 100 + + +class ByteBlock(nn.Module): + """ + 卷积神经网络 + """ + def __init__(self, in_channels, nb_filter=(64, 100), filter_length=(3, 3), + subsample=(2, 1), pool_length=(2, 2)): + super(ByteBlock, self).__init__() + + layers = [] + for i in range(len(nb_filter)): + layers.append(nn.Conv1d(in_channels, nb_filter[i], kernel_size=filter_length[i], + padding=0, stride=subsample[i])) + layers.append(nn.Tanh()) + if pool_length[i]: + layers.append(nn.MaxPool1d(pool_length[i])) + in_channels = nb_filter[i] + + self.block = nn.Sequential(*layers) + self.global_pool = nn.AdaptiveMaxPool1d(1) + self.fc = nn.Linear(nb_filter[-1], 128) + + def forward(self, x): + x = self.block(x) + x = self.global_pool(x).squeeze(dim=2) + x = torch.nn.functional.relu(self.fc(x)) + return x + + +def update_confusion_matrix(confusion_matrix, actual_lb, predict_lb): + for idx, value in enumerate(actual_lb): + p_value = predict_lb[idx] + confusion_matrix[value, p_value] += 1 + return confusion_matrix + + +def truncate(f, n): + trunc_f = np.math.floor(f * 10 ** n) / 10 ** n + return '{:.2f}'.format(trunc_f) + + +def binarize(x, sz=256): + return torch.nn.functional.one_hot(x, sz).float() + + +class OneHotEncodingLayer(nn.Module): + def __init__(self, sz=256): + super(OneHotEncodingLayer, self).__init__() + self.size = sz + + def forward(self, x): + return torch.nn.functional.one_hot(x, num_classes=self.size).float() + + +class MyDataset(data.Dataset): + """ + 数据转换编码(独热编码) + """ + def __init__(self, sessions, labels, indices): + self.sessions = sessions + self.labels = labels + self.indices = indices + self.packet_num_per_session = PACKET_NUM_PER_SESSION + self.packet_len = PACKET_LEN + + def __getitem__(self, index): + idx = self.indices[index] + X = torch.ones((self.packet_num_per_session, self.packet_len), dtype=torch.int64) * -1 + + for i, packet in enumerate(self.sessions[idx]): + if i < self.packet_num_per_session: # 每个数据会话留只取前 num 个 + for j, byte in enumerate(packet[:self.packet_len]): # 每个数据包取前 PACKET_LEN 字节 + X[i, (self.packet_len - 1 - j)] = byte + + # label = self.labels[idx].astype(np.int64) # CrossEntropyLoss 会自动把标签转换成onehot形式 + # y = torch.nn.functional.one_hot(torch.from_numpy(label), num_classes=5)[0] + y = self.labels[idx][0].astype(np.int64) + return X, y + + def __len__(self): + return len(self.indices) + + +class FEMnet(nn.Module): + """ + Feature extraction module 定义 + """ + def __init__(self, flow_len, packet_len, gru_units): + super(FEMnet, self).__init__() + self.packet_len = packet_len + self.flow_len = flow_len + self.batch_size = 10 + self.gru_hidden_size = gru_units + self.rep_dim = gru_units + + self.embedding = OneHotEncodingLayer(sz=256) # 独热编码 + self.block2 = ByteBlock(self.packet_len, (128, 256), (5, 5), (1, 1), (2, 2)) + self.block3 = ByteBlock(self.packet_len, (192, 320), (7, 5), (1, 1), (2, 2)) + + self.lstm_layer = nn.GRU(256, self.gru_hidden_size, dropout=0.1, bidirectional=True) + # self.dense_layer = nn.Linear(self.gru_hidden_size * 2, 5) + # self.output = nn.Softmax(dim=1) # Linear 自带Softmax 分类 + + def forward(self, x): # x: [batch_size, flow_len, packet_len] = [10, 14, 100] + embeddings_list = self.embedding(x) # [10, 14, 100, 256] + encoder_list = torch.zeros((self.batch_size, self.flow_len, 256)) + for ix, embeddings in enumerate(embeddings_list): # [14, 100, 256] + # print("embeddings 1: ", embeddings.shape) + # embeddings = embeddings.permute(0, 2, 1) + # print("embeddings 2: ", embeddings.shape) + encoder1 = self.block2(embeddings) # [14, 128] + # print("encoder 1: ", encoder1.shape) + encoder2 = self.block3(embeddings) # [14, 128] + # print("encoder 2: ", encoder2.shape) + encoder = torch.cat([encoder1, encoder2], 1) # [14, 256] + # print("encoder : ", encoder.shape) + encoder_list[ix] = encoder + + # rnn 网络输入:[seq_len, batch_size, hidden_size] + encoder_list = encoder_list.permute(1, 0, 2) # [10, 14, 256] -> [14, 10 ,256] + biLSTM, final_hidden_state = self.lstm_layer(encoder_list) # [14, 10, 184], [2, 10, 92] + biLSTM = biLSTM.permute(1, 0, 2) # [10, 14, 184] + # print("biLSTM: ", biLSTM.shape) + attn_output, attention = self.attention_net(biLSTM, final_hidden_state) + dense = self.dense_layer(attn_output) + # out = self.output(dense) + # out = dense[:, -1, :] + return dense + + # lstm_output : [batch_size, n_step, self.byte_hidden_size * num_directions(=2)], F matrix + def attention_net(self, lstm_output, final_state): + # print("lstm_output: ", lstm_output.shape) + # print("final_state: ", final_state.shape) + # hidden : [batch_size, self.byte_hidden_size * num_directions(=2), 1(=n_layer)] + hidden = final_state.view(-1, self.gru_hidden_size * 2, 1) # Tensor维度的重构,-1表示该维度取决于其他维度 + # attn_weights : [batch_size, n_step] + attn_weights = torch.bmm(lstm_output, hidden).squeeze(2) # 加权求和,第三维降维 + soft_attn_weights = torch.nn.functional.softmax(attn_weights, 1) + # [batch_size, self.byte_hidden_size * num_directions(=2), n_step] * [batch_size, n_step, 1] + # = [batch_size, self.byte_hidden_size * num_directions(=2), 1] + context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2) + return context, soft_attn_weights # context : [batch_size, self.byte_hidden_size * num_directions(=2)] + + +class MyModel(nn.Module): + """ + Feature extraction module定义 + """ + def __init__(self, binet, feature_dim, class_n): + super(MyModel, self).__init__() + self.binet = binet + self.feature_dim = feature_dim + self.cluster_num = class_n + """ 对比聚类 """ + self.instance_projector = nn.Sequential( # 实例-单例 + nn.Linear(self.binet.rep_dim, self.binet.rep_dim), + nn.ReLU(), + nn.Linear(self.binet.rep_dim, self.feature_dim), + ) + self.cluster_projector = nn.Sequential( # 聚类-集群 + nn.Linear(self.binet.rep_dim, self.binet.rep_dim), + nn.ReLU(), + nn.Linear(self.binet.rep_dim, self.cluster_num), + nn.Softmax(dim=1) + ) + + # 训练时执行 + def forward(self, x_i, x_j): # x_i, x_j 来自同一数据的两种不同预处理方式得到的嵌入矩阵 + h_i = self.resnet(x_i) + h_j = self.resnet(x_j) + + z_i = normalize(self.instance_projector(h_i), dim=1) + z_j = normalize(self.instance_projector(h_j), dim=1) + + c_i = self.cluster_projector(h_i) + c_j = self.cluster_projector(h_j) + + return z_i, z_j, c_i, c_j + + # 测试时执行 + def forward_cluster(self, x): + h = self.resnet(x) + c = self.cluster_projector(h) # 聚类分布 + c = torch.argmax(c, dim=1) # 得到每个样本的聚类标签。 + return c + + +def save_result(cf_ma, len_test, epochs=8): + """ + 计算 metrics_list,保存测试/训练结果 + :param cf_ma: + :param len_test: + :param epochs: + :return: + """ + metrics_list = [] + for i in range(5): + if i == 0: + metrics_list.append( + [dict_5class[i], str(i), str(cf_ma[i, 0]), str(cf_ma[i, 1]), str(cf_ma[i, 2]), str(cf_ma[i, 3]), + str(cf_ma[i, 4]), '--', '--', '--']) + else: + acc = truncate((float(len_test - cf_ma[:, i].sum() - cf_ma[i, :].sum() + cf_ma[i, i] * 2) / len_test) * 100, + 2) + tpr = truncate((float(cf_ma[i, i]) / cf_ma[i].sum()) * 100, 2) + fpr = truncate((float(cf_ma[0, i]) / cf_ma[0].sum()) * 100, 2) + metrics_list.append( + [dict_5class[i], str(i), str(cf_ma[i, 0]), str(cf_ma[i, 1]), str(cf_ma[i, 2]), str(cf_ma[i, 3]), + str(cf_ma[i, 4]), str(acc), str(tpr), str(fpr)]) + overall_acc = truncate( + (float(cf_ma[0, 0] + cf_ma[1, 1] + cf_ma[2, 2] + cf_ma[3, 3] + cf_ma[4, 4]) / len_test) * 100, 2) + overall_tpr = truncate((float(cf_ma[1, 1] + cf_ma[2, 2] + cf_ma[3, 3] + cf_ma[4, 4]) / cf_ma[1:].sum()) * 100, 2) + overall_fpr = truncate((float(cf_ma[0, 1:].sum()) / cf_ma[0, :].sum()) * 100, 2) + + # 获取当前日期 + current_date = time.strftime("%Y%m%d", time.localtime()) + # 构造文件名 + file_name = f"evaluate_{current_date}.txt" + + with open(file_name, 'a') as f: + f.write("\n") + t = time.strftime('%Y-%m-%d %X', time.localtime()) + f.write(t + "\n") + f.write('CLASS_NUM: 5\n') + f.write('PACKET_LEN: ' + str(PACKET_LEN) + "\n") + f.write('PACKET_NUM_PER_SESSION: ' + str(PACKET_NUM_PER_SESSION) + "\n") + f.write('MINI_BATCH: ' + str(MINI_BATCH) + "\n") + f.write('TRAIN_EPOCHS: ' + str(epochs) + "\n") + f.write('DATA_DIR: ' + DATA_DIR + "\n") + f.write("label\tindex\t0\t1\t2\t3\t4\tACC\tTPR\tFPR\n") + for metrics in metrics_list: + f.write('\t'.join(metrics) + "\n") + f.write('Overall accuracy: ' + str(overall_acc) + "\n") + f.write('Overall TPR: ' + str(overall_tpr) + "\n") + f.write('Overall FPR: ' + str(overall_fpr) + "\n") + # f.write('Train time(second): ' + str(int(train_time)) + "\n") + # f.write('Test time(second): ' + str(int(test_time)) + "\n\n") + f.write("\n\n") + + +def train(model, dataloader, criterion, optimizer, device): + model.train() + running_loss = 0.0 + num = 0 + for inputs, labels in dataloader: + inputs = inputs.to(device) + labels = labels.to(device) + + optimizer.zero_grad() # 梯度清零 + + outputs = model(inputs) + num += 1 + # print(“ {}/{} outputs & label shape: ".format(num,len(dataloader.data_loader)), + # outputs.shape, labels.shape) + loss = criterion(outputs, labels) + + loss.backward() + optimizer.step() + + running_loss += loss.item() * inputs.size(0) + + return running_loss / len(dataloader.dataset) + + +def evaluate(model, dataloader, criterion, device): + model.eval() + running_loss = 0.0 + cf_ma = np.zeros((5, 5), dtype=int) + num = 0 + with torch.no_grad(): + for inputs, labels in dataloader: + inputs = inputs.to(device) + labels = labels.to(device) + + outputs = model(inputs) + loss = criterion(outputs, labels) + + running_loss += loss.item() * inputs.size(0) + predicted_labels = torch.argmax(outputs, dim=1).cpu().numpy() + true_labels = labels.cpu().numpy() + + cf_ma = update_confusion_matrix(cf_ma, true_labels, predicted_labels) + num += predicted_labels.shape[0] + + print("num len: ", num) + save_result(cf_ma, num) + return running_loss / len(dataloader.dataset), cf_ma + + +def load_data(): + """ + 加载数据 + :return: + """ + t1 = timer() + sessions = [] + labels = [] + num_pkls = len(glob.glob(DATA_DIR + 'ISCX2012_labels_*.pkl')) # 匹配路径 + for i in range(num_pkls): + # if i != 1: + # continue + session_pkl = DATA_DIR + 'ISCX2012_pcaps_' + str(i) + '.pkl' + session_lists = pickle.load(open(session_pkl, 'rb')) # 反序列化对象 + sessions.extend(session_lists.values.tolist()) # 追加元素 + + label_pkl = DATA_DIR + 'ISCX2012_labels_' + str(i) + '.pkl' + label_lists = pickle.load(open(label_pkl, 'rb')) + labels.extend(label_lists.values.tolist()) + print(i) + t2 = timer() + print("load data tims: ", t2 - t1) + + labels = np.array(labels) + normal_indices = np.where(labels == 0)[0] # 结果所在的 行,是个array + # 数据量太大,不好训练。以下注释代码可以选择100000条正常流量进入训练(建议在数据预处理阶段选择一定数量的正常数据——节约内存开支) + normal_indices = np.random.choice(normal_indices, 100000, replace=False) # 注释代码 + attack_indices = [np.where(labels == i)[0] for i in range(1, 5)] # label 1~4 所在行,是个 list + # np.random.choice 会重复抽样, 若想不重复,增加参数:replace=False + test_normal_indices = np.random.choice(normal_indices, int(len(normal_indices) * 0.4), replace=False) + test_attack_indices = np.concatenate( # 模态融合 + [np.random.choice(attack_indices[i], int(len(attack_indices[i]) * 0.4), replace=False) for i in range(4)]) + test_indices = np.concatenate([test_normal_indices, test_attack_indices]).astype(int) + # train_indices = np.array(list(set(np.arange(len(labels))) - set(test_indices))) + attack_indices = np.concatenate(attack_indices).astype(int) # 注释代码 + indices = np.concatenate([normal_indices, attack_indices]).astype(int) # 注释代码 + train_indices = np.array(list(set(indices) - set(test_indices))) # 注释代码 + + return sessions, labels, train_indices, test_indices + + +# 定义超参数 +NUM_EPOCHS = 8 +LEARNING_RATE = 0.001 + +# 创建模型实例 +fe_model = FEMnet(PACKET_NUM_PER_SESSION, PACKET_LEN, LSTM_UNITS) +model = MyModel(fe_model, 128, class_num) +# model = PLA_Attention_Model(100, 100, 50, 100, 14) + +# 将模型移到GPU上(如果可用) +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") +model.to(device) + +# 定义损失函数和优化器 +criterion = nn.CrossEntropyLoss() +optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE) + +# 创建训练集和验证集的数据加载器 +sessions, labels, train_indices, test_indices = load_data() + +train_dataset = MyDataset(sessions, labels, train_indices) # # num_workers=2,Windows不允许多个进程加载数据 +train_dataloader = data.DataLoader(train_dataset, batch_size=MINI_BATCH, shuffle=True, drop_last=True) + +val_dataset = MyDataset(sessions, labels, test_indices) # 丢弃不成 batch 数据,否则会报错 +val_dataloader = data.DataLoader(val_dataset, batch_size=MINI_BATCH, shuffle=False, drop_last=True) + +# 开始训练 +start_time = timer() + +for epoch in range(NUM_EPOCHS): + # 训练模型 + train_loss = train(model, train_dataloader, criterion, optimizer, device) + # print(f"Train Loss: {truncate(train_loss, 4)}") + # 在验证集上评估模型 + val_loss, confusion_matrix = evaluate(model, val_dataloader, criterion, device) + + # 输出训练和验证的损失以及混淆矩阵 + print(f"Epoch {epoch + 1}/{NUM_EPOCHS}") + print(f"Train Loss: {truncate(train_loss, 4)}") + print(f"Validation Loss: {truncate(val_loss, 4)}") + print("Confusion Matrix:") + for i in range(5): + for j in range(5): + print(confusion_matrix[i][j], end="\t") + print() + print("---------------------------------") + +end_time = timer() +training_time = end_time - start_time + +print(f"Training Time: {truncate(training_time, 2)} seconds") + diff --git a/LYZ/dataloader.py b/LYZ/dataloader.py new file mode 100644 index 0000000..99c08b4 --- /dev/null +++ b/LYZ/dataloader.py @@ -0,0 +1,65 @@ +import os +import os.path as osp +import numpy as np +import pandas as pd +import torch +import torch.utils.data as data +from scapy.all import rdpcap # pcap 数据处理包 +import time +import csv + + +class NetworkFlowDataset(data.Dataset): + def __init__(self, pcapname, csvname): + super().__init__() + self.pcap_data = rdpcap(osp.join('data', pcapname)) + self.label_data = pd.read_csv(osp.join('data', csvname), encoding='latin1') + + def __len__(self): + return len(self.pcap_data) + + def __getitem__(self, idx): + sample_raw = self.pcap_data[idx].load + sample = np.frombuffer(sample_raw, dtype=np.uint8) + + label_raw = self.label_data[idx]['Label'] + return sample, label_raw + + +class NetworkFlowDataloader(object): + def __init__(self, opt, dataset): + super().__init__() + use_cuda = not torch.cuda.is_available() + kwargs = {'num_workers': opt.num_workers} if use_cuda else {} + + self.data_loader = torch.utils.data.DataLoader( + dataset, batch_size=opt.batch_size, shuffle=True, **kwargs) + + self.data_iter = self.data_loader.__iter__() + + def next_batch(self): + try: + batch = self.data_iter.__next__() + except StopIteration: + self.data_iter = self.data_loader.__iter__() + batch = self.data_iter.__next__() + + return batch + + +if __name__ == '__main__': + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('-n', '--num-workers', type=int, default=4) + parser.add_argument('-e', '--epoch', type=int, default=10) + parser.add_argument('-b', '--batch-size', type=int, default=4) + parser.add_argument('-d', '--display-step', type=int, default=600) + opt = parser.parse_args() + + start = time.time() + dataset = NetworkFlowDataset('Thursday-WorkingHours.pcap', 'Thursday-WorkingHours-Morning-WebAttacks.pcap_ISCX.csv') + data_loader = NetworkFlowDataloader(opt, dataset) + + print('[+] Size of the dataset: %05d, dataloader: %03d' + % (len(dataset), len(data_loader.data_loader))) diff --git a/LYZ/loss.py b/LYZ/loss.py new file mode 100644 index 0000000..db97235 --- /dev/null +++ b/LYZ/loss.py @@ -0,0 +1,24 @@ +import torch +import torch.nn as nn + + +class Loss(nn.Module): + def __init__(self): + super().__init__() + self.loss = nn.BCELoss() + + def forward(self, x, y): + return self.loss(x, y) + + +if __name__ == '__main__': + batch_size = 3 + + x = torch.rand(batch_size, 1).cuda() + y = torch.rand(batch_size, 1).cuda() + + criterion = Loss() + loss = criterion(x, y) + + print(loss.shape) + print(loss) diff --git a/LYZ/model.py b/LYZ/model.py new file mode 100644 index 0000000..fda9f80 --- /dev/null +++ b/LYZ/model.py @@ -0,0 +1,76 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class PLA_Attention_Model(nn.Module): + def __init__(self, byte_hidden_size, packet_hidden_size, packet_output_size, max_packet=1500, max_flow=128): + super().__init__() + self.byte_emb_size = 50 + self.byte_hidden_size = byte_hidden_size # 100 + self.packet_emb_size = 50 + self.packet_hidden_size = packet_hidden_size # 100 + self.packet_output_size = packet_output_size # 50 + self.max_packet = max_packet + self.max_flow = max_flow + + self.embedding = nn.Embedding(256 * 256, self.byte_emb_size) + self.byte_GRU = nn.GRU(self.byte_emb_size, self.byte_hidden_size, bias=False, bidirectional=True) + self.byte_attn = nn.Linear(self.byte_hidden_size * 2, self.packet_emb_size) + self.packet_GRU = nn.GRU(self.packet_emb_size, self.packet_hidden_size, bias=False, bidirectional=True) + self.packet_attn = nn.Linear(self.packet_hidden_size * 2, self.packet_output_size) + self.classify = nn.Linear(self.packet_output_size, 11) + + # lstm_output : [batch_size, n_step, self.byte_hidden_size * num_directions(=2)], F matrix + def attention_net(self, lstm_output, final_state): + # print("lstm_output: ", lstm_output.shape) + # print("final_state: ", final_state.shape) + # hidden : [batch_size, self.byte_hidden_size * num_directions(=2), 1(=n_layer)] + hidden = final_state.view(-1, self.byte_hidden_size * 2, 1) # Tensor维度的重构,-1表示该维度取决于其他维度 + # attn_weights : [batch_size, n_step] + attn_weights = torch.bmm(lstm_output, hidden).squeeze(2) # 加权求和,第三维降维 + soft_attn_weights = F.softmax(attn_weights, 1) + # [batch_size, self.byte_hidden_size * num_directions(=2), n_step] * [batch_size, n_step, 1] + # = [batch_size, self.byte_hidden_size * num_directions(=2), 1] + context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2) + return context, soft_attn_weights # context : [batch_size, self.byte_hidden_size * num_directions(=2)] + + def forward(self, flow): + num_packet = flow.shape[0] + batch_size = flow.shape[1] + embedded_bytes_list = self.embedding(flow) + encoding_bytes_list = torch.zeros((num_packet, batch_size, self.packet_emb_size))#.cuda() # [4, 3, 120, 50] + for i, embedded_bytes in enumerate(embedded_bytes_list): # [3, 120, 50] + h0_bytes = torch.randn(2, batch_size, self.byte_hidden_size)#.cuda() # [2,3,100] + embedded_bytes = embedded_bytes.transpose(0, 1) # 交换 dim_0 和 dim_1 : [120, 3, 50] + # print(embedded_bytes.shape, h0_bytes.shape) + output, final_hidden_state = self.byte_GRU(embedded_bytes, h0_bytes) # [120, 3, 200], [2, 3, 100] + output = output.permute(1, 0, 2) # [3, 120, 200] + # print(output.shape) + # print("final: ", final_hidden_state.shape) + attn_output, attention = self.attention_net(output, final_hidden_state) # [3, 200] + # print("attn_output", attn_output.shape) + encoding_bytes_list[i] = self.byte_attn(attn_output) # [4, 3, 50] 最后一维维持不变 + + # print("2: ", encoding_bytes_list.shape) # [4, 3, 50] + h0_packet = torch.randn(2, batch_size, self.packet_hidden_size)#.cuda() # [2,3,100] + # print(h0_packet.shape) + output, final_hidden_state = self.packet_GRU(encoding_bytes_list, h0_packet) + # print("final_hidden_state: ", final_hidden_state.shape) # [2, 3, 100] + output = output.permute(1, 0, 2) # 维度排列转置 [3, 4, 200] + attn_output, attention = self.attention_net(output, final_hidden_state) # [3, 200] + print("attn_output2: ", attn_output.shape) + output = self.packet_attn(attn_output) + classify = self.classify(output) + + return classify + + +if __name__ == '__main__': + batch_size = 3 + model = PLA_Attention_Model(100, 100, 50)#.cuda() + print(model) + data = torch.randint(255, size=(4, batch_size, 120))#.cuda() # flow_len, batch_size, packet_len + print(data.shape) + res = model(data) + print(res.shape) diff --git a/LYZ/model/Bartmodel.py b/LYZ/model/Bartmodel.py new file mode 100644 index 0000000..c0635ba --- /dev/null +++ b/LYZ/model/Bartmodel.py @@ -0,0 +1,898 @@ +from transformers import BartPretrainedModel, BartConfig +from transformers.models.bart.modeling_bart import BartLearnedPositionalEmbedding, BartEncoderLayer, BartDecoderLayer, _expand_mask, \ + _make_causal_mask, shift_tokens_right +from transformers.modeling_outputs import BaseModelOutput, BaseModelOutputWithPastAndCrossAttentions, Seq2SeqModelOutput +from torch.nn import TransformerEncoderLayer +from transformers.utils import logging +import torch.nn as nn +import torch.nn.functional as F +from dataclasses import dataclass +from torch.nn import CrossEntropyLoss +from transformers.file_utils import ModelOutput +import torch +import random +from typing import Optional, Tuple +import math +import pandas as pd +import numpy as np + +logger = logging.get_logger(__name__) + + +# 引入了话语级Transformer来模拟话语之间的长期上下文依赖关系 +# 定义了可重复使用的 Transformer 模型单元 +class TransformerUnit(nn.Module): + def __init__(self, d_model: int, n_heads: int = 8): + super(TransformerUnit, self).__init__() + + self.d_model = d_model # 隐藏层维度 + self.n_heads = n_heads # 注意力头数 + # self.out_features = out_features + # activation by default the GELU + self.transformerlayer = TransformerEncoderLayer( # 构建 Transformer 编码层的模块 + d_model=d_model, + nhead=n_heads, + activation='gelu' # 基于高斯误差函数的激活函数 + ) + + def forward(self, features): + features = self.transformerlayer(features) # (bsz, dim) + # dense_features = self.linear(features) # (bsz, cls_num) + return features + + +# 利用 BART,一种具有编码器-解码器结构的预训练 Transformer,作为骨干模型,并通过对比和生成损失任务对其进行增强。 +# 定义 BART 模型的编码器 +class BartEncoder(BartPretrainedModel): + """ + Transformer encoder consisting of *config.encoder_layers* self attention layers. Each layer is a + :class:`BartEncoderLayer`. + + Args: + config: BartConfig + embed_tokens (nn.Embedding): output embedding + """ + + def __init__(self, config: BartConfig, embed_tokens: Optional[nn.Embedding] = None): + super().__init__(config) + + self.dropout = config.dropout # dropout 率 + self.layerdrop = config.encoder_layerdrop + + embed_dim = config.d_model + self.padding_idx = config.pad_token_id + self.max_source_positions = config.max_position_embeddings + self.embed_scale = math.sqrt(embed_dim) if config.scale_embedding else 1.0 # 嵌入尺度 + + # 如果提供了 embed_tokens 参数,则直接使用;否则,创建一个新的嵌入层。 + if embed_tokens is not None: + self.embed_tokens = embed_tokens + else: + self.embed_tokens = nn.Embedding(config.vocab_size, embed_dim, self.padding_idx) + + # 位置嵌入层 + """ + 位置嵌入是一种用于引入序列中单词位置信息的技术, + 因为Transformer模型并不关注输入序列中单词的顺序。 + 通过引入位置嵌入,模型能够了解单词在序列中的相对位置。 + """ + self.embed_positions = BartLearnedPositionalEmbedding( + config.max_position_embeddings, + embed_dim, + ) + # 多个BART编码器层 + self.layers = nn.ModuleList([BartEncoderLayer(config) for _ in range(config.encoder_layers)]) + self.layernorm_embedding = nn.LayerNorm(embed_dim) # 归一化 + + self.init_weights() + + def forward( + self, + input_ids=None, # 输入序列索引 + attention_mask=None, # 掩码[0,1]以避免网络关注填充令牌索引 + head_mask=None, # 掩码[0,1]使注意力模块的选定头部无效 + inputs_embeds=None, + output_attentions=None, + output_hidden_states=None, # 是否返回隐藏层状态 + return_dict=None, # 返回字典/元组 + ): + r""" 加 r 防止字符转义 + Args: + input_ids (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`): + Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you + provide it. + + Indices can be obtained using :class:`~transformers.BartTokenizer`. See + :meth:`transformers.PreTrainedTokenizer.encode` and :meth:`transformers.PreTrainedTokenizer.__call__` + for details. + + `What are input IDs? <../glossary.html#input-ids>`__ + attention_mask (:obj:`torch.Tensor` of shape :obj:`(batch_size, sequence_length)`, `optional`): + Mask to avoid performing attention on padding token indices. Mask values selected in ``[0, 1]``: + + - 1 for tokens that are **not masked**, + - 0 for tokens that are **masked**. + + `What are attention masks? <../glossary.html#attention-mask>`__ + head_mask (:obj:`torch.Tensor` of shape :obj:`(encoder_layers, encoder_attention_heads)`, `optional`): + Mask to nullify selected heads of the attention modules. Mask values selected in ``[0, 1]``: + + - 1 indicates the head is **not masked**, + - 0 indicates the head is **masked**. + + inputs_embeds (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`): + Optionally, instead of passing :obj:`input_ids` you can choose to directly pass an embedded + representation. This is useful if you want more control over how to convert :obj:`input_ids` indices + into associated vectors than the model's internal embedding lookup matrix. + output_attentions (:obj:`bool`, `optional`): + Whether or not to return the attentions tensors of all attention layers. See ``attentions`` under + returned tensors for more detail. + output_hidden_states (:obj:`bool`, `optional`): + Whether or not to return the hidden states of all layers. See ``hidden_states`` under returned tensors + for more detail. + return_dict (:obj:`bool`, `optional`): + Whether or not to return a :class:`~transformers.file_utils.ModelOutput` instead of a plain tuple. + """ + output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions + output_hidden_states = ( + output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states + ) + return_dict = return_dict if return_dict is not None else self.config.use_return_dict + + # retrieve input_ids and inputs_embeds + if input_ids is not None and inputs_embeds is not None: + raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time") + elif input_ids is not None: # 如果使用 input_ids,将其展平成二维张量。 + input_shape = input_ids.size() + input_ids = input_ids.view(-1, input_shape[-1]) + elif inputs_embeds is not None: + input_shape = inputs_embeds.size()[:-1] + else: + raise ValueError("You have to specify either input_ids or inputs_embeds") + + # 如果没有提供 inputs_embeds,使用模型自带的嵌入层 获得 输入序列的嵌入表示 + if inputs_embeds is None: + inputs_embeds = self.embed_tokens(input_ids) * self.embed_scale + + # 对输入序列的位置信息进行嵌入得到张量 + embed_pos = self.embed_positions(input_shape) + + # 将位置嵌入加到输入序列的嵌入表示中,以引入位置信息。这是为了让模型更好地理解输入序列中不同位置的单词。 + hidden_states = inputs_embeds + embed_pos + # 归一化操作有助于缓解训练中的梯度消失问题,提高模型的训练稳定性。 + hidden_states = self.layernorm_embedding(hidden_states) + # dropout 操作 + hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training) + + # expand attention_mask + # 如果提供了 attention_mask,为了与注意力模块的计算匹配,将其扩展为形状 [batch_size, 1, tgt_seq_len, src_seq_len]。 + if attention_mask is not None: + # [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len] + attention_mask = _expand_mask(attention_mask, inputs_embeds.dtype) + + encoder_states = () if output_hidden_states else None + all_attentions = () if output_attentions else None + + # check if head_mask has a correct number of layers specified if desired + # 确保该掩码(mask)的数量与编码器层的数量匹配 + if head_mask is not None: # head_mask 用于指定在注意力操作中哪些头部应该被禁用 + assert head_mask.size()[0] == ( + len(self.layers) + ), f"The head_mask should be specified for {len(self.layers)} layers, but it is for {head_mask.size()[0]}." + # 对编码器的每一层进行迭代 + for idx, encoder_layer in enumerate(self.layers): + if output_hidden_states: + encoder_states = encoder_states + (hidden_states,) # 将每一层的隐藏状态添加到 encoder_states 中 + # add LayerDrop (see https://arxiv.org/abs/1909.11556 for description) + # LayerDrop 机制:在训练中随机跳过某些编码器层的方法,以提高模型的鲁棒性。 + dropout_probability = random.uniform(0, 1) + if self.training and (dropout_probability < self.layerdrop): # skip the layer + layer_outputs = (None, None) + else: + if getattr(self.config, "gradient_checkpointing", False) and self.training: # 是否开启梯度检查点 + + def create_custom_forward(module): # 内部函数 + def custom_forward(*inputs): + return module(*inputs, output_attentions) + + return custom_forward + + layer_outputs = torch.utils.checkpoint.checkpoint( + create_custom_forward(encoder_layer), + hidden_states, + attention_mask, + (head_mask[idx] if head_mask is not None else None), + ) + else: + layer_outputs = encoder_layer( + hidden_states, + attention_mask, + layer_head_mask=(head_mask[idx] if head_mask is not None else None), + output_attentions=output_attentions, + ) + + hidden_states = layer_outputs[0] + + if output_attentions: + all_attentions = all_attentions + (layer_outputs[1],) + + if output_hidden_states: + encoder_states = encoder_states + (hidden_states,) + + if not return_dict: # 如果不使用字典,则返回元组 + return tuple(v for v in [hidden_states, encoder_states, all_attentions] if v is not None) + return BaseModelOutput( + last_hidden_state=hidden_states, hidden_states=encoder_states, attentions=all_attentions + ) + + +# 定义 BART 模型的解码器 +class BartDecoder(BartPretrainedModel): + """ + Transformer decoder consisting of *config.decoder_layers* layers. Each layer is a :class:`BartDecoderLayer` + + Args: + config: BartConfig + embed_tokens (nn.Embedding): output embedding + """ + + def __init__(self, config: BartConfig, embed_tokens: Optional[nn.Embedding] = None): + super().__init__(config) + self.dropout = config.dropout + self.layerdrop = config.decoder_layerdrop + self.padding_idx = config.pad_token_id + self.max_target_positions = config.max_position_embeddings + self.embed_scale = math.sqrt(config.d_model) if config.scale_embedding else 1.0 # 嵌入尺度 + + # 嵌入层 + if embed_tokens is not None: + self.embed_tokens = embed_tokens + else: + self.embed_tokens = nn.Embedding(config.vocab_size, config.d_model, self.padding_idx) + + # 位置嵌入层 + self.embed_positions = BartLearnedPositionalEmbedding( + config.max_position_embeddings, + config.d_model, + ) + # 多个BART解码器层 + self.layers = nn.ModuleList([BartDecoderLayer(config) for _ in range(config.decoder_layers)]) + self.layernorm_embedding = nn.LayerNorm(config.d_model) + + self.init_weights() + + # 返回嵌入层 + def get_input_embeddings(self): + return self.embed_tokens + + # 设置嵌入层 + def set_input_embeddings(self, value): + self.embed_tokens = value + + # 创建解码器的自注意力掩码。包括 创建因果(causal)掩码和扩展输入序列的掩码 + def _prepare_decoder_attention_mask(self, attention_mask, input_shape, inputs_embeds, past_key_values_length): + # create causal mask + # [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len] + combined_attention_mask = None + if input_shape[-1] > 1: + combined_attention_mask = _make_causal_mask( + input_shape, inputs_embeds.dtype, past_key_values_length=past_key_values_length + ).to(self.device) + + if attention_mask is not None: + # [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len] + expanded_attn_mask = _expand_mask(attention_mask, inputs_embeds.dtype, tgt_len=input_shape[-1]) + combined_attention_mask = ( + expanded_attn_mask if combined_attention_mask is None else expanded_attn_mask + combined_attention_mask + ) + + return combined_attention_mask + + def forward( + self, + input_ids=None, + attention_mask=None, + encoder_hidden_states=None, + encoder_attention_mask=None, + head_mask=None, + cross_attn_head_mask=None, + past_key_values=None, + inputs_embeds=None, + use_cache=None, # 解码过程可以通过缓存中间结果,避免在每个时间步重新计算。 + output_attentions=None, + output_hidden_states=None, + return_dict=None, + ): + r""" + Args: + input_ids (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`): + Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you + provide it. + + Indices can be obtained using :class:`~transformers.BartTokenizer`. See + :meth:`transformers.PreTrainedTokenizer.encode` and :meth:`transformers.PreTrainedTokenizer.__call__` + for details. + + `What are input IDs? <../glossary.html#input-ids>`__ + attention_mask (:obj:`torch.Tensor` of shape :obj:`(batch_size, sequence_length)`, `optional`): + Mask to avoid performing attention on padding token indices. Mask values selected in ``[0, 1]``: + + - 1 for tokens that are **not masked**, + - 0 for tokens that are **masked**. + + `What are attention masks? <../glossary.html#attention-mask>`__ + encoder_hidden_states (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, encoder_sequence_length, hidden_size)`, `optional`): + Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention + of the decoder. + encoder_attention_mask (:obj:`torch.LongTensor` of shape :obj:`(batch_size, encoder_sequence_length)`, `optional`): + Mask to avoid performing cross-attention on padding tokens indices of encoder input_ids. Mask values + selected in ``[0, 1]``: + + - 1 for tokens that are **not masked**, + - 0 for tokens that are **masked**. + + `What are attention masks? <../glossary.html#attention-mask>`__ + head_mask (:obj:`torch.Tensor` of shape :obj:`(decoder_layers, decoder_attention_heads)`, `optional`): + Mask to nullify selected heads of the attention modules. Mask values selected in ``[0, 1]``: + + - 1 indicates the head is **not masked**, + - 0 indicates the head is **masked**. + + cross_attn_head_mask (:obj:`torch.Tensor` of shape :obj:`(decoder_layers, decoder_attention_heads)`, `optional`): + Mask to nullify selected heads of the cross-attention modules in the decoder to avoid performing + cross-attention on hidden heads. Mask values selected in ``[0, 1]``: + + - 1 indicates the head is **not masked**, + - 0 indicates the head is **masked**. + + past_key_values (:obj:`tuple(tuple(torch.FloatTensor))`, `optional`, returned when ``use_cache=True`` is passed or when ``config.use_cache=True``): + Tuple of :obj:`tuple(torch.FloatTensor)` of length :obj:`config.n_layers`, with each tuple having 2 + tensors of shape :obj:`(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional + tensors of shape :obj:`(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`. + + Contains pre-computed hidden-states (key and values in the self-attention blocks and in the + cross-attention blocks) that can be used (see :obj:`past_key_values` input) to speed up sequential + decoding. + + If :obj:`past_key_values` are used, the user can optionally input only the last + :obj:`decoder_input_ids` (those that don't have their past key value states given to this model) of + shape :obj:`(batch_size, 1)` instead of all :obj:`decoder_input_ids`` of shape :obj:`(batch_size, + sequence_length)`. + inputs_embeds (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`): + Optionally, instead of passing :obj:`input_ids` you can choose to directly pass an embedded + representation. This is useful if you want more control over how to convert :obj:`input_ids` indices + into associated vectors than the model's internal embedding lookup matrix. + output_attentions (:obj:`bool`, `optional`): + Whether or not to return the attentions tensors of all attention layers. See ``attentions`` under + returned tensors for more detail. + output_hidden_states (:obj:`bool`, `optional`): + Whether or not to return the hidden states of all layers. See ``hidden_states`` under returned tensors + for more detail. + return_dict (:obj:`bool`, `optional`): + Whether or not to return a :class:`~transformers.file_utils.ModelOutput` instead of a plain tuple. + """ + output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions + output_hidden_states = ( + output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states + ) + use_cache = use_cache if use_cache is not None else self.config.use_cache + return_dict = return_dict if return_dict is not None else self.config.use_return_dict + + # retrieve input_ids and inputs_embeds + if input_ids is not None and inputs_embeds is not None: + raise ValueError("You cannot specify both decoder_input_ids and decoder_inputs_embeds at the same time") + elif input_ids is not None: + input_shape = input_ids.size() + input_ids = input_ids.view(-1, input_shape[-1]) + elif inputs_embeds is not None: + input_shape = inputs_embeds.size()[:-1] + else: + raise ValueError("You have to specify either decoder_input_ids or decoder_inputs_embeds") + + # past_key_values_length + past_key_values_length = past_key_values[0][0].shape[2] if past_key_values is not None else 0 + + if inputs_embeds is None: + inputs_embeds = self.embed_tokens(input_ids) * self.embed_scale + + attention_mask = self._prepare_decoder_attention_mask( + attention_mask, input_shape, inputs_embeds, past_key_values_length + ) + + # expand encoder attention mask + if encoder_hidden_states is not None and encoder_attention_mask is not None: + # [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len] + encoder_attention_mask = _expand_mask(encoder_attention_mask, inputs_embeds.dtype, tgt_len=input_shape[-1]) + + # embed positions + positions = self.embed_positions(input_shape, past_key_values_length) + + hidden_states = inputs_embeds + positions + hidden_states = self.layernorm_embedding(hidden_states) + + hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training) + + # decoder layers + all_hidden_states = () if output_hidden_states else None + all_self_attns = () if output_attentions else None + all_cross_attentions = () if (output_attentions and encoder_hidden_states is not None) else None + next_decoder_cache = () if use_cache else None + + # check if head_mask/cross_attn_head_mask has a correct number of layers specified if desired + for attn_mask, mask_name in zip([head_mask, cross_attn_head_mask], ["head_mask", "cross_attn_head_mask"]): + if attn_mask is not None: + assert attn_mask.size()[0] == ( + len(self.layers) + ), f"The `{mask_name}` should be specified for {len(self.layers)} layers, but it is for {head_mask.size()[0]}." + for idx, decoder_layer in enumerate(self.layers): + # add LayerDrop (see https://arxiv.org/abs/1909.11556 for description) + if output_hidden_states: + all_hidden_states += (hidden_states,) + dropout_probability = random.uniform(0, 1) + if self.training and (dropout_probability < self.layerdrop): + continue + + past_key_value = past_key_values[idx] if past_key_values is not None else None + + if getattr(self.config, "gradient_checkpointing", False) and self.training: # 是否开启梯度检查点 + + if use_cache: # 这在生成任务(如文本生成)中特别有用,因为每次生成一个 token 时,都可以重复使用之前生成的中间结果,而无需重新计算整个序列。 + logger.warning( # 两个参数不兼容 + "`use_cache=True` is incompatible with `config.gradient_checkpointing=True`. Setting " + "`use_cache=False`..." + ) + use_cache = False + + def create_custom_forward(module): + def custom_forward(*inputs): + # None for past_key_value + return module(*inputs, output_attentions, use_cache) + + return custom_forward + + layer_outputs = torch.utils.checkpoint.checkpoint( + create_custom_forward(decoder_layer), + hidden_states, + attention_mask, + encoder_hidden_states, + encoder_attention_mask, + head_mask[idx] if head_mask is not None else None, + cross_attn_head_mask[idx] if cross_attn_head_mask is not None else None, + None, + ) + else: + + layer_outputs = decoder_layer( + hidden_states, + attention_mask=attention_mask, + encoder_hidden_states=encoder_hidden_states, + encoder_attention_mask=encoder_attention_mask, + layer_head_mask=(head_mask[idx] if head_mask is not None else None), + cross_attn_layer_head_mask=( + cross_attn_head_mask[idx] if cross_attn_head_mask is not None else None + ), + past_key_value=past_key_value, + output_attentions=output_attentions, + use_cache=use_cache, + ) + hidden_states = layer_outputs[0] + + if use_cache: + next_decoder_cache += (layer_outputs[3 if output_attentions else 1],) + + if output_attentions: + all_self_attns += (layer_outputs[1],) + + if encoder_hidden_states is not None: + all_cross_attentions += (layer_outputs[2],) + + # add hidden states from the last decoder layer + if output_hidden_states: + all_hidden_states += (hidden_states,) + + next_cache = next_decoder_cache if use_cache else None + if not return_dict: + return tuple( + v + for v in [hidden_states, next_cache, all_hidden_states, all_self_attns, all_cross_attentions] + if v is not None + ) + return BaseModelOutputWithPastAndCrossAttentions( + last_hidden_state=hidden_states, + past_key_values=next_cache, + hidden_states=all_hidden_states, + attentions=all_self_attns, + cross_attentions=all_cross_attentions, + ) + + +# 完整版 Bart 模型 +class BartModel(BartPretrainedModel): + def __init__(self, config: BartConfig): + super().__init__(config) + + padding_idx, vocab_size = config.pad_token_id, config.vocab_size + self.shared = nn.Embedding(vocab_size, config.d_model, padding_idx) + + self.encoder = BartEncoder(config, self.shared) + self.decoder = BartDecoder(config, self.shared) + + self.init_weights() + + def get_input_embeddings(self): + return self.shared + + def set_input_embeddings(self, value): + self.shared = value + self.encoder.embed_tokens = self.shared + self.decoder.embed_tokens = self.shared + + def get_encoder(self): + return self.encoder + + def get_decoder(self): + return self.decoder + + def forward( + self, + input_ids=None, + attention_mask=None, + decoder_input_ids=None, + decoder_attention_mask=None, + head_mask=None, + decoder_head_mask=None, + cross_attn_head_mask=None, + encoder_outputs=None, + past_key_values=None, + inputs_embeds=None, + decoder_inputs_embeds=None, + use_cache=None, + output_attentions=None, + output_hidden_states=None, + return_dict=None, + ): + + # different to other models, Bart automatically creates decoder_input_ids from + # input_ids if no decoder_input_ids are provided + if decoder_input_ids is None and decoder_inputs_embeds is None: + decoder_input_ids = shift_tokens_right( + input_ids, self.config.pad_token_id, self.config.decoder_start_token_id + ) + + output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions + output_hidden_states = ( + output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states + ) + use_cache = use_cache if use_cache is not None else self.config.use_cache + return_dict = return_dict if return_dict is not None else self.config.use_return_dict + + if encoder_outputs is None: + encoder_outputs = self.encoder( + input_ids=input_ids, + attention_mask=attention_mask, + head_mask=head_mask, + inputs_embeds=inputs_embeds, + output_attentions=output_attentions, + output_hidden_states=output_hidden_states, + return_dict=return_dict, + ) + # If the user passed a tuple for encoder_outputs, we wrap it in a BaseModelOutput when return_dict=True + elif return_dict and not isinstance(encoder_outputs, BaseModelOutput): + encoder_outputs = BaseModelOutput( + last_hidden_state=encoder_outputs[0], + hidden_states=encoder_outputs[1] if len(encoder_outputs) > 1 else None, + attentions=encoder_outputs[2] if len(encoder_outputs) > 2 else None, + ) + + # decoder outputs consists of (dec_features, past_key_value, dec_hidden, dec_attn) + decoder_outputs = self.decoder( + input_ids=decoder_input_ids, + attention_mask=decoder_attention_mask, + encoder_hidden_states=encoder_outputs[0], + encoder_attention_mask=attention_mask, + head_mask=decoder_head_mask, + cross_attn_head_mask=cross_attn_head_mask, + past_key_values=past_key_values, + inputs_embeds=decoder_inputs_embeds, + use_cache=use_cache, + output_attentions=output_attentions, + output_hidden_states=output_hidden_states, + return_dict=return_dict, + ) + + if not return_dict: + return decoder_outputs + encoder_outputs + + return Seq2SeqModelOutput( + last_hidden_state=decoder_outputs.last_hidden_state, + past_key_values=decoder_outputs.past_key_values, + decoder_hidden_states=decoder_outputs.hidden_states, + decoder_attentions=decoder_outputs.attentions, + cross_attentions=decoder_outputs.cross_attentions, + encoder_last_hidden_state=encoder_outputs.last_hidden_state, + encoder_hidden_states=encoder_outputs.hidden_states, + encoder_attentions=encoder_outputs.attentions, + ) + + +def SupConLoss(temperature=0.07, contrast_mode='all', features=None, labels=None, mask=None): + """Supervised Contrastive Learning: https://arxiv.org/pdf/2004.11362.pdf.""" + device = (torch.device('cuda') if features.is_cuda else torch.device('cpu')) + + if len(features.shape) < 3: + raise ValueError('`features` needs to be [bsz, n_views, ...],' + 'at least 3 dimensions are required') + if len(features.shape) > 3: + features = features.view(features.shape[0], features.shape[1], -1) + + batch_size = features.shape[0] + if labels is not None and mask is not None: + raise ValueError('Cannot define both `labels` and `mask`') + elif labels is None and mask is None: + mask = torch.eye(batch_size, dtype=torch.float32).to(device) + elif labels is not None: + labels = labels.contiguous().view(-1, 1) + if labels.shape[0] != batch_size: + raise ValueError('Num of labels does not match num of features') + mask = torch.eq(labels, labels.T).float().to(device) # 1 indicates two items belong to same class + else: + mask = mask.float().to(device) + + contrast_count = features.shape[1] # num of views + contrast_feature = torch.cat(torch.unbind(features, dim=1), dim=0) # (bsz * views, dim) + if contrast_mode == 'one': + anchor_feature = features[:, 0] + anchor_count = 1 + elif contrast_mode == 'all': + anchor_feature = contrast_feature # (bsz * views, dim) + anchor_count = contrast_count # num of views + else: + raise ValueError('Unknown mode: {}'.format(contrast_mode)) + + # compute logits + anchor_dot_contrast = torch.div( + torch.matmul(anchor_feature, contrast_feature.T), temperature) # (bsz, bsz) + # for numerical stability + logits_max, _ = torch.max(anchor_dot_contrast, dim=1, keepdim=True) # (bsz, 1) + logits = anchor_dot_contrast - logits_max.detach() # (bsz, bsz) set max_value in logits to zero + # logits = anchor_dot_contrast + + # tile mask + mask = mask.repeat(anchor_count, contrast_count) # (anchor_cnt * bsz, contrast_cnt * bsz) + # mask-out self-contrast cases + logits_mask = torch.scatter(torch.ones_like(mask), 1, torch.arange(batch_size * anchor_count).view(-1, 1).to(device), + 0) # (anchor_cnt * bsz, contrast_cnt * bsz) + mask = mask * logits_mask # 1 indicates two items belong to same class and mask-out itself + + # compute log_prob + exp_logits = torch.exp(logits) * logits_mask # (anchor_cnt * bsz, contrast_cnt * bsz) + log_prob = logits - torch.log(exp_logits.sum(1, keepdim=True) + 1e-12) + + # compute mean of log-likelihood over positive + if 0 in mask.sum(1): + raise ValueError('Make sure there are at least two instances with the same class') + # temp = mask.sum(1) + mean_log_prob_pos = (mask * log_prob).sum(1) / (mask.sum(1) + 1e-12) + + # loss + # loss = - (self.temperature / self.base_temperature) * mean_log_prob_pos + loss = -mean_log_prob_pos + loss = loss.view(anchor_count, batch_size).mean() + return loss + + +@dataclass +class Seq2SeqLMOutput(ModelOutput): + loss: Optional[torch.FloatTensor] = None + ce_loss: Optional[torch.FloatTensor] = None + cl_loss: Optional[torch.FloatTensor] = None + gen_loss: Optional[torch.FloatTensor] = None + logits: torch.FloatTensor = None + cls_logits: torch.FloatTensor = None + last_hidden_states: torch.FloatTensor = None + past_key_values: Optional[Tuple[Tuple[torch.FloatTensor]]] = None + decoder_hidden_states: Optional[Tuple[torch.FloatTensor]] = None + decoder_attentions: Optional[Tuple[torch.FloatTensor]] = None + cross_attentions: Optional[Tuple[torch.FloatTensor]] = None + encoder_last_hidden_state: Optional[torch.FloatTensor] = None + encoder_hidden_states: Optional[Tuple[torch.FloatTensor]] = None + encoder_attentions: Optional[Tuple[torch.FloatTensor]] = None + + +""" +class BartForMultiTask(BartPretrainedModel): +""" + + +class BartForERC(BartPretrainedModel): + base_model_prefix = "model" + _keys_to_ignore_on_load_missing = [r"final_logits_bias", r"lm_head\.weight"] + + def __init__(self, config: BartConfig, temperature, alpha, beta, use_trans_layer): + super().__init__(config) + self.model = BartModel(config) + # 注册一个名为 final_logits_bias 的缓冲区,用于生成最终的 logits + self.register_buffer("final_logits_bias", torch.zeros((1, self.model.shared.num_embeddings))) + # 使用一个线性层作为语言模型头(lm_head),将 BART 的隐藏表示映射到词汇表空间。 + self.lm_head = nn.Linear(config.d_model, self.model.shared.num_embeddings, bias=False) + + self.init_weights() + + # 引入了一个 Transformer 单元作为辅助任务模块,用于处理上下文表示。 + self.transformer_unit = TransformerUnit(d_model=config.hidden_size, n_heads=8) + # 前馈神经网络(ffn)用于分类任务,包括两个线性层和一个 GELU 激活函数。 + self.ffn = nn.Sequential(nn.Linear(config.hidden_size, 400), + nn.Dropout(0.3), + nn.GELU(), + nn.Linear(400, config.num_labels)) + + self.temperature = temperature # 温度参数,用于控制生成任务的 softmax 温度。 + self.alpha = alpha # 用于组合分类任务和对比损失的权重参数 + self.beta = beta # 用于组合分类任务和对比损失的权重参数(具体得看公式) + self.num_labels = config.num_labels + self.use_trans_layer = use_trans_layer # 是否使用 Transformer 单元进行特征变换 + + def get_encoder(self): + return self.model.get_encoder() + + def get_decoder(self): + return self.model.get_decoder() + + # 提供了改变 token embeddings 大小的方法 + def resize_token_embeddings(self, new_num_tokens: int) -> nn.Embedding: + new_embeddings = super().resize_token_embeddings(new_num_tokens) + self._resize_final_logits_bias(new_num_tokens) + return new_embeddings + + def _resize_final_logits_bias(self, new_num_tokens: int) -> None: + old_num_tokens = self.final_logits_bias.shape[-1] + if new_num_tokens <= old_num_tokens: + new_bias = self.final_logits_bias[:, :new_num_tokens] + else: + extra_bias = torch.zeros((1, new_num_tokens - old_num_tokens), device=self.final_logits_bias.device) + new_bias = torch.cat([self.final_logits_bias, extra_bias], dim=1) + self.register_buffer("final_logits_bias", new_bias) + + # 获取输出 embeddings 的方法 + def get_output_embeddings(self): + return self.lm_head + + def set_output_embeddings(self, new_embeddings): + self.lm_head = new_embeddings + + def forward( + self, + input_ids=None, # 输入序列的 token IDs + attention_mask=None, # 输入序列的注意力掩码,指示哪些位置是真实的 token + decoder_input_ids=None, # 解码器输入序列的 token IDs(用于生成任务) + decoder_attention_mask=None, # 解码器输入序列的注意力掩码 + head_mask=None, + decoder_head_mask=None, + cross_attn_head_mask=None, + encoder_outputs=None, + past_key_values=None, + inputs_embeds=None, + decoder_inputs_embeds=None, + labels=None, # 分类任务的真实标签 + use_cache=None, + output_attentions=None, + output_hidden_states=None, + return_dict=None, + speakers=None, + next_input_ids=None, # 是否进行生成任务 + next_attention_mask=None, + ): + r""" + labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`): + Labels for computing the masked language modeling loss. Indices should either be in ``[0, ..., + config.vocab_size]`` or -100 (see ``input_ids`` docstring). Tokens with indices set to ``-100`` are ignored + (masked), the loss is only computed for the tokens with labels in ``[0, ..., config.vocab_size]``. + + Returns: + """ + # 上下文掩码,表示哪些位置是真实的 token,通过计算输入序列的注意力掩码的和来得到 + context_mask = torch.sum(attention_mask, dim=-1).gt(0) + + batch_size, max_seq_len_ex, max_text_seq_len = input_ids.shape + seqlens = torch.sum(context_mask, dim=-1) + + # 生成任务 + if next_input_ids is not None: + decoder_input_ids = shift_tokens_right( # shift_tokens_right 函数将 next_input_ids 右移一位,得到解码器的输入序列。 + next_input_ids[context_mask, :], self.config.pad_token_id, self.config.decoder_start_token_id + ) + # hidden state for generation —— 生成任务 + # 对于生成任务,使用 BartModel 处理输入序列和生成序列的隐藏表示,然后通过 lm_head 得到 logits + outputs_gen = self.model(input_ids=input_ids[context_mask, :], + attention_mask=attention_mask[context_mask, :], + decoder_input_ids=decoder_input_ids) + hidden_states_gen = outputs_gen.last_hidden_state + gen_logits = self.lm_head(hidden_states_gen) + self.final_logits_bias + + # hidden state for classification —— 分类任务 + # 对于分类任务,使用 BartModel 处理输入序列,提取隐藏表示,通过最大池化获得全局特征,然后通过前馈神经网络 ffn 得到分类的 logits。 + outputs_cls = self.model(input_ids=input_ids[context_mask, :], # 使用上下文掩码提取输入序列的隐藏表示 + attention_mask=attention_mask[context_mask, :]) + hidden_states_cls = outputs_cls.last_hidden_state + + mask_for_fill = attention_mask[context_mask, :].unsqueeze(-1).expand(-1, -1, hidden_states_cls.shape[-1]).bool() + + hidden_states_dropout = hidden_states_cls.clone().detach() + + hidden_states = hidden_states_cls.masked_fill(~mask_for_fill, -1e8) # mask position of padding with -1e8 + hidden_states_dropout = hidden_states_dropout.masked_fill(~mask_for_fill, -1e8) + cls_tokens, _ = torch.max(hidden_states, dim=1) # max pooling 最大池化获得全局特征 cls_tokens + cls_tokens_dropout, _ = torch.max(hidden_states_dropout, dim=1) + + # 保证每个批次中的样本在序列长度上具有相同的维度 + we_dim = self.config.hidden_size + for ibatch in range(batch_size): + # 计算需要填充的零向量 fullzeropad4insert,其形状为 [max_seq_len_ex - seqlens[ibatch], we_dim], + # 其中 max_seq_len_ex 是序列的最大长度,seqlens[ibatch] 是当前样本的实际序列长度。 + fullzeropad4insert = torch.zeros([max_seq_len_ex - seqlens[ibatch], we_dim], device=cls_tokens.device) + # 计算插入位置的索引 index4insert,该位置是批次中当前样本序列的末尾 + index4insert = ibatch * max_seq_len_ex + seqlens[ibatch] + # 将零向量插入到 cls_tokens 的相应位置。这将在当前样本的序列末尾添加零向量,以使所有样本的序列长度相等。 + cls_tokens = torch.cat([cls_tokens[:index4insert], fullzeropad4insert, cls_tokens[index4insert:]], dim=0) + # 将零向量插入到 cls_tokens_dropout 的相应位置 + cls_tokens_dropout = torch.cat([cls_tokens_dropout[:index4insert], fullzeropad4insert, cls_tokens_dropout[index4insert:]], dim=0) + # 将调整后的 cls_tokens 和 cls_tokens_dropout 的形状变回 [batch_size, max_seq_len_ex, we_dim] + cls_tokens = cls_tokens.view(batch_size, max_seq_len_ex, we_dim) + cls_tokens_dropout = cls_tokens_dropout.view(batch_size, max_seq_len_ex, we_dim) + + if self.use_trans_layer: + cls_tokens = self.transformer_unit(cls_tokens) + cls_tokens_dropout = self.transformer_unit(cls_tokens_dropout) + + logits = self.ffn(cls_tokens) # 前馈神经网络 + logits_dropout = self.ffn(cls_tokens_dropout) + + loss_fct = CrossEntropyLoss() + + # 生成任务损失 + if next_input_ids is not None: + gen_loss = loss_fct(gen_logits.view(-1, self.config.vocab_size), next_input_ids[context_mask, :].view(-1)) + else: + gen_loss = 0 + # 分类任务损失 + if labels is not None: + ce_loss = loss_fct(logits[context_mask, :], labels[context_mask]) # 交叉熵损失 + cl_loss = SupConLoss(temperature=self.temperature, # 对比损失 + features=torch.stack([logits[context_mask, :], logits_dropout[context_mask, :]], dim=1), + labels=labels[context_mask]) + loss = (1 - self.alpha - self.beta) * ce_loss + self.alpha * cl_loss + self.beta * gen_loss # 整体损失 + # return loss, ce_loss, cl_loss, gen_loss + return Seq2SeqLMOutput( + loss=loss, + ce_loss=ce_loss, + cl_loss=cl_loss, + gen_loss=gen_loss + ) + else: # evaluate + return Seq2SeqLMOutput( + loss=None, + logits=None, + cls_logits=logits[context_mask, :], + last_hidden_states=cls_tokens[context_mask, :], + ) + + +""" +# 用于生成(generation)准备输入,通常用于生成文本的场景 +def prepare_inputs_for_generation( +""" + + +def prepare_decoder_input_ids_from_labels(self, labels: torch.Tensor): + return shift_tokens_right(labels, self.config.pad_token_id, self.config.decoder_start_token_id) + + +@staticmethod +def _reorder_cache(past, beam_idx): + reordered_past = () + for layer_past in past: + # cached cross_attention states don't have to be reordered -> they are always the same + reordered_past += ( + tuple(past_state.index_select(0, beam_idx) for past_state in layer_past[:2]) + layer_past[2:], + ) + return reordered_past diff --git a/LYZ/model/__pycache__/Bartmodel.cpython-37.pyc b/LYZ/model/__pycache__/Bartmodel.cpython-37.pyc new file mode 100644 index 0000000..3023e3a Binary files /dev/null and b/LYZ/model/__pycache__/Bartmodel.cpython-37.pyc differ diff --git a/LYZ/model/__pycache__/loggingHandler.cpython-37.pyc b/LYZ/model/__pycache__/loggingHandler.cpython-37.pyc new file mode 100644 index 0000000..16ad692 Binary files /dev/null and b/LYZ/model/__pycache__/loggingHandler.cpython-37.pyc differ diff --git a/LYZ/model/date_process.py b/LYZ/model/date_process.py new file mode 100644 index 0000000..bd8c494 --- /dev/null +++ b/LYZ/model/date_process.py @@ -0,0 +1,188 @@ +""" +数据预处理的 +现在先跑模型 +""" + +import os +import torch +import logging + +from typing import Optional + +from dataclasses import dataclass, field +from loggingHandler import LoggingHandler +from Bartmodel import BartForERC + +from transformers import (AutoTokenizer, + HfArgumentParser, + TrainingArguments, + AutoConfig, + set_seed) + +import fitlog + +logger = logging.getLogger(__name__) + +""" +python main.py \ +--model_name_or_path facebook/bart-large \ +--do_train \ +--task_name $TASK \ +--num_train_epochs $EPOCHS \ +--learning_rate $LEARNING_RATE \ +--output_dir ./save/$TASK \ +--overwrite_output_dir \ +--per_device_train_batch_size $TRAIN_BATCH_SIZE \ +--per_device_eval_batch_size $EVAL_BATCH_SIZE \ +--logging_steps $LOGGING_STEPS \ +--warmup_ratio $WARMUP_RATIO \ +--adam_epsilon 1e-6 \ +--weight_decay 0.01 \ +--seed $SEED \ +--alpha $ALPHA \ +--beta $BETA \ +--temperature $TEMPERATURE \ +--use_trans_layer $DIALOG_TRANSFORMER \ +--train_with_generation $TRAIN_WITH_GENERATION + +EPOCHS=4 +TRAIN_BATCH_SIZE=2 +LOGGING_STEPS=500 +WARMUP_RATIO=0.3 +LEARNING_RATE=2e-5 +ALPHA=0.1 +BETA=0.1 +TEMPERATURE=5 +""" + +# 差点 参数解析需要其他参数 +# 训练后模型保存地址 +model_output_dir = "./" + +rng_seed = -1 # 随机数种子,对话默认 738497 +model_name_or_path = "facebook/bart-large" # C:/Users/A00l/.cache/huggingface/hub/models--facebook--bart-large/snapshots/cb48c1365bd826bd521f650dc2e0940aee54720c" # 模型 +do_train = 1 # 训练模式 +do_eval = 0 # 验证模式 +temperature = 5 +alpha = 0.1 +beta = 0.1 +use_trans_layer = 1 + +if __name__ == '__main__': + # fitlog.commit(__file__) + logging.basicConfig(format='%(asctime)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + level=logging.INFO, + handlers=[LoggingHandler()]) + + # Set seed before initializing model. + + # 设置日志格式和级别 + fitlog.set_log_dir('./logs/') + # 设置随机种子 + rnd_seed = fitlog.set_rng_seed() if rng_seed == -1 else fitlog.set_rng_seed(rng_seed) + # training_args.seed = rnd_seed + + logger.info("The random seed is %d" % rnd_seed) + + device = 'cuda' if torch.cuda.is_available() else 'cpu' + + # speaker_vocab, label_vocab = load_vocab(other_args.task_name) # 加载词汇表 + num_labels = 6 # 标签数量 + + # 初始化 BART 模型的分词器 + tokenizer = AutoTokenizer.from_pretrained( + "facebook/bart-base", + cache_dir=None, + use_fast=True) + + data = torch.randint(255, size=(10, 14, 100)) + """ + train_dataloader, eval_dataloader, test_dataloader = get_dataloaders(tokenizer, other_args.task_name, + train_batch_size=training_args.per_device_train_batch_size, + eval_batch_size=training_args.per_device_eval_batch_size, + device=device, + train_with_generation=other_args.train_with_generation, + max_seq_length=128) # 可以对应数据包数量 + + # 将所有的参数整合到一个字典中 + param_dict = {} + for k, v in vars(training_args).items(): + param_dict[k] = v + for k, v in vars(data_args).items(): + param_dict[k] = v + for k, v in vars(model_args).items(): + param_dict[k] = v + for k, v in vars(other_args).items(): + param_dict[k] = v + + + # 使用fitlog库记录超参数 + fitlog.add_hyper(param_dict)""" + fitlog.add_hyper_in_file(__file__) + + try: + + qs = [None] + if do_train: + config = AutoConfig.from_pretrained( + model_name_or_path, + num_labels=num_labels, + # finetuning_task=task_name, + cache_dir=None, + revision=None, + use_auth_token=None, + ) + config.use_cache = True + + model = BartForERC.from_pretrained( # 情感识别模型 + model_name_or_path, + from_tf=bool(".ckpt" in model_name_or_path), + config=config, + cache_dir=None, + revision=None, + use_auth_token=None, + temperature=temperature, + alpha=alpha, + beta=beta, + use_trans_layer=use_trans_layer + ) + # print(model) + model = model.to(device) + + # train(train_dataloader, eval_dataloader, test_dataloader, model, training_args, other_args) + + fitlog.finish() + + except KeyboardInterrupt: + print("Catch keyboard interrupt.") + + # 保存最佳模型 + if do_train: + best_model_path = os.path.join(model_output_dir, "best_model_%d" % rnd_seed) + else: + best_model_path = model_name_or_path + +""" + if do_eval or do_predict: + config = AutoConfig.from_pretrained(best_model_path) + + model = BartForERC.from_pretrained( + best_model_path, + from_tf=bool(".ckpt" in model_name_or_path), + config=config, + temperature=temperature, + alpha=alpha, + beta=beta, + use_trans_layer=use_trans_layer + ) + model = model.to(device) + + if do_eval: + results = evaluate(training_args, other_args, eval_dataloader, model, "evaluate") + print(results) + + if do_predict: + results = evaluate(training_args, other_args, test_dataloader, model, "predict") + print(results) +""" diff --git a/LYZ/model/loggingHandler.py b/LYZ/model/loggingHandler.py new file mode 100644 index 0000000..b515cbf --- /dev/null +++ b/LYZ/model/loggingHandler.py @@ -0,0 +1,22 @@ +# For longer texts or text not related to a specific progress bar +# tqdm offers write() which logs text safely to the console. To be +# precise, it adds the text above the progress bars, so each line +# you ever logged using write() will be visible. + +import logging +import tqdm + + +class LoggingHandler(logging.Handler): + # default: logging.info + def __init__(self, level=logging.NOTSET): + super().__init__(level) + + def emit(self, record): + # must be implemented in the logginghandler subclass + try: + msg = self.format(record) + tqdm.tqdm.write(msg) + self.flush() + except (KeyboardInterrupt, SystemExit): + self.handleError(record) diff --git a/LYZ/model/model.py b/LYZ/model/model.py new file mode 100644 index 0000000..999c118 --- /dev/null +++ b/LYZ/model/model.py @@ -0,0 +1,80 @@ +""" +Bart网络 + +""" +import torch +import torch.nn as nn +import torch.nn.functional as F +from transformers import BartPretrainedModel, BartConfig + + +class SubNet(nn.Module): + def __init__( + self, + block, + layers, + in_channel=3, + zero_init_residual=False, + groups=1, + width_per_group=64, + replace_stride_with_dilation=None, + norm_layer=None, + ): + super(SubNet, self).__init__() + + def _forward_impl(self, x): + # See note [TorchScript super()] + # with torch.no_grad(): + x = self.conv1(x) + x = self.bn1(x) + x = self.relu(x) + x = self.maxpool(x) + + x = self.layer1(x) + x = self.layer2(x) + x = self.layer3(x) + x = self.layer4(x) + + x = self.avgpool(x) + x = torch.flatten(x, 1) + x = self.fc(x) + + return x + + def forward(self, x): + return self._forward_impl(x) + + +class Network(nn.Module): + def __init__(self, subnet, hidden_dim, feature_dim, class_num): + super(Network, self).__init__() + self.subnet = subnet + self.feature_dim = feature_dim + self.cluster_num = class_num + self.instance_projector = nn.Sequential( + nn.BatchNorm1d(hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, hidden_dim), + nn.BatchNorm1d(hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, self.feature_dim), + ) + self.cluster_projector = nn.Sequential( + nn.BatchNorm1d(hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, hidden_dim), + nn.BatchNorm1d(hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, self.cluster_num), + ) + + def forward(self, x_i, x_j, return_ci=True): + pass + + + def forward_zc(self, x): + h = self.subnet(x) + z = F.normalize(self.instance_projector(h), dim=1) + c = self.cluster_projector(h) + c = F.softmax(c, dim=1) + return z, c diff --git a/LYZ/test.py b/LYZ/test.py new file mode 100644 index 0000000..438a1e3 --- /dev/null +++ b/LYZ/test.py @@ -0,0 +1,222 @@ +# 打印网络测试而已 +import torch +import torch.nn as nn +from torch.nn.functional import normalize + + +class OneHotEncodingLayer(nn.Module): + def __init__(self, sz=256): + super(OneHotEncodingLayer, self).__init__() + self.size = sz + + def forward(self, x): + return torch.nn.functional.one_hot(x, num_classes=self.size).float() + + +class ByteBlock(nn.Module): + def __init__(self, in_channels, nb_filter=(64, 100), filter_length=(3, 3), + subsample=(2, 1), pool_length=(2, 2)): + super(ByteBlock, self).__init__() + + layers = [] + for i in range(len(nb_filter)): + layers.append(nn.Conv1d(in_channels, nb_filter[i], kernel_size=filter_length[i], + padding=0, stride=subsample[i])) + layers.append(nn.Tanh()) + if pool_length[i]: + layers.append(nn.MaxPool1d(pool_length[i])) + in_channels = nb_filter[i] + + self.block = nn.Sequential(*layers) + self.global_pool = nn.AdaptiveMaxPool1d(1) + self.fc = nn.Linear(nb_filter[-1], 128) + + def forward(self, x): + x = self.block(x) + x = self.global_pool(x).squeeze(dim=2) + x = torch.nn.functional.relu(self.fc(x)) + return x + + + +class FEMnet(nn.Module): + """ + Feature extraction module 定义 + """ + def __init__(self, flow_len, packet_len, gru_units): + super(FEMnet, self).__init__() + self.packet_len = packet_len + self.flow_len = flow_len + self.batch_size = 10 + self.gru_hidden_size = gru_units + self.rep_dim = gru_units + + self.embedding = OneHotEncodingLayer(sz=256) # 独热编码 + self.block2 = ByteBlock(self.packet_len, (128, 256), (5, 5), (1, 1), (2, 2)) + self.block3 = ByteBlock(self.packet_len, (192, 320), (7, 5), (1, 1), (2, 2)) + + self.lstm_layer = nn.GRU(256, self.gru_hidden_size, dropout=0.1, bidirectional=True) + # self.dense_layer = nn.Linear(self.gru_hidden_size * 2, 5) + # self.output = nn.Softmax(dim=1) # Linear 自带Softmax 分类 + + def forward(self, x): # x: [batch_size, flow_len, packet_len] = [10, 14, 100] + embeddings_list = self.embedding(x) # [10, 14, 100, 256] + encoder_list = torch.zeros((self.batch_size, self.flow_len, 256)) + for ix, embeddings in enumerate(embeddings_list): # [14, 100, 256] + # print("embeddings 1: ", embeddings.shape) + # embeddings = embeddings.permute(0, 2, 1) + # print("embeddings 2: ", embeddings.shape) + encoder1 = self.block2(embeddings) # [14, 128] + # print("encoder 1: ", encoder1.shape) + encoder2 = self.block3(embeddings) # [14, 128] + # print("encoder 2: ", encoder2.shape) + encoder = torch.cat([encoder1, encoder2], 1) # [14, 256] + # print("encoder : ", encoder.shape) + encoder_list[ix] = encoder + + # rnn 网络输入:[seq_len, batch_size, hidden_size] + encoder_list = encoder_list.permute(1, 0, 2) # [10, 14, 256] -> [14, 10 ,256] + biLSTM, final_hidden_state = self.lstm_layer(encoder_list) # [14, 10, 184], [2, 10, 92] + biLSTM = biLSTM.permute(1, 0, 2) # [10, 14, 184] + # print("biLSTM: ", biLSTM.shape) + attn_output, attention = self.attention_net(biLSTM, final_hidden_state) + dense = self.dense_layer(attn_output) + # out = self.output(dense) + # out = dense[:, -1, :] + return dense + + # lstm_output : [batch_size, n_step, self.byte_hidden_size * num_directions(=2)], F matrix + def attention_net(self, lstm_output, final_state): + # print("lstm_output: ", lstm_output.shape) + # print("final_state: ", final_state.shape) + # hidden : [batch_size, self.byte_hidden_size * num_directions(=2), 1(=n_layer)] + hidden = final_state.view(-1, self.gru_hidden_size * 2, 1) # Tensor维度的重构,-1表示该维度取决于其他维度 + # attn_weights : [batch_size, n_step] + attn_weights = torch.bmm(lstm_output, hidden).squeeze(2) # 加权求和,第三维降维 + soft_attn_weights = torch.nn.functional.softmax(attn_weights, 1) + # [batch_size, self.byte_hidden_size * num_directions(=2), n_step] * [batch_size, n_step, 1] + # = [batch_size, self.byte_hidden_size * num_directions(=2), 1] + context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2) + return context, soft_attn_weights # context : [batch_size, self.byte_hidden_size * num_directions(=2)] + + +class MyModel(nn.Module): + """ + Feature extraction module定义 + """ + def __init__(self, binet, feature_dim, class_n): + super(MyModel, self).__init__() + self.binet = binet + self.feature_dim = feature_dim + self.cluster_num = class_n + """ 对比聚类 """ + self.instance_projector = nn.Sequential( # 实例-单例 + nn.Linear(self.binet.rep_dim, self.binet.rep_dim), + nn.ReLU(), + nn.Linear(self.binet.rep_dim, self.feature_dim), + ) + self.cluster_projector = nn.Sequential( # 聚类-集群 + nn.Linear(self.binet.rep_dim, self.binet.rep_dim), + nn.ReLU(), + nn.Linear(self.binet.rep_dim, self.cluster_num), + nn.Softmax(dim=1) + ) + + # 训练时执行 + def forward(self, x_i, x_j): # x_i, x_j 来自同一数据的两种不同预处理方式得到的嵌入矩阵 + h_i = self.resnet(x_i) + h_j = self.resnet(x_j) + + z_i = normalize(self.instance_projector(h_i), dim=1) + z_j = normalize(self.instance_projector(h_j), dim=1) + + c_i = self.cluster_projector(h_i) + c_j = self.cluster_projector(h_j) + + return z_i, z_j, c_i, c_j + + # 测试时执行 + def forward_cluster(self, x): + h = self.resnet(x) + c = self.cluster_projector(h) # 聚类分布 + c = torch.argmax(c, dim=1) # 得到每个样本的聚类标签。 + return c + + +class MyModel1(nn.Module): + """ + 模型定义 + """ + def __init__(self, flow_len, packet_len, gru_units): + super(MyModel1, self).__init__() + self.packet_len = packet_len + self.flow_len = flow_len + self.batch_size = 10 + self.gru_hidden_size = gru_units + + self.embedding = OneHotEncodingLayer(sz=256) # 独热编码 + self.block2 = ByteBlock(self.packet_len, (128, 256), (5, 5), (1, 1), (2, 2)) + self.block3 = ByteBlock(self.packet_len, (192, 320), (7, 5), (1, 1), (2, 2)) + + self.lstm_layer = nn.GRU(256, self.gru_hidden_size, dropout=0.1, bidirectional=True) + self.dense_layer = nn.Linear(self.gru_hidden_size * 2, 5) # # 其实像特征聚类,输出聚类数 + # self.output = nn.Softmax(dim=1) + + def forward(self, x): # x: [batch_size, flow_len, packet_len] = [10, 14, 100] + embeddings_list = self.embedding(x) # [10, 14, 100, 256] + encoder_list = torch.zeros((self.batch_size, self.flow_len, 256)) + for ix, embeddings in enumerate(embeddings_list): # [14, 100, 256] + # print("embeddings 1: ", embeddings.shape) + # embeddings = embeddings.permute(0, 2, 1) + # print("embeddings 2: ", embeddings.shape) + encoder1 = self.block2(embeddings) # [14, 128] + # print("encoder 1: ", encoder1.shape) + encoder2 = self.block3(embeddings) # [14, 128] + # print("encoder 2: ", encoder2.shape) + encoder = torch.cat([encoder1, encoder2], 1) # [14, 256] + # print("encoder : ", encoder.shape) + encoder_list[ix] = encoder + + # rnn 网络输入:[seq_len, batch_size, hidden_size] + encoder_list = encoder_list.permute(1, 0, 2) # [10, 14, 256] -> [14, 10 ,256] + biLSTM, final_hidden_state = self.lstm_layer(encoder_list) # [14, 10, 184], [2, 10, 92] + biLSTM = biLSTM.permute(1, 0, 2) # [10, 14, 184] + # print("biLSTM: ", biLSTM.shape) + attn_output, attention = self.attention_net(biLSTM, final_hidden_state) + dense = self.dense_layer(attn_output) + # out = self.output(dense) + # out = dense[:, -1, :] + return dense + + # lstm_output : [batch_size, n_step, self.byte_hidden_size * num_directions(=2)], F matrix + def attention_net(self, lstm_output, final_state): + # print("lstm_output: ", lstm_output.shape) + # print("final_state: ", final_state.shape) + # hidden : [batch_size, self.byte_hidden_size * num_directions(=2), 1(=n_layer)] + hidden = final_state.view(-1, self.gru_hidden_size * 2, 1) # Tensor维度的重构,-1表示该维度取决于其他维度 + # attn_weights : [batch_size, n_step] + attn_weights = torch.bmm(lstm_output, hidden).squeeze(2) # 加权求和,第三维降维 + soft_attn_weights = torch.nn.functional.softmax(attn_weights, 1) + # [batch_size, self.byte_hidden_size * num_directions(=2), n_step] * [batch_size, n_step, 1] + # = [batch_size, self.byte_hidden_size * num_directions(=2), 1] + context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2) + return context, soft_attn_weights # context : [batch_size, self.byte_hidden_size * num_directions(=2)] + +if __name__ == '__main__': + #fe_model = FEMnet(14, 100, 92) + #model = MyModel(fe_model, 128, 5) + # print(model) + + model = MyModel1(14, 100, 92) + data = torch.randint(255, size=(10, 14, 100)) # batch_size, flow_len, packet_len + model(data) + +""" + params = list(model.parameters()) + print(len(params)) + print(params[0].size()) # (0): conv1's .weight + + +""" + + diff --git a/LYZ/train.py b/LYZ/train.py new file mode 100644 index 0000000..725dfb9 --- /dev/null +++ b/LYZ/train.py @@ -0,0 +1,89 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F +import os +import argparse +import numpy as np + +from torch.utils.tensorboard import SummaryWriter +from torchvision.utils import make_grid +from torch.optim import lr_scheduler + +from model import * +from loss import * +from dataloader import * + + +def get_opt(): + parser = argparse.ArgumentParser() + parser.add_argument('-n', '--num-workers', type=int, default=4) + parser.add_argument('-e', '--epoch', type=int, default=10) + parser.add_argument('-b', '--batch-size', type=int, default=128) + parser.add_argument('-t', '--test-batch-size', type=int, default=1) + parser.add_argument('-d', '--display-step', type=int, default=600) + opt = parser.parse_args() + return opt + + +def train(opt): + model = PLA_Attention_Model(100, 100, 50).cuda() + # model.load_state_dict(torch.load('checkpoint.pt')) + model.train() + + train_dataset = NetworkFlowDataset('Thursday-WorkingHours.pcap', + 'Thursday-WorkingHours-Morning-WebAttacks.pcap_ISCX.csv') + train_data_loader = NetworkFlowDataloader(opt, train_dataset) + + test_dataset = NetworkFlowDataset('Friday-WorkingHours.pcap', 'Friday-WorkingHours-Morning.pcap_ISCX.csv') + test_data_loader = NetworkFlowDataloader(opt, test_dataset) + + optim = torch.optim.Adam(model.parameters(), lr=0.001) + + criterion = Loss() + + writer = SummaryWriter() + + for epoch in range(opt.epoch): + for i in range(len(train_data_loader.data_loader)): + step = epoch * len(train_data_loader.data_loader) + i + 1 + + # load data + flow, label = train_data_loader.next_batch() + flow = flow.cuda() + label = label.cuda() + + # train model + optim.zero_grad() # 梯度清零,不加则会累加梯度 + result = model(flow) + loss = criterion(result, label) + loss.backward() + optim.step() + + writer.add_scalar('loss', loss, step) + + writer.close() + + if step % opt.display_step == 0: + _, predicted = torch.max(result, 1) + total = label.size(0) + correct = (predicted == label).sum().item() + total_test = 0 + correct_test = 0 + for i in range(len(test_data_loader.data_loader)): + flow, label = test_data_loader.next_batch() + flow = flow.cuda() + label = label.cuda() + result = model(flow) + _, predicted = torch.max(result, 1) + total_test += label.size(0) + correct_test += (predicted == label).sum().item() + print( + '[Epoch {}] Loss : {:.2}, train_acc : {:.2}, test_acc : {:.2}'.format(epoch, loss, correct / total, + correct_test / total_test)) + + torch.save(model.state_dict(), 'checkpoint.pt') + + +if __name__ == '__main__': + opt = get_opt() + train(opt)