Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
PaddleX
提交
bb3030a8
P
PaddleX
项目概览
PaddlePaddle
/
PaddleX
通知
138
Star
4
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
43
列表
看板
标记
里程碑
合并请求
5
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleX
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
43
Issue
43
列表
看板
标记
里程碑
合并请求
5
合并请求
5
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
bb3030a8
编写于
5月 25, 2020
作者:
F
FlyingQianMM
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'develop' of
https://github.com/PaddlePaddle/PaddleX
into develop_qh
上级
b03f9b63
7acf4f36
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
147 addition
and
84 deletion
+147
-84
.pre-commit-config.yaml
.pre-commit-config.yaml
+1
-1
deploy/cpp/demo/detector.cpp
deploy/cpp/demo/detector.cpp
+2
-2
deploy/cpp/include/paddlex/results.h
deploy/cpp/include/paddlex/results.h
+2
-1
deploy/lite/export_lite.py
deploy/lite/export_lite.py
+8
-8
docs/apis/models/instance_segmentation.md
docs/apis/models/instance_segmentation.md
+1
-1
docs/apis/transforms/augment.md
docs/apis/transforms/augment.md
+1
-1
docs/tutorials/deploy/deploy_lite.md
docs/tutorials/deploy/deploy_lite.md
+16
-3
paddlex/cv/datasets/voc.py
paddlex/cv/datasets/voc.py
+1
-1
paddlex/cv/models/faster_rcnn.py
paddlex/cv/models/faster_rcnn.py
+2
-1
paddlex/cv/models/mask_rcnn.py
paddlex/cv/models/mask_rcnn.py
+4
-2
paddlex/cv/models/yolo_v3.py
paddlex/cv/models/yolo_v3.py
+15
-18
paddlex/interpret/as_data_reader/readers.py
paddlex/interpret/as_data_reader/readers.py
+4
-3
paddlex/interpret/core/interpretation_algorithms.py
paddlex/interpret/core/interpretation_algorithms.py
+28
-22
paddlex/interpret/core/lime_base.py
paddlex/interpret/core/lime_base.py
+4
-4
paddlex/interpret/core/normlime_base.py
paddlex/interpret/core/normlime_base.py
+16
-16
tools/codestyle/clang_format.hook
tools/codestyle/clang_format.hook
+15
-0
tools/codestyle/cpplint_pre_commit.hook
tools/codestyle/cpplint_pre_commit.hook
+27
-0
未找到文件。
.pre-commit-config.yaml
浏览文件 @
bb3030a8
...
...
@@ -35,6 +35,6 @@
-
id
:
cpplint-cpp-source
name
:
cpplint
description
:
Check C++ code style using cpplint.py.
entry
:
bash cpplint_pre_commit.hook
entry
:
bash
./tools/codestyle/
cpplint_pre_commit.hook
language
:
system
files
:
\.(c|cc|cxx|cpp|cu|h|hpp|hxx)$
deploy/cpp/demo/detector.cpp
浏览文件 @
bb3030a8
...
...
@@ -66,7 +66,7 @@ int main(int argc, char** argv) {
std
::
cout
<<
"image file: "
<<
image_path
<<
", predict label: "
<<
result
.
boxes
[
i
].
category
<<
", label_id:"
<<
result
.
boxes
[
i
].
category_id
<<
", score: "
<<
result
.
boxes
[
i
].
score
<<
", box:("
<<
", score: "
<<
result
.
boxes
[
i
].
score
<<
", box
(xmin, ymin, w, h)
:("
<<
result
.
boxes
[
i
].
coordinate
[
0
]
<<
", "
<<
result
.
boxes
[
i
].
coordinate
[
1
]
<<
", "
<<
result
.
boxes
[
i
].
coordinate
[
2
]
<<
", "
...
...
@@ -89,7 +89,7 @@ int main(int argc, char** argv) {
for
(
int
i
=
0
;
i
<
result
.
boxes
.
size
();
++
i
)
{
std
::
cout
<<
", predict label: "
<<
result
.
boxes
[
i
].
category
<<
", label_id:"
<<
result
.
boxes
[
i
].
category_id
<<
", score: "
<<
result
.
boxes
[
i
].
score
<<
", box:("
<<
", score: "
<<
result
.
boxes
[
i
].
score
<<
", box
(xmin, ymin, w, h)
:("
<<
result
.
boxes
[
i
].
coordinate
[
0
]
<<
", "
<<
result
.
boxes
[
i
].
coordinate
[
1
]
<<
", "
<<
result
.
boxes
[
i
].
coordinate
[
2
]
<<
", "
...
...
deploy/cpp/include/paddlex/results.h
浏览文件 @
bb3030a8
...
...
@@ -63,9 +63,10 @@ class SegResult : public BaseResult {
public:
Mask
<
int64_t
>
label_map
;
Mask
<
float
>
score_map
;
std
::
string
type
=
"seg"
;
void
clear
()
{
label_map
.
clear
();
score_map
.
clear
();
}
};
}
// namesp
ce of
PaddleX
}
// namesp
ace
PaddleX
deploy/lite/export_lite.py
浏览文件 @
bb3030a8
...
...
@@ -19,30 +19,30 @@ import argparse
def
export_lite
():
opt
=
lite
.
Opt
()
model_file
=
os
.
path
.
join
(
FLAGS
.
model_
path
,
'__model__'
)
params_file
=
os
.
path
.
join
(
FLAGS
.
model_
path
,
'__params__'
)
opt
.
run_optimize
(
""
,
model_file
,
params_file
,
FLAGS
.
place
,
FLAGS
.
save_
dir
)
model_file
=
os
.
path
.
join
(
FLAGS
.
model_
dir
,
'__model__'
)
params_file
=
os
.
path
.
join
(
FLAGS
.
model_
dir
,
'__params__'
)
opt
.
run_optimize
(
""
,
model_file
,
params_file
,
FLAGS
.
place
,
FLAGS
.
save_
file
)
if
__name__
==
'__main__'
:
parser
=
argparse
.
ArgumentParser
(
description
=
__doc__
)
parser
.
add_argument
(
"--model_
path
"
,
"--model_
dir
"
,
type
=
str
,
default
=
""
,
help
=
"
model path
."
,
help
=
"
path of '__model__' and '__params__'
."
,
required
=
True
)
parser
.
add_argument
(
"--place"
,
type
=
str
,
default
=
"arm"
,
help
=
"
preprocess config path
."
,
help
=
"
run place: 'arm|opencl|x86|npu|xpu|rknpu|apu'
."
,
required
=
True
)
parser
.
add_argument
(
"--save_
dir
"
,
"--save_
file
"
,
type
=
str
,
default
=
"paddlex.onnx"
,
help
=
"
Directory for storing the output visualization
files."
,
help
=
"
file name for storing the output
files."
,
required
=
True
)
FLAGS
=
parser
.
parse_args
()
export_lite
()
docs/apis/models/instance_segmentation.md
浏览文件 @
bb3030a8
...
...
@@ -82,4 +82,4 @@ predict(self, img_file, transforms=None)
>
> **返回值**
>
> > - **list**: 预测结果列表,列表中每个元素均为一个dict,key'bbox', 'mask', 'category', 'category_id', 'score',分别表示每个预测目标的框坐标信息、Mask信息,类别、类别id、置信度
,其中框坐标信息为[xmin, ymin, w, h],即左上角x, y坐标和框的宽和高
。
> > - **list**: 预测结果列表,列表中每个元素均为一个dict,key'bbox', 'mask', 'category', 'category_id', 'score',分别表示每个预测目标的框坐标信息、Mask信息,类别、类别id、置信度
。其中框坐标信息为[xmin, ymin, w, h],即左上角x, y坐标和框的宽和高。Mask信息为原图大小的二值图,1表示像素点属于预测类别,0表示像素点是背景
。
docs/apis/transforms/augment.md
浏览文件 @
bb3030a8
...
...
@@ -9,7 +9,7 @@ PaddleX对于图像分类、目标检测、实例分割和语义分割内置了
| 任务类型 | 增强方法 |
| :------- | :------------|
| 图像分类 |
[
RandomCrop
](
cls_transforms.html#randomcrop
)
、
[
RandomHorizontalFlip
](
cls_transforms.html#randomhorizontalflip
)
、
[
RandomVerticalFlip
](
cls_transforms.html#randomverticalflip
)
、
<br>
[
RandomRotate
](
cls_transforms.html#randomratate
)
、
[
RandomDistort
](
cls_transforms.html#randomdistort
)
|
|目标检测
<br>
实例分割|
[
RandomHorizontalFlip
](
det_transforms.html#randomhorizontalflip
)
、
[
RandomDistort
](
det_transforms.html#randomdistort
)
、
[
RandomCrop
](
det_transforms.html#randomcrop
)
、
<br>
[
[MixupImage
](
det_transforms.html#mixupimage
)(
仅支持YOLOv3模型
)
、
RandomExpand](det_transforms.html#randomexpand) |
|目标检测
<br>
实例分割|
[
RandomHorizontalFlip
](
det_transforms.html#randomhorizontalflip
)
、
[
RandomDistort
](
det_transforms.html#randomdistort
)
、
[
RandomCrop
](
det_transforms.html#randomcrop
)
、
<br>
[
MixupImage
](
det_transforms.html#mixupimage
)(
仅支持YOLOv3模型
)
、
[
RandomExpand
](
det_transforms.html#randomexpand
)
|
|语义分割 |
[
RandomHorizontalFlip
](
seg_transforms.html#randomhorizontalflip
)
、
[
RandomVerticalFlip
](
seg_transforms.html#randomverticalflip
)
、
[
RandomRangeScaling
](
seg_transforms.html#randomrangescaling
)
、
<br>
[
RandomStepScaling
](
seg_transforms.html#randomstepscaling
)
、
[
RandomPaddingCrop
](
seg_transforms.html#randompaddingcrop
)
、
[
RandomBlur
](
seg_transforms.html#randomblur
)
、
<br>
[
RandomRotation
](
seg_transforms.html#randomrotation
)
、
[
RandomScaleAspect
](
seg_transforms.html#randomscaleaspect
)
、
[
RandomDistort
](
seg_transforms.html#randomdistort
)
|
## imgaug增强库的支持
...
...
docs/tutorials/deploy/deploy_lite.md
浏览文件 @
bb3030a8
# 移动端部署
PaddleX的移动端部署由PaddleLite实现,部署的流程如下,首先将训练好的模型导出为inference model,然后使用PaddleLite的python接口对模型进行优化,最后使用PaddleLite的预测库进行部署,
PaddleLite的详细介绍和使用可参考:
[
PaddleLite文档
](
https://paddle-lite.readthedocs.io/zh/latest/
)
> PaddleX --> Inference Model --> PaddleLite Opt --> PaddleLite Inference
以下介绍如何将PaddleX导出为inference model,然后使用PaddleLite的OPT模块对模型进行优化:
step 1: 安装PaddleLite
```
...
...
@@ -9,15 +16,21 @@ pip install paddlelite
step 2: 将PaddleX模型导出为inference模型
参考
[
导出inference模型
](
deploy_server/deploy_python.html#inference
)
将模型导出为inference格式模型。
**注意:由于PaddleX代码的持续更新,版本低于1.0.0的模型暂时无法直接用于预测部署,参考[模型版本升级](.
.
/upgrade_version.md)对模型版本进行升级。**
**注意:由于PaddleX代码的持续更新,版本低于1.0.0的模型暂时无法直接用于预测部署,参考[模型版本升级](./upgrade_version.md)对模型版本进行升级。**
step 3: 将inference模型转换成PaddleLite模型
```
python /path/to/PaddleX/deploy/lite/export_lite.py --model_path /path/to/inference_model --save_dir /path/to/onnx_model
python /path/to/PaddleX/deploy/lite/export_lite.py --model_dir /path/to/inference_model --save_file /path/to/onnx_model --place place/to/run
```
`--model_path`
用于指定inference模型的路径,
`--save_dir`
用于指定Lite模型的保存路径。
| 参数 | 说明 |
| ---- | ---- |
| model_dir | 预测模型所在路径,包含"__model__", "__params__"文件 |
| save_file | 模型输出的名称,默认为"paddlex.nb" |
| place | 运行的平台,可选:arm|opencl|x86|npu|xpu|rknpu|apu |
step 4: 预测
...
...
paddlex/cv/datasets/voc.py
浏览文件 @
bb3030a8
...
...
@@ -113,7 +113,7 @@ class VOCDetection(Dataset):
is_crowd
=
np
.
zeros
((
len
(
objs
),
1
),
dtype
=
np
.
int32
)
difficult
=
np
.
zeros
((
len
(
objs
),
1
),
dtype
=
np
.
int32
)
for
i
,
obj
in
enumerate
(
objs
):
cname
=
obj
.
find
(
'name'
).
text
cname
=
obj
.
find
(
'name'
).
text
.
strip
()
gt_class
[
i
][
0
]
=
cname2cid
[
cname
]
_difficult
=
int
(
obj
.
find
(
'difficult'
).
text
)
x1
=
float
(
obj
.
find
(
'bndbox'
).
find
(
'xmin'
).
text
)
...
...
paddlex/cv/models/faster_rcnn.py
浏览文件 @
bb3030a8
...
...
@@ -367,7 +367,8 @@ class FasterRCNN(BaseAPI):
Returns:
list: 预测结果列表,每个预测结果由预测框类别标签、
预测框类别名称、预测框坐标、预测框得分组成。
预测框类别名称、预测框坐标(坐标格式为[xmin, ymin, w, h])、
预测框得分组成。
"""
if
transforms
is
None
and
not
hasattr
(
self
,
'test_transforms'
):
raise
Exception
(
"transforms need to be defined, now is None."
)
...
...
paddlex/cv/models/mask_rcnn.py
浏览文件 @
bb3030a8
...
...
@@ -333,8 +333,10 @@ class MaskRCNN(FasterRCNN):
transforms (paddlex.det.transforms): 数据预处理操作。
Returns:
dict: 预测结果列表,每个预测结果由预测框类别标签、预测框类别名称、预测框坐标、预测框内的二值图、
预测框得分组成。
dict: 预测结果列表,每个预测结果由预测框类别标签、预测框类别名称、
预测框坐标(坐标格式为[xmin, ymin, w, h])、
原图大小的预测二值图(1表示预测框类别,0表示背景类)、
预测框得分组成。
"""
if
transforms
is
None
and
not
hasattr
(
self
,
'test_transforms'
):
raise
Exception
(
"transforms need to be defined, now is None."
)
...
...
paddlex/cv/models/yolo_v3.py
浏览文件 @
bb3030a8
...
...
@@ -306,11 +306,10 @@ class YOLOv3(BaseAPI):
images
=
np
.
array
([
d
[
0
]
for
d
in
data
])
im_sizes
=
np
.
array
([
d
[
1
]
for
d
in
data
])
feed_data
=
{
'image'
:
images
,
'im_size'
:
im_sizes
}
outputs
=
self
.
exe
.
run
(
self
.
test_prog
,
feed
=
[
feed_data
],
fetch_list
=
list
(
self
.
test_outputs
.
values
()),
return_numpy
=
False
)
outputs
=
self
.
exe
.
run
(
self
.
test_prog
,
feed
=
[
feed_data
],
fetch_list
=
list
(
self
.
test_outputs
.
values
()),
return_numpy
=
False
)
res
=
{
'bbox'
:
(
np
.
array
(
outputs
[
0
]),
outputs
[
0
].
recursive_sequence_lengths
())
...
...
@@ -326,13 +325,13 @@ class YOLOv3(BaseAPI):
res
[
'gt_label'
]
=
(
res_gt_label
,
[])
res
[
'is_difficult'
]
=
(
res_is_difficult
,
[])
results
.
append
(
res
)
logging
.
debug
(
"[EVAL] Epoch={}, Step={}/{}"
.
format
(
epoch_id
,
step
+
1
,
total_steps
))
logging
.
debug
(
"[EVAL] Epoch={}, Step={}/{}"
.
format
(
epoch_id
,
step
+
1
,
total_steps
))
box_ap_stats
,
eval_details
=
eval_results
(
results
,
metric
,
eval_dataset
.
coco_gt
,
with_background
=
False
)
evaluate_metrics
=
OrderedDict
(
zip
([
'bbox_mmap'
if
metric
==
'COCO'
else
'bbox_map'
],
box_ap_stats
))
zip
([
'bbox_mmap'
if
metric
==
'COCO'
else
'bbox_map'
],
box_ap_stats
))
if
return_details
:
return
evaluate_metrics
,
eval_details
return
evaluate_metrics
...
...
@@ -346,7 +345,8 @@ class YOLOv3(BaseAPI):
Returns:
list: 预测结果列表,每个预测结果由预测框类别标签、
预测框类别名称、预测框坐标、预测框得分组成。
预测框类别名称、预测框坐标(坐标格式为[xmin, ymin, w, h])、
预测框得分组成。
"""
if
transforms
is
None
and
not
hasattr
(
self
,
'test_transforms'
):
raise
Exception
(
"transforms need to be defined, now is None."
)
...
...
@@ -359,14 +359,11 @@ class YOLOv3(BaseAPI):
im
,
im_size
=
self
.
test_transforms
(
img_file
)
im
=
np
.
expand_dims
(
im
,
axis
=
0
)
im_size
=
np
.
expand_dims
(
im_size
,
axis
=
0
)
outputs
=
self
.
exe
.
run
(
self
.
test_prog
,
feed
=
{
'image'
:
im
,
'im_size'
:
im_size
},
fetch_list
=
list
(
self
.
test_outputs
.
values
()),
return_numpy
=
False
)
outputs
=
self
.
exe
.
run
(
self
.
test_prog
,
feed
=
{
'image'
:
im
,
'im_size'
:
im_size
},
fetch_list
=
list
(
self
.
test_outputs
.
values
()),
return_numpy
=
False
)
res
=
{
k
:
(
np
.
array
(
v
),
v
.
recursive_sequence_lengths
())
for
k
,
v
in
zip
(
list
(
self
.
test_outputs
.
keys
()),
outputs
)
...
...
paddlex/interpret/as_data_reader/readers.py
浏览文件 @
bb3030a8
...
...
@@ -20,6 +20,7 @@ import six
import
glob
from
.data_path_utils
import
_find_classes
from
PIL
import
Image
import
paddlex.utils.logging
as
logging
def
resize_short
(
img
,
target_size
,
interpolation
=
None
):
...
...
@@ -117,7 +118,7 @@ def read_image(img_path, target_size=256, crop_size=224):
assert
len
(
img_path
.
shape
)
==
4
return
img_path
else
:
ValueError
(
f
"Not recognized data type
{
type
(
img_path
)
}
."
)
ValueError
(
"Not recognized data type {}."
.
format
(
type
(
img_path
))
)
class
ReaderConfig
(
object
):
...
...
@@ -156,7 +157,7 @@ class ReaderConfig(object):
img
=
cv2
.
imread
(
img_path
)
if
img
is
None
:
print
(
img_path
)
logging
.
info
(
img_path
)
continue
img
=
resize_short
(
img
,
target_size
,
interpolation
=
None
)
img
=
crop_image
(
img
,
crop_size
,
center
=
self
.
is_test
)
...
...
@@ -208,7 +209,7 @@ def create_reader(list_image_path, list_label=None, is_test=False):
img
=
cv2
.
imread
(
img_path
)
if
img
is
None
:
print
(
img_path
)
logging
.
info
(
img_path
)
continue
img
=
resize_short
(
img
,
target_size
,
interpolation
=
None
)
...
...
paddlex/interpret/core/interpretation_algorithms.py
浏览文件 @
bb3030a8
...
...
@@ -21,6 +21,7 @@ from . import lime_base
from
._session_preparation
import
paddle_get_fc_weights
,
compute_features_for_kmeans
,
gen_user_home
from
.normlime_base
import
combine_normlime_and_lime
,
get_feature_for_kmeans
,
load_kmeans_model
from
paddlex.interpret.as_data_reader.readers
import
read_image
import
paddlex.utils.logging
as
logging
import
cv2
...
...
@@ -71,7 +72,8 @@ class CAM(object):
if
self
.
label_names
is
not
None
:
ln
=
self
.
label_names
[
l
]
print
(
f
'predicted result:
{
ln
}
with probability
{
probability
[
pred_label
[
0
]]:.
3
f
}
'
)
prob_str
=
"%.3f"
%
(
probability
[
pred_label
[
0
]])
logging
.
info
(
"predicted result: {} with probability {}."
.
format
(
ln
,
prob_str
))
return
feature_maps
,
fc_weights
def
interpret
(
self
,
data_
,
visualization
=
True
,
save_to_disk
=
True
,
save_outdir
=
None
):
...
...
@@ -96,7 +98,8 @@ class CAM(object):
ax
.
axis
(
"off"
)
axes
=
axes
.
ravel
()
axes
[
0
].
imshow
(
self
.
image
)
axes
[
0
].
set_title
(
f
"label
{
ln
}
, proba:
{
self
.
predicted_probability
:
.
3
f
}
"
)
prob_str
=
"{%.3f}"
%
(
self
.
predicted_probability
)
axes
[
0
].
set_title
(
"label {}, proba: {}"
.
format
(
ln
,
prob_str
))
axes
[
1
].
imshow
(
cam
)
axes
[
1
].
set_title
(
"CAM"
)
...
...
@@ -157,14 +160,15 @@ class LIME(object):
if
self
.
label_names
is
not
None
:
ln
=
self
.
label_names
[
l
]
print
(
f
'predicted result:
{
ln
}
with probability
{
probability
[
pred_label
[
0
]]:.
3
f
}
'
)
prob_str
=
"%.3f"
%
(
probability
[
pred_label
[
0
]])
logging
.
info
(
"predicted result: {} with probability {}."
.
format
(
ln
,
prob_str
))
end
=
time
.
time
()
algo
=
lime_base
.
LimeImageInterpreter
()
interpreter
=
algo
.
interpret_instance
(
self
.
image
,
self
.
predict_fn
,
self
.
labels
,
0
,
num_samples
=
self
.
num_samples
,
batch_size
=
self
.
batch_size
)
self
.
lime_interpreter
=
interpreter
print
(
'lime time: '
,
time
.
time
()
-
end
,
's.'
)
logging
.
info
(
'lime time: '
+
str
(
time
.
time
()
-
end
)
+
's.'
)
def
interpret
(
self
,
data_
,
visualization
=
True
,
save_to_disk
=
True
,
save_outdir
=
None
):
if
self
.
lime_interpreter
is
None
:
...
...
@@ -189,7 +193,8 @@ class LIME(object):
ax
.
axis
(
"off"
)
axes
=
axes
.
ravel
()
axes
[
0
].
imshow
(
self
.
image
)
axes
[
0
].
set_title
(
f
"label
{
ln
}
, proba:
{
self
.
predicted_probability
:
.
3
f
}
"
)
prob_str
=
"{%.3f}"
%
(
self
.
predicted_probability
)
axes
[
0
].
set_title
(
"label {}, proba: {}"
.
format
(
ln
,
prob_str
))
axes
[
1
].
imshow
(
mark_boundaries
(
self
.
image
,
self
.
lime_interpreter
.
segments
))
axes
[
1
].
set_title
(
"superpixel segmentation"
)
...
...
@@ -201,7 +206,7 @@ class LIME(object):
l
,
positive_only
=
False
,
hide_rest
=
False
,
num_features
=
num_to_show
)
axes
[
ncols
+
i
].
imshow
(
mark_boundaries
(
temp
,
mask
))
axes
[
ncols
+
i
].
set_title
(
f
"label
{
ln
}
, first
{
num_to_show
}
superpixels"
)
axes
[
ncols
+
i
].
set_title
(
"label {}, first {} superpixels"
.
format
(
ln
,
num_to_show
)
)
if
save_to_disk
and
save_outdir
is
not
None
:
os
.
makedirs
(
save_outdir
,
exist_ok
=
True
)
...
...
@@ -232,8 +237,9 @@ class NormLIME(object):
raise
ValueError
(
"NormLIME needs the KMeans model, where we provided a default one in "
"pre_models/kmeans_model.pkl."
)
else
:
print
(
"Warning: It is *strongly* suggested to use the default KMeans model in pre_models/kmeans_model.pkl. "
"Use another one will change the final result."
)
logging
.
debug
(
"Warning: It is *strongly* suggested to use the
\
default KMeans model in pre_models/kmeans_model.pkl.
\
Use another one will change the final result."
)
self
.
kmeans_model
=
load_kmeans_model
(
kmeans_model_for_normlime
)
self
.
num_samples
=
num_samples
...
...
@@ -243,7 +249,7 @@ class NormLIME(object):
self
.
normlime_weights
=
np
.
load
(
normlime_weights
,
allow_pickle
=
True
).
item
()
except
:
self
.
normlime_weights
=
None
print
(
"Warning: not find the correct precomputed Normlime result."
)
logging
.
debug
(
"Warning: not find the correct precomputed Normlime result."
)
self
.
predict_fn
=
predict_fn
...
...
@@ -289,8 +295,7 @@ class NormLIME(object):
self
.
predicted_probability
=
self
.
_lime
.
predicted_probability
self
.
image
=
image_show
[
0
]
self
.
labels
=
self
.
_lime
.
labels
# print(f'predicted result: {self.predicted_label} with probability {self.predicted_probability: .3f}')
print
(
'performing NormLIME operations ...'
)
logging
.
info
(
'performing NormLIME operations ...'
)
cluster_labels
=
self
.
predict_cluster_labels
(
compute_features_for_kmeans
(
image_show
).
transpose
((
1
,
2
,
0
)),
self
.
_lime
.
lime_interpreter
.
segments
...
...
@@ -329,7 +334,8 @@ class NormLIME(object):
axes
=
axes
.
ravel
()
axes
[
0
].
imshow
(
self
.
image
)
axes
[
0
].
set_title
(
f
"label
{
ln
}
, proba:
{
self
.
predicted_probability
:
.
3
f
}
"
)
prob_str
=
"{%.3f}"
%
(
self
.
predicted_probability
)
axes
[
0
].
set_title
(
"label {}, proba: {}"
.
format
(
ln
,
prob_str
))
axes
[
1
].
imshow
(
mark_boundaries
(
self
.
image
,
self
.
_lime
.
lime_interpreter
.
segments
))
axes
[
1
].
set_title
(
"superpixel segmentation"
)
...
...
@@ -342,7 +348,7 @@ class NormLIME(object):
l
,
positive_only
=
False
,
hide_rest
=
False
,
num_features
=
num_to_show
)
axes
[
ncols
+
i
].
imshow
(
mark_boundaries
(
temp
,
mask
))
axes
[
ncols
+
i
].
set_title
(
f
"LIME: first
{
num_to_show
}
superpixels"
)
axes
[
ncols
+
i
].
set_title
(
"LIME: first {} superpixels"
.
format
(
num_to_show
)
)
# NormLIME visualization
self
.
_lime
.
lime_interpreter
.
local_weights
=
g_weights
...
...
@@ -351,7 +357,7 @@ class NormLIME(object):
l
,
positive_only
=
False
,
hide_rest
=
False
,
num_features
=
num_to_show
)
axes
[
ncols
*
2
+
i
].
imshow
(
mark_boundaries
(
temp
,
mask
))
axes
[
ncols
*
2
+
i
].
set_title
(
f
"NormLIME: first
{
num_to_show
}
superpixels"
)
axes
[
ncols
*
2
+
i
].
set_title
(
"NormLIME: first {} superpixels"
.
format
(
num_to_show
)
)
# NormLIME*LIME visualization
combined_weights
=
combine_normlime_and_lime
(
lime_weights
,
g_weights
)
...
...
@@ -361,7 +367,7 @@ class NormLIME(object):
l
,
positive_only
=
False
,
hide_rest
=
False
,
num_features
=
num_to_show
)
axes
[
ncols
*
3
+
i
].
imshow
(
mark_boundaries
(
temp
,
mask
))
axes
[
ncols
*
3
+
i
].
set_title
(
f
"Combined: first
{
num_to_show
}
superpixels"
)
axes
[
ncols
*
3
+
i
].
set_title
(
"Combined: first {} superpixels"
.
format
(
num_to_show
)
)
self
.
_lime
.
lime_interpreter
.
local_weights
=
lime_weights
...
...
@@ -433,32 +439,32 @@ def save_fig(data_, save_outdir, algorithm_name, num_samples=3000):
import
matplotlib.pyplot
as
plt
if
isinstance
(
data_
,
str
):
if
algorithm_name
==
'cam'
:
f_out
=
f
"
{
algorithm_name
}
_
{
data_
.
split
(
'/'
)[
-
1
]
}
.png"
f_out
=
"{}_{}.png"
.
format
(
algorithm_name
,
data_
.
split
(
'/'
)[
-
1
])
else
:
f_out
=
f
"
{
algorithm_name
}
_
{
data_
.
split
(
'/'
)[
-
1
]
}
_s
{
num_samples
}
.png"
f_out
=
"{}_{}_s{}.png"
.
format
(
algorithm_name
,
data_
.
split
(
'/'
)[
-
1
],
num_samples
)
plt
.
savefig
(
os
.
path
.
join
(
save_outdir
,
f_out
)
)
else
:
n
=
0
if
algorithm_name
==
'cam'
:
f_out
=
f
'cam-
{
n
}
.png'
f_out
=
'cam-{}.png'
.
format
(
n
)
else
:
f_out
=
f
'
{
algorithm_name
}
_s
{
num_samples
}
-
{
n
}
.png'
f_out
=
'{}_s{}-{}.png'
.
format
(
algorithm_name
,
num_samples
,
n
)
while
os
.
path
.
exists
(
os
.
path
.
join
(
save_outdir
,
f_out
)
):
n
+=
1
if
algorithm_name
==
'cam'
:
f_out
=
f
'cam-
{
n
}
.png'
f_out
=
'cam-{}.png'
.
format
(
n
)
else
:
f_out
=
f
'
{
algorithm_name
}
_s
{
num_samples
}
-
{
n
}
.png'
f_out
=
'{}_s{}-{}.png'
.
format
(
algorithm_name
,
num_samples
,
n
)
continue
plt
.
savefig
(
os
.
path
.
join
(
save_outdir
,
f_out
)
)
print
(
'The image of intrepretation result save in {}'
.
format
(
os
.
path
.
join
(
logging
.
info
(
'The image of intrepretation result save in {}'
.
format
(
os
.
path
.
join
(
save_outdir
,
f_out
)))
paddlex/interpret/core/lime_base.py
浏览文件 @
bb3030a8
...
...
@@ -34,6 +34,7 @@ import scipy as sp
import
tqdm
import
copy
from
functools
import
partial
import
paddlex.utils.logging
as
logging
class
LimeBase
(
object
):
...
...
@@ -230,9 +231,9 @@ class LimeBase(object):
local_pred
=
easy_model
.
predict
(
neighborhood_data
[
0
,
used_features
].
reshape
(
1
,
-
1
))
if
self
.
verbose
:
print
(
'Intercept'
,
easy_model
.
intercept_
)
print
(
'Prediction_local'
,
local_pred
,
)
print
(
'Right:'
,
neighborhood_labels
[
0
,
label
]
)
logging
.
info
(
'Intercept'
+
str
(
easy_model
.
intercept_
)
)
logging
.
info
(
'Prediction_local'
+
str
(
local_pred
)
)
logging
.
info
(
'Right:'
+
str
(
neighborhood_labels
[
0
,
label
])
)
return
(
easy_model
.
intercept_
,
sorted
(
zip
(
used_features
,
easy_model
.
coef_
),
key
=
lambda
x
:
np
.
abs
(
x
[
1
]),
reverse
=
True
),
...
...
@@ -451,7 +452,6 @@ class LimeImageInterpreter(object):
d
=
cdist
(
centroids
,
centroids
,
'sqeuclidean'
)
for
x
in
np
.
unique
(
segments
):
# print(np.argmin(d[x]))
a
=
[
image
[
segments
==
i
]
for
i
in
np
.
argsort
(
d
[
x
])[
1
:
6
]]
mx
=
np
.
mean
(
np
.
concatenate
(
a
),
axis
=
0
)
fudged_image
[
segments
==
x
]
=
mx
...
...
paddlex/interpret/core/normlime_base.py
浏览文件 @
bb3030a8
...
...
@@ -21,6 +21,7 @@ from paddlex.interpret.as_data_reader.readers import read_image
import
paddlex.utils.logging
as
logging
from
.
import
lime_base
from
._session_preparation
import
compute_features_for_kmeans
,
gen_user_home
import
paddlex.utils.logging
as
logging
def
load_kmeans_model
(
fname
):
...
...
@@ -67,7 +68,6 @@ def centroid_using_superpixels(features, segments):
one_list
=
np
.
zeros
((
len
(
np
.
unique
(
segments
)),
features
.
shape
[
2
]))
for
i
,
r
in
enumerate
(
regions
):
one_list
[
i
]
=
features
[
int
(
r
.
centroid
[
0
]
+
0.5
),
int
(
r
.
centroid
[
1
]
+
0.5
),
:]
# print(one_list.shape)
return
one_list
...
...
@@ -85,7 +85,7 @@ def precompute_normlime_weights(list_data_, predict_fn, num_samples=3000, batch_
precompute_lime_weights
(
list_data_
,
predict_fn
,
num_samples
,
batch_size
,
save_dir
)
# load precomputed results, compute normlime weights and save.
fname_list
=
glob
.
glob
(
os
.
path
.
join
(
save_dir
,
f
'lime_weights_s
{
num_samples
}
*.npy'
))
fname_list
=
glob
.
glob
(
os
.
path
.
join
(
save_dir
,
'lime_weights_s{}*.npy'
.
format
(
num_samples
)
))
return
compute_normlime_weights
(
fname_list
,
save_dir
,
num_samples
)
...
...
@@ -117,10 +117,10 @@ def precompute_lime_weights(list_data_, predict_fn, num_samples, batch_size, sav
for
data_index
,
each_data_
in
enumerate
(
list_data_
):
if
isinstance
(
each_data_
,
str
):
save_path
=
f
"lime_weights_s
{
num_samples
}
_
{
each_data_
.
split
(
'/'
)[
-
1
].
split
(
'.'
)[
0
]
}
.npy"
save_path
=
"lime_weights_s{}_{}.npy"
.
format
(
num_samples
,
each_data_
.
split
(
'/'
)[
-
1
].
split
(
'.'
)[
0
])
save_path
=
os
.
path
.
join
(
save_dir
,
save_path
)
else
:
save_path
=
f
"lime_weights_s
{
num_samples
}
_
{
data_index
}
.npy"
save_path
=
"lime_weights_s{}_{}.npy"
.
format
(
num_samples
,
data_index
)
save_path
=
os
.
path
.
join
(
save_dir
,
save_path
)
if
os
.
path
.
exists
(
save_path
):
...
...
@@ -174,16 +174,16 @@ def precompute_lime_weights(list_data_, predict_fn, num_samples, batch_size, sav
def
compute_normlime_weights
(
a_list_lime_fnames
,
save_dir
,
lime_num_samples
):
normlime_weights_all_labels
=
{}
for
f
in
a_list_lime_fnames
:
try
:
lime_weights_and_cluster
=
np
.
load
(
f
,
allow_pickle
=
True
).
item
()
lime_weights
=
lime_weights_and_cluster
[
'lime_weights'
]
cluster
=
lime_weights_and_cluster
[
'cluster'
]
except
:
print
(
'When loading precomputed LIME result, skipping'
,
f
)
logging
.
info
(
'When loading precomputed LIME result, skipping'
+
str
(
f
)
)
continue
print
(
'Loading precomputed LIME result,'
,
f
)
logging
.
info
(
'Loading precomputed LIME result,'
+
str
(
f
))
pred_labels
=
lime_weights
.
keys
()
for
y
in
pred_labels
:
normlime_weights
=
normlime_weights_all_labels
.
get
(
y
,
{})
...
...
@@ -207,23 +207,23 @@ def compute_normlime_weights(a_list_lime_fnames, save_dir, lime_num_samples):
# check normlime
if
len
(
normlime_weights_all_labels
.
keys
())
<
max
(
normlime_weights_all_labels
.
keys
())
+
1
:
print
(
"
\n
"
"Warning: !!!
\n
"
f
"There are at least
{
max
(
normlime_weights_all_labels
.
keys
())
+
1
}
classes, "
f
"but the NormLIME has results of only
{
len
(
normlime_weights_all_labels
.
keys
())
}
classes.
\n
"
"It may have cause unstable results in the later computation"
" but can be improved by computing more test samples."
logging
.
info
(
"
\n
"
+
\
"Warning: !!!
\n
"
+
\
"There are at least {} classes, "
.
format
(
max
(
normlime_weights_all_labels
.
keys
())
+
1
)
+
\
"but the NormLIME has results of only {} classes.
\n
"
.
format
(
len
(
normlime_weights_all_labels
.
keys
()))
+
\
"It may have cause unstable results in the later computation"
+
\
" but can be improved by computing more test samples."
+
\
"
\n
"
)
n
=
0
f_out
=
f
'normlime_weights_s
{
lime_num_samples
}
_samples_
{
len
(
a_list_lime_fnames
)
}
-
{
n
}
.npy'
f_out
=
'normlime_weights_s{}_samples_{}-{}.npy'
.
format
(
lime_num_samples
,
len
(
a_list_lime_fnames
),
n
)
while
os
.
path
.
exists
(
os
.
path
.
join
(
save_dir
,
f_out
)
):
n
+=
1
f_out
=
f
'normlime_weights_s
{
lime_num_samples
}
_samples_
{
len
(
a_list_lime_fnames
)
}
-
{
n
}
.npy'
f_out
=
'normlime_weights_s{}_samples_{}-{}.npy'
.
format
(
lime_num_samples
,
len
(
a_list_lime_fnames
),
n
)
continue
np
.
save
(
...
...
tools/codestyle/clang_format.hook
0 → 100755
浏览文件 @
bb3030a8
#!/bin/bash
set
-e
readonly
VERSION
=
"3.8"
version
=
$(
clang-format
-version
)
if
!
[[
$version
==
*
"
$VERSION
"
*
]]
;
then
echo
"clang-format version check failed."
echo
"a version contains '
$VERSION
' is needed, but get '
$version
'"
echo
"you can install the right version, and make an soft-link to '
\$
PATH' env"
exit
-1
fi
clang-format
$@
tools/codestyle/cpplint_pre_commit.hook
0 → 100755
浏览文件 @
bb3030a8
#!/bin/bash
TOTAL_ERRORS
=
0
if
[[
!
$TRAVIS_BRANCH
]]
;
then
# install cpplint on local machine.
if
[[
!
$(
which cpplint
)
]]
;
then
pip
install
cpplint
fi
# diff files on local machine.
files
=
$(
git diff
--cached
--name-status
|
awk
'$1 != "D" {print $2}'
)
else
# diff files between PR and latest commit on Travis CI.
branch_ref
=
$(
git rev-parse
"
$TRAVIS_BRANCH
"
)
head_ref
=
$(
git rev-parse HEAD
)
files
=
$(
git diff
--name-status
$branch_ref
$head_ref
|
awk
'$1 != "D" {print $2}'
)
fi
# The trick to remove deleted files: https://stackoverflow.com/a/2413151
for
file
in
$files
;
do
if
[[
$file
=
~ ^
(
patches/.
*
)
]]
;
then
continue
;
else
cpplint
--filter
=
-readability
/fn_size
$file
;
TOTAL_ERRORS
=
$(
expr
$TOTAL_ERRORS
+
$?
)
;
fi
done
exit
$TOTAL_ERRORS
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录