Skip to content

Commit 7badd5b

Browse files
zhangyubo0722cuicheng01
authored andcommitted
add metrics and postprocess
1 parent a9cb417 commit 7badd5b

File tree

5 files changed

+166
-2
lines changed

5 files changed

+166
-2
lines changed

deploy/python/postprocess.py

+52
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,58 @@ def __call__(self, batch_preds, file_names=None):
346346
return batch_res
347347

348348

349+
class FaceAttribute(object):
350+
def __init__(self, threshold=0.65, convert_cn=False):
351+
self.threshold = threshold
352+
self.convert_cn = convert_cn
353+
354+
def __call__(self, x, file_names=None):
355+
attribute_list = [
356+
["CheekWhiskers", "刚长出的双颊胡须"], ["ArchedEyebrows", "柳叶眉"],
357+
["Attractive", "吸引人的"], ["BagsUnderEyes", "眼袋"], ["Bald", "秃头"],
358+
["Bangs", "刘海"], ["BigLips", "大嘴唇"], ["BigNose", "大鼻子"],
359+
["BlackHair", "黑发"], ["BlondHair", "金发"], ["Blurry", "模糊的"],
360+
["BrownHair", "棕发"], ["BushyEyebrows", "浓眉"], ["Chubby", "圆胖的"],
361+
["DoubleChin", "双下巴"], ["Eyeglasses", "带眼镜"], ["Goatee", "山羊胡子"],
362+
["GrayHair", "灰发或白发"], ["HeavyMakeup", "浓妆"],
363+
["HighCheekbones", "高颧骨"], ["Male", "男性"],
364+
["MouthSlightlyOpen", "微微张开嘴巴"], ["Mustache", "胡子"],
365+
["NarrowEyes", "细长的眼睛"], ["NoBeard", "无胡子"],
366+
["OvalFace", "椭圆形的脸"], ["PaleSkin", "苍白的皮肤"],
367+
["PointyNose", "尖鼻子"], ["RecedingHairline", "发际线后移"],
368+
["RosyCheeks", "红润的双颊"], ["Sideburns", "连鬓胡子"], ["Smiling", "微笑"],
369+
["StraightHair", "直发"], ["WavyHair", "卷发"],
370+
["WearingEarrings", "戴着耳环"], ["WearingHat", "戴着帽子"],
371+
["WearingLipstick", "涂了唇膏"], ["WearingNecklace", "戴着项链"],
372+
["WearingNecktie", "戴着领带"], ["Young", "年轻人"]
373+
]
374+
gender_list = [["Male", "男性"], ["Female", "女性"]]
375+
age_list = [["Young", "年轻人"], ["Old", "老年人"]]
376+
batch_res = []
377+
if self.convert_cn:
378+
index = 1
379+
else:
380+
index = 0
381+
for idx, res in enumerate(x):
382+
res = res.tolist()
383+
label_res = []
384+
threshold_list = [self.threshold] * len(res)
385+
pred_res = (np.array(res) > np.array(threshold_list)
386+
).astype(np.int8).tolist()
387+
for i, value in enumerate(pred_res):
388+
if i == 20:
389+
label_res.append(gender_list[0][index]
390+
if value == 1 else gender_list[1][index])
391+
elif i == 39:
392+
label_res.append(age_list[0][index]
393+
if value == 1 else age_list[1][index])
394+
else:
395+
if value == 1:
396+
label_res.append(attribute_list[i][index])
397+
batch_res.append({"attributes": label_res, "output": pred_res})
398+
return batch_res
399+
400+
349401
class VehicleAttribute(object):
350402
def __init__(self, color_threshold=0.5, type_threshold=0.5):
351403
self.color_threshold = color_threshold

deploy/python/predict_cls.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ def main(config):
136136
if "PersonAttribute" in config[
137137
"PostProcess"] or "VehicleAttribute" in config[
138138
"PostProcess"] or "TableAttribute" in config[
139-
"PostProcess"]:
139+
"PostProcess"] or "FaceAttribute" in config[
140+
"PostProcess"]:
140141
filename = batch_names[number]
141142
print("{}:\t {}".format(filename, result_dict))
142143
else:

ppcls/data/postprocess/attr_rec.py

+62
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def __call__(self, x, file_names=None):
8484
if isinstance(x, dict):
8585
x = x['logits']
8686
assert isinstance(x, paddle.Tensor)
87+
8788
if file_names is not None:
8889
assert x.shape[0] == len(file_names)
8990
x = F.sigmoid(x).numpy()
@@ -98,6 +99,7 @@ def __call__(self, x, file_names=None):
9899
'Skirt&Dress'
99100
]
100101
batch_res = []
102+
101103
for idx, res in enumerate(x):
102104
res = res.tolist()
103105
label_res = []
@@ -171,6 +173,66 @@ def __call__(self, x, file_names=None):
171173
return batch_res
172174

173175

