| 619 | |
| 620 | template<OptimizerType optimizer_type> |
| 621 | __host__ __device__ |
| 622 | static void backward(Vector &head, Vector &tail, Vector &relation, |
| 623 | float l3_regularization, Float gradient, const Optimizer &optimizer, |
| 624 | float relation_lr_multiplier = 1, Float weight = 1) { |
| 625 | auto update = get_update_function<Float, optimizer_type>(); |
| 626 | l3_regularization *= 3; |
| 627 | FOR(i, dim / 4) { |
| 628 | Float h_r = head[i * 4]; |
| 629 | Float h_i = head[i * 4 + 1]; |
| 630 | Float h_j = head[i * 4 + 2]; |
| 631 | Float h_k = head[i * 4 + 3]; |
| 632 | Float r_r = relation[i * 4]; |
| 633 | Float r_i = relation[i * 4 + 1]; |
| 634 | Float r_j = relation[i * 4 + 2]; |
| 635 | Float r_k = relation[i * 4 + 3]; |
| 636 | Float t_r = tail[i * 4]; |
| 637 | Float t_i = tail[i * 4 + 1]; |
| 638 | Float t_j = tail[i * 4 + 2]; |
| 639 | Float t_k = tail[i * 4 + 3]; |
| 640 | Float r_norm = sqrt(r_r * r_r + r_i * r_i + r_j * r_j + r_k * r_k); |
| 641 | Float grad = gradient / (r_norm + kEpsilon); |
| 642 | // head |
| 643 | Float h_r_grad = grad * (r_r * t_r + r_i * t_i + r_j * t_j + r_k * t_k); |
| 644 | Float h_i_grad = grad * (-r_i * t_r + r_r * t_i - r_k * t_j + r_j * t_k); |
| 645 | Float h_j_grad = grad * (-r_j * t_r + r_k * t_i + r_r * t_j - r_i * t_k); |
| 646 | Float h_k_grad = grad * (-r_k * t_r - r_j * t_i + r_i * t_j + r_r * t_k); |
| 647 | head[i * 4] -= (optimizer.*update)(h_r, h_r_grad + l3_regularization * abs(h_r) * h_r, weight); |
| 648 | head[i * 4 + 1] -= (optimizer.*update)(h_i, h_i_grad + l3_regularization * abs(h_i) * h_i, weight); |
| 649 | head[i * 4 + 2] -= (optimizer.*update)(h_j, h_j_grad + l3_regularization * abs(h_j) * h_j, weight); |
| 650 | head[i * 4 + 3] -= (optimizer.*update)(h_k, h_k_grad + l3_regularization * abs(h_k) * h_k, weight); |
| 651 | // tail |
| 652 | Float t_r_grad = grad * (h_r * r_r - h_i * r_i - h_j * r_j - h_k * r_k); |
| 653 | Float t_i_grad = grad * (h_r * r_i + h_i * r_r + h_j * r_k - h_k * r_j); |
| 654 | Float t_j_grad = grad * (h_r * r_j - h_i * r_k + h_j * r_r + h_k * r_i); |
| 655 | Float t_k_grad = grad * (h_r * r_k + h_i * r_j - h_j * r_i + h_k * r_r); |
| 656 | tail[i * 4] -= (optimizer.*update)(t_r, t_r_grad + l3_regularization * abs(t_r) * t_r, weight); |
| 657 | tail[i * 4 + 1] -= (optimizer.*update)(t_i, t_i_grad + l3_regularization * abs(t_i) * t_i, weight); |
| 658 | tail[i * 4 + 2] -= (optimizer.*update)(t_j, t_j_grad + l3_regularization * abs(t_j) * t_j, weight); |
| 659 | tail[i * 4 + 3] -= (optimizer.*update)(t_k, t_k_grad + l3_regularization * abs(t_k) * t_k, weight); |
| 660 | // relation |
| 661 | Float r_r_grad = grad * (h_r * t_r + h_i * t_i + h_j * t_j + h_k * t_k); |
| 662 | Float r_i_grad = grad * (-h_i * t_r + h_r * t_i + h_k * t_j - h_j * t_k); |
| 663 | Float r_j_grad = grad * (-h_j * t_r - h_k * t_i + h_r * t_j + h_i * t_k); |
| 664 | Float r_k_grad = grad * (-h_k * t_r + h_j * t_i - h_i * t_j + h_r * t_k); |
| 665 | relation[i * 4] -= relation_lr_multiplier * |
| 666 | (optimizer.*update)(r_r, r_r_grad + l3_regularization * abs(r_r) * r_r, weight); |
| 667 | relation[i * 4 + 1] -= relation_lr_multiplier * |
| 668 | (optimizer.*update)(r_i, r_i_grad + l3_regularization * abs(r_i) * r_i, weight); |
| 669 | relation[i * 4 + 2] -= relation_lr_multiplier * |
| 670 | (optimizer.*update)(r_j, r_j_grad + l3_regularization * abs(r_j) * r_j, weight); |
| 671 | relation[i * 4 + 3] -= relation_lr_multiplier * |
| 672 | (optimizer.*update)(r_k, r_k_grad + l3_regularization * abs(r_k) * r_k, weight); |
| 673 | } |
| 674 | } |
| 675 | |
| 676 | template<OptimizerType optimizer_type> |
| 677 | __host__ __device__ |
nothing calls this directly
no outgoing calls
no test coverage detected