def __init__(self, max_iter=10, batch_size=10, learning_rate=0.001, is_plot_loss=True): super(LogisticRegression, self).__init__() self._nFeat = None self._nClass = None self._label2ix = None self._ix2label = None self._parameter_shape = list() self._lossor = CrossEntropy() self._batch_size = batch_size self._max_iter = max_iter self._learning_rate = learning_rate self._is_plot_loss = is_plot_loss
class LogisticRegression(AbstractClassifier): def __init__(self, max_iter=10, batch_size=10, learning_rate=0.001, is_plot_loss=True): super(LogisticRegression, self).__init__() self._nFeat = None self._nClass = None self._label2ix = None self._ix2label = None self._parameter_shape = list() self._lossor = CrossEntropy() self._batch_size = batch_size self._max_iter = max_iter self._learning_rate = learning_rate self._is_plot_loss = is_plot_loss def predict(self, X): assert self._is_trained, 'model must be trained before predict.' nSize = X.shape[0] param_list = unroll_parameter(self._parameter, self._parameter_shape) W, b = param_list[0], param_list[1] proj = np.dot(X, W) + np.repeat(np.reshape(b, (1, -1)), nSize, axis=0) h = sigmoid(proj) pred = [1 if v >= 0.5 else 0 for v in h] return np.array([self._ix2label[ix] for ix in pred]) def fit(self, X, y): _X = copy.deepcopy(X) _y = copy.deepcopy(y) assert self.__check_valid(_X, _y), 'input is invalid.' if self._is_trained is False: self._label2ix = {label: i for i, label in enumerate(np.unique(_y))} self._ix2label = {i: label for i, label in enumerate(np.unique(_y))} self._nFeat = _X.shape[1] self._nClass = len(np.unique(_y)) assert self._nClass == 2, 'class number must be 2.' W = np.random.uniform(-0.08, 0.08, (self._nFeat, 1)) b = np.zeros(1) self._parameter_shape.append(W.shape) self._parameter_shape.append(b.shape) self._parameter = roll_parameter([W, b]) _y = np.array([self._label2ix[label] for label in _y]) nSize = _X.shape[0] assert nSize >= self._batch_size, 'batch size must less or equal than X size.' optimizer = StochasticGradientDescent(learning_rate=self._learning_rate, batch_size=self._batch_size, decay_strategy='anneal', max_iter=self._max_iter, is_plot_loss=True, add_gradient_noise=True) # optimizer = MomentumSGD(learning_rate=self._learning_rate, batch_size=self._batch_size, momentum=0.9, # momentum_type='nesterov', max_iter=self._max_iter, is_plot_loss=True, # add_gradient_noise=True) # optimizer = Adagrad(learning_rate=self._learning_rate, batch_size=self._batch_size, max_iter=self._max_iter, # is_plot_loss=True, add_gradient_noise=True) # optimizer = Adadelta(batch_size=self._batch_size, max_iter=self._max_iter, is_plot_loss=True, # add_gradient_noise=True) # optimizer = RMSProp(learning_rate=self._learning_rate, batch_size=self._batch_size, max_iter=self._max_iter, # is_plot_loss=True, add_gradient_noise=True) # optimizer = Adam(learning_rate=self._learning_rate, batch_size=self._batch_size, max_iter=self._max_iter, # is_plot_loss=True, add_gradient_noise=True) # optimizer = ConjugateGradientDescent(max_iter=self._max_iter) # optimizer = LBFGS(max_iter=self._max_iter) self._parameter = optimizer.optim(feval=self.feval, X=_X, y=_y, parameter=self._parameter) self._is_trained = True def __check_valid(self, X, y): if self._is_trained is False: return True else: is_valid = False nFeat = X.shape[1] nClass = len(np.unique(y)) if nFeat == self._nFeat and nClass == self._nClass: is_valid = True return is_valid def feval(self, parameter, X, y): y = np.reshape(y, (-1, 1)) param_list = unroll_parameter(parameter, self._parameter_shape) W, b = param_list[0], param_list[1] nSize = X.shape[0] proj = np.dot(X, W) + np.repeat(np.reshape(b, (1, -1)), X.shape[0], axis=0) h = sigmoid(proj) residual = h - y loss = self._lossor.calculate(y, h) grad_W = 1. / nSize * np.dot(X.T, residual) grad_b = 1. / nSize * np.sum(residual) grad_parameter = roll_parameter([grad_W, grad_b]) return loss, grad_parameter
class LogisticRegression(AbstractClassifier): def __init__(self, max_iter=10, batch_size=10, learning_rate=0.001, is_plot_loss=True): super(LogisticRegression, self).__init__() self._nFeat = None self._nClass = None self._label2ix = None self._ix2label = None self._parameter_shape = list() self._lossor = CrossEntropy() self._batch_size = batch_size self._max_iter = max_iter self._learning_rate = learning_rate self._is_plot_loss = is_plot_loss def predict(self, X): assert self._is_trained, 'model must be trained before predict.' nSize = X.shape[0] param_list = unroll_parameter(self._parameter, self._parameter_shape) W, b = param_list[0], param_list[1] proj = np.dot(X, W) + np.repeat( np.reshape(b, (1, b.shape[0])), X.shape[0], axis=0) h = sigmoid(proj) pred = [1 if v >= 0.5 else 0 for v in h] return np.array([self._ix2label[ix] for ix in pred]) def fit(self, X, y): _X = copy.deepcopy(X) _y = copy.deepcopy(y) assert self.__check_valid(_X, _y), 'input is invalid.' if self._is_trained is False: self._label2ix = { label: i for i, label in enumerate(np.unique(_y)) } self._ix2label = { i: label for i, label in enumerate(np.unique(_y)) } self._nFeat = _X.shape[1] self._nClass = len(np.unique(_y)) assert self._nClass == 2, 'class number must be 2.' W = np.random.uniform(-0.08, 0.08, (self._nFeat, 1)) b = np.zeros(1) self._parameter_shape.append(W.shape) self._parameter_shape.append(b.shape) self._parameter = roll_parameter([W, b]) _y = np.array([self._label2ix[label] for label in _y]) nSize = _X.shape[0] assert nSize >= self._batch_size, 'batch size must less or equal than X size.' # optimizer = StochasticGradientDescent(learning_rate=self._learning_rate, batch_size=self._batch_size, # decay_strategy='anneal', max_iter=self._max_iter, is_plot_loss=True) # optimizer = MomentumSGD(learning_rate=self._learning_rate, batch_size=self._batch_size, momentum=0.9, # momentum_type='standard', max_iter=self._max_iter, is_plot_loss=True) optimizer = LBFGS(max_iter=self._max_iter) self._parameter = optimizer.optim(feval=self.feval, X=_X, y=_y, parameter=self._parameter) self._is_trained = True def __check_valid(self, X, y): if self._is_trained is False: return True else: is_valid = False nFeat = X.shape[1] nClass = len(np.unique(y)) if nFeat == self._nFeat and nClass == self._nClass: is_valid = True return is_valid def feval(self, parameter, X, y): y = np.reshape(y, (y.shape[0], 1)) param_list = unroll_parameter(parameter, self._parameter_shape) W, b = param_list[0], param_list[1] nSize = X.shape[0] proj = np.dot(X, W) + np.repeat( np.reshape(b, (1, b.shape[0])), X.shape[0], axis=0) h = sigmoid(proj) residual = h - y loss = self._lossor.calculate(y, h) grad_W = 1. / nSize * np.dot(X.T, residual) grad_b = 1. / nSize * np.sum(residual) grad_parameter = roll_parameter([grad_W, grad_b]) return loss, grad_parameter