Skip to content

Commit

Permalink
Merge pull request #2 from deepvision-class/A3
Browse files Browse the repository at this point in the history
A3
  • Loading branch information
jcjohnson committed Oct 1, 2019
2 parents b51cf56 + 1d060b9 commit d45bf7b
Show file tree
Hide file tree
Showing 4 changed files with 391 additions and 3 deletions.
4 changes: 3 additions & 1 deletion coutils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from .import_colab import register_colab_notebooks
from .import_colab import extract_drive_file_id, register_colab_notebooks
from .utils import tensor_to_image, fix_random_seed, visualize_dataset
from .eval import rel_error, compute_numeric_gradient
from .solver import Solver
from . import data
63 changes: 63 additions & 0 deletions coutils/eval.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import torch

@torch.no_grad()
def rel_error(pred, true, eps=1e-8):
"""
Returns relative error: (|pred| - |true|) / |true|
Inputs:
- pred: A torch tensor of the prediction of the true tensor
- true: A torch tensor of the true tensor
- eps: Small epsilon for numerical stability
Returns:
- Relative error between pred and true in floating point
"""
return ((pred-true).abs() / true.abs().clamp(min=eps)).max().item()


@torch.no_grad()
def compute_numeric_gradient(f, x, dy=None, h=1e-5):
"""
Compute a numeric gradient of the function f at the point x.
Inputs:
- f: The function for which to compute the numeric gradient
- x: A torch tensor giving the point at which to evaluate the gradient
- dy: (Optional) A torch tensor giving the upstream gradient dL/dy. If this
is not provided then initialize it to be all ones.
- h: (Optional) A Python float giving the step size to use
Returns:
- dx: A torch tensor giving the downstream gradient dL/dx
"""
# First run the function unmodified
y = f(x)

# Initialize upstream gradient to all ones if not provided
if dy is None:
dy = torch.ones_like(y)

# Initialize downstream gradient to zeros
dx = torch.zeros_like(x)

# Get flattened views of everything
x_flat = x.contiguous().view(-1)
y_flat = y.contiguous().view(-1)
dx_flat = dx.contiguous().view(-1)
dy_flat = dy.contiguous().view(-1)
for i in range(dx_flat.shape[0]):
# Compute numeric derivative dy/dx[i]
orig = x_flat[i].item()
x_flat[i] = orig + h
yph = f(x).clone().view(-1)
x_flat[i] = orig - h
ymh = f(x).clone().view(-1)
x_flat[i] = orig
dy_dxi = (yph - ymh) / (2.0 * h)

# Use chain rule to compute dL/dx[i] = dL/dy . dy/dx[i]
dx_flat[i] = dy_flat.dot(dy_dxi).item()

dx = dx_flat.view(x.shape)
return dx

18 changes: 16 additions & 2 deletions coutils/import_colab.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
from oauth2client.client import GoogleCredentials


def extract_drive_file_id(notebook_link):
prefix = 'https://colab.research.google.com/drive/'
if not notebook_link.startswith(prefix):
raise ValueError('notebook_link should start with "%s"' % prefix)
file_id = notebook_link[len(prefix):]
return file_id


def register_colab_notebooks(id_map):
"""
Register a set of Colab notebooks so they can be imported as Python modules.
Expand All @@ -30,6 +38,8 @@ def register_colab_notebooks(id_map):
Inputs:
- id_map: Dictionary mapping module names to Google Drive IDs
"""
# Clear any existing ColabNotebookFinder objects from the path
sys.meta_path = [x for x in sys.meta_path if not isinstance(x, ColabNotebookFinder)]
sys.meta_path.append(ColabNotebookFinder(id_map))


Expand Down Expand Up @@ -70,7 +80,12 @@ def load_module(self, name):
if cell.cell_type == 'code':
itm = self.shell.input_transformer_manager
code = itm.transform_cell(cell.source)
exec(code, mod.__dict__)
# exec import, class, or function cell only
if code.startswith('import ') or code.startswith('class ') or code.startswith('def ') or code.startswith('@'):
exec(code, mod.__dict__)
except Exception as e:
print(e)
print(code)
finally:
self.shell.user_ns = save_user_ns
return mod
Expand All @@ -87,4 +102,3 @@ def find_module(self, fullname, path=None):
loader = ColabLoader(self.id_map)
return loader


Loading

0 comments on commit d45bf7b

Please sign in to comment.