Unverified Commit 3d695fcc authored by xiaoting's avatar xiaoting Committed by GitHub
Browse files

Merge branch 'dygraph' into add_test_serving

parents ae12e0d5 d2d1483c
...@@ -141,6 +141,7 @@ Train: ...@@ -141,6 +141,7 @@ Train:
img_mode: BGR img_mode: BGR
channel_first: False channel_first: False
- DetLabelEncode: # Class handling label - DetLabelEncode: # Class handling label
- CopyPaste:
- IaaAugment: - IaaAugment:
augmenter_args: augmenter_args:
- { 'type': Fliplr, 'args': { 'p': 0.5 } } - { 'type': Fliplr, 'args': { 'p': 0.5 } }
......
...@@ -68,8 +68,7 @@ Loss: ...@@ -68,8 +68,7 @@ Loss:
ohem_ratio: 3 ohem_ratio: 3
- DistillationDBLoss: - DistillationDBLoss:
weight: 1.0 weight: 1.0
model_name_list: ["Student", "Teacher"] model_name_list: ["Student"]
# key: maps
name: DBLoss name: DBLoss
balance_loss: true balance_loss: true
main_loss_type: DiceLoss main_loss_type: DiceLoss
...@@ -116,6 +115,7 @@ Train: ...@@ -116,6 +115,7 @@ Train:
img_mode: BGR img_mode: BGR
channel_first: False channel_first: False
- DetLabelEncode: # Class handling label - DetLabelEncode: # Class handling label
- CopyPaste:
- IaaAugment: - IaaAugment:
augmenter_args: augmenter_args:
- { 'type': Fliplr, 'args': { 'p': 0.5 } } - { 'type': Fliplr, 'args': { 'p': 0.5 } }
......
...@@ -118,6 +118,7 @@ Train: ...@@ -118,6 +118,7 @@ Train:
img_mode: BGR img_mode: BGR
channel_first: False channel_first: False
- DetLabelEncode: # Class handling label - DetLabelEncode: # Class handling label
- CopyPaste:
- IaaAugment: - IaaAugment:
augmenter_args: augmenter_args:
- { 'type': Fliplr, 'args': { 'p': 0.5 } } - { 'type': Fliplr, 'args': { 'p': 0.5 } }
......
...@@ -94,7 +94,7 @@ Eval: ...@@ -94,7 +94,7 @@ Eval:
label_file_list: [./train_data/total_text/test/test.txt] label_file_list: [./train_data/total_text/test/test.txt]
transforms: transforms:
- DecodeImage: # load image - DecodeImage: # load image
img_mode: RGB img_mode: BGR
channel_first: False channel_first: False
- E2ELabelEncodeTest: - E2ELabelEncodeTest:
- E2EResizeForTest: - E2EResizeForTest:
...@@ -111,4 +111,4 @@ Eval: ...@@ -111,4 +111,4 @@ Eval:
shuffle: False shuffle: False
drop_last: False drop_last: False
batch_size_per_card: 1 # must be 1 batch_size_per_card: 1 # must be 1
num_workers: 2 num_workers: 2
\ No newline at end of file
...@@ -16,7 +16,7 @@ Focal Loss 出自论文《Focal Loss for Dense Object Detection》, 该loss最 ...@@ -16,7 +16,7 @@ Focal Loss 出自论文《Focal Loss for Dense Object Detection》, 该loss最
从上图可以看到, 当γ> 0时,调整系数(1-y’)^γ 赋予易分类样本损失一个更小的权重,使得网络更关注于困难的、错分的样本。 调整因子γ用于调节简单样本权重降低的速率,当γ为0时即为交叉熵损失函数,当γ增加时,调整因子的影响也会随之增大。实验发现γ为2是最优。平衡因子α用来平衡正负样本本身的比例不均,文中α取0.25。 从上图可以看到, 当γ> 0时,调整系数(1-y’)^γ 赋予易分类样本损失一个更小的权重,使得网络更关注于困难的、错分的样本。 调整因子γ用于调节简单样本权重降低的速率,当γ为0时即为交叉熵损失函数,当γ增加时,调整因子的影响也会随之增大。实验发现γ为2是最优。平衡因子α用来平衡正负样本本身的比例不均,文中α取0.25。
对于经典的CTC算法,假设某个特征序列(f<sub>1</sub>, f<sub>2</sub>, ......f<sub>t</sub>), 经过CTC解码之后结果等于label的概率为y’, 则CTC解码结果不为label的概率即为(1-y’);不难发现 CTCLoss值和y’有如下关系: 对于经典的CTC算法,假设某个特征序列(f<sub>1</sub>, f<sub>2</sub>, ......f<sub>t</sub>), 经过CTC解码之后结果等于label的概率为y’, 则CTC解码结果不为label的概率即为(1-y’);不难发现, CTCLoss值和y’有如下关系:
<div align="center"> <div align="center">
<img src="./equation_ctcloss.png" width = "250" /> <img src="./equation_ctcloss.png" width = "250" />
</div> </div>
...@@ -38,7 +38,7 @@ A-CTC Loss是CTC Loss + ACE Loss的简称。 其中ACE Loss出自论文< Aggrega ...@@ -38,7 +38,7 @@ A-CTC Loss是CTC Loss + ACE Loss的简称。 其中ACE Loss出自论文< Aggrega
<img src="./rec_algo_compare.png" width = "1000" /> <img src="./rec_algo_compare.png" width = "1000" />
</div> </div>
虽然ACELoss确实如上图所说,可以处理2D预测,在内存占用及推理速度方面具备优势,但在实践过程中,我们发现单独使用ACE Loss, 识别效果并不如CTCLoss. 因此,我们尝试将CTCLoss和ACELoss进行合,同时以CTCLoss为主,将ACELoss 定位为一个辅助监督loss。 这一尝试收到了效果,在我们内部的实验数据集上,相比单独使用CTCLoss,识别准确率可以提升1%左右。 虽然ACELoss确实如上图所说,可以处理2D预测,在内存占用及推理速度方面具备优势,但在实践过程中,我们发现单独使用ACE Loss, 识别效果并不如CTCLoss. 因此,我们尝试将CTCLoss和ACELoss进行合,同时以CTCLoss为主,将ACELoss 定位为一个辅助监督loss。 这一尝试收到了效果,在我们内部的实验数据集上,相比单独使用CTCLoss,识别准确率可以提升1%左右。
A_CTC Loss定义如下: A_CTC Loss定义如下:
<div align="center"> <div align="center">
<img src="./equation_a_ctc.png" width = "300" /> <img src="./equation_a_ctc.png" width = "300" />
...@@ -47,7 +47,7 @@ A_CTC Loss定义如下: ...@@ -47,7 +47,7 @@ A_CTC Loss定义如下:
实验中,λ = 0.1. ACE loss实现代码见: [ace_loss.py](../../ppocr/losses/ace_loss.py) 实验中,λ = 0.1. ACE loss实现代码见: [ace_loss.py](../../ppocr/losses/ace_loss.py)
## 3. C-CTC Loss ## 3. C-CTC Loss
C-CTC Loss是CTC Loss + Center Loss的简称。 其中Center Loss出自论文 < A Discriminative Feature Learning Approach for Deep Face Recognition>. 最早用于人脸识别任务,用于增大间距离,减小类内距离, 是Metric Learning领域一种较早的、也比较常用的一种算法。 C-CTC Loss是CTC Loss + Center Loss的简称。 其中Center Loss出自论文 < A Discriminative Feature Learning Approach for Deep Face Recognition>. 最早用于人脸识别任务,用于增大间距离,减小类内距离, 是Metric Learning领域一种较早的、也比较常用的一种算法。
在中文OCR识别任务中,通过对badcase分析, 我们发现中文识别的一大难点是相似字符多,容易误识。 由此我们想到是否可以借鉴Metric Learing的想法, 增大相似字符的类间距,从而提高识别准确率。然而,MetricLearning主要用于图像识别领域,训练数据的标签为一个固定的值;而对于OCR识别来说,其本质上是一个序列识别任务,特征和label之间并不具有显式的对齐关系,因此两者如何结合依然是一个值得探索的方向。 在中文OCR识别任务中,通过对badcase分析, 我们发现中文识别的一大难点是相似字符多,容易误识。 由此我们想到是否可以借鉴Metric Learing的想法, 增大相似字符的类间距,从而提高识别准确率。然而,MetricLearning主要用于图像识别领域,训练数据的标签为一个固定的值;而对于OCR识别来说,其本质上是一个序列识别任务,特征和label之间并不具有显式的对齐关系,因此两者如何结合依然是一个值得探索的方向。
通过尝试Arcmargin, Cosmargin等方法, 我们最终发现Centerloss 有助于进一步提升识别的准确率。C_CTC Loss定义如下: 通过尝试Arcmargin, Cosmargin等方法, 我们最终发现Centerloss 有助于进一步提升识别的准确率。C_CTC Loss定义如下:
<div align="center"> <div align="center">
......
# 运行环境准备 # 运行环境准备
Windows和Mac用户推荐使用Anaconda搭建Python环境,Linux用户建议使用docker搭建PyThon环境。 Windows和Mac用户推荐使用Anaconda搭建Python环境,Linux用户建议使用docker搭建PyThon环境。
推荐环境:
- PaddlePaddle >= 2.0.0 (2.1.2)
- python3.7
- CUDA10.1 / CUDA10.2
- CUDNN 7.6
如果对于Python环境熟悉的用户可以直接跳到第2步安装PaddlePaddle。 如果对于Python环境熟悉的用户可以直接跳到第2步安装PaddlePaddle。
* [1. Python环境搭建](#1) * [1. Python环境搭建](#1)
...@@ -123,13 +130,13 @@ Windows和Mac用户推荐使用Anaconda搭建Python环境,Linux用户建议使 ...@@ -123,13 +130,13 @@ Windows和Mac用户推荐使用Anaconda搭建Python环境,Linux用户建议使
# !! Contents within this block are managed by 'conda init' !! # !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/Users/xxx/opt/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)" __conda_setup="$('/Users/xxx/opt/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
eval "$__conda_setup" eval "$__conda_setup"
else else
if [ -f "/Users/xxx/opt/anaconda3/etc/profile.d/conda.sh" ]; then if [ -f "/Users/xxx/opt/anaconda3/etc/profile.d/conda.sh" ]; then
. "/Users/xxx/opt/anaconda3/etc/profile.d/conda.sh" . "/Users/xxx/opt/anaconda3/etc/profile.d/conda.sh"
else else
export PATH="/Users/xxx/opt/anaconda3/bin:$PATH" export PATH="/Users/xxx/opt/anaconda3/bin:$PATH"
fi fi
fi fi
unset __conda_setup unset __conda_setup
# <<< conda initialize <<< # <<< conda initialize <<<
...@@ -294,11 +301,12 @@ cd /home/Projects ...@@ -294,11 +301,12 @@ cd /home/Projects
# 首次运行需创建一个docker容器,再次运行时不需要运行当前命令 # 首次运行需创建一个docker容器,再次运行时不需要运行当前命令
# 创建一个名字为ppocr的docker容器,并将当前目录映射到容器的/paddle目录下 # 创建一个名字为ppocr的docker容器,并将当前目录映射到容器的/paddle目录下
如果您希望在CPU环境下使用docker,使用docker而不是nvidia-docker创建docker #如果您希望在CPU环境下使用docker,使用docker而不是nvidia-docker创建docker
sudo docker run --name ppocr -v $PWD:/paddle --network=host -it paddlepaddle/paddle:latest-dev-cuda10.1-cudnn7-gcc82 /bin/bash sudo docker run --name ppocr -v $PWD:/paddle --network=host -it registry.baidubce.com/paddlepaddle/paddle:2.1.3-gpu-cuda10.2-cudnn7 /bin/bash
如果使用CUDA10,请运行以下命令创建容器,设置docker容器共享内存shm-size为64G,建议设置32G以上 #如果使用CUDA10,请运行以下命令创建容器,设置docker容器共享内存shm-size为64G,建议设置32G以上
sudo nvidia-docker run --name ppocr -v $PWD:/paddle --shm-size=64G --network=host -it paddlepaddle/paddle:latest-dev-cuda10.1-cudnn7-gcc82 /bin/bash # 如果是CUDA11+CUDNN8,推荐使用镜像registry.baidubce.com/paddlepaddle/paddle:2.1.3-gpu-cuda11.2-cudnn8
sudo nvidia-docker run --name ppocr -v $PWD:/paddle --shm-size=64G --network=host -it registry.baidubce.com/paddlepaddle/paddle:2.1.3-gpu-cuda10.2-cudnn7 /bin/bash
# ctrl+P+Q可退出docker 容器,重新进入docker 容器使用如下命令 # ctrl+P+Q可退出docker 容器,重新进入docker 容器使用如下命令
sudo docker container exec -it ppocr /bin/bash sudo docker container exec -it ppocr /bin/bash
...@@ -321,8 +329,3 @@ python3 -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple ...@@ -321,8 +329,3 @@ python3 -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple
``` ```
更多的版本需求,请参照[飞桨官网安装文档](https://www.paddlepaddle.org.cn/install/quick)中的说明进行操作。 更多的版本需求,请参照[飞桨官网安装文档](https://www.paddlepaddle.org.cn/install/quick)中的说明进行操作。
# Environment Preparation # Environment Preparation
Recommended working environment:
- PaddlePaddle >= 2.0.0 (2.1.2)
- python3.7
- CUDA10.1 / CUDA10.2
- CUDNN 7.6
* [1. Python Environment Setup](#1) * [1. Python Environment Setup](#1)
+ [1.1 Windows](#1.1) + [1.1 Windows](#1.1)
+ [1.2 Mac](#1.2) + [1.2 Mac](#1.2)
+ [1.3 Linux](#1.3) + [1.3 Linux](#1.3)
* [2. Install PaddlePaddle 2.0](#2) * [2. Install PaddlePaddle 2.0](#2)
<a name="1"></a> <a name="1"></a>
## 1. Python Environment Setup ## 1. Python Environment Setup
...@@ -38,7 +45,7 @@ ...@@ -38,7 +45,7 @@
- Check conda to add environment variables and ignore the warning that - Check conda to add environment variables and ignore the warning that
<img src="../install/windows/anaconda_install_env.png" alt="add conda to path" width="500" align="center"/> <img src="../install/windows/anaconda_install_env.png" alt="add conda to path" width="500" align="center"/>
#### 1.1.2 Opening the terminal and creating the conda environment #### 1.1.2 Opening the terminal and creating the conda environment
...@@ -69,7 +76,7 @@ ...@@ -69,7 +76,7 @@
# View the current location of python # View the current location of python
where python where python
``` ```
<img src="../install/windows/conda_list_env.png" alt="create environment" width="600" align="center"/> <img src="../install/windows/conda_list_env.png" alt="create environment" width="600" align="center"/>
The above anaconda environment and python environment are installed The above anaconda environment and python environment are installed
...@@ -133,13 +140,13 @@ The above anaconda environment and python environment are installed ...@@ -133,13 +140,13 @@ The above anaconda environment and python environment are installed
# !!! Contents within this block are managed by 'conda init' !!! # !!! Contents within this block are managed by 'conda init' !!!
__conda_setup="$('/Users/xxx/opt/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)" __conda_setup="$('/Users/xxx/opt/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
eval "$__conda_setup" eval "$__conda_setup"
else else
if [ -f "/Users/xxx/opt/anaconda3/etc/profile.d/conda.sh" ]; then if [ -f "/Users/xxx/opt/anaconda3/etc/profile.d/conda.sh" ]; then
. "/Users/xxx/opt/anaconda3/etc/profile.d/conda.sh" . "/Users/xxx/opt/anaconda3/etc/profile.d/conda.sh"
else else
export PATH="/Users/xxx/opt/anaconda3/bin:$PATH" export PATH="/Users/xxx/opt/anaconda3/bin:$PATH"
fi fi
fi fi
unset __conda_setup unset __conda_setup
# <<< conda initialize <<< # <<< conda initialize <<<
...@@ -197,11 +204,10 @@ Linux users can choose to run either Anaconda or Docker. If you are familiar wit ...@@ -197,11 +204,10 @@ Linux users can choose to run either Anaconda or Docker. If you are familiar wit
- **Download Anaconda**. - **Download Anaconda**.
- Download at: https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=D - Download at: https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=D
<img src="../install/linux/anaconda_download.png" akt="anaconda download" width="800" align="center"/> <img src="../install/linux/anaconda_download.png" akt="anaconda download" width="800" align="center"/>
- Select the appropriate version for your operating system - Select the appropriate version for your operating system
- Type `uname -m` in the terminal to check the command set used by your system - Type `uname -m` in the terminal to check the command set used by your system
...@@ -216,12 +222,12 @@ Linux users can choose to run either Anaconda or Docker. If you are familiar wit ...@@ -216,12 +222,12 @@ Linux users can choose to run either Anaconda or Docker. If you are familiar wit
sudo yum install wget # CentOS sudo yum install wget # CentOS
``` ```
```bash ```bash
# Then use wget to download from Tsinghua source # Then use wget to download from Tsinghua source
# If you want to download Anaconda3-2021.05-Linux-x86_64.sh, the download command is as follows # If you want to download Anaconda3-2021.05-Linux-x86_64.sh, the download command is as follows
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2021.05-Linux-x86_64.sh wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2021.05-Linux-x86_64.sh
# If you want to download another version, you need to change the file name after the last 1 / to the version you want to download # If you want to download another version, you need to change the file name after the last 1 / to the version you want to download
``` ```
- To install Anaconda. - To install Anaconda.
- Type `sh Anaconda3-2021.05-Linux-x86_64.sh` at the command line - Type `sh Anaconda3-2021.05-Linux-x86_64.sh` at the command line
...@@ -309,7 +315,18 @@ cd /home/Projects ...@@ -309,7 +315,18 @@ cd /home/Projects
# Create a docker container named ppocr and map the current directory to the /paddle directory of the container # Create a docker container named ppocr and map the current directory to the /paddle directory of the container
# If using CPU, use docker instead of nvidia-docker to create docker # If using CPU, use docker instead of nvidia-docker to create docker
sudo docker run --name ppocr -v $PWD:/paddle --network=host -it paddlepaddle/paddle:latest-dev-cuda10.1-cudnn7-gcc82 /bin/bash sudo docker run --name ppocr -v $PWD:/paddle --network=host -it registry.baidubce.com/paddlepaddle/paddle:2.1.3-gpu-cuda10.2-cudnn7 /bin/bash
# If using GPU, use nvidia-docker to create docker
# docker image registry.baidubce.com/paddlepaddle/paddle:2.1.3-gpu-cuda11.2-cudnn8 is recommended for CUDA11.2 + CUDNN8.
sudo nvidia-docker run --name ppocr -v $PWD:/paddle --shm-size=64G --network=host -it registry.baidubce.com/paddlepaddle/paddle:2.1.3-gpu-cuda10.2-cudnn7 /bin/bash
```
You can also visit [DockerHub](https://hub.docker.com/r/paddlepaddle/paddle/tags/) to get the image that fits your machine.
```
# ctrl+P+Q to exit docker, to re-enter docker using the following command:
sudo docker container exec -it ppocr /bin/bash
``` ```
<a name="2"></a> <a name="2"></a>
...@@ -329,4 +346,3 @@ python3 -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple ...@@ -329,4 +346,3 @@ python3 -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple
``` ```
For more software version requirements, please refer to the instructions in [Installation Document](https://www.paddlepaddle.org.cn/install/quick) for operation. For more software version requirements, please refer to the instructions in [Installation Document](https://www.paddlepaddle.org.cn/install/quick) for operation.
doc/joinus.PNG

194 KB | W: | H:

doc/joinus.PNG

188 KB | W: | H:

doc/joinus.PNG
doc/joinus.PNG
doc/joinus.PNG
doc/joinus.PNG
  • 2-up
  • Swipe
  • Onion skin
...@@ -32,6 +32,7 @@ class ACELoss(nn.Layer): ...@@ -32,6 +32,7 @@ class ACELoss(nn.Layer):
def __call__(self, predicts, batch): def __call__(self, predicts, batch):
if isinstance(predicts, (list, tuple)): if isinstance(predicts, (list, tuple)):
predicts = predicts[-1] predicts = predicts[-1]
B, N = predicts.shape[:2] B, N = predicts.shape[:2]
div = paddle.to_tensor([N]).astype('float32') div = paddle.to_tensor([N]).astype('float32')
...@@ -42,9 +43,7 @@ class ACELoss(nn.Layer): ...@@ -42,9 +43,7 @@ class ACELoss(nn.Layer):
length = batch[2].astype("float32") length = batch[2].astype("float32")
batch = batch[3].astype("float32") batch = batch[3].astype("float32")
batch[:, 0] = paddle.subtract(div, length) batch[:, 0] = paddle.subtract(div, length)
batch = paddle.divide(batch, div) batch = paddle.divide(batch, div)
loss = self.loss_func(aggregation_preds, batch) loss = self.loss_func(aggregation_preds, batch)
return {"loss_ace": loss} return {"loss_ace": loss}
...@@ -27,7 +27,6 @@ class CenterLoss(nn.Layer): ...@@ -27,7 +27,6 @@ class CenterLoss(nn.Layer):
""" """
Reference: Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016. Reference: Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016.
""" """
def __init__(self, def __init__(self,
num_classes=6625, num_classes=6625,
feat_dim=96, feat_dim=96,
...@@ -37,8 +36,7 @@ class CenterLoss(nn.Layer): ...@@ -37,8 +36,7 @@ class CenterLoss(nn.Layer):
self.num_classes = num_classes self.num_classes = num_classes
self.feat_dim = feat_dim self.feat_dim = feat_dim
self.centers = paddle.randn( self.centers = paddle.randn(
shape=[self.num_classes, self.feat_dim]).astype( shape=[self.num_classes, self.feat_dim]).astype("float64")
"float64") #random center
if init_center: if init_center:
assert os.path.exists( assert os.path.exists(
...@@ -60,22 +58,23 @@ class CenterLoss(nn.Layer): ...@@ -60,22 +58,23 @@ class CenterLoss(nn.Layer):
batch_size = feats_reshape.shape[0] batch_size = feats_reshape.shape[0]
#calc feat * feat #calc l2 distance between feats and centers
dist1 = paddle.sum(paddle.square(feats_reshape), axis=1, keepdim=True) square_feat = paddle.sum(paddle.square(feats_reshape),
dist1 = paddle.expand(dist1, [batch_size, self.num_classes]) axis=1,
keepdim=True)
square_feat = paddle.expand(square_feat, [batch_size, self.num_classes])
#dist2 of centers square_center = paddle.sum(paddle.square(self.centers),
dist2 = paddle.sum(paddle.square(self.centers), axis=1, axis=1,
keepdim=True) #num_classes keepdim=True)
dist2 = paddle.expand(dist2, square_center = paddle.expand(
[self.num_classes, batch_size]).astype("float64") square_center, [self.num_classes, batch_size]).astype("float64")
dist2 = paddle.transpose(dist2, [1, 0]) square_center = paddle.transpose(square_center, [1, 0])
#first x * x + y * y distmat = paddle.add(square_feat, square_center)
distmat = paddle.add(dist1, dist2) feat_dot_center = paddle.matmul(feats_reshape,
tmp = paddle.matmul(feats_reshape, paddle.transpose(self.centers, [1, 0]))
paddle.transpose(self.centers, [1, 0])) distmat = distmat - 2.0 * feat_dot_center
distmat = distmat - 2.0 * tmp
#generate the mask #generate the mask
classes = paddle.arange(self.num_classes).astype("int64") classes = paddle.arange(self.num_classes).astype("int64")
...@@ -83,7 +82,8 @@ class CenterLoss(nn.Layer): ...@@ -83,7 +82,8 @@ class CenterLoss(nn.Layer):
paddle.unsqueeze(label, 1), (batch_size, self.num_classes)) paddle.unsqueeze(label, 1), (batch_size, self.num_classes))
mask = paddle.equal( mask = paddle.equal(
paddle.expand(classes, [batch_size, self.num_classes]), paddle.expand(classes, [batch_size, self.num_classes]),
label).astype("float64") #get mask label).astype("float64")
dist = paddle.multiply(distmat, mask) dist = paddle.multiply(distmat, mask)
loss = paddle.sum(paddle.clip(dist, min=1e-12, max=1e+12)) / batch_size loss = paddle.sum(paddle.clip(dist, min=1e-12, max=1e+12)) / batch_size
return {'loss_center': loss} return {'loss_center': loss}
...@@ -9,11 +9,14 @@ from paddle import nn ...@@ -9,11 +9,14 @@ from paddle import nn
class SARLoss(nn.Layer): class SARLoss(nn.Layer):
def __init__(self, **kwargs): def __init__(self, **kwargs):
super(SARLoss, self).__init__() super(SARLoss, self).__init__()
self.loss_func = paddle.nn.loss.CrossEntropyLoss(reduction="mean", ignore_index=96) self.loss_func = paddle.nn.loss.CrossEntropyLoss(
reduction="mean", ignore_index=92)
def forward(self, predicts, batch): def forward(self, predicts, batch):
predict = predicts[:, :-1, :] # ignore last index of outputs to be in same seq_len with targets predict = predicts[:, :
label = batch[1].astype("int64")[:, 1:] # ignore first index of target in loss calculation -1, :] # ignore last index of outputs to be in same seq_len with targets
label = batch[1].astype(
"int64")[:, 1:] # ignore first index of target in loss calculation
batch_size, num_steps, num_classes = predict.shape[0], predict.shape[ batch_size, num_steps, num_classes = predict.shape[0], predict.shape[
1], predict.shape[2] 1], predict.shape[2]
assert len(label.shape) == len(list(predict.shape)) - 1, \ assert len(label.shape) == len(list(predict.shape)) - 1, \
......
# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,26 +16,17 @@ from __future__ import absolute_import ...@@ -16,26 +16,17 @@ from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import numpy as np
import paddle
from paddle import ParamAttr
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn import Conv2D, BatchNorm, Linear, Dropout
from paddle.nn import AdaptiveAvgPool2D, MaxPool2D, AvgPool2D
from paddle.nn.initializer import KaimingNormal
import math import math
import numpy as np import numpy as np
import paddle import paddle
from paddle import ParamAttr, reshape, transpose, concat, split from paddle import ParamAttr, reshape, transpose
import paddle.nn as nn import paddle.nn as nn
import paddle.nn.functional as F import paddle.nn.functional as F
from paddle.nn import Conv2D, BatchNorm, Linear, Dropout from paddle.nn import Conv2D, BatchNorm, Linear, Dropout
from paddle.nn import AdaptiveAvgPool2D, MaxPool2D, AvgPool2D from paddle.nn import AdaptiveAvgPool2D, MaxPool2D, AvgPool2D
from paddle.nn.initializer import KaimingNormal from paddle.nn.initializer import KaimingNormal
import math
from paddle.nn.functional import hardswish, hardsigmoid
from paddle.regularizer import L2Decay from paddle.regularizer import L2Decay
from paddle.nn.functional import hardswish, hardsigmoid
class ConvBNLayer(nn.Layer): class ConvBNLayer(nn.Layer):
......
...@@ -51,7 +51,7 @@ class EncoderWithFC(nn.Layer): ...@@ -51,7 +51,7 @@ class EncoderWithFC(nn.Layer):
super(EncoderWithFC, self).__init__() super(EncoderWithFC, self).__init__()
self.out_channels = hidden_size self.out_channels = hidden_size
weight_attr, bias_attr = get_para_bias_attr( weight_attr, bias_attr = get_para_bias_attr(
l2_decay=0.00001, k=in_channels, name='reduce_encoder_fea') l2_decay=0.00001, k=in_channels)
self.fc = nn.Linear( self.fc = nn.Linear(
in_channels, in_channels,
hidden_size, hidden_size,
......
0
1
2
3
4
5
6
7
8
9
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
!
"
#
$
%
&
'
(
)
*
+
,
-
.
/
:
;
<
=
>
?
@
[
\
]
_
`
~
\ No newline at end of file
# C++预测功能测试
C++预测功能测试的主程序为`test_cpp.sh`,可以测试基于C++预测库的模型推理功能。
## 测试结论汇总
| 算法名称 | 模型名称 |device | batchsize | mkldnn | cpu多线程 | tensorrt | 离线量化 |
| ---- | ---- | ---- | ---- | ---- | ---- | ----| --- |
| DB |ch_ppocr_mobile_v2.0_det| CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
| DB |ch_ppocr_server_v2.0_det| CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
| CRNN |ch_ppocr_mobile_v2.0_rec| CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
| CRNN |ch_ppocr_server_v2.0_rec| CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
|PP-OCR|ch_ppocr_server_v2.0 | CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
|PP-OCR|ch_ppocr_server_v2.0 | CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
## 1. 功能测试
先运行`prepare.sh`准备数据和模型,然后运行`test_cpp.sh`进行测试,最终在```tests/output```目录下生成`cpp_infer_*.log`后缀的日志文件。
```shell
bash tests/prepare.sh ./tests/configs/ppocr_det_mobile_params.txt
# 用法1:
bash tests/test_cpp.sh ./tests/configs/ppocr_det_mobile_params.txt
# 用法2: 指定GPU卡预测,第三个传入参数为GPU卡号
bash tests/test_cpp.sh ./tests/configs/ppocr_det_mobile_params.txt '1'
```
## 2. 精度测试
使用compare_results.py脚本比较模型预测的结果是否符合预期,主要步骤包括:
- 提取日志中的预测坐标;
- 从本地文件中提取保存好的坐标结果;
- 比较上述两个结果是否符合精度预期,误差大于设置阈值时会报错。
### 使用方式
运行命令:
```shell
python3.7 tests/compare_results.py --gt_file=./tests/results/cpp_*.txt --log_file=./tests/output/cpp_*.log --atol=1e-3 --rtol=1e-3
```
参数介绍:
- gt_file: 指向事先保存好的预测结果路径,支持*.txt 结尾,会自动索引*.txt格式的文件,文件默认保存在tests/result/ 文件夹下
- log_file: 指向运行tests/test.sh 脚本的infer模式保存的预测日志,预测日志中打印的有预测结果,比如:文本框,预测文本,类别等等,同样支持infer_*.log格式传入
- atol: 设置的绝对误差
- rtol: 设置的相对误差
### 运行结果
正常运行效果如下图:
<img src="compare_right.png" width="1000">
出现不一致结果时的运行输出:
<img src="compare_wrong.png" width="1000">
# Python功能测试
Python功能测试的主程序为`test_python.sh`,可以测试基于Python的模型训练、评估、推理等基本功能,包括裁剪、量化、蒸馏。
## 测试结论汇总
- 训练相关:
| 算法名称 | 模型名称 | 单机单卡 | 单机多卡 | 多机多卡 | 模型压缩(单机多卡) |
| :---- | :---- | :---- | :---- | :---- | :---- |
| DB | ch_ppocr_mobile_v2.0_det| 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练:FPGM裁剪、PACT量化 |
| DB | ch_ppocr_server_v2.0_det| 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练:FPGM裁剪、PACT量化 |
| CRNN | ch_ppocr_mobile_v2.0_rec| 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练:FPGM裁剪、PACT量化 |
| CRNN | ch_ppocr_server_v2.0_rec| 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练:FPGM裁剪、PACT量化 |
|PP-OCR| ch_ppocr_mobile_v2.0| 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练:FPGM裁剪、PACT量化 |
|PP-OCR| ch_ppocr_server_v2.0| 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练 <br> 混合精度 | 正常训练:FPGM裁剪、PACT量化 |
- 预测相关:
| 算法名称 | 模型名称 |device | batchsize | mkldnn | cpu多线程 | tensorrt | 离线量化 |
| ---- | ---- | ---- | ---- | ---- | ---- | ----| --- |
| DB |ch_ppocr_mobile_v2.0_det| CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
| DB |ch_ppocr_server_v2.0_det| CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
| CRNN |ch_ppocr_mobile_v2.0_rec| CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
| CRNN |ch_ppocr_server_v2.0_rec| CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
|PP-OCR|ch_ppocr_server_v2.0 | CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
|PP-OCR|ch_ppocr_server_v2.0 | CPU/GPU | 1/6 | 支持 | 支持 | fp32/fp16/int8 | 支持 |
## 1. 安装依赖
- 安装PaddlePaddle >= 2.0
- 安装PaddleOCR依赖
```
pip3 install -r ../requirements.txt
```
- 安装autolog(规范化日志输出工具)
```
git clone https://github.com/LDOUBLEV/AutoLog
cd AutoLog
pip3 install -r requirements.txt
python3 setup.py bdist_wheel
pip3 install ./dist/auto_log-1.0.0-py3-none-any.whl
cd ../
```
## 2. 功能测试
先运行`prepare.sh`准备数据和模型,然后运行`test_python.sh`进行测试,最终在```tests/output```目录下生成`infer_*.log`格式的日志文件。
test_python.sh包含四种运行模式,每种模式的运行数据不同,分别用于测试速度和精度,分别是:
- 模式1:lite_train_infer,使用少量数据训练,用于快速验证训练到预测的走通流程,不验证精度和速度;
```shell
bash tests/prepare.sh ./tests/configs/ppocr_det_mobile_params.txt 'lite_train_infer'
bash tests/test_python.sh ./tests/configs/ppocr_det_mobile_params.txt 'lite_train_infer'
```
- 模式2:whole_infer,使用少量数据训练,一定量数据预测,用于验证训练后的模型执行预测,预测速度是否合理;
```shell
bash tests/prepare.sh ./tests/configs/ppocr_det_mobile_params.txt 'whole_infer'
bash tests/test_python.sh ./tests/configs/ppocr_det_mobile_params.txt 'whole_infer'
```
- 模式3:infer 不训练,全量数据预测,走通开源模型评估、动转静,检查inference model预测时间和精度;
```shell
bash tests/prepare.sh ./tests/configs/ppocr_det_mobile_params.txt 'infer'
# 用法1:
bash tests/test_python.sh ./tests/configs/ppocr_det_mobile_params.txt 'infer'
# 用法2: 指定GPU卡预测,第三个传入参数为GPU卡号
bash tests/test_python.sh ./tests/configs/ppocr_det_mobile_params.txt 'infer' '1'
```
- 模式4:whole_train_infer , CE: 全量数据训练,全量数据预测,验证模型训练精度,预测精度,预测速度;
```shell
bash tests/prepare.sh ./tests/configs/ppocr_det_mobile_params.txt 'whole_train_infer'
bash tests/test.sh ./tests/configs/ppocr_det_mobile_params.txt 'whole_train_infer'
```
- 模式5:klquant_infer , 测试离线量化;
```shell
bash tests/test_python.sh tests/configs/ppocr_det_mobile_params.txt 'klquant_infer'
```
## 3. 精度测试
使用compare_results.py脚本比较模型预测的结果是否符合预期,主要步骤包括:
- 提取日志中的预测坐标;
- 从本地文件中提取保存好的坐标结果;
- 比较上述两个结果是否符合精度预期,误差大于设置阈值时会报错。
### 使用方式
运行命令:
```shell
python3.7 tests/compare_results.py --gt_file=./tests/results/python_*.txt --log_file=./tests/output/python_*.log --atol=1e-3 --rtol=1e-3
```
参数介绍:
- gt_file: 指向事先保存好的预测结果路径,支持*.txt 结尾,会自动索引*.txt格式的文件,文件默认保存在tests/result/ 文件夹下
- log_file: 指向运行tests/test.sh 脚本的infer模式保存的预测日志,预测日志中打印的有预测结果,比如:文本框,预测文本,类别等等,同样支持infer_*.log格式传入
- atol: 设置的绝对误差
- rtol: 设置的相对误差
### 运行结果
正常运行效果如下图:
<img src="compare_right.png" width="1000">
出现不一致结果时的运行输出:
<img src="compare_wrong.png" width="1000">
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment