You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

SoftmaxCrossEntropy.py 3.4 kB

4 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. from __future__ import absolute_import
  2. import numpy as np
  3. from .Node import Op
  4. from .._base import DNNL_LIB
  5. from ..cpu_links import softmax_crossentropy
  6. from .Softmax import softmax_func
  7. from ..gpu_links import CuDNN_softmax_cross_entropy
  8. from ..gpu_links import softmax_cross_entropy
  9. from ..gpu_links import CuDNN_softmax_cross_entropy_gradient
  10. from ..gpu_links import softmax_cross_entropy_gradient
  11. class SoftmaxCrossEntropyOp(Op):
  12. def __init__(self, node_A, node_B, use_cudnn=True, ctx=None):
  13. super().__init__(SoftmaxCrossEntropyOp, [node_A, node_B], ctx)
  14. self.use_cudnn = use_cudnn
  15. def compute(self, input_vals, output_val, stream_handle=None):
  16. y = input_vals[0]
  17. y_ = input_vals[1]
  18. if self.on_cpu:
  19. if DNNL_LIB['DnnlSoftmaxCrossEntropy']:
  20. softmax_crossentropy(y, y_, output_val)
  21. else:
  22. softmax = softmax_func(y.asnumpy())
  23. output_val[:] = -np.sum(y_.asnumpy() * np.log(softmax), axis=1)
  24. else:
  25. if self.use_cudnn:
  26. CuDNN_softmax_cross_entropy(y, y_, output_val, stream_handle)
  27. else:
  28. softmax_cross_entropy(y, y_, output_val, stream_handle)
  29. def gradient(self, output_grad):
  30. from .Softmax import softmax_op
  31. grad_A = softmaxcrossentropy_gradient_op(
  32. self.inputs[0], self.inputs[1], output_grad, use_cudnn=self.use_cudnn, ctx=self.raw_ctx)
  33. return [grad_A, None]
  34. def infer_shape(self, input_shapes):
  35. assert len(input_shapes) == 2
  36. assert len(input_shapes[0]) >= 2
  37. return input_shapes[0][:-1]
  38. class SoftmaxCrossEntropyGradientOp(Op):
  39. def __init__(self, node_A, node_B, node_C, use_cudnn=True, ctx=None):
  40. super().__init__(SoftmaxCrossEntropyGradientOp,
  41. [node_A, node_B, node_C], ctx)
  42. self.use_cudnn = use_cudnn
  43. def compute(self, input_vals, output_val, stream_handle=None):
  44. if self.on_cpu:
  45. if DNNL_LIB['DnnlSoftmaxCrossEntropy_Gradient']:
  46. print('No support for DnnlSoftmaxCrossEntropy_gradient')
  47. else:
  48. output_val[:] = (softmax_func(input_vals[0].asnumpy(
  49. )) + -1 * input_vals[1].asnumpy()) * np.expand_dims(input_vals[2].asnumpy(), -1)
  50. else:
  51. if self.use_cudnn:
  52. CuDNN_softmax_cross_entropy_gradient(
  53. input_vals[2], input_vals[0], input_vals[1], output_val, stream_handle)
  54. else:
  55. softmax_cross_entropy_gradient(
  56. input_vals[0], input_vals[1], input_vals[2], output_val, stream_handle)
  57. def gradient(self, output_grad):
  58. raise NotImplementedError
  59. def infer_shape(self, input_shapes):
  60. assert len(input_shapes) == 3
  61. return input_shapes[0]
  62. def softmaxcrossentropy_op(node_A, node_B, use_cudnn=True, ctx=None):
  63. """Computes cross entropy loss for pre-softmax activations.
  64. Parameters:
  65. ----
  66. node_A : Node
  67. Predicted probability.
  68. node_B : Node
  69. Labels.
  70. Returns:
  71. ----
  72. A new Node instance created by Op.
  73. """
  74. return SoftmaxCrossEntropyOp(node_A, node_B, use_cudnn=use_cudnn, ctx=ctx)
  75. def softmaxcrossentropy_gradient_op(node_A, node_B, node_C, use_cudnn=True, ctx=None):
  76. return SoftmaxCrossEntropyGradientOp(node_A, node_B, node_C, use_cudnn=use_cudnn, ctx=ctx)