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.

textcnn.py 5.3 kB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. # Copyright 2020 Huawei Technologies Co., Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # ============================================================================
  15. """TextCNN"""
  16. import numpy as np
  17. import mindspore.nn as nn
  18. import mindspore.ops.operations as P
  19. from mindspore import Tensor
  20. from mindspore.nn.cell import Cell
  21. import mindspore.ops.functional as F
  22. import mindspore
  23. class SoftmaxCrossEntropyExpand(Cell):
  24. r"""
  25. Computes softmax cross entropy between logits and labels. Implemented by expanded formula.
  26. This is a wrapper of several functions.
  27. .. math::
  28. \ell(x_i, t_i) = -log\left(\frac{\exp(x_{t_i})}{\sum_j \exp(x_j)}\right),
  29. where :math:`x_i` is a 1D score Tensor, :math:`t_i` is the target class.
  30. Note:
  31. When argument sparse is set to True, the format of label is the index
  32. range from :math:`0` to :math:`C - 1` instead of one-hot vectors.
  33. Args:
  34. sparse(bool): Specifies whether labels use sparse format or not. Default: False.
  35. Inputs:
  36. - **input_data** (Tensor) - Tensor of shape :math:`(x_1, x_2, ..., x_R)`.
  37. - **label** (Tensor) - Tensor of shape :math:`(y_1, y_2, ..., y_S)`.
  38. Outputs:
  39. Tensor, a scalar tensor including the mean loss.
  40. Examples:
  41. >>> loss = nn.SoftmaxCrossEntropyExpand(sparse=True)
  42. >>> input_data = Tensor(np.ones([64, 512]), dtype=mindspore.float32)
  43. >>> label = Tensor(np.ones([64]), dtype=mindspore.int32)
  44. >>> loss(input_data, label)
  45. """
  46. def __init__(self, sparse=False):
  47. super(SoftmaxCrossEntropyExpand, self).__init__()
  48. self.exp = P.Exp()
  49. self.reduce_sum = P.ReduceSum(keep_dims=True)
  50. self.onehot = P.OneHot()
  51. self.on_value = Tensor(1.0, mindspore.float32)
  52. self.off_value = Tensor(0.0, mindspore.float32)
  53. self.div = P.Div()
  54. self.log = P.Log()
  55. self.sum_cross_entropy = P.ReduceSum(keep_dims=False)
  56. self.mul = P.Mul()
  57. self.mul2 = P.Mul()
  58. self.cast = P.Cast()
  59. self.reduce_mean = P.ReduceMean(keep_dims=False)
  60. self.sparse = sparse
  61. self.reduce_max = P.ReduceMax(keep_dims=True)
  62. self.sub = P.Sub()
  63. def construct(self, logit, label):
  64. """
  65. construct
  66. """
  67. logit_max = self.reduce_max(logit, -1)
  68. exp = self.exp(self.sub(logit, logit_max))
  69. exp_sum = self.reduce_sum(exp, -1)
  70. softmax_result = self.div(exp, exp_sum)
  71. if self.sparse:
  72. label = self.onehot(label, F.shape(logit)[1], self.on_value, self.off_value)
  73. softmax_result_log = self.log(softmax_result)
  74. loss = self.sum_cross_entropy((self.mul(softmax_result_log, label)), -1)
  75. loss = self.mul2(F.scalar_to_array(-1.0), loss)
  76. loss = self.reduce_mean(loss, -1)
  77. return loss
  78. def _weight_variable(shape, factor=0.01):
  79. init_value = np.random.randn(*shape).astype(np.float32) * factor
  80. return Tensor(init_value)
  81. def make_conv_layer(kernel_size):
  82. weight_shape = (96, 1, *kernel_size)
  83. weight = _weight_variable(weight_shape)
  84. return nn.Conv2d(in_channels=1, out_channels=96, kernel_size=kernel_size, padding=1,
  85. pad_mode="pad", weight_init=weight, has_bias=True)
  86. class TextCNN(nn.Cell):
  87. """
  88. TextCNN architecture
  89. """
  90. def __init__(self, vocab_len, word_len, num_classes, vec_length):
  91. super(TextCNN, self).__init__()
  92. self.vec_length = vec_length
  93. self.word_len = word_len
  94. self.num_classes = num_classes
  95. self.unsqueeze = P.ExpandDims()
  96. self.embedding = nn.Embedding(vocab_len, self.vec_length, embedding_table='normal')
  97. self.slice = P.Slice()
  98. self.layer1 = self.make_layer(kernel_height=3)
  99. self.layer2 = self.make_layer(kernel_height=4)
  100. self.layer3 = self.make_layer(kernel_height=5)
  101. self.concat = P.Concat(1)
  102. self.fc = nn.Dense(96*3, self.num_classes)
  103. self.drop = nn.Dropout(keep_prob=0.5)
  104. self.print = P.Print()
  105. self.reducemean = P.ReduceMax(keep_dims=False)
  106. def make_layer(self, kernel_height):
  107. return nn.SequentialCell(
  108. [
  109. make_conv_layer((kernel_height, self.vec_length)), nn.ReLU(),
  110. nn.MaxPool2d(kernel_size=(self.word_len-kernel_height+1, 1)),
  111. ]
  112. )
  113. def construct(self, x):
  114. """
  115. construct
  116. """
  117. x = self.unsqueeze(x, 1)
  118. x = self.embedding(x)
  119. x1 = self.layer1(x)
  120. x2 = self.layer2(x)
  121. x3 = self.layer3(x)
  122. x1 = self.reducemean(x1, (2, 3))
  123. x2 = self.reducemean(x2, (2, 3))
  124. x3 = self.reducemean(x3, (2, 3))
  125. x = self.concat((x1, x2, x3))
  126. x = self.drop(x)
  127. x = self.fc(x)
  128. return x