├── __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 |
--------------------------------------------------------------------------------