Init an embedding operator
| 5646 | |
| 5647 | |
| 5648 | class Embedding(Operator): |
| 5649 | """ |
| 5650 | Init an embedding operator |
| 5651 | """ |
| 5652 | |
| 5653 | def __init__(self): |
| 5654 | super(Embedding, self).__init__() |
| 5655 | |
| 5656 | def forward(self, x, w): |
| 5657 | """ |
| 5658 | forward of embedding |
| 5659 | Args: |
| 5660 | x (CTensor): input tensor. |
| 5661 | w (CTensor): weight tensor. |
| 5662 | Returns: |
| 5663 | the output CTensor. |
| 5664 | """ |
| 5665 | x = tensor.to_numpy(tensor.from_raw_tensor(x)) |
| 5666 | if training: |
| 5667 | self.cache = (x, w.shape()) |
| 5668 | |
| 5669 | xs = [] |
| 5670 | x = x.tolist() |
| 5671 | for indice in x: |
| 5672 | sub_xs = [] |
| 5673 | for idx in indice: |
| 5674 | idx = int(idx) |
| 5675 | tmp_tensor = singa.SliceOn(w, idx, idx + 1, 0) |
| 5676 | sub_xs.append(tmp_tensor) |
| 5677 | sub_xs = singa.VecTensor(sub_xs) |
| 5678 | tmp_tensor = singa.ConcatOn(sub_xs, 0) |
| 5679 | tmp_tensor = singa.Reshape(tmp_tensor, |
| 5680 | [1] + list(tmp_tensor.shape())) |
| 5681 | |
| 5682 | xs.append(tmp_tensor) |
| 5683 | xs = singa.VecTensor(xs) |
| 5684 | xs = singa.ConcatOn(xs, 0) |
| 5685 | return xs |
| 5686 | |
| 5687 | def backward(self, dy): |
| 5688 | """ |
| 5689 | backward of embedding |
| 5690 | Args: |
| 5691 | dy (CTensor): gradient tensor. |
| 5692 | Raises: |
| 5693 | the gradient tensor over input tensor. |
| 5694 | """ |
| 5695 | x, w_shape = self.cache |
| 5696 | dy_shape = dy.shape() |
| 5697 | # construct the dx |
| 5698 | dx = tensor.sum(tensor.from_raw_tensor(dy), axis=2) |
| 5699 | |
| 5700 | # construct the dw |
| 5701 | dws = [] |
| 5702 | for idx in range(w_shape[0]): |
| 5703 | tmp_tensor = singa.Tensor((1, w_shape[1]), dy.device()) |
| 5704 | tmp_tensor.SetFloatValue(0.0) |
| 5705 | dws.append(tmp_tensor) |