Skip to content

Commit

Permalink
Publicize percent_waste() and format with yapf
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenjfox committed Feb 7, 2019
1 parent 603ce6d commit 66170ed
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 33 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
A crafty implementation of Google's [MorphNet](https://arxiv.org/abs/1711.06798) (and derivative iterations) in PyTorch.
A crafty implementation of Google's [MorphNet](https://arxiv.org/abs/1711.06798) (and derivative iterations) in PyTorch.

This API is undergoing wild changes as it approaches release.
* Almost every change will be a breaking change.
* __Do not__ rely on the functions as they currently are

Please feel free to look around, but bookmark which release tag it was. Master will be changing, viciously.
2 changes: 1 addition & 1 deletion morph/layers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .sparsify import sparsify
from .sparsify import *
from .widen import widen
16 changes: 16 additions & 0 deletions morph/layers/sparsify.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import torch
import torch.nn as nn

_ZERO_TENSOR = torch.tensor(0.)

Expand All @@ -16,3 +17,18 @@ def sparsify(tensor: torch.Tensor, threshold: float = 0.0) -> torch.Tensor:
`torch.Tensor` of the same dimensions as `tensor`
"""
return tensor.where(tensor > threshold, _ZERO_TENSOR)

def percent_waste(layer: nn.Module) -> float:
"""Computes the number of sparse neurons in a weight matrix,
given the supplied layer.
Return: percentage as a float. Multiply with the `n` of an `m` x `n`
weight matrix/tensor to determine how many neurons can be spared
"""
w = layer.weight
non_sparse_w = torch.nonzero(sparsify(w))
non_zero_count = non_sparse_w.numel() // len(non_sparse_w[0])

percent_size = non_zero_count / w.numel()

return percent_size
17 changes: 0 additions & 17 deletions morph/nn/shrink.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from ..layers.sparsify import sparsify

import torch
import torch.nn as nn

Expand Down Expand Up @@ -29,18 +27,3 @@ def _group_layers_by_algo(children_list):
last = children_list[-1]

return first, middle, last

def _percent_waste(layer: nn.Module) -> float:
"""Computes the number of sparse neurons in a weight matrix,
given the supplied layer.
Return: percentage as a float. Multiply with the `n` of an `m` x `n`
weight matrix/tensor to determine how many neurons can be spared
"""
w = layer.weight
non_sparse_w = torch.nonzero(sparsify(w))
non_zero_count = non_sparse_w.numel() // len(non_sparse_w[0])

percent_size = non_zero_count / w.numel()

return percent_size
53 changes: 41 additions & 12 deletions morph/nn/utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,56 @@

from utils import new_input_layer, new_output_layer


class TestLayer(unittest.TestCase):

def test_new_input_layer_only_touches_output(self):
def test_new_input_layer_only_touches_output_Linear(self):
test = new_input_layer(nn.Linear(5, 4), 'Linear', 7)
expected = nn.Linear(5, 7)

self.assertEqual(expected.out_features, test.out_features,
"Changing the output dimension should be successful")
"Changing the output dimension should be successful")

self.assertEqual(expected.in_features, test.in_features,
"The input dimensions should be unchanged")
def test_new_output_layer_only_touches_output(self):
"The input dimensions should be unchanged")

def test_new_output_layer_only_touches_output_Linear(self):
test = new_output_layer(nn.Linear(5, 4), 'Linear', 7)
expected = nn.Linear(7, 4)

self.assertEqual(expected.in_features, test.in_features,
"Changing the input dimension should be successful")
"Changing the input dimension should be successful")

self.assertEqual(expected.out_features, test.out_features,
"The output dimensions should be unchanged")
"The output dimensions should be unchanged")

def test_new_output_layer_only_changes_input_Conv2d(self):
test = new_output_layer(
nn.Conv2d(3, 12, kernel_size=3, stride=1), 'Conv2d', 6)
expected = nn.Conv2d(6, 12, 3, 1)

self.assertEqual(expected.in_channels, test.in_channels,
"The input dimension should be the same")

self.assertEqual(expected.out_channels, test.out_channels,
"The output dimension should be the same")

self.assertEqual(expected.padding, test.padding,
"The padding aspect shoud be the same")

def test_new_input_layer_only_changes_output_Conv2d(self):
test = new_input_layer(
nn.Conv2d(3, 12, kernel_size=3, stride=1), 'Conv2d', 16)
expected = nn.Conv2d(3, 16, 3, 1)

self.assertEqual(expected.in_channels, test.in_channels,
"The input dimension should be the same")

self.assertEqual(expected.out_channels, test.out_channels,
"The output dimension should be the same")

self.assertEqual(expected.padding, test.padding,
"The padding aspect shoud be the same")


if __name__ == "__main__":
unittest.main()
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
name='morph-py', # How you named your package folder (MyLib)
packages=['morph'], # Chose the same as "name"
# Start with a small number and increase it with every change you make
version='0.0.2-alpha',
version='0.0.3-alpha',
# Chose a license from here: https://help.github.com/articles/licensing-a-repository
license='GNU',
# Give a short description about your library
Expand All @@ -19,7 +19,7 @@
# Provide either the link to your github or to your website
url='https://github.com/stephenjfox/Morph.py',
# I explain this later on
download_url='https://github.com/stephenjfox/Morph.py/archive/v0.0.2.tar.gz',
download_url='https://github.com/stephenjfox/Morph.py/archive/v0.0.3.tar.gz',
keywords=[
'machine learning', 'deep learning', 'nas', 'architecture',
'neural networks'
Expand Down

0 comments on commit 66170ed

Please sign in to comment.