# Normality scoring phase
dc_gcae.eval()
if pretrained and getattr(args, 'dpmm_fn', False):
pt_dpmm = args.dpmm_fn
else:# True
pt_dpmm = None
在模型的评估模式下 dc_gcae.eval()
- 以上函数中的pt_dpmm = None
dpmm_calc_scores(分数计算)
def dpmm_calc_scores(model, train_dataset, eval_normal_dataset, eval_abn_dataset=None, args=None,
ret_metadata=False, dpmm_components=10, dpmm_downsample_fac=10, pt_dpmm_path=None):
def dpmm_calc_scores(model{dc_gcae*}, train_dataset{“正常”训练数据集,用于阿尔法计算*}, eval_normal_dataset{“正常”或“混合”评估数据集*},
eval_abn_dataset=None{“异常”评估数据集(可选)}, args=None{命令行参数*},ret_metadata=False{*},
dpmm_components=10{dpmm的截断参数}, dpmm_downsample_fac=10{dpmm拟合的下采样因子}, pt_dpmm_path=None{预训练dpmm模型的路径*}):
"""
Wrapper for extracting features for DNS experiment, given a trained DCEC models, a normal training dataset and two
datasets for evaluation, a "normal" one and an "abnormal" one
:param model: A trained model
:param train_dataset: "normal" training dataset, for alpha calculation
:param eval_normal_dataset: "normal" or "mixed" evaluation dataset
:param eval_abn_dataset: "abnormal" evaluation dataset (optional)
:param args - command line arguments
:param ret_metadata:
:param dpmm_components: Truncation parameter for DPMM
:param dpmm_downsample_fac: Downsampling factor for DPMM fitting
:param pt_dpmm_path: Path to a pretrained DPMM model
:return actual experiment done after feature extraction (calc_p)
apper用于提取DNS实验的特征,给定一个经过训练的DCEC模型、一个正常的训练数据集和两个用于评估的数据集,“正常”和“异常”数据集
:返回特征提取后的实际实验(calc_p)
"""
# Alpha calculation and fitting
train_p = calc_p(model, train_dataset, args, ret_metadata=False) #[560900,10]
eval_p_ret = calc_p(model, eval_normal_dataset, args, ret_metadata=ret_metadata)
if ret_metadata:
eval_p_normal, metadata = eval_p_ret
else:
eval_p_normal = eval_p_ret
p_vec = eval_p_normal
eval_p_abn = None
if eval_abn_dataset:
eval_p_abn = calc_p(model, eval_abn_dataset, args, ret_metadata=ret_metadata)
p_vec = np.concatenate([eval_p_normal, eval_p_abn])
print("Started fitting DPMM")
if pt_dpmm_path is None:
dpmm_mix = mixture.BayesianGaussianMixture(n_components=dpmm_components,
max_iter=500, verbose=1, n_init=1)
dpmm_mix.fit(train_p[::dpmm_downsample_fac])
else:
dpmm_mix = load(pt_dpmm_path)
dpmm_scores = dpmm_mix.score_samples(p_vec)
if eval_p_abn is not None:
gt = np.concatenate([np.ones(eval_p_normal.shape[0], dtype=np.int),
np.zeros(eval_p_abn.shape[0], dtype=np.int)])
else:
gt = np.ones_like(dpmm_scores, dtype=np.int)
try: # Model persistence
dpmm_fn = args.ae_fn.split('.')[0] + '_dpgmm.pkl'
dpmm_path = os.path.join(args.ckpt_dir, dpmm_fn)
dump(dpmm_mix, dpmm_path)
except ModuleNotFoundError:
print("Joblib missing, DPMM not saved")
if ret_metadata:
return dpmm_scores, gt, metadata
else:
return dpmm_scores, gt
train_p(两个概率的计算使用的是同一个函数,不同的参数)
- train_p = calc_p(model, train_dataset, args, ret_metadata=False) #[560900,10]
train_p = calc_p(model, train_dataset, args, ret_metadata=False) #[560900,10]
def calc_p(model, dataset, args, ret_metadata=True, ret_z=False):
""" Evalutates the models output over the data in the dataset. """
loader = DataLoader(dataset, batch_size=args.batch_size, num_workers=args.num_workers,
shuffle=False, drop_last=False, pin_memory=True)
model = model.to(args.device)
model.eval()
p = p_compute_features(loader, model, device=args.device, ret_z=ret_z)# ret_z=False p为ndarry (560900,10)
if ret_z:# False
p, z = p
if ret_metadata:
return p, z, dataset.metadata
else:
return p, z
else:
if ret_metadata:# False
return p, dataset.metadata
else:
return p
def p_compute_features(loader, model, device='cuda:0', ret_z=False):
sfmax = []
z_arr = []
for itern, data_arr in enumerate(loader):
data = data_arr[0]
if itern % 100 == 0:
print("Compute Features Iter {}".format(itern))
with torch.no_grad():
data = data.to(device) # torch.Size([256, 3, 12, 18])
model_ret = model(data, ret_z=ret_z)
cls_sfmax = model_ret[0]# !!!
if ret_z:
z = model_ret[-1]
z_arr.append(z.to('cpu', non_blocking=True).numpy().astype('float32'))
cls_sfmax = torch.reshape(cls_sfmax, (cls_sfmax.size(0), -1))
sfmax.append(cls_sfmax.to('cpu', non_blocking=True).numpy().astype('float32'))
sfmax = np.concatenate(sfmax)
if ret_z:# False
z_arr = np.concatenate(z_arr)
return sfmax, z_arr
else:
return sfmax
eval_p_ret
- eval_p_ret = calc_p(model, eval_normal_dataset, args, ret_metadata=ret_metadata)
- 传入的model为dc_gcae
eval_p_ret = calc_p(model, eval_normal_dataset, args, ret_metadata=ret_metadata) # ret_metadata传过来的True
def calc_p(model, dataset, args, ret_metadata=True, ret_z=False):
""" Evalutates the models output over the data in the dataset. """
loader = DataLoader(dataset, batch_size=args.batch_size, num_workers=args.num_workers,
shuffle=False, drop_last=False, pin_memory=True)
model = model.to(args.device)
model.eval()
p = p_compute_features(loader, model, device=args.device, ret_z=ret_z)
if ret_z:# False
p, z = p
if ret_metadata:
return p, z, dataset.metadata
else:
return p, z
else:
if ret_metadata:# True
return p, dataset.metadata # !!!!
else:
return p
Started fitting DPMM
def dpmm_calc_scores(model, train_dataset, eval_normal_dataset, eval_abn_dataset=None, args=None,ret_metadata=False, dpmm_components=10, dpmm_downsample_fac=10, pt_dpmm_path=None):
# Alpha calculation and fitting
train_p = calc_p(model, train_dataset, args, ret_metadata=False) #[560900,10]
eval_p_ret = calc_p(model, eval_normal_dataset, args, ret_metadata=ret_metadata)
if ret_metadata:# True 第二个计算返回两个数据!!!!!!!!!!!!!!!!!!!!!!!!!
eval_p_normal, metadata = eval_p_ret
else:
eval_p_normal = eval_p_ret
p_vec = eval_p_normal # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
eval_p_abn = None
if eval_abn_dataset:# None
eval_p_abn = calc_p(model, eval_abn_dataset, args, ret_metadata=ret_metadata)
p_vec = np.concatenate([eval_p_normal, eval_p_abn])
print("Started fitting DPMM")
if pt_dpmm_path is None:# True !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
dpmm_mix = mixture.BayesianGaussianMixture(n_components=dpmm_components,max_iter=500, verbose=1, n_init=1) # sklearn中的函数
dpmm_mix.fit(train_p[::dpmm_downsample_fac])# dpmm_downsample_fac=10
else:
dpmm_mix = load(pt_dpmm_path)
- 拟合dpmm
dpmm_scores = dpmm_mix.score_samples(p_vec)# ndarry 750370 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if eval_p_abn is not None:# False
gt = np.concatenate([np.ones(eval_p_normal.shape[0], dtype=np.int),
np.zeros(eval_p_abn.shape[0], dtype=np.int)])
else: # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
gt = np.ones_like(dpmm_scores, dtype=np.int)# ???
try: # Model persistence
dpmm_fn = args.ae_fn.split('.')[0] + '_dpgmm.pkl'
dpmm_path = os.path.join(args.ckpt_dir, dpmm_fn)
dump(dpmm_mix, dpmm_path)
except ModuleNotFoundError:
print("Joblib missing, DPMM not saved")
if ret_metadata: # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return dpmm_scores, gt, metadata
else:
return dpmm_scores, gt
- 持久化
- 主要返回由测试数据集得到的dpmm_scores
- 然后由返回的dp_scores得到另一个dp_scores_tavg
dp_scores_tavg, _ = avg_scores_by_trans(dp_scores, gt, args.num_transform)
def avg_scores_by_trans(scores, gt, num_transform=5, ret_first=False):
score_mask, scores_by_trans, scores_tavg = dict(), dict(), dict()
gti = {'normal': 1, 'abnormal': 0}
for k, gt_val in gti.items():
score_mask[k] = scores[gt == gt_val]
scores_by_trans[k] = score_mask[k].reshape(-1, num_transform)
scores_tavg[k] = scores_by_trans[k].mean(axis=1)
gt_trans_avg = np.concatenate([np.ones_like(scores_tavg['normal'], dtype=np.int),
np.zeros_like(scores_tavg['abnormal'], dtype=np.int)])
scores_trans_avg = np.concatenate([scores_tavg['normal'], scores_tavg['abnormal']])
if ret_first:
scores_first_trans = dict()
for k, v in scores_by_trans.items():
scores_first_trans[k] = v[:, 0]
scores_first_trans = np.concatenate([scores_first_trans['normal'], scores_first_trans['abnormal']])
return scores_trans_avg, gt_trans_avg, scores_first_trans
else:# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return scores_trans_avg, gt_trans_avg
- 750370/5=150074 对5个数据增强变换得到地结果进行avg
然后进行:
max_clip = 5 if args.debug else None # None
dp_auc, dp_shift, dp_sigma = score_dataset(dp_scores_tavg ndarry(150074), metadatandarry(150074,4), max_clip=max_clip)
def score_dataset(score_vals, metadata, max_clip=None, scene_id=None):
gt_arr, scores_arr, score_ids_arr, metadata_arr = get_dataset_scores(score_vals, metadata, max_clip, scene_id)
gt_np = np.concatenate(gt_arr)
scores_np = np.concatenate(scores_arr)
auc, shift, sigma = score_align(scores_np, gt_np)
return auc, shift, sigma
- get_dataset_scores函数,主要 传入score_vals(n)和数据集的meta_data(n,4) 用于计算 scores_np, gt_np (clip_list为读取的gt的位置) 也就是返回以下两张图片中的值
def get_dataset_scores(scores, metadata, max_clip=None, scene_id=None):
dataset_gt_arr = []
dataset_scores_arr = []
dataset_metadata_arr = []
dataset_score_ids_arr = []
metadata_np = np.array(metadata) # (150074,4)
per_frame_scores_root = '/media/ubuntu/data2/cuitao/gepc-master1/data/testing/test_frame_mask' # TODO 'data/testing/test_frame_mask/'
clip_list = os.listdir(per_frame_scores_root)# 对应于每个视频的gt
clip_list = sorted(fn for fn in clip_list if fn.endswith('.npy'))
if scene_id is not None:# False
clip_list = [cl for cl in clip_list if int(cl[:2]) == scene_id]
if max_clip: # None
max_clip = min(max_clip, len(clip_list))
clip_list = clip_list[:max_clip]
print("Scoring {} clips".format(len(clip_list))) # Scoring 107 clips
for clip in clip_list:
clip_res_fn = os.path.join(per_frame_scores_root, clip) # '*/gepc-master1/data/testing/test_frame_mask/01_0014.npy'
clip_gt = np.load(clip_res_fn) # 加载视频的gt 256长度的ndarry
scene_id, clip_id = [int(i) for i in clip.split('.')[0].split('_')] # 1 , 14
clip_metadata_inds = np.where((metadata_np[:, 1] == clip_id) &
(metadata_np[:, 0] == scene_id))[0]# 大小839 [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23, 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47, 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71, 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95, 96 97 98 99]
clip_metadata = metadata[clip_metadata_inds] # 大小(839,4) [[ 1 14 1 0], [ 1 14 1 1], [ 1 14 1 2], [ 1 14 1 3], [ 1 14 1 4], [ 1 14 1 5], [ 1 14 1 6], [ 1 14 1 7], [ 1 14 1 8], [ 1 14 1 9], [ 1 14 1 10], [ 1 14 1 11], [ 1 14 1 12], [ 1 14 1 13], [ 1 14 1 14], [ 1 14 1 15], [ 1 14 1 16], [ 1 14 1 17], [ 1 14 1 18], [ 1 14 1 19], [ 1 14 1 20], [ 1 14 1 21], [ 1 14 1 22], [ 1 14 1 23], [ 1 14 1 24], [ 1 14 1 25], [ 1 14 1 26], [ 1 14 1 27], [ 1 14 1 28], [ 1 14 1 29], [ 1 14 1 30], [ 1 14 1 31], [ 1 14 1 32], [ 1 14 1 33], [ 1 14 1 34], [ 1 14 1 35], [ 1 14 1 36], [ 1 14 1 37], [ 1 14 1 38], [ 1 14 1 39], [ 1 14 1 40], [ 1 14 1 41], [ 1 14 1 42], [ 1 14 1 43], [ 1 14 1 44], [ 1 14 1 45], [ 1 14 1 46], [ 1 14 1 47], [ 1 14 1 48], [ 1 14 1 49], [ 1 14 1 50], [ 1 14 1 51], [ 1 14 1 52], [ 1 14 1 53], [ 1 14 1 54], [ 1 14 1 55], [ 1 14 1 56], [ 1 14 1 57], [ 1 14 1 58], [ 1 14 1 59], [ 1 14 1 60], [ 1 14 1 61], [ 1 14 1 62], [ 1 14 1 63], [ 1 14 1 64], [ 1 14 1 65], [ 1 14 1...
clip_fig_idxs = set([arr[2] for arr in clip_metadata]) # 集合 {1, 2, 4, 6, 8}应该是这个视频中有几个人吧
scores_zeros = np.zeros(clip_gt.shape[0]) # 256(gt的大小)大小的0
clip_person_scores_dict = {i: np.copy(scores_zeros) for i in clip_fig_idxs} # 让1,2,4,6,8每个对应于于265大小的 值0 ndarry的字典
for person_id in clip_fig_idxs:
person_metadata_inds = np.where((metadata_np[:, 1] == clip_id) &
(metadata_np[:, 0] == scene_id) &
(metadata_np[:, 2] == person_id))[0]
pid_scores = scores[person_metadata_inds]
pid_frame_inds = np.array([metadata[i][3] for i in person_metadata_inds])
clip_person_scores_dict[person_id][pid_frame_inds] = pid_scores
clip_ppl_score_arr = np.stack(list(clip_person_scores_dict.values())) # (5, 265)
clip_score = np.amax(clip_ppl_score_arr, axis=0) # 256
fig_score_id = [list(clip_fig_idxs)[i] for i in np.argmax(clip_ppl_score_arr, axis=0)]# 这应该是把那个人的id记下来 后续可以可视化用
dataset_gt_arr.append(clip_gt)
dataset_scores_arr.append(clip_score)
dataset_score_ids_arr.append(fig_score_id)
dataset_metadata_arr.append([scene_id, clip_id])
return dataset_gt_arr, dataset_scores_arr, dataset_score_ids_arr, dataset_metadata_arr # 返回值dataset_gt_arr与dataset_scores_arr用于AUC的计算
- clip_metadata_inds为满足条件的meta项在metadata中的索引
clip_fig_idxs:为singleposemeta[0]见
https://img-blog.csdnimg.cn/4d89076c8aa647a0a89a42d58fd616b5.png
singleposemeta[0]是在一个 clip_dict的一个pose的索引 ,singlepose是 clip_dict(9,n,51)的单个 (n,51)
clip_gt大小 256(应该是256帧)
for person_id in clip_fig_idxs:
person_metadata_inds = np.where((metadata_np[:, 1] == clip_id) &
(metadata_np[:, 0] == scene_id) &
(metadata_np[:, 2] == person_id))[0]
pid_scores = scores[person_metadata_inds]
pid_frame_inds = np.array([metadata[i][3] for i in person_metadata_inds])
#[i][3] 为startkey https://img-blog.csdnimg.cn/ed839efa89954342bf59087e2b5c12ac.png 开始的帧的位置
clip_person_scores_dict[person_id][pid_frame_inds] = pid_scores # 填充clip_person_scores_dict