forked from mindspore-Ecosystem/mindspore
remove CTCLossV2
This commit is contained in:
parent
f5128faba5
commit
fea928e976
|
@ -1,31 +0,0 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "backend/kernel_compiler/gpu/nn/ctclossv2_gpu_kernel.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace kernel {
|
||||
MS_REG_GPU_KERNEL_ONE(CTCLossV2,
|
||||
KernelAttr()
|
||||
.AddInputAttr(kNumberTypeFloat32)
|
||||
.AddInputAttr(kNumberTypeInt32)
|
||||
.AddInputAttr(kNumberTypeInt32)
|
||||
.AddInputAttr(kNumberTypeInt32)
|
||||
.AddOutputAttr(kNumberTypeFloat32)
|
||||
.AddOutputAttr(kNumberTypeFloat32),
|
||||
CtcLossV2GpuKernel, float)
|
||||
} // namespace kernel
|
||||
} // namespace mindspore
|
|
@ -1,192 +0,0 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_GPU_NN_CTCLOSS_GPU_KERNEL_H_
|
||||
#define MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_GPU_NN_CTCLOSS_GPU_KERNEL_H_
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <vector>
|
||||
#include "backend/kernel_compiler/gpu/gpu_kernel.h"
|
||||
#include "backend/kernel_compiler/gpu/gpu_kernel_factory.h"
|
||||
#include "runtime/device/gpu/gpu_memory_allocator.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace kernel {
|
||||
template <typename T>
|
||||
class CtcLossV2GpuKernel : public GpuKernel {
|
||||
public:
|
||||
CtcLossV2GpuKernel()
|
||||
: cudnn_handle_(nullptr),
|
||||
probs_desc_(nullptr),
|
||||
ctcloss_desc_(nullptr),
|
||||
label_size_(0),
|
||||
input_lengths_size_(0),
|
||||
label_lengths_size_(0) {}
|
||||
~CtcLossV2GpuKernel() override { DestroyResource(); }
|
||||
|
||||
const std::vector<size_t> &GetInputSizeList() const override { return input_size_list_; }
|
||||
const std::vector<size_t> &GetOutputSizeList() const override { return output_size_list_; }
|
||||
const std::vector<size_t> &GetWorkspaceSizeList() const override { return workspace_size_list_; }
|
||||
|
||||
bool Launch(const std::vector<AddressPtr> &inputs, const std::vector<AddressPtr> &,
|
||||
const std::vector<AddressPtr> &outputs, void *stream_ptr) override {
|
||||
float *probs = GetDeviceAddress<float>(inputs, 0);
|
||||
float *costs = GetDeviceAddress<float>(outputs, 0);
|
||||
float *grads = GetDeviceAddress<float>(outputs, 1);
|
||||
|
||||
// Copy labels/input_lengths/label_length to host as cudnn7.x.x requires
|
||||
int *labels_host = nullptr;
|
||||
int *no_blank_labels_host = nullptr;
|
||||
void *input_lengths_host = nullptr;
|
||||
void *label_lengths_host = nullptr;
|
||||
cudaStream_t stream = reinterpret_cast<cudaStream_t>(stream_ptr);
|
||||
AllocHostMem(&labels_host, &no_blank_labels_host, &input_lengths_host, &label_lengths_host, inputs);
|
||||
CopyToHostSync(labels_host, no_blank_labels_host, input_lengths_host, label_lengths_host, inputs, stream);
|
||||
|
||||
size_t workspace_size = 0;
|
||||
CHECK_CUDNN_RET_WITH_EXCEPT(
|
||||
cudnnGetCTCLossWorkspaceSize(
|
||||
cudnn_handle_, probs_desc_, probs_desc_, reinterpret_cast<int *>(no_blank_labels_host),
|
||||
reinterpret_cast<int *>(label_lengths_host), reinterpret_cast<int *>(input_lengths_host),
|
||||
CUDNN_CTC_LOSS_ALGO_DETERMINISTIC, ctcloss_desc_, &workspace_size),
|
||||
"cudnnGetCTCLossWorkspaceSize failed.");
|
||||
void *workspace = device::gpu::GPUMemoryAllocator::GetInstance().AllocTensorMem(workspace_size);
|
||||
if (workspace == nullptr) {
|
||||
MS_LOG(EXCEPTION) << "Failed to alloc workspace, size: " << workspace_size;
|
||||
}
|
||||
|
||||
CHECK_CUDNN_RET_WITH_EXCEPT(
|
||||
cudnnCTCLoss(cudnn_handle_, probs_desc_, probs, reinterpret_cast<int *>(no_blank_labels_host),
|
||||
reinterpret_cast<int *>(label_lengths_host), reinterpret_cast<int *>(input_lengths_host), costs,
|
||||
probs_desc_, grads, CUDNN_CTC_LOSS_ALGO_DETERMINISTIC, ctcloss_desc_, workspace, workspace_size),
|
||||
"cudnnCtcLoss failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaStreamSynchronize(stream), "cudaStreamSynchronize failed.");
|
||||
|
||||
device::gpu::GPUMemoryAllocator::GetInstance().FreeTensorMem(workspace);
|
||||
FreeHostMem(labels_host, no_blank_labels_host, input_lengths_host, label_lengths_host);
|
||||
return true;
|
||||
}
|
||||
bool Init(const CNodePtr &kernel_node) override {
|
||||
InitResource();
|
||||
auto probs_shape = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 0);
|
||||
if (probs_shape.size() != 3) {
|
||||
MS_LOG(EXCEPTION) << "probs dims: " << probs_shape.size() << " not support.";
|
||||
}
|
||||
probs_dims_[0] = probs_shape[0];
|
||||
probs_dims_[1] = probs_shape[1];
|
||||
probs_dims_[2] = probs_shape[2];
|
||||
|
||||
auto labels_dims = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 1);
|
||||
if (labels_dims.size() != 1 && labels_dims.size() != 2) {
|
||||
MS_LOG(EXCEPTION) << "labels dims: " << labels_dims.size() << " not support.";
|
||||
}
|
||||
label_size_ = sizeof(int);
|
||||
for (auto i : labels_dims) {
|
||||
label_size_ *= i;
|
||||
}
|
||||
|
||||
auto input_length_dims = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 2);
|
||||
input_lengths_size_ = input_length_dims[0] * sizeof(int);
|
||||
auto label_length_dims = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 3);
|
||||
label_lengths_size_ = label_length_dims[0] * sizeof(int);
|
||||
CHECK_CUDNN_RET_WITH_EXCEPT(
|
||||
cudnnSetTensorNdDescriptorEx(probs_desc_, CUDNN_TENSOR_NCHW, CUDNN_DATA_FLOAT, 3, probs_dims_),
|
||||
"cudnnSetTensorNdDescriptorEx failed.");
|
||||
CHECK_CUDNN_RET_WITH_EXCEPT(cudnnSetCTCLossDescriptorEx(ctcloss_desc_, CUDNN_DATA_FLOAT,
|
||||
CUDNN_LOSS_NORMALIZATION_SOFTMAX, CUDNN_PROPAGATE_NAN),
|
||||
"cudnnSetCTCLossDescriptorEx failed.");
|
||||
InitSizeLists();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void InitResource() override {
|
||||
cudnn_handle_ = device::gpu::GPUDeviceManager::GetInstance().GetCudnnHandle();
|
||||
CHECK_CUDNN_RET_WITH_EXCEPT(cudnnCreateTensorDescriptor(&probs_desc_), "cudnnCreateTensorDescriptor failed.");
|
||||
CHECK_CUDNN_RET_WITH_EXCEPT(cudnnCreateCTCLossDescriptor(&ctcloss_desc_), "cudnnCreateCTCLossDescriptor failed.");
|
||||
}
|
||||
|
||||
void InitSizeLists() override {
|
||||
input_size_list_.push_back(probs_dims_[0] * probs_dims_[1] * probs_dims_[2] * sizeof(float));
|
||||
input_size_list_.push_back(label_size_);
|
||||
input_size_list_.push_back(input_lengths_size_);
|
||||
input_size_list_.push_back(label_lengths_size_);
|
||||
|
||||
output_size_list_.push_back(probs_dims_[1] * sizeof(float));
|
||||
output_size_list_.push_back(probs_dims_[0] * probs_dims_[1] * probs_dims_[2] * sizeof(float));
|
||||
}
|
||||
|
||||
private:
|
||||
void DestroyResource() noexcept {
|
||||
CHECK_CUDNN_RET_WITH_ERROR(cudnnDestroyCTCLossDescriptor(ctcloss_desc_), "cudnnDestroyCTCLossDescriptor failed.");
|
||||
CHECK_CUDNN_RET_WITH_ERROR(cudnnDestroyTensorDescriptor(probs_desc_), "cudnnDestroyTensorDescriptor failed.");
|
||||
}
|
||||
|
||||
void AllocHostMem(int **labels_host, int **no_blank_labels_host, void **input_lengths_host, void **label_lengths_host,
|
||||
const std::vector<AddressPtr> &inputs) {
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaMallocHost(labels_host, inputs[1]->size), "cudaMallocHost failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaMallocHost(no_blank_labels_host, inputs[1]->size), "cudaMallocHost failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaMallocHost(input_lengths_host, inputs[2]->size), "cudaMallocHost failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaMallocHost(label_lengths_host, inputs[3]->size), "cudaMallocHost failed.");
|
||||
}
|
||||
|
||||
void FreeHostMem(int *labels_host, int *no_blank_labels_host, void *input_lengths_host, void *label_lengths_host) {
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaFreeHost(label_lengths_host), "cudaFreeHost failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaFreeHost(input_lengths_host), "cudaFreeHost failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaFreeHost(labels_host), "cudaFreeHost failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaFreeHost(no_blank_labels_host), "cudaFreeHost failed.");
|
||||
}
|
||||
|
||||
void CopyToHostSync(int *labels_host, int *no_blank_labels_host, void *input_lengths_host, void *label_lengths_host,
|
||||
const std::vector<AddressPtr> &inputs, cudaStream_t stream) {
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaStreamSynchronize(stream), "cudaStreamSynchronize failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(
|
||||
cudaMemcpyAsync(labels_host, inputs[1]->addr, inputs[1]->size, cudaMemcpyDeviceToHost, stream),
|
||||
"cudaMemcpyAsync failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(
|
||||
cudaMemcpyAsync(input_lengths_host, inputs[2]->addr, inputs[2]->size, cudaMemcpyDeviceToHost, stream),
|
||||
"cudaMemcpyAsync failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(
|
||||
cudaMemcpyAsync(label_lengths_host, inputs[3]->addr, inputs[3]->size, cudaMemcpyDeviceToHost, stream),
|
||||
"cudaMemcpyAsync failed.");
|
||||
CHECK_CUDA_RET_WITH_EXCEPT(cudaStreamSynchronize(stream), "cudaStreamSynchronize failed.");
|
||||
|
||||
// remove blank element
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < inputs[1]->size / sizeof(int); i++) {
|
||||
if (labels_host[i] != 0) {
|
||||
no_blank_labels_host[j] = labels_host[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<size_t> input_size_list_;
|
||||
std::vector<size_t> output_size_list_;
|
||||
std::vector<size_t> workspace_size_list_;
|
||||
|
||||
cudnnHandle_t cudnn_handle_;
|
||||
cudnnTensorDescriptor_t probs_desc_;
|
||||
cudnnCTCLossDescriptor_t ctcloss_desc_;
|
||||
int probs_dims_[3] = {0};
|
||||
int label_size_;
|
||||
int input_lengths_size_;
|
||||
int label_lengths_size_;
|
||||
};
|
||||
} // namespace kernel
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_GPU_NN_CTCLOSS_GPU_KERNEL_H_
|
|
@ -987,19 +987,6 @@ def get_bprop_ctc_loss(self):
|
|||
return bprop
|
||||
|
||||
|
||||
@bprop_getters.register(P.CTCLossV2)
|
||||
def get_bprop_ctc_loss_v2(self):
|
||||
"""Grad definition for `CTCLossV2` operation"""
|
||||
expand = P.ExpandDims()
|
||||
|
||||
def bprop(inputs, labels, input_lengths, labels_lengths, out, dout):
|
||||
grad_loss = out[1]
|
||||
grad = grad_loss * expand(dout[0], -1)
|
||||
return grad, zeros_like(labels), zeros_like(input_lengths), zeros_like(labels_lengths)
|
||||
|
||||
return bprop
|
||||
|
||||
|
||||
@bprop_getters.register(P.BasicLSTMCell)
|
||||
def get_bprop_basic_lstm_cell(self):
|
||||
"""Grad definition for `BasicLSTMCell` operation."""
|
||||
|
|
|
@ -64,7 +64,7 @@ from .nn_ops import (LSTM, SGD, Adam, FusedSparseAdam, FusedSparseLazyAdam, Appl
|
|||
DropoutDoMask, Dropout,
|
||||
DropoutGenMask, Flatten, FusedBatchNorm, FusedBatchNormEx, BNTrainingReduce, BNTrainingUpdate,
|
||||
Gelu, Elu,
|
||||
GetNext, L2Normalize, LayerNorm, L2Loss, CTCLoss, CTCLossV2, CTCGreedyDecoder,
|
||||
GetNext, L2Normalize, LayerNorm, L2Loss, CTCLoss, CTCGreedyDecoder,
|
||||
LogSoftmax,
|
||||
MaxPool, DataFormatDimMap,
|
||||
AvgPool, Conv2DBackpropInput,
|
||||
|
|
|
@ -5605,57 +5605,3 @@ class LRN(PrimitiveWithInfer):
|
|||
def infer_shape(self, x_shape):
|
||||
validator.check_integer("x_shape", len(x_shape), 4, Rel.EQ, self.name)
|
||||
return x_shape
|
||||
|
||||
|
||||
class CTCLossV2(PrimitiveWithInfer):
|
||||
r"""
|
||||
Calculates the CTC (Connectionist Temporal Classification) loss and the gradient.
|
||||
Note:
|
||||
- Cudnn Uses label value of for the `blank`
|
||||
|
||||
Inputs:
|
||||
- **inputs** (Tensor) - The input Tensor must be a `3-D` tensor whose shape is
|
||||
:math:`(max_time, batch_size, num_class)`. `num_class` must be `num_labels + 1` classes, `num_labels`
|
||||
indicates the number of actual labels. Blank labels are reserved.
|
||||
- **labels** (Tensor) - The labels Tensor must be a `1-D` tensor whose shape is
|
||||
:math:`(\sigma{label_lengths})`
|
||||
or `2-D` tensor whose shape is
|
||||
:math:`(max_time, max{label_lengths})`
|
||||
The type must be int32.
|
||||
- **input_lengths** (Tensor) - A `1-D` input tensor whose shape is
|
||||
:math:`(batch_size,)`. The values must be batch. The type must be int32.
|
||||
- **label_lengths** (Tensor) - A tensor containing sequence lengths with the shape of :math:`(batch_size)`.
|
||||
The type must be int32. Each value in the tensor must not greater than `max_time`.
|
||||
|
||||
Outputs:
|
||||
- **loss** (Tensor) - A tensor containing log-probabilities, the shape is :math:`(batch_size)`, has the same
|
||||
type with `inputs`.
|
||||
- **gradient** (Tensor) - The gradient of `loss`, has the same type and shape with `inputs`.
|
||||
|
||||
Examples:
|
||||
>>> inputs = Tensor(np.random.random((2, 2, 3)), mindspore.float32)
|
||||
>>> labels = Tensor(np.array([[0, 0], [1, 0]]), mindspore.int32)
|
||||
>>> input_lengths = Tensor(np.array([3, 3, 3]), mindspore.int32)
|
||||
>>> label_lengths = Tensor(np.array([3, 3, 3]), mindspore.int32)
|
||||
>>> ctc_loss = P.CTCLossV2()
|
||||
>>> output = ctc_loss(inputs, labels, input_lengths, label_lengths)
|
||||
"""
|
||||
@prim_attr_register
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def infer_dtype(self, input_dtype, labels_dtype, input_lengths_dtype, label_lengths_dtype):
|
||||
validator.check_tensor_type_same({"input": input_dtype}, (mstype.float32,), self.name)
|
||||
validator.check_tensor_type_same({"labels": labels_dtype}, (mstype.int32,), self.name)
|
||||
validator.check_tensor_type_same({"input_lengths": input_lengths_dtype}, (mstype.int32,), self.name)
|
||||
validator.check_tensor_type_same({"target_lengths": label_lengths_dtype}, (mstype.int32,), self.name)
|
||||
return mstype.float32, mstype.float32
|
||||
|
||||
def infer_shape(self, input_shape, labels_shape, input_lengths_shape, label_lengths_shape):
|
||||
validator.check_integer("input shape", len(input_shape), 3, Rel.EQ, self.name)
|
||||
validator.check_number_range("labels shape", len(labels_shape), 1, 2, Rel.INC_BOTH, self.name)
|
||||
validator.check_integer("input lengths shape", len(input_lengths_shape), 1, Rel.EQ, self.name)
|
||||
validator.check_integer("label lengths shape", len(label_lengths_shape), 1, Rel.EQ, self.name)
|
||||
validator.check_integer("input[1]", input_shape[1], input_lengths_shape[0], Rel.EQ, self.name)
|
||||
validator.check_integer("input[1]", input_shape[1], label_lengths_shape[0], Rel.EQ, self.name)
|
||||
return (input_shape[1],), input_shape
|
||||
|
|
|
@ -21,7 +21,7 @@ from mindspore.common import set_seed
|
|||
from mindspore.train.model import Model
|
||||
from mindspore.train.serialization import load_checkpoint, load_param_into_net
|
||||
|
||||
from src.loss import CTCLoss, CTCLossV2
|
||||
from src.loss import CTCLoss
|
||||
from src.config import config as cf
|
||||
from src.dataset import create_dataset
|
||||
from src.warpctc import StackedRNN, StackedRNNForGPU
|
||||
|
@ -49,13 +49,12 @@ if __name__ == '__main__':
|
|||
batch_size=cf.batch_size,
|
||||
device_target=args_opt.platform)
|
||||
step_size = dataset.get_dataset_size()
|
||||
loss = CTCLoss(max_sequence_length=cf.captcha_width,
|
||||
max_label_length=max_captcha_digits,
|
||||
batch_size=cf.batch_size)
|
||||
if args_opt.platform == 'Ascend':
|
||||
loss = CTCLoss(max_sequence_length=cf.captcha_width,
|
||||
max_label_length=max_captcha_digits,
|
||||
batch_size=cf.batch_size)
|
||||
net = StackedRNN(input_size=input_size, batch_size=cf.batch_size, hidden_size=cf.hidden_size)
|
||||
else:
|
||||
loss = CTCLossV2(max_sequence_length=cf.captcha_width, batch_size=cf.batch_size)
|
||||
net = StackedRNNForGPU(input_size=input_size, batch_size=cf.batch_size, hidden_size=cf.hidden_size)
|
||||
|
||||
# load checkpoint
|
||||
|
|
|
@ -41,7 +41,7 @@ class _CaptchaDataset:
|
|||
self.img_names = [i for i in os.listdir(img_root_dir) if i.endswith('.png')]
|
||||
self.max_captcha_digits = max_captcha_digits
|
||||
self.target = device_target
|
||||
self.blank = 10 if self.target == 'Ascend' else 0
|
||||
self.blank = 10
|
||||
self.label_length = [len(os.path.splitext(n)[0].split('-')[-1]) for n in self.img_names]
|
||||
|
||||
def __len__(self):
|
||||
|
@ -55,14 +55,8 @@ class _CaptchaDataset:
|
|||
image = np.array(im)
|
||||
label_str = os.path.splitext(img_name)[0]
|
||||
label_str = label_str[label_str.find('-') + 1:]
|
||||
if self.target == 'Ascend':
|
||||
label = [int(i) for i in label_str]
|
||||
label.extend([int(self.blank)] * (self.max_captcha_digits - len(label)))
|
||||
else:
|
||||
label = [int(i) + 1 for i in label_str]
|
||||
length = len(label)
|
||||
label.extend([int(self.blank)] * (self.max_captcha_digits - len(label)))
|
||||
label.append(length)
|
||||
label = [int(i) for i in label_str]
|
||||
label.extend([int(self.blank)] * (self.max_captcha_digits - len(label)))
|
||||
label = np.array(label)
|
||||
return image, label
|
||||
|
||||
|
|
|
@ -47,25 +47,3 @@ class CTCLoss(_Loss):
|
|||
labels_values = self.reshape(label, (-1,))
|
||||
loss, _ = self.ctc_loss(logit, self.labels_indices, labels_values, self.sequence_length)
|
||||
return loss
|
||||
|
||||
|
||||
class CTCLossV2(_Loss):
|
||||
"""
|
||||
CTCLoss definition
|
||||
|
||||
Args:
|
||||
max_sequence_length(int): max number of sequence length. For captcha images, the value is equal to image width
|
||||
batch_size(int): batch size of input logits
|
||||
"""
|
||||
|
||||
def __init__(self, max_sequence_length, batch_size):
|
||||
super(CTCLossV2, self).__init__()
|
||||
self.input_length = Tensor(np.array([max_sequence_length] * batch_size), mstype.int32)
|
||||
self.reshape = P.Reshape()
|
||||
self.ctc_loss = P.CTCLossV2()
|
||||
|
||||
def construct(self, logit, label):
|
||||
labels_values = label[:, :-1]
|
||||
labels_length = label[:, -1]
|
||||
loss, _ = self.ctc_loss(logit, labels_values, self.input_length, labels_length)
|
||||
return loss
|
||||
|
|
|
@ -27,7 +27,7 @@ class WarpCTCAccuracy(nn.Metric):
|
|||
self._total_num = 0
|
||||
self._count = 0
|
||||
self.device_target = device_target
|
||||
self.blank = 10 if device_target == 'Ascend' else 0
|
||||
self.blank = 10
|
||||
|
||||
def clear(self):
|
||||
self._correct_num = 0
|
||||
|
|
|
@ -25,7 +25,7 @@ from mindspore.nn.wrap import WithLossCell
|
|||
from mindspore.train.callback import TimeMonitor, LossMonitor, CheckpointConfig, ModelCheckpoint
|
||||
from mindspore.communication.management import init, get_group_size, get_rank
|
||||
|
||||
from src.loss import CTCLoss, CTCLossV2
|
||||
from src.loss import CTCLoss
|
||||
from src.config import config as cf
|
||||
from src.dataset import create_dataset
|
||||
from src.warpctc import StackedRNN, StackedRNNForGPU
|
||||
|
@ -58,7 +58,7 @@ if __name__ == '__main__':
|
|||
rank = int(os.environ.get("RANK_ID"))
|
||||
else:
|
||||
init()
|
||||
lr_scale = 0.5
|
||||
lr_scale = 1
|
||||
device_num = get_group_size()
|
||||
rank = get_rank()
|
||||
context.reset_auto_parallel_context()
|
||||
|
@ -78,16 +78,14 @@ if __name__ == '__main__':
|
|||
# define lr
|
||||
lr_init = cf.learning_rate if not args_opt.run_distribute else cf.learning_rate * device_num * lr_scale
|
||||
lr = get_lr(cf.epoch_size, step_size, lr_init)
|
||||
loss = CTCLoss(max_sequence_length=cf.captcha_width,
|
||||
max_label_length=max_captcha_digits,
|
||||
batch_size=cf.batch_size)
|
||||
if args_opt.platform == 'Ascend':
|
||||
loss = CTCLoss(max_sequence_length=cf.captcha_width,
|
||||
max_label_length=max_captcha_digits,
|
||||
batch_size=cf.batch_size)
|
||||
net = StackedRNN(input_size=input_size, batch_size=cf.batch_size, hidden_size=cf.hidden_size)
|
||||
opt = nn.SGD(params=net.trainable_params(), learning_rate=lr, momentum=cf.momentum)
|
||||
else:
|
||||
loss = CTCLossV2(max_sequence_length=cf.captcha_width, batch_size=cf.batch_size)
|
||||
net = StackedRNNForGPU(input_size=input_size, batch_size=cf.batch_size, hidden_size=cf.hidden_size)
|
||||
opt = nn.Momentum(params=net.trainable_params(), learning_rate=lr, momentum=cf.momentum)
|
||||
opt = nn.SGD(params=net.trainable_params(), learning_rate=lr, momentum=cf.momentum)
|
||||
|
||||
net = WithLossCell(net, loss)
|
||||
net = TrainOneStepCellWithGradClip(net, opt).set_train()
|
||||
|
|
|
@ -23,28 +23,28 @@ from mindspore.ops import operations as P
|
|||
from mindspore.common import dtype as mstype
|
||||
from mindspore.ops.composite import GradOperation
|
||||
|
||||
|
||||
class Net(nn.Cell):
|
||||
def __init__(self):
|
||||
super(Net, self).__init__()
|
||||
self.loss = P.CTCLossV2()
|
||||
self.loss = P.CTCLoss()
|
||||
self.div = P.RealDiv()
|
||||
self.cast = P.Cast()
|
||||
self.mean = P.ReduceMean()
|
||||
|
||||
def construct(self, probs, label, input_length, label_length):
|
||||
x, _ = self.loss(probs, label, input_length, label_length)
|
||||
x = self.div(x, self.cast(label_length, mstype.float32))
|
||||
def construct(self, probs, label, input_length, indices):
|
||||
x, _ = self.loss(probs, indices, label, input_length)
|
||||
x = self.mean(x)
|
||||
return x
|
||||
|
||||
|
||||
class GradData(nn.Cell):
|
||||
def __init__(self, network):
|
||||
super(GradData, self).__init__()
|
||||
self.grad = GradOperation(get_all=True, sens_param=False)
|
||||
self.network = network
|
||||
|
||||
def construct(self, probs, labels, input_lengths, label_lengths):
|
||||
return self.grad(self.network)(probs, labels, input_lengths, label_lengths)
|
||||
def construct(self, probs, indices, labels, input_lengths):
|
||||
return self.grad(self.network)(probs, indices, labels, input_lengths)
|
||||
|
||||
|
||||
@pytest.mark.level0
|
||||
|
@ -71,49 +71,18 @@ def test_ctcloss():
|
|||
[-3.3031, -3.0087, -1.9982, -1.9081, -3.8731, -2.8764, -2.2485, -2.3808, -1.4283, -2.1625],
|
||||
[-2.4516, -3.2394, -4.2053, -4.3541, -2.5229, -4.0717, -1.4894, -2.3151, -1.1098, -2.3465]]],
|
||||
dtype=mstype.float32)
|
||||
labels = Tensor([9, 4, 6, 4, 7, 1, 4, 6, 6, 8], dtype=mstype.int32)
|
||||
labels = Tensor([3, 4, 6, 4, 7, 1, 4, 6, 6, 8], dtype=mstype.int32)
|
||||
indices = [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2], [2, 3]]
|
||||
indices = Tensor(indices, dtype=mstype.int64)
|
||||
input_lengths = Tensor([5, 5, 5], dtype=mstype.int32)
|
||||
label_lengths = Tensor([3, 3, 4], dtype=mstype.int32)
|
||||
|
||||
context.set_context(mode=context.GRAPH_MODE, device_target="GPU")
|
||||
net = Net()
|
||||
ctc_loss = net(probs, labels, input_lengths, label_lengths)
|
||||
expect_loss = [2.4099]
|
||||
ctc_loss = net(probs, labels, input_lengths, indices)
|
||||
expect_loss = [9.083767]
|
||||
assert np.allclose(ctc_loss.asnumpy(), expect_loss)
|
||||
|
||||
grad = GradData(net)(probs, labels, input_lengths, label_lengths)
|
||||
expect_grad = [[[8.8442e-05, 1.1065e-03, 3.5867e-03, 2.1896e-03, 6.1646e-03,
|
||||
3.6738e-03, 1.6262e-03, 3.5610e-02, 9.1258e-05, -5.4134e-02],
|
||||
[-3.7523e-03, 3.9386e-03, 7.9623e-04, 3.1132e-02, -6.2954e-02,
|
||||
9.4143e-03, 7.6425e-03, 1.7902e-03, 7.4211e-03, 4.5719e-03],
|
||||
[6.7778e-03, 1.6178e-02, 1.0344e-02, 1.5173e-03, -6.5840e-02,
|
||||
8.1707e-03, 6.9674e-03, 4.1814e-03, 3.6026e-03, 8.0991e-03]],
|
||||
|
||||
[[-1.2581e-02, 3.1057e-03, 4.9517e-03, 1.3301e-03, -2.6320e-02,
|
||||
1.5568e-02, 1.4305e-02, 9.6671e-03, 1.7262e-02, -2.7292e-02],
|
||||
[-1.5566e-02, 3.3126e-03, 2.6887e-02, 6.2993e-03, -3.9716e-02,
|
||||
1.1420e-02, 7.4531e-03, -1.4252e-02, 8.5603e-03, 5.6048e-03],
|
||||
[3.3483e-03, 2.0579e-02, 3.7231e-03, 1.5832e-03, 2.4837e-03,
|
||||
3.2909e-03, -7.7267e-02, 1.3861e-02, 1.3558e-02, 1.4840e-02]],
|
||||
|
||||
[[-8.0007e-03, 1.2751e-02, 4.3901e-02, 5.8435e-03, -7.2627e-02,
|
||||
1.4647e-02, -8.0584e-03, 4.4595e-03, 6.5557e-03, 5.2891e-04],
|
||||
[-3.6006e-02, 1.5308e-03, 9.3225e-03, 1.0969e-03, -2.5098e-03,
|
||||
2.0260e-02, 2.3419e-02, -3.0053e-02, 1.8809e-03, 1.1059e-02],
|
||||
[-7.7639e-02, 1.8533e-02, 2.0764e-03, 5.9706e-03, 5.6150e-03,
|
||||
5.6868e-03, 5.2854e-03, 9.8085e-03, 2.0360e-02, 4.3053e-03]],
|
||||
|
||||
[[-2.6776e-02, 1.1113e-02, 3.8314e-03, 3.9986e-02, -1.6020e-02,
|
||||
1.1579e-02, -4.1635e-02, 5.5992e-03, 2.7429e-03, 9.5786e-03],
|
||||
[-6.8619e-03, -6.4066e-03, 1.0888e-02, 1.4201e-02, 1.4413e-03,
|
||||
1.3225e-02, 8.0039e-03, -4.9191e-02, 5.6352e-03, 9.0651e-03],
|
||||
[5.1026e-03, 1.9343e-03, 3.2506e-03, 1.0347e-03, 2.9837e-02,
|
||||
1.7121e-03, -5.9261e-02, 9.1443e-04, 8.3608e-03, 7.1146e-03]],
|
||||
|
||||
[[-2.0848e-02, 7.0754e-03, 2.7633e-03, 2.4447e-03, 3.1520e-02,
|
||||
7.5401e-03, -5.8895e-02, 8.9559e-04, 5.7796e-03, 2.1724e-02],
|
||||
[-1.3499e-03, -1.0019e-01, 1.5064e-02, 1.6485e-02, 2.3104e-03,
|
||||
6.2597e-03, 1.1729e-02, 1.0275e-02, 2.6635e-02, 1.2782e-02],
|
||||
[7.1796e-03, 3.2656e-03, 1.2430e-03, 1.0712e-03, 6.6856e-03,
|
||||
1.4207e-03, 1.8792e-02, 8.2297e-03, -5.5865e-02, 7.9753e-03]]]
|
||||
assert np.allclose(grad[0].asnumpy(), expect_grad, atol=1e-5)
|
||||
grad = GradData(net)(probs, labels, input_lengths, indices)
|
||||
grad = P.ReduceMean()(grad[0])
|
||||
expect_grad = [-5.9604646e-09]
|
||||
assert np.allclose(grad.asnumpy(), expect_grad, atol=1e-5)
|
||||
|
|
Loading…
Reference in New Issue