未验证 提交 8c1aa4e6 编写于 作者: saxon_zh's avatar saxon_zh 提交者: GitHub

[Bug Fix]change paddle.disable_static() position (#902)

* upgrade code to 2.0-beta

* add high level api doc

* add define callback/metric/loss chapter

* add define callback/metric/loss chapter

* rerun code with 2.0-beta whl

* fix bug: modify PetModel to PetNet

* Fix BUG: change paddle.disable_static() position
上级 241823fc
...@@ -6,3 +6,4 @@ pandoc.template ...@@ -6,3 +6,4 @@ pandoc.template
py_env* py_env*
*.ipynb *.ipynb
build build
.vscode
...@@ -31,24 +31,22 @@ ...@@ -31,24 +31,22 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 8,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "name": "stdout",
"text/plain": [ "output_type": "stream",
"'2.0.0-beta0'" "text": [
"2.0.0-beta0\n"
] ]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
} }
], ],
"source": [ "source": [
"import paddle\n", "import paddle\n",
"\n", "\n",
"paddle.__version__" "print(paddle.__version__)\n",
"paddle.disable_static()"
] ]
}, },
{ {
...@@ -71,7 +69,7 @@ ...@@ -71,7 +69,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 9,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -90,7 +88,7 @@ ...@@ -90,7 +88,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 35, "execution_count": 10,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -113,7 +111,7 @@ ...@@ -113,7 +111,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 36, "execution_count": 11,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
...@@ -123,15 +121,15 @@ ...@@ -123,15 +121,15 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Epoch 1/5\n", "Epoch 1/5\n",
"step 1875/1875 [==============================] - loss: 0.2571 - acc: 0.9037 - 10ms/step \n", "step 1875/1875 [==============================] - loss: 0.2250 - acc: 0.9025 - 9ms/step \n",
"Epoch 2/5\n", "Epoch 2/5\n",
"step 1875/1875 [==============================] - loss: 0.1880 - acc: 0.9458 - 14ms/step \n", "step 1875/1875 [==============================] - loss: 0.0969 - acc: 0.9462 - 13ms/step \n",
"Epoch 3/5\n", "Epoch 3/5\n",
"step 1875/1875 [==============================] - loss: 0.0279 - acc: 0.9549 - 11ms/step \n", "step 1875/1875 [==============================] - loss: 0.1035 - acc: 0.9550 - 12ms/step \n",
"Epoch 4/5\n", "Epoch 4/5\n",
"step 1875/1875 [==============================] - loss: 0.0505 - acc: 0.9608 - 13ms/step \n", "step 1875/1875 [==============================] - loss: 0.0316 - acc: 0.9603 - 12ms/step \n",
"Epoch 5/5\n", "Epoch 5/5\n",
"step 1875/1875 [==============================] - loss: 0.2253 - acc: 0.9646 - 12ms/step \n" "step 1875/1875 [==============================] - loss: 0.1771 - acc: 0.9637 - 12ms/step \n"
] ]
} }
], ],
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 2,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
"'2.0.0-beta0'" "'2.0.0-beta0'"
] ]
}, },
"execution_count": 1, "execution_count": 2,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
...@@ -55,6 +55,9 @@ ...@@ -55,6 +55,9 @@
"import paddle.vision as vision\n", "import paddle.vision as vision\n",
"import paddle.text as text\n", "import paddle.text as text\n",
"\n", "\n",
"# 启动动态图训练模式\n",
"paddle.disable_static()\n",
"\n",
"paddle.__version__" "paddle.__version__"
] ]
}, },
...@@ -90,7 +93,7 @@ ...@@ -90,7 +93,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 3,
"metadata": { "metadata": {
"tags": [] "tags": []
}, },
...@@ -118,7 +121,7 @@ ...@@ -118,7 +121,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 24, "execution_count": 18,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -140,7 +143,7 @@ ...@@ -140,7 +143,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 5,
"metadata": { "metadata": {
"tags": [] "tags": []
}, },
...@@ -207,8 +210,8 @@ ...@@ -207,8 +210,8 @@
" return len(self.data)\n", " return len(self.data)\n",
"\n", "\n",
"# 测试定义的数据集\n", "# 测试定义的数据集\n",
"train_dataset = MyDataset(mode='train')\n", "train_dataset_2 = MyDataset(mode='train')\n",
"val_dataset = MyDataset(mode='test')\n", "val_dataset_2 = MyDataset(mode='test')\n",
"\n", "\n",
"print('=============train dataset=============')\n", "print('=============train dataset=============')\n",
"for data, label in train_dataset:\n", "for data, label in train_dataset:\n",
...@@ -232,7 +235,7 @@ ...@@ -232,7 +235,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 6,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -243,7 +246,7 @@ ...@@ -243,7 +246,7 @@
"transform = Compose([ColorJitter(), Resize(size=100)])\n", "transform = Compose([ColorJitter(), Resize(size=100)])\n",
"\n", "\n",
"# 通过transform参数传递定义好的数据增项方法即可完成对自带数据集的应用\n", "# 通过transform参数传递定义好的数据增项方法即可完成对自带数据集的应用\n",
"train_dataset = vision.datasets.MNIST(mode='train', transform=transform)" "train_dataset_3 = vision.datasets.MNIST(mode='train', transform=transform)"
] ]
}, },
{ {
...@@ -257,7 +260,7 @@ ...@@ -257,7 +260,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 7,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -316,7 +319,7 @@ ...@@ -316,7 +319,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 28, "execution_count": 12,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -340,7 +343,7 @@ ...@@ -340,7 +343,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 31,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -364,7 +367,7 @@ ...@@ -364,7 +367,7 @@
"\n", "\n",
" return y\n", " return y\n",
"\n", "\n",
"mnist = Mnist()" "mnist_2 = Mnist()"
] ]
}, },
{ {
...@@ -380,14 +383,12 @@ ...@@ -380,14 +383,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 32,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"# 场景1:动态图模式\n", "# 场景1:动态图模式\n",
"\n", "\n",
"# 启动动态图训练模式\n",
"paddle.disable_static()\n",
"# 使用GPU训练\n", "# 使用GPU训练\n",
"paddle.set_device('gpu')\n", "paddle.set_device('gpu')\n",
"# 模型封装\n", "# 模型封装\n",
...@@ -412,9 +413,45 @@ ...@@ -412,9 +413,45 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 33,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--------------------------------------------------------------------------------\n",
" Layer (type) Input Shape Output Shape Param #\n",
"================================================================================\n",
" Flatten-57509 [-1, 1, 28, 28] [-1, 784] 0\n",
" Linear-7 [-1, 784] [-1, 512] 401,920\n",
" ReLU-4 [-1, 512] [-1, 512] 0\n",
" Dropout-4 [-1, 512] [-1, 512] 0\n",
" Linear-8 [-1, 512] [-1, 10] 5,130\n",
"================================================================================\n",
"Total params: 407,050\n",
"Trainable params: 407,050\n",
"Non-trainable params: 0\n",
"--------------------------------------------------------------------------------\n",
"Input size (MB): 0.00\n",
"Forward/backward pass size (MB): 0.02\n",
"Params size (MB): 1.55\n",
"Estimated Total Size (MB): 1.57\n",
"--------------------------------------------------------------------------------\n",
"\n"
]
},
{
"data": {
"text/plain": [
"{'total_params': 407050, 'trainable_params': 407050}"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [ "source": [
"model.summary((1, 28, 28))" "model.summary((1, 28, 28))"
] ]
...@@ -428,9 +465,45 @@ ...@@ -428,9 +465,45 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 34,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--------------------------------------------------------------------------------\n",
" Layer (type) Input Shape Output Shape Param #\n",
"================================================================================\n",
" Flatten-57508 [-1, 1, 28, 28] [-1, 784] 0\n",
" Linear-5 [-1, 784] [-1, 512] 401,920\n",
" ReLU-3 [-1, 512] [-1, 512] 0\n",
" Dropout-3 [-1, 512] [-1, 512] 0\n",
" Linear-6 [-1, 512] [-1, 10] 5,130\n",
"================================================================================\n",
"Total params: 407,050\n",
"Trainable params: 407,050\n",
"Non-trainable params: 0\n",
"--------------------------------------------------------------------------------\n",
"Input size (MB): 0.00\n",
"Forward/backward pass size (MB): 0.02\n",
"Params size (MB): 1.55\n",
"Estimated Total Size (MB): 1.57\n",
"--------------------------------------------------------------------------------\n",
"\n"
]
},
{
"data": {
"text/plain": [
"{'total_params': 407050, 'trainable_params': 407050}"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [ "source": [
"paddle.summary(mnist, (1, 28, 28))" "paddle.summary(mnist, (1, 28, 28))"
] ]
...@@ -456,7 +529,7 @@ ...@@ -456,7 +529,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 35,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -475,9 +548,36 @@ ...@@ -475,9 +548,36 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 36,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/10\n",
"step 1875/1875 [==============================] - loss: 0.1600 - acc: 0.9022 - 10ms/step \n",
"Epoch 2/10\n",
"step 1875/1875 [==============================] - loss: 0.0455 - acc: 0.9461 - 12ms/step \n",
"Epoch 3/10\n",
"step 1875/1875 [==============================] - loss: 0.1429 - acc: 0.9544 - 19ms/step \n",
"Epoch 4/10\n",
"step 1875/1875 [==============================] - loss: 0.0197 - acc: 0.9601 - 22ms/step \n",
"Epoch 5/10\n",
"step 1875/1875 [==============================] - loss: 0.1762 - acc: 0.9644 - 25ms/step \n",
"Epoch 6/10\n",
"step 1875/1875 [==============================] - loss: 0.1304 - acc: 0.9667 - 22ms/step \n",
"Epoch 7/10\n",
"step 1875/1875 [==============================] - loss: 0.0133 - acc: 0.9682 - 22ms/step \n",
"Epoch 8/10\n",
"step 1875/1875 [==============================] - loss: 0.0097 - acc: 0.9705 - 19ms/step \n",
"Epoch 9/10\n",
"step 1875/1875 [==============================] - loss: 3.1264e-04 - acc: 0.9716 - 23ms/step \n",
"Epoch 10/10\n",
"step 1875/1875 [==============================] - loss: 0.0767 - acc: 0.9729 - 13ms/step \n"
]
}
],
"source": [ "source": [
"# 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式\n", "# 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式\n",
"model.fit(train_dataset, \n", "model.fit(train_dataset, \n",
...@@ -497,14 +597,39 @@ ...@@ -497,14 +597,39 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 30, "execution_count": 20,
"metadata": { "metadata": {
"tags": [] "tags": []
}, },
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/10\n",
"step 1875/1875 [==============================] - loss: 0.0490 - acc: 0.9741 - 6ms/step \n",
"Epoch 2/10\n",
"step 1875/1875 [==============================] - loss: 0.1384 - acc: 0.9760 - 7ms/step \n",
"Epoch 3/10\n",
"step 1875/1875 [==============================] - loss: 0.0929 - acc: 0.9767 - 7ms/step \n",
"Epoch 4/10\n",
"step 1875/1875 [==============================] - loss: 0.0190 - acc: 0.9772 - 6ms/step \n",
"Epoch 5/10\n",
"step 1875/1875 [==============================] - loss: 0.0862 - acc: 0.9774 - 7ms/step \n",
"Epoch 6/10\n",
"step 1875/1875 [==============================] - loss: 0.0748 - acc: 0.9785 - 8ms/step \n",
"Epoch 7/10\n",
"step 1875/1875 [==============================] - loss: 0.0039 - acc: 0.9798 - 17ms/step \n",
"Epoch 8/10\n",
"step 1875/1875 [==============================] - loss: 0.0037 - acc: 0.9808 - 11ms/step \n",
"Epoch 9/10\n",
"step 1875/1875 [==============================] - loss: 0.0013 - acc: 0.9800 - 8ms/step \n",
"Epoch 10/10\n",
"step 1875/1875 [==============================] - loss: 0.0376 - acc: 0.9810 - 8ms/step \n"
]
}
],
"source": [ "source": [
"# 启动动态图训练模式\n",
"paddle.disable_static()\n",
"\n", "\n",
"# 使用GPU训练\n", "# 使用GPU训练\n",
"paddle.set_device('gpu')\n", "paddle.set_device('gpu')\n",
...@@ -530,17 +655,13 @@ ...@@ -530,17 +655,13 @@
"source": [ "source": [
"### 5.2 单机多卡\n", "### 5.2 单机多卡\n",
"\n", "\n",
"对于高层API来实现单机多卡非常简单,整个训练代码和单机单卡没有差异。直接使用`paddle.distributed.launch`启动单机单卡的程序即可。" "对于高层API来实现单机多卡非常简单,整个训练代码和单机单卡没有差异。直接使用`paddle.distributed.launch`启动单机单卡的程序即可。\n",
] "\n",
}, "```bash\n",
{ "$ python -m paddle.distributed.launch train.py\n",
"cell_type": "code", "```\n",
"execution_count": null, "\n",
"metadata": {}, "train.py里面包含的就是单机单卡代码"
"outputs": [],
"source": [
"# train.py里面包含的就是单机单卡代码\n",
"python -m paddle.distributed.launch train.py"
] ]
}, },
{ {
...@@ -810,9 +931,19 @@ ...@@ -810,9 +931,19 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 21,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Eval begin...\n",
"step 10000/10000 [==============================] - loss: 0.0000e+00 - acc: 0.9801 - 2ms/step \n",
"Eval samples: 10000\n"
]
}
],
"source": [ "source": [
"result = model.evaluate(val_dataset, verbose=1)" "result = model.evaluate(val_dataset, verbose=1)"
] ]
...@@ -834,9 +965,19 @@ ...@@ -834,9 +965,19 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 22,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Predict begin...\n",
"step 10000/10000 [==============================] - 4ms/step \n",
"Predict samples: 10000\n"
]
}
],
"source": [ "source": [
"pred_result = model.predict(val_dataset)" "pred_result = model.predict(val_dataset)"
] ]
...@@ -866,17 +1007,40 @@ ...@@ -866,17 +1007,40 @@
"\n", "\n",
"### 8.1 模型存储\n", "### 8.1 模型存储\n",
"\n", "\n",
"模型训练和验证达到我们的预期后,可以使用`save`接口来将我们的模型保存下来,用于后续模型的Fine-tuning(接口参数training=True)或推理部署(接口参数training=False)。" "模型训练和验证达到我们的预期后,可以使用`save`接口来将我们的模型保存下来,用于后续模型的Fine-tuning(接口参数training=True)或推理部署(接口参数training=False)。\n",
"\n",
"需要注意的是,在动态图模式训练时保存推理模型的参数文件和模型文件,需要在forward成员函数上添加@paddle.jit.to_static装饰器,参考下面的例子:\n",
"\n",
"```python\n",
"class Mnist(paddle.nn.Layer):\n",
" def __init__(self):\n",
" super(Mnist, self).__init__()\n",
"\n",
" self.flatten = paddle.nn.Flatten()\n",
" self.linear_1 = paddle.nn.Linear(784, 512)\n",
" self.linear_2 = paddle.nn.Linear(512, 10)\n",
" self.relu = paddle.nn.ReLU()\n",
" self.dropout = paddle.nn.Dropout(0.2)\n",
"\n",
" @paddle.jit.to_static\n",
" def forward(self, inputs):\n",
" y = self.flatten(inputs)\n",
" y = self.linear_1(y)\n",
" y = self.relu(y)\n",
" y = self.dropout(y)\n",
" y = self.linear_2(y)\n",
"\n",
" return y\n",
"```"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 24,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"# 保存用于推理部署的模型(training=False)\n", "model.save('~/model/mnist')"
"model.save('~/model/mnist', training=False)"
] ]
}, },
{ {
......
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
"import paddle\n", "import paddle\n",
"from paddle.nn import functional as F\n", "from paddle.nn import functional as F\n",
"\n", "\n",
"device = paddle.set_device('gpu')\n",
"paddle.disable_static(device)\n",
"\n",
"paddle.__version__" "paddle.__version__"
] ]
}, },
...@@ -808,34 +811,6 @@ ...@@ -808,34 +811,6 @@
"## 5.模型训练" "## 5.模型训练"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "8Sskbyz58X4J"
},
"source": [
"### 5.1 配置信息\n",
"\n",
"定义训练BATCH_SIZE、训练轮次和计算设备等信息。"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "4fSkTiRB8OpP"
},
"outputs": [],
"source": [
"BATCH_SIZE = 32\n",
"EPOCHS = 15\n",
"device = paddle.set_device('gpu')\n",
"paddle.disable_static(device)"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {
...@@ -843,14 +818,14 @@ ...@@ -843,14 +818,14 @@
"id": "x_vaedRa8eoy" "id": "x_vaedRa8eoy"
}, },
"source": [ "source": [
"### 5.3 自定义Loss\n", "### 5.1 自定义Loss\n",
"\n", "\n",
"在这个任务中我们使用SoftmaxWithCrossEntropy损失函数来做计算,飞桨中有functional形式的API,这里我们做一个自定义操作,实现一个Class形式API放到模型训练中使用。没有直接使用CrossEntropyLoss的原因主要是对计算维度的自定义需求,本次需要进行softmax计算的维度是1,不是默认的最后一维,所以我们采用上面提到的损失函数,通过axis参数来指定softmax计算维度。" "在这个任务中我们使用SoftmaxWithCrossEntropy损失函数来做计算,飞桨中有functional形式的API,这里我们做一个自定义操作,实现一个Class形式API放到模型训练中使用。没有直接使用CrossEntropyLoss的原因主要是对计算维度的自定义需求,本次需要进行softmax计算的维度是1,不是默认的最后一维,所以我们采用上面提到的损失函数,通过axis参数来指定softmax计算维度。"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": 10,
"metadata": { "metadata": {
"colab": {}, "colab": {},
"colab_type": "code", "colab_type": "code",
...@@ -877,7 +852,7 @@ ...@@ -877,7 +852,7 @@
"id": "rj6MPPMkJIdZ" "id": "rj6MPPMkJIdZ"
}, },
"source": [ "source": [
"### 5.4 启动模型训练\n", "### 5.2 启动模型训练\n",
"\n", "\n",
"使用模型代码进行Model实例生成,使用prepare接口定义优化器、损失函数和评价指标等信息,用于后续训练使用。在所有初步配置完成后,调用fit接口开启训练执行过程,调用fit时只需要将前面定义好的训练数据集、测试数据集、训练轮次(Epoch)和批次大小(batch_size)配置好即可。" "使用模型代码进行Model实例生成,使用prepare接口定义优化器、损失函数和评价指标等信息,用于后续训练使用。在所有初步配置完成后,调用fit接口开启训练执行过程,调用fit时只需要将前面定义好的训练数据集、测试数据集、训练轮次(Epoch)和批次大小(batch_size)配置好即可。"
] ]
...@@ -907,8 +882,8 @@ ...@@ -907,8 +882,8 @@
"model.prepare(optim, SoftmaxWithCrossEntropy())\n", "model.prepare(optim, SoftmaxWithCrossEntropy())\n",
"model.fit(train_dataset, \n", "model.fit(train_dataset, \n",
" val_dataset, \n", " val_dataset, \n",
" epochs=EPOCHS, \n", " epochs=15, \n",
" batch_size=BATCH_SIZE)" " batch_size=32)"
] ]
}, },
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册