Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
s920243400
PaddleDetection
提交
80efb3d1
P
PaddleDetection
项目概览
s920243400
/
PaddleDetection
与 Fork 源项目一致
Fork自
PaddlePaddle / PaddleDetection
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleDetection
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
80efb3d1
编写于
2月 27, 2017
作者:
Y
Yu Yang
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'develop' of github.com:baidu/Paddle into feature/mnist_reader
上级
fefd0065
6bdd362c
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
286 addition
and
36 deletion
+286
-36
paddle/api/Evaluator.cpp
paddle/api/Evaluator.cpp
+15
-0
paddle/api/PaddleAPI.h
paddle/api/PaddleAPI.h
+4
-0
paddle/api/test/testTrain.py
paddle/api/test/testTrain.py
+6
-1
paddle/scripts/docker/Dockerfile
paddle/scripts/docker/Dockerfile
+6
-4
paddle/scripts/docker/Dockerfile.gpu
paddle/scripts/docker/Dockerfile.gpu
+6
-4
paddle/scripts/docker/build.sh
paddle/scripts/docker/build.sh
+28
-24
python/CMakeLists.txt
python/CMakeLists.txt
+1
-0
python/paddle/reader/__init__.py
python/paddle/reader/__init__.py
+2
-0
python/paddle/reader/creator.py
python/paddle/reader/creator.py
+53
-0
python/paddle/reader/tests/CMakeLists.txt
python/paddle/reader/tests/CMakeLists.txt
+5
-0
python/paddle/reader/tests/creator_test.py
python/paddle/reader/tests/creator_test.py
+38
-0
python/paddle/reader/tests/test_data_creator.txt
python/paddle/reader/tests/test_data_creator.txt
+3
-0
python/paddle/v2/optimizer.py
python/paddle/v2/optimizer.py
+52
-3
python/paddle/v2/tests/CMakeLists.txt
python/paddle/v2/tests/CMakeLists.txt
+4
-0
python/paddle/v2/tests/test_layer.py
python/paddle/v2/tests/test_layer.py
+63
-0
未找到文件。
paddle/api/Evaluator.cpp
浏览文件 @
80efb3d1
...
...
@@ -27,3 +27,18 @@ std::string Evaluator::toString() {
m
->
rawPtr
->
printStats
(
sout
);
return
sout
.
str
();
}
std
::
vector
<
std
::
string
>
Evaluator
::
getNames
()
const
{
std
::
vector
<
std
::
string
>
retv
;
m
->
rawPtr
->
getNames
(
&
retv
);
return
retv
;
}
double
Evaluator
::
getValue
(
const
std
::
string
name
)
const
{
paddle
::
Error
err
;
double
v
=
m
->
rawPtr
->
getValue
(
name
,
&
err
);
if
(
err
)
{
throw
std
::
runtime_error
(
err
.
msg
());
}
return
v
;
}
paddle/api/PaddleAPI.h
浏览文件 @
80efb3d1
...
...
@@ -900,6 +900,10 @@ public:
*/
std
::
string
toString
();
std
::
vector
<
std
::
string
>
getNames
()
const
;
double
getValue
(
const
std
::
string
name
)
const
;
private:
EvaluatorPrivate
*
m
;
...
...
paddle/api/test/testTrain.py
浏览文件 @
80efb3d1
...
...
@@ -89,9 +89,14 @@ def main():
except
Exception
as
e
:
print
e
ev
=
m
.
makeEvaluator
()
ev
.
start
()
m
.
forwardBackward
(
inArgs
,
outArgs
,
swig_paddle
.
PASS_TRAIN
,
update_callback
)
m
.
eval
(
ev
)
ev
.
finish
()
for
name
in
ev
.
getNames
():
print
name
,
ev
.
getValue
(
name
)
for
optimizer
in
optimizers
:
optimizer
.
finishBatch
()
...
...
paddle/scripts/docker/Dockerfile
浏览文件 @
80efb3d1
...
...
@@ -10,28 +10,30 @@ RUN apt-get update && \
apt-get
install
-y
wget unzip
tar
xz-utils bzip2
gzip
coreutils
&&
\
apt-get
install
-y
curl
sed grep
graphviz libjpeg-dev zlib1g-dev
&&
\
apt-get
install
-y
python-numpy python-matplotlib gcc g++ gfortran
&&
\
apt-get
install
-y
automake
clang-3.8 llvm-3.8 libclang-3.8-dev
&&
\
apt-get
install
-y
automake
&&
\
apt-get clean
-y
RUN
pip
install
--upgrade
pip
&&
\
pip
install
-U
protobuf
&&
\
pip
install
-U
"protobuf==3.1.0"
&&
\
pip
install
-U
wheel pillow BeautifulSoup
&&
\
pip
install
-U
docopt PyYAML sphinx
&&
\
pip
install
-U
sphinx_rtd_theme recommonmark jupyter
RUN
curl
-sSL
https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz |
tar
-xz
&&
\
cd
cmake-3.4.1
&&
./bootstrap
&&
make
-j
4
&&
make
install
&&
\
cd
cmake-3.4.1
&&
./bootstrap
&&
make
-j
`
nproc
`
&&
make
install
&&
\
cd
..
&&
rm
-rf
cmake-3.4.1
ARG
BUILD_WOBOQ
ARG
BUILD_AND_INSTALL
ARG
WITH_AVX
ARG
WITH_DOC
ARG
WITH_STYLE_CHECK
ENV
BUILD_WOBOQ=${BUILD_WOBOQ:-OFF}
ENV
BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF}
ENV
WITH_GPU=OFF
ENV
WITH_AVX=${WITH_AVX:-ON}
ENV
WITH_DOC=${WITH_DOC:-O
N
}
ENV
WITH_DOC=${WITH_DOC:-O
FF
}
ENV
WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF}
RUN
mkdir
/paddle
...
...
paddle/scripts/docker/Dockerfile.gpu
浏览文件 @
80efb3d1
...
...
@@ -10,28 +10,30 @@ RUN apt-get update && \
apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \
apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \
apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \
apt-get install -y automake
clang-3.8 llvm-3.8 libclang-3.8-dev
&& \
apt-get install -y automake && \
apt-get clean -y
RUN pip install --upgrade pip && \
pip install -U
protobuf
&& \
pip install -U
"protobuf==3.1.0"
&& \
pip install -U wheel pillow BeautifulSoup && \
pip install -U docopt PyYAML sphinx && \
pip install -U sphinx_rtd_theme recommonmark jupyter
RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \
cd cmake-3.4.1 && ./bootstrap && make -j
4
&& make install && \
cd cmake-3.4.1 && ./bootstrap && make -j
`nproc`
&& make install && \
cd .. && rm -rf cmake-3.4.1
ARG BUILD_WOBOQ
ARG BUILD_AND_INSTALL
ARG WITH_AVX
ARG WITH_DOC
ARG WITH_STYLE_CHECK
ENV BUILD_WOBOQ=${BUILD_WOBOQ:-OFF}
ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF}
ENV WITH_GPU=ON
ENV WITH_AVX=${WITH_AVX:-ON}
ENV WITH_DOC=${WITH_DOC:-O
N
}
ENV WITH_DOC=${WITH_DOC:-O
FF
}
ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF}
RUN mkdir /paddle
...
...
paddle/scripts/docker/build.sh
浏览文件 @
80efb3d1
...
...
@@ -11,7 +11,7 @@ set -e
# If Dockerfile.* sets BUILD_AND_INSTALL to 'ON', it would have copied
# source tree to /paddle, and this scripts should build it into
# /paddle/build.
if
[[
${
BUILD_AND_INSTALL
:-
O
N
}
==
'ON'
]]
;
then
if
[[
${
BUILD_AND_INSTALL
:-
O
FF
}
==
'ON'
]]
;
then
if
[[
${
WITH_GPU
:-
OFF
}
==
'ON'
]]
;
then
ln
-s
/usr/lib/x86_64-linux-gnu/libcudnn.so /usr/lib/libcudnn.so
fi
...
...
@@ -19,7 +19,7 @@ if [[ ${BUILD_AND_INSTALL:-ON} == 'ON' ]]; then
mkdir
-p
/paddle/build
# -p means no error if exists
cd
/paddle/build
cmake ..
\
-DWITH_DOC
=
ON
\
-DWITH_DOC
=
${
WITH_DOC
:-
OFF
}
\
-DWITH_GPU
=
${
WITH_GPU
:-
OFF
}
\
-DWITH_AVX
=
${
WITH_AVX
:-
OFF
}
\
-DWITH_SWIG_PY
=
ON
\
...
...
@@ -29,28 +29,32 @@ if [[ ${BUILD_AND_INSTALL:-ON} == 'ON' ]]; then
make
-j
`
nproc
`
make
install
# Install woboq_codebrowser.
git clone https://github.com/woboq/woboq_codebrowser /woboq
cd
/woboq
cmake
-DLLVM_CONFIG_EXECUTABLE
=
/usr/bin/llvm-config-3.8
\
-DCMAKE_BUILD_TYPE
=
Release
\
.
make
export
WOBOQ_OUT
=
/usr/share/nginx/html/paddle
export
BUILD_DIR
=
/paddle/build
mkdir
-p
$WOBOQ_OUT
cp
-rv
/woboq/data
$WOBOQ_OUT
/../data
/woboq/generator/codebrowser_generator
\
-b
/paddle/build
\
-a
\
-o
$WOBOQ_OUT
\
-p
paddle:/paddle
/woboq/indexgenerator/codebrowser_indexgenerator
$WOBOQ_OUT
cd
/woboq
make clean
pip
install
/usr/local/opt/paddle/share/wheels/
*
.whl
if
[[
${
BUILD_WOBOQ
:-
OFF
}
==
'ON'
]]
;
then
apt-get
install
-y
clang-3.8 llvm-3.8 libclang-3.8-dev
# Install woboq_codebrowser.
git clone https://github.com/woboq/woboq_codebrowser /woboq
cd
/woboq
cmake
-DLLVM_CONFIG_EXECUTABLE
=
/usr/bin/llvm-config-3.8
\
-DCMAKE_BUILD_TYPE
=
Release
\
.
make
export
WOBOQ_OUT
=
/usr/share/nginx/html/paddle
export
BUILD_DIR
=
/paddle/build
mkdir
-p
$WOBOQ_OUT
cp
-rv
/woboq/data
$WOBOQ_OUT
/../data
/woboq/generator/codebrowser_generator
\
-b
/paddle/build
\
-a
\
-o
$WOBOQ_OUT
\
-p
paddle:/paddle
/woboq/indexgenerator/codebrowser_indexgenerator
$WOBOQ_OUT
cd
/woboq
make clean
fi
pip
install
/usr/local/opt/paddle/share/wheels/py_paddle
*
linux
*
.whl
pip
install
/usr/local/opt/paddle/share/wheels/paddle
*
.whl
paddle version
fi
...
...
python/CMakeLists.txt
浏览文件 @
80efb3d1
...
...
@@ -25,6 +25,7 @@ add_custom_target(paddle_python ALL DEPENDS
add_subdirectory
(
paddle/trainer_config_helpers/tests
)
add_subdirectory
(
paddle/reader/tests
)
add_subdirectory
(
paddle/v2/tests
)
install
(
DIRECTORY
${
CMAKE_CURRENT_BINARY_DIR
}
/dist/
DESTINATION opt/paddle/share/wheels
...
...
python/paddle/reader/__init__.py
浏览文件 @
80efb3d1
...
...
@@ -21,3 +21,5 @@
#
# r = paddle.reader.buffered(paddle.reader.creator.text("hello.txt"))
from
decorator
import
*
import
creator
python/paddle/reader/creator.py
0 → 100644
浏览文件 @
80efb3d1
# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__all__
=
[
'np_array'
,
'text_file'
]
def
np_array
(
x
):
"""
Creates a reader that yields elements of x, if it is a
numpy vector. Or rows of x, if it is a numpy matrix.
Or any sub-hyperplane indexed by the highest dimension.
:param x: the numpy array to create reader from.
:returns: data reader created from x.
"""
def
reader
():
if
x
.
ndim
<
1
:
yield
x
for
e
in
x
:
yield
e
return
reader
def
text_file
(
path
):
"""
Creates a data reader that outputs text line by line from given text file.
Trailing new line ('
\n
') of each line will be removed.
:path: path of the text file.
:returns: data reader of text file
"""
def
reader
():
f
=
open
(
path
,
"r"
)
for
l
in
f
:
yield
l
.
rstrip
(
'
\n
'
)
f
.
close
()
return
reader
python/paddle/reader/tests/CMakeLists.txt
浏览文件 @
80efb3d1
...
...
@@ -2,3 +2,8 @@ add_test(NAME reader_decorator_test
COMMAND
${
PROJ_ROOT
}
/paddle/.set_python_path.sh -d
${
PROJ_ROOT
}
/python/
${
PYTHON_EXECUTABLE
}
${
PROJ_ROOT
}
/python/paddle/reader/tests/decorator_test.py
WORKING_DIRECTORY
${
PROJ_ROOT
}
/python/paddle
)
add_test
(
NAME reader_creator_test
COMMAND
${
PROJ_ROOT
}
/paddle/.set_python_path.sh -d
${
PROJ_ROOT
}
/python/
${
PYTHON_EXECUTABLE
}
${
PROJ_ROOT
}
/python/paddle/reader/tests/creator_test.py
WORKING_DIRECTORY
${
PROJ_ROOT
}
/python/paddle
)
python/paddle/reader/tests/creator_test.py
0 → 100644
浏览文件 @
80efb3d1
# Copyright PaddlePaddle contributors. All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import
unittest
import
paddle.reader.creator
import
numpy
as
np
import
os
class
TestNumpyArray
(
unittest
.
TestCase
):
def
test_numpy_array
(
self
):
l
=
[[
1
,
2
,
3
],
[
4
,
5
,
6
]]
x
=
np
.
array
(
l
,
np
.
int32
)
reader
=
paddle
.
reader
.
creator
.
np_array
(
x
)
for
idx
,
e
in
enumerate
(
reader
()):
self
.
assertItemsEqual
(
e
,
l
[
idx
])
class
TestTextFile
(
unittest
.
TestCase
):
def
test_text_file
(
self
):
path
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"test_data_creator.txt"
)
reader
=
paddle
.
reader
.
creator
.
text_file
(
path
)
for
idx
,
e
in
enumerate
(
reader
()):
self
.
assertEqual
(
e
,
str
(
idx
*
2
)
+
" "
+
str
(
idx
*
2
+
1
))
if
__name__
==
'__main__'
:
unittest
.
main
()
python/paddle/reader/tests/test_data_creator.txt
0 → 100644
浏览文件 @
80efb3d1
0 1
2 3
4 5
python/paddle/v2/optimizer.py
浏览文件 @
80efb3d1
...
...
@@ -3,7 +3,10 @@ import paddle.trainer_config_helpers.optimizers as v1_optimizers
import
paddle.trainer_config_helpers.config_parser_utils
as
config_parser_utils
import
paddle.v2
__all__
=
[
'Adam'
,
'Adamax'
]
__all__
=
[
'Momentum'
,
'Adam'
,
'Adamax'
,
'AdaGrad'
,
'DecayedAdaGrad'
,
'AdaDelta'
,
'RMSProp'
,
'ModelAverage'
,
'L2Regularization'
]
class
Optimizer
(
object
):
...
...
@@ -38,6 +41,14 @@ class Optimizer(object):
pass_num
)
class
Momentum
(
Optimizer
):
def
__init__
(
self
,
momentum
=
None
,
sparse
=
False
,
**
kwargs
):
learning_method
=
v1_optimizers
.
MomentumOptimizer
(
momentum
=
None
,
sparse
=
False
)
super
(
Momentum
,
self
).
__init__
(
learning_method
=
learning_method
,
**
kwargs
)
class
Adam
(
Optimizer
):
def
__init__
(
self
,
beta1
=
0.9
,
beta2
=
0.999
,
epsilon
=
1e-8
,
**
kwargs
):
learning_method
=
v1_optimizers
.
AdamOptimizer
(
...
...
@@ -52,7 +63,45 @@ class Adamax(Optimizer):
super
(
Adamax
,
self
).
__init__
(
learning_method
=
learning_method
,
**
kwargs
)
class
AdaGrad
(
Optimizer
):
def
__init__
(
self
,
**
kwargs
):
learning_method
=
v1_optimizers
.
AdaGradOptimizer
()
super
(
AdaGrad
,
self
).
__init__
(
learning_method
=
learning_method
,
**
kwargs
)
class
DecayedAdaGrad
(
Optimizer
):
def
__init__
(
self
,
rho
=
0.95
,
epsilon
=
1e-06
,
**
kwargs
):
learning_method
=
v1_optimizers
.
DecayedAdaGradOptimizer
(
rho
=
rho
,
epsilon
=
epsilon
)
super
(
DecayedAdaGrad
,
self
).
__init__
(
learning_method
=
learning_method
,
**
kwargs
)
class
AdaDelta
(
Optimizer
):
def
__init__
(
self
,
rho
=
0.95
,
epsilon
=
1e-06
,
**
kwargs
):
learning_method
=
v1_optimizers
.
AdaDeltaOptimizer
(
rho
=
rho
,
epsilon
=
epsilon
)
super
(
AdaDelta
,
self
).
__init__
(
learning_method
=
learning_method
,
**
kwargs
)
class
RMSProp
(
Optimizer
):
def
__init__
(
self
,
rho
=
0.95
,
epsilon
=
1e-6
,
**
kwargs
):
learning_method
=
v1_optimizers
.
RMSPropOptimizer
(
rho
=
rho
,
epsilon
=
epsilon
)
super
(
RMSProp
,
self
).
__init__
(
learning_method
=
learning_method
,
**
kwargs
)
ModelAverage
=
v1_optimizers
.
ModelAverage
L2Regularization
=
v1_optimizers
.
L2Regularization
if
__name__
==
'__main__'
:
swig_api
.
initPaddle
(
'--use_gpu=false'
)
opt
=
paddle
.
v2
.
optimizer
.
Adam
()
print
opt
.
enable_types
()
for
opt
in
[
Momentum
(),
Adam
(),
Adamax
(),
AdaGrad
(),
DecayedAdaGrad
(),
AdaDelta
(),
RMSProp
(),
Adam
(
model_average
=
ModelAverage
(
average_window
=
0.5
),
regularization
=
L2Regularization
(
rate
=
0.5
),
gradient_clipping_threshold
=
25
)
]:
print
opt
,
opt
.
enable_types
()
python/paddle/v2/tests/CMakeLists.txt
0 → 100644
浏览文件 @
80efb3d1
add_test
(
NAME test_v2_layer
COMMAND
${
PROJ_ROOT
}
/paddle/.set_python_path.sh -d
${
PROJ_ROOT
}
/python/
${
PYTHON_EXECUTABLE
}
${
PROJ_ROOT
}
/python/paddle/v2/tests/test_layer.py
WORKING_DIRECTORY
${
PROJ_ROOT
}
/python/paddle
)
python/paddle/v2/tests/test_layer.py
0 → 100644
浏览文件 @
80efb3d1
# Copyright PaddlePaddle contributors. All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import
difflib
import
unittest
import
paddle.trainer_config_helpers
as
conf_helps
import
paddle.v2.activation
as
activation
import
paddle.v2.attr
as
attr
import
paddle.v2.data_type
as
data_type
import
paddle.v2.layer
as
layer
from
paddle.trainer_config_helpers.config_parser_utils
import
\
parse_network_config
as
parse_network
pixel
=
layer
.
data
(
name
=
'pixel'
,
type
=
data_type
.
dense_vector
(
784
))
label
=
layer
.
data
(
name
=
'label'
,
type
=
data_type
.
integer_value
(
10
))
weight
=
layer
.
data
(
name
=
'weight'
,
type
=
data_type
.
dense_vector
(
10
))
score
=
layer
.
data
(
name
=
'score'
,
type
=
data_type
.
dense_vector
(
1
))
hidden
=
layer
.
fc
(
input
=
pixel
,
size
=
100
,
act
=
activation
.
Sigmoid
(),
param_attr
=
attr
.
Param
(
name
=
'hidden'
))
inference
=
layer
.
fc
(
input
=
hidden
,
size
=
10
,
act
=
activation
.
Softmax
())
class
CostLayerTest
(
unittest
.
TestCase
):
def
test_cost_layer
(
self
):
cost1
=
layer
.
classification_cost
(
input
=
inference
,
label
=
label
)
cost2
=
layer
.
classification_cost
(
input
=
inference
,
label
=
label
,
weight
=
weight
)
cost3
=
layer
.
cross_entropy_cost
(
input
=
inference
,
label
=
label
)
cost4
=
layer
.
cross_entropy_with_selfnorm_cost
(
input
=
inference
,
label
=
label
)
cost5
=
layer
.
regression_cost
(
input
=
inference
,
label
=
label
)
cost6
=
layer
.
regression_cost
(
input
=
inference
,
label
=
label
,
weight
=
weight
)
cost7
=
layer
.
multi_binary_label_cross_entropy_cost
(
input
=
inference
,
label
=
label
)
cost8
=
layer
.
rank_cost
(
left
=
score
,
right
=
score
,
label
=
score
)
cost9
=
layer
.
lambda_cost
(
input
=
inference
,
score
=
score
)
cost10
=
layer
.
sum_cost
(
input
=
inference
)
cost11
=
layer
.
huber_cost
(
input
=
score
,
label
=
label
)
print
dir
(
layer
)
layer
.
parse_network
(
cost1
,
cost2
)
print
dir
(
layer
)
#print layer.parse_network(cost3, cost4)
#print layer.parse_network(cost5, cost6)
#print layer.parse_network(cost7, cost8, cost9, cost10, cost11)
if
__name__
==
'__main__'
:
unittest
.
main
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录