code: def propagate(w, b, X, Y):
      
      m = X.shape[1]
      A = sigmoid(np.dot(w.T, X) + b)
      cost = -1 / m * np.sum(Y * np.log(A) + (1 - Y) * np.log(1 - A))
  
      # BACKWARD PROPAGATION (TO FIND GRAD)
      dw = 1.0 / m * np.dot(X, (A - Y).T)
      db = 1.0 / m * np.sum(A - Y)
  
      assert (dw.shape == w.shape)
      assert (db.dtype == float)
      cost = np.squeeze(cost)
      assert (cost.shape == ())
  
      grads = {"dw": dw,
               "db": db}
  
      return grads, cost
docs: Implement the cost function and its gradient for the propagation
  
      Arguments:
      w       weights, a numpy array of size (dim, 1)
      b       bias, a scalar
      X       data of size (dim, number of examples)
      Y       true "label" vector of size (1, number of examples)
  
      Return:
      cost    negative log-likelihood cost for logistic regression
      dw      gradient of the loss with respect to w, thus same shape as w
      db      gradient of the loss with respect to b, thus same shape as b