176+
class FaceAttribute(object):
177+
def __init__(self, threshold=0.65, convert_cn=False):
178+
self.threshold = threshold
179+
self.convert_cn = convert_cn
180+
181+
def __call__(self, x, file_names=None):
182+
if isinstance(x, dict):
183+
x = x['logits']
184+
assert isinstance(x, paddle.Tensor)
185+
186+
if file_names is not None:
187+
assert x.shape[0] == len(file_names)
188+
x = F.sigmoid(x).numpy()
189+
190+
attribute_list = [
191+
["CheekWhiskers", "刚长出的双颊胡须"], ["ArchedEyebrows", "柳叶眉"],
192+
["Attractive", "吸引人的"], ["BagsUnderEyes", "眼袋"], ["Bald", "秃头"],
193+
["Bangs", "刘海"], ["BigLips", "大嘴唇"], ["BigNose", "大鼻子"],
194+
["BlackHair", "黑发"], ["BlondHair", "金发"], ["Blurry", "模糊的"],
195+
["BrownHair", "棕发"], ["BushyEyebrows", "浓眉"], ["Chubby", "圆胖的"],
196+
["DoubleChin", "双下巴"], ["Eyeglasses", "带眼镜"], ["Goatee", "山羊胡子"],
197+
["GrayHair", "灰发或白发"], ["HeavyMakeup", "浓妆"],
198+
["HighCheekbones", "高颧骨"], ["Male", "男性"],
199+
["MouthSlightlyOpen", "微微张开嘴巴"], ["Mustache", "胡子"],
200+
["NarrowEyes", "细长的眼睛"], ["NoBeard", "无胡子"],
201+
["OvalFace", "椭圆形的脸"], ["PaleSkin", "苍白的皮肤"],
202+
["PointyNose", "尖鼻子"], ["RecedingHairline", "发际线后移"],
203+
["RosyCheeks", "红润的双颊"], ["Sideburns", "连鬓胡子"], ["Smiling", "微笑"],
204+
["StraightHair", "直发"], ["WavyHair", "卷发"],
205+
["WearingEarrings", "戴着耳环"], ["WearingHat", "戴着帽子"],
206+
["WearingLipstick", "涂了唇膏"], ["WearingNecklace", "戴着项链"],
207+
["WearingNecktie", "戴着领带"], ["Young", "年轻人"]
208+
]
209+
gender_list = [["Male", "男性"], ["Female", "女性"]]
210+
age_list = [["Young", "年轻人"], ["Old", "老年人"]]
211+
batch_res = []
212+
if self.convert_cn:
213+
index = 1
214+
else:
215+
index = 0
216+
for idx, res in enumerate(x):
217+
res = res.tolist()
218+
label_res = []
219+
threshold_list = [self.threshold] * len(res)
220+
pred_res = (np.array(res) > np.array(threshold_list)
221+
).astype(np.int8).tolist()
222+
for i, value in enumerate(pred_res):
223+
if i == 20:
224+
label_res.append(gender_list[0][index]
225+
if value == 1 else gender_list[1][index])
226+
elif i == 39:
227+
label_res.append(age_list[0][index]
228+
if value == 1 else age_list[1][index])
229+
else:
230+
if value == 1:
231+
label_res.append(attribute_list[i][index])
232+
batch_res.append({"attributes": label_res, "output": pred_res})
233+
return batch_res
234+
235+
174236
class TableAttribute(object):
175237
def __init__(
176238
self,

ppcls/metric/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from .metrics import GoogLeNetTopkAcc
2222
from .metrics import HammingDistance, AccuracyScore
2323
from .metrics import ATTRMetric
24-
from .metrics import TprAtFpr
24+
from .metrics import TprAtFpr, MultilabelMeanAccuracy
2525

2626

2727
class CombinedMetrics(AvgMetrics):

ppcls/metric/metrics.py

+49
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,55 @@ def avg_info(self):
218218
return result
219219

220220

221+
class MultilabelMeanAccuracy(nn.Layer):
222+
def __init__(self, class_num=40):
223+
super().__init__()
224+
self.gt_all_score_list = []
225+
self.gt_label_score_list = []
226+
self.max_acc = 0.
227+
self.class_num = class_num
228+
229+
def forward(self, x, label):
230+
if isinstance(x, dict):
231+
x = x["logits"]
232+
x = F.sigmoid(x)
233+
label = label[:, 0, :]
234+
for i in range(len(x)):
235+
self.gt_all_score_list.append(x[i].numpy())
236+
self.gt_label_score_list.append(label[i].numpy())
237+
return {}
238+
239+
def reset(self):
240+
self.gt_all_score_list = []
241+
self.gt_label_score_list = []
242+
self.max_acc = 0.
243+
244+
@property
245+
def avg(self):
246+
return self.max_acc
247+
248+
@property
249+
def avg_info(self):
250+
max_acc = 0.
251+
result = ""
252+
gt_all_score_list = np.array(self.gt_all_score_list)
253+
gt_label_score_list = np.array(self.gt_label_score_list)
254+
for i in range(10):
255+
threshold = 0.4 + i * 0.05
256+
pred_label = (gt_all_score_list > threshold).astype(int)
257+
TP = np.sum(
258+
(gt_label_score_list == 1) * (pred_label == 1)).astype(float)
259+
TN = np.sum(
260+
(gt_label_score_list == 0) * (pred_label == 0)).astype(float)
261+
acc = (TP + TN) / len(gt_all_score_list)
262+
if max_acc <= acc:
263+
max_acc = acc
264+
result = "threshold: {}, mean_acc: {}".format(
265+
threshold, max_acc / self.class_num)
266+
self.max_acc = max_acc / self.class_num
267+
return result
268+
269+
221270
class Recallk(nn.Layer):
222271
def __init__(self, topk=(1, 5), descending=True):
223272
super().__init__()

0 commit comments

Comments
 (0)