| 583 | */ |
| 584 | template<class _Vector> |
| 585 | class QuatE { |
| 586 | public: |
| 587 | static_assert(_Vector::dim % 4 == 0, |
| 588 | "Model `QuatE` can only be instantiated with vector dimensions divisible by 4"); |
| 589 | static const size_t dim = _Vector::dim; |
| 590 | typedef _Vector Vector; |
| 591 | typedef typename _Vector::Float Float; |
| 592 | |
| 593 | __host__ __device__ |
| 594 | static void forward(const Vector &head, const Vector &tail, const Vector &relation, Float &output, |
| 595 | float l3_regularization) { |
| 596 | output = 0; |
| 597 | FOR(i, dim / 4) { |
| 598 | Float h_r = head[i * 4]; |
| 599 | Float h_i = head[i * 4 + 1]; |
| 600 | Float h_j = head[i * 4 + 2]; |
| 601 | Float h_k = head[i * 4 + 3]; |
| 602 | Float r_r = relation[i * 4]; |
| 603 | Float r_i = relation[i * 4 + 1]; |
| 604 | Float r_j = relation[i * 4 + 2]; |
| 605 | Float r_k = relation[i * 4 + 3]; |
| 606 | Float t_r = tail[i * 4]; |
| 607 | Float t_i = tail[i * 4 + 1]; |
| 608 | Float t_j = tail[i * 4 + 2]; |
| 609 | Float t_k = tail[i * 4 + 3]; |
| 610 | Float r_norm = sqrt(r_r * r_r + r_i * r_i + r_j * r_j + r_k * r_k); |
| 611 | Float product_r = h_r * r_r - h_i * r_i - h_j * r_j - h_k * r_k; |
| 612 | Float product_i = h_r * r_i + h_i * r_r + h_j * r_k - h_k * r_j; |
| 613 | Float product_j = h_r * r_j - h_i * r_k + h_j * r_r + h_k * r_i; |
| 614 | Float product_k = h_r * r_k + h_i * r_j - h_j * r_i + h_k * r_r; |
| 615 | output += (product_r * t_r + product_i * t_i + product_j * t_j + product_k * t_k) / (r_norm + kEpsilon); |
| 616 | } |
| 617 | output = SUM(output); |
| 618 | } |
| 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 |
nothing calls this directly
no outgoing calls
no test coverage detected