# Path: crowdastro/crowd/util.py
# def majority_vote(y):
#     """Computes the majority vote of a set of crowd labels.
# 
#     y: (n_annotators, n_examples) NumPy masked array of labels.
#     -> (n_examples,) NumPy array of labels.
#     """
#     _, n_samples = y.shape
#     mv = numpy.zeros((n_samples,))
#     for i in range(n_samples):
#         labels = y[:, i]
# 
#         if labels.mask is False:
#             counter = collections.Counter(labels)
#         else:
#             counter = collections.Counter(labels[~labels.mask])
# 
#         if counter:
#             mv[i] = max(counter, key=counter.get)
#         else:
#             # No labels for this data point.
#             mv[i] = numpy.random.randint(2)  # ¯\_(ツ)_/¯
#     return mv
# 
# def logistic_regression(w, x):
#     """Logistic regression classifier model.
# 
#     w: Weights w. (n_features,) NumPy array
#     x: Data point x_i. (n_features,) NumPy array
#     -> float in [0, 1]
#     """
#     return scipy.special.expit(numpy.dot(x, w.T))


import logging
import time
import numpy
import scipy.optimize
import sklearn.linear_model
from crowdastro.crowd.util import majority_vote, logistic_regression

        while True:
            then = time.time()
            # Maximisation step.
            # w first, so the optimisation uses the old parameters.
            w = self._max_w_step(a, b, m, x, y_0, y_1, mv, init_w=w)
            a = self._max_alpha_step(m, y, y_mask)
            b = self._max_beta_step(m, y, y_mask)

            # Expectation step.
            m_ = self._exp_m_step(a, b, w, x, y, y_mask)

            logging.debug('Current value of delta mu: %f',
                          numpy.linalg.norm(m_ - m))

            dm = numpy.linalg.norm(m_ - m)
            if dm < self.epsilon:
                logging.debug('a: {}'.format(a))
                logging.debug('b: {}'.format(b))
                return a, b, w

            m = m_

            # Estimate time remaining.
            now = time.time()
            dt = now - then
            logging.debug('Raykar iteration took {} s.'.format(dt))

    def _exp_m_step(self, a, b, w, x, y, y_mask):
        """Computes expectation value of μ."""

# Path: crowdastro/crowd/util.py
# def majority_vote(y):
#     """Computes the majority vote of a set of crowd labels.
# 
#     y: (n_annotators, n_examples) NumPy masked array of labels.
#     -> (n_examples,) NumPy array of labels.
#     """
#     _, n_samples = y.shape
#     mv = numpy.zeros((n_samples,))
#     for i in range(n_samples):
#         labels = y[:, i]
# 
#         if labels.mask is False:
#             counter = collections.Counter(labels)
#         else:
#             counter = collections.Counter(labels[~labels.mask])
# 
#         if counter:
#             mv[i] = max(counter, key=counter.get)
#         else:
#             # No labels for this data point.
#             mv[i] = numpy.random.randint(2)  # ¯\_(ツ)_/¯
#     return mv
# 
# def logistic_regression(w, x):
#     """Logistic regression classifier model.
# 
#     w: Weights w. (n_features,) NumPy array
#     x: Data point x_i. (n_features,) NumPy array
#     -> float in [0, 1]
#     """
#     return scipy.special.expit(numpy.dot(x, w.T))


# Path: crowdastro/crowd/raykar.py
import logging
import time
import numpy
import scipy.optimize
import sklearn.linear_model
from crowdastro.crowd.util import majority_vote, logistic_regression


        while True:
            then = time.time()
            # Maximisation step.
            # w first, so the optimisation uses the old parameters.
            w = self._max_w_step(a, b, m, x, y_0, y_1, mv, init_w=w)
            a = self._max_alpha_step(m, y, y_mask)
            b = self._max_beta_step(m, y, y_mask)

            # Expectation step.
            m_ = self._exp_m_step(a, b, w, x, y, y_mask)

            logging.debug('Current value of delta mu: %f',
                          numpy.linalg.norm(m_ - m))

            dm = numpy.linalg.norm(m_ - m)
            if dm < self.epsilon:
                logging.debug('a: {}'.format(a))
                logging.debug('b: {}'.format(b))
                return a, b, w

            m = m_

            # Estimate time remaining.
            now = time.time()
            dt = now - then
            logging.debug('Raykar iteration took {} s.'.format(dt))

    def _exp_m_step(self, a, b, w, x, y, y_mask):
        """Computes expectation value of μ."""

        lr = logistic_regression(w, x)