Exemplo n.º 1
0
    def test(self):
        """Test for all possible input combinations.
        """
        for epsilon in (0.01, 0.1, 0.5):
            self.assertEqual(psi(HONEST, GOOD, PLUS, epsilon), 1-epsilon)
            self.assertEqual(psi(HONEST, GOOD, MINUS, epsilon), epsilon)
            self.assertEqual(psi(HONEST, BAD, PLUS, epsilon), epsilon)
            self.assertEqual(psi(HONEST, BAD, MINUS, epsilon), 1-epsilon)

            self.assertEqual(psi(FRAUD, GOOD, PLUS, epsilon), 2*epsilon)
            self.assertEqual(psi(FRAUD, GOOD, MINUS, epsilon), 1-2*epsilon)
            self.assertEqual(psi(FRAUD, BAD, PLUS, epsilon), 1-2*epsilon)
            self.assertEqual(psi(FRAUD, BAD, MINUS, epsilon), 2*epsilon)

        with self.assertRaises(ValueError):
            psi(HONEST, 3, PLUS, 10)
Exemplo n.º 2
0
    def _update_product_to_user(self, reviewer, product, ulabel):
        """Compute an updated message from a product to a user with a user label.

        The updated message is defined as

        .. math::
           m_{p\\rightarrow u}(y_{i}) \\leftarrow
           \\alpha_{3} \\sum_{y_{j} \\in \\cal{L}_{\\cal{P}}}
           \\psi_{ij}^{s}(y_{i}, y_{j}) \\phi^{\\cal{P}}_{j}(y_{j})
           \\prod_{Y_{k} \\in \\cal{N}_{j} \\cap \\cal{Y}^{\\cal{U}}/u}
           m_{k\\rightarrow j}(y_{j}),

        where :math:`y_{i} \\in {honest, fraud}`, and
        :math:`\\cal{N}_{j} \\cap \\cal{Y}^{\\cal{U}}/u` means a set of users
        who review the product :math:`p` but except user :math:`u`,
        The :math:`\\psi_{ij}^{s}(y_{i}, y_{j})` takes :math:`\\epsilon` as a
        hyper parameter, self.epsilon is used for it.

        This method returns a logarithm of the updated message.

        Args:
          reviewer: Reviewer i.e. a user,
          product: Product,
          ulabel: user label,

        Returns:
          a logarithm of the updated message from the given product to the
          given reviewer with the given user label.
        """
        review = self.retrieve_review(reviewer, product)
        res = {}
        for plabel in (GOOD, BAD):
            res[plabel] = \
                np.log(psi(ulabel, plabel, review.evaluation, self.epsilon)) \
                + phi_p(plabel) \
                + self.prod_message_from_users(reviewer, product, plabel)
        return np.logaddexp(*res.values())
Exemplo n.º 3
0
    def _update_user_to_product(self, reviewer, product, plabel):
        """Compute an updated message from a user to a product with a product label.

        The updated message is defined as

        .. math::
           m_{u\\rightarrow p}(y_{j}) \\leftarrow
            \\alpha_{1} \\sum_{y_{i} \\in \\cal{L}_{\\cal{U}}}
            \\psi_{ij}^{s}(y_{i}, y_{j}) \\phi^{\\cal{U}}_{i}(y_{i})
            \\prod_{Y_{k} \\in \\cal{N}_{i} \\cap \\cal{Y}^{\\cal{P}}/p}
            m_{k \\rightarrow i}(y_{i}),

        where :math:`y_{j} \\in {good, bad}`, and
        :math:`\\cal{N}_{i} \\cap \\cal{Y}^{\\cal{P}}/p` means a set of product
        the user :math:`u` reviews but except product :math:`p`.
        The :math:`\\psi_{ij}^{s}(y_{i}, y_{j})` takes :math:`\\epsilon` as a
        hyper parameter, self.epsilon is used for it.

        This method returns a logarithm of the updated message.

        Args:
          reviewer: Reviewer,
          product: Product,
          plabel: produce label,

        Returns:
          a logarithm of the updated message from the given reviewer to the
          given product with the given product label.
        """
        review = self.retrieve_review(reviewer, product)
        res = {}
        for ulabel in (HONEST, FRAUD):
            res[ulabel] = \
                np.log(psi(ulabel, plabel, review.evaluation, self.epsilon)) \
                + phi_u(ulabel) \
                + self.prod_message_from_products(reviewer, product, ulabel)
        return np.logaddexp(*res.values())
