初始化仓库
This commit is contained in:
commit
136e20f31a
185
adv_training.py
Normal file
185
adv_training.py
Normal file
@ -0,0 +1,185 @@
|
||||
from models import ResNet, ConvNet
|
||||
import torch.nn as nn
|
||||
import argparse
|
||||
from utils import UcrDataset, UCR_dataloader, AdvDataset
|
||||
import torch.optim as optim
|
||||
import torch.utils.data
|
||||
import os
|
||||
import random
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('--test', action='store_true', help='')
|
||||
parser.add_argument('--query_one', action='store_true', help='query the probability of target idx sample')
|
||||
parser.add_argument('--idx', type=int, help='the index of test sample ')
|
||||
parser.add_argument('--gpu', type=str, default='0', help='the index of test sample ')
|
||||
parser.add_argument('--channel_last', type=bool, default=True, help='the channel of data is last or not')
|
||||
parser.add_argument('--n_class', type=int, default=3, help='the class number of dataset')
|
||||
parser.add_argument('--epochs', type=int, default=1500, help='number of epochs to train for')
|
||||
parser.add_argument('--e', default=1499, help='number of epochs to train for')
|
||||
parser.add_argument('--lr', type=float, default=0.0002, help='learning rate, default=0.0002')
|
||||
parser.add_argument('--cuda', action='store_false', help='enables cuda')
|
||||
parser.add_argument('--checkpoints_folder', default='model_checkpoints', help='folder to save checkpoints')
|
||||
parser.add_argument('--manualSeed', type=int, help='manual seed')
|
||||
parser.add_argument('--run_tag', default='StarLightCurves', help='tags for the current run')
|
||||
parser.add_argument('--model', default='f', help='the model type(ResNet,FCN)')
|
||||
parser.add_argument('--normalize', action='store_true', help='')
|
||||
parser.add_argument('--checkpoint_every', default=5, help='number of epochs after which saving checkpoints')
|
||||
opt = parser.parse_args()
|
||||
|
||||
print(opt)
|
||||
# configure cuda
|
||||
if torch.cuda.is_available() and not opt.cuda:
|
||||
os.environ["CUDA_VISIBLE_DEVICES"] = opt.gpu
|
||||
print("You have a cuda device, so you might want to run with --cuda as option")
|
||||
|
||||
device = torch.device("cuda:0" if opt.cuda else "cpu")
|
||||
if opt.manualSeed is None:
|
||||
opt.manualSeed = random.randint(1, 10000)
|
||||
print("Random Seed: ", opt.manualSeed)
|
||||
random.seed(opt.manualSeed)
|
||||
torch.manual_seed(opt.manualSeed)
|
||||
|
||||
|
||||
def train(l,e):
|
||||
os.makedirs(opt.checkpoints_folder, exist_ok=True)
|
||||
os.makedirs('%s/%s' % (opt.checkpoints_folder, opt.run_tag), exist_ok=True)
|
||||
#这里是获得的train数据
|
||||
dataset_path = 'data/' + opt.run_tag + '/' + opt.run_tag + '_TRAIN.txt'
|
||||
dataset = UcrDataset(dataset_path, channel_last=opt.channel_last, normalize=True)
|
||||
#这里是result里面的攻击时间序列数据,对抗训练
|
||||
# attacked_data_path = 'final_result/' + opt.run_tag + '/' + 'attack_time_series.txt' #攻击的时间序列
|
||||
# attacked_dataset = AdvDataset(txt_file=attacked_data_path)
|
||||
#batch数值小于等于16(这里是10)
|
||||
batch_size = int(min(len(dataset) / 10, 16))
|
||||
#batch_size = 64
|
||||
print('dataset length: ', len(dataset))
|
||||
# print('number of adv examples:', len(attacked_dataset))
|
||||
print('batch size:', batch_size)
|
||||
#这里batch数值是10
|
||||
dataloader = UCR_dataloader(dataset, batch_size)
|
||||
# adv_dataloader = UCR_dataloader(attacked_dataset, batch_size)
|
||||
|
||||
seq_len = dataset.get_seq_len()
|
||||
n_class = opt.n_class
|
||||
print('sequence len:', seq_len)
|
||||
if opt.model == 'r':
|
||||
net = ResNet(n_in=seq_len, n_classes=n_class).to(device)
|
||||
if opt.model == 'f':
|
||||
net = ConvNet(n_in=seq_len, n_classes=n_class).to(device)
|
||||
net.train()
|
||||
criterion = nn.CrossEntropyLoss().to(device)
|
||||
optimizer = optim.Adam(net.parameters(), lr=opt.lr)
|
||||
print('#############!! Start to Train!! ###############')
|
||||
#opt.epochs=100(原来等于1499,别忘了改回去)
|
||||
for epoch in range(opt.epochs):
|
||||
for i, (data, label) in enumerate(dataloader):
|
||||
if data.size(0) != batch_size:
|
||||
break
|
||||
data = data.float()
|
||||
data = data.to(device)
|
||||
label = label.long()
|
||||
label = label.to(device)
|
||||
|
||||
optimizer.zero_grad()
|
||||
output = net(data)
|
||||
loss = criterion(output, label.view(label.size(0)))
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
print('#######!!!Train!!!########')
|
||||
print('[%d/%d][%d/%d] Loss: %.4f ' % (epoch, opt.epochs, i + 1, len(dataloader), loss.item()))
|
||||
if (epoch % (opt.checkpoint_every * 10) == 0) or (epoch == (opt.epochs - 1)):
|
||||
print('Saving the %dth epoch model.....' % epoch)
|
||||
#训练完保存模型
|
||||
torch.save(net, '%s/%s/pre_%s%depoch.pth' % (opt.checkpoints_folder, opt.run_tag, opt.model, epoch))
|
||||
if (epoch % 10 == 0):
|
||||
l.append(loss.item())
|
||||
e.append(epoch)
|
||||
|
||||
|
||||
def te():
|
||||
data_path = 'data/' + opt.run_tag + '/' + opt.run_tag + '_TEST.txt'
|
||||
dataset = UcrDataset(data_path, channel_last=opt.channel_last, normalize=opt.normalize)
|
||||
batch_size = int(min(len(dataset) / 10, 16))
|
||||
print('dataset length: ', len(dataset))
|
||||
print('batch_size:', batch_size)
|
||||
dataloader = UCR_dataloader(dataset, batch_size)
|
||||
type = opt.model
|
||||
model_path = 'model_checkpoints/' + opt.run_tag + '/pre_' + type + str(opt.e) + 'epoch.pth'
|
||||
#model_path ='model_checkpoints/' + opt.run_tag + '/pre_fTrained.pth'
|
||||
model = torch.load(model_path, map_location='cuda:0')
|
||||
|
||||
with torch.no_grad():
|
||||
model.eval()
|
||||
total = 0
|
||||
correct = 0
|
||||
for i, (data, label) in enumerate(dataloader):
|
||||
|
||||
data = data.float()
|
||||
data = data.to(device)
|
||||
label = label.long()
|
||||
label = label.to(device)
|
||||
label = label.view(label.size(0))
|
||||
total += label.size(0)
|
||||
out = model(data).cuda()
|
||||
softmax = nn.Softmax(dim=-1)
|
||||
prob = softmax(out)
|
||||
pred_label = torch.argmax(prob, dim=1)
|
||||
|
||||
correct += (pred_label == label).sum().item()
|
||||
|
||||
print('The TEST Accuracy of %s is : %.2f %%' % (data_path, correct / total * 100))
|
||||
|
||||
|
||||
def query_one(idx):
|
||||
data_path = 'data/' + opt.run_tag + '/' + opt.run_tag + '_TEST.txt'
|
||||
test_data = np.loadtxt(data_path)
|
||||
test_data = torch.from_numpy(test_data)
|
||||
|
||||
test_one = test_data[idx]
|
||||
|
||||
X = test_one[1:].float()
|
||||
X = X.to(device)
|
||||
y = test_one[0].long() - 1
|
||||
y = y.to(device)
|
||||
if y < 0:
|
||||
y = opt.n_class - 1
|
||||
print('ground truth:', y)
|
||||
type = opt.model
|
||||
model_path = 'model_checkpoints/' + opt.run_tag + '/pre_' + type + str(opt.e) + 'epoch.pth'
|
||||
#model_path = 'model_checkpoints/' + opt.run_tag + '/pre_fTrained.pth'
|
||||
model = torch.load(model_path, map_location='cpu')
|
||||
model.eval()
|
||||
|
||||
out = model(X)
|
||||
softmax = nn.Softmax(dim=-1)
|
||||
prob_vector = softmax(out)
|
||||
print('prob vector:', prob_vector)
|
||||
prob = prob_vector.view(opt.n_class)[y].item()
|
||||
|
||||
print('Confidence in true class of the %d sample is %.4f ' % (idx, prob))
|
||||
|
||||
def plot1(model,loss,epoch):
|
||||
plt.title('The loss of traing '+opt.run_tag+'model', fontstyle='italic')
|
||||
plt.figure(figsize=(6, 4))
|
||||
plt.plot(epoch,loss, color='b', label='loss')
|
||||
plt.xlabel('epoch', fontsize=12)
|
||||
plt.legend(loc='upper right', fontsize=8)
|
||||
#plt.savefig('loss' + model+'.png')
|
||||
plt.show()
|
||||
|
||||
if __name__ == '__main__':
|
||||
# if opt.test:
|
||||
# ce()
|
||||
# elif opt.query_one:
|
||||
# query_one(opt.idx)
|
||||
# else:
|
||||
# train()
|
||||
|
||||
l = []
|
||||
e = []
|
||||
train(l,e)
|
||||
# plot1(opt.model,l,e)
|
||||
te()
|
294
analyzeTool.py
Normal file
294
analyzeTool.py
Normal file
@ -0,0 +1,294 @@
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def analyze_info_tool(info_index=1, pattern=r'result_\d+\.\d+_\d+_*', parent_folder='./'):
|
||||
for folder in os.listdir(parent_folder):
|
||||
# 使用正则表达式匹配文件夹名
|
||||
if re.match(pattern, folder):
|
||||
folder_path = os.path.join(parent_folder, folder)
|
||||
|
||||
# 对结果遍历 result_0.04_9_r/下文件
|
||||
analyze_one_folder(info_index, folder_path)
|
||||
|
||||
|
||||
def analyze_multiple_folders(folder_paths, info_index=1, restore=True):
|
||||
"""
|
||||
分析多个指定文件夹中的数据文件,提取并计算指标信息。
|
||||
|
||||
参数:
|
||||
folder_paths (list): 要分析的文件夹路径列表
|
||||
info_index (int): 要分析的第几个结果,默认为 1,指的是information文件下的第i条记录
|
||||
restore (bool): 是否将结果保存为 CSV 文件,默认为 True。如果为 False,则打印结果
|
||||
|
||||
返回:
|
||||
pandas.DataFrame: 包含所有分析结果的DataFrame
|
||||
"""
|
||||
# 结果存储
|
||||
all_results = []
|
||||
|
||||
for folder_path in folder_paths:
|
||||
# 对每个文件夹进行分析
|
||||
results = analyze_one_folder(info_index, folder_path, restore=False)
|
||||
all_results.extend(results)
|
||||
|
||||
# 创建DataFrame
|
||||
df = pd.DataFrame(all_results, columns=['Dataset', 'Accuracy', 'ANI', 'MSE', 'Queries'])
|
||||
|
||||
if restore:
|
||||
# 获取当前的日期和时间
|
||||
now = datetime.now()
|
||||
# 按照指定的格式生成文件名
|
||||
results_filename = f"multiple_folders_analysis_{now.year}-{now.month:02d}-{now.day:02d}-{now.hour:02d}-{now.minute:02d}-{now.second:02d}.csv"
|
||||
df.to_csv(results_filename, index=False)
|
||||
print(f"Results saved to {results_filename}")
|
||||
else:
|
||||
for result in all_results:
|
||||
dataset_name, acc, ani, mse, queries = result
|
||||
print(f'{dataset_name}\n'
|
||||
f'\t Acc:{acc}\n'
|
||||
f'\t ANI:{ani}\n'
|
||||
f'\t MSE:{mse}\n'
|
||||
f'\t Que:{queries}\n')
|
||||
|
||||
return df
|
||||
|
||||
def analyze_one_folder(info_index=1, folder_path='./', restore=False):
|
||||
"""
|
||||
分析指定文件夹中的数据文件,提取并计算指标信息。
|
||||
|
||||
参数:
|
||||
info_index (int): 要分析的第几个结果,默认为 1,指的是information文件下的第i条记录。
|
||||
folder_path (str): 要分析的文件夹路径,默认为当前文件夹 ('./')。
|
||||
restore (bool): 是否将结果保存为 CSV 文件,默认为 False。
|
||||
|
||||
返回:
|
||||
list: 包含分析结果的列表,每个元素是一个元组 (dataset_name, acc, ani, mse, queries)
|
||||
"""
|
||||
# 结果存储
|
||||
results = []
|
||||
|
||||
for root, dirs, files in os.walk(folder_path):
|
||||
# 跳过所有figures文件夹
|
||||
if re.match(r'\*/figures\d+', root):
|
||||
continue
|
||||
|
||||
# 存储匹配到的信息
|
||||
successful_samples_list = [] # 成功样本数
|
||||
ani_list = [] # ANI值
|
||||
mse_list = [] # MSE值
|
||||
queries_list = [] # queries值
|
||||
correctly_classified_samples_list = [] # 总样本数
|
||||
|
||||
for file in files:
|
||||
# 筛选子文件夹内所有information*文件
|
||||
if re.match(r'information\d', file):
|
||||
# 打开文件并读取内容
|
||||
with open(os.path.join(root, file), 'r', errors='replace') as f:
|
||||
s = f.read()
|
||||
|
||||
# 匹配Successful samples,ANI,MSE,queries的模式
|
||||
pattern_successful = r'Successful samples:\s*(\d+)'
|
||||
pattern_ani = r'ANI:(\d+\.\d+)'
|
||||
pattern_mse = r'MSE:(\d+\.\d+)'
|
||||
pattern_queries = r'Mean queries:(\d+\.\d+)'
|
||||
pattern_correctly_classified_samples = r'Correctly-classified samples:\s*(\d+)'
|
||||
|
||||
# 使用正则表达式匹配模式
|
||||
successful_match = re.finditer(pattern_successful, s)
|
||||
ani_match = re.finditer(pattern_ani, s)
|
||||
mse_match = re.finditer(pattern_mse, s)
|
||||
queries_match = re.finditer(pattern_queries, s)
|
||||
correctly_classified_samples_match = re.finditer(pattern_correctly_classified_samples, s)
|
||||
|
||||
try:
|
||||
successful_samples = None
|
||||
ani = None
|
||||
mse = None
|
||||
queries = None
|
||||
correctly_classified_samples = None
|
||||
|
||||
for _ in range(info_index): # 想要分析的第几个结果
|
||||
successful_samples = next(successful_match).group(1)
|
||||
ani = next(ani_match).group(1)
|
||||
mse = next(mse_match).group(1)
|
||||
queries = next(queries_match).group(1)
|
||||
correctly_classified_samples = next(correctly_classified_samples_match).group(1)
|
||||
|
||||
successful_samples_list.append(successful_samples)
|
||||
ani_list.append(ani)
|
||||
mse_list.append(mse)
|
||||
queries_list.append(queries)
|
||||
correctly_classified_samples_list.append(correctly_classified_samples)
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
ani_value = 0 # 总ani权值
|
||||
mse_value = 0 # 总mse权值
|
||||
queries_value = 0 # 总queries权值
|
||||
successful_samples_counts = 0 # 成功样本数
|
||||
correct_samples_counts = 0 # 总样本数
|
||||
|
||||
for i in range(len(successful_samples_list)):
|
||||
# 跳过全部失败结果
|
||||
if successful_samples_list[i] is None or ani_list[i] is None or mse_list[i] is None:
|
||||
continue
|
||||
|
||||
mse_value += float(successful_samples_list[i]) * float(mse_list[i])
|
||||
ani_value += float(successful_samples_list[i]) * float(ani_list[i])
|
||||
queries_value += float(successful_samples_list[i]) * float(queries_list[i])
|
||||
successful_samples_counts += float(successful_samples_list[i])
|
||||
correct_samples_counts += float(correctly_classified_samples_list[i])
|
||||
|
||||
# 保存结果
|
||||
if successful_samples_counts > 0:
|
||||
# 数据集名称是文件夹的最后两个部分
|
||||
# dataset_name = os.path.basename(os.path.dirname(root)) + '_' + os.path.basename(root)
|
||||
# 数据集名称是文件夹的倒数第两个部分
|
||||
# dataset_name = os.path.basename(os.path.dirname(root))
|
||||
# 数据集名称是文件夹的最后一个部分
|
||||
dataset_name = os.path.basename(root)
|
||||
acc = successful_samples_counts / correct_samples_counts
|
||||
ani = ani_value / successful_samples_counts
|
||||
mse = mse_value / successful_samples_counts
|
||||
queries = queries_value / successful_samples_counts
|
||||
|
||||
results.append((dataset_name, acc, ani, mse, queries))
|
||||
|
||||
if restore:
|
||||
df = pd.DataFrame(results, columns=['Dataset', 'Accuracy', 'ANI', 'MSE', 'Queries'])
|
||||
# 获取当前的日期和时间
|
||||
now = datetime.now()
|
||||
# 按照指定的格式生成文件名
|
||||
results_filename = f"analyze_result_{now.year}-{now.month:02d}-{now.day:02d}-{now.hour:02d}-{now.minute:02d}-{now.second:02d}.csv"
|
||||
df.to_csv(results_filename, index=False)
|
||||
else:
|
||||
for dataset_name, acc, ani, mse, queries in results:
|
||||
print(f'{dataset_name}\n'
|
||||
f'\t Acc:{acc}\n'
|
||||
f'\t ANI:{ani}\n'
|
||||
f'\t MSE:{mse}\n'
|
||||
f'\t Que:{queries}\n')
|
||||
|
||||
return results
|
||||
|
||||
def count_classes_samples(folder_path, select_colum='Success'):
|
||||
"""
|
||||
根据给定文件夹路径,分析包含的information*文件,统计文件中第4列和第5列的元组出现个数,
|
||||
仅在第9列的值为'Success'时统计。
|
||||
|
||||
:param select_colum: 选择统计的第九列类别
|
||||
:param folder_path: 被分析的文件夹根目录
|
||||
:return: 元组出现次数的二维数组
|
||||
"""
|
||||
key_pair_counts = {}
|
||||
|
||||
for root, dirs, files in os.walk(folder_path):
|
||||
for file in files:
|
||||
# 筛选子文件夹内所有information*文件
|
||||
if re.match(r'information\d', file):
|
||||
# 打开文件并读取内容
|
||||
with open(os.path.join(root, file), 'r') as f:
|
||||
data = f.read()
|
||||
|
||||
# 将数据拆分成行并解析成列表
|
||||
lines = data.strip().split('\n')
|
||||
records = [line.split() for line in lines if len(line.split()) > 8] # 确保至少有9列
|
||||
|
||||
# 统计第4列和第5列的键对值出现次数,仅在第9列为'select_colum'时统计,默认Success
|
||||
for record in records:
|
||||
if record[8] == select_colum:
|
||||
key_pair = (int(record[3]), int(record[4]))
|
||||
if key_pair in key_pair_counts:
|
||||
key_pair_counts[key_pair] += 1
|
||||
else:
|
||||
key_pair_counts[key_pair] = 1
|
||||
|
||||
# 将结果转换为二维数组
|
||||
result_array = [[key_pair[0], key_pair[1], count] for key_pair, count in key_pair_counts.items()]
|
||||
|
||||
return result_array
|
||||
|
||||
|
||||
def generate_heat_maps_array(data, default_value=0, classes_size=None):
|
||||
"""
|
||||
根据给定的数据生成一个二维数组。规则是对于每个元组,例如[6, 1, 1],
|
||||
将生成的二维数组array[6][1]设置为1。
|
||||
|
||||
:param classes_size: 元组维度
|
||||
:param data: 包含元组的列表,每个元组包含三个整数(行索引,列索引,值)。
|
||||
:param default_value: 生成的二维数组的默认值,默认为0。
|
||||
:return: 生成的二维数组。
|
||||
"""
|
||||
# 找到二维数组的大小
|
||||
if classes_size is not None:
|
||||
max_row = max_col = classes_size
|
||||
else:
|
||||
max_row = max(item[0] for item in data) + 1
|
||||
max_col = max(item[1] for item in data) + 1
|
||||
|
||||
# 初始化二维数组
|
||||
array = [[default_value for _ in range(max_col)] for _ in range(max_row)]
|
||||
|
||||
# 设置数组中的指定值
|
||||
for row, col, value in data:
|
||||
array[col][row] = value
|
||||
|
||||
return array
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 定义要分析的实验结果文件夹路径列表
|
||||
experiment_folders = [
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/Car",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/Wafer",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/ItalyPowerDemand",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/AllGestureWiimoteY",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/NonIFECGTho2",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/Trace",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/PigAirwayPressure",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/GesturePebbleZ2",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/AllGestureWiimoteX",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/FordA",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/DodgerLoopDay",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/SonyAIBORobotSurface1",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/PigArtPressure",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/MoteStrain",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/ECGFiveDays",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/PickupGeWZ",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/FreezerSmallTrain",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/TwoLeadECG",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/Lightning7",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/Phoneme",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/DodgerLoopWeekend",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/ECG5000",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/ShakeGestureWiimoteZ",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/GesturePebbleZ1",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/NonIFECGTho1",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/AllGestureWiimoteZ",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/FordB",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/InsectWingbeatSound",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/EOGHorizontalSignal",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/ChlorineConcentration",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/Plane",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/EOGVerticalSignal",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/DodgerLoopGame",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/ECG200",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/Fungi",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/CinCEC",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/SonyAIBORobotSurface2",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/Lightning2",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/FreezerRegularTrain",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/StarLightCurves",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/Earthquakes",
|
||||
"/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/model_f/PigCVP",
|
||||
]
|
||||
|
||||
# 分析所有文件夹并将结果保存到单个CSV文件中
|
||||
results_df = analyze_multiple_folders(experiment_folders)
|
||||
|
||||
# 如果想查看结果但不保存CSV,可以使用:
|
||||
# results_df = analyze_multiple_folders(experiment_folders, restore=False)
|
112
attack.py
Normal file
112
attack.py
Normal file
@ -0,0 +1,112 @@
|
||||
import argparse
|
||||
import numpy as np
|
||||
import os
|
||||
import time
|
||||
import torch
|
||||
from attacker import Attacker
|
||||
|
||||
def attack_process(opt):
|
||||
try:
|
||||
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
# device = 'cpu'
|
||||
print(device)
|
||||
#device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
||||
# os.makedirs('result_%s_%d_%s/%s/figures%s' % (str(opt.magnitude_factor), opt.topk,
|
||||
# opt.model, opt.run_tag,opt.gpu), exist_ok=True)
|
||||
os.makedirs('result_%s_%s/%s/figures%s' % (str(opt.magnitude_factor),
|
||||
opt.model, opt.run_tag, opt.gpu), exist_ok=True)
|
||||
|
||||
data_path = 'data/' + opt.run_tag + '/' + opt.run_tag + '_attack'+opt.gpu+'.txt'
|
||||
|
||||
test_data = np.loadtxt(data_path)
|
||||
size = test_data.shape[0]-1
|
||||
idx_array = np.arange(size)
|
||||
attacker = Attacker(run_tag=opt.run_tag, e=opt.e,
|
||||
model_type=opt.model, cuda=opt.cuda, normalize=opt.normalize, device=device, gpu=opt.gpu, classes=opt.classes)
|
||||
# record of the running time
|
||||
start_time = time.time()
|
||||
# count the number of the successful instances, mse,iterations,queries
|
||||
success_cnt = 0
|
||||
right_cnt = 0
|
||||
total_mse = 0
|
||||
total_iterations = 0
|
||||
total_quries = 0
|
||||
for idx in idx_array:
|
||||
print('###Start %s : generating adversarial example of the %d sample ###' % (opt.run_tag, idx))
|
||||
ori_ts, attack_ts, info = attacker.attack(sample_idx=idx, target_class=opt.target_class,
|
||||
factor=opt.magnitude_factor, max_iteration=opt.maxitr,
|
||||
popsize=opt.popsize,device=device)
|
||||
|
||||
# only save the successful adversarial example
|
||||
if info[-1] == 'Success':
|
||||
success_cnt = success_cnt + 1
|
||||
total_iterations += info[-2]
|
||||
total_mse += info[-3]
|
||||
total_quries += info[-4]
|
||||
file0 = open('result_' + str(opt.magnitude_factor) + '_' + opt.model
|
||||
+ '/' + opt.run_tag + '/ori_time_series' + str(opt.gpu) + '.txt', 'a+')
|
||||
file0.write('%d %d ' % (idx, info[3]))
|
||||
for i in ori_ts:
|
||||
file0.write('%.4f ' % i)
|
||||
file0.write('\n')
|
||||
file0.close()
|
||||
|
||||
file = open('result_' + str(opt.magnitude_factor) + '_' + opt.model
|
||||
+ '/' + opt.run_tag + '/attack_time_series' + str(opt.gpu) + '.txt', 'a+')
|
||||
file.write('%d %d ' % (idx, info[3]))
|
||||
for i in attack_ts:
|
||||
file.write('%.4f ' % i)
|
||||
file.write('\n')
|
||||
file.close()
|
||||
|
||||
if info[-1] != 'WrongSample':
|
||||
right_cnt += 1
|
||||
|
||||
# Save the returned information, whether the attack was successful or not
|
||||
file = open('result_' + str(opt.magnitude_factor) + '_' + opt.model
|
||||
+ '/' + opt.run_tag + '/information' + opt.gpu + '.txt', 'a+')
|
||||
|
||||
file.write('%d ' % idx)
|
||||
for i in info:
|
||||
if isinstance(i, int):
|
||||
file.write('%d ' % i)
|
||||
elif isinstance(i, float):
|
||||
file.write('%.4f ' % i)
|
||||
else:
|
||||
file.write(str(i) + ' ')
|
||||
file.write('\n')
|
||||
file.close()
|
||||
|
||||
endtime = time.time()
|
||||
total = endtime - start_time
|
||||
# print useful information
|
||||
print('Running time: %.4f ' % total)
|
||||
print('Correctly-classified samples: %d' % right_cnt)
|
||||
print('Successful samples: %d' % success_cnt)
|
||||
print('Success rate:%.2f%%' % (success_cnt / right_cnt * 100))
|
||||
print('Misclassification rate:%.2f%%' % (success_cnt / size * 100))
|
||||
print('ANI: %.2f' % (total_iterations / success_cnt))
|
||||
print('MSE: %.4f' % (total_mse / success_cnt))
|
||||
print('Mean queries:%.2f\n' % (total_quries / success_cnt))
|
||||
|
||||
# save the useful information
|
||||
file = open('result_' + str(opt.magnitude_factor) + '_' + opt.model
|
||||
+ '/' + opt.run_tag + '/information' + opt.gpu + '.txt', 'a+')
|
||||
file.write('Running time:%.4f\n' % total)
|
||||
file.write('Correctly-classified samples: %d' % right_cnt)
|
||||
file.write('Successful samples:%d\n' % success_cnt)
|
||||
file.write('Success rate:%.2f%%' % (success_cnt / right_cnt * 100))
|
||||
file.write('Misclassification rate:%.2f%%\n' % (success_cnt / size * 100))
|
||||
file.write('ANI:%.2f\n' % (total_iterations / success_cnt))
|
||||
file.write('MSE:%.4f\n' % (total_mse / success_cnt))
|
||||
file.write('Mean queries:%.2f\n' % (total_quries / success_cnt))
|
||||
|
||||
file.close()
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
import traceback
|
||||
print("失败:" + str(e))
|
||||
print(traceback.format_exc())
|
||||
return False
|
57
attackData.py
Normal file
57
attackData.py
Normal file
@ -0,0 +1,57 @@
|
||||
import configparser
|
||||
|
||||
|
||||
def read_and_group_data_by_class(input_file):
|
||||
data_by_class = {}
|
||||
with open(input_file + '_attack.txt', 'r') as file:
|
||||
for line in file:
|
||||
parts = line.strip().split()
|
||||
cls = parts[0]
|
||||
if cls not in data_by_class:
|
||||
data_by_class[cls] = []
|
||||
data_by_class[cls].append(parts)
|
||||
return data_by_class
|
||||
|
||||
def split_data(data, n):
|
||||
# 确保即使数据不能均匀分配也能处理
|
||||
total_length = len(data)
|
||||
split_length = max(total_length // n, 1)
|
||||
remainder = total_length % n
|
||||
splits = []
|
||||
start_idx = 0
|
||||
for i in range(n):
|
||||
if i < remainder:
|
||||
end_idx = start_idx + split_length + 1
|
||||
else:
|
||||
end_idx = start_idx + split_length
|
||||
splits.append(data[start_idx:end_idx])
|
||||
start_idx = end_idx
|
||||
return splits
|
||||
|
||||
def write_split_data(split_data_by_class, n, data_path):
|
||||
for i in range(n):
|
||||
output_file = f'{data_path}_attack{i}.txt'
|
||||
with open(output_file, 'w') as f:
|
||||
for cls, data_splits in split_data_by_class.items():
|
||||
if i < len(data_splits): # 检查索引以防止越界
|
||||
for line in data_splits[i]:
|
||||
f.write(" ".join(line) + "\n")
|
||||
|
||||
def split_and_save_data(data_path, n):
|
||||
# Step 1: Read and group data by class
|
||||
data_by_class = read_and_group_data_by_class(data_path)
|
||||
|
||||
# Step 2: Split data for each class
|
||||
split_data_by_class = {cls: split_data(data, n) for cls, data in data_by_class.items()}
|
||||
|
||||
# Step 3: Write split data into files
|
||||
write_split_data(split_data_by_class, n, data_path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 临时添加配置文件类别种类
|
||||
config = configparser.ConfigParser()
|
||||
config.read("run_parallel_config.ini")
|
||||
file_name = config['MODEL']['run_tag']
|
||||
data_path = 'data/' + file_name + '/' + file_name
|
||||
n = 5 # 假设我们想将数据均分到7个文件中,最多7个
|
||||
split_and_save_data(data_path, n)
|
405
attacker.py
Normal file
405
attacker.py
Normal file
@ -0,0 +1,405 @@
|
||||
import warnings
|
||||
|
||||
import matplotlib
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
matplotlib.use('Agg')
|
||||
import numpy as np
|
||||
import torch
|
||||
import pandas as pd
|
||||
import ruptures as rpt
|
||||
from scipy.optimize import differential_evolution
|
||||
from sklearn.metrics import mean_squared_error
|
||||
from query_probability import query_one, load_ucr
|
||||
from pymoo.core.problem import ElementwiseProblem
|
||||
from pymoo.algorithms.soo.nonconvex.pso import PSO
|
||||
from pymoo.optimize import minimize
|
||||
from pymoo.core.callback import Callback
|
||||
warnings.filterwarnings('ignore')
|
||||
|
||||
|
||||
|
||||
|
||||
def detect_change_points(data):
|
||||
models = ['l2', 'rbf', 'l1'] # 使用三种模型
|
||||
all_bkps = set() # 使用集合来自动去重
|
||||
|
||||
for model in models:
|
||||
algo = rpt.Binseg(model=model, min_size=1, jump=1).fit(data)
|
||||
bkps = algo.predict(pen=1)
|
||||
all_bkps.update(bkps) # 将检测到的变点添加到集合中
|
||||
|
||||
return sorted(all_bkps) # 返回排序后的唯一变点列表
|
||||
|
||||
# def process_change_points(length, change_points, window_size):
|
||||
# # 初始化次要变点集合
|
||||
# all_important_nodes = set()
|
||||
# # 遍历每一个主要变点
|
||||
# for bkp in change_points:
|
||||
# # 计算该变点左右窗口的边界
|
||||
# start = max(0, int(bkp - window_size/2))
|
||||
# end = min(length, int(bkp + window_size/2))
|
||||
# a = 0.4
|
||||
# b = 0.6
|
||||
# prob = a + (b - a) * np.random.random()
|
||||
# # 遍历窗口内的每一个点
|
||||
# for i in range(start, end):
|
||||
# # 生成一个[0, 1]之间的随机数
|
||||
# random_value = np.random.random()
|
||||
# # 如果随机数大于0.5,将该点添加到次要变点集合中
|
||||
# if random_value >= 0.4:
|
||||
# all_important_nodes.add(i)
|
||||
#
|
||||
# return all_important_nodes
|
||||
|
||||
def process_change_points(ori_ts, length, change_points, window_size):
|
||||
# 计算每个变点的变化激烈程度
|
||||
changes_intensity = [(bkp, abs(ori_ts[bkp] - ori_ts[bkp - 1])) for bkp in change_points]
|
||||
# 根据变化激烈程度对主要变点进行排序
|
||||
changes_intensity.sort(key=lambda x: x[1], reverse=True)
|
||||
|
||||
# 初始化次要变点集合
|
||||
all_important_nodes = set()
|
||||
|
||||
# 分配阈值
|
||||
# num_points = len(changes_intensity)
|
||||
# thresholds = {bkp: 0.7 - 0.4 * ((rank) / (num_points - 1))**2 for rank, (bkp, _) in enumerate(changes_intensity)}
|
||||
# 初始化一个空字典来存储每个变点及其对应的阈值
|
||||
thresholds = {}
|
||||
|
||||
# 获取变点总数
|
||||
num_points = len(changes_intensity)
|
||||
# 使用enumerate函数遍历排序后的变点列表及其索引(即排名)
|
||||
for rank, (bkp, _) in enumerate(changes_intensity):
|
||||
# 计算归一化排名比例
|
||||
normalized_rank = 1 - ((num_points - 1-rank) / (num_points - 1))
|
||||
# 计算阈值降低的量,即缩放因子乘以归一化排名比例的平方
|
||||
decrement = 0.4 * (normalized_rank ** 2)
|
||||
# 计算并设置当前变点的阈值
|
||||
thresholds[bkp] = 0.3+decrement
|
||||
# 此时,thresholds字典中包含了每个变点的位置和对应的阈值
|
||||
|
||||
# 遍历每一个主要变点
|
||||
for bkp, intensity in changes_intensity:
|
||||
# 计算该变点左右窗口的边界
|
||||
start = max(0, int(bkp - window_size / 2))
|
||||
end = min(length, int(bkp + window_size / 2))
|
||||
threshold = thresholds[bkp]
|
||||
|
||||
# 遍历窗口内的每一个点
|
||||
for i in range(start, end):
|
||||
# 生成一个[0, 1]之间的随机数
|
||||
random_value = np.random.random()
|
||||
# 如果随机数大于分配的阈值,将该点添加到次要变点集合中
|
||||
if random_value >= threshold:
|
||||
all_important_nodes.add(i)
|
||||
|
||||
return all_important_nodes
|
||||
|
||||
|
||||
def get_magnitude(run_tag, factor, normalize,gpu):
|
||||
'''
|
||||
:param run_tag:
|
||||
:param factor:
|
||||
:return: Perturbed Magnitude
|
||||
'''
|
||||
data = load_ucr('data/' + run_tag + '/' + run_tag + '_attack'+gpu+'.txt', normalize=normalize)
|
||||
X = data[:, 1:]
|
||||
|
||||
max_magnitude = X.max(1)
|
||||
min_magnitude = X.min(1)
|
||||
mean_magnitude = np.mean(max_magnitude - min_magnitude)
|
||||
|
||||
perturbed_mag = mean_magnitude * factor
|
||||
print('Perturbed Magnitude:', perturbed_mag)
|
||||
|
||||
return perturbed_mag
|
||||
|
||||
|
||||
class Attacker:
|
||||
|
||||
def __init__(self, run_tag, model_type, cuda, normalize, e,device,gpu,classes):
|
||||
self.run_tag = run_tag
|
||||
self.model_type = model_type
|
||||
self.cuda = cuda
|
||||
#self.intervals = get_attack_position(self.run_tag, self.top_k)
|
||||
self.normalize = normalize
|
||||
self.e = e
|
||||
self.device = device
|
||||
self.gpu = gpu
|
||||
self.classes = classes
|
||||
|
||||
def perturb_ts(self, perturbations, ts, attack_pos):
|
||||
'''
|
||||
:param perturbations:formalized as a tuple(x,e),x(int) is the x-coordinate,e(float) is the epsilon,e.g.,(2,0.01)
|
||||
:param ts: time series
|
||||
:return: perturbed ts
|
||||
'''
|
||||
# first we copy a ts
|
||||
|
||||
ts_tmp = np.copy(ts)
|
||||
|
||||
coordinate = 0 # 初始化perturbations数组的索引
|
||||
for i in range(len(attack_pos)):
|
||||
if attack_pos[i] == 1:
|
||||
ts_tmp[i] += perturbations[coordinate]
|
||||
coordinate += 1
|
||||
# for interval in self.intervals:
|
||||
# for i in range(int(interval[0]), int(interval[1])):
|
||||
# ts_tmp[i] += perturbations[coordinate]
|
||||
# coordinate += 1
|
||||
return ts_tmp
|
||||
|
||||
def plot_per(self, perturbations, ts, target_class, sample_idx,attack_pos, prior_probs, attack_probs, factor):
|
||||
|
||||
# Obtain the perturbed ts
|
||||
ts_tmp = np.copy(ts)
|
||||
ts_perturbed = self.perturb_ts(perturbations=perturbations, ts=ts, attack_pos=attack_pos)
|
||||
# Start to plot
|
||||
plt.figure(figsize=(6, 4))
|
||||
plt.plot(ts_tmp, color='b', label='Original %.2f' % prior_probs)
|
||||
plt.plot(ts_perturbed, color='r', label='Perturbed %.2f' % attack_probs)
|
||||
plt.xlabel('Time', fontsize=12)
|
||||
|
||||
if target_class == -1:
|
||||
plt.title('Untargeted: Sample %d, eps_factor=%.3f' %
|
||||
(sample_idx, factor), fontsize=14)
|
||||
else:
|
||||
plt.title('Targeted(%d): Sample %d, eps_factor=%.3f' %
|
||||
(target_class, sample_idx, factor), fontsize=14)
|
||||
|
||||
plt.legend(loc='upper right', fontsize=8)
|
||||
plt.savefig('result_' + str(factor) + '_' + str(self.model_type) + '/'
|
||||
+ self.run_tag + '/figures'+self.gpu+'/' + self.run_tag +'_' + str(sample_idx) + '.png')
|
||||
# plt.show()
|
||||
|
||||
|
||||
|
||||
def fitness(self, device,perturbations, ts, sample_idx, queries,attack_pos, target_class=-1):
|
||||
#device = torch.device("cuda:0" if self.cuda else "cpu")
|
||||
perturbations = torch.tensor(perturbations)
|
||||
#ts = torch.tensor(ts, device='cuda')
|
||||
# perturbations = torch.tensor(perturbations, dtype=torch.float32)
|
||||
# perturbations = perturbations.to(device)
|
||||
|
||||
queries[0] += 1
|
||||
ts_perturbed = self.perturb_ts(perturbations, ts,attack_pos = attack_pos)
|
||||
mse = mean_squared_error(ts, ts_perturbed)
|
||||
|
||||
prob, _, _, _, _ = query_one(run_tag=self.run_tag,device=device, idx=sample_idx, attack_ts=ts_perturbed,
|
||||
target_class=target_class, normalize=self.normalize,
|
||||
cuda=self.cuda, model_type=self.model_type, e=self.e,gpu=self.gpu,n_class=self.classes)
|
||||
# decimal_places = -int(np.floor(np.log10(prob))) + 1
|
||||
# # 计算需要标准化的数字的标准化因子
|
||||
# scale_factor = 10 ** decimal_places
|
||||
# # 标准化目标数字
|
||||
# normalized = np.round(scale_factor * mse, 0) / scale_factor
|
||||
# 确保标准化后的数字至少为0.01
|
||||
#normalized = max(normalized, 0.01)
|
||||
prob = torch.tensor(prob)
|
||||
|
||||
if target_class != -1:
|
||||
prob = 1 - prob
|
||||
|
||||
return prob # The fitness function is to minimize the fitness value
|
||||
|
||||
def attack_success(self, device, perturbations, ts, sample_idx, attack_pos, iterations, target_class=-1,
|
||||
verbose=True):
|
||||
iterations[0] += 1
|
||||
print('The %d iteration' % iterations[0])
|
||||
ts_perturbed = self.perturb_ts(perturbations, ts, attack_pos)
|
||||
# ts_perturbed = torch.tensor(ts_perturbed, device='cuda')
|
||||
# Obtain the perturbed probability vector and the prior probability vector
|
||||
prob, prob_vector, prior_prob, prior_prob_vec, real_label = query_one(self.run_tag, device, idx=sample_idx,
|
||||
attack_ts=ts_perturbed,
|
||||
target_class=target_class,
|
||||
normalize=self.normalize,
|
||||
verbose=verbose, cuda=self.cuda,
|
||||
model_type=self.model_type,
|
||||
e=self.e, gpu=self.gpu,n_class=self.classes)
|
||||
|
||||
predict_class = torch.argmax(prob_vector).to(device)
|
||||
prior_class = torch.argmax(prior_prob_vec).to(device)
|
||||
real_label = real_label.to(device)
|
||||
|
||||
# Conditions for early termination(empirical-based estimation), leading to save the attacking time
|
||||
# But it may judge incorrectly that this may decrease the success rate of the attack.
|
||||
if (iterations[0] > 20 and prob > 0.9):
|
||||
|
||||
print('The %d sample is not expected to successfully attack.' % sample_idx)
|
||||
print('prob: ', prob)
|
||||
return True
|
||||
|
||||
if prior_class != real_label:
|
||||
print('The %d sample cannot be classified correctly, no need to attack' % sample_idx)
|
||||
return True
|
||||
|
||||
if prior_class == target_class:
|
||||
print(
|
||||
'The true label of %d sample equals to target label, no need to attack' % sample_idx)
|
||||
return True
|
||||
|
||||
if verbose:
|
||||
print('The Confidence of current iteration: %.4f' % prob)
|
||||
print('########################################################')
|
||||
|
||||
# The criterion of attacking successfully:
|
||||
# Untargeted attack: predicted label is not equal to the original label.
|
||||
# Targeted attack: predicted label is equal to the target label.
|
||||
if ((target_class == -1 and predict_class != prior_class) or
|
||||
(target_class != -1 and predict_class == target_class)):
|
||||
print('##################### Attack Successfully! ##########################')
|
||||
|
||||
return True
|
||||
|
||||
def attack(self, sample_idx,device, target_class=-1, factor=0.04,
|
||||
max_iteration=50, popsize=200, verbose=True):
|
||||
|
||||
class MyProblem(ElementwiseProblem):
|
||||
def __init__(self, outer, ts, sample_idx, queries, attack_pos, target_class, device, bounds,perturbed_magnitude):
|
||||
#self, device, perturbations, ts, sample_idx, queries, attack_pos, target_class = -1
|
||||
self.perturbed_magnitude=perturbed_magnitude
|
||||
super().__init__(n_var=len(bounds), n_obj=1, n_constr=0, xl=-perturbed_magnitude * np.ones(len(bounds)), # 下界
|
||||
xu=perturbed_magnitude * np.ones(len(bounds)))
|
||||
self.outer = outer
|
||||
self.ts = ts
|
||||
self.sample_idx = sample_idx
|
||||
self.queries = queries
|
||||
self.attack_pos = attack_pos
|
||||
self.target_class = target_class
|
||||
self.device = device
|
||||
|
||||
def _evaluate(self, x, out, *args, **kwargs):
|
||||
f = self.outer.fitness(self.device,x , self.ts, self.sample_idx,self.queries, self.attack_pos, self.target_class,
|
||||
)
|
||||
# self, device,perturbations, ts, sample_idx, queries,attack_pos, target_class=-1
|
||||
out["F"] = np.array([f])
|
||||
|
||||
class MyCallback(Callback):
|
||||
def __init__(self, outer, device, ts, sample_idx, queries, attack_pos, target_class, verbose,iterations):
|
||||
super().__init__()
|
||||
self.outer = outer
|
||||
self.device = device
|
||||
self.ts = ts
|
||||
self.sample_idx = sample_idx
|
||||
self.queries = queries
|
||||
self.attack_pos = attack_pos
|
||||
self.target_class = target_class
|
||||
self.iterations = iterations
|
||||
self.verbose = verbose
|
||||
self.generation = 0
|
||||
|
||||
def notify(self, algorithm):
|
||||
x = algorithm.pop.get("X")[np.argmin(algorithm.pop.get("F"))] # Current best solution
|
||||
ifsuccess=self.outer.attack_success(self.device, x, self.ts,
|
||||
self.sample_idx, self.attack_pos,
|
||||
self.iterations, self.target_class,
|
||||
self.verbose)
|
||||
#self,device,perturbations, ts, sample_idx, attack_pos, iterations, target_class=-1, verbose=True
|
||||
# best_f = min(algorithm.pop.get("F"))
|
||||
# best_x = algorithm.pop.get("X")[np.argmin(algorithm.pop.get("F"))]
|
||||
# print(f"Generation {self.generation}: Best solution so far: {best_x}, Fitness: {best_f}")
|
||||
# print('-------',should_terminate)
|
||||
if ifsuccess:
|
||||
algorithm.termination.force_termination = True
|
||||
self.generation += 1
|
||||
|
||||
test = load_ucr('data/' + self.run_tag + '/' + self.run_tag + '_attack'+self.gpu+'.txt'
|
||||
, normalize=self.normalize)
|
||||
#attack_poses = np.loadtxt('data/' + self.run_tag + '/' + self.run_tag + '_attackPos'+self.gpu+'.txt')
|
||||
|
||||
ori_ts = test[sample_idx][1:]
|
||||
|
||||
attacked_probs, attacked_vec, prior_probs, prior_vec, real_label = query_one(self.run_tag,device,idx=sample_idx,
|
||||
attack_ts=ori_ts,
|
||||
target_class=target_class,
|
||||
normalize=self.normalize,
|
||||
verbose=False,
|
||||
cuda=self.cuda, e=self.e,
|
||||
model_type=self.model_type,gpu=self.gpu,n_class=self.classes)
|
||||
prior_class = torch.argmax(prior_vec).to(device)
|
||||
if prior_class != real_label:
|
||||
print('The %d sample cannot be classified correctly, no need to attack' % sample_idx)
|
||||
return ori_ts,ori_ts, [prior_probs, attacked_probs, 0, 0, 0, 0, 0, 'WrongSample']
|
||||
# Get the maximum perturbed magnitude
|
||||
perturbed_magnitude = get_magnitude(self.run_tag, factor, normalize=self.normalize,gpu=self.gpu)
|
||||
bounds = []
|
||||
# 变点检测找区间
|
||||
length = ori_ts.shape
|
||||
all_bkps = detect_change_points(ori_ts)
|
||||
all_bkps = [x - 1 for x in all_bkps]
|
||||
window_size = int(length[0] / len(all_bkps)) # 窗口大小
|
||||
|
||||
sequence = np.zeros(len(ori_ts), dtype=int)
|
||||
# secondary_changes = process_change_points(length[0], all_bkps, window_size)
|
||||
# sequence[list(secondary_changes)] = 1
|
||||
# sequence[list(all_bkps)] = 1
|
||||
# 处理变点
|
||||
if len(all_bkps)<0.7*length[0] :
|
||||
secondary_changes = process_change_points(ori_ts, length[0], all_bkps, window_size)
|
||||
sequence[list(secondary_changes)] = 1
|
||||
sequence[list(all_bkps)] = 1
|
||||
else:
|
||||
sequence[list(all_bkps)] = 1
|
||||
attack_pos = sequence
|
||||
|
||||
steps_count = attack_pos.sum()
|
||||
for i in range(len(attack_pos)):
|
||||
if attack_pos[i] == 1:
|
||||
bounds.append((-1 * perturbed_magnitude, perturbed_magnitude))
|
||||
|
||||
print('The length of shapelet interval', steps_count)
|
||||
#print('The length of bounds', len(bounds))
|
||||
popmul = max(1, popsize // len(bounds))
|
||||
# Record of the number of iterations
|
||||
iterations = [0]
|
||||
queries = [0]
|
||||
problem = MyProblem(self, ori_ts, sample_idx, queries, attack_pos, target_class, device,bounds,perturbed_magnitude)
|
||||
algorithm = PSO(pop_size=50, w=0.9, c1=1.2, c2=2.2)
|
||||
callback1 = MyCallback(self, device, ori_ts, sample_idx, queries, attack_pos, target_class, verbose,iterations)
|
||||
res = minimize(problem, algorithm, ('n_gen', max_iteration), callback=callback1, seed=1, verbose=verbose)
|
||||
|
||||
|
||||
attack_result = res.X # 最优解
|
||||
# attack_result = differential_evolution(func=fitness_fn, bounds=bounds
|
||||
# , maxiter=max_iteration, popsize=popmul
|
||||
# , recombination=0.7, callback=callback_fn,
|
||||
# atol=-1, polish=False)
|
||||
|
||||
|
||||
attack_ts = self.perturb_ts(attack_result, ori_ts, attack_pos)
|
||||
|
||||
mse = mean_squared_error(ori_ts, attack_ts)
|
||||
|
||||
attacked_probs, attacked_vec, prior_probs, prior_vec, real_label = query_one(self.run_tag,device, idx=sample_idx,
|
||||
attack_ts=attack_ts,
|
||||
target_class=target_class,
|
||||
normalize=self.normalize,
|
||||
verbose=False,
|
||||
cuda=self.cuda, e=self.e,
|
||||
model_type=self.model_type,gpu=self.gpu,n_class=self.classes)
|
||||
|
||||
predicted_class = torch.argmax(attacked_vec).to(device)
|
||||
prior_class = torch.argmax(prior_vec).to(device)
|
||||
|
||||
if prior_class != real_label:
|
||||
success = 'WrongSample'
|
||||
|
||||
elif prior_class == target_class:
|
||||
success = 'NoNeedAttack'
|
||||
|
||||
else:
|
||||
if (predicted_class.item() != prior_class.item() and target_class == -1) \
|
||||
or (predicted_class.item() == target_class and target_class != -1):
|
||||
success = 'Success'
|
||||
else:
|
||||
success = 'Fail'
|
||||
|
||||
if success == 'Success':
|
||||
self.plot_per(perturbations=attack_result, ts=ori_ts, target_class=target_class,
|
||||
sample_idx=sample_idx, attack_pos=attack_pos, prior_probs=prior_probs, attack_probs=attacked_probs, factor=factor)
|
||||
|
||||
return ori_ts, attack_ts, [prior_probs, attacked_probs, prior_class.item(),
|
||||
predicted_class.item(), queries[0], mse, iterations[0], success]
|
||||
|
||||
|
55
dataPre.py
Normal file
55
dataPre.py
Normal file
@ -0,0 +1,55 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import configparser
|
||||
|
||||
|
||||
def process_and_split_data(file_name):
|
||||
# 读取文件内容
|
||||
data_path = 'data/' + file_name + '/' + file_name
|
||||
with open(data_path+'_TEST.txt', 'r') as file:
|
||||
lines = file.readlines()
|
||||
|
||||
# 解析数据,并按类别排序
|
||||
data = [line.strip().split() for line in lines]
|
||||
data.sort(key=lambda x: x[0]) # 假设类别在每行的第一列
|
||||
|
||||
# 按类别分组
|
||||
from collections import defaultdict
|
||||
categorized_data = defaultdict(list)
|
||||
for row in data:
|
||||
categorized_data[row[0]].append(row)
|
||||
|
||||
# 分别存储每个类别的前50%和剩余的数据
|
||||
cp_file_name = data_path + '_cp.txt'
|
||||
attack_file_name = data_path + '_attack.txt'
|
||||
|
||||
with open(cp_file_name, 'w') as cp_file, open(attack_file_name, 'w') as attack_file:
|
||||
for category, rows in categorized_data.items():
|
||||
#如果数据量很大,找区间不用这么多条数据,cp文件里面应该少一些
|
||||
if len(rows)>100:
|
||||
half_index = len(rows) // 10
|
||||
#half_index = 6
|
||||
#half = len(rows) // 10
|
||||
#StarLightCurves这个数据集太长了,截取每一类的后百分之十
|
||||
half = (len(rows) // 2)
|
||||
else:
|
||||
half_index = len(rows) // 2
|
||||
# half = (len(rows) // 10)*9
|
||||
half = (len(rows) // 2)
|
||||
# 存储前50%的数据
|
||||
for row in rows[:half_index]:
|
||||
cp_file.write(' '.join(row) + '\n')
|
||||
# 存储剩余的数据
|
||||
for row in rows[half:]:
|
||||
attack_file.write(' '.join(row) + '\n')
|
||||
|
||||
|
||||
|
||||
|
||||
# 假设文件名为'Car.txt'
|
||||
if __name__ == '__main__':
|
||||
# 临时添加配置文件类别种类
|
||||
config = configparser.ConfigParser()
|
||||
config.read("run_parallel_config.ini")
|
||||
file_name = config['MODEL']['run_tag']
|
||||
process_and_split_data(file_name)
|
||||
|
43
datasets_config.csv
Normal file
43
datasets_config.csv
Normal file
@ -0,0 +1,43 @@
|
||||
dataset_name,cuda,total_gpus,classes,target_class,pop_size,magnitude_factor,max_itr,run_tag,model,normalize,e,done
|
||||
Car,store_true,5,4,-1,1,0.04,50,Car,r,store_true,1499,0
|
||||
Wafer,store_true,7,2,-1,1,0.04,50,Wafer,r,store_true,1499,0
|
||||
ItalyPowerDemand,store_true,4,2,-1,1,0.04,50,ItalyPowerDemand,r,store_true,1499,0
|
||||
AllGestureWiimoteY,store_true,7,10,-1,1,0.04,50,AllGestureWiimoteY,r,store_true,1499,0
|
||||
NonIFECGTho2,store_true,4,42,-1,1,0.04,50,NonIFECGTho2,r,store_true,1499,0
|
||||
Trace,store_true,1,4,-1,1,0.04,50,Trace,r,store_true,1499,0
|
||||
PigAirwayPressure,store_true,1,52,-1,1,0.04,50,PigAirwayPressure,r,store_true,1499,0
|
||||
GesturePebbleZ2,store_true,5,6,-1,1,0.04,50,GesturePebbleZ2,r,store_true,1499,0
|
||||
AllGestureWiimoteX,store_true,7,10,-1,1,0.04,50,AllGestureWiimoteX,r,store_true,1499,0
|
||||
FordA,store_true,6,2,-1,1,0.04,50,FordA,r,store_true,1499,0
|
||||
DodgerLoopDay,store_true,5,7,-1,1,0.04,50,DodgerLoopDay,r,store_true,1499,0
|
||||
SonyAIBORobotSurface1,store_true,4,2,-1,1,0.04,50,SonyAIBORobotSurface1,r,store_true,1499,0
|
||||
PigArtPressure,store_true,7,52,-1,1,0.04,50,PigArtPressure,r,store_true,1499,0
|
||||
MoteStrain,store_true,4,2,-1,1,0.04,50,MoteStrain,r,store_true,1499,0
|
||||
ECGFiveDays,store_true,5,2,-1,1,0.04,50,ECGFiveDays,r,store_true,1499,0
|
||||
PickupGeWZ,store_true,1,10,-1,1,0.04,50,PickupGeWZ,r,store_true,1499,0
|
||||
FreezerSmallTrain,store_true,7,2,-1,1,0.04,50,FreezerSmallTrain,r,store_true,1499,0
|
||||
TwoLeadECG,store_true,7,2,-1,1,0.04,50,TwoLeadECG,r,store_true,1499,0
|
||||
Lightning7,store_true,4,7,-1,1,0.04,50,Lightning7,r,store_true,1499,0
|
||||
Phoneme,store_true,7,39,-1,1,0.04,50,Phoneme,r,store_true,1499,0
|
||||
DodgerLoopWeekend,store_true,5,2,-1,1,0.04,50,DodgerLoopWeekend,r,store_true,1499,0
|
||||
ECG5000,store_true,6,5,-1,1,0.04,50,ECG5000,r,store_true,1499,0
|
||||
ShakeGestureWiimoteZ,store_true,1,10,-1,1,0.04,50,ShakeGestureWiimoteZ,r,store_true,1499,0
|
||||
GesturePebbleZ1,store_true,5,6,-1,1,0.04,50,GesturePebbleZ1,r,store_true,1499,0
|
||||
NonIFECGTho1,store_true,7,42,-1,1,0.04,50,NonIFECGTho1,r,store_true,1499,0
|
||||
AllGestureWiimoteZ,store_true,7,10,-1,1,0.04,50,AllGestureWiimoteZ,r,store_true,1499,0
|
||||
FordB,store_true,4,2,-1,1,0.04,50,FordB,r,store_true,1499,0
|
||||
InsectWingbeatSound,store_true,4,11,-1,1,0.04,50,InsectWingbeatSound,r,store_true,1499,0
|
||||
EOGHorizontalSignal,store_true,7,12,-1,1,0.04,50,EOGHorizontalSignal,r,store_true,1499,0
|
||||
ChlorineConcentration,store_true,6,3,-1,1,0.04,50,ChlorineConcentration,r,store_true,1499,0
|
||||
Plane,store_true,4,7,-1,1,0.04,50,Plane,r,store_true,1499,0
|
||||
EOGVerticalSignal,store_true,7,12,-1,1,0.04,50,EOGVerticalSignal,r,store_true,1499,0
|
||||
DodgerLoopGame,store_true,7,2,-1,1,0.04,50,DodgerLoopGame,r,store_true,1499,0
|
||||
ECG200,store_true,2,2,-1,1,0.04,50,ECG200,r,store_true,1499,0
|
||||
Fungi,store_true,1,18,-1,1,0.04,50,Fungi,r,store_true,1499,0
|
||||
CinCEC,store_true,6,4,-1,1,0.04,50,CinCEC,r,store_true,1499,0
|
||||
SonyAIBORobotSurface2,store_true,4,2,-1,1,0.04,50,SonyAIBORobotSurface2,r,store_true,1499,0
|
||||
Lightning2,store_true,4,2,-1,1,0.04,50,Lightning2,r,store_true,1499,0
|
||||
FreezerRegularTrain,store_true,7,2,-1,1,0.04,50,FreezerRegularTrain,r,store_true,1499,0
|
||||
StarLightCurves,store_true,6,3,-1,1,0.04,50,StarLightCurves,r,store_true,1499,0
|
||||
Earthquakes,store_true,4,2,-1,1,0.04,50,Earthquakes,r,store_true,1499,0
|
||||
PigCVP,store_true,7,52,-1,1,0.04,50,PigCVP,r,store_true,1499,0
|
|
223
draw_main.py
Normal file
223
draw_main.py
Normal file
@ -0,0 +1,223 @@
|
||||
import numpy as np
|
||||
|
||||
from analyzeTool import generate_heat_maps_array, count_classes_samples
|
||||
from drawing_tool import draw_ori_perturbed, draw_times_diff_bar, draw_ori_perturbed_with_inset, draw_diff_pert_info, \
|
||||
heat_maps_of_classes
|
||||
|
||||
if __name__ == '__main__':
|
||||
# # ECG 0.04
|
||||
# original_data = "6.410247599999999712e-01 7.814486200000000382e-01 8.841660900000000156e-01 1.235362999999999989e+00 1.782253300000000040e+00 2.219029200000000035e+00 2.350801099999999977e+00 2.111025199999999824e+00 1.595795800000000098e+00 1.063145000000000007e+00 5.214278199999999863e-01 8.905684099999999770e-02 1.531264400000000026e-01 2.324356599999999884e-01 -1.149376899999999951e-01 -1.651973100000000139e-01 5.011464799999999602e-03 -1.478869999999999907e-01 -6.105320999999999665e-02 3.645349999999999979e-02 -4.441071200000000219e-01 -6.793092099999999967e-01 -5.299733599999999489e-01 -6.467437299999999611e-01 -7.079432799999999526e-01 -6.633238200000000084e-01 -8.606828899999999782e-01 -9.597856700000000352e-01 -9.276052399999999976e-01 -1.140874799999999967e+00 -1.364474799999999988e+00 -1.286232400000000053e+00 -1.193629000000000051e+00 -1.332616500000000093e+00 -1.469505899999999921e+00 -1.489589899999999911e+00 -1.600690200000000063e+00 -1.777332799999999935e+00 -1.810176000000000007e+00 -1.735597099999999893e+00 -1.704956899999999997e+00 -1.724591900000000066e+00 -1.707795699999999917e+00 -1.594449299999999958e+00 -1.396698400000000007e+00 -1.187054700000000018e+00 -9.916590499999999864e-01 -7.708646200000000004e-01 -5.576156799999999469e-01 -3.874625899999999956e-01 -1.684684999999999933e-01 1.158190000000000053e-01 3.144081799999999816e-01 3.764868499999999840e-01 4.204736399999999819e-01 4.975668799999999892e-01 5.742429000000000006e-01 6.478606900000000168e-01 6.616984399999999988e-01 6.051487300000000236e-01 6.295551700000000528e-01 7.117260399999999487e-01 6.740077100000000376e-01 6.155466400000000338e-01 6.777178400000000158e-01 7.207244900000000509e-01 6.626562999999999759e-01 6.158657499999999896e-01 6.617521699999999729e-01 7.109475100000000047e-01 6.147269899999999732e-01 5.231166299999999714e-01 5.887229699999999566e-01 5.911069100000000409e-01 5.855090899999999543e-01 6.948123600000000177e-01 5.469097400000000331e-01 3.645842599999999933e-01 6.602078500000000405e-01 8.684830799999999629e-01 6.410247599999999712e-01 5.403232999999999508e-01 6.355810499999999807e-01 7.083335299999999890e-01 7.426267199999999624e-01 6.175198499999999813e-01 5.871576699999999649e-01 8.247907500000000169e-01 9.697120799999999763e-01 9.259981499999999643e-01 5.296564000000000272e-01 -1.374844299999999908e-01 -4.576849700000000243e-01 -1.061242400000000030e+00 -2.023360600000000176e+00 -1.376014099999999907e+00"
|
||||
# perturbed_data = "0.6444 0.7856 0.8888 1.2418 1.7713 2.0436 2.2346 2.1930 1.6804 1.0748 0.3897 -0.0399 0.0686 0.4267 -0.1309 -0.2164 0.0050 -0.1487 -0.0614 0.0366 -0.4464 -0.6829 -0.5328 -0.6501 -0.7117 -0.6668 -0.9808 -1.0112 -1.0913 -1.0141 -1.4900 -1.4651 -1.1812 -1.2940 -1.5742 -1.3882 -1.6847 -1.7861 -1.9346 -1.7152 -1.8077 -1.6203 -1.6006 -1.6807 -1.3937 -1.3646 -1.1665 -0.6113 -0.5605 -0.3895 -0.1694 0.1164 0.3161 0.3785 0.4227 0.5002 0.5773 0.6513 0.6652 0.6083 0.6329 0.7155 0.6775 0.6188 0.6813 0.7245 0.6661 0.6191 0.6652 0.7147 0.6180 0.5259 0.5918 0.5942 0.5886 0.6985 0.5498 0.3665 0.6637 0.8730 0.7138 0.4777 0.6356 0.8395 0.9112 0.5005 0.7421 0.9235 0.9903 1.1184 0.6624 -0.0234 -0.5430 -0.8738 -2.0340 -1.3832"
|
||||
# scale = (25, 50)
|
||||
# xy = (45, 0.85)
|
||||
# xytext = (40, -0.4)
|
||||
# loc_sample = 'upper right'
|
||||
# loc_sub = 'upper center'
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_ECG004对比图.pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# inset_range=scale,
|
||||
# dashed_lists=[scale],
|
||||
# xy=xy,
|
||||
# xytext=xytext)
|
||||
#
|
||||
# # ECG 0.02
|
||||
# perturbed_data = "0.6444 0.7856 0.8888 1.2418 1.8865 2.1496 2.3434 2.1861 1.5822 1.0904 0.5405 0.0347 0.1713 0.3206 -0.1030 -0.1754 0.0050 -0.1487 -0.0614 0.0366 -0.4464 -0.6829 -0.5328 -0.6501 -0.7117 -0.6668 -0.9112 -0.9741 -1.0095 -1.1322 -1.3230 -1.3910 -1.2761 -1.3497 -1.5226 -1.4313 -1.6892 -1.8592 -1.7471 -1.7912 -1.6806 -1.6637 -1.7026 -1.6638 -1.4444 -1.1879 -1.0551 -0.8528 -0.5605 -0.3895 -0.1694 0.1164 0.3161 0.3785 0.4227 0.5002 0.5773 0.6513 0.6652 0.6083 0.6329 0.7155 0.6775 0.6188 0.6813 0.7245 0.6661 0.6191 0.6652 0.7147 0.6180 0.5259 0.5918 0.5942 0.5886 0.6985 0.5498 0.3665 0.6637 0.8730 0.6238 0.5742 0.6817 0.7971 0.7187 0.7069 0.6060 0.8689 1.0034 1.0273 0.5092 -0.2091 -0.3818 -0.9827 -2.0340 -1.3832"
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_ECG002对比图.pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# inset_range=scale,
|
||||
# dashed_lists=[scale],
|
||||
# xy=xy,
|
||||
# xytext=xytext)
|
||||
#
|
||||
# # ECG 0.01
|
||||
# perturbed_data = "0.6444 0.7856 0.8888 1.2762 1.7566 2.2411 2.3631 2.1221 1.6042 1.0687 0.4979 0.0412 0.1737 0.2803 -0.1073 -0.1920 0.0453 -0.1498 -0.0614 0.0366 -0.4464 -0.6829 -0.5328 -0.6501 -0.7117 -0.6668 -0.8652 -1.0050 -0.9247 -1.1196 -1.3812 -1.3010 -1.1999 -1.3396 -1.4772 -1.4974 -1.6091 -1.7867 -1.8197 -1.7447 -1.7139 -1.6926 -1.6829 -1.6361 -1.3716 -1.1626 -1.0194 -0.7482 -0.5426 -0.4157 -0.1808 0.1277 0.3185 0.4245 0.4058 0.5200 0.5515 0.6634 0.6617 0.5656 0.6466 0.7155 0.6775 0.6188 0.6813 0.7245 0.6661 0.6191 0.6652 0.7147 0.6180 0.5259 0.5918 0.5942 0.5794 0.6845 0.5835 0.3818 0.6755 0.8561 0.6444 0.5432 0.6389 0.7121 0.7465 0.6208 0.5902 0.8291 0.9838 0.9516 0.5245 -0.1788 -0.4601 -1.0668 -2.0340 -1.3832"
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_ECG001对比图.pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# inset_range=scale,
|
||||
# dashed_lists=[scale],
|
||||
# xy=xy,
|
||||
# xytext=xytext)
|
||||
|
||||
# # Sony 0.04
|
||||
# original_data = "0.0599 0.0599 0.0599 0.0599 -0.7742 -1.3302 -0.4962 0.3379 1.4499 1.1719 0.3379 0.8939 1.7280 1.7280 0.6159 -1.0521 -1.0521 -0.2181 -0.4962 -0.7742 -1.0521 -1.0521 -1.0521 -0.4962 0.0599 0.0599 0.3379 -0.2181 0.3379 0.0599 0.3379 0.3379 -0.7742 -0.4962 -0.4962 -0.4962 -0.2181 -0.2181 -0.2181 0.0599 -0.2181 -0.2181 0.0599 -1.6082 -1.0521 0.6159 0.3379 -0.7742 1.1719 2.8400 3.3960 2.2840 0.8939 -2.1642 -2.1642 -0.4962 0.0599 -0.2181 -0.4962 -0.4962 0.6159 0.6159 0.0599 -0.2181 0.0599"
|
||||
# perturbed_data = "0.0599 0.0599 0.0599 0.0310 -0.6830 -1.1319 -0.3566 0.3379 1.4499 1.2683 0.4334 0.9029 1.8575 1.9152 0.6944 -1.0521 -1.0521 -0.2181 -0.4962 -0.7742 -1.0521 -1.0521 -1.0521 -0.4962 0.0599 0.0599 0.3379 -0.2181 0.3379 0.0599 0.3379 0.3379 -0.7742 -0.4962 -0.4962 -0.4962 -0.2181 -0.2181 -0.2181 0.0599 -0.2181 -0.2181 0.0599 -1.6082 -1.0521 0.5199 0.1594 -0.7803 1.1256 2.9534 3.5492 2.3713 0.7483 -2.0346 -2.1955 -0.3492 0.0359 -0.1742 -0.3939 -0.6957 0.4353 0.4462 0.0599 -0.2181 0.0599"
|
||||
# scale = (7, 15)
|
||||
# xy = (33, 1.4)
|
||||
# xytext = (15, 0.8)
|
||||
# loc_sample = 'upper right'
|
||||
# loc_sub = 'upper center'
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_Sony004对比图.pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# inset_range=scale,
|
||||
# dashed_lists=[scale],
|
||||
# xy=xy,
|
||||
# xytext=xytext)
|
||||
#
|
||||
# # Sony 0.02
|
||||
# perturbed_data = "0.0599 0.0599 0.0599 0.0374 -0.7051 -1.3549 -0.4990 0.3379 1.4499 1.0861 0.3807 0.9880 1.7390 1.7361 0.6788 -1.0521 -1.0521 -0.2181 -0.4962 -0.7742 -1.0521 -1.0521 -1.0521 -0.4962 0.0599 0.0599 0.3379 -0.2181 0.3379 0.0599 0.3379 0.3379 -0.7742 -0.4962 -0.4962 -0.4962 -0.2181 -0.2181 -0.2181 0.0599 -0.2181 -0.2181 0.0599 -1.6082 -1.0521 0.6970 0.2896 -0.7888 1.1938 2.7924 3.4649 2.3376 0.8073 -2.0784 -2.1942 -0.5223 0.0861 -0.2344 -0.5798 -0.5959 0.5172 0.5588 0.0599 -0.2181 0.0599"
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_Sony002对比图.pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# inset_range=scale,
|
||||
# dashed_lists=[scale],
|
||||
# xy=xy,
|
||||
# xytext=xytext)
|
||||
#
|
||||
# # Sony 0.01
|
||||
# perturbed_data = "0.0599 0.0599 0.0599 0.0169 -0.7642 -1.3113 -0.4875 0.3379 1.4499 1.1723 0.3651 0.9393 1.6804 1.7290 0.6672 -1.0521 -1.0521 -0.2181 -0.4962 -0.7742 -1.0521 -1.0521 -1.0521 -0.4962 0.0599 0.0599 0.3379 -0.2181 0.3379 0.0599 0.3379 0.3379 -0.7742 -0.4962 -0.4962 -0.4962 -0.2181 -0.2181 -0.2181 0.0599 -0.2181 -0.2181 0.0599 -1.6082 -1.0521 0.6248 0.3447 -0.7442 1.1737 2.7967 3.4208 2.2884 0.8680 -2.1330 -2.1518 -0.5447 0.0130 -0.2304 -0.5026 -0.4783 0.5671 0.6399 0.0599 -0.2181 0.0599"
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_Sony001对比图.pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# inset_range=scale,
|
||||
# dashed_lists=[scale],
|
||||
# xy=xy,
|
||||
# xytext=xytext)
|
||||
#
|
||||
|
||||
# 随机区间成功
|
||||
# scale = [(13, 29), (33, 47), (56, 72)]
|
||||
# # xy = (95, -5)
|
||||
# # xytext = (40, -0.4)
|
||||
# loc_sample = 'lower right'
|
||||
# loc_sub = 'lower right'
|
||||
# original_data = "0.7105 0.6894 0.6551 1.2894 1.9932 1.9182 1.5860 1.6460 1.5084 0.7529 0.0330 -0.1929 -0.1509 -0.1136 -0.2392 -0.5039 -0.6020 -0.4257 -0.3627 -0.6225 -0.8194 -0.7298 -0.6382 -0.7202 -0.9134 -1.0540 -1.0283 -1.0828 -1.2669 -1.2678 -1.2946 -1.4921 -1.3886 -1.2382 -1.5695 -1.8409 -1.7606 -1.7878 -1.8247 -1.7041 -1.7095 -1.7474 -1.6194 -1.4682 -1.3479 -1.2382 -1.0846 -0.8102 -0.6451 -0.6373 -0.3964 -0.0379 0.0010 -0.0685 0.0609 0.2248 0.3061 0.3292 0.3028 0.3230 0.3998 0.4567 0.5148 0.5269 0.4515 0.4403 0.5410 0.5968 0.5534 0.4987 0.4910 0.5554 0.6822 0.7272 0.6650 0.7387 0.8708 0.7335 0.5975 0.8433 1.0931 1.0070 0.9677 1.0794 0.8658 0.6264 0.9619 1.1341 0.7718 0.9090 1.3177 1.1296 1.0961 1.3177 0.8113 0.1427"
|
||||
# perturbed_data = '0.7105 0.6894 0.6551 1.2894 1.9932 1.9182 1.5860 1.6460 1.5084 0.7529 0.0330 -0.1929 -0.1509 0.0662 -0.1203 -0.3538 -0.5494 -0.5772 -0.5440 -0.5975 -0.8799 -0.6269 -0.8194 -0.5960 -0.9585 -1.2015 -0.8784 -1.0897 -1.4161 -1.2678 -1.2946 -1.4921 -1.3886 -1.0961 -1.4944 -1.9683 -1.6469 -1.6565 -1.9820 -1.6598 -1.5989 -1.7915 -1.8038 -1.3032 -1.2258 -1.3837 -1.0666 -0.8102 -0.6451 -0.6373 -0.3964 -0.0379 0.0010 -0.0685 0.0609 0.2248 0.3491 0.5100 0.4655 0.5169 0.3829 0.4692 0.5358 0.4554 0.5778 0.5362 0.4921 0.5452 0.6070 0.5404 0.4519 0.6364 0.6822 0.7272 0.6650 0.7387 0.8708 0.7335 0.5975 0.8433 1.0931 1.0070 0.9677 1.0794 0.8658 0.6264 0.9619 1.1341 0.7718 0.9090 1.3177 1.1296 1.0961 1.3177 0.8113 0.1427'
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_ECGFiveDays(随机区间成功).pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# dashed_lists=scale)
|
||||
#
|
||||
# # 原区间成功
|
||||
# scale = [(3, 14), (27, 52), (74,84)]
|
||||
# perturbed_data = '0.7105 0.6894 0.6551 1.2224 1.8428 2.0472 1.7260 1.6045 1.3185 0.5770 0.1076 -0.2949 -0.1636 0.0517 -0.2392 -0.5039 -0.6020 -0.4257 -0.3627 -0.6225 -0.8194 -0.7298 -0.6382 -0.7202 -0.9134 -1.0540 -1.0283 -0.9722 -1.4386 -1.2600 -1.1366 -1.6790 -1.5343 -1.2766 -1.6165 -1.9023 -1.5843 -1.6212 -1.9980 -1.7463 -1.5317 -1.8412 -1.7552 -1.5399 -1.3920 -1.4149 -1.2649 -0.6781 -0.4535 -0.7282 -0.3204 -0.0391 0.0010 -0.0685 0.0609 0.2248 0.3061 0.3292 0.3028 0.3230 0.3998 0.4567 0.5148 0.5269 0.4515 0.4403 0.5410 0.5968 0.5534 0.4987 0.4910 0.5554 0.6822 0.7272 0.6277 0.6284 0.7937 0.6874 0.7385 0.7790 1.0495 1.1863 0.9164 1.0463 0.8658 0.6264 0.9619 1.1341 0.7718 0.9090 1.3177 1.1296 1.0961 1.3177 0.8113 0.1427'
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_ECGFiveDays(原区间成功).pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# dashed_lists=scale)
|
||||
#
|
||||
# # 随机区间失败1~2
|
||||
# scale = [(100,130)]
|
||||
# perturbed_data = original_data
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_ECGFiveDays(随机区间失败1).pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# dashed_lists=scale)
|
||||
# scale = [(80, 110)]
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# filename='论文插图2/figure3_ECGFiveDays(随机区间失败2).pdf',
|
||||
# loc_sample=loc_sample,
|
||||
# loc_sub=loc_sub,
|
||||
# dashed_lists=scale)
|
||||
|
||||
# # 扰动因子和成功率
|
||||
# data1 = [52, 81, 81, 81, 81, 81] # Car*
|
||||
# data2 = [1, 8, 8, 19, 18, 29] # ItalyPowerDemand*
|
||||
# data3 = [3, 12, 17, 42, 59, 77] # SonyAIBORobotSurface2
|
||||
# data4 = [0, 4, 65, 78, 78, 78] # Plane
|
||||
# data5 = [17, 22, 82, 87, 88, 88] # ECG200*
|
||||
# data6 = [23, 43, 81.5, 100, 100, 100] # Ligning7*
|
||||
# labels = ['0.01', '0.02', '0.04', '0.06', '0.08', '0.1'] # x轴扰乱因子标记
|
||||
#
|
||||
# draw_diff_pert_info(data1, data2, data5, data6, labels, marker='o', linewidth=3,
|
||||
# filename='./论文插图2/SR3.pdf')
|
||||
#
|
||||
# 种群倍数
|
||||
# car_data_ani = [1, 1, 1, 1, 1]
|
||||
# ecg200_data_ani = [13.8, 9.4, 11.8, 13.5, 13]
|
||||
# italy_data_ani = [6.7, 4.8, 3.9, 5.2, 4.5]
|
||||
# ligning_ani = [8.78, 8.3, 8.2, 8.16, 8.2]
|
||||
# # car_data_mse = [0.0031, 0.003, 0.00315, 0.0032, 0.00325]
|
||||
# # ecg200_data_mse = [0.0066, 0.00655, 0.00652, 0.0068, 0.0067]
|
||||
# # italy_data_mse = [0.0024, 0.00245, 0.0024, 0.0026, 0.0027]
|
||||
# # ligning_mse = [0.0144, 0.0144, 0.0147, 0.0146, 0.0145]
|
||||
#
|
||||
# car_data_q = [544.00, 544.00, 544.00, 544.00, 544.00]
|
||||
# ecg200_data_q = [423, 469.5, 544, 693, 592]
|
||||
# italy_data_q = [39, 42.75, 49.05, 42.75, 48]
|
||||
# ligning_q = [380, 400, 400, 400, 400]
|
||||
# draw_times_diff_bar(car_data_ani, ecg200_data_ani, italy_data_ani, ligning_ani,
|
||||
# car_data_q, ecg200_data_q, italy_data_q, ligning_q,
|
||||
# 'Car', 'ECG200', 'Italy', 'Ligning7',
|
||||
# filename='./论文插图2/GT-ANI-bar.pdf',
|
||||
# rightLabel='Queries', leftLabel='ANI', times=1)
|
||||
|
||||
# 扰动因子2
|
||||
car_data_sr = [8.63,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2]
|
||||
|
||||
ecg200_data_sr = [7.25,
|
||||
16.591176470588238,
|
||||
12.325,
|
||||
5.8884375,
|
||||
3.8646153846153846]
|
||||
|
||||
italy_data_sr = [6.75,
|
||||
4.715714285714285,
|
||||
9.205416666666666,
|
||||
10.055915492957746,
|
||||
9.667916666666667]
|
||||
|
||||
ligning_sr = [15.417499999999999,
|
||||
15.142857142857142,
|
||||
7.199666666666667,
|
||||
3.9983333333333335,
|
||||
2.5326666666666666]
|
||||
|
||||
car_data_mse = [431.5810526,
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
100]
|
||||
|
||||
ecg200_data_mse = [362.5,
|
||||
829.4088235294118,
|
||||
616.1317741935484,
|
||||
294.53125,
|
||||
193.07507692307695]
|
||||
|
||||
italy_data_mse = [337.5,
|
||||
235.71285714285713,
|
||||
460.41625000000005,
|
||||
502.8149295774648,
|
||||
483.33214285714286]
|
||||
|
||||
ligning_mse = [770.8325000000001,
|
||||
757.1428571428571,
|
||||
359.99899999999997,
|
||||
200.001,
|
||||
126.66633333333333]
|
||||
|
||||
|
||||
draw_times_diff_bar(car_data_mse, ecg200_data_mse, italy_data_mse, ligning_mse,
|
||||
car_data_sr, ecg200_data_sr, italy_data_sr, ligning_sr,
|
||||
'Car', 'ECG200', 'Italy', 'Ligning7',
|
||||
filename='扰动因子.pdf', rightLabel='ANI', xlabel='$\\beta$',
|
||||
x_value=['0.01', '0.02', '0.04', '0.06', '0.08'], leftLabel='Queries',times=1)
|
||||
|
||||
|
||||
# 热力图
|
||||
# data1 = generate_heat_maps_array(count_classes_samples('/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/热力图/Lightning7', select_colum='Success'),
|
||||
# classes_size=7)
|
||||
|
||||
# data2 = generate_heat_maps_array(count_classes_samples('/Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/热力图/Plane', select_colum='Success'),
|
||||
# classes_size=7)
|
||||
|
||||
# heat_maps_of_classes(data1, data2,
|
||||
# '',
|
||||
# cbar_ticks1=[0, 1, 2, 3, 4], cbar_ticks2=[0, 1, 2, 3, 4], filename='热力图.pdf')
|
565
drawing_tool.py
Normal file
565
drawing_tool.py
Normal file
@ -0,0 +1,565 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib import patches
|
||||
from matplotlib.font_manager import FontProperties
|
||||
from matplotlib.ticker import FuncFormatter
|
||||
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
|
||||
import matplotlib.patheffects as pe
|
||||
|
||||
# 设置字体为 Times New Roman,并调整字体大小
|
||||
plt.rcParams['font.family'] = 'Times New Roman'
|
||||
plt.rcParams['font.size'] = 22 # 设置默认字体大小
|
||||
plt.rcParams['axes.titlesize'] = 26 # 设置标题字体大小
|
||||
plt.rcParams['axes.labelsize'] = 26 # 设置轴标签字体大小
|
||||
plt.rcParams['xtick.labelsize'] = 26 # 设置x轴刻度字体大小
|
||||
plt.rcParams['ytick.labelsize'] = 26 # 设置y轴刻度字体大小
|
||||
plt.rcParams['legend.fontsize'] = 20 # 设置图例字体大小
|
||||
import matplotlib
|
||||
from matplotlib.patches import FancyBboxPatch
|
||||
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
||||
|
||||
from analyzeTool import generate_heat_maps_array, count_classes_samples
|
||||
|
||||
matplotlib.use('MacOSX') # 使用MacOSX后端以兼容Mac
|
||||
|
||||
|
||||
# 绘制原始和扰动时间序列的函数
|
||||
def draw_ori_perturbed(ori_data, pert_data, dashed_lists=None, title=None, filename='comp_ori_pert_result.pdf',
|
||||
loc_sample='upper left', loc_sub='upper left', inset_range=None, xy=(0, 0), xytext=(0, 0)):
|
||||
color_1 = '#4B0082'
|
||||
color_2 = '#FF8C00'
|
||||
|
||||
# 将字符串数据转换为浮点数列表
|
||||
ori_ts = list(map(float, ori_data.split()))
|
||||
perturbed_ts = list(map(float, pert_data.split()))
|
||||
|
||||
length = len(ori_ts)
|
||||
x = np.arange(0, length, 1) # 生成从0到数据长度的x值
|
||||
|
||||
# 绘制数据
|
||||
plt.figure(figsize=(10, 5))
|
||||
plt.plot(x, ori_ts, label='Original', color=color_1, linewidth=5)
|
||||
plt.plot(x, perturbed_ts, label='Perturbed', color=color_2, linewidth=5)
|
||||
|
||||
# 添加虚线框
|
||||
if dashed_lists is None:
|
||||
dashed_lists = []
|
||||
if len(dashed_lists) > 0:
|
||||
for start, end in dashed_lists:
|
||||
max_len = max(max(ori_ts[start:end]), max(perturbed_ts[start:end]))
|
||||
min_len = min(min(ori_ts[start:end]), min(perturbed_ts[start:end]))
|
||||
plt.plot(
|
||||
[start, start, end, end, start],
|
||||
[min_len, max_len, max_len, min_len, min_len],
|
||||
linestyle='--', # 使用linestyle来指定虚线样式
|
||||
linewidth=4, # 线宽
|
||||
color='black'
|
||||
)
|
||||
|
||||
plt.xlim(-10, length + 10) # 设置x轴范围
|
||||
plt.legend(loc=loc_sample)
|
||||
plt.grid(True)
|
||||
|
||||
# 获取当前轴并设置边框宽度
|
||||
ax = plt.gca()
|
||||
for spine in ax.spines.values():
|
||||
spine.set_linewidth(2) # 设置边框线宽
|
||||
|
||||
# 添加局部放大
|
||||
if inset_range is not None:
|
||||
plt.annotate('', xy=xy, xytext=xytext,
|
||||
arrowprops=dict(arrowstyle='->', color='black', lw=3))
|
||||
inset_start, inset_end = inset_range
|
||||
ax_inset = inset_axes(plt.gca(), width="30%", height="30%", loc=loc_sub, borderpad=1) # 调整宽度和高度
|
||||
ax_inset.plot(x[inset_start:inset_end], ori_ts[inset_start:inset_end], label='Original', color=color_1,
|
||||
linewidth=4)
|
||||
ax_inset.plot(x[inset_start:inset_end], perturbed_ts[inset_start:inset_end], label='Perturbed', color=color_2,
|
||||
linewidth=4)
|
||||
ax_inset.set_xlim(inset_start, inset_end)
|
||||
ax_inset.grid(True)
|
||||
|
||||
# 移除插入图的坐标轴刻度
|
||||
ax_inset.set_xticks([])
|
||||
ax_inset.set_yticks([])
|
||||
|
||||
for spine in ax_inset.spines.values():
|
||||
spine.set_linewidth(2) # 设置边框线宽
|
||||
|
||||
if title is not None:
|
||||
# 使用 tight_layout 和 subplots_adjust 调整布局
|
||||
plt.tight_layout()
|
||||
plt.subplots_adjust(bottom=0.15) # 调整底部边距
|
||||
|
||||
# 在下方添加标题
|
||||
plt.figtext(0.5, 0.02, title, ha='center', fontsize=12)
|
||||
|
||||
plt.savefig(filename)
|
||||
plt.show()
|
||||
|
||||
|
||||
# 绘制原始和扰动时间序列的函数,带有放大视图
|
||||
def draw_ori_perturbed_with_inset(ori_data, pert_data, inset_start, inset_end):
|
||||
# 将字符串数据转换为浮点数列表
|
||||
ori_ts = list(map(float, ori_data.split()))
|
||||
perturbed_ts = list(map(float, pert_data.split()))
|
||||
|
||||
length = len(ori_ts)
|
||||
x = np.arange(0, length, 1) # 生成从0到数据长度的x值
|
||||
|
||||
# 创建主图
|
||||
fig, ax = plt.subplots(figsize=(10, 5))
|
||||
ax.plot(x, ori_ts, label='Original: Class 0', color='royalblue', linewidth=2)
|
||||
ax.plot(x, perturbed_ts, label='Perturbed: Class 1', color='tomato', linewidth=2)
|
||||
|
||||
ax.set_xlim(-20, length + 20) # 设置x轴范围
|
||||
ax.grid(True)
|
||||
|
||||
# 创建放大视图
|
||||
from mpl_toolkits.axes_grid1.inset_locator import inset_axes, mark_inset
|
||||
|
||||
# 定义放大区域
|
||||
inset_axes_params = {
|
||||
'width': '40%', # 放大视图的宽度
|
||||
'height': '40%', # 放大视图的高度
|
||||
'bbox_to_anchor': (-0.2, -0.1, 0.8, 0.8), # 偏移,尺寸
|
||||
'bbox_transform': ax.transAxes # 使用轴的变换
|
||||
}
|
||||
|
||||
# 创建放大视图轴
|
||||
ax_inset = inset_axes(ax, **inset_axes_params)
|
||||
|
||||
# 设置放大视图的范围
|
||||
ax_inset.plot(x, ori_ts, color='royalblue', linewidth=2)
|
||||
ax_inset.plot(x, perturbed_ts, color='tomato', linewidth=2)
|
||||
ax_inset.set_xlim(inset_start, inset_end)
|
||||
ax_inset.set_ylim(min(ori_ts[inset_start:inset_end]) - 0.5, max(ori_ts[inset_start:inset_end]) + 0.5)
|
||||
|
||||
# 移除放大视图中的刻度
|
||||
ax_inset.set_xticks([])
|
||||
ax_inset.set_yticks([])
|
||||
|
||||
# 标记放大区域并设置边框粗细和zorder(层次位置,越大越靠前),避免线条重叠在数据线上,loc1和loc2代表引导线的起始角
|
||||
mark_inset(ax, ax_inset, loc1=3, loc2=1, fc="none", ec="0.5", lw=2, zorder=10)
|
||||
|
||||
# 添加阴影效果到原图的标记框
|
||||
bbox_shadow = FancyBboxPatch((inset_start, min(ori_ts[inset_start:inset_end]) - 0.5),
|
||||
inset_end - inset_start,
|
||||
max(ori_ts[inset_start:inset_end]) - min(ori_ts[inset_start:inset_end]) + 1,
|
||||
boxstyle="round,pad=0.1",
|
||||
ec="none", fc="black", alpha=0.2,
|
||||
transform=ax.transData, zorder=2)
|
||||
ax.add_patch(bbox_shadow)
|
||||
|
||||
# 保存并展示图像
|
||||
plt.savefig('comp_ori_pert_inset_result.pdf')
|
||||
plt.show()
|
||||
|
||||
|
||||
def draw_times_diff(data1, data2, data3, data1_label, data2_label, data3_label):
|
||||
x = np.arange(1, 6)
|
||||
|
||||
# 创建图表
|
||||
plt.figure(figsize=(10, 5))
|
||||
plt.plot(x, data1, label=data1_label, color='royalblue', marker='o')
|
||||
plt.plot(x, data2, label=data2_label, color='tomato', marker='o')
|
||||
plt.plot(x, data3, label=data3_label, color='sandybrown', marker='o')
|
||||
|
||||
# 添加标签和图例
|
||||
plt.xlabel('Times of population size')
|
||||
plt.ylabel('MSE')
|
||||
plt.legend()
|
||||
plt.grid(True)
|
||||
|
||||
# 调整布局以防止标签被裁剪
|
||||
plt.tight_layout()
|
||||
plt.legend(loc='center right')
|
||||
|
||||
# 保存为PDF格式(矢量图)
|
||||
plt.savefig('line_chart_result.pdf', format='pdf')
|
||||
plt.show()
|
||||
|
||||
|
||||
def draw_times_diff_bar(data1, data2, data3, data4,
|
||||
line_data1, line_data2, line_data3, line_data4,
|
||||
data1_label, data2_label, data3_label, data4_label,
|
||||
filename='bar_chart_with_lines_and_legend_above.pdf', leftLabel='MSE (10^-3)', rightLabel='ANI',
|
||||
xlabel='Times of population size', x_value=None, times=1000):
|
||||
if x_value is None:
|
||||
x_value = ['1', '2', '3', '4', '5']
|
||||
x = np.arange(1, 6) # 假设有5个数据点
|
||||
|
||||
# 设置柱状图的宽度
|
||||
bar_width = 0.15
|
||||
|
||||
# 创建图表
|
||||
fig, ax1 = plt.subplots(figsize=(8, 5))
|
||||
|
||||
color1 = '#05B9E2'
|
||||
color2 = '#54B345'
|
||||
color3 = '#F27970'
|
||||
color4 = '#8983BF'
|
||||
|
||||
# 为每组数据创建柱状图,并添加黑色边框
|
||||
bars1 = ax1.bar(x - bar_width * 1.5, data1, width=bar_width, label=data1_label, color=color1, alpha=0.6,
|
||||
edgecolor='black')
|
||||
bars2 = ax1.bar(x - bar_width * 0.5, data2, width=bar_width, label=data2_label, color=color2, alpha=0.6,
|
||||
edgecolor='black')
|
||||
bars3 = ax1.bar(x + bar_width * 0.5, data3, width=bar_width, label=data3_label, color=color3, alpha=0.6,
|
||||
edgecolor='black')
|
||||
bars4 = ax1.bar(x + bar_width * 1.5, data4, width=bar_width, label=data4_label, color=color4, alpha=0.6,
|
||||
edgecolor='black')
|
||||
|
||||
# 设置左侧Y轴标签和格式
|
||||
ax1.set_xlabel(xlabel)
|
||||
ax1.set_ylabel(leftLabel)
|
||||
ax1.set_xticks(x)
|
||||
ax1.set_xticklabels(x_value)
|
||||
ax1.tick_params(axis='y')
|
||||
ax1.grid(axis='y') # 只显示y轴的网格线
|
||||
|
||||
for spine in ax1.spines.values():
|
||||
spine.set_linewidth(2) # 设置边框线宽
|
||||
|
||||
# 格式化y轴刻度为指数形式
|
||||
def to_exponential(x, _):
|
||||
return f'{x * times:.0f}'
|
||||
|
||||
ax1.yaxis.set_major_formatter(FuncFormatter(to_exponential))
|
||||
|
||||
# 创建右侧Y轴
|
||||
ax2 = ax1.twinx()
|
||||
ax2.plot(x, line_data1, color=color1, marker='o', linestyle='-', linewidth=2, markersize=8)
|
||||
ax2.plot(x, line_data2, color=color2, marker='o', linestyle='-', linewidth=2, markersize=8)
|
||||
ax2.plot(x, line_data3, color=color3, marker='o', linestyle='-', linewidth=2, markersize=8)
|
||||
ax2.plot(x, line_data4, color=color4, marker='o', linestyle='-', linewidth=2, markersize=8)
|
||||
ax2.set_ylabel(rightLabel)
|
||||
ax2.tick_params(axis='y')
|
||||
|
||||
# 将柱状图的图例放在图的上方,并设置字体大小
|
||||
bars_legend = ax1.legend(loc='upper center', bbox_to_anchor=(0.5, 1.2), ncol=4, frameon=False)
|
||||
|
||||
# 添加图例到图中
|
||||
ax1.add_artist(bars_legend)
|
||||
|
||||
# 调整布局以防止标签被裁剪
|
||||
plt.tight_layout(rect=[0, 0, 1, 0.95])
|
||||
|
||||
# 保存为PDF格式(矢量图)
|
||||
plt.savefig(filename, format='pdf')
|
||||
plt.show()
|
||||
|
||||
|
||||
def draw_diff_pert_info(data1, data2, data5, data6, labels, marker=None, linewidth=2, filename='line_chart_result.pdf'):
|
||||
x = np.arange(len(labels))
|
||||
|
||||
color1 = '#F27970'
|
||||
color2 = '#54B345'
|
||||
color3 = '#05B9E2'
|
||||
color4 = '#8983BF'
|
||||
|
||||
# 创建图表
|
||||
plt.figure(figsize=(7, 5))
|
||||
plt.plot(x, data1, label='Car', color=color1, marker=marker, linewidth=linewidth, markersize=8)
|
||||
plt.plot(x, data5, label='ECG200', color=color2, marker=marker, linewidth=linewidth, markersize=8)
|
||||
plt.plot(x, data2, label='Italy', color=color3, marker=marker, linewidth=linewidth, markersize=8)
|
||||
plt.plot(x, data6, label='Ligning7', color=color4, marker=marker, linewidth=linewidth, markersize=8)
|
||||
|
||||
# 添加标签和图例
|
||||
plt.xlabel('$\\beta$')
|
||||
plt.ylabel('Success Rate')
|
||||
plt.xticks(x, labels, rotation=0, ha='center')
|
||||
# plt.legend(loc='center right') # 图例位置和字体大小
|
||||
plt.grid(True) # 网格线
|
||||
|
||||
# 调整子图布局以防止重叠
|
||||
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
|
||||
|
||||
# 获取当前坐标轴对象
|
||||
ax = plt.gca()
|
||||
for spine in ax.spines.values():
|
||||
spine.set_linewidth(2) # 设置边框线宽
|
||||
|
||||
# 保存为PDF格式(矢量图)
|
||||
plt.savefig(filename, format='pdf')
|
||||
plt.show()
|
||||
|
||||
|
||||
# 画大表
|
||||
def draw_all_data_set_info(data1, data2, data3, data4, data5, labels):
|
||||
def replace_neg_ones_with_nan(data):
|
||||
"""
|
||||
将数据中的所有-1替换为np.nan。
|
||||
|
||||
参数:
|
||||
data (array-like): 输入数据数组。
|
||||
|
||||
返回:
|
||||
numpy.ndarray: 将-1替换为np.nan后的数据数组。
|
||||
"""
|
||||
return np.array([np.nan if x == -1 else x for x in data])
|
||||
|
||||
def move_neg_ones_to_end(arrays):
|
||||
for i in range(len(arrays)):
|
||||
# 跳过所有非数字数组
|
||||
if not isinstance(arrays[i][0], (int, float)):
|
||||
continue
|
||||
|
||||
# 记录每个数组中的元素和对应的索引
|
||||
elements = [(val, idx) for idx, val in enumerate(arrays[i])]
|
||||
|
||||
# 将-1移动到末尾
|
||||
sorted_elements = sorted(elements, key=lambda x: (x[0] == -1, 0))
|
||||
|
||||
# 重新排列每个数组
|
||||
for array in arrays:
|
||||
sorted_array = [array[elem[1]] for elem in sorted_elements]
|
||||
array[:] = sorted_array
|
||||
|
||||
# 修正数组
|
||||
move_neg_ones_to_end([labels, data1, data2, data3, data4, data5])
|
||||
|
||||
# 将数据集中的-1替换为NaN
|
||||
data1 = replace_neg_ones_with_nan(data1)
|
||||
data2 = replace_neg_ones_with_nan(data2)
|
||||
data3 = replace_neg_ones_with_nan(data3)
|
||||
data4 = replace_neg_ones_with_nan(data4)
|
||||
data5 = replace_neg_ones_with_nan(data5)
|
||||
|
||||
# 创建x轴的值
|
||||
x = np.arange(len(labels))
|
||||
|
||||
# 创建折线图
|
||||
plt.figure(figsize=(10, 5))
|
||||
plt.plot(x, data1, label='GATN MSE', color='black')
|
||||
plt.plot(x, data2, label='advGAN MSE', color='royalblue')
|
||||
plt.plot(x, data3, label='TSadv MSE $\\beta=0.04$', color='tomato')
|
||||
plt.plot(x, data4, label='CPadv MSE $\\beta=0.04$', color='sandybrown')
|
||||
plt.plot(x, data5, label='CPadv MSE $\\beta=0.02$', color='firebrick')
|
||||
|
||||
# 添加标签和图例
|
||||
plt.xlabel('')
|
||||
plt.ylabel('MSE')
|
||||
plt.xticks(x, labels, rotation=30, ha='right', fontsize=5, fontweight='bold')
|
||||
plt.legend(loc='upper right') # 标签位置
|
||||
plt.grid(False) # 网格线
|
||||
|
||||
# 调整布局以防止重叠
|
||||
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
|
||||
|
||||
# 添加标题
|
||||
plt.figtext(0.5, 0.01, 'Fig. 9. MSE results of TSadv over different $\\beta$ and GATN on 42 UCR datasets',
|
||||
ha='center', fontsize=12)
|
||||
|
||||
# 保存为PDF文件
|
||||
plt.savefig('line_chart_result.pdf', format='pdf')
|
||||
plt.show()
|
||||
|
||||
|
||||
def heat_maps_of_classes(ori_data1, ori_data2, title, labels=None, cbar_ticks1=None, cbar_ticks2=None,
|
||||
cmap_color='Blues', filename='heatmap.pdf'):
|
||||
"""
|
||||
生成两个数据集的并排热图,并将其保存为PDF文件。
|
||||
|
||||
参数:
|
||||
ori_data1 (list of int/float): 第一个数据集,将其可视化为热图。
|
||||
ori_data2 (list of int/float): 第二个数据集,将其可视化为热图。
|
||||
title (str): 热图的标题。
|
||||
labels (list of tuple of str, optional): 两个热图的x轴和y轴标签列表。默认值为[('', ''), ('', '')]。
|
||||
cbar_ticks1 (list of float, optional): 自定义color bar1的刻度列表。默认值为None。
|
||||
cbar_ticks2 (list of float, optional): 自定义color bar2的刻度列表。默认值为None。
|
||||
cmap_color (str): 热力图颜色,默认Blues
|
||||
"""
|
||||
# 设置字体
|
||||
# 设置颜色条的字体
|
||||
font = FontProperties()
|
||||
font.set_family('serif')
|
||||
font.set_name('Times New Roman')
|
||||
font.set_size(20) # 设置字体大小
|
||||
|
||||
# 数据
|
||||
if labels is None:
|
||||
labels = [('', ''), ('', '')]
|
||||
data1 = np.array(ori_data1)
|
||||
data2 = np.array(ori_data2)
|
||||
|
||||
fig, axs = plt.subplots(1, 2, figsize=(8, 3), gridspec_kw={'wspace': 0.4})
|
||||
|
||||
# 第一个子图
|
||||
cax1 = axs[0].matshow(data1, cmap=cmap_color, alpha=0.8, vmin=min(cbar_ticks1), vmax=max(cbar_ticks1))
|
||||
|
||||
# 添加网格
|
||||
axs[0].set_xticks(np.arange(data1.shape[1] + 1) - 0.5, minor=True)
|
||||
axs[0].set_yticks(np.arange(data1.shape[0] + 1) - 0.5, minor=True)
|
||||
axs[0].grid(which='minor', color='gray', linestyle='-', linewidth=0.5)
|
||||
|
||||
# 创建第一个子图的颜色条
|
||||
divider1 = make_axes_locatable(axs[0])
|
||||
cax1_cb = divider1.append_axes("right", size="5%", pad=0.1)
|
||||
cb1 = fig.colorbar(cax1, cax=cax1_cb)
|
||||
if cbar_ticks1:
|
||||
cb1.set_ticks(cbar_ticks1)
|
||||
# 应用字体设置到颜色条的标签
|
||||
cb1.ax.yaxis.set_tick_params(labelsize=12)
|
||||
for label in cb1.ax.get_yticklabels():
|
||||
label.set_fontproperties(font)
|
||||
|
||||
# 第二个子图
|
||||
cax2 = axs[1].matshow(data2, cmap=cmap_color, alpha=0.8, vmin=min(cbar_ticks2), vmax=max(cbar_ticks2))
|
||||
|
||||
# 添加网格
|
||||
axs[1].set_xticks(np.arange(data2.shape[1] + 1) - 0.5, minor=True)
|
||||
axs[1].set_yticks(np.arange(data2.shape[0] + 1) - 0.5, minor=True)
|
||||
axs[1].grid(which='minor', color='gray', linestyle='-', linewidth=0.5)
|
||||
|
||||
# 创建第二个子图的颜色条
|
||||
divider2 = make_axes_locatable(axs[1])
|
||||
cax2_cb = divider2.append_axes("right", size="5%", pad=0.1)
|
||||
cb2 = fig.colorbar(cax2, cax=cax2_cb)
|
||||
if cbar_ticks2:
|
||||
cb2.set_ticks(cbar_ticks2)
|
||||
cb2.ax.yaxis.set_tick_params(labelsize=12)
|
||||
for label in cb2.ax.get_yticklabels():
|
||||
label.set_fontproperties(font)
|
||||
|
||||
for i in range(2):
|
||||
axs[i].tick_params(axis='both', which='major', labelsize=12)
|
||||
axs[i].xaxis.set_ticks_position('bottom')
|
||||
axs[i].xaxis.set_label_position('bottom')
|
||||
axs[i].invert_yaxis()
|
||||
for label in (axs[i].get_xticklabels() + axs[i].get_yticklabels()):
|
||||
label.set_fontproperties(font)
|
||||
|
||||
# 设置xy轴刻度间隔为1
|
||||
axs[0].set_xticks(np.arange(data1.shape[1]))
|
||||
axs[0].set_yticks(np.arange(data1.shape[0]))
|
||||
axs[1].set_xticks(np.arange(data2.shape[1]))
|
||||
axs[1].set_yticks(np.arange(data2.shape[0]))
|
||||
|
||||
# 添加描述文字
|
||||
plt.figtext(0.5, 0.01, title, ha='center', va='center', fontsize=10, fontname='Times New Roman')
|
||||
|
||||
# 保存为矢量图(PDF格式)
|
||||
plt.savefig(filename, format='pdf', bbox_inches='tight')
|
||||
|
||||
# 显示图像
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 攻击样本对比
|
||||
# original_data = "0.95110175 0.03860069 0.001077176 0.001077176 0.001077176 -0.028107779 0.0052464556 -0.036446338 -0.040615617 -0.036446338 -0.028107779 -0.078139131 -0.08647769 -0.044784896 -0.078139131 -0.057292734 -0.057292734 -0.094816249 -0.08647769 -0.069800573 -0.069800573 -0.08647769 -0.1240012 -0.11566264 -0.078139131 -0.094816249 -0.094816249 -0.14067832 -0.14067832 -0.090646969 -0.14901688 -0.16986328 -0.098985528 -0.15735544 -0.1240012 -0.061462014 -0.0072613824 -0.0072613824 0.071954926 0.096970602 -0.032277059 -0.13233976 -0.19070967 -0.27826454 -0.21572535 -0.27409526 -0.26992598 -0.28660309 -0.25741814 -0.28243382 -0.24907958 -0.24907958 -0.24907958 -0.2240639 -0.098985528 1.0600742 1.7771901 -0.82027086 -3.8930297 -5.3647854 -4.0431238 -2.2294872 -1.0287348 -0.44920499 -0.23240247 -0.1240012 -0.08647769 -0.015599941 0.017754294 0.03860069 0.063616366 0.10530916 0.10530916 0.18869474 0.18035619 0.28458817 0.40549727 0.46803646 0.60979196 0.75988602 0.93499575 1.2018296 1.5312027 1.8522372 2.1565946 2.4943062 2.7402937 2.9445884 2.9154034 2.5443376 2.0148391 1.3811086 0.85161016 0.45135934 0.21371042 0.071954926 -0.0239385 -0.078139131 -0.10315481 -0.08647769 -0.13233976 -0.094816249 -0.090646969 -0.044784896 -0.053123455 -0.044784896 -0.057292734 -0.10315481 -0.08647769 -0.08647769 -0.11566264 -0.15735544 -0.165694 -0.20321751 -0.21572535 -0.28243382 -0.28243382 -0.26992598 -0.29077238 -0.3074495 -0.34914228 -0.34080373 -0.33246517 -0.34914228 -0.32829589 -0.34080373 -0.3658194 -0.3658194 -0.37832724 -0.38249653 -0.39083508 -0.39917364 -0.39500436 -0.39083508 -0.43252788 -0.40334292"
|
||||
# perturbed_data = "0.9546 0.0387 0.0011 0.0011 0.0011 -0.0282 0.0053 -0.0366 -0.0408 -0.0366 -0.0282 -0.0784 -0.0868 -0.0450 -0.0784 -0.0575 -0.0575 -0.0952 -0.0868 -0.0701 -0.0701 -0.0868 -0.1245 -0.1161 -0.0784 -0.0952 -0.0952 -0.1412 -0.1412 -0.0910 -0.1496 -0.1705 -0.0994 -0.1579 -0.1245 -0.0617 -0.0073 -0.0073 0.0722 0.0973 -0.0324 -0.1328 -0.1914 -0.2793 -0.2165 -0.2751 -0.2709 -0.2877 -0.2584 -0.1592 -0.2146 0.0321 -0.0189 0.0241 0.1806 1.3527 1.6821 -1.0405 -3.7122 -5.2477 -4.2234 -2.4362 -1.3062 -0.6095 -0.2333 -0.1245 -0.0868 -0.0157 0.0178 0.0387 0.0639 0.1057 0.1057 0.1894 0.1810 0.4762 0.2598 0.1544 0.2773 0.8633 0.8632 1.0042 1.3689 1.9531 2.3896 2.7358 2.7239 2.8305 2.7696 2.5007 2.0223 1.3862 0.8548 0.4530 0.2145 0.0722 -0.0240 -0.0784 -0.1035 -0.0868 -0.1328 -0.0952 -0.0910 -0.0450 -0.0533 -0.0450 -0.0575 -0.1035 -0.0868 -0.0868 -0.1161 -0.1579 -0.1663 -0.2040 -0.2165 -0.2835 -0.2835 -0.2709 -0.2918 -0.3086 -0.3504 -0.3421 -0.3337 -0.3504 -0.3295 -0.3421 -0.3672 -0.3672 -0.3797 -0.3839 -0.3923 -0.4006 -0.3965 -0.3923 -0.4341 -0.4048"
|
||||
# # # 样本4成功
|
||||
# # -0.4898 -0.4707 -0.4611 -0.4323 -0.4898 -0.4515 -0.4036 -0.4228 -0.4898 -0.4707 -0.3461 -0.4132 -0.4898 -0.3173 -0.4707 -0.2982 -0.3653 -0.2886 -0.3461 -0.2694 -0.3844 -0.3077 -0.3365 -0.3269 -0.2119 -0.2598 -0.2694 -0.2311 -0.3269 -0.2215 -0.2694 -0.1640 -0.1256 0.0660 0.0564 -0.0202 -0.1927 -0.4803 -0.5569 -0.3077 -0.3557 -0.2119 -0.2502 -0.2694 -0.2311 -0.2790 -0.0969 -0.0011 -0.0969 0.1653 0.2051 0.2683 0.8980 -0.2241 -4.2003 -6.0178 -4.5483 -3.0059 -1.3216 -0.5447 -0.2506 0.1809 -0.1301 0.4711 0.2481 0.2673 0.2385 0.2865 0.2673 0.3631 0.3823 0.3056 0.3823 0.4877 0.5261 0.9649 0.6908 0.7372 0.6360 0.8578 1.0912 1.5034 1.6566 1.7832 2.1861 2.5592 2.3825 1.6257 1.4009 0.9878 0.4590 0.3248 0.2194 0.2290 0.1906 0.1906 0.1715 0.1906 0.1906 0.1906 0.3344 0.1715 0.2290 0.2098 0.2481 0.2098 0.2194 0.2385 0.1715 0.2673 0.2290 0.2098 0.2098 0.2769 0.1715 0.2002 0.1810 0.1715 0.1906 0.1810 0.2098 0.1715 0.1906 0.1140 0.2290 0.1906 0.1619 0.2290 0.2481 0.2290 0.2481 0.2290 0.1715 0.1906 0.2002 0.2481
|
||||
# draw_ori_perturbed(original_data, perturbed_data,
|
||||
# [(49, 64), (75, 90)],
|
||||
# '') # 可以添加多个虚线框
|
||||
# draw_ori_perturbed_with_inset(original_data, perturbed_data, 220, 230)
|
||||
# draw_ori_perturbed(original_data, perturbed_data)
|
||||
|
||||
# 种群倍数
|
||||
# car_data = [1, 1, 1, 1, 1]
|
||||
# ecg200_data = [10.2, 9.2, 8.3, 10, 8.7]
|
||||
# italy_data = [6.7, 5.8, 4.2, 6.2, 6.2]
|
||||
# car_data = [0.0031, 0.003, 0.00315, 0.0032, 0.00325]
|
||||
# ecg200_data = [0.0066, 0.00655, 0.00652, 0.0068, 0.0067]
|
||||
# italy_data = [0.0024, 0.00245, 0.0024, 0.0026, 0.0027]
|
||||
# draw_times_diff_bar(car_data, ecg200_data, italy_data, 'Car', 'ECG200', 'ItalyPowerDemand')
|
||||
|
||||
# 大表MSE
|
||||
# labels = [
|
||||
# "Car", "Chlorine", "CinCECGTorso", "Earthquakes", "ECG200",
|
||||
# "ECG5000", "ECGFiveDays", "FordA", "FordB", "InsectWngSnd",
|
||||
# "ItalyPowerDemand", "Lightning2", "Lightning7", "MoteStrain", "NonIFECGTho1",
|
||||
# "NonIFECGTho2", "Phoneme", "Plane", "SonyAIBOSurf1", "SonyAIBOSurf2",
|
||||
# "StarLightCurves", "Trace", "TwoLeadECG", "Wafer", "AllGestureWiimoteX",
|
||||
# "AllGestureWiimoteY", "AllGestureWiimoteZ", "FreezerRegularTrain", "FreezerSmallTrain", "PickupGestureZ",
|
||||
# "PigAirwayPressure", "PigArtPressure", "PigCVP", "ShakeGestureZ", "Fungi",
|
||||
# "GesturePebbleZ1", "GesturePebbleZ2", "DodgerLoopDay", "DodgerLoopWeekend", "DodgerLoopGame",
|
||||
# "EOGHorizontalSignal", "EOGVerticalSignal"
|
||||
# ]
|
||||
#
|
||||
# GATN = [
|
||||
# 0.1130, 0.2690, 0.0490, 0.1220, 0.1380,
|
||||
# 0.1530, 0.0830, 0.1130, 0.1190, 0.1580,
|
||||
# 0.0800, 0.1330, 0.1320, 0.1430, 0.0840,
|
||||
# 0.0870, 0.0750, 0.2730, 0.1680, 0.1790,
|
||||
# 0.0640, 0.0780, 0.1080, 0.1330, 0.1200,
|
||||
# 0.1220, 0.1090, 0.1490, 0.1310, 0.1350,
|
||||
# 0.0400, 0.0380, 0.0410, 0.1220, 0.2050,
|
||||
# 0.1290, 0.1300, 0.0950, 0.1370, 0.0260,
|
||||
# 0.0580, 0.0640
|
||||
# ]
|
||||
#
|
||||
# advGAN = [
|
||||
# 0.246, 0.1223, 0.138, -1, 0.1257,
|
||||
# 0.1796, 0.0331, 0.2281, 0.2466, 0.1306,
|
||||
# 0.2473, 0.2102, 0.1856, 0.2194, 0.1587,
|
||||
# 0.2434, 0.1778, 0.1774, 0.1924, 0.2033,
|
||||
# 0.1479, 0.0406, 0.1169, 0.0743, 0.2397,
|
||||
# 0.1447, 0.1936, 0.0533, 0.0624, 0.1253,
|
||||
# -1, -1, -1, 0.1421, 0.1388,
|
||||
# 0.124, 0.1386, -1, -1, -1,
|
||||
# -1, -1
|
||||
# ]
|
||||
#
|
||||
# TS_adv4 = [
|
||||
# 0.0013, 0.0111, 0.017, 0.0052, 0.0079,
|
||||
# 0.0062, 0.0139, 0.0067, 0.0079, 0.0063,
|
||||
# 0.0036, 0.0383, 0.0138, 0.0048, 0.0085,
|
||||
# 0.0049, 0.0048, 0.0068, 0.0063, 0.0073,
|
||||
# 0.0022, 0.0024, 0.0034, 0.0031, 0.0201,
|
||||
# 0.0096, 0.0019, 0.0012, 0.001, 0.006,
|
||||
# 0.0022, 0.0014, 0.0052, 0.0087, 0.0086,
|
||||
# 0.0345, 0.0204, 0.003, 0.003, 0.0044,
|
||||
# 0.0023, 0.0043
|
||||
# ]
|
||||
#
|
||||
# CP_adv4 = [
|
||||
# 0.0029, 0.0042, 0.0179, 0.0042, 0.0065,
|
||||
# 0.0085, 0.0092, 0.0091, 0.0094, 0.0064,
|
||||
# 0.0042, 0.0208, 0.0143, 0.004, 0.0112,
|
||||
# 0.0097, 0.0186, 0.0055, 0.0051, 0.0069,
|
||||
# 0.0032, 0.0013, 0.0039, 0.0032, 0.0203,
|
||||
# 0.0126, 0.0057, 0.0011, 0.0017, 0.005,
|
||||
# 0.0045, 0.0044, 0.0058, 0.0097, 0.0066,
|
||||
# 0.0281, 0.0226, 0.0036, 0.0038, 0.0057,
|
||||
# 0.0043, 0.0051
|
||||
# ]
|
||||
#
|
||||
# CP_adv2 = [
|
||||
# 0.0008, 0.0011, 0.0046, 0.0011, 0.0018,
|
||||
# 0.0022, 0.0027, 0.0023, 0.0024, 0.0016,
|
||||
# 0.0008, 0.006, 0.0038, 0.0011, 0.0029,
|
||||
# 0.0026, 0.0046, 0.0006, 0.0014, 0.0016,
|
||||
# 0.0008, -1, 0.0012, 0.0008, 0.0052,
|
||||
# 0.0031, 0.0014, 0.0003, 0.0004, 0.0013,
|
||||
# 0.0011, 0.0011, 0.0013, 0.0023, 0.0022,
|
||||
# 0.0067, 0.0053, 0.0009, 0.001, 0.0014,
|
||||
# 0.0011, 0.0013
|
||||
# ]
|
||||
#
|
||||
# draw_all_data_set_info(GATN, advGAN, TS_adv4, CP_adv4, CP_adv2, labels)
|
||||
|
||||
# 画不同扰乱因子下,mse/ani对比图
|
||||
|
||||
# 扰动因子和成功率
|
||||
# data1 = [52, 81, 81, 81, 81, 81] # Car
|
||||
# # data2 = [1, 8, 8, 19, 18, 29] # ItalyPowerDemand
|
||||
# data3 = [3, 12, 17, 42, 59, 77] # SonyAIBORobotSurface2
|
||||
# data4 = [0, 4, 65, 78, 78, 78] # Plane
|
||||
# data5 = [17, 22, 82, 87, 88, 88] # ECG200
|
||||
# data6 = [23, 43, 81.5, 100, 100, 100] # Ligning7
|
||||
# labels = ['0.01', '0.02', '0.04', '0.06', '0.08', '0.1'] # x轴扰乱因子标记
|
||||
#
|
||||
# draw_diff_pert_info(data1, data3, data4, data5, data6, labels,marker='o',linewidth=3)
|
||||
|
||||
# 热力图
|
||||
# data1 = generate_heat_maps_array(count_classes_samples('result_0.08_6_f/Lightning7', select_colum='Success'),
|
||||
# classes_size=7)
|
||||
#
|
||||
# data2 = generate_heat_maps_array(count_classes_samples('result_0.08_8_f/Plane', select_colum='Success'),
|
||||
# classes_size=7)
|
||||
#
|
||||
# heat_maps_of_classes(data1, data2, '', cbar_ticks1=[2,4,6,8,10], cbar_ticks2=[3,6,9,12,15,18])
|
||||
pass
|
375
ex.py
Normal file
375
ex.py
Normal file
@ -0,0 +1,375 @@
|
||||
import warnings
|
||||
|
||||
import matplotlib
|
||||
|
||||
# matplotlib.use('Agg')
|
||||
|
||||
import networkx as nx
|
||||
import matplotlib.pyplot as plt
|
||||
matplotlib.use('Agg')
|
||||
import numpy as np
|
||||
import torch
|
||||
import pandas as pd
|
||||
import ruptures as rpt
|
||||
from scipy.optimize import differential_evolution
|
||||
from sklearn.metrics import mean_squared_error
|
||||
from query_probability import query_one, load_ucr
|
||||
warnings.filterwarnings('ignore')
|
||||
|
||||
|
||||
def detect_change_points(data, model="l2", pen=1):
|
||||
algo = rpt.Pelt(model=model,min_size=1,jump=1).fit(data)
|
||||
#algo = rpt.Binseg(model=model, min_size=1, jump=1).fit(data)
|
||||
bkps = algo.predict(pen=pen)
|
||||
#print('=======',bkps)
|
||||
return bkps
|
||||
|
||||
def build_local_graph(data, center_index, window_size):
|
||||
"""构建局部图"""
|
||||
start = max(0, center_index - window_size // 2)
|
||||
end = min(len(data), center_index + window_size // 2)
|
||||
G = nx.Graph()
|
||||
for i in range(start, end):
|
||||
for j in range(i + 1, end):
|
||||
weight = np.linalg.norm(data[i] - data[j])
|
||||
G.add_edge(i, j, weight=weight)
|
||||
return G
|
||||
|
||||
def find_important_nodes_via_components(G):
|
||||
"""使用连通分量动态确定次要变点的数量"""
|
||||
components = list(nx.connected_components(G))
|
||||
important_nodes = []
|
||||
for component in components:
|
||||
if len(component) > 1: # 考虑大于一个节点的组件
|
||||
important_nodes.extend(component)
|
||||
return list(important_nodes)
|
||||
|
||||
def process_change_points(data, change_points, window_size):
|
||||
all_important_nodes = set()
|
||||
for cp in change_points:
|
||||
G = build_local_graph(data, cp, window_size)
|
||||
important_nodes = find_important_nodes_via_components(G)
|
||||
print(cp, '------', important_nodes)
|
||||
all_important_nodes.update(important_nodes)
|
||||
all_important_nodes.update((change_points))
|
||||
return all_important_nodes
|
||||
|
||||
def get_magnitude(run_tag, factor, normalize,gpu):
|
||||
'''
|
||||
:param run_tag:
|
||||
:param factor:
|
||||
:return: Perturbed Magnitude
|
||||
'''
|
||||
data = load_ucr('data/' + run_tag + '/' + run_tag + '_attack'+gpu+'.txt', normalize=normalize)
|
||||
X = data[:, 1:]
|
||||
|
||||
max_magnitude = X.max(1)
|
||||
min_magnitude = X.min(1)
|
||||
mean_magnitude = np.mean(max_magnitude - min_magnitude)
|
||||
|
||||
perturbed_mag = mean_magnitude * factor
|
||||
print('Perturbed Magnitude:', perturbed_mag)
|
||||
|
||||
return perturbed_mag
|
||||
|
||||
|
||||
class Attacker:
|
||||
|
||||
def __init__(self, run_tag, model_type, cuda, normalize, e,device,gpu):
|
||||
self.run_tag = run_tag
|
||||
self.model_type = model_type
|
||||
self.cuda = cuda
|
||||
#self.intervals = get_attack_position(self.run_tag, self.top_k)
|
||||
self.normalize = normalize
|
||||
self.e = e
|
||||
self.device = device
|
||||
self.gpu = gpu
|
||||
|
||||
def perturb_ts(self, perturbations, ts, attack_pos):
|
||||
'''
|
||||
:param perturbations:formalized as a tuple(x,e),x(int) is the x-coordinate,e(float) is the epsilon,e.g.,(2,0.01)
|
||||
:param ts: time series
|
||||
:return: perturbed ts
|
||||
'''
|
||||
# first we copy a ts
|
||||
|
||||
ts_tmp = np.copy(ts)
|
||||
|
||||
coordinate = 0 # 初始化perturbations数组的索引
|
||||
for i in range(len(attack_pos)):
|
||||
if attack_pos[i] == 1:
|
||||
ts_tmp[i] += perturbations[coordinate]
|
||||
coordinate += 1
|
||||
# for interval in self.intervals:
|
||||
# for i in range(int(interval[0]), int(interval[1])):
|
||||
# ts_tmp[i] += perturbations[coordinate]
|
||||
# coordinate += 1
|
||||
return ts_tmp
|
||||
|
||||
def plot_per(self, perturbations, ts, target_class, sample_idx,attack_pos, prior_probs, attack_probs, factor):
|
||||
|
||||
# Obtain the perturbed ts
|
||||
ts_tmp = np.copy(ts)
|
||||
ts_perturbed = self.perturb_ts(perturbations=perturbations, ts=ts, attack_pos=attack_pos)
|
||||
# Start to plot
|
||||
plt.figure(figsize=(6, 4))
|
||||
plt.plot(ts_tmp, color='b', label='Original %.2f' % prior_probs)
|
||||
plt.plot(ts_perturbed, color='r', label='Perturbed %.2f' % attack_probs)
|
||||
plt.xlabel('Time', fontsize=12)
|
||||
|
||||
if target_class == -1:
|
||||
plt.title('Untargeted: Sample %d, eps_factor=%.3f' %
|
||||
(sample_idx, factor), fontsize=14)
|
||||
else:
|
||||
plt.title('Targeted(%d): Sample %d, eps_factor=%.3f' %
|
||||
(target_class, sample_idx, factor), fontsize=14)
|
||||
|
||||
plt.legend(loc='upper right', fontsize=8)
|
||||
plt.savefig('result_' + str(factor) + '_' + str(self.model_type) + '/'
|
||||
+ self.run_tag + '/figures'+self.gpu+'/' + self.run_tag +'_' + str(sample_idx) + '.png')
|
||||
# plt.show()
|
||||
|
||||
def fitness(self, device,perturbations, ts, sample_idx, queries,attack_pos, target_class=-1):
|
||||
#device = torch.device("cuda:0" if self.cuda else "cpu")
|
||||
perturbations = torch.tensor(perturbations).to(device)
|
||||
#ts = torch.tensor(ts, device='cuda')
|
||||
|
||||
queries[0] += 1
|
||||
|
||||
ts_perturbed = self.perturb_ts(perturbations, ts,attack_pos = attack_pos)
|
||||
prob, _, _, _, _ = query_one(run_tag=self.run_tag,device=device, idx=sample_idx, attack_ts=ts_perturbed,
|
||||
target_class=target_class, normalize=self.normalize,
|
||||
cuda=self.cuda, model_type=self.model_type, e=self.e,gpu=self.gpu)
|
||||
prob = torch.tensor(prob)
|
||||
|
||||
if target_class != -1:
|
||||
prob = 1 - prob
|
||||
|
||||
return prob # The fitness function is to minimize the fitness value
|
||||
|
||||
def attack_success(self,device,perturbations, ts, sample_idx, attack_pos, iterations, target_class=-1, verbose=True):
|
||||
iterations[0] += 1
|
||||
print('The %d iteration' % iterations[0])
|
||||
ts_perturbed = self.perturb_ts(perturbations, ts, attack_pos)
|
||||
#ts_perturbed = torch.tensor(ts_perturbed, device='cuda')
|
||||
# Obtain the perturbed probability vector and the prior probability vector
|
||||
prob, prob_vector, prior_prob, prior_prob_vec, real_label = query_one(self.run_tag, device,idx=sample_idx,
|
||||
attack_ts=ts_perturbed,
|
||||
target_class=target_class,
|
||||
normalize=self.normalize,
|
||||
verbose=verbose, cuda=self.cuda,
|
||||
model_type=self.model_type,
|
||||
e=self.e,gpu=self.gpu)
|
||||
|
||||
predict_class = torch.argmax(prob_vector).to(device)
|
||||
prior_class = torch.argmax(prior_prob_vec).to(device)
|
||||
real_label = real_label.to(device)
|
||||
|
||||
# Conditions for early termination(empirical-based estimation), leading to save the attacking time
|
||||
# But it may judge incorrectly that this may decrease the success rate of the attack.
|
||||
if (iterations[0] > 5 and prob > 0.99) or \
|
||||
(iterations[0] > 20 and prob > 0.9):
|
||||
print('The %d sample is not expected to successfully attack.' % sample_idx)
|
||||
print('prob: ',prob)
|
||||
return True
|
||||
|
||||
if prior_class != real_label:
|
||||
print('The %d sample cannot be classified correctly, no need to attack' % sample_idx)
|
||||
return True
|
||||
|
||||
if prior_class == target_class:
|
||||
print(
|
||||
'The true label of %d sample equals to target label, no need to attack' % sample_idx)
|
||||
return True
|
||||
|
||||
if verbose:
|
||||
print('The Confidence of current iteration: %.4f' % prob)
|
||||
print('########################################################')
|
||||
|
||||
# The criterion of attacking successfully:
|
||||
# Untargeted attack: predicted label is not equal to the original label.
|
||||
# Targeted attack: predicted label is equal to the target label.
|
||||
if ((target_class == -1 and predict_class != prior_class) or
|
||||
(target_class != -1 and predict_class == target_class)):
|
||||
print('##################### Attack Successfully! ##########################')
|
||||
|
||||
return True
|
||||
|
||||
def attack(self, sample_idx,device, target_class=-1, factor=0.04,
|
||||
max_iteration=50, popsize=200, verbose=True):
|
||||
|
||||
test = load_ucr('data/' + self.run_tag + '/' + self.run_tag + '_attack'+self.gpu+'.txt'
|
||||
, normalize=self.normalize)
|
||||
#attack_poses = np.loadtxt('data/' + self.run_tag + '/' + self.run_tag + '_attackPos'+self.gpu+'.txt')
|
||||
|
||||
ori_ts = test[sample_idx][1:]
|
||||
#变点检测找区间
|
||||
length = ori_ts.shape
|
||||
|
||||
result = detect_change_points(ori_ts)
|
||||
sampled_indices = np.zeros(len(ori_ts), dtype=int)
|
||||
if length[0] > 500 or len(result) > 0.4 * length[0]:
|
||||
|
||||
# 设置基本窗口大小和基本采样密度
|
||||
base_window_size = 0
|
||||
base_density_factor = 0.01
|
||||
else:
|
||||
# 设置基本窗口大小和基本采样密度
|
||||
base_window_size = int(0.1 * length[0])
|
||||
base_density_factor = 0.5
|
||||
|
||||
# 计算变点的重要性并调整窗口大小和采样密度
|
||||
for i, cp in enumerate(result[:-1]):
|
||||
# 计算变点前后的统计差异
|
||||
if i == 0:
|
||||
pre_mean = np.mean(ori_ts[:cp])
|
||||
else:
|
||||
pre_mean = np.mean(ori_ts[result[i - 1]:cp])
|
||||
post_mean = np.mean(ori_ts[cp:result[i + 1]])
|
||||
|
||||
# 重要性评估:差异的绝对值
|
||||
importance = abs(post_mean - pre_mean)
|
||||
|
||||
# 动态调整窗口大小和采样密度
|
||||
if length[0] > 500 or len(result) > 0.1 * length[0]:
|
||||
window_size = int(base_window_size + int(importance * 5)) # 重要性越大,窗口越大
|
||||
density_factor = base_density_factor + importance * 0.1 # 重要性越大,采样密度越高
|
||||
else:
|
||||
window_size = int(base_window_size + int(importance * 10)) # 重要性越大,窗口越大
|
||||
density_factor = base_density_factor + importance * 0.3 # 重要性越大,采样密度越高
|
||||
|
||||
|
||||
# 设置窗口的开始和结束位置
|
||||
start = max(cp - window_size // 2, 0)
|
||||
end = min(cp + window_size // 2, len(ori_ts))
|
||||
|
||||
# 在窗口内随机采样
|
||||
sample_count = int((end - start) * density_factor)
|
||||
if sample_count > 0:
|
||||
samples = np.random.choice(range(start, end), sample_count, replace=True)
|
||||
sampled_indices[samples] = 1
|
||||
attack_pos = sampled_indices
|
||||
|
||||
#attack_pos = attack_poses[sample_idx,:]
|
||||
# attack_pos = attack_poses.head(sample_idx)
|
||||
# attack_pos = attack_pos.apply(pd.to_numeric, errors='coerce').fillna(0)
|
||||
|
||||
#ori_ts = torch.tensor(ori_ts).to(device)
|
||||
attacked_probs, attacked_vec, prior_probs, prior_vec, real_label = query_one(self.run_tag,device,idx=sample_idx,
|
||||
attack_ts=ori_ts,
|
||||
target_class=target_class,
|
||||
normalize=self.normalize,
|
||||
verbose=False,
|
||||
cuda=self.cuda, e=self.e,
|
||||
model_type=self.model_type,gpu=self.gpu)
|
||||
prior_class = torch.argmax(prior_vec).to(device)
|
||||
if prior_class != real_label:
|
||||
print('The %d sample cannot be classified correctly, no need to attack' % sample_idx)
|
||||
return ori_ts,ori_ts, [prior_probs, attacked_probs, 0, 0, 0, 0, 0, 'WrongSample']
|
||||
|
||||
|
||||
# Get the maximum perturbed magnitude
|
||||
perturbed_magnitude = get_magnitude(self.run_tag, factor, normalize=self.normalize,gpu=self.gpu)
|
||||
|
||||
bounds = []
|
||||
|
||||
# for interval in self.intervals:
|
||||
# steps_count += int(interval[1]) - int(interval[0])
|
||||
# for i in range(int(interval[0]), int(interval[1])):
|
||||
# bounds.append((-1 * perturbed_magnitude, perturbed_magnitude))
|
||||
steps_count = attack_pos.sum()
|
||||
for i in range(len(attack_pos)):
|
||||
if attack_pos[i] == 1:
|
||||
bounds.append((-1 * perturbed_magnitude, perturbed_magnitude))
|
||||
|
||||
print('The length of shapelet interval', steps_count)
|
||||
#print('The length of bounds', len(bounds))
|
||||
popmul = max(1, popsize // len(bounds))
|
||||
# Record of the number of iterations
|
||||
iterations = [0]
|
||||
queries = [0]
|
||||
|
||||
def fitness_fn(perturbations):
|
||||
|
||||
return self.fitness(perturbations=perturbations, ts=ori_ts, queries=queries,
|
||||
sample_idx=sample_idx, attack_pos=attack_pos,target_class=target_class,device=device)
|
||||
|
||||
def callback_fn(x, convergence):
|
||||
|
||||
return self.attack_success(perturbations=x, ts=ori_ts,
|
||||
sample_idx=sample_idx,
|
||||
attack_pos = attack_pos,
|
||||
iterations=iterations,
|
||||
target_class=target_class,
|
||||
verbose=verbose,device=device)
|
||||
|
||||
attack_result = differential_evolution(func=fitness_fn, bounds=bounds
|
||||
, maxiter=max_iteration, popsize=popmul
|
||||
, recombination=0.7, callback=callback_fn,
|
||||
atol=-1, polish=False)
|
||||
|
||||
attack_ts = self.perturb_ts(attack_result.x, ori_ts, attack_pos)
|
||||
|
||||
mse = mean_squared_error(ori_ts, attack_ts)
|
||||
|
||||
attacked_probs, attacked_vec, prior_probs, prior_vec, real_label = query_one(self.run_tag,device, idx=sample_idx,
|
||||
attack_ts=attack_ts,
|
||||
target_class=target_class,
|
||||
normalize=self.normalize,
|
||||
verbose=False,
|
||||
cuda=self.cuda, e=self.e,
|
||||
model_type=self.model_type,gpu=self.gpu)
|
||||
|
||||
predicted_class = torch.argmax(attacked_vec).to(device)
|
||||
prior_class = torch.argmax(prior_vec).to(device)
|
||||
|
||||
if prior_class != real_label:
|
||||
success = 'WrongSample'
|
||||
|
||||
elif prior_class == target_class:
|
||||
success = 'NoNeedAttack'
|
||||
|
||||
else:
|
||||
if (predicted_class.item() != prior_class.item() and target_class == -1) \
|
||||
or (predicted_class.item() == target_class and target_class != -1):
|
||||
success = 'Success'
|
||||
else:
|
||||
success = 'Fail'
|
||||
|
||||
if success == 'Success':
|
||||
self.plot_per(perturbations=attack_result.x, ts=ori_ts, target_class=target_class,
|
||||
sample_idx=sample_idx, attack_pos=attack_pos, prior_probs=prior_probs, attack_probs=attacked_probs, factor=factor)
|
||||
|
||||
return ori_ts, attack_ts, [prior_probs, attacked_probs, prior_class.item(),
|
||||
predicted_class.item(), queries[0], mse, iterations[0], success]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
idx = [1]
|
||||
attacker = Attacker(run_tag='ECG200', top_k=3, model_type='f', e=1499,
|
||||
cuda=True, normalize=False)
|
||||
for idx in idx:
|
||||
attack_ts, info = attacker.attack(sample_idx=idx, target_class=-1, factor=0.01,
|
||||
max_iteration=200, popsize=1, verbose=True)
|
||||
#这里是生成对抗样本
|
||||
if info[-1] == 'Success':
|
||||
file = open('attack_time_series.txt', 'w+')
|
||||
file.write('%d %d ' % (idx, info[3])) # save the sample index and the perturbed label
|
||||
for i in attack_ts:
|
||||
file.write('%.4f ' % i)
|
||||
file.write('\n')
|
||||
file.close()
|
||||
|
||||
print(info)
|
||||
file = open('info.txt', 'w+')
|
||||
file.write('%d ' % idx)
|
||||
for i in info:
|
||||
if isinstance(i, int):
|
||||
file.write('%d ' % i)
|
||||
elif isinstance(i, float):
|
||||
file.write('%.4f ' % i)
|
||||
else:
|
||||
file.write(i + ' ')
|
||||
|
||||
file.write('\n')
|
||||
file.close()
|
53
filter_figures_folder.py
Normal file
53
filter_figures_folder.py
Normal file
@ -0,0 +1,53 @@
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
def copy_with_filtered_figures(source_root, target_root):
|
||||
"""
|
||||
Copy the directory structure from source_root to target_root,
|
||||
excluding all folders that start with 'figures' directly under each dataset folder.
|
||||
|
||||
Args:
|
||||
source_root: Path to the source directory (/Users/catb/Downloads/result_0.04_r)
|
||||
target_root: Path to the target directory (/Users/catb/Downloads/result_0.04_r_filtered)
|
||||
"""
|
||||
# Create target root directory if it doesn't exist
|
||||
if not os.path.exists(target_root):
|
||||
os.makedirs(target_root)
|
||||
|
||||
# First level: Get all dataset directories
|
||||
for dataset_name in os.listdir(source_root):
|
||||
dataset_path = os.path.join(source_root, dataset_name)
|
||||
|
||||
# Skip if not a directory
|
||||
if not os.path.isdir(dataset_path):
|
||||
continue
|
||||
|
||||
# Create corresponding dataset directory in target
|
||||
target_dataset_path = os.path.join(target_root, dataset_name)
|
||||
if not os.path.exists(target_dataset_path):
|
||||
os.makedirs(target_dataset_path)
|
||||
|
||||
# Process contents of each dataset directory
|
||||
for item in os.listdir(dataset_path):
|
||||
item_path = os.path.join(dataset_path, item)
|
||||
target_item_path = os.path.join(target_dataset_path, item)
|
||||
|
||||
# Skip folders that start with 'figures'
|
||||
if os.path.isdir(item_path) and item.startswith('figures'):
|
||||
continue
|
||||
|
||||
# Copy directories (recursively) or files
|
||||
if os.path.isdir(item_path):
|
||||
shutil.copytree(item_path, target_item_path)
|
||||
else:
|
||||
shutil.copy2(item_path, target_item_path)
|
||||
|
||||
# Define source and target directories with absolute paths
|
||||
source_directory = "/Users/catb/Downloads/result_0.04_f"
|
||||
target_directory = source_directory + "_filtered"
|
||||
|
||||
# Run the filtering and copying process
|
||||
copy_with_filtered_figures(source_directory, target_directory)
|
||||
|
||||
print(f"完成! 已创建筛选后的目录结构: {target_directory}")
|
120
main.py
Normal file
120
main.py
Normal file
@ -0,0 +1,120 @@
|
||||
import argparse
|
||||
import numpy as np
|
||||
import os
|
||||
import time
|
||||
import torch
|
||||
from attacker import Attacker
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--cuda', action='store_false', help='it is unnecessary')
|
||||
parser.add_argument('--gpu', type=str, default='0', help='the index of test sample ')
|
||||
parser.add_argument('--target_class', type=int, default=-1, help='-1:untargeted')
|
||||
parser.add_argument('--popsize', type=int, default=1, help='the popsuze of DE')
|
||||
parser.add_argument('--magnitude_factor', type=float, default=0.04, help='the value of beta')
|
||||
parser.add_argument('--maxitr', type=int, default=50, help='max iterations of DE')
|
||||
parser.add_argument('--run_tag', default='ItalyPowerDemand', help='the name of dataset e.g.ECG200')
|
||||
parser.add_argument('--model', default='f', help='the model type(ResNet,FCN),f:FCN r:Resnet')
|
||||
parser.add_argument('--topk', type=int, default=4, help='employ the top k shapelets, maxima value is 5')
|
||||
parser.add_argument('--normalize', action='store_true', help='it is unnecessary in our project, we have '
|
||||
'normalized the data')
|
||||
parser.add_argument('--e', type=int, default=1499, help='epochs of model')
|
||||
|
||||
opt = parser.parse_args()
|
||||
device = "cpu"
|
||||
|
||||
# device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
print(device)
|
||||
# device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
||||
os.makedirs('result_%s_%s/%s/figures%s' % (str(opt.magnitude_factor),
|
||||
opt.model, opt.run_tag, opt.gpu), exist_ok=True)
|
||||
|
||||
data_path = 'data/' + opt.run_tag + '/' + opt.run_tag + '_attack' + opt.gpu + '.txt'
|
||||
|
||||
test_data = np.loadtxt(data_path)
|
||||
|
||||
size = test_data.shape[0]
|
||||
idx_array = np.arange(size)
|
||||
attacker = Attacker(run_tag=opt.run_tag, e=opt.e,
|
||||
model_type=opt.model, cuda=opt.cuda, normalize=opt.normalize, device=device, gpu=opt.gpu)
|
||||
# record of the running time
|
||||
start_time = time.time()
|
||||
# count the number of the successful instances, mse,iterations,queries
|
||||
success_cnt = 0
|
||||
right_cnt = 0
|
||||
total_mse = 0
|
||||
total_iterations = 0
|
||||
total_quries = 0
|
||||
for idx in idx_array:
|
||||
print('###Start %s : generating adversarial example of the %d sample ###' % (opt.run_tag, idx))
|
||||
|
||||
ori_ts, attack_ts, info = attacker.attack(sample_idx=idx, target_class=opt.target_class,
|
||||
factor=opt.magnitude_factor, max_iteration=opt.maxitr,
|
||||
popsize=opt.popsize, device=device)
|
||||
|
||||
# only save the successful adversarial example
|
||||
if info[-1] == 'Success':
|
||||
success_cnt = success_cnt + 1
|
||||
total_iterations += info[-2]
|
||||
total_mse += info[-3]
|
||||
total_quries += info[-4]
|
||||
file0 = open('result_' + str(opt.magnitude_factor) + '_' + opt.model
|
||||
+ '/' + opt.run_tag + '/ori_time_series' + str(opt.gpu) + '.txt', 'a+')
|
||||
file0.write('%d %d ' % (idx, info[3]))
|
||||
for i in ori_ts:
|
||||
file0.write('%.4f ' % i)
|
||||
file0.write('\n')
|
||||
file0.close()
|
||||
|
||||
file = open('result_' + str(opt.magnitude_factor) + '_' + opt.model
|
||||
+ '/' + opt.run_tag + '/attack_time_series' + str(opt.gpu) + '.txt', 'a+')
|
||||
file.write('%d %d ' % (idx, info[3]))
|
||||
for i in attack_ts:
|
||||
file.write('%.4f ' % i)
|
||||
file.write('\n')
|
||||
file.close()
|
||||
|
||||
if info[-1] != 'WrongSample':
|
||||
right_cnt += 1
|
||||
|
||||
# Save the returned information, whether the attack was successful or not
|
||||
file = open('result_' + str(opt.magnitude_factor) + '_' + opt.model
|
||||
+ '/' + opt.run_tag + '/information' + opt.gpu + '.txt', 'a+')
|
||||
|
||||
file.write('%d ' % idx)
|
||||
for i in info:
|
||||
if isinstance(i, int):
|
||||
file.write('%d ' % i)
|
||||
elif isinstance(i, float):
|
||||
file.write('%.4f ' % i)
|
||||
else:
|
||||
file.write(str(i) + ' ')
|
||||
file.write('\n')
|
||||
file.close()
|
||||
|
||||
endtime = time.time()
|
||||
total = endtime - start_time
|
||||
# print useful information
|
||||
print('Running time: %.4f ' % total)
|
||||
print('Correctly-classified samples: %d' % right_cnt)
|
||||
print('Successful samples: %d' % success_cnt)
|
||||
print('Success rate:%.2f%%' % (success_cnt / right_cnt * 100))
|
||||
print('Misclassification rate:%.2f%%' % (success_cnt / size * 100))
|
||||
print('ANI: %.2f' % (total_iterations / success_cnt))
|
||||
print('MSE: %.4f' % (total_mse / success_cnt))
|
||||
print('Mean queries:%.2f\n' % (total_quries / success_cnt))
|
||||
|
||||
# save the useful information
|
||||
file = open('result_' + str(opt.magnitude_factor) + '_' + opt.model
|
||||
+ '/' + opt.run_tag + '/information' + opt.gpu + '.txt', 'a+')
|
||||
file.write('Running time:%.4f\n' % total)
|
||||
file.write('Correctly-classified samples: %d' % right_cnt)
|
||||
file.write('Successful samples:%d\n' % success_cnt)
|
||||
file.write('Success rate:%.2f%%' % (success_cnt / right_cnt * 100))
|
||||
file.write('Misclassification rate:%.2f%%\n' % (success_cnt / size * 100))
|
||||
file.write('ANI:%.2f\n' % (total_iterations / success_cnt))
|
||||
file.write('MSE:%.4f\n' % (total_mse / success_cnt))
|
||||
file.write('Mean queries:%.2f\n' % (total_quries / success_cnt))
|
||||
|
||||
file.close()
|
97
models.py
Normal file
97
models.py
Normal file
@ -0,0 +1,97 @@
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
import torch
|
||||
|
||||
|
||||
class ResNet(nn.Module):
|
||||
def __init__(self, n_in, n_classes):
|
||||
super(ResNet, self).__init__()
|
||||
self.n_in = n_in
|
||||
self.n_classes = n_classes
|
||||
|
||||
blocks = [1, 64, 128, 128]
|
||||
self.blocks = nn.ModuleList()
|
||||
for b, _ in enumerate(blocks[:-1]):
|
||||
self.blocks.append(ResidualBlock(*blocks[b:b + 2], self.n_in))
|
||||
|
||||
self.fc1 = nn.Linear(blocks[-1], self.n_classes)
|
||||
|
||||
def forward(self, x: torch.Tensor):
|
||||
for block in self.blocks:
|
||||
x = block(x)
|
||||
|
||||
x = F.adaptive_avg_pool2d(x, 1)
|
||||
|
||||
x = x.view(-1, 1, 128)
|
||||
x = self.fc1(x)
|
||||
# x = F.log_softmax(x,1)
|
||||
return x.view(-1, self.n_classes)
|
||||
|
||||
|
||||
class ResidualBlock(nn.Module):
|
||||
def __init__(self, in_maps, out_maps, time_steps):
|
||||
super(ResidualBlock, self).__init__()
|
||||
self.in_maps = in_maps
|
||||
self.out_maps = out_maps
|
||||
self.time_steps = time_steps
|
||||
|
||||
self.conv1 = nn.Conv2d(self.in_maps, self.out_maps, (7, 1), 1, (3, 0))
|
||||
self.bn1 = nn.BatchNorm2d(self.out_maps)
|
||||
|
||||
self.conv2 = nn.Conv2d(self.out_maps, self.out_maps, (5, 1), 1, (2, 0))
|
||||
self.bn2 = nn.BatchNorm2d(self.out_maps)
|
||||
|
||||
self.conv3 = nn.Conv2d(self.out_maps, self.out_maps, (3, 1), 1, (1, 0))
|
||||
self.bn3 = nn.BatchNorm2d(self.out_maps)
|
||||
|
||||
def forward(self, x):
|
||||
x = x.view(-1, self.in_maps, self.time_steps, 1)
|
||||
x = F.relu(self.bn1(self.conv1(x)))
|
||||
inx = x
|
||||
x = F.relu(self.bn2(self.conv2(x)))
|
||||
x = F.relu(self.bn3(self.conv3(x)) + inx)
|
||||
|
||||
return x
|
||||
|
||||
|
||||
# FCN model
|
||||
|
||||
class ConvNet(nn.Module):
|
||||
def __init__(self, n_in, n_classes):
|
||||
super(ConvNet, self).__init__()
|
||||
self.n_in = n_in
|
||||
self.n_classes = n_classes
|
||||
|
||||
self.conv1 = nn.Conv2d(1, 128, (7, 1), 1, (3, 0))
|
||||
self.bn1 = nn.BatchNorm2d(128)
|
||||
|
||||
self.conv2 = nn.Conv2d(128, 256, (5, 1), 1, (2, 0))
|
||||
self.bn2 = nn.BatchNorm2d(256)
|
||||
|
||||
self.conv3 = nn.Conv2d(256, 128, (3, 1), 1, (1, 0))
|
||||
self.bn3 = nn.BatchNorm2d(128)
|
||||
|
||||
self.fc4 = nn.Linear(128, self.n_classes)
|
||||
|
||||
def forward(self, x: torch.Tensor):
|
||||
x = x.view(-1, 1, self.n_in, 1)
|
||||
x = F.relu(self.bn1(self.conv1(x)))
|
||||
x = F.relu(self.bn2(self.conv2(x)))
|
||||
x = F.relu(self.bn3(self.conv3(x)))
|
||||
x = F.adaptive_avg_pool2d(x, 1)
|
||||
x = x.view(-1, 128)
|
||||
x = self.fc4(x)
|
||||
# return F.log_softmax(x,1)
|
||||
return x
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# resNet = ResNet(n_in=96, n_classes=3)
|
||||
# input = torch.randn(32, 96, 1)
|
||||
# out = resNet(input)
|
||||
# print(out.shape)
|
||||
torch.manual_seed(3)
|
||||
fcn = ConvNet(n_in=112, n_classes=3)
|
||||
input = torch.randn(32, 112, 1)
|
||||
out = fcn(input)
|
||||
print(out.size())
|
0
print_results_path.py
Normal file
0
print_results_path.py
Normal file
78
query_probability.py
Normal file
78
query_probability.py
Normal file
@ -0,0 +1,78 @@
|
||||
'''
|
||||
This script use pre-trained model(e.g. FCN)
|
||||
as the target model. We can query the probability
|
||||
from it to decide attacks whether efficient or not.
|
||||
'''
|
||||
import numpy as np
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
device = torch.device("cuda:0" if 'store_true' else "cpu")
|
||||
|
||||
|
||||
def load_ucr(path, normalize=False):
|
||||
data = np.loadtxt(path)
|
||||
data[:, 0] -= 1
|
||||
# limit label to [0,num_classes-1]
|
||||
num_classes = len(np.unique(data[:, 0]))
|
||||
for i in range(data.shape[0]):
|
||||
if data[i, 0] < 0:
|
||||
data[i, 0] = num_classes - 1
|
||||
|
||||
# Normalize some datasets without normalization
|
||||
if normalize:
|
||||
mean = data[:, 1:].mean(axis=1, keepdims=True)
|
||||
std = data[:, 1:].std(axis=1, keepdims=True)
|
||||
data[:, 1:] = (data[:, 1:] - mean) / (std + 1e-8)
|
||||
return data
|
||||
|
||||
|
||||
|
||||
def query_one(run_tag, device, idx, attack_ts, target_class=-1, normalize=False,
|
||||
e=1499, verbose=False, cuda=True, model_type='r', gpu='0',n_class=1024):
|
||||
ts = torch.from_numpy(attack_ts).float().to(device)
|
||||
data_path = 'data/' + run_tag + '/' + run_tag + '_attack' + gpu + '.txt'
|
||||
test_data = load_ucr(path=data_path, normalize=normalize)
|
||||
test_data = torch.from_numpy(test_data).to(device)
|
||||
Y = test_data[:, 0]
|
||||
|
||||
test_one = test_data[idx]
|
||||
|
||||
X = test_one[1:].float()
|
||||
y = test_one[0].long()
|
||||
y = y.to(device)
|
||||
|
||||
real_label = y
|
||||
|
||||
if target_class != -1:
|
||||
y = target_class
|
||||
|
||||
ts = ts.to(device)
|
||||
X = X.to(device)
|
||||
model_path = 'model_checkpoints/' + run_tag + '/pre_'+model_type+'Trained.pth'
|
||||
#print(device)
|
||||
model = torch.load(model_path, map_location=device, weights_only=False)
|
||||
|
||||
with torch.no_grad():
|
||||
|
||||
model.eval()
|
||||
softmax = nn.Softmax(dim=-1)
|
||||
|
||||
out = model(X)
|
||||
|
||||
prob_vector = softmax(out)
|
||||
prob = prob_vector.view(n_class)[y].item()
|
||||
|
||||
out2 = model(ts)
|
||||
|
||||
prob_vector2 = softmax(out2)
|
||||
prob2 = prob_vector2.view(n_class)[y].item()
|
||||
if verbose:
|
||||
print('Target_Class:', target_class)
|
||||
print('Prior Confidence of the %d sample is %.4f ' % (idx, prob))
|
||||
|
||||
return prob2, prob_vector2, prob, prob_vector, real_label
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
query_one('ECG200', 2)
|
5
requirements.txt
Normal file
5
requirements.txt
Normal file
@ -0,0 +1,5 @@
|
||||
matplotlib
|
||||
pandas
|
||||
ruptures
|
||||
scikit-learn
|
||||
pymoo
|
203
run_all_datasets.py
Normal file
203
run_all_datasets.py
Normal file
@ -0,0 +1,203 @@
|
||||
import os
|
||||
import csv
|
||||
import pandas as pd
|
||||
|
||||
import concurrent.futures
|
||||
from argparse import Namespace
|
||||
from attack import attack_process
|
||||
|
||||
def create_datasets_csv(datasets_dir, output_csv="datasets_config.csv"):
|
||||
"""
|
||||
创建包含所有数据集及其参数的CSV文件
|
||||
|
||||
Args:
|
||||
datasets_dir: 包含所有数据集文件夹的目录
|
||||
output_csv: 输出CSV文件的路径
|
||||
"""
|
||||
# 检查目录是否存在
|
||||
if not os.path.exists(datasets_dir):
|
||||
raise FileNotFoundError(f"数据集目录 {datasets_dir} 不存在")
|
||||
|
||||
# 获取所有数据集文件夹
|
||||
datasets = [d for d in os.listdir(datasets_dir) if os.path.isdir(os.path.join(datasets_dir, d))]
|
||||
|
||||
# 创建CSV文件
|
||||
with open(output_csv, 'w', newline='') as csvfile:
|
||||
fieldnames = [
|
||||
'dataset_name',
|
||||
'cuda',
|
||||
'total_gpus',
|
||||
'classes',
|
||||
'target_class',
|
||||
'pop_size',
|
||||
'magnitude_factor',
|
||||
'max_itr',
|
||||
'run_tag',
|
||||
'model',
|
||||
'normalize',
|
||||
'e',
|
||||
'done'
|
||||
]
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
writer.writeheader()
|
||||
|
||||
# 为每个数据集添加一行,使用默认参数
|
||||
for dataset in datasets:
|
||||
writer.writerow({
|
||||
'dataset_name': dataset,
|
||||
'cuda': 'store_true',
|
||||
'total_gpus': 1,
|
||||
'target_class': -1,
|
||||
'classes': 0,
|
||||
'pop_size': 1,
|
||||
'magnitude_factor': 0.04,
|
||||
'max_itr': 50,
|
||||
'run_tag': dataset,
|
||||
'model': 'r',
|
||||
'normalize': 'store_true',
|
||||
'e': 1499,
|
||||
'done': '0' # 初始状态为未完成
|
||||
})
|
||||
|
||||
print(f"已创建数据集配置文件: {output_csv}")
|
||||
return output_csv
|
||||
|
||||
def validate_dataset(dataset_path):
|
||||
"""验证数据集路径是否有效"""
|
||||
if not os.path.exists(dataset_path):
|
||||
return False
|
||||
# 可以添加更多的验证逻辑,如检查必要的文件是否存在
|
||||
return True
|
||||
|
||||
def process_dataset(row, datasets_base_dir):
|
||||
"""处理单个数据集,利用多个GPU并行处理"""
|
||||
dataset_name = row['dataset_name']
|
||||
dataset_path = os.path.join(datasets_base_dir, dataset_name)
|
||||
|
||||
# 验证数据集
|
||||
if not validate_dataset(dataset_path):
|
||||
print(f"警告: 数据集 '{dataset_name}' 路径无效或格式不正确")
|
||||
return False
|
||||
|
||||
# 获取总GPU数量
|
||||
total_gpus = int(row['total_gpus'])
|
||||
|
||||
# 为每个GPU创建一个配置
|
||||
configurations = []
|
||||
for i in range(total_gpus):
|
||||
config = {
|
||||
'cuda': row['cuda'] == 'store_true',
|
||||
'gpu': str(i), # 分配不同的GPU
|
||||
'target_class': int(row['target_class']),
|
||||
'classes':int(row['classes']),
|
||||
'popsize': int(row['pop_size']),
|
||||
'magnitude_factor': float(row['magnitude_factor']),
|
||||
'maxitr': int(row['max_itr']),
|
||||
'run_tag': row['run_tag'],
|
||||
'model': row['model'],
|
||||
'normalize': row['normalize'] == 'store_true',
|
||||
'e': int(row['e']),
|
||||
'dataset': dataset_name # 添加数据集名称
|
||||
}
|
||||
configurations.append(config)
|
||||
|
||||
# 并行处理同一个数据集的多个任务
|
||||
success = True
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
futures = []
|
||||
for config in configurations:
|
||||
arg = Namespace(**config)
|
||||
future = executor.submit(attack_process, arg)
|
||||
futures.append(future)
|
||||
|
||||
# 等待所有进程完成
|
||||
for future in concurrent.futures.as_completed(futures):
|
||||
try:
|
||||
result = future.result()
|
||||
# 如果任何一个进程失败,标记整个数据集处理为失败
|
||||
if not result:
|
||||
success = False
|
||||
except Exception as e:
|
||||
import traceback
|
||||
print(f"处理数据集 '{dataset_name}' 时出错: {str(e)}")
|
||||
print(traceback.format_exc())
|
||||
success = False
|
||||
|
||||
return success
|
||||
|
||||
def main(csv_file, datasets_base_dir, max_workers=4):
|
||||
"""
|
||||
主程序:顺序遍历CSV文件中的数据集并执行任务
|
||||
每个数据集内部可能有并行处理(由attack_process内部实现)
|
||||
Args:
|
||||
csv_file: 包含数据集和参数的CSV文件
|
||||
datasets_base_dir: 数据集根目录
|
||||
max_workers: 数据集内部并行的最大工作进程数
|
||||
"""
|
||||
# 验证CSV文件
|
||||
if not os.path.exists(csv_file):
|
||||
raise FileNotFoundError(f"CSV文件 {csv_file} 不存在")
|
||||
|
||||
# 读取CSV文件
|
||||
df = pd.read_csv(csv_file)
|
||||
|
||||
# 检查CSV格式是否正确
|
||||
required_columns = [
|
||||
'dataset_name',
|
||||
'cuda',
|
||||
'total_gpus',
|
||||
'target_class',
|
||||
'classes',
|
||||
'pop_size',
|
||||
'magnitude_factor',
|
||||
'max_itr',
|
||||
'run_tag',
|
||||
'model',
|
||||
'normalize',
|
||||
'e',
|
||||
'done'
|
||||
]
|
||||
missing_columns = [col for col in required_columns if col not in df.columns]
|
||||
if missing_columns:
|
||||
raise ValueError(f"CSV文件缺少必要的列: {', '.join(missing_columns)}")
|
||||
|
||||
# 只处理未完成的数据集
|
||||
pending_datasets = df[df['done'] == 0]
|
||||
total_pending = len(pending_datasets)
|
||||
print(f"发现 {total_pending} 个未处理的数据集")
|
||||
|
||||
# 顺序处理数据集
|
||||
for index, row in pending_datasets.iterrows():
|
||||
dataset_name = row['dataset_name']
|
||||
print(f"开始处理数据集: {dataset_name} ({pending_datasets.index[pending_datasets.index == index].item() + 1}/{total_pending})")
|
||||
|
||||
try:
|
||||
# 处理单个数据集(内部可能有并行)
|
||||
success = process_dataset(row, datasets_base_dir)
|
||||
|
||||
if success:
|
||||
# 更新CSV中的done状态
|
||||
df.at[index, 'done'] = 1
|
||||
df.to_csv(csv_file, index=False)
|
||||
print(f"完成数据集: {dataset_name}")
|
||||
else:
|
||||
print(f"处理数据集失败: {dataset_name}")
|
||||
except Exception as e:
|
||||
print(f"处理数据集 '{dataset_name}' 时出现异常: {str(e)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='批量处理数据集')
|
||||
parser.add_argument('--csv', type=str, default='datasets_config.csv', help='数据集配置CSV文件')
|
||||
parser.add_argument('--datasets_dir',default='data' , type=str, help='数据集根目录')
|
||||
parser.add_argument('--create_csv', action='store_true', help='是否创建新的CSV文件')
|
||||
parser.add_argument('--max_workers', type=int, default=4, help='最大并行工作进程数')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.create_csv:
|
||||
create_datasets_csv(args.datasets_dir, args.csv)
|
||||
|
||||
main(args.csv, args.datasets_dir, args.max_workers)
|
18
run_parallel_config.ini
Normal file
18
run_parallel_config.ini
Normal file
@ -0,0 +1,18 @@
|
||||
[GLOBAL]
|
||||
# mac win
|
||||
#machine = mac
|
||||
|
||||
[GPU]
|
||||
cuda=store_true
|
||||
total_gpus=5
|
||||
|
||||
[MODEL]
|
||||
run_tag=Car
|
||||
classes=5
|
||||
target_class=-1
|
||||
pop_size=1
|
||||
magnitude_factor=0.04
|
||||
max_itr=50
|
||||
model=f
|
||||
normalize=store_true
|
||||
e=1499
|
42
run_parallel_main.py
Normal file
42
run_parallel_main.py
Normal file
@ -0,0 +1,42 @@
|
||||
import concurrent
|
||||
from argparse import Namespace
|
||||
from attack import attack_process
|
||||
from utils import read_config
|
||||
|
||||
|
||||
def create_configurations(config):
|
||||
# 基于配置文件生成配置列表
|
||||
total_gpus = int(config['GPU']['total_gpus'])
|
||||
configurations = []
|
||||
for i in range(total_gpus):
|
||||
conf_dict = {
|
||||
'cuda': config['GPU']['cuda'],
|
||||
'gpu': str(i),
|
||||
'target_class': int(config['MODEL']['target_class']),
|
||||
'popsize': int(config['MODEL']['pop_size']),
|
||||
'magnitude_factor': float(config['MODEL']['magnitude_factor']),
|
||||
'maxitr': int(config['MODEL']['max_itr']),
|
||||
'run_tag': config['MODEL']['run_tag'],
|
||||
'model': config['MODEL']['model'],
|
||||
'normalize': config['MODEL']['normalize'],
|
||||
'e': int(config['MODEL']['e'])
|
||||
}
|
||||
configurations.append(conf_dict)
|
||||
return configurations
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
config_file = read_config("run_parallel_config.ini")
|
||||
configurations = create_configurations(config_file)
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
futures = []
|
||||
for config in configurations:
|
||||
arg = Namespace(**config)
|
||||
future = executor.submit(attack_process, arg)
|
||||
# attack_process(arg)
|
||||
futures.append(future)
|
||||
|
||||
for future in concurrent.futures.as_completed(futures):
|
||||
# 处理结果,如果需要的话
|
||||
pass
|
58
test.py
Normal file
58
test.py
Normal file
@ -0,0 +1,58 @@
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
|
||||
# 设置全局字体为 Times New Roman
|
||||
plt.rcParams['font.family'] = 'Times New Roman'
|
||||
plt.rcParams['mathtext.fontset'] = 'stix' # 数学文本也使用与 Times New Roman 兼容的字体
|
||||
|
||||
# 读取Excel文件
|
||||
file_path = "实验结果.xlsx" # 请替换为你的文件路径
|
||||
sheet_name = "Sheet1"
|
||||
df = pd.read_excel(file_path, sheet_name=sheet_name)
|
||||
|
||||
# 提取所需数据
|
||||
# 注意: Excel范围F2:F42对应pandas的索引1:41
|
||||
# 同样L2:L43对应索引1:42,A2:A43对应索引1:42
|
||||
dataset_names = df.iloc[1:42, 0].values # A2:A43 数据集名称
|
||||
cp_adv = df.iloc[1:41, 5].values # F2:F42 CPadv数据
|
||||
cp_soadv = df.iloc[1:42, 12].values # L2:L43 CPsoadv数据
|
||||
|
||||
# 计算均值
|
||||
cp_adv_mean = np.mean(cp_adv)
|
||||
cp_soadv_mean = np.mean(cp_soadv)
|
||||
|
||||
# 创建图表 - 减小图片尺寸
|
||||
plt.figure(figsize=(10, 5)) # 从 (12, 6) 减小到 (10, 5)
|
||||
|
||||
# 绘制CPadv折线
|
||||
plt.plot(dataset_names[:len(cp_adv)], cp_adv, 'b-', marker='o', label='CPadv')
|
||||
# 绘制CPadv均值线
|
||||
plt.axhline(y=cp_adv_mean, color='b', linestyle='--', alpha=0.7, label='Mean of CPadv')
|
||||
|
||||
# 绘制CPsoadv折线
|
||||
plt.plot(dataset_names[:len(cp_soadv)], cp_soadv, 'r-', marker='s', label='CPsoadv')
|
||||
# 绘制CPsoadv均值线
|
||||
plt.axhline(y=cp_soadv_mean, color='r', linestyle='--', alpha=0.7, label='Mean of CPsoadv')
|
||||
|
||||
# 设置图表标题和标签
|
||||
plt.ylabel('Queries', fontsize=12)
|
||||
plt.grid(True, linestyle='--', alpha=0.7)
|
||||
plt.legend()
|
||||
|
||||
# 调整x轴标签
|
||||
plt.xticks(rotation=45, ha='right')
|
||||
plt.tight_layout()
|
||||
|
||||
# 保存为PDF矢量图
|
||||
plt.savefig('CCPP_comparison.pdf', bbox_inches='tight')
|
||||
|
||||
# 同时也保存一份PNG格式(如果需要)
|
||||
plt.savefig('CCPP_comparison.png', dpi=300, bbox_inches='tight')
|
||||
|
||||
plt.show()
|
||||
|
||||
# 打印均值结果
|
||||
print(f"CPadv 均值: {cp_adv_mean:.2f}")
|
||||
print(f"CPsoadv 均值: {cp_soadv_mean:.2f}")
|
70
utils.py
Normal file
70
utils.py
Normal file
@ -0,0 +1,70 @@
|
||||
import configparser
|
||||
|
||||
import torch
|
||||
import numpy as np
|
||||
from torch.utils.data import Dataset
|
||||
from query_probability import load_ucr
|
||||
import warnings
|
||||
|
||||
warnings.filterwarnings('ignore')
|
||||
|
||||
|
||||
class UcrDataset(Dataset):
|
||||
def __init__(self, txt_file, channel_last, normalize):
|
||||
'''
|
||||
:param txt_file: path of file
|
||||
:param channel_last
|
||||
'''
|
||||
# self.data = np.loadtxt(txt_file)
|
||||
self.data = load_ucr(txt_file, normalize)
|
||||
self.channel_last = channel_last
|
||||
if self.channel_last:
|
||||
self.data = np.reshape(self.data, [self.data.shape[0], self.data.shape[1], 1])
|
||||
else:
|
||||
self.data = np.reshape(self.data, [self.data.shape[0], 1, self.data.shape[1]])
|
||||
|
||||
def __len__(self):
|
||||
|
||||
return len(self.data)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
|
||||
if not self.channel_last:
|
||||
return self.data[idx, :, 1:], self.data[idx, :, 0]
|
||||
else:
|
||||
return self.data[idx, 1:, :], self.data[idx, 0, :]
|
||||
|
||||
def get_seq_len(self):
|
||||
if self.channel_last:
|
||||
return self.data.shape[1] - 1
|
||||
else:
|
||||
return self.data.shape[2] - 1
|
||||
|
||||
|
||||
class AdvDataset(Dataset):
|
||||
def __init__(self, txt_file):
|
||||
self.data = np.loadtxt(txt_file)
|
||||
self.data = np.reshape(self.data, [self.data.shape[0], self.data.shape[1], 1])
|
||||
|
||||
def __len__(self):
|
||||
return len(self.data)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return self.data[idx, 2:, :], self.data[idx, 1, :]
|
||||
|
||||
def get_seq_len(self):
|
||||
return self.data.shape[1] - 2
|
||||
|
||||
|
||||
def UCR_dataloader(dataset, batch_size):
|
||||
data_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True, num_workers=0)
|
||||
|
||||
return data_loader
|
||||
|
||||
|
||||
def read_config(file_name):
|
||||
# 创建一个配置解析器
|
||||
config = configparser.ConfigParser()
|
||||
# 从INI文件读取配置
|
||||
config.read(file_name)
|
||||
return config
|
Loading…
Reference in New Issue
Block a user