Skip to content

Commit

Permalink
WIP: ImageLayer; tidy up summary text
Browse files Browse the repository at this point in the history
  • Loading branch information
dsblank committed Aug 9, 2017
1 parent 00f14fc commit a34091b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 20 deletions.
44 changes: 33 additions & 11 deletions conx/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ def __init__(self, name, *args, **params):
self.dropout = dropout
else:
self.dropout = 0

if 'activation' in params: # let's keep a copy of it
self.activation = params["activation"]

self.incoming_connections = []
self.outgoing_connections = []

Expand All @@ -129,10 +133,11 @@ def summary(self):
"""
Print out a representation of the layer.
"""
print("Name: %s (%s) VShape: %s Dropout: %s" %
(self.name, self.kind(), self.vshape, self.dropout))
print(" Layer name: '%s' (%s)" % (self.name, self.kind()))
print(" VShape:", self.vshape)
print(" Dropout:", self.dropout)
if len(self.outgoing_connections) > 0:
print("Connected to:", [layer.name for layer in self.outgoing_connections])
print(" Connected to:", [layer.name for layer in self.outgoing_connections])

def kind(self):
"""
Expand Down Expand Up @@ -187,6 +192,11 @@ def make_image(self, vector, config={}):
## Drop dimensions of vector:
s = slice(None, None)
args = []
# The data is in the same format as Keras
# so we can ask Keras what that format is:
# ASSUMES: that the network that loaded the
# dataset has the same image_data_format as
# now:
if K.image_data_format() == 'channels_last':
for d in range(len(vector.shape)):
if d in [0, 1]:
Expand Down Expand Up @@ -331,8 +341,6 @@ def __init__(self, name: str, shape, **params):
if not (callable(act) or act in Layer.ACTIVATION_FUNCTIONS):
raise Exception('unknown activation function: %s' % (act,))
self.activation = act
self.incoming_connections = []
self.outgoing_connections = []

def __repr__(self):
return "<Layer name='%s', shape=%s, act='%s'>" % (
Expand All @@ -342,10 +350,9 @@ def summary(self):
"""
Print a summary of the dense/input layer.
"""
print("Name: %s (%s) Shape: %s Size: %d VShape: %s Activation function: %s Dropout: %s" %
(self.name, self.kind(), self.shape, self.size, self.vshape, self.activation, self.dropout))
if len(self.outgoing_connections) > 0:
print("Connected to:", [layer.name for layer in self.outgoing_connections])
super().summary()
print(" Activation function:", self.activation)
print(" Dropout percent:", self.dropout)

def make_keras_function(self):
"""
Expand All @@ -354,17 +361,32 @@ def make_keras_function(self):
## This is only for Dense:
return self.CLASS(self.size, **self.params)

class PictureLayer(Layer):
class ImageLayer(Layer):
"""
A class for pictures. WIP.
A class for images. WIP.
"""
def __init__(self, name, dimensions, depth, **params):
super().__init__(name, dimensions, **params)
if self.vshape is None:
self.vshape = self.shape
self.dimensions = dimensions
self.depth = depth
if K.image_data_format() == "channels_last":
self.shape = tuple(list(self.shape) + [depth])
self.image_indexes = (0, 1)
else:
self.shape = tuple([depth] + list(self.shape))
self.image_indexes = (1, 2)

def make_image(self, vector, config={}):
"""
Given an activation name (or function), and an output vector, display
make and return an image widget.
"""
## see K.image_data_format() == 'channels_last': above
## We keep the dataset data in the right format.
import PIL
## FIXME: select the right dimensions:
return PIL.Image.fromarray(vector.astype("uint8")).resize(self.vshape)

def process_class_docstring(docstring):
Expand Down
31 changes: 22 additions & 9 deletions conx/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ def _repr_svg_(self):
return None

def __repr__(self):
return "<Network name='%s'>" % self.name
return "<Network name='%s' (%s)>" % (
self.name, ("uncompiled" if not self.model else "compiled"))

def add(self, layer: Layer):
"""
Expand Down Expand Up @@ -275,6 +276,9 @@ def summary(self):
"""
Print out a summary of the network.
"""
print("Network Summary")
print("---------------")
print("Network name:", self.name)
for layer in self.layers:
layer.summary()

Expand Down Expand Up @@ -368,11 +372,22 @@ def _cache_dataset_values(self):
assert self.get_train_inputs_length() == self.get_train_targets_length(), "train inputs/targets lengths do not match"
assert self.get_inputs_length() == self.get_targets_length(), "inputs/targets lengths do not match"

## FIXME: add these for users' convenience:
#def image_to_channels_last(self, matrix):
# x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
#def image_to_channels_first(self, matrix):
# x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)

def set_dataset(self, pairs, verbose=True):
"""
Set the human-specified dataset to a proper keras dataset.
Multi-inputs or multi-outputs must be: [vector, vector, ...] for each layer input/target pairing.
Note:
If you have images in your dataset, they must match K.image_data_format().
See also :any:`image_to_channels_last` and :any:`image_to_channels_first`.
"""
## Either the inputs/targets are a list of a list -> np.array(...) (np.array() of vectors)
## or are a list of list of list -> [np.array(), np.array()] (list of np.array cols of vectors)
Expand Down Expand Up @@ -407,6 +422,8 @@ def load_mnist_dataset(self, verbose=True):
img_rows, img_cols = 28, 28
# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()
## We need to convert the data to images, but which format?
## We ask this Keras instance what it wants, and convert:
if K.image_data_format() == 'channels_first':
x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
Expand Down Expand Up @@ -535,19 +552,15 @@ def summary_dataset(self):
Print out a summary of the dataset.
"""
print('Input Summary:')
print(' length : %d' % (self.get_inputs_length(),))
print(' training: %d' % (self.get_train_inputs_length(),))
print(' testing : %d' % (self.get_test_inputs_length(),))
print(' count : %d' % (self.get_inputs_length(),))
if self.get_inputs_length() != 0:
if self.multi_targets:
print(' shape : %s' % ([x[0].shape for x in self.inputs],))
else:
print(' shape : %s' % (self.inputs[0].shape,))
print(' range : %s' % (self.inputs_range,))
print('Target Summary:')
print(' length : %d' % (self.get_targets_length(),))
print(' training: %d' % (self.get_train_targets_length(),))
print(' testing : %d' % (self.get_test_targets_length(),))
print(' count : %d' % (self.get_targets_length(),))
if self.get_targets_length() != 0:
if self.multi_targets:
print(' shape : %s' % ([x[0].shape for x in self.targets],))
Expand Down Expand Up @@ -641,8 +654,8 @@ def split_dataset(self, split=0.50, verbose=True):
self.test_targets = self.targets[self.split:]
if verbose:
print('Split dataset into:')
print(' %d train inputs' % self.get_train_inputs_length())
print(' %d test inputs' % self.get_test_inputs_length())
print(' train set count: %d' % self.get_train_inputs_length())
print(' test set count : %d' % self.get_test_inputs_length())

def test(self, inputs=None, targets=None, batch_size=32, tolerance=0.1):
"""
Expand Down

0 comments on commit a34091b

Please sign in to comment.