Advertisement
Guest User

Untitled

a guest
Apr 6th, 2020
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.46 KB | None | 0 0
  1. class SLogRegOptimizer(BaseEstimator, ClassifierMixin):
  2.     def __init__(self, init_type='zero',
  3.                  max_iter=10000,
  4.                  eps=1e-4,
  5.                  method='SGD',
  6.                  batch_size=100,
  7.                  params={'lr': 0.1, 'C': 0.01},
  8.                  validation=False):
  9.         self.init_type = init_type
  10.         self.max_iter = max_iter
  11.         self.batch_size = batch_size
  12.         self.eps = eps
  13.         self.method = method
  14.         self.params = params
  15.         self.lr = self.params["lr"]
  16.         self.C = self.params["C"]
  17.         self.val = validation
  18.         if self.method == 'momentum':
  19.             self.gamma = self.params["momentum_term"]
  20.             self.v_wt = 0
  21.             self.v_bt = 0
  22.         if self.method == 'adagrad':
  23.             self.alpha = self.params["alpha"]
  24.    
  25.     def _loss(self, X, y, margin):
  26.         return np.log(1 + np.exp(margin)).mean(axis=0)[0]
  27.    
  28.     def _grad_w(self, X, y, margin):
  29.         return - (y * X * (1 - 1 / (1 + np.exp(margin)))).mean(axis=0).reshape(-1, 1) + self.C * self.w
  30.    
  31.     def _grad_b(self, X, y, margin):
  32.         return - (y * (1 - 1 / (1 + np.exp(margin)))).mean(axis=0)
  33.    
  34.     def _update_weights_sgd(self, grad_w, grad_b):
  35.         self.w -= self.lr * grad_w
  36.         self.b -= self.lr * grad_b
  37.         return self.lr * grad_w
  38.    
  39.     def _update_weights_adagrad(self, grad_w, grad_b):
  40.         delta_w = self.lr * grad_w / np.sqrt(self.eps + self._cum_w)
  41.         delta_b = self.lr * grad_b / np.sqrt(self.eps + self._cum_b)
  42.         self.w -= delta_w
  43.         self.b -= delta_b
  44.         self._cum_w += grad_w ** 2
  45.         self._cum_b += grad_b ** 2
  46.         return self.lr * grad_w / np.sqrt(self.alpha + self._cum_w)
  47.  
  48.     def _update_weights_momentum(self, grad_w, grad_b):
  49.         self.v_wt = self.v_wt * self.gamma + self.lr * grad_w
  50.         self.v_bt = self.v_bt * self.gamma + self.lr * grad_b
  51.         self.w -= self.v_wt
  52.         self.b -= self.v_bt
  53.         return self.v_wt
  54.    
  55.     def _gen_batch(self, X, y, max_idx):
  56.         idx = random.randint(0, max_idx, size=self.batch_size)
  57.         return X[idx], y[idx]
  58.    
  59.     def fit(self, X, y):
  60.         self.history = []
  61.        
  62.         if isinstance(X, pd.DataFrame):
  63.             X = X.values
  64.        
  65.         if isinstance(y, pd.DataFrame):
  66.             y = y.values
  67.            
  68.         if len(y.shape) == 1:
  69.             y = y.reshape(-1, 1)
  70.        
  71.         if self.val:
  72.             X, X_val, y, y_val = train_test_split(X, y, test_size=0.3)
  73.             self.val_history = []
  74.        
  75.         if self.method == 'momentum':
  76.             updater = self._update_weights_momentum
  77.         if self.method == 'SGD':
  78.             updater = self._update_weights_sgd
  79.         if self.method == 'adagrad':
  80.             updater = self._update_weights_adagrad
  81.  
  82.         max_batch_idx = X.shape[0]
  83.         weights_dim = X.shape[1]
  84.        
  85.         if self.init_type == 'zero':
  86.             self.w = np.zeros((weights_dim, 1))
  87.             self.b = 0
  88.         if self.init_type == 'random':
  89.             self.w = random.randn(weights_dim, 1)
  90.             self.b = random.randn(1)
  91.        
  92.         margin = - y * (X.dot(self.w) + self.b)
  93.        
  94.         if self.method == 'adagrad':
  95.             self._cum_w = 0.1
  96.             self._cum_b = 0.1
  97.  
  98.        
  99.         iter_num = 0
  100.         w_delta = 1000
  101.        
  102.         while np.linalg.norm(w_delta) > self.eps and iter_num != self.max_iter:
  103.             X_batch, y_batch = self._gen_batch(X, y, max_batch_idx)
  104.    
  105.             margin = - y_batch * (X_batch.dot(self.w) + self.b)
  106.            
  107.             grad_w = self._grad_w(X_batch, y_batch, margin)
  108.             grad_b = self._grad_b(X_batch, y_batch, margin)
  109.  
  110.             w_delta = updater(grad_w, grad_b)
  111.  
  112.            
  113.             iter_num += 1
  114.            
  115.             margin = - y * (X.dot(self.w) + self.b)
  116.        
  117.             self.history.append(self._loss(X, y, margin))
  118.             if self.val:
  119.                 margin = - y_val * (X_val.dot(self.w) + self.b)
  120.                 self.val_history.append(self._loss(X_val, y_val, margin))
  121.         self._conv_iter = iter_num
  122.        
  123.    
  124.     def predict(self, X):
  125.         return 1 / (1 + np.exp(- (X.dot(self.w) + self.b) ))
  126.    
  127.     def predict_proba(self, X):
  128.         if isinstance(X, pd.DataFrame):
  129.             X = X.values
  130.        
  131.         pred = 1 / (1 + np.exp(- (X.dot(self.w) + self.b) ))
  132.         return np.concatenate((1 - pred, pred), axis=1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement