{ "cells": [ { "cell_type": "markdown", "id": "a1e738e0", "metadata": {}, "source": [ "## 获取测试的 logit 数据" ] }, { "cell_type": "code", "execution_count": 1, "id": "29d3368b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hlens.npy\n", "logits.npy\n", "ys_lens.npy\n", "ys_pad.npy\n" ] } ], "source": [ "!mkdir -p ./test_data\n", "!test -f ./test_data/ctc_loss_compare_data.tgz || wget -P ./test_data https://paddlespeech.bj.bcebos.com/datasets/unit_test/asr/ctc_loss_compare_data.tgz\n", "!tar xzvf test_data/ctc_loss_compare_data.tgz -C ./test_data\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "240caf1d", "metadata": {}, "outputs": [], "source": [ "import os\n", "import numpy as np\n", "import time\n", "\n", "data_dir=\"./test_data\"\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "91bad949", "metadata": {}, "outputs": [], "source": [ "logits_np = np.load(os.path.join(data_dir, \"logits.npy\"))\n", "ys_pad_np = np.load(os.path.join(data_dir, \"ys_pad.npy\"))\n", "hlens_np = np.load(os.path.join(data_dir, \"hlens.npy\"))\n", "ys_lens_np = np.load(os.path.join(data_dir, \"ys_lens.npy\"))" ] }, { "cell_type": "markdown", "id": "4cef2f15", "metadata": {}, "source": [ "## 使用 torch 的 ctc loss" ] }, { "cell_type": "code", "execution_count": 4, "id": "90612004", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'1.10.1+cu102'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import torch\n", "torch.__version__" ] }, { "cell_type": "code", "execution_count": 5, "id": "00799f97", "metadata": {}, "outputs": [], "source": [ "def torch_ctc_loss(use_cpu):\n", " if use_cpu:\n", " device = torch.device(\"cpu\")\n", " else:\n", " device = torch.device(\"cuda\")\n", "\n", " reduction_type = \"sum\" \n", "\n", " ctc_loss = torch.nn.CTCLoss(reduction=reduction_type)\n", "\n", " ys_hat = torch.tensor(logits_np, device = device)\n", " ys_pad = torch.tensor(ys_pad_np, device = device)\n", " hlens = torch.tensor(hlens_np, device = device)\n", " ys_lens = torch.tensor(ys_lens_np, device = device)\n", "\n", " ys_hat = ys_hat.transpose(0, 1)\n", " \n", " # 开始计算时间\n", " start_time = time.time()\n", " ys_hat = ys_hat.log_softmax(2)\n", " loss = ctc_loss(ys_hat, ys_pad, hlens, ys_lens)\n", " end_time = time.time()\n", " \n", " loss = loss / ys_hat.size(1)\n", " return end_time - start_time, loss.item()" ] }, { "cell_type": "markdown", "id": "ba47b5a4", "metadata": {}, "source": [ "## 使用 paddle 的 ctc loss" ] }, { "cell_type": "code", "execution_count": 6, "id": "6882a06e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'2.2.2'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import paddle\n", "paddle.__version__" ] }, { "cell_type": "code", "execution_count": 7, "id": "3cfa3b7c", "metadata": {}, "outputs": [], "source": [ "def paddle_ctc_loss(use_cpu): \n", " import paddle.nn as pn\n", " if use_cpu:\n", " device = \"cpu\"\n", " else:\n", " device = \"gpu\"\n", "\n", " paddle.set_device(device)\n", "\n", " logits = paddle.to_tensor(logits_np)\n", " ys_pad = paddle.to_tensor(ys_pad_np,dtype='int32')\n", " hlens = paddle.to_tensor(hlens_np, dtype='int64')\n", " ys_lens = paddle.to_tensor(ys_lens_np, dtype='int64')\n", "\n", " logits = logits.transpose([1,0,2])\n", "\n", " ctc_loss = pn.CTCLoss(reduction='sum')\n", " # 开始计算时间\n", " start_time = time.time()\n", " pn_loss = ctc_loss(logits, ys_pad, hlens, ys_lens)\n", " end_time = time.time()\n", " \n", " pn_loss = pn_loss / logits.shape[1]\n", " return end_time - start_time, pn_loss.item()" ] }, { "cell_type": "code", "execution_count": 8, "id": "40413ef9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU, iteration 10\n", "torch_ctc_loss 159.17137145996094\n", "paddle_ctc_loss 159.16574096679688\n", "paddle average time 1.718252992630005\n", "torch average time 0.17536230087280275\n", "paddle time / torch time (cpu) 9.798303193320452\n", "\n", "GPU, iteration 10\n", "torch_ctc_loss 159.172119140625\n", "paddle_ctc_loss 159.17205810546875\n", "paddle average time 0.018606925010681154\n", "torch average time 0.0026710033416748047\n", "paddle time / torch time (gpu) 6.966267963938231\n" ] } ], "source": [ "# 使用 CPU\n", "\n", "iteration = 10\n", "use_cpu = True\n", "torch_total_time = 0\n", "paddle_total_time = 0\n", "for _ in range(iteration):\n", " cost_time, torch_loss = torch_ctc_loss(use_cpu)\n", " torch_total_time += cost_time\n", "for _ in range(iteration):\n", " cost_time, paddle_loss = paddle_ctc_loss(use_cpu)\n", " paddle_total_time += cost_time\n", "print (\"CPU, iteration\", iteration)\n", "print (\"torch_ctc_loss\", torch_loss)\n", "print (\"paddle_ctc_loss\", paddle_loss)\n", "print (\"paddle average time\", paddle_total_time / iteration)\n", "print (\"torch average time\", torch_total_time / iteration)\n", "print (\"paddle time / torch time (cpu)\" , paddle_total_time/ torch_total_time)\n", "\n", "print (\"\")\n", "\n", "# 使用 GPU\n", "\n", "use_cpu = False\n", "torch_total_time = 0\n", "paddle_total_time = 0\n", "for _ in range(iteration):\n", " cost_time, torch_loss = torch_ctc_loss(use_cpu)\n", " torch_total_time += cost_time\n", "for _ in range(iteration):\n", " cost_time, paddle_loss = paddle_ctc_loss(use_cpu)\n", " paddle_total_time += cost_time\n", "print (\"GPU, iteration\", iteration)\n", "print (\"torch_ctc_loss\", torch_loss)\n", "print (\"paddle_ctc_loss\", paddle_loss)\n", "print (\"paddle average time\", paddle_total_time / iteration)\n", "print (\"torch average time\", torch_total_time / iteration)\n", "print (\"paddle time / torch time (gpu)\" , paddle_total_time/ torch_total_time)" ] }, { "cell_type": "markdown", "id": "7cdf8697", "metadata": {}, "source": [ "## 其他: 使用 PaddleSpeech 中的 ctcloss 查一下loss值" ] }, { "cell_type": "code", "execution_count": 9, "id": "73fad81d", "metadata": {}, "outputs": [], "source": [ "logits_np = np.load(os.path.join(data_dir, \"logits.npy\"))\n", "ys_pad_np = np.load(os.path.join(data_dir, \"ys_pad.npy\"))\n", "hlens_np = np.load(os.path.join(data_dir, \"hlens.npy\"))\n", "ys_lens_np = np.load(os.path.join(data_dir, \"ys_lens.npy\"))" ] }, { "cell_type": "code", "execution_count": 10, "id": "2b41e45d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2022-02-25 11:34:34.143 | INFO | paddlespeech.s2t.modules.loss:__init__:41 - CTCLoss Loss reduction: sum, div-bs: True\n", "2022-02-25 11:34:34.143 | INFO | paddlespeech.s2t.modules.loss:__init__:42 - CTCLoss Grad Norm Type: instance\n", "2022-02-25 11:34:34.144 | INFO | paddlespeech.s2t.modules.loss:__init__:73 - CTCLoss() kwargs:{'norm_by_times': True}, not support: {'norm_by_batchsize': False, 'norm_by_total_logits_len': False}\n", "loss 159.17205810546875\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/root/miniconda3/lib/python3.7/site-packages/paddle/fluid/dygraph/math_op_patch.py:253: UserWarning: The dtype of left and right variables are not the same, left dtype is paddle.float32, but right dtype is paddle.int32, the right dtype will convert to paddle.float32\n", " format(lhs_dtype, rhs_dtype, lhs_dtype))\n" ] } ], "source": [ "use_cpu = False\n", "\n", "from paddlespeech.s2t.modules.loss import CTCLoss\n", "\n", "if use_cpu:\n", " device = \"cpu\"\n", "else:\n", " device = \"gpu\"\n", "\n", "paddle.set_device(device)\n", "\n", "blank_id=0\n", "reduction_type='sum'\n", "batch_average= True\n", "grad_norm_type='instance'\n", "\n", "criterion = CTCLoss(\n", " blank=blank_id,\n", " reduction=reduction_type,\n", " batch_average=batch_average,\n", " grad_norm_type=grad_norm_type)\n", "\n", "logits = paddle.to_tensor(logits_np)\n", "ys_pad = paddle.to_tensor(ys_pad_np,dtype='int32')\n", "hlens = paddle.to_tensor(hlens_np, dtype='int64')\n", "ys_lens = paddle.to_tensor(ys_lens_np, dtype='int64')\n", "\n", "pn_ctc_loss = criterion(logits, ys_pad, hlens, ys_lens)\n", "print(\"loss\", pn_ctc_loss.item())\n", " " ] }, { "cell_type": "markdown", "id": "de525d38", "metadata": {}, "source": [ "## 结论\n", "在 CPU 环境下: torch 的 CTC loss 的计算速度是 paddle 的 9.8 倍 \n", "在 GPU 环境下: torch 的 CTC loss 的计算速度是 paddle 的 6.87 倍\n", "\n", "## 其他结论\n", "torch 的 ctc loss 在 CPU 和 GPU 下 都没有完全对齐。其中CPU的前向对齐精度大约为 1e-2。 GPU 的前向对齐精度大约为 1e-4 。" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.10" } }, "nbformat": 4, "nbformat_minor": 5 }