Advertisement
Guest User

Untitled

a guest
Apr 4th, 2020
411
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.14 KB | None | 0 0
  1. class LogisticRegressionGD:
  2.     '''
  3.    A simple logistic regression for binary classification with gradient descent
  4.    '''
  5.  
  6.     def __init__(self):
  7.         pass
  8.  
  9.     def __extend_X(self, X):
  10.         """
  11.            Данный метод должен возвращать следующую матрицу:
  12.            X_ext = [1, X], где 1 - единичный вектор
  13.            это необходимо для того, чтобы было удобнее производить
  14.            вычисления, т.е., вместо того, чтобы считать X@W + b
  15.            можно было считать X_ext@W_ext
  16.        """
  17.         return np.hstack((np.ones((X.shape[0], 1)), X)) #YOUR_CODE
  18.  
  19.     def init_weights(self, input_size, output_size):
  20.         """
  21.            Инициализирует параметры модели
  22.            W - матрица размерности (input_size, output_size)
  23.            инициализируется рандомными числами из
  24.            нормального распределения со средним 0 и стандартным отклонением 0.01
  25.        """
  26.         np.random.seed(42)
  27.         self.W = np.random.normal(0, 0.01, (input_size, output_size)) #YOUR_CODE
  28.  
  29.     def get_loss(self, p, y):
  30.         """
  31.            Данный метод вычисляет логистическую функцию потерь
  32.            @param p: Вероятности принадлежности к классу 1
  33.            @param y: Истинные метки
  34.        """
  35.         #YOUR_CODE
  36.         return -1 / y.shape[0] * np.sum(y * np.log(p) + (1 - y) * (1 - np.log(1 - p)))
  37.  
  38.     def get_prob(self, X):
  39.         """
  40.            Данный метод вычисляет P(y=1|X,W)
  41.            Возможно, будет удобнее реализовать дополнительный
  42.            метод для вычисления сигмоиды
  43.        """
  44.         if X.shape[1] != self.W.shape[0]:
  45.             X = self.__extend_X(X)
  46.         #YOUR_CODE
  47.         return 1 / (1 + np.exp(-(np.dot(X, self.W))))
  48.  
  49.     def get_acc(self, p, y, threshold=0.5):
  50.         """
  51.            Данный метод вычисляет accuracy:
  52.            acc = \frac{1}{len(y)}\sum_{i=1}^{len(y)}{I[y_i == (p_i >= threshold)]}
  53.        """
  54.         #YOUR_CODE
  55.         return -1 / y.shape[0] * np.sum(y == (p >= threshold))
  56.  
  57.     def fit(self, X, y, num_epochs=100, lr=0.001):
  58.  
  59.         X = self.__extend_X(X)
  60.         self.init_weights(X.shape[1], y.shape[1])
  61.  
  62.         accs = []
  63.         losses = []
  64.         for _ in range(num_epochs):
  65.             p = self.get_prob(X)
  66.  
  67.             W_grad = np.dot(X.T, p - y) / y.shape[0] #YOUR_CODE
  68.             self.W -= W_grad * lr #YOUR_CODE
  69.  
  70.             # необходимо для стабильности вычислений под логарифмом
  71.             p = np.clip(p, 1e-10, 1 - 1e-10)
  72.  
  73.             log_loss = self.get_loss(p, y)
  74.             losses.append(log_loss)
  75.             acc = self.get_acc(p, y)
  76.             accs.append(acc)
  77.  
  78.         return accs, losses
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement