DatStorm

Untitled

Oct 8th, 2018
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.93 KB | None | 0 0
  1. import numpy as np
  2.  
  3.  
  4. def one_in_k_encoding(vec, k):
  5.     """ One-in-k encoding of vector to k classes
  6.    
  7.    Args:
  8.       vec: numpy array - data to encode
  9.       k: int - number of classes to encode to (0,...,k-1)
  10.    """
  11.     n = vec.shape[0]
  12.     enc = np.zeros((n, k))
  13.     enc[np.arange(n), vec] = 1
  14.     return enc
  15.  
  16.  
  17. def softmax(X):
  18.     """
  19.    You can take this from handin I
  20.    Compute the softmax of each row of an input matrix (2D numpy array).
  21.    
  22.    the numpy functions amax, log, exp, sum may come in handy as well as the keepdims=True option and the axis option.
  23.    Remember to handle the numerical problems as discussed in the description.
  24.    You should compute lg softmax first and then exponentiate
  25.    
  26.    More precisely this is what you must do.
  27.    
  28.    For each row x do:
  29.    compute max of x
  30.    compute the log of the denominator sum for softmax but subtracting out the max i.e (log sum exp x-max) + max
  31.    compute log of the softmax: x - logsum
  32.    exponentiate that
  33.    
  34.    You can do all of it without for loops using numpys vectorized operations.
  35.  
  36.    Args:
  37.        X: numpy array shape (n, d) each row is a data point
  38.    Returns:
  39.        res: numpy array shape (n, d)  where each row is the softmax transformation of the corresponding row in X i.e res[i, :] = softmax(X[i, :])
  40.    """
  41.     res = np.zeros(X.shape)
  42.     toAssert = res
  43.     ### YOUR CODE HERE no for loops please
  44.  
  45.     max = np.amax(X, axis=1, keepdims=True)
  46.     exp = np.exp(X - max)
  47.     np_sum = np.sum(exp, axis=1, keepdims=True)
  48.     logsum = np.log(np_sum) + max
  49.     res = np.exp(X - logsum)
  50.  
  51.     assert toAssert.shape == res.shape, "Shapes mismatch in softmax. Expected {0} - Got {1}".format(toAssert, res)
  52.     ### END CODE
  53.     return res
  54.  
  55.  
  56. def relu(x):
  57.     """ Compute the relu activation function on every element of the input
  58.    
  59.        Args:
  60.            x: np.array
  61.        Returns:
  62.            res: np.array same shape as x
  63.        Beware of np.max and look at np.maximum
  64.    """
  65.     ### YOUR CODE HERE
  66.     zeros = np.zeros(x.shape)
  67.     res = np.maximum(x, zeros)
  68.     ### END CODE
  69.     return res
  70.  
  71.  
  72. def make_dict(W1, b1, W2, b2):
  73.     """ Trivial helper function """
  74.     return {'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}
  75.  
  76.  
  77. def get_init_params(input_dim, hidden_size, output_size):
  78.     """ Initializer function using he et al Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification
  79.  
  80.    Args:
  81.      input_dim: int
  82.      hidden_size: int
  83.      output_size: int
  84.    Returns:
  85.       dict of randomly initialized parameter matrices.
  86.    """
  87.     W1 = np.random.normal(0, np.sqrt(1. / (input_dim + hidden_size)), size=(input_dim, hidden_size))
  88.     b1 = np.zeros((1, hidden_size))
  89.     W2 = np.random.normal(0, np.sqrt(2. / (hidden_size + output_size)), size=(hidden_size, output_size))
  90.     b2 = np.zeros((1, output_size))
  91.     return {'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}
  92.  
  93.  
  94. def test_shapes_fit(name, vec, test_vec):
  95.     if vec.shape == test_vec.shape:
  96.         # print("SHAPES FIT \"{2}\" : VEC: {0} , TEST_VEC: {1}".format(vec.shape, test_vec.shape,name))
  97.         A = None
  98.     else:
  99.         B = None
  100.         # print("SHAPES NOT FITTING: \"{2}\" : VEC: {0} , TEST_VEC: {1}".format(vec.shape, test_vec.shape,name))
  101.  
  102.     # assert vec.shape == test_vec.shape, "SHAPES NOT FITTING: VEC: {0} , TEST_VEC: {1}".format(vec, test_vec)
  103.  
  104.  
  105. class NetClassifier():
  106.  
  107.     def __init__(self):
  108.         """ Trivial Init """
  109.         self.params = None
  110.         self.hist = None
  111.  
  112.     def predict(self, X, params=None):
  113.         """ Compute class prediction for all data points in class X
  114.        
  115.        Args:
  116.            X: np.array shape n, d
  117.            params: dict of params to use (if none use stored params)
  118.        Returns:
  119.            np.array shape n, 1
  120.        """
  121.         if params is None:
  122.             params = self.params
  123.         pred = None
  124.         ### YOUR CODE HERE
  125.         W1 = params['W1']
  126.         b1 = params['b1']
  127.         W2 = params['W2']
  128.         b2 = params['b2']
  129.         hidden_layer = relu(X @ W1 + b1)
  130.         pred = hidden_layer @ W2 + b2
  131.         ### END CODE        
  132.         return pred
  133.  
  134.     def score(self, X, y, params=None):
  135.         """ Compute accuracy of model on data X with labels y
  136.        
  137.        Args:
  138.            X: np.array shape n, d
  139.            y: np.array shape n, 1
  140.            params: dict of params to use (if none use stored params)
  141.  
  142.        Returns:
  143.            np.array shape n, 1
  144.        """
  145.         if params is None:
  146.             params = self.params
  147.         acc = None
  148.         ### YOUR CODE HERE
  149.         acc = np.mean(np.equal(self.predict(X, params).T, y))
  150.  
  151.         ### END CODE
  152.         return acc
  153.  
  154.     @staticmethod
  155.     def cost_grad(X, y, params, reg=0.0):
  156.         """ Compute cost and gradient of neural net on data X with labels y using weight decay parameter c
  157.        You should implement a forward pass and store the intermediate results
  158.        and the implement the backwards pass using the intermediate stored results
  159.        
  160.        Use the derivative for cost as a function for input to softmax as derived above
  161.        
  162.        Args:
  163.            X: np.array shape n, self.input_size
  164.            y: np.array shape n, 1
  165.            params: dict with keys (W1, W2, b1, b2)
  166.            reg: float - weight decay regularization weight
  167.            params: dict of params to use for the computation
  168.        
  169.        Returns
  170.            cost: scalar - average cross entropy cost
  171.            dict with keys
  172.            d_w1: np.array shape w1.shape, entry d_w1[i, j] = \partial cost/ \partial w1[i, j]
  173.            d_w2: np.array shape w2.shape, entry d_w2[i, j] = \partial cost/ \partial w2[i, j]
  174.            d_b1: np.array shape b1.shape, entry d_b1[1, j] = \partial cost/ \partial b1[1, j]
  175.            d_b2: np.array shape b2.shape, entry d_b2[1, j] = \partial cost/ \partial b2[1, j]
  176.            
  177.        """
  178.  
  179.         W1 = params['W1']
  180.         b1 = params['b1']
  181.         W2 = params['W2']
  182.         b2 = params['b2']
  183.         labels = one_in_k_encoding(y, W2.shape[1])  # shape n x k
  184.  
  185.         ### INIT ###
  186.         cost = 0
  187.         d_W1 = d_W1_TEST = np.zeros(W1.shape)
  188.         d_W2 = d_W2_TEST = np.zeros(W2.shape)
  189.         d_b1 = d_b1_TEST = np.zeros(b1.shape)
  190.         d_b2 = d_b2_TEST = np.zeros(b2.shape)
  191.         n = X.shape[0]
  192.         d1 = W1.shape[0]
  193.         d2 = W1.shape[1]
  194.         d3 = W2.shape[1]
  195.         ### YOUR CODE HERE - FORWARD PASS - compute regularized cost and store relevant values for backprop
  196.  
  197.         hidden_layer = X @ W1  # => n x d2
  198.         test_shapes_fit("hidden_layer", hidden_layer, np.zeros((n, d2)))
  199.  
  200.         biased_hidden_layer = hidden_layer + b1  # => n x d2
  201.         test_shapes_fit("biased_hidden_layer", biased_hidden_layer, np.zeros((n, d2)))
  202.  
  203.         activated_hidden_layer = relu(biased_hidden_layer)  # => n x d2
  204.         test_shapes_fit("activated_hidden_layer", activated_hidden_layer, np.zeros((n, d2)))
  205.  
  206.         output_layer = activated_hidden_layer @ W2  # => n x d3
  207.         test_shapes_fit("output_layer", output_layer, np.zeros((n, d3)))
  208.  
  209.         biased_output_layer = output_layer + b2  # => n x d3
  210.         test_shapes_fit("biased_output_layer", biased_output_layer, np.zeros((n, d3)))
  211.  
  212.         smax = softmax(biased_output_layer)  # => n x d3
  213.         test_shapes_fit("smax", smax, np.zeros((n, d3)))
  214.  
  215.         smax_where_y_is_one = smax[labels == 1]  # => n x 1
  216.         # test_shapes_fit("smax_where_y_is_one", smax_where_y_is_one, np.zeros((n, 1)))
  217.  
  218.         L = - np.log(smax_where_y_is_one)  # => n x 1
  219.         # test_shapes_fit("L", L, np.zeros((n, 1)))
  220.  
  221.         L_mean = np.mean(L)  # => 1 x 1
  222.         # test_shapes_fit("L_mean", L_mean, np.zeros((1, 1)))
  223.  
  224.         # weight decay
  225.         W1_squared = W1 ** 2.0  # => d1 x d2
  226.         test_shapes_fit("W1_squared", W1_squared, np.zeros((d1, d2)))
  227.  
  228.         W2_squared = W2 ** 2.0  # => d2 x d3
  229.         test_shapes_fit("W2_squared", W2_squared, np.zeros((d2, d3)))
  230.  
  231.         summ = np.sum(W1_squared) + np.sum(W2_squared)  # => 1 x 1
  232.         # test_shapes_fit("summ", summ, np.zeros((1, 1)))
  233.  
  234.         weight_decay = reg * summ  # => 1 x 1
  235.         # test_shapes_fit("weight_decay", weight_decay, np.zeros((1, 1)))
  236.  
  237.         cost = L_mean + weight_decay  # => 1 x 1
  238.         # test_shapes_fit("cost", cost, np.zeros((1, 1)))
  239.  
  240.         ### END CODE
  241.  
  242.         ### YOUR CODE HERE - BACKWARDS PASS - compute derivatives of all (regularized) weights and bias, store them in d_w1, d_w2' d_w2, d_b1, d_b2
  243.  
  244.         d_cost = 1.0  # => 1 x 1
  245.         d_L_mean = 1 / n * d_cost  # => 1 x 1
  246.         d_L = (- labels + smax) * d_L_mean  # => n x d3
  247.         test_shapes_fit("d_L", d_L, np.zeros((n, d3)))
  248.  
  249.         d_b2 = 1.0 * d_L.sum(axis=0, keepdims=True)  # => 1 x d3
  250.         test_shapes_fit("d_b2", d_b2, np.zeros((1, d3)))
  251.  
  252.         d_biased_output_layer = 1.0 * d_L  # => n x d3
  253.         test_shapes_fit("d_biased_output_layer", d_biased_output_layer, np.zeros((n, d3)))
  254.  
  255.         d_activated_hidden_layer = d_biased_output_layer @ W2.T  # => n x d2
  256.         test_shapes_fit("d_activated_hidden_layer", d_activated_hidden_layer, np.zeros((n, d2)))
  257.  
  258.         d_W2 = activated_hidden_layer.T @ d_biased_output_layer  # => d2 x d3
  259.         test_shapes_fit("d_W2", d_W2, np.zeros((d2, d3)))
  260.  
  261.         # d_activated_hidden_layer = (biased_hidden_layer > 0).astype(int) * d_path_to_relu  # => n * d2
  262.         d_biased_hidden_layer = np.multiply((biased_hidden_layer > 0).astype(int),
  263.                                             d_activated_hidden_layer)  # => n * d2 ???????????
  264.         test_shapes_fit("d_biased_hidden_layer", d_biased_hidden_layer, np.zeros((n, d2)))
  265.  
  266.         d_b1 = 1.0 * d_biased_hidden_layer.sum(axis=0, keepdims=True)  # => 1 x d2
  267.         test_shapes_fit("d_b1", d_b1, np.zeros((1, d2)))
  268.  
  269.         d_hidden_layer = 1.0 * d_biased_hidden_layer  # => n x d2
  270.         test_shapes_fit("d_hidden_layer", d_hidden_layer, np.zeros((n, d2)))
  271.  
  272.         d_W1 = X.T @ d_hidden_layer  # => d1 x d2
  273.         test_shapes_fit("d_W1", d_W1, np.zeros((d1, d2)))
  274.  
  275.         # Weight decay
  276.         d_weight_decay = d_cost * reg  # 1 x 1
  277.  
  278.         d_W1_squared = 1.0 * d_weight_decay  # 1 x 1
  279.         d_W2_squared = 1.0 * d_weight_decay  # 1 x 1
  280.  
  281.         d_W1 += 2.0 * W1 * d_W1_squared  # w1
  282.         test_shapes_fit("d_W1", d_W1, W1)
  283.  
  284.         d_W2 += 2.0 * W2 * d_W2_squared  # w2
  285.         test_shapes_fit("d_W2", d_W2, W2)
  286.  
  287.         test_shapes_fit("W1", d_W1, d_W1_TEST)
  288.         test_shapes_fit("W2", d_W2, d_W2_TEST)
  289.         test_shapes_fit("b1", d_b1, d_b1_TEST)
  290.         test_shapes_fit("b2", d_b2, d_b2_TEST)
  291.  
  292.         ### END CODE
  293.         # the return signature
  294.         return cost, {'d_w1': d_W1, 'd_w2': d_W2, 'd_b1': d_b1, 'd_b2': d_b2}
  295.  
  296.     def fit(self, X_train, y_train, X_val, y_val, init_params, batch_size=32, lr=0.1, reg=1e-4, epochs=30):
  297.         """ Run Mini-Batch Gradient Descent on data X, Y to minimize the in sample error (1/n)Cross Entropy for Neural Net classification
  298.        Printing the performance every epoch is a good idea to see if the algorithm is working
  299.  
  300.        Args:
  301.           X_train: numpy array shape (n, d) - the training data each row is a data point
  302.           y_train: numpy array shape (n,) int - training target labels numbers in {0, 1,..., k-1}
  303.           X_val: numpy array shape (n, d) - the validation data each row is a data point
  304.           y_val: numpy array shape (n,) int - validation target labels numbers in {0, 1,..., k-1}
  305.           init_params: dict - has initial setting of parameters
  306.           lr: scalar - initial learning rate
  307.           batch_size: scalar - size of mini-batch
  308.           epochs: scalar - number of iterations through the data to use
  309.  
  310.        Sets:
  311.           params: dict with keys {W1, W2, b1, b2} parameters for neural net
  312.           history: dict:{keys: train_loss, train_acc, val_loss, val_acc} each an np.array of size epochs of the the given cost after every epoch
  313.        """
  314.  
  315.         W1 = init_params['W1']
  316.         b1 = init_params['b1']
  317.         W2 = init_params['W2']
  318.         b2 = init_params['b2']
  319.         params = init_params
  320.  
  321.         d_W1 = d_W2 = d_b1 = d_b2 = None
  322.  
  323.         train_loss = []
  324.         train_acc = []
  325.         val_loss = []
  326.         val_acc = []
  327.         n = len(X_train)
  328.         b = batch_size
  329.         ### YOUR CODE HERE
  330.         for i in range(1, epochs):
  331.             perm = np.random.permutation(n)
  332.             mini_batches = [perm[k:k + b] for k in range(0, n, b)]
  333.  
  334.             cost = 0
  335.             for mini_batch in mini_batches:
  336.                 xs = np.array([X_train[index] for index in mini_batch])
  337.                 ys = np.array([y_train[index] for index in mini_batch])
  338.                 _, dictWb = self.cost_grad(xs, ys, params, reg=reg)
  339.                 d_W1 = dictWb['d_w1']
  340.                 d_b1 = dictWb['d_b1']
  341.                 d_W2 = dictWb['d_w2']
  342.                 d_b2 = dictWb['d_b2']
  343.  
  344.                 W1 = - lr * (1 / b * d_W1)
  345.                 W2 = - lr * (1 / b * d_W2)
  346.                 b1 = - lr * (1 / b * d_b1)
  347.                 b2 = - lr * (1 / b * d_b2)
  348.                 params = make_dict(W1, b1, W2, b2)
  349.  
  350.             # Calculate the cost over all datapoints, to get a better history
  351.             # Remove for better effeciency
  352.             lr = lr * 0.99
  353.             tester, _ = self.cost_grad(X_train, y_train, params, reg)
  354.             train_loss.append(tester)
  355.             test1 = np.sum(self.predict(X_train, params) == y_train) / len(X_train)
  356.             train_acc.append(test1)
  357.             tester2, _ = self.cost_grad(X_val, y_val, params, reg)
  358.             val_loss.append(tester2)
  359.             test2 = np.sum(self.predict(X_val, params) == y_val) / len(X_val)
  360.             val_acc.append(test2)
  361.  
  362.         ### END CODE
  363.         # hist dict should look like this with something different than none
  364.         self.history = {
  365.             'train_loss': np.array(train_loss),
  366.             'train_acc': np.array(train_acc),
  367.             'val_loss': np.array(val_loss),
  368.             'val_acc': np.array(val_acc),
  369.         }
  370.         ## self.params should look like this with something better than none, i.e. the best parameters found.
  371.         self.params = params
  372.  
  373.  
  374. def numerical_grad_check(f, x, key):
  375.     """ Numerical Gradient Checker """
  376.     eps = 1e-6
  377.     h = 1e-5
  378.     # d = x.shape[0]
  379.     cost, grad = f(x)
  380.     grad = grad[key]
  381.     it = np.nditer(x, flags=['multi_index'])
  382.     while not it.finished:
  383.         dim = it.multi_index
  384.         print(dim)
  385.         tmp = x[dim]
  386.         x[dim] = tmp + h
  387.         cplus, _ = f(x)
  388.         x[dim] = tmp - h
  389.         cminus, _ = f(x)
  390.         x[dim] = tmp
  391.         num_grad = (cplus - cminus) / (2 * h)
  392.         # print('cplus: {0}, cminus: {1}, cplus-cminus: {2}'.format(cplus, cminus, cplus - cminus))
  393.         # print('dim: {0}, grad: {1}, num_grad: {2}, grad-num_grad: {3}'.format(dim, grad[dim], num_grad,
  394.         #                                                                      grad[dim] - num_grad))
  395.         np_abs = np.abs(num_grad - grad[dim])
  396.         abs_eps = np_abs < eps
  397.         print("np_abs: ", np_abs, " np_abs < eps =", abs_eps)
  398.         assert abs_eps, 'numerical gradient error index {0}, numerical gradient {1}, computed gradient {2}'.format(dim,
  399.                                                                                                                    num_grad,
  400.                                                                                                                    grad[
  401.                                                                                                                        dim])
  402.         it.iternext()
  403.  
  404.  
  405. def test_grad():
  406.     stars = '*' * 5
  407.     print(stars, 'Testing  Cost and Gradient Together', stars)
  408.     input_dim = 7
  409.     hidden_size = 1
  410.     output_size = 3
  411.     nc = NetClassifier()
  412.     params = get_init_params(input_dim, hidden_size, output_size)
  413.  
  414.     nc = NetClassifier()
  415.     X = np.random.randn(7, input_dim)
  416.     y = np.array([0, 1, 2, 0, 1, 2, 0])
  417.  
  418.     f = lambda z: nc.cost_grad(X, y, params, reg=1.0)
  419.     print('\n', stars, 'Test Cost and Gradient of b2', stars)
  420.     numerical_grad_check(f, params['b2'], 'd_b2')
  421.     print(stars, 'Test Success of b2', stars)
  422.  
  423.     print('\n', stars, 'Test Cost and Gradient of w2', stars)
  424.     numerical_grad_check(f, params['W2'], 'd_w2')
  425.     print('Test Success w2')
  426.  
  427.     print('\n', stars, 'Test Cost and Gradient of b1', stars)
  428.     numerical_grad_check(f, params['b1'], 'd_b1')
  429.     print(stars, 'Test Success b1', stars)
  430.  
  431.     print('\n', stars, 'Test Cost and Gradient of w1', stars)
  432.     numerical_grad_check(f, params['W1'], 'd_w1')
  433.     print('Test Success w1')
  434.  
  435.  
  436. if __name__ == '__main__':
  437.     input_dim = 3
  438.     hidden_size = 5
  439.     output_size = 4
  440.     batch_size = 7
  441.     nc = NetClassifier()
  442.     params = get_init_params(input_dim, hidden_size, output_size)
  443.     X = np.random.randn(batch_size, input_dim)
  444.     Y = np.array([0, 1, 2, 0, 1, 2, 0])
  445.     nc.cost_grad(X, Y, params, reg=0)
  446.     test_grad()
Advertisement
Add Comment
Please, Sign In to add comment