Exemplo n.º 4
0
    def test_update_product_to_user(self):
        """Test updating a message from a product to a user.

        In this test, we assume the following review graph,

        .. graphviz::

           digraph bipartite {
              graph [rankdir = LR];
              "product-0";
              "reviewer-0";
              "reviewer-1";
              "reviewer-2";
              "product-0" -> "reviewer-0" [label="+, m(honest)=0.4, m(fraud)=0.6"];
              "reviewer-0" -> "product-0" [label="+, m(good)=0.3, m(bad)=0.7"];
              "reviewer-1" -> "product-0" [label="-, m(good)=0.6, m(bad)=0.4"];
              "reviewer-2" -> "product-0" [label="+, m(good)=0.8, m(bad)=0.2"];
           }

        The updated message is defined as

        .. math::
           m_{p\\rightarrow u}(y_{i}) \\leftarrow
           \\alpha_{3} \\sum_{y_{j} \\in \\cal{L}_{\\cal{P}}}
           \\psi_{ij}^{s}(y_{i}, y_{j}) \\phi^{\\cal{P}}_{j}(y_{j})
           \\prod_{Y_{k} \\in \\cal{N}_{j} \\cap \\cal{Y}^{\\cal{U}}/u}
           m_{k\\rightarrow j}(y_{j}),

        where :math:`y_{i} \\in {honest, fraud}`, and
        :math:`\\cal{N}_{j} \\cap \\cal{Y}^{\\cal{U}}/u` means a set of users
        who review the product :math:`p` but except user :math:`u`,
        """
        reviewers = [
            self.graph.new_reviewer("reviewer-{0}".format(i)) for i in range(3)
        ]
        product = self.graph.new_product("product-0")
        reviews = {}
        reviews[0] = self.graph.add_review(reviewers[0], product, 1)
        reviews[0].update_product_to_user(HONEST, np.log(0.4))
        reviews[0].update_product_to_user(FRAUD, np.log(0.6))
        reviews[0].update_user_to_product(GOOD, np.log(0.3))
        reviews[0].update_user_to_product(BAD, np.log(0.7))
        reviews[1] = self.graph.add_review(reviewers[1], product, 0)
        reviews[1].update_user_to_product(GOOD, np.log(0.6))
        reviews[1].update_user_to_product(BAD, np.log(0.4))
        reviews[2] = self.graph.add_review(reviewers[2], product, 1)
        reviews[2].update_user_to_product(GOOD, np.log(0.8))
        reviews[2].update_user_to_product(BAD, np.log(0.2))

        # 0.6*0.8: products of other messages to the product with GOOD.
        # 2.0: phi of the label (constant)
        # 0.4*0.2: products of other messages to the product with BAD.
        ans1 = 0.6 * 0.8 * 2.0 * psi(HONEST, GOOD, PLUS, self.epsilon) \
            + 0.4 * 0.2 * 2.0 * psi(HONEST, BAD, PLUS, self.epsilon)
        self.assertAlmostEqual(
            np.exp(
                self.graph._update_product_to_user(  # pylint: disable=protected-access
                    reviewers[0], product, HONEST)),
            ans1)

        # 0.6*0.8: products of other messages to the product with GOOD.
        # 2.0: phi of the label (constant)
        # 0.4*0.2: products of other messages to the product with BAD.
        ans2 = 0.6 * 0.8 * 2.0 * psi(FRAUD, GOOD, PLUS, self.epsilon) \
            + 0.4 * 0.2 * 2.0 * psi(FRAUD, BAD, PLUS, self.epsilon)
        self.assertAlmostEqual(
            np.exp(
                self.graph._update_product_to_user(  # pylint: disable=protected-access
                    reviewers[0], product, FRAUD)),
            ans2)