Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
PaddleHub
提交
d728f771
P
PaddleHub
项目概览
PaddlePaddle
/
PaddleHub
大约 2 年 前同步成功
通知
285
Star
12117
Fork
2091
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
200
列表
看板
标记
里程碑
合并请求
4
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleHub
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
200
Issue
200
列表
看板
标记
里程碑
合并请求
4
合并请求
4
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d728f771
编写于
12月 01, 2020
作者:
W
wuzewu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update docs
上级
ca8541bd
变更
5
展开全部
隐藏空白更改
内联
并排
Showing
5 changed file
with
2 addition
and
873 deletion
+2
-873
RELEASE.md
RELEASE.md
+0
-183
docs/index.rst
docs/index.rst
+0
-1
docs/tutorial/contri_pretrained_model.md
docs/tutorial/contri_pretrained_model.md
+0
-309
docs/tutorial/how_to_finetune.md
docs/tutorial/how_to_finetune.md
+0
-376
docs/tutorial/tutorial_index.rst
docs/tutorial/tutorial_index.rst
+2
-4
未找到文件。
RELEASE.md
已删除
100644 → 0
浏览文件 @
ca8541bd
## `v1.8.0`
*
预训练模型丰富,一键完成更多
*
『
[
文本生成
](
https://www.paddlepaddle.org.cn/hublist?filter=en_category&value=TextGeneration
)
』新增基于ERNIE-tiny和ERNIE-gen的对联和写诗生成模型,支持一键自动写诗和对对联。
*
『
[
词法分析
](
https://www.paddlepaddle.org.cn/hublist?filter=en_category&value=LexicalAnalysis
)
』新增jieba的paddle模式切词模型,可一键完成中文分词、关键词抽取等功能。
*
『
[
语义表示
](
https://www.paddlepaddle.org.cn/hublist?filter=en_category&value=SemanticModel
)
』新增基于网页、小说、新闻三类大规模文本数据的LDA主题模型及其语义相似度计算接口。
*
Fine-tune API升级,提升灵活性并支持更多任务
*
新增Tokenizer API,支持更加灵活的切词、切字模式和自定义切词工具拓展。
*
新增
[
文本生成
](
https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.8/demo/text_generation
)
任务,支持Seq2Seq任务的Fine-tuning。
*
新增文本匹配任务,支持
[
Pointwise
](
https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.8/demo/pointwise_text_matching
)
、
[
Pairwise
](
https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.8/demo/pairwise_text_matching
)
两种文本匹配训练模式,更便捷完成语义匹配任务。
## `v1.7.0`
*
丰富预训练模型,提升应用性
*
新增VENUS系列视觉预训练模型
[
yolov3_darknet53_venus
](
https://www.paddlepaddle.org.cn/hubdetail?name=yolov3_darknet53_venus&en_category=ObjectDetection
)
,
[
faster_rcnn_resnet50_fpn_venus
](
https://www.paddlepaddle.org.cn/hubdetail?name=faster_rcnn_resnet50_fpn_venus&en_category=ObjectDetection
)
,可大幅度提升图像分类和目标检测任务的Fine-tune效果
*
新增工业级短视频分类模型
[
videotag_tsn_lstm
](
https://paddlepaddle.org.cn/hubdetail?name=videotag_tsn_lstm&en_category=VideoClassification
)
,支持3000类中文标签识别
*
新增轻量级中文
[
OCR模型
](
https://www.paddlepaddle.org.cn/hublist?filter=en_category&value=TextRecognition
)
,支持一键快速OCR识别
*
新增行人检测、车辆检测、动物识别、Object等工业级模型
*
Fine-tune API升级
*
文本分类任务新增6个预置网络,包括CNN, BOW, LSTM, BiLSTM, DPCNN等
*
使用VisualDL可视化训练评估性能数据
## `v1.6.2`
*
修复图像分类在windows下运行错误
## `v1.6.1`
*
修复windows下安装PaddleHub缺失config.json文件
# `v1.6.0`
*
NLP Module全面升级,提升应用性和灵活性
*
lac、senta系列(bow、cnn、bilstm、gru、lstm)、simnet_bow、porn_detection系列(cnn、gru、lstm)升级高性能预测,性能提升高达50%
*
ERNIE、BERT、RoBERTa等Transformer类语义模型新增获取预训练embedding接口get_embedding,方便接入下游任务,提升应用性
*
新增RoBERTa通过模型结构压缩得到的3层Transformer模型
[
rbt3
](
https://www.paddlepaddle.org.cn/hubdetail?name=rbt3&en_category=SemanticModel
)
、
[
rbtl3
](
https://www.paddlepaddle.org.cn/hubdetail?name=rbtl3&en_category=SemanticModel
)
*
Task predict接口增加高性能预测模式accelerate_mode,性能提升高达90%
*
PaddleHub Module创建流程开放,支持Fine-tune模型转化,全面提升应用性和灵活性
*
[
预训练模型转化为PaddleHub Module教程
](
./docs/contribution/contri_pretrained_model.md
)
*
[
Fine-tune模型转化为PaddleHub Module教程
](
./docs/tutorial/finetuned_model_to_module.md
)
*
[
PaddleHub Serving
](
/docs/tutorial/serving.md
)
优化启动方式,支持更加灵活的参数配置
# `v1.5.4`
*
修复Fine-tune中断,checkpoint文件恢复训练失败的问题
# `v1.5.3`
*
优化口罩模型输出结果,提供更加灵活的部署及调用方式
# `v1.5.2`
*
优化pyramidbox_lite_server_mask、pyramidbox_lite_mobile_mask模型的服务化部署性能
# `v1.5.1`
*
修复加载module缺少cache目录的问题
# `v1.5.0`
*
升级PaddleHub Serving,提升性能和易用性
*
新增文本Embedding服务
[
Bert Service
](
./docs/tutorial/bert_service.md
)
, 轻松获取文本embedding;
*
代码精短,易于使用。服务端/客户端一行命令即可获取文本embedding;
*
更高性能,更高效率。通过Paddle AnalysisPredictor API优化计算图,提升速度减小显存占用
*
随"机"应变,灵活扩展。根据机器资源和实际需求可灵活增加服务端数量,支持多显卡多模型计算任务
*
优化并发方式,多核环境中使用多线程并发提高整体QPS
*
优化PaddleHub迁移学习组网Task功能,提升易用性
*
增加Hook机制,支持
[
修改Task内置方法
](
https://github.com/PaddlePaddle/PaddleHub/wiki/%E5%A6%82%E4%BD%95%E4%BF%AE%E6%94%B9Task%E5%86%85%E7%BD%AE%E6%96%B9%E6%B3%95%EF%BC%9F
)
*
增加colorlog,支持日志彩色显示
*
改用save_inference_model接口保存模型,方便模型部署
*
优化predict接口,增加return_result参数,方便用户直接获取预测结果
*
优化PaddleHub Dataset基类,加载
[
自定义数据
](
https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E9%80%82%E9%85%8D%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E5%AE%8C%E6%88%90FineTune
)
代码更少、更简单
# `v1.4.1`
*
修复利用Transformer类模型完成序列标注任务适配paddle1.6版本的问题
*
Windows下兼容性提升为python >= 3.6
# `v1.4.0`
*
新增预训练模型ERNIE tiny
*
新增数据集:INEWS、BQ、DRCD、CMRC2018、THUCNEWS,支持ChineseGLUE(CLUE)V0 所有任务
*
修复module与PaddlePaddle版本兼容性问题
*
优化Hub Serving启动过程和模型加载流程,提高服务响应速度
# `v1.3.0`
*
新增PaddleHub Serving服务部署
*
新增
[
hub serving
](
https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-Serving%E4%B8%80%E9%94%AE%E6%9C%8D%E5%8A%A1%E9%83%A8%E7%BD%B2
)
命令,支持一键启动Module预测服务部署
*
新增预训练模型:
*
roberta_wwm_ext_chinese_L-24_H-1024_A-16
*
roberta_wwm_ext_chinese_L-12_H-768_A-12
*
bert_wwm_ext_chinese_L-12_H-768_A-12
*
bert_wwm_chinese_L-12_H-768_A-12
*
AutoDL Finetuner优化使用体验
*
支持通过接口方式回传模型性能
*
可视化效果优化,支持多trail效果显示
# `v1.2.1`
*
新增
**超参优化Auto Fine-tune**
,实现给定超参搜索空间,PaddleHub自动给出较佳的超参组合
*
支持两种超参优化算法:HAZero和PSHE2
*
支持两种评估方式:FullTrail和PopulationBased
*
新增Fine-tune
**优化策略ULMFiT**
,包括以下三种设置
*
Slanted triangular learning rates:学习率先线性增加后缓慢降低
*
Discriminative fine-tuning:将计算图划分为n段,不同的段设置不同学习率
*
Gradual unfreezing:根据计算图的拓扑结构逐层unfreezing
*
新增支持用户自定义PaddleHub配置,包括
*
预训练模型管理服务器地址
*
日志记录级别
*
Fine-tune API升级,灵活性与易用性提升
*
新增
**阅读理解Fine-tune任务**
和
**回归Fine-tune任务**
*
新增多指标评测
*
优化predict接口
*
可视化工具支持使用tensorboard
# `v1.1.2`
*
PaddleHub支持修改预训练模型存放路径${HUB_HOME}
# `v1.1.1`
*
PaddleHub支持离线运行
*
修复python2安装PaddleHub失败问题
# `v1.1.0`
*
PaddleHub
**新增预训练模型ERNIE 2.0**
*
升级Reader, 支持自动传送数据给Ernie 1.0/2.0
*
新增数据集GLUE(MRPC、QQP、SST-2、CoLA、QNLI、RTE、MNLI)
# `v1.0.1`
*
安装模型时自动选择与paddlepaddle版本适配的模型
# `v1.0.0`
*
全新发布PaddleHub官网,易用性全面提升
*
新增网站 https://www.paddlepaddle.org.cn/hub 包含PaddlePaddle生态的预训练模型使用介绍
*
迁移学习Demo接入AI Studio与AI Book,无需安装即可快速体验
*
新增29个预训练模型,覆盖文本、图像、视频三大领域;目前官方提供40个预训练模型
*
CV预训练模型:
*
新增图像分类预训练模型11个:SE_ResNeXt, GoogleNet, ShuffleNet等
*
新增目标检测模型Faster-RCNN和YOLOv3
*
新增图像生成模型CycleGAN
*
新增人脸检测模型Pyramidbox
*
新增视频分类模型4个: TSN, TSM, StNet, Non-Local
*
NLP预训练模型
*
新增语义模型ELMo
*
新增情感分析模型5个: Senta-BOW, Senta-CNN, Senta-GRNN, , Senta-LSTM, EmoTect
*
新增中文语义相似度分析模型SimNet
*
升级LAC词法分析模型,新增词典干预功能,支持用户自定义分词
*
Fine-tune API升级,灵活性与性能全面提升
*
支持多卡并行、PyReader多线程IO,Fine-tune速度提升60%
*
简化finetune、evaluate、predict等使用逻辑,提升易用性
*
增加事件回调功能,方便用户快速实现自定义迁移学习任务
*
新增多标签分类Fine-tune任务
# `v0.5.0`
正式发布PaddleHub预训练模型管理工具,旨在帮助用户更高效的管理模型并开展迁移学习的工作。
**预训练模型管理**
: 通过hub命令行可完成PaddlePaddle生态的预训练模型下载、搜索、版本管理等功能。
**命令行一键使用**
: 无需代码,通过命令行即可直接使用预训练模型进行预测,快速调研训练模型效果。目前版本支持以下模型:词法分析LAC;情感分析Senta;目标检测SSD;图像分类ResNet, MobileNet, NASNet等。
**迁移学习**
: 提供了基于预训练模型的Fine-tune API,用户通过少量代码即可完成迁移学习,包括BERT/ERNIE文本分类、序列标注、图像分类迁移等。
docs/index.rst
浏览文件 @
d728f771
...
...
@@ -10,7 +10,6 @@ PaddleHub 文档
概述<overview>
安装<install>
快速体验<quick_experience/quick_index>
迁移学习<tutorial/tutorial_index>
部署预训练模型<tutorial/Serving_index>
API<reference/ref_index>
命令行参考<tutorial/cmdintro>
...
...
docs/tutorial/contri_pretrained_model.md
已删除
100644 → 0
浏览文件 @
ca8541bd
# 如何编写一个PaddleHub Module
## 模型基本信息
我们准备编写一个PaddleHub Module,Module的基本信息如下:
```
yaml
name="openpose_body_estimation",
type="CV/image_editing",
author="paddlepaddle",
author_email="",
summary="Openpose_body_estimation is a body pose estimation model based on Realtime Multi-Person 2D Pose \
Estimation using Part Affinity Fields.",
version="1.0.0"
```
Module存在一个接口predict,用于接收传入图片,并得到最终输出的结果,支持python接口调用和命令行调用。
```
python
import
paddlehub
as
hub
model
=
hub
.
Module
(
name
=
"openpose_body_estimation"
)
result
=
model
.
predict
(
"demo.jpg"
)
```
```
cmd
hub run openpose_body_estimation --input_path demo.jpg
```
## Module创建
### step 1. 创建必要的目录与文件
创建一个openpose_body_estimation的目录,并在openpose_body_estimation目录下分别创建module.py, processor.py。其中
|文件名|用途|
|-|-|
|module.py|主模块,提供Module的实现代码|
|processor.py|辅助模块,提供词表加载的方法|
```
cmd
➜ tree openpose_body_estimation
openpose_body_estimation/
├── module.py
└── processor.py
```
### step 2. 实现辅助模块processor
在processor.py中实现一些在module.py里面需要调用到的类和函数。例如在processor.py 中实现ResizeScaling类:
```
python
class
ResizeScaling
:
"""Resize images by scaling method.
Args:
target(int): Target image size.
interpolation(Callable): Interpolation method.
"""
def
__init__
(
self
,
target
:
int
=
368
,
interpolation
:
Callable
=
cv2
.
INTER_CUBIC
):
self
.
target
=
target
self
.
interpolation
=
interpolation
def
__call__
(
self
,
img
,
scale_search
):
scale
=
scale_search
*
self
.
target
/
img
.
shape
[
0
]
resize_img
=
cv2
.
resize
(
img
,
(
0
,
0
),
fx
=
scale
,
fy
=
scale
,
interpolation
=
self
.
interpolation
)
return
resize_img
```
### step 3. 编写Module处理代码
module.py文件为Module的入口代码所在,我们需要在其中实现预测逻辑。
#### step 3_1. 引入必要的头文件
```
python
import
os
import
time
import
copy
import
base64
import
argparse
from
typing
import
Union
from
collections
import
OrderedDict
import
cv2
import
paddle
import
paddle.nn
as
nn
import
numpy
as
np
from
paddlehub.module.module
import
moduleinfo
,
runnable
,
serving
import
paddlehub.vision.transforms
as
T
import
openpose_body_estimation.processor
as
P
```
**NOTE:**
`paddlehub.vision.transforms`
有常见的图像处理方法,可以方便调用。
#### step 3_2. 定义BodyPoseModel类
module.py中需要有一个继承了nn.Layer,该类负责实现预测逻辑,并使用moduleinfo填写基本信息。当使用hub.Module(name="openpose_body_estimation")加载Module时,PaddleHub会自动创建openpose_body_estimation的对象并返回。
```
python
@
moduleinfo
(
name
=
"openpose_body_estimation"
,
type
=
"CV/image_editing"
,
author
=
"paddlepaddle"
,
author_email
=
""
,
summary
=
"Openpose_body_estimation is a body pose estimation model based on Realtime Multi-Person 2D Pose
\
Estimation using Part Affinity Fields."
,
version
=
"1.0.0"
)
class
BodyPoseModel
(
nn
.
Layer
):
...
```
#### step 3_3. 执行必要的初始化及模型搭建
模型的初始化主要完成几个功能:待使用的类的声明,模型使用的类的声明及参数加载。
```
python
def
__init__
(
self
,
load_checkpoint
:
str
=
None
):
super
(
BodyPoseModel
,
self
).
__init__
()
#将会使用到的类的声明
self
.
resize_func
=
P
.
ResizeScaling
()
self
.
norm_func
=
T
.
Normalize
(
std
=
[
1
,
1
,
1
])
#模型声明
self
.
input_nc
=
4
self
.
output_nc
=
2
model1
=
(
Conv2D
(
self
.
input_nc
,
64
,
3
,
1
,
1
),
nn
.
ReLU
(),
Conv2D
(
64
,
64
,
3
,
1
,
1
),
nn
.
ReLU
(),
nn
.
BatchNorm
(
64
),
)
self
.
model1
=
nn
.
Sequential
(
*
model1
)
#参数加载
if
load_checkpoint
is
not
None
:
self
.
model_dict
=
paddle
.
load
(
load_checkpoint
)
self
.
set_dict
(
self
.
model_dict
)
print
(
"load custom checkpoint success"
)
else
:
checkpoint
=
os
.
path
.
join
(
self
.
directory
,
'model.pdparams'
)
self
.
model_dict
=
paddle
.
load
(
checkpoint
)
self
.
set_dict
(
self
.
model_dict
)
print
(
"load pretrained checkpoint success"
)
```
模型的搭建主要在
`forward`
里面实现:
```
python
def
forward
(
self
,
input
:
paddle
.
Tensor
)
->
paddle
.
Tensor
:
result
=
self
.
model1
(
input
)
return
result
```
#### step 3_4. 完善预测逻辑
```
python
def
predict
(
self
,
img
:
Union
(
np
.
ndarray
,
str
),
visualization
:
bool
=
True
):
self
.
eval
()
self
.
visualization
=
visualization
if
isinstance
(
img
,
str
):
orgImg
=
cv2
.
imread
(
img
)
else
:
orgImg
=
img
data
=
self
.
resize_func
(
self
.
norm_func
(
orgImg
))
output
=
self
.
forward
(
paddle
.
to_tensor
(
data
.
astype
(
'float32'
)))
output
=
paddle
.
clip
(
output
[
0
].
transpose
((
1
,
2
,
0
)),
0
,
255
).
numpy
()
output
=
output
.
astype
(
np
.
uint8
)
if
self
.
visualization
:
style_name
=
"body_"
+
str
(
time
.
time
())
+
".png"
if
not
os
.
path
.
exists
(
save_path
):
os
.
mkdir
(
save_path
)
path
=
os
.
path
.
join
(
save_path
,
style_name
)
cv2
.
imwrite
(
path
,
output
)
return
output
```
#### step 3_5. 支持命令行调用
如果希望Module可以支持命令行调用,则需要提供一个经过runnable修饰的接口,接口负责解析传入数据并进行预测,将结果返回。
```
python
@
runnable
def
run_cmd
(
self
,
argvs
):
"""
Run as a command.
"""
self
.
parser
=
argparse
.
ArgumentParser
(
description
=
"Run the {} module."
.
format
(
self
.
name
),
prog
=
'hub run {}'
.
format
(
self
.
name
),
usage
=
'%(prog)s'
,
add_help
=
True
)
self
.
arg_input_group
=
self
.
parser
.
add_argument_group
(
title
=
"Input options"
,
description
=
"Input data. Required"
)
self
.
arg_config_group
=
self
.
parser
.
add_argument_group
(
title
=
"Config options"
,
description
=
"Run configuration for controlling module behavior, not required."
)
self
.
add_module_config_arg
()
self
.
add_module_input_arg
()
args
=
self
.
parser
.
parse_args
(
argvs
)
results
=
self
.
predict
(
img
=
args
.
input_path
,
save_path
=
args
.
output_dir
,
visualization
=
args
.
visualization
)
return
results
def
add_module_config_arg
(
self
):
"""
Add the command config options.
"""
self
.
arg_config_group
.
add_argument
(
'--output_dir'
,
type
=
str
,
default
=
'openpose_body'
,
help
=
"The directory to save output images."
)
self
.
arg_config_group
.
add_argument
(
'--save_dir'
,
type
=
str
,
default
=
'openpose_model'
,
help
=
"The directory to save model."
)
self
.
arg_config_group
.
add_argument
(
'--visualization'
,
type
=
bool
,
default
=
True
,
help
=
"whether to save output as images."
)
def
add_module_input_arg
(
self
):
"""
Add the command input options.
"""
self
.
arg_input_group
.
add_argument
(
'--input_path'
,
type
=
str
,
help
=
"path to image."
)
```
#### step 3_6. 支持serving调用
如果希望Module可以支持PaddleHub Serving部署预测服务,则需要提供一个经过serving修饰的接口,接口负责解析传入数据并进行预测,将结果返回。
如果不需要提供PaddleHub Serving部署预测服务,则可以不需要加上serving修饰。
```
python
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
"""
Run as a service.
"""
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
results
=
self
.
predict
(
img
=
images_decode
[
0
],
**
kwargs
)
final
=
{}
final
[
'data'
]
=
P
.
cv2_to_base64
(
results
)
return
final
```
## 测试步骤
完成Module编写后,我们可以通过以下方式测试该Module
### 调用方法1
将Module安装到本机中,再通过Hub.Module(name=...)加载
```
shell
hub
install
openpose_body_estimation
```
```
python
import
paddlehub
as
hub
if
__name__
==
"__main__"
:
model
=
hub
.
Module
(
name
=
'openpose_hands_estimation'
)
result
=
model
.
predict
(
"demo.jpg"
)
```
### 调用方法2
将Module安装到本机中,再通过hub run运行
```
shell
hub
install
openpose_body_estimation
hub run openpose_body_estimation
--input_path
demo.jpg
```
### 测试serving方法
运行启动命令:
```
shell
$
hub serving start
-m
openpose_body_estimation
```
发送预测请求,获取预测结果.
```
python
import
requests
import
json
import
cv2
import
base64
import
numpy
as
np
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
def
base64_to_cv2
(
b64str
):
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
fromstring
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
# 发送HTTP请求
org_im
=
cv2
.
imread
(
'/PATH/TO/IMAGE'
)
data
=
{
'images'
:[
cv2_to_base64
(
org_im
)]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/openpose_body_estimation"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
canvas
=
base64_to_cv2
(
r
.
json
()[
"results"
][
'data'
])
cv2
.
imwrite
(
'keypoint_body.png'
,
canvas
)
```
docs/tutorial/how_to_finetune.md
已删除
100644 → 0
浏览文件 @
ca8541bd
此差异已折叠。
点击以展开。
docs/tutorial/tutorial_index.rst
浏览文件 @
d728f771
迁移学习
==================
本文将介绍介绍了如何自定义数据、
如何完成Finetune以及如何使用超参优化AutoDL Finetuner
。
本文将介绍介绍了如何自定义数据、
以及基于PaddleHub Module的一些应用场景
。
详细信息,参考以下教程:
...
...
@@ -10,7 +10,5 @@
:maxdepth: 1
自定义数据<how_to_load_data>
ULMFit优化策略<strategy_exp>
如何迁移学习<how_to_finetune>
超参优化<autofinetune>
文本相似度计算<sentence_sim>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录