├── __pycache__ ├── cnn.cpython-37.pyc ├── qcnn.cpython-36.pyc ├── qcnn.cpython-37.pyc ├── base_model.cpython-36.pyc ├── base_model.cpython-37.pyc └── base_model.cpython-38.pyc ├── README.md ├── bp.py ├── cnn.py ├── qnn.py ├── prehandle.py ├── base_model.py ├── LICENSE ├── mainwindow.ui ├── main.py ├── qcnn.py └── newMainWindow.ui /__pycache__/cnn.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyu2018/QuantumCnn-NetworkAttackDetection/HEAD/__pycache__/cnn.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/qcnn.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyu2018/QuantumCnn-NetworkAttackDetection/HEAD/__pycache__/qcnn.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/qcnn.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyu2018/QuantumCnn-NetworkAttackDetection/HEAD/__pycache__/qcnn.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/base_model.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyu2018/QuantumCnn-NetworkAttackDetection/HEAD/__pycache__/base_model.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/base_model.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyu2018/QuantumCnn-NetworkAttackDetection/HEAD/__pycache__/base_model.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/base_model.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyu2018/QuantumCnn-NetworkAttackDetection/HEAD/__pycache__/base_model.cpython-38.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuantumCnn--NetworkAttackDetection 2 | 基于谷歌提供的样例量子卷积神经网络模型,训练KDD99数据集实现了网络攻击分类检测。 3 | 4 | 0 必要python包:tensorflow-2.1.0、tensorflow_quantum、sklearn、matplotlib、cirq、sympy、numpy、PyQt5 5 | 6 | 1 qcnn.py包含了量子门组神经网络与量子卷积神经网络的具体实现 7 | 8 | 2 dataset文件夹存放初步处理完毕的数据 9 | 10 | 3 mymodels文件夹存放参数及训练过程图 11 | 12 | 4 `python main.py` 运行程序 13 | 14 | -------------------------------------------------------------------------------- /bp.py: -------------------------------------------------------------------------------- 1 | from base_model import BaseModel 2 | from tensorflow_core import keras 3 | from datetime import datetime 4 | 5 | # import os 6 | # os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" 7 | # os.environ["CUDA_VISIBLE_DEVICES"] = "-1" 8 | 9 | class MyBPModel(BaseModel): 10 | def __init__(self): 11 | BaseModel.__init__(self) 12 | self.model_name = "BP" 13 | 14 | def Train(self): 15 | start_time = datetime.now() 16 | 17 | 18 | 19 | self.model = keras.Sequential() 20 | 21 | # 展平一个张量,返回一个调整为1D的张量 22 | self.model.add(keras.layers.Flatten( 23 | input_shape=self.input_shape, name="flatten_layer")) 24 | 25 | #防止过拟合 26 | #model.add(Dropout(0.25)) #需要丢弃的输入比例=0.25 dropout正则化-减少过拟合 27 | self.model.add( 28 | keras.layers.Dense(64, activation='relu',name="hidden_layer")) 29 | self.model.add(keras.layers.Dense( 30 | self.num_classes, activation='softmax', name='softmax_layer')) 31 | 32 | self.model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=False), 33 | optimizer=keras.optimizers.Adam(), metrics=['sparse_categorical_accuracy']) 34 | 35 | self.history = self.model.fit(self.train_data, self.train_label, batch_size=self.batch_size, 36 | epochs=self.epochs, verbose=1, validation_data=(self.val_data, self.val_label)) 37 | 38 | end_time = datetime.now() 39 | self.train_time = (end_time-start_time).seconds 40 | 41 | #保存 42 | self.train_accuracy = self.history.history['sparse_categorical_accuracy'][self.epochs-1] 43 | self.val_accuracy = self.history.history['val_sparse_categorical_accuracy'][self.epochs-1] 44 | self.train_loss = self.history.history['loss'][self.epochs-1] 45 | self.val_loss = self.history.history['val_loss'][self.epochs-1] 46 | 47 | if(self.is_save_model): 48 | self.model.save(".//mymodles//Bp_model_"+str(self.data_mode)+".h5") 49 | 50 | 51 | if __name__ == "__main__": 52 | mymodel = MyBPModel() 53 | mymodel.data_mode=2 54 | mymodel.epochs=50 55 | mymodel.batch_size=128 56 | mymodel.is_save_model=False 57 | 58 | mymodel.LoadData() 59 | mymodel.Train() 60 | print(mymodel.train_time) 61 | print(mymodel.train_accuracy) 62 | # mymodel.SaveTrainProcess() 63 | # mymodel.LoadModle(f'.//mymodles//Bp_model_{mymodel.data_mode}.h5') 64 | 65 | mymodel.Evaluate() 66 | # mymodel.model.summary() 67 | # mymodel.RandomTest() 68 | -------------------------------------------------------------------------------- /cnn.py: -------------------------------------------------------------------------------- 1 | from base_model import BaseModel 2 | from tensorflow_core import keras 3 | from datetime import datetime 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | class MyCnnModel(BaseModel): 12 | def __init__(self) : 13 | BaseModel.__init__(self) 14 | self.model_name="CNN" 15 | 16 | def Train(self): 17 | start_time=datetime.now() 18 | 19 | 20 | #将标签转换为独热编码 21 | # self.train_label=keras.utils.to_categorical(self.train_label) 22 | # self.test_label=keras.utils.to_categorical(self.test_label) 23 | 24 | 25 | self.model = keras.Sequential() # sequential序贯模型:多个网络层的线性堆叠 26 | #输出的维度(卷积滤波器的数量)filters=32;1D卷积窗口的长度kernel_size=3;激活函数activation 模型第一层需指定input_shape: 27 | # data_format默认channels_last(39,1) 28 | self.model.add(keras.layers.Conv1D( 29 | 32, 3, activation='relu', input_shape=self.input_shape, name='convolution_layer')) 30 | # 池化层:最大池化 池化窗口大小pool_size=2 31 | self.model.add(keras.layers.MaxPooling1D( 32 | pool_size=(2), name='pooling_layer')) 33 | self.model.add(keras.layers.Flatten( 34 | name='flatten_layer')) # 展平一个张量,返回一个调整为1D的张量 35 | 36 | # 防止过拟合 37 | # 需要丢弃的输入比例=0.25 dropout正则化-减少过拟合 38 | # self.model.add(keras.layers.Dropout(0.25)) 39 | 40 | self.model.add(keras.layers.Dense(64, activation='relu', 41 | name='hidden_layer')) # 全连接层 42 | # 需要丢弃的输入比例=0.25 dropout正则化-减少过拟合 43 | # self.model.add(keras.layers.Dropout(0.15)) 44 | self.model.add(keras.layers.Dense( 45 | self.num_classes, activation='softmax', name='softmax_layer')) 46 | 47 | #编译,损失函数:多类对数损失,用于多分类问题, 优化函数:adadelta, 模型性能评估是准确率 48 | #输入特征经softmax层转换为概率分布,from_logits=False 49 | #label未转换为独热码,特征为概率分布,metrics用sparse_categorical_accuracy 50 | self.model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=False), 51 | optimizer=keras.optimizers.Adam(), metrics=['sparse_categorical_accuracy']) 52 | #运行 , verbose=1输出进度条记录 epochs训练的轮数 batch_size:指定进行梯度下降时每个batch包含的样本数 53 | self.history = self.model.fit(self.train_data, self.train_label, batch_size=self.batch_size, 54 | epochs=self.epochs, verbose=1, validation_data=(self.val_data,self.val_label)) 55 | end_time=datetime.now() 56 | self.train_time=(end_time-start_time).seconds 57 | 58 | #保存 59 | self.train_accuracy = self.history.history['sparse_categorical_accuracy'][self.epochs-1] 60 | self.val_accuracy = self.history.history['val_sparse_categorical_accuracy'][self.epochs-1] 61 | self.train_loss = self.history.history['loss'][self.epochs-1] 62 | self.val_loss = self.history.history['val_loss'][self.epochs-1] 63 | 64 | if(self.is_save_model): 65 | self.model.save(".//mymodles//Cnn_model_"+str(self.data_mode)+".h5") 66 | 67 | if __name__ == "__main__": 68 | mymodel=MyCnnModel() 69 | 70 | mymodel.data_mode = 2 71 | mymodel.epochs = 50 72 | mymodel.batch_size = 64 73 | mymodel.is_save_model = False 74 | 75 | mymodel.LoadData() 76 | mymodel.Train() 77 | print(mymodel.train_time) 78 | print(mymodel.train_accuracy) 79 | # mymodel.SaveTrainProcess() 80 | # mymodel.LoadModle(f'.//mymodles//Cnn_model_{mymodel.data_mode}.h5') 81 | 82 | mymodel.Evaluate() 83 | # mymodel.model.summary() 84 | mymodel.RandomTest() 85 | 86 | 87 | -------------------------------------------------------------------------------- /qnn.py: -------------------------------------------------------------------------------- 1 | from sklearn import preprocessing 2 | from cirq.contrib.svg import SVGCircuit 3 | import matplotlib.pyplot as plt 4 | import tensorflow as tf 5 | import tensorflow_quantum as tfq 6 | 7 | import cirq 8 | import sympy 9 | import numpy as np 10 | import math 11 | 12 | #数据载入 13 | def thetas_append(bits, datas_minmax): 14 | circuit = cirq.Circuit() 15 | circuit += [cirq.rz(datas_minmax[0])(bits[0])] # -2 * math.pi * 16 | circuit += [cirq.rz(datas_minmax[1])(bits[1])] 17 | circuit += [cirq.rz(datas_minmax[2])(bits[2])] 18 | circuit += [cirq.rz(datas_minmax[3])(bits[3])] 19 | circuit += [cirq.rz(datas_minmax[4])(bits[4])] 20 | circuit += [cirq.rz(datas_minmax[5])(bits[5])] 21 | return circuit 22 | 23 | 24 | def datasets(bits): 25 | dataTotal = np.genfromtxt( 26 | ".//dataset//1back_ipsweep_normal_3000 -6 _1.csv", delimiter=",") 27 | datas = dataTotal[:, 0:6] 28 | labels = dataTotal[:, -1] 29 | datas_minmax = preprocessing.MinMaxScaler().fit_transform(datas) 30 | thetas = [] 31 | n_data = len(labels) 32 | for n in range(n_data): 33 | thetas.append(thetas_append(bits, datas_minmax[n])) 34 | permutation = np.random.permutation(range(n_data)) 35 | 36 | split_ind = int(n_data * 0.7) 37 | 38 | train_datas = thetas[:split_ind] 39 | test_datas = thetas[split_ind:] 40 | 41 | train_labels = labels[:split_ind] 42 | test_labels = labels[split_ind:] 43 | 44 | return tfq.convert_to_tensor(train_datas), np.array(train_labels), \ 45 | tfq.convert_to_tensor(test_datas), np.array(test_labels) 46 | 47 | 48 | 49 | # 1. 量子态编码线路(QSEC) 50 | def quantum_state_encoding_circuit(bits): 51 | """根据`bits`构建并返回量子态编码线路.""" 52 | circuit = cirq.Circuit() 53 | circuit.append(cirq.H.on_each(bits)) 54 | return circuit 55 | 56 | 57 | # 2. 变分量子线路(VQC) 58 | # 单条R门变分量子线路 59 | def one_qubit_unitary(bit, symbols): 60 | return cirq.Circuit( 61 | cirq.Y(bit)**symbols[0], 62 | cirq.Z(bit)**symbols[1]) 63 | 64 | 65 | # R门变分量子线路 66 | def variational_quantum_circuit_R(bits, symbols): 67 | circuit = cirq.Circuit() 68 | circuit += one_qubit_unitary(bits[0], symbols[0:2]) 69 | circuit += one_qubit_unitary(bits[1], symbols[2:4]) 70 | circuit += one_qubit_unitary(bits[2], symbols[4:6]) 71 | circuit += one_qubit_unitary(bits[3], symbols[6:8]) 72 | circuit += one_qubit_unitary(bits[4], symbols[8:10]) 73 | circuit += one_qubit_unitary(bits[5], symbols[10:12]) 74 | return circuit 75 | 76 | # CZ门变分量子线路 77 | def variational_quantum_circuit_CZ(bits): 78 | circuit = cirq.Circuit() 79 | for this_bit, next_bit in zip(bits, bits[1:] + [bits[0]]): 80 | circuit.append(cirq.CZ(this_bit, next_bit)) 81 | return circuit 82 | 83 | 84 | # 变分量子线路 85 | def variational_quantum_circuit(bits, symbols): 86 | circuit = cirq.Circuit() 87 | circuit += variational_quantum_circuit_R(bits, symbols[0:12]) 88 | circuit += variational_quantum_circuit_CZ(bits) 89 | circuit += variational_quantum_circuit_R(bits, symbols[12:24]) 90 | circuit += variational_quantum_circuit_CZ(bits) 91 | circuit += variational_quantum_circuit_R(bits, symbols[24:36]) 92 | circuit += variational_quantum_circuit_CZ(bits) 93 | circuit += variational_quantum_circuit_R(bits, symbols[36:48]) 94 | circuit += variational_quantum_circuit_CZ(bits) 95 | circuit += variational_quantum_circuit_R(bits, symbols[48:60]) 96 | circuit += variational_quantum_circuit_CZ(bits) 97 | circuit += variational_quantum_circuit_R(bits, symbols[60:72]) 98 | 99 | return circuit 100 | 101 | 102 | # 3. 模型构建 103 | 104 | # 创建自定义层 105 | def create_model_circuit(qubits): 106 | model_circuit = cirq.Circuit() 107 | symbols = sympy.symbols('w0:72') 108 | # Cirq通过sympy.Symbols将符号映射为待学习变量 109 | # TensorFlow Quantum扫描电路的输入并将其替换为TensorFlow变量 110 | model_circuit += variational_quantum_circuit(qubits, symbols[0:72]) 111 | 112 | return model_circuit 113 | 114 | 115 | # 在Cirq中创建qubits以及测量操作 116 | establish_qbits = cirq.GridQubit.rect(1, 6) 117 | readout_operators0 = cirq.Z(establish_qbits[0]) 118 | readout_operators1 = cirq.Z(establish_qbits[1]) 119 | readout_operators2 = cirq.Z(establish_qbits[2]) 120 | readout_operators3 = cirq.Z(establish_qbits[3]) 121 | readout_operators4 = cirq.Z(establish_qbits[4]) 122 | readout_operators5 = cirq.Z(establish_qbits[5]) 123 | 124 | 125 | # 将经典数据输入QSEC并作为AddCircuit的一部分 126 | datas_input = tf.keras.Input(shape=(), dtype=tf.dtypes.string) 127 | datas_state = tfq.layers.AddCircuit()( 128 | datas_input, prepend=quantum_state_encoding_circuit(establish_qbits)) 129 | 130 | quantum_model = tfq.layers.PQC(create_model_circuit( 131 | establish_qbits), readout_operators0)(datas_state) 132 | 133 | #quantum_model = tfq.layers.PQC(create_model_circuit(establish_qbits),[readout_operators0, readout_operators1, readout_operators2, readout_operators3])(datas_state) 134 | 135 | vqnn_model = tf.keras.Model(inputs=[datas_input], outputs=[quantum_model]) 136 | 137 | 138 | # 4训练模型 139 | # 获取训练集与测试集 140 | train_datas, train_labels, test_datas, \ 141 | test_labels = datasets(establish_qbits) 142 | 143 | # 参数设置 144 | @tf.function 145 | def custom_accuracy(y_true, y_pred): 146 | y_true = tf.squeeze(y_true) 147 | y_pred = tf.map_fn(lambda x: 1.0 if x >= 0.5 else 0.0, y_pred) 148 | return tf.keras.backend.mean(tf.keras.backend.equal(y_true, y_pred)) 149 | 150 | 151 | vqnn_model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.01), 152 | loss=tf.losses.mse, 153 | metrics=[custom_accuracy]) 154 | 155 | history = vqnn_model.fit(x=train_datas, 156 | y=train_labels, 157 | #batch_size=140, 158 | epochs=20, 159 | verbose=1, 160 | validation_data=(test_datas, test_labels)) 161 | 162 | -------------------------------------------------------------------------------- /prehandle.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | 3 | #KDD99数据集预处理 4 | #共使用39个特征,去除了原数据集中20、21号特征 5 | 6 | import numpy as np 7 | import pandas as pd 8 | import csv 9 | from datetime import datetime 10 | from sklearn import preprocessing # 数据标准化处理 11 | 12 | 13 | 14 | #定义KDD99字符型特征转数值型特征函数 15 | def char2num(sourceFile, handledFile): 16 | print('START: 字符型特征转数值型特征函数中') 17 | data_file=open(handledFile,'w',newline='') #python3.x中添加newline=''这一参数使写入的文件没有多余的空行 18 | global dataCnt 19 | with open(sourceFile, 'r') as data_source: 20 | csv_reader=csv.reader(data_source) 21 | csv_writer=csv.writer(data_file) 22 | dataCnt=0 #记录数据的行数,初始化为0 23 | for row in csv_reader: 24 | temp_line=np.array(row) #将每行数据存入temp_line数组里 25 | temp_line[1]=handleProtocol(row) #将源文件行中3种协议类型转换成数字标识 26 | temp_line[2]=handleService(row) #将源文件行中70种网络服务类型转换成数字标识 27 | temp_line[3]=handleFlag(row) #将源文件行中11种网络连接状态转换成数字标识 28 | temp_line[41]=handleLabel(row) #将源文件行中23种攻击类型转换成数字标识 29 | csv_writer.writerow(temp_line) 30 | dataCnt+=1 31 | #输出每行数据中所修改后的状态 32 | data_file.close() 33 | print('FINISH: 字符型特征转数值型特征函数完成\n') 34 | 35 | #将相应的非数字类型转换为数字标识即符号型数据转化为数值型数据 36 | def find_index(x,y): 37 | return [i for i in range(len(y)) if y[i]==x] 38 | 39 | #定义将源文件行中3种协议类型转换成数字标识的函数 40 | def handleProtocol(input): 41 | protocol_list=['tcp','udp','icmp'] 42 | if input[1] in protocol_list: 43 | return find_index(input[1],protocol_list)[0] 44 | 45 | #定义将源文件行中70种网络服务类型转换成数字标识的函数 46 | def handleService(input): 47 | service_list=['aol','auth','bgp','courier','csnet_ns','ctf','daytime','discard','domain','domain_u', 48 | 'echo','eco_i','ecr_i','efs','exec','finger','ftp','ftp_data','gopher','harvest','hostnames', 49 | 'http','http_2784','http_443','http_8001','imap4','IRC','iso_tsap','klogin','kshell','ldap', 50 | 'link','login','mtp','name','netbios_dgm','netbios_ns','netbios_ssn','netstat','nnsp','nntp', 51 | 'ntp_u','other','pm_dump','pop_2','pop_3','printer','private','red_i','remote_job','rje','shell', 52 | 'smtp','sql_net','ssh','sunrpc','supdup','systat','telnet','tftp_u','tim_i','time','urh_i','urp_i', 53 | 'uucp','uucp_path','vmnet','whois','X11','Z39_50'] 54 | if input[2] in service_list: 55 | return find_index(input[2],service_list)[0] 56 | 57 | #定义将源文件行中11种网络连接状态转换成数字标识的函数 58 | def handleFlag(input): 59 | flag_list=['OTH','REJ','RSTO','RSTOS0','RSTR','S0','S1','S2','S3','SF','SH'] 60 | if input[3] in flag_list: 61 | return find_index(input[3],flag_list)[0] 62 | 63 | #定义将源文件行中攻击类型转换成数字标识的函数(共出现了22个攻击类型+1个未受到攻击) 64 | def handleLabel(input): 65 | global label_list 66 | label_list = ['normal.', # normal 67 | 'back.', 'land.', 'neptune.', 'pod.', 'smurf.', 'teardrop.', # DOS 68 | 'ipsweep.', 'nmap.', 'portsweep.', 'satan.', # PROBE 69 | 'ftp_write.', 'guess_passwd.', 'imap.', 'multihop.', 'phf.', 'spy.', 'warezclient.', 'warezmaster.', # R2L 70 | 'buffer_overflow.', 'loadmodule.', 'perl.', 'rootkit.'] # U2R 71 | 72 | if input[41] in label_list: 73 | return find_index(input[41], label_list)[0] 74 | else: 75 | label_list.append(input[41]) 76 | return find_index(input[41], label_list)[0] 77 | 78 | def standardize(inputFile): 79 | import warnings 80 | # 忽略UserWarning: Numerical issues were encountered when centering the data and might not be solved. Dataset may contain too large values. You may need to prescale your features. 81 | # warnings.warn("Numerical issues were encountered " 82 | warnings.filterwarnings("ignore", message="Numerical issues were encountered ") 83 | print('START: 数据标准化中') 84 | dataMatrix = np.loadtxt(open(inputFile,"rb"),delimiter=",",skiprows=0) # 读入数据 85 | labelColumn = dataMatrix[:,-1] 86 | result = preprocessing.scale(dataMatrix[:,:-1]) # 标签列不参与训练 87 | print('FINISH: 数据标准化完成\n') 88 | return result, labelColumn 89 | 90 | def normalize(inMatrix): 91 | print('START: 数据归一化中') 92 | np.seterr(divide='ignore',invalid='ignore') # 忽略0/0的报错 93 | minVals = inMatrix.min(0) 94 | maxVals = inMatrix.max(0) 95 | ranges = maxVals - minVals 96 | # normData = np.zeros(np.shape(inMatrix)) 97 | m = inMatrix.shape[0] 98 | normData = inMatrix - np.tile(minVals, (m, 1)) 99 | normData = normData/np.tile(ranges, (m, 1)) 100 | # 去掉数据中的空列 101 | print('FINISH: 数据归一化完成\n') 102 | return normData, ranges, minVals 103 | 104 | 105 | 106 | 107 | def exportData(npData, outputFile): 108 | 109 | 110 | 111 | pd_data = pd.DataFrame(npData, columns=['duration', 'protocol_type', 'service', 'flag', 'src_bytes', 'dst_bytes', 'land', 'wrong_fragment', 112 | 'urgent', 'hot', 'num_failed_logins', 'logged_in', 'num_compromised', 'root_shell', 'su_attempted', 113 | 'num_root', 'num_file_creations', 'num_shells', 'num_access_files', 'num_outbound_cmds', 114 | 'is_host_login', 'is_guest_login', 'count', 'srv_count', 'serror_rate', 'srv_serror_rate', 115 | 'rerror_rate', 'srv_rerror_rate', 'same_srv_rate', 'diff_srv_rate', 'srv_diff_host_rate', 116 | 'dst_host_count', 'dst_host_srv_count', 'dst_host_same_srv_rate', 'dst_host_diff_srv_rate', 117 | 'dst_host_same_src_port_rate', 'dst_host_srv_diff_host_rate', 'dst_host_serror_rate', 118 | 'dst_host_srv_serror_rate', 'dst_host_rerror_rate', 'dst_host_srv_rerror_rate']) 119 | pd_data.drop('num_outbound_cmds', axis=1, inplace=True) # 删除存在空值的列 120 | pd_data.drop('is_host_login', axis=1, inplace=True) # 删除存在空值的列 121 | pd_data.to_csv(outputFile, header=None, index=None) 122 | 123 | 124 | 125 | 126 | def run(source,temp): 127 | char2num(source, temp) # 字符型特征转数字型特征 128 | stdData, labelColumn = standardize(temp) 129 | normData, _, _ = normalize(stdData) 130 | 131 | #数据集乱序 132 | np.random.seed(116) 133 | np.random.shuffle(normData) 134 | np.random.seed(116) 135 | np.random.shuffle(labelColumn) 136 | 137 | #按6:2:2分出训练集,验证集和测试集 138 | n_data=len(labelColumn) 139 | split_ind1 = int(n_data * 0.6) 140 | split_ind2 = int(n_data * 0.8) 141 | 142 | train_data=normData[:split_ind1,:] 143 | train_label = labelColumn[:split_ind1] 144 | val_data=normData[split_ind1:split_ind2,:] 145 | val_label = labelColumn[split_ind1:split_ind2] 146 | test_data=normData[split_ind2:,:] 147 | test_label = labelColumn[split_ind2:] 148 | 149 | 150 | 151 | label = pd.DataFrame(train_label,columns=["attack_type"]) 152 | label.to_csv(".//dataset//"+"train_label.csv", header=None, index=None) 153 | label = pd.DataFrame(val_label, columns=["attack_type"]) 154 | label.to_csv(".//dataset//"+"val_label.csv", header=None, index=None) 155 | label = pd.DataFrame(test_label, columns=["attack_type"]) 156 | label.to_csv(".//dataset//"+"test_label.csv", header=None, index=None) 157 | 158 | print('START: 数据导出中') 159 | exportData(train_data, ".//dataset//"+"train_data.csv") 160 | exportData(val_data, ".//dataset//"+"val_data.csv") 161 | exportData(test_data, ".//dataset//"+"test_data.csv") 162 | 163 | print(f'FINISH: 数据导出成功\n共导出 {dataCnt} 条数据') 164 | 165 | 166 | if __name__=='__main__': 167 | start_time=datetime.now() 168 | 169 | sourceFile= './/dataset//kddcup.data_10_percent_corrected' 170 | deCharFile = './/dataset//decharedData.csv' 171 | 172 | run(sourceFile,deCharFile) 173 | 174 | end_time=datetime.now() 175 | print("运行时间 ",(end_time-start_time),'s') #输出程序运行时间 176 | -------------------------------------------------------------------------------- /base_model.py: -------------------------------------------------------------------------------- 1 | from tensorflow_core import keras 2 | from tensorflow_core import argmax 3 | from tensorflow_core import newaxis 4 | import pandas as pd 5 | import matplotlib.pyplot as plt 6 | import random 7 | import numpy as np 8 | 9 | 10 | intrusion_list_1 = ['normal.', # normal 11 | 'back.', 'land.', 'neptune.', 'pod.', 'smurf.', 'teardrop.', # DOS 12 | 'ipsweep.', 'nmap.', 'portsweep.', 'satan.', # PROBE 13 | 'ftp_write.', 'guess_passwd.', 'imap.', 'multihop.', 'phf.', 'spy.', 'warezclient.', 'warezmaster.', # R2L 14 | 'buffer_overflow.', 'loadmodule.', 'perl.', 'rootkit.'] # U2R 15 | 16 | intrusion_list_2 = ['normal.', # normal 17 | 'back.', 'neptune.', 'teardrop.', # DOS 18 | 'ipsweep.', 'satan.', # PROBE 19 | 'warezclient.', 'guess_passwd.' # R2L 20 | ] 21 | 22 | intrusion_list_3 = ['normal.', # normal 23 | 'back.', 'neptune.', 'pod.', 'smurf.', 'teardrop.', # DOS 24 | 'ipsweep.', 'nmap.', 'portsweep.', 'satan.' # PROBE 25 | ] 26 | 27 | class BaseModel(): 28 | def __init__(self): 29 | self.is_save_model = False # 是否保存训练模型 30 | 31 | self.train_accuracy = 2.5 32 | self.val_accuracy = 1.0 33 | self.test_accuracy = 1.0 34 | 35 | self.train_loss=1.0 36 | self.val_loss=1.0 37 | self.test_loss=1.0 38 | 39 | self.train_time = 0 40 | self.history = keras.callbacks.History 41 | self.model = keras.models.Model 42 | 43 | self.batch_size = 64 #批次大小 44 | self.epochs=100 #迭代轮数 45 | self.input_shape = () 46 | self.num_classes= -1 #最终分类数 47 | 48 | self.model_name="" 49 | self.data_mode = 2 # 选取数据集 50 | 51 | def LoadData(self): 52 | if(self.data_mode == 1): 53 | # 1号数据集39个特征,23分类 54 | self.input_shape = (39, 1) 55 | self.num_classes = 23 56 | 57 | self.train_data = pd.read_csv( 58 | './/dataset//train_data_1.csv', header=None).values 59 | self.train_label = pd.read_csv( 60 | './/dataset//train_label_1.csv', header=None).values 61 | self.val_data = pd.read_csv( 62 | './/dataset//val_data_1.csv', header=None).values 63 | self.val_label = pd.read_csv( 64 | './/dataset//val_label_1.csv', header=None).values 65 | self.test_data = pd.read_csv( 66 | './/dataset//test_data_1.csv', header=None).values 67 | self.test_label = pd.read_csv( 68 | './/dataset//test_label_1.csv', header=None).values 69 | 70 | elif(self.data_mode == 2): 71 | # 2号数据集10个特征,10分类 72 | self.input_shape = (12, 1) 73 | self.num_classes = 8 74 | 75 | self.train_data = pd.read_csv( 76 | './/dataset//train_data_2.csv', header=None).values 77 | self.train_label = pd.read_csv( 78 | './/dataset//train_label_2.csv', header=None).values 79 | self.val_data = pd.read_csv( 80 | './/dataset//val_data_2.csv', header=None).values 81 | self.val_label = pd.read_csv( 82 | './/dataset//val_label_2.csv', header=None).values 83 | self.test_data = pd.read_csv( 84 | './/dataset//test_data_2.csv', header=None).values 85 | self.test_label = pd.read_csv( 86 | './/dataset//test_label_2.csv', header=None).values 87 | 88 | elif(self.data_mode == 3): 89 | # 3号数据集19个特征,10分类 90 | self.input_shape = (19, 1) 91 | self.num_classes = 10 92 | 93 | self.train_data = pd.read_csv( 94 | './/dataset//train_data_3.csv', header=None).values 95 | self.train_label = pd.read_csv( 96 | './/dataset//train_label_3.csv', header=None).values 97 | self.val_data = pd.read_csv( 98 | './/dataset//val_data_3.csv', header=None).values 99 | self.val_label = pd.read_csv( 100 | './/dataset//val_label_3.csv', header=None).values 101 | self.test_data = pd.read_csv( 102 | './/dataset//test_data_3.csv', header=None).values 103 | self.test_label = pd.read_csv( 104 | './/dataset//test_label_3.csv', header=None).values 105 | # 调整数据输入形状 106 | self.Reshpae() 107 | 108 | def Reshpae(self): 109 | #因为送入神经网络是成batch的 110 | #所以要把数据变shape为(self.train_data.shape[0], 39, 1) 111 | #一维卷积只能在列维度移动所以要(self.train_data.shape[0], 39, 1) 112 | if(self.data_mode == 1): 113 | self.train_data = self.train_data.reshape( 114 | self.train_data.shape[0], 39, 1) 115 | self.test_data = self.test_data.reshape( 116 | self.test_data.shape[0], 39, 1) 117 | self.val_data = self.val_data.reshape( 118 | self.val_data.shape[0], 39, 1) 119 | elif(self.data_mode == 2): 120 | self.train_data = self.train_data.reshape( 121 | self.train_data.shape[0], 12, 1) 122 | self.test_data = self.test_data.reshape( 123 | self.test_data.shape[0], 12, 1) 124 | self.val_data = self.val_data.reshape( 125 | self.val_data.shape[0], 12, 1) 126 | elif(self.data_mode == 3): 127 | self.train_data = self.train_data.reshape( 128 | self.train_data.shape[0], 19, 1) 129 | self.test_data = self.test_data.reshape( 130 | self.test_data.shape[0], 19, 1) 131 | self.val_data = self.val_data.reshape( 132 | self.val_data.shape[0], 19, 1) 133 | 134 | def LoadModle(self, path): 135 | self.model = keras.models.load_model(path) 136 | 137 | def RandomTest(self): 138 | num = random.randint(0, len(self.test_data)-1) 139 | # 变为模型能接受的形式 140 | x_predict = self.test_data[num] 141 | x_predict = x_predict[newaxis,...] 142 | 143 | predict = self.model.predict(x_predict) 144 | print(predict,self.test_label[num]) 145 | if(self.data_mode == 1): 146 | real = intrusion_list_1[int(self.test_label[num])] 147 | pred = intrusion_list_1[argmax(predict[0], axis=-1)] 148 | elif(self.data_mode == 2): 149 | real = intrusion_list_2[int(self.test_label[num])] 150 | pred = intrusion_list_2[argmax(predict[0], axis=-1)] 151 | elif(self.data_mode == 3): 152 | real = intrusion_list_3[int(self.test_label[num])] 153 | pred = intrusion_list_3[argmax(predict[0], axis=-1)] 154 | 155 | print('真实值:', real) 156 | print('检测值:', pred) 157 | 158 | return real,pred 159 | 160 | def Evaluate(self): 161 | 162 | # 将测试集输入到训练好的模型中,查看测试集的误差 163 | score = self.model.evaluate(self.test_data, self.test_label, 164 | verbose=1, batch_size=64) 165 | self.test_accuracy = score[1] 166 | self.test_loss = score[0] 167 | print('Test loss:', score[0]) 168 | print('Test accuracy: %.2f%%' % (score[1] * 100)) 169 | 170 | def SaveTrainProcess(self): 171 | # 保存训练结果txt文件 172 | with open(f".//mymodles//{self.model_name}_{self.data_mode}.txt", "w") as f: 173 | f.writelines(line+'\n' for line in[str(round(self.train_loss,7)),str(self.train_accuracy), 174 | str(round(self.val_loss, 7)), str(self.val_accuracy),str(self.train_time)]) 175 | 176 | 177 | # 保存训练过程图片 178 | acc = self.history.history['sparse_categorical_accuracy'] 179 | val_acc = self.history.history['val_sparse_categorical_accuracy'] 180 | loss = self.history.history['loss'] 181 | val_loss = self.history.history['val_loss'] 182 | 183 | 184 | plt.subplot(2, 1, 1) 185 | plt.plot(acc, label='Training Accuracy') 186 | plt.plot(val_acc, label='Validation Accuracy') 187 | plt.title('Training and Validation Accuracy of '+self.model_name) 188 | plt.legend() 189 | #设置坐标轴刻度 190 | my_x_ticks = np.arange(0, self.epochs, 1) 191 | my_y_ticks = np.arange(0.5, 1, 0.05) 192 | # plt.xticks(my_x_ticks) 193 | plt.yticks(my_y_ticks) 194 | 195 | plt.subplot(2, 1, 2) 196 | plt.plot(loss, label='Training Loss') 197 | plt.plot(val_loss, label='Validation Loss') 198 | plt.title('Training and Validation Loss of '+self.model_name) 199 | plt.legend() 200 | #设置坐标轴刻度 201 | my_x_ticks = np.arange(0, self.epochs, 1) 202 | my_y_ticks = np.arange(0, 2, 0.15) 203 | # plt.xticks(my_x_ticks) 204 | plt.yticks(my_y_ticks) 205 | 206 | # 调整图片使不重叠 207 | plt.tight_layout() 208 | plt.savefig('.//mymodles//'+self.model_name+"_"+str(self.data_mode)+'.jpg') 209 | plt.clf() 210 | 211 | # 等待子类实现 212 | def Train(self): 213 | pass 214 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 650 10 | 376 11 | 12 | 13 | 14 | 15 | 650 16 | 376 17 | 18 | 19 | 20 | 21 | 650 22 | 376 23 | 24 | 25 | 26 | 网络入侵检测系统 27 | 28 | 29 | 30 | 31 | 32 | 10 33 | 20 34 | 115 35 | 311 36 | 37 | 38 | 39 | 40 | 41 | 11 42 | 0 43 | 93 44 | 51 45 | 46 | 47 | 48 | 49 | 微软雅黑 Light 50 | 11 51 | 75 52 | true 53 | 54 | 55 | 56 | 开始训练 57 | 58 | 59 | 60 | 61 | 62 | 11 63 | 180 64 | 93 65 | 51 66 | 67 | 68 | 69 | 70 | 微软雅黑 Light 71 | 11 72 | 75 73 | true 74 | 75 | 76 | 77 | 随机检测 78 | 79 | 80 | 81 | 82 | 83 | 11 84 | 60 85 | 93 86 | 51 87 | 88 | 89 | 90 | 91 | 微软雅黑 Light 92 | 11 93 | 75 94 | true 95 | 96 | 97 | 98 | 训练过程 99 | 100 | 101 | 102 | 103 | 104 | 10 105 | 240 106 | 93 107 | 51 108 | 109 | 110 | 111 | 112 | 微软雅黑 Light 113 | 11 114 | 75 115 | true 116 | 117 | 118 | 119 | 全集检测 120 | 121 | 122 | 123 | 124 | 125 | 10 126 | 120 127 | 93 128 | 51 129 | 130 | 131 | 132 | 133 | 微软雅黑 Light 134 | 11 135 | 75 136 | true 137 | 138 | 139 | 140 | 加载模型 141 | 142 | 143 | 144 | 145 | 146 | 147 | 240 148 | 30 149 | 91 150 | 31 151 | 152 | 153 | 154 | 155 | 微软雅黑 156 | 10 157 | 158 | 159 | 160 | 训练准确率 161 | 162 | 163 | 164 | 165 | 166 | 420 167 | 30 168 | 91 169 | 31 170 | 171 | 172 | 173 | 174 | 微软雅黑 175 | 10 176 | 177 | 178 | 179 | 验证准确率 180 | 181 | 182 | 183 | 184 | 185 | 230 186 | 60 187 | 111 188 | 41 189 | 190 | 191 | 192 | 193 | 微软雅黑 Light 194 | 13 195 | 75 196 | true 197 | 198 | 199 | 200 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 201 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 202 | p, li { white-space: pre-wrap; } 203 | </style></head><body style=" font-family:'微软雅黑 Light'; font-size:13pt; font-weight:600; font-style:normal;"> 204 | <p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> 205 | 206 | 207 | 208 | 209 | 210 | 410 211 | 60 212 | 111 213 | 41 214 | 215 | 216 | 217 | 218 | 微软雅黑 Light 219 | 13 220 | 75 221 | true 222 | 223 | 224 | 225 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 226 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 227 | p, li { white-space: pre-wrap; } 228 | </style></head><body style=" font-family:'微软雅黑 Light'; font-size:13pt; font-weight:600; font-style:normal;"> 229 | <p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> 230 | 231 | 232 | 233 | 234 | 235 | 410 236 | 200 237 | 111 238 | 41 239 | 240 | 241 | 242 | 243 | 微软雅黑 Light 244 | 11 245 | 75 246 | true 247 | 248 | 249 | 250 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 251 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 252 | p, li { white-space: pre-wrap; } 253 | </style></head><body style=" font-family:'微软雅黑 Light'; font-size:11pt; font-weight:600; font-style:normal;"> 254 | <p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:13pt;"><br /></p></body></html> 255 | 256 | 257 | 258 | 259 | 260 | 230 261 | 200 262 | 111 263 | 41 264 | 265 | 266 | 267 | 268 | 微软雅黑 Light 269 | 11 270 | 75 271 | true 272 | 273 | 274 | 275 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 276 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 277 | p, li { white-space: pre-wrap; } 278 | </style></head><body style=" font-family:'微软雅黑 Light'; font-size:11pt; font-weight:600; font-style:normal;"> 279 | <p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> 280 | 281 | 282 | 283 | 284 | 285 | 430 286 | 170 287 | 91 288 | 31 289 | 290 | 291 | 292 | 293 | 微软雅黑 294 | 10 295 | 296 | 297 | 298 | 真实结果 299 | 300 | 301 | 302 | 303 | 304 | 250 305 | 170 306 | 91 307 | 31 308 | 309 | 310 | 311 | 312 | 微软雅黑 313 | 10 314 | 315 | 316 | 317 | 检测结果 318 | 319 | 320 | 321 | 322 | 323 | 170 324 | 320 325 | 411 326 | 22 327 | 328 | 329 | 330 | 331 | Classical Quantum Convolutional Neural Network 332 | 333 | 334 | 335 | 336 | Hybrid model with a single quantum filter 337 | 338 | 339 | 340 | 341 | Hybrid convolution with multiple quantum filters 342 | 343 | 344 | 345 | 346 | 347 | 348 | 30 349 | 320 350 | 71 351 | 21 352 | 353 | 354 | 355 | 356 | 微软雅黑 Light 357 | 10 358 | 75 359 | true 360 | 361 | 362 | 363 | 算法选择 364 | 365 | 366 | 367 | 368 | 369 | 370 | true 371 | 372 | 373 | 使用现有模型 374 | 375 | 376 | 377 | 378 | true 379 | 380 | 381 | false 382 | 383 | 384 | 训练结束保存模型 385 | 386 | 387 | 388 | 389 | Quantum Convolutional Neural Network 390 | 391 | 392 | 393 | 394 | Hybrid Model With A Single Quantum Filter 395 | 396 | 397 | 398 | 399 | Hybrid Convolution With Multiple Quantum Filters 400 | 401 | 402 | 403 | 404 | 405 | 406 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PyQt5 import QtCore 3 | from PyQt5.QtWidgets import QFileDialog, QMainWindow, QApplication, QLabel, QHBoxLayout, QWidget 4 | from PyQt5.QtGui import QPixmap 5 | from PyQt5.uic import loadUi 6 | import qcnn 7 | import base_model 8 | import random 9 | import PyQt5 10 | 11 | # # 自适应高分辨率 12 | # QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) 13 | if hasattr(QtCore.Qt, 'AA_EnableHighDpiScaling'): 14 | PyQt5.QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) 15 | 16 | if hasattr(QtCore.Qt, 'AA_UseHighDpiPixmaps'): 17 | PyQt5.QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) 18 | 19 | 20 | # 隐藏GPU 21 | import os 22 | os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" 23 | os.environ["CUDA_VISIBLE_DEVICES"] = "-1" 24 | 25 | 26 | model_type=-1 27 | 28 | #训练过程窗口 29 | class Process_win(QWidget): 30 | def __init__(self,jpg_path): 31 | super().__init__() 32 | 33 | self.setWindowTitle("训练过程") 34 | self.setAttribute( 35 | QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) 36 | self.lab = QLabel() 37 | 38 | self.lab.setPixmap(QPixmap(jpg_path[0])) 39 | self.vbox = QHBoxLayout() 40 | self.vbox.addWidget(self.lab) 41 | self.setLayout(self.vbox) 42 | 43 | 44 | 45 | #开辟新的线程训练模型 46 | class RunThread(QtCore.QThread): 47 | # 通过类成员对象定义信号对象 48 | _signal = QtCore.pyqtSignal(qcnn.MyQnnModel) 49 | 50 | def __init__(self, model): 51 | super(RunThread, self).__init__() 52 | self.model=model 53 | 54 | def __del__(self): 55 | self.wait() 56 | 57 | def run(self): 58 | 59 | 60 | self.model.Train() 61 | self._signal.emit(self.model) 62 | 63 | # 记录此模型 64 | self.model.Evaluate() 65 | self.model.RandomTest() 66 | self.exit() 67 | 68 | class win(QMainWindow): 69 | def __init__(self): 70 | super().__init__() 71 | loadUi(".//newMainWindow.ui", self) 72 | # 丑化界面 73 | self.setWindowOpacity(0.98) 74 | # self.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 隐藏边框 75 | 76 | 77 | self.my_qmodel = qcnn.MyQnnModel() 78 | self.my_model=base_model.BaseModel() 79 | self.process_win=Process_win 80 | 81 | #信号连接 82 | self.comboBox_select.currentIndexChanged.connect( 83 | self.ChangeStat_combox) 84 | self.pushButton_starttrain.clicked.connect(self.StartTrain) 85 | self.pushButton_showprocess.clicked.connect(self.ShowProcess) 86 | self.pushButton_random.clicked.connect(self.RandomPredict) 87 | self.pushButton_all.clicked.connect(self.AllPredict) 88 | self.pushButton_loadmodel.clicked.connect(self.LoadModel) 89 | 90 | self.pushButton_trainpath.clicked.connect(self.GetTrainPath) 91 | self.pushButton_valpath.clicked.connect(self.GetValPath) 92 | self.pushButton_testpath.clicked.connect(self.GetTestPath) 93 | self.checkBox_save.stateChanged.connect( 94 | lambda: self.ChangeStat_checkbox(self.checkBox_save)) 95 | # 仅提供量子卷积神经网络,默认是2号数据集 96 | def GetTrainPath(self): 97 | name_list = QFileDialog. getOpenFileNames( 98 | self, "请选择训练集数据与训练集标签", ".//dataset", "CSV Files(*.csv)") 99 | if(len(name_list[0])<2): 100 | self.statusbar.showMessage("未正确选择训练集!") 101 | return 102 | 103 | self.my_qmodel.traindata_path = name_list[0][0] 104 | self.my_qmodel.trainlabel_path = name_list[0][1] 105 | 106 | self.lineEdit_trainpath.setText(f"{name_list[0][0]};{name_list[0][1]}") 107 | 108 | # 仅提供量子卷积神经网络,默认是2号数据集 109 | def GetValPath(self): 110 | name_list = QFileDialog. getOpenFileNames( 111 | self, "请选择验证集数据与验证集标签", ".//dataset", "CSV Files(*.csv)") 112 | if(len(name_list[0]) < 2): 113 | self.statusbar.showMessage("未正确选择验证集!") 114 | return 115 | 116 | self.my_qmodel.valdata_path = name_list[0][0] 117 | self.my_qmodel.vallabel_path = name_list[0][1] 118 | 119 | self.lineEdit_valpath.setText(f"{name_list[0][0]};{name_list[0][1]}") 120 | 121 | # 仅提供量子卷积神经网络,默认是2号数据集 122 | def GetTestPath(self): 123 | name_list = QFileDialog. getOpenFileNames( 124 | self, "请选择验证集数据与验证集标签", ".//dataset", "CSV Files(*.csv)") 125 | if(len(name_list[0]) < 2): 126 | self.statusbar.showMessage("未正确选择测试集!") 127 | return 128 | 129 | self.my_qmodel.testdata_path = name_list[0][0] 130 | self.my_qmodel.testlabel_path = name_list[0][1] 131 | 132 | self.lineEdit_testpath.setText(f"{name_list[0][0]};{name_list[0][1]}") 133 | 134 | # 切换算法后更新状态栏 135 | def ChangeStat_combox(self): 136 | self.statusbar.showMessage( 137 | "即将训练的算法已更换为 "+f"{self.comboBox_select.currentText()}"+"!") 138 | 139 | def ChangeStat_checkbox(self,a): 140 | if(a.isChecked()==True): 141 | self.statusbar.showMessage("将保存本次训练结果!") 142 | else: 143 | self.statusbar.showMessage("不保存本次训练结果!") 144 | 145 | # 子线程的回调 146 | def CallBack(self,msg): 147 | self.my_qmodel=msg 148 | 149 | def StartTrain(self): 150 | # 仅提供量子卷积神经网络的模型训练 151 | self.lineEdit_trainacc.setText("") 152 | self.lineEdit_trainloss.setText("") 153 | self.lineEdit_valacc.setText("") 154 | self.lineEdit_valloss.setText("") 155 | self.lineEdit_traintime.setText("") 156 | 157 | self.my_qmodel.is_save = self.checkBox_save.isChecked() 158 | 159 | self.statusbar.showMessage("正在训练模型...") 160 | 161 | 162 | if(self.comboBox_select.currentText() == "Hybrid model with a single quantum filter"): 163 | self.my_qmodel.model_name = "HQcnn_s" 164 | elif(self.comboBox_select.currentText() == "Hybrid convolution with multiple quantum filters"): 165 | self.my_qmodel.model_name = "HQcnn_m" 166 | 167 | self.my_qmodel.epochs = int(self.lineEdit_epoch.text()) 168 | self.my_qmodel.batch_size = int(self.lineEdit_batch.text()) 169 | self.my_qmodel.num_classes = int(self.lineEdit_class.text()) 170 | self.my_qmodel.features = int(self.lineEdit_feature.text()) 171 | self.my_qmodel.LoadData() 172 | 173 | 174 | 175 | self.thread = RunThread(self.my_qmodel) 176 | self.thread._signal.connect(self.CallBack) 177 | self.thread.start() 178 | 179 | #等待子线程运行完毕 180 | while(True): 181 | QApplication.processEvents() 182 | if(self.my_qmodel.train_over==True): 183 | self.lineEdit_trainacc.setText( 184 | "%.7f" % self.my_qmodel.train_accuracy) 185 | self.lineEdit_valacc.setText( 186 | "%.7f" % self.my_qmodel.val_accuracy) 187 | self.lineEdit_trainloss.setText( 188 | "%.7f" % self.my_qmodel.train_loss) 189 | self.lineEdit_valloss.setText( 190 | "%.7f" % self.my_qmodel.val_loss) 191 | self.lineEdit_traintime.setText( 192 | "%ds" % self.my_qmodel.train_time) 193 | 194 | self.statusbar.showMessage(f"模型训练完毕!") 195 | break 196 | 197 | #重置训练状态 198 | self.my_qmodel.train_over = False 199 | 200 | 201 | def ShowProcess(self): 202 | jpg_path = QFileDialog.getOpenFileName( 203 | self, "请选择某个模型的训练过程图", ".//mymodles", "JPG Files(*.jpg)") 204 | if(jpg_path[0]==""): 205 | self.statusbar.showMessage("未正确选择图片!") 206 | return 207 | self.process_win = Process_win(jpg_path) 208 | self.process_win.show() 209 | self.statusbar.showMessage("过程图片已显示!") 210 | 211 | def AllPredict(self): 212 | # 传统神经网络模型 213 | if(model_type == 0): 214 | self.statusbar.showMessage(f"正在检测全部测试集,共 {len(self.my_model.test_label)} 条数据...") 215 | 216 | self.my_model.Evaluate() 217 | self.lineEdit_testacc.setText("%.7f" % self.my_model.test_accuracy) 218 | self.lineEdit_testloss.setText("%.7f" % self.my_model.test_loss) 219 | self.statusbar.showMessage("测试集检测完毕!") 220 | 221 | # 量子神经网络模型 222 | elif(model_type == 1): 223 | with open(f".//mymodles//{self.my_qmodel.model_name}_alltest.txt", "r") as f: 224 | test_loss, test_accuracy = f.readlines() 225 | 226 | self.lineEdit_testloss.setText( 227 | "%.7f" % float(test_loss)) 228 | self.lineEdit_testacc.setText( 229 | "%.7f" % float(test_accuracy)) 230 | else: 231 | self.statusbar.showMessage("请先加载模型!") 232 | 233 | def RandomPredict(self): 234 | # 传统神经网络模型 235 | if(model_type==0): 236 | self.statusbar.showMessage("正在随机抽检...") 237 | 238 | predict,real=self.my_model.RandomTest() 239 | 240 | self.lineEdit_predictresult.setText(predict) 241 | self.lineEdit_realresult.setText(real) 242 | 243 | self.statusbar.showMessage("抽检完毕!") 244 | 245 | # 量子神经网络模型 246 | elif(model_type==1): 247 | with open(f".//mymodles//{self.my_qmodel.model_name}_randomtest.txt", "r") as f: 248 | lines = f.readlines() 249 | num=random.randint(0, len(lines)) 250 | real,predict=lines[num].split(" ") 251 | 252 | self.lineEdit_predictresult.setText(predict) 253 | self.lineEdit_realresult.setText(real) 254 | else: 255 | self.statusbar.showMessage("请先加载模型!") 256 | 257 | 258 | def LoadModel(self): 259 | self.statusbar.showMessage("正在加载模型...") 260 | model_path=QFileDialog.getOpenFileName(self, "请选择预载模型",".//mymodles", "H5 Files(*.h5)") 261 | 262 | 263 | if(model_path[0]==""): 264 | self.statusbar.showMessage("模型未正确而载入!") 265 | return 266 | 267 | self.lineEdit_loadmodel.setText(model_path[0]) 268 | 269 | global model_type 270 | 271 | # 加载传统神经网络模型 272 | if(("Bp_model" in str(model_path[0])) or ("Cnn_model" in str(model_path[0]))): 273 | self.my_model.LoadModle(str(model_path[0])) 274 | 275 | if("Bp"in str(model_path[0])): 276 | self.my_model.model_name = "BP" 277 | else: 278 | self.my_model.model_name = "CNN" 279 | 280 | 281 | # 使用规定好的测试集 282 | if('1'in str(model_path[0])): 283 | flag = 1 284 | elif('2'in str(model_path[0])): 285 | flag = 2 286 | elif('3' in str(model_path[0])): 287 | flag = 3 288 | 289 | self.my_model.data_mode=flag 290 | 291 | # 读取训练结果文件 292 | with open(f".//mymodles//{self.my_model.model_name}_{self.my_model.data_mode}.txt", "r") as f: 293 | train_loss, train_accuracy, val_loss, val_accuracy, train_time = f.readlines() 294 | 295 | # 显示训练结果 296 | self.lineEdit_trainacc.setText( 297 | "%.7f" % float(train_accuracy)) 298 | self.lineEdit_valacc.setText( 299 | "%.7f" % float(val_accuracy)) 300 | self.lineEdit_trainloss.setText( 301 | "%.7f" % float(train_loss)) 302 | self.lineEdit_valloss.setText( 303 | "%.7f" % float(val_loss)) 304 | self.lineEdit_traintime.setText( 305 | "%ds" % int(train_time)) 306 | 307 | # 载入测试集数据 308 | self.my_model.LoadData() 309 | # 界面显示测试集路径 310 | self.lineEdit_testpath.setText( 311 | ".//dataset//test_data_%d.csv;.//dataset//test_label_%d.csv" % (flag,flag)) 312 | 313 | # 禁止选取测试集操作 314 | self.pushButton_testpath.setEnabled(False) 315 | 316 | model_type = 0 317 | # 加载量子卷积神经网络模型 318 | else: 319 | self.pushButton_testpath.setEnabled(True) 320 | 321 | # self.my_qmodel.LoadModle(str(model_path[0])) 322 | if("HQcnn_s" in str(model_path[0])): 323 | self.my_qmodel.model_name = "HQcnn_s" 324 | else: 325 | self.my_qmodel.model_name = "HQcnn_m" 326 | 327 | # print(model_path[0],self.my_qmodel.model_name) 328 | # 读取训练结果文件 329 | with open(f".//mymodles//{self.my_qmodel.model_name}.txt", "r") as f: 330 | train_loss, train_accuracy, val_loss, val_accuracy, train_time = f.readlines() 331 | 332 | # 显示训练结果 333 | self.lineEdit_trainacc.setText( 334 | "%.7f" % float(train_accuracy)) 335 | self.lineEdit_valacc.setText( 336 | "%.7f" % float(val_accuracy)) 337 | self.lineEdit_trainloss.setText( 338 | "%.7f" % float(train_loss)) 339 | self.lineEdit_valloss.setText( 340 | "%.7f" % float(val_loss)) 341 | self.lineEdit_traintime.setText( 342 | "%ds" % int(train_time)) 343 | 344 | # 界面显示默认测试集路径 345 | self.lineEdit_testpath.setText( 346 | ".//dataset//test_data_2.csv;.//dataset//test_label_2.csv") 347 | 348 | model_type = 1 349 | 350 | # 显示模型加载状态 351 | if(model_type == 0): 352 | self.statusbar.showMessage("传统神经网络模型载入成功!") 353 | elif(model_type==1): 354 | self.statusbar.showMessage("量子神经网络模型载入成功!") 355 | else: 356 | self.statusbar.showMessage("模型未正确而载入!") 357 | 358 | 359 | def RunWindow(): 360 | app = QApplication(sys.argv) 361 | w = win() 362 | w.show() 363 | sys.exit(app.exec_()) 364 | 365 | if __name__ == "__main__": 366 | RunWindow() 367 | -------------------------------------------------------------------------------- /qcnn.py: -------------------------------------------------------------------------------- 1 | import tensorflow_quantum as tfq 2 | from tensorflow_core import argmax 3 | from tensorflow_core import newaxis 4 | from tensorflow_core import dtypes 5 | from tensorflow_core import keras 6 | 7 | from datetime import datetime 8 | import matplotlib.pyplot as plt 9 | 10 | import cirq 11 | import sympy 12 | import numpy as np 13 | 14 | # import os 15 | # os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" 16 | # os.environ["CUDA_VISIBLE_DEVICES"] = "-1" 17 | 18 | intrusion_list = ['normal.', # normal 19 | 'back.', 'neptune.', 'teardrop.', # DOS 20 | 'ipsweep.', 'satan.', # PROBE 21 | 'warezclient.', 'guess_passwd.' # R2L 22 | ] 23 | 24 | intrusion_list_3 = ['normal.', # normal 25 | 'back.', 'neptune.', 'pod.', 'smurf.', 'teardrop.', # DOS 26 | 'ipsweep.', 'nmap.', 'portsweep.', 'satan.' # PROBE 27 | ] 28 | 29 | class MyQnnModel(): 30 | def __init__(self): 31 | 32 | self.train_accuracy = 2.5 33 | self.train_loss = 2.5 34 | self.val_accuracy = 1.0 35 | self.val_loss = 1.0 36 | self.test_accuracy = 1.0 37 | self.test_loss = 1.0 38 | self.train_time = 0 39 | 40 | self.train_over = False 41 | self.is_save = False 42 | 43 | self.model = keras.models.Model 44 | self.history = keras.callbacks.History 45 | 46 | self.model_name = "" 47 | self.batch_size = 16 # 批次大小 48 | self.epochs = 70 # 迭代轮数 49 | self.num_classes = 8 #分类数 50 | self.features = 12 #数据特征数 51 | 52 | # 默认使用2号数据集 53 | self.traindata_path = ".//dataset//train_data_2.csv" 54 | self.trainlabel_path = ".//dataset//train_label_2.csv" 55 | self.valdata_path = ".//dataset//val_data_2.csv" 56 | self.vallabel_path = ".//dataset//val_label_2.csv" 57 | self.testdata_path = ".//dataset//test_data_2.csv" 58 | self.testlabel_path = ".//dataset//test_label_2.csv" 59 | 60 | 61 | self.train_data = [] 62 | self.train_label = [] 63 | self.val_data = [] 64 | self.val_label = [] 65 | self.test_data = [] 66 | self.test_label = [] 67 | 68 | # 初始量子比特 69 | self.quantum_bits = cirq.GridQubit.rect(1, self.features) 70 | 71 | # 将经典数据设置为旋转z门系数,8个量子比特首先进入旋转Z门 72 | # 达到将经典数据转化为量子数据的目的 73 | def ThetasAppend(self, bits, classic_data): 74 | circuit = cirq.Circuit() 75 | for i in range(self.features): 76 | circuit += [cirq.rz(classic_data[i])(bits[i])] 77 | # 返回的量子线路将作为输入 78 | return circuit 79 | 80 | # 载入数据 81 | def LoadData(self): 82 | print(self.features, 83 | len(self.trainlabel_path), self.valdata_path) 84 | # 更新量子比特 85 | self.quantum_bits = cirq.GridQubit.rect(1, self.features) 86 | 87 | train_data = np.genfromtxt( 88 | self.traindata_path, delimiter=",") 89 | train_label = np.genfromtxt( 90 | self.trainlabel_path, delimiter=",") 91 | val_data = np.genfromtxt( 92 | self.valdata_path, delimiter=",") 93 | val_label = np.genfromtxt( 94 | self.vallabel_path, delimiter=",") 95 | test_data = np.genfromtxt( 96 | self.testdata_path, delimiter=",") 97 | test_label = np.genfromtxt( 98 | self.testlabel_path, delimiter=",") 99 | 100 | thetas = [] 101 | n_data = len(train_label) 102 | # 逐条将经典数据转换为量子数据 103 | for n in range(n_data): 104 | thetas.append(self.ThetasAppend( 105 | self.quantum_bits, train_data[n])) 106 | # 将量子线路转换为dtype为string的张量形式 107 | self.train_data = tfq.convert_to_tensor(thetas) 108 | self.train_label = np.array(train_label) 109 | 110 | thetas = [] 111 | n_data = len(val_label) 112 | for n in range(n_data): 113 | thetas.append(self.ThetasAppend( 114 | self.quantum_bits, val_data[n])) 115 | self.val_data = tfq.convert_to_tensor(thetas) 116 | self.val_label = np.array(val_label) 117 | 118 | thetas = [] 119 | n_data = len(test_label) 120 | for n in range(n_data): 121 | thetas.append(self.ThetasAppend( 122 | self.quantum_bits, test_data[n])) 123 | self.test_data = tfq.convert_to_tensor(thetas) 124 | self.test_label = np.array(test_label) 125 | 126 | # 加载模型 127 | def LoadModle(self, path): 128 | self.model.load_weights(path) 129 | 130 | # 全集检测 131 | def Evaluate(self): 132 | if(self.is_save == False): 133 | print('未保存') 134 | return 135 | # 将测试集输入到训练好的模型中,查看测试集的误差 136 | score = self.model.evaluate(self.test_data, self.test_label, 137 | verbose=1, batch_size=128) 138 | self.test_accuracy = score[1] 139 | self.test_loss = score[0] 140 | print('Test loss:', score[0]) 141 | print('Test accuracy: %.2f%%' % (score[1] * 100)) 142 | 143 | # 保存训练结果txt文件 144 | with open(f".//mymodles//{self.model_name}_alltest.txt", "w") as f: 145 | f.writelines(line+'\n' for line in[str(round(self.test_loss, 7)), str(self.test_accuracy)]) 146 | # 随机检测 147 | def RandomTest(self): 148 | if(self.is_save==False): 149 | print('未保存') 150 | return 151 | # 获取所有单条检测值保存到txt文件 152 | with open(f".//mymodles//{self.model_name}_randomtest.txt", "w") as f: 153 | for num in range(len(self.test_data)): 154 | 155 | # 变为模型能接受的形式 156 | x_predict = self.test_data[num] 157 | x_predict = x_predict[newaxis, ...] 158 | 159 | predict = self.model.predict(x_predict) 160 | print(predict, self.test_label[num]) 161 | real = intrusion_list[int(self.test_label[num])] 162 | pred = intrusion_list[argmax(predict[0], axis=-1)] 163 | 164 | print('真实值:', real) 165 | print('检测值:', pred) 166 | f.write(f"{real} {pred}\n") 167 | 168 | # 开始训练 169 | def Train(self): 170 | 171 | if(self.model_name == "HQcnn_s"): 172 | model = self.GetHModel_s() 173 | elif(self.model_name == "HQcnn_m"): 174 | model = self.GetHModel_m() 175 | 176 | self.model = model 177 | 178 | 179 | start_time = datetime.now() 180 | 181 | self.model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=False), 182 | optimizer=keras.optimizers.Adam(learning_rate=0.01), metrics=['sparse_categorical_accuracy']) 183 | 184 | # # 存储模型的回调函数 185 | # cp_callback= keras.callbacks.ModelCheckpoint(filepath=f".//mymodles//{self.model_name}_model.ckpt", 186 | # save_weights_only=True, 187 | # save_best_only=True) 188 | 189 | self.history = model.fit(self.train_data, 190 | self.train_label, 191 | batch_size=self.batch_size, 192 | epochs=self.epochs, 193 | verbose=1, 194 | validation_data=(self.val_data, self.val_label) 195 | ) 196 | end_time = datetime.now() 197 | self.train_time = (end_time-start_time).seconds 198 | 199 | self.train_accuracy = self.history.history['sparse_categorical_accuracy'][self.epochs-1] 200 | self.val_accuracy = self.history.history['val_sparse_categorical_accuracy'][self.epochs-1] 201 | self.train_loss = self.history.history['loss'][self.epochs-1] 202 | self.val_loss = self.history.history['val_loss'][self.epochs-1] 203 | print(self.train_accuracy, self.val_accuracy) 204 | 205 | if(self.is_save==True): 206 | 207 | #保存训练过程图片 208 | acc = self.history.history['sparse_categorical_accuracy'] 209 | val_acc = self.history.history['val_sparse_categorical_accuracy'] 210 | loss = self.history.history['loss'] 211 | val_loss = self.history.history['val_loss'] 212 | 213 | plt.subplot(2, 1, 1) 214 | plt.plot(acc, label='Training Accuracy') 215 | plt.plot(val_acc, label='Validation Accuracy') 216 | plt.title('Training and Validation Accuracy of '+self.model_name) 217 | plt.legend() 218 | #设置坐标轴刻度 219 | my_x_ticks = np.arange(0, self.epochs, 1) 220 | my_y_ticks = np.arange(0.5, 1, 0.05) 221 | plt.xticks(my_x_ticks) 222 | plt.yticks(my_y_ticks) 223 | 224 | plt.subplot(2, 1, 2) 225 | plt.plot(loss, label='Training Loss') 226 | plt.plot(val_loss, label='Validation Loss') 227 | plt.title('Training and Validation Loss of '+self.model_name) 228 | plt.legend() 229 | #设置坐标轴刻度 230 | my_x_ticks = np.arange(0, self.epochs, 1) 231 | my_y_ticks = np.arange(0, 2, 0.15) 232 | plt.xticks(my_x_ticks) 233 | plt.yticks(my_y_ticks) 234 | # 调整图片使不重叠 235 | plt.tight_layout() 236 | plt.savefig('.//mymodles//'+self.model_name +'.jpg') 237 | plt.clf() 238 | 239 | # 保存训练结果txt文件 240 | with open(f".//mymodles//{self.model_name}.txt", "w") as f: 241 | f.writelines(line+'\n' for line in[str(round(self.train_loss, 7)), str(self.train_accuracy), 242 | str(round(self.val_loss, 7)), str(self.val_accuracy), str(self.train_time)]) 243 | 244 | self.train_over = True 245 | 246 | 247 | # 基础量子线路 248 | # 量子态编码线路(QSEC),每个量子比特都经过一个Hadamard门 249 | # 将初始为0态的量子比特振幅为(根号2,根号2)的叠加态 250 | def quantum_state_encoding_circuit(self,bits): 251 | circuit = cirq.Circuit() 252 | circuit.append(cirq.H.on_each(bits)) 253 | return circuit 254 | 255 | # 单比特量子门,symbols为参数 256 | def one_qubit_unitary(self, bit, symbols): 257 | return cirq.Circuit( 258 | cirq.X(bit)**symbols[0], 259 | cirq.Y(bit)**symbols[1], 260 | cirq.Z(bit)**symbols[2]) 261 | 262 | # 双比特量子门 263 | def two_qubit_unitary(self, bits, symbols): 264 | circuit = cirq.Circuit() 265 | circuit += self.one_qubit_unitary(bits[0], symbols[0:3]) 266 | circuit += self.one_qubit_unitary(bits[1], symbols[3:6]) 267 | circuit += [cirq.ZZ(*bits)**symbols[6]] 268 | circuit += [cirq.YY(*bits)**symbols[7]] 269 | circuit += [cirq.XX(*bits)**symbols[8]] 270 | circuit += self.one_qubit_unitary(bits[0], symbols[9:12]) 271 | circuit += self.one_qubit_unitary(bits[1], symbols[12:]) 272 | return circuit 273 | 274 | # 双比特池化门 275 | def two_qubit_pool(self, source_qubit, sink_qubit, symbols): 276 | pool_circuit = cirq.Circuit() 277 | sink_basis_selector = self.one_qubit_unitary(sink_qubit, symbols[0:3]) 278 | source_basis_selector = self.one_qubit_unitary( 279 | source_qubit, symbols[3:6]) 280 | pool_circuit.append(sink_basis_selector) 281 | pool_circuit.append(source_basis_selector) 282 | pool_circuit.append(cirq.CNOT(control=source_qubit, target=sink_qubit)) 283 | pool_circuit.append(sink_basis_selector**-1) 284 | return pool_circuit 285 | 286 | # 量子卷积 287 | def quantum_conv_circuit(self, bits, symbols): 288 | circuit = cirq.Circuit() 289 | for first, second in zip(bits[0::2], bits[1::2]): 290 | circuit += self.two_qubit_unitary([first, second], symbols) 291 | for first, second in zip(bits[1::2], bits[2::2] + [bits[0]]): 292 | circuit += self.two_qubit_unitary([first, second], symbols) 293 | return circuit 294 | 295 | # 量子池化 296 | def quantum_pool_circuit(self, source_bits, sink_bits, symbols): 297 | circuit = cirq.Circuit() 298 | for source, sink in zip(source_bits, sink_bits): 299 | circuit += self.two_qubit_pool(source, sink, symbols) 300 | return circuit 301 | 302 | 303 | # 量子卷积神经网络模型 304 | # 量子卷积池化线路 305 | def multi_readout_model_circuit(self, qubits): 306 | model_circuit = cirq.Circuit() 307 | symbols = sympy.symbols('qconv0:21') 308 | model_circuit += self.quantum_conv_circuit(qubits, symbols[0:15]) 309 | model_circuit += self.quantum_pool_circuit(qubits[:int(self.features/2)], qubits[int(self.features/2):], 310 | symbols[15:21]) 311 | return model_circuit 312 | 313 | # 带单量子滤波器的量子卷积神经网络 314 | def GetHModel_s(self): 315 | 316 | # 在Cirq中创建qubits以及测量操作 317 | readouts = [cirq.Z(bit) 318 | for bit in self.quantum_bits[int(self.features/2):]] 319 | 320 | qdata_input = keras.Input( 321 | shape=(), dtype=dtypes.string) 322 | 323 | qdata_state = tfq.layers.AddCircuit()( 324 | qdata_input, prepend=self.quantum_state_encoding_circuit(self.quantum_bits)) 325 | 326 | quantum_model = tfq.layers.PQC( 327 | self.multi_readout_model_circuit(self.quantum_bits), 328 | readouts)(qdata_state) 329 | 330 | dense_1 = keras.layers.Dense( 331 | 16, activation='relu')(quantum_model) 332 | 333 | dense_2 = keras.layers.Dense(self.num_classes, 334 | activation='softmax')(dense_1) 335 | 336 | hybrid_model = keras.Model( 337 | inputs=[qdata_input], outputs=[dense_2]) 338 | 339 | return hybrid_model 340 | 341 | # 带多量子滤波器的量子卷积神经网络 342 | def GetHModel_m(self): 343 | 344 | # 在Cirq中创建qubits以及测量操作 345 | readouts = [cirq.Z(bit) for bit in self.quantum_bits[int(self.features/2):]] 346 | 347 | qdata_input = keras.Input( 348 | shape=(), dtype=dtypes.string) 349 | 350 | qdata_state = tfq.layers.AddCircuit()( 351 | qdata_input, prepend=self.quantum_state_encoding_circuit(self.quantum_bits)) 352 | 353 | # 实现三个量子滤波器 354 | quantum_model_multi1 = tfq.layers.PQC( 355 | self.multi_readout_model_circuit(self.quantum_bits), 356 | readouts)(qdata_state) 357 | 358 | quantum_model_multi2 = tfq.layers.PQC( 359 | self.multi_readout_model_circuit(self.quantum_bits), 360 | readouts)(qdata_state) 361 | 362 | quantum_model_multi3 = tfq.layers.PQC( 363 | self.multi_readout_model_circuit(self.quantum_bits), 364 | readouts)(qdata_state) 365 | 366 | # 将测量所得的输出输入到一个经典神经网络中 367 | concat_out = keras.layers.concatenate( 368 | [quantum_model_multi1, quantum_model_multi2, quantum_model_multi3]) 369 | 370 | dense_1 = keras.layers.Dense(16, 371 | activation='relu')(concat_out) 372 | 373 | dense_2 = keras.layers.Dense(self.num_classes, 374 | activation='softmax')(dense_1) 375 | 376 | multi_qconv_model = keras.Model(inputs=[qdata_input], 377 | outputs=[dense_2]) 378 | return multi_qconv_model 379 | 380 | 381 | 382 | if __name__ == "__main__": 383 | model = MyQnnModel() 384 | model.model_name = "HQcnn_s" 385 | model.epochs=50 386 | model.LoadData() 387 | model.Train() 388 | model.Evaluate() 389 | model.RandomTest() 390 | 391 | 392 | 393 | -------------------------------------------------------------------------------- /newMainWindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 621 10 | 680 11 | 12 | 13 | 14 | 15 | 621 16 | 680 17 | 18 | 19 | 20 | 21 | 621 22 | 680 23 | 24 | 25 | 26 | 网络攻击检测模拟软件 27 | 28 | 29 | background-color: rgb(223, 238, 234); 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 10 39 | 50 40 | 601 41 | 211 42 | 43 | 44 | 45 | QWidget{background-color:rgb(167, 196, 188);} 46 | .QWidget{border:2px groove gray;border-radius:10px;padding:2px 4px;} 47 | 48 | 49 | 50 | 51 | 52 | 230 53 | 100 54 | 61 55 | 21 56 | 57 | 58 | 59 | 60 | 微软雅黑 61 | 7 62 | 63 | 64 | 65 | border:2px groove rgb(94, 139, 126);border-radius:10px;padding:2px 4px; 66 | 67 | 68 | 浏览 69 | 70 | 71 | 72 | 73 | 74 | 30 75 | 150 76 | 41 77 | 21 78 | 79 | 80 | 81 | 82 | 微软雅黑 83 | 7 84 | 85 | 86 | 87 | 算法选择 88 | 89 | 90 | 91 | 92 | 93 | 60 94 | 100 95 | 161 96 | 20 97 | 98 | 99 | 100 | 101 | 微软雅黑 102 | 7 103 | 104 | 105 | 106 | border:2px groove; 107 | border-color: rgb(153, 204, 204); 108 | 109 | 110 | F:\tedious\FinalDesign\code\withgit\dataset\train_data_2.csv;F:\tedious\FinalDesign\code\withgit\dataset\train_label_2.csv 111 | 112 | 113 | true 114 | 115 | 116 | 117 | 118 | 119 | 80 120 | 150 121 | 271 122 | 20 123 | 124 | 125 | 126 | 127 | 微软雅黑 128 | 7 129 | 130 | 131 | 132 | border:2px groove; 133 | border-color: rgb(153, 204, 204); 134 | 135 | 136 | 137 | Hybrid model with a single quantum filter 138 | 139 | 140 | 141 | 142 | Hybrid convolution with multiple quantum filters 143 | 144 | 145 | 146 | 147 | 148 | 149 | 10 150 | 100 151 | 51 152 | 21 153 | 154 | 155 | 156 | 157 | 微软雅黑 158 | 7 159 | 160 | 161 | 162 | 训练集路径 163 | 164 | 165 | 166 | 167 | 168 | 370 169 | 100 170 | 151 171 | 20 172 | 173 | 174 | 175 | 176 | 微软雅黑 177 | 7 178 | 179 | 180 | 181 | border:2px groove; 182 | border-color: rgb(153, 204, 204); 183 | 184 | 185 | F:\tedious\FinalDesign\code\withgit\dataset\val_data_2.csv;F:\tedious\FinalDesign\code\withgit\dataset\val_label_2.csv 186 | 187 | 188 | true 189 | 190 | 191 | 192 | 193 | 194 | 320 195 | 100 196 | 51 197 | 21 198 | 199 | 200 | 201 | 202 | 微软雅黑 203 | 7 204 | 205 | 206 | 207 | 验证集路径 208 | 209 | 210 | 211 | 212 | 213 | 530 214 | 100 215 | 61 216 | 21 217 | 218 | 219 | 220 | 221 | 微软雅黑 222 | 7 223 | 224 | 225 | 226 | border:2px groove rgb(94, 139, 126);border-radius:10px;padding:2px 4px; 227 | 228 | 229 | 浏览 230 | 231 | 232 | 233 | 234 | 235 | 480 236 | 140 237 | 81 238 | 51 239 | 240 | 241 | 242 | 243 | 微软雅黑 244 | 7 245 | 246 | 247 | 248 | QPushButton#pushButton_starttrain {border:2px groove rgb(94, 139, 126);border-radius:10px;padding:2px 4px;} 249 | 250 | 251 | 252 | 开始训练 253 | 254 | 255 | 256 | 257 | 258 | 440 259 | 9 260 | 131 261 | 20 262 | 263 | 264 | 265 | 266 | 微软雅黑 267 | 7 268 | 269 | 270 | 271 | border:2px groove; 272 | border-color: rgb(153, 204, 204); 273 | 274 | 275 | 16 276 | 277 | 278 | 279 | 280 | 281 | 30 282 | 9 283 | 41 284 | 21 285 | 286 | 287 | 288 | 289 | 微软雅黑 290 | 7 291 | 292 | 293 | 294 | 训练代数 295 | 296 | 297 | 298 | 299 | 300 | 390 301 | 9 302 | 41 303 | 21 304 | 305 | 306 | 307 | 308 | 微软雅黑 309 | 7 310 | 311 | 312 | 313 | 批次大小 314 | 315 | 316 | 317 | 318 | 319 | 80 320 | 9 321 | 131 322 | 20 323 | 324 | 325 | 326 | 327 | 微软雅黑 328 | 7 329 | 330 | 331 | 332 | border:2px groove; 333 | border-color: rgb(153, 204, 204); 334 | 335 | 336 | 70 337 | 338 | 339 | 340 | 341 | 342 | 30 343 | 50 344 | 41 345 | 21 346 | 347 | 348 | 349 | 350 | 微软雅黑 351 | 7 352 | 353 | 354 | 355 | 特征数目 356 | 357 | 358 | 359 | 360 | 361 | 440 362 | 50 363 | 131 364 | 20 365 | 366 | 367 | 368 | 369 | 微软雅黑 370 | 7 371 | 372 | 373 | 374 | border:2px groove; 375 | border-color: rgb(153, 204, 204); 376 | 377 | 378 | 8 379 | 380 | 381 | false 382 | 383 | 384 | 385 | 386 | 387 | 390 388 | 50 389 | 41 390 | 21 391 | 392 | 393 | 394 | 395 | 微软雅黑 396 | 7 397 | 398 | 399 | 400 | 分类数目 401 | 402 | 403 | 404 | 405 | 406 | 80 407 | 50 408 | 131 409 | 20 410 | 411 | 412 | 413 | 414 | 微软雅黑 415 | 7 416 | 417 | 418 | 419 | border:2px groove; 420 | border-color: rgb(153, 204, 204); 421 | 422 | 423 | 12 424 | 425 | 426 | false 427 | 428 | 429 | 430 | 431 | 432 | 30 433 | 180 434 | 91 435 | 21 436 | 437 | 438 | 439 | 440 | 微软雅黑 441 | 7 442 | 443 | 444 | 445 | 保存本次训练结果 446 | 447 | 448 | 449 | 450 | 451 | 452 | 10 453 | 10 454 | 601 455 | 31 456 | 457 | 458 | 459 | 460 | 微软雅黑 461 | 11 462 | 75 463 | true 464 | 465 | 466 | 467 | color: rgb(47, 93, 98); 468 | border-style:solid; 469 | border-bottom-width:2px; 470 | 471 | 472 | 模型设置 473 | 474 | 475 | Qt::AlignCenter 476 | 477 | 478 | 479 | 480 | 481 | 10 482 | 310 483 | 601 484 | 151 485 | 486 | 487 | 488 | QWidget{background-color: rgb(167, 196, 188);} 489 | .QWidget{border:2px groove gray;border-radius:10px;padding:2px 4px;} 490 | 491 | 492 | 493 | 494 | 90 495 | 10 496 | 111 497 | 20 498 | 499 | 500 | 501 | 502 | 微软雅黑 503 | 7 504 | 505 | 506 | 507 | border:2px groove; 508 | border-color: rgb(153, 204, 204); 509 | 510 | 511 | 512 | 513 | 514 | true 515 | 516 | 517 | 518 | 519 | 520 | 30 521 | 10 522 | 51 523 | 21 524 | 525 | 526 | 527 | 528 | 微软雅黑 529 | 7 530 | 531 | 532 | 533 | 训练准确率 534 | 535 | 536 | 537 | 538 | 539 | 460 540 | 10 541 | 111 542 | 20 543 | 544 | 545 | 546 | 547 | 微软雅黑 548 | 7 549 | 550 | 551 | 552 | border:2px groove; 553 | border-color: rgb(153, 204, 204); 554 | 555 | 556 | true 557 | 558 | 559 | 560 | 561 | 562 | 400 563 | 10 564 | 51 565 | 21 566 | 567 | 568 | 569 | 570 | 微软雅黑 571 | 7 572 | 573 | 574 | 575 | 验证准确率 576 | 577 | 578 | 579 | 580 | 581 | 400 582 | 50 583 | 41 584 | 21 585 | 586 | 587 | 588 | 589 | 微软雅黑 590 | 7 591 | 592 | 593 | 594 | 验证损失 595 | 596 | 597 | 598 | 599 | 600 | 90 601 | 50 602 | 111 603 | 20 604 | 605 | 606 | 607 | 608 | 微软雅黑 609 | 7 610 | 611 | 612 | 613 | border:2px groove; 614 | border-color: rgb(153, 204, 204); 615 | 616 | 617 | 618 | 619 | 620 | true 621 | 622 | 623 | 624 | 625 | 626 | 30 627 | 50 628 | 41 629 | 21 630 | 631 | 632 | 633 | 634 | 微软雅黑 635 | 7 636 | 637 | 638 | 639 | 训练损失 640 | 641 | 642 | 643 | 644 | 645 | 460 646 | 50 647 | 111 648 | 20 649 | 650 | 651 | 652 | 653 | 微软雅黑 654 | 7 655 | 656 | 657 | 658 | border:2px groove; 659 | border-color: rgb(153, 204, 204); 660 | 661 | 662 | 663 | 664 | 665 | true 666 | 667 | 668 | 669 | 670 | 671 | 220 672 | 80 673 | 41 674 | 21 675 | 676 | 677 | 678 | 679 | 微软雅黑 680 | 7 681 | 682 | 683 | 684 | 训练用时 685 | 686 | 687 | 688 | 689 | 690 | 270 691 | 80 692 | 111 693 | 20 694 | 695 | 696 | 697 | 698 | 微软雅黑 699 | 7 700 | 701 | 702 | 703 | border:2px groove; 704 | border-color: rgb(153, 204, 204); 705 | 706 | 707 | 708 | 709 | 710 | true 711 | 712 | 713 | 714 | 715 | 716 | 260 717 | 110 718 | 91 719 | 31 720 | 721 | 722 | 723 | 724 | 微软雅黑 725 | 7 726 | 727 | 728 | 729 | border:2px groove rgb(94, 139, 126);border-radius:10px;padding:2px 4px; 730 | 731 | 732 | 查看训练过程 733 | 734 | 735 | 736 | 737 | 738 | 739 | 10 740 | 270 741 | 601 742 | 31 743 | 744 | 745 | 746 | 747 | 微软雅黑 748 | 11 749 | 75 750 | true 751 | 752 | 753 | 754 | color: rgb(47, 93, 98); 755 | border-style:solid; 756 | border-bottom-width:2px; 757 | 758 | 759 | 训练结果 760 | 761 | 762 | Qt::AlignCenter 763 | 764 | 765 | 766 | 767 | 768 | 10 769 | 510 770 | 601 771 | 141 772 | 773 | 774 | 775 | QWidget{background-color: rgb(167, 196, 188);} 776 | .QWidget{border:2px groove gray;border-radius:10px;padding:2px 4px;} 777 | 778 | 779 | 780 | 781 | 782 | 783 | 340 784 | 60 785 | 51 786 | 21 787 | 788 | 789 | 790 | 791 | 微软雅黑 792 | 7 793 | 794 | 795 | 796 | 测试准确率 797 | 798 | 799 | 800 | 801 | 802 | 140 803 | 64 804 | 111 805 | 20 806 | 807 | 808 | 809 | 810 | 微软雅黑 811 | 7 812 | 813 | 814 | 815 | border:2px groove; 816 | border-color: rgb(153, 204, 204); 817 | 818 | 819 | 820 | 821 | 822 | true 823 | 824 | 825 | 826 | 827 | 828 | 90 829 | 60 830 | 41 831 | 21 832 | 833 | 834 | 835 | 836 | 微软雅黑 837 | 7 838 | 839 | 840 | 841 | 测试损失 842 | 843 | 844 | 845 | 846 | 847 | 400 848 | 60 849 | 111 850 | 20 851 | 852 | 853 | 854 | 855 | 微软雅黑 856 | 7 857 | 858 | 859 | 860 | border:2px groove; 861 | border-color: rgb(153, 204, 204); 862 | 863 | 864 | 865 | 866 | 867 | true 868 | 869 | 870 | 871 | 872 | 873 | 30 874 | 680 875 | 751 876 | 191 877 | 878 | 879 | 880 | 881 | 882 | 460 883 | 130 884 | 75 885 | 21 886 | 887 | 888 | 889 | 890 | 微软雅黑 891 | 892 | 893 | 894 | 验证损失 895 | 896 | 897 | 898 | 899 | 900 | 150 901 | 130 902 | 131 903 | 24 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 70 914 | 120 915 | 75 916 | 21 917 | 918 | 919 | 920 | 921 | 微软雅黑 922 | 923 | 924 | 925 | 训练损失 926 | 927 | 928 | 929 | 930 | 931 | 540 932 | 130 933 | 131 934 | 24 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 80 945 | 30 946 | 211 947 | 24 948 | 949 | 950 | 951 | 952 | 953 | 954 | 10 955 | 30 956 | 75 957 | 21 958 | 959 | 960 | 961 | 962 | 微软雅黑 963 | 964 | 965 | 966 | 加载模型 967 | 968 | 969 | 970 | 971 | 972 | 300 973 | 30 974 | 93 975 | 28 976 | 977 | 978 | 979 | 浏览 980 | 981 | 982 | 983 | 984 | 985 | 986 | 390 987 | 20 988 | 131 989 | 20 990 | 991 | 992 | 993 | 994 | 微软雅黑 995 | 7 996 | 997 | 998 | 999 | Qt::StrongFocus 1000 | 1001 | 1002 | border:2px groove; 1003 | border-color: rgb(153, 204, 204); 1004 | 1005 | 1006 | true 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 50 1013 | 20 1014 | 131 1015 | 20 1016 | 1017 | 1018 | 1019 | 1020 | 微软雅黑 1021 | 7 1022 | 1023 | 1024 | 1025 | border:2px groove; 1026 | border-color: rgb(153, 204, 204); 1027 | 1028 | 1029 | true 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 530 1036 | 20 1037 | 61 1038 | 21 1039 | 1040 | 1041 | 1042 | 1043 | 微软雅黑 1044 | 7 1045 | 1046 | 1047 | 1048 | border:2px groove rgb(94, 139, 126);border-radius:10px;padding:2px 4px; 1049 | 1050 | 1051 | 浏览 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 10 1058 | 20 1059 | 41 1060 | 21 1061 | 1062 | 1063 | 1064 | 1065 | 微软雅黑 1066 | 7 1067 | 1068 | 1069 | 1070 | 加载模型 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 190 1077 | 20 1078 | 61 1079 | 21 1080 | 1081 | 1082 | 1083 | 1084 | 微软雅黑 1085 | 7 1086 | 1087 | 1088 | 1089 | border:2px groove rgb(94, 139, 126);border-radius:10px;padding:2px 4px; 1090 | 1091 | 1092 | 浏览 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 340 1099 | 20 1100 | 51 1101 | 21 1102 | 1103 | 1104 | 1105 | 1106 | 微软雅黑 1107 | 7 1108 | 1109 | 1110 | 1111 | 测试集路径 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 10 1118 | 60 1119 | 71 1120 | 28 1121 | 1122 | 1123 | 1124 | 1125 | 微软雅黑 1126 | 7 1127 | 1128 | 1129 | 1130 | border:2px groove rgb(94, 139, 126);border-radius:10px;padding:2px 4px; 1131 | 1132 | 1133 | 全集测试 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 10 1140 | 100 1141 | 71 1142 | 28 1143 | 1144 | 1145 | 1146 | 1147 | 微软雅黑 1148 | 7 1149 | 1150 | 1151 | 1152 | border:2px groove rgb(94, 139, 126);border-radius:10px;padding:2px 4px; 1153 | 1154 | 1155 | 随机测试 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 140 1162 | 100 1163 | 111 1164 | 20 1165 | 1166 | 1167 | 1168 | 1169 | 微软雅黑 1170 | 7 1171 | 1172 | 1173 | 1174 | border:2px groove; 1175 | border-color: rgb(153, 204, 204); 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | true 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 400 1188 | 100 1189 | 111 1190 | 20 1191 | 1192 | 1193 | 1194 | 1195 | 微软雅黑 1196 | 7 1197 | 1198 | 1199 | 1200 | border:2px groove; 1201 | border-color: rgb(153, 204, 204); 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | true 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 90 1214 | 100 1215 | 41 1216 | 21 1217 | 1218 | 1219 | 1220 | 1221 | 微软雅黑 1222 | 7 1223 | 1224 | 1225 | 1226 | 检测结果 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 340 1233 | 100 1234 | 41 1235 | 21 1236 | 1237 | 1238 | 1239 | 1240 | 微软雅黑 1241 | 7 1242 | 1243 | 1244 | 1245 | 真实结果 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 10 1253 | 470 1254 | 601 1255 | 31 1256 | 1257 | 1258 | 1259 | 1260 | 微软雅黑 1261 | 11 1262 | 75 1263 | true 1264 | 1265 | 1266 | 1267 | color: rgb(47, 93, 98); 1268 | border-style:solid; 1269 | border-bottom-width:2px; 1270 | 1271 | 1272 | 模型测试 1273 | 1274 | 1275 | Qt::AlignCenter 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | background-color:rgb(239, 245, 235); 1282 | 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | --------------------------------------------------------------------------------