Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format numpynet files #57

Merged
merged 7 commits into from
Oct 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 59 additions & 27 deletions examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
"""


def make_checkerboard_training_set(num_points=0, noise=0.0, randomize=True,
x_min=0.0, x_max=1.0, y_min=0.0, y_max=1.0):
def make_checkerboard_training_set(
num_points=0, noise=0.0, randomize=True, x_min=0.0, x_max=1.0, y_min=0.0, y_max=1.0
):
"""
Makes a binary array like a checkerboard (to work on an xor like problem)
:param num_points: (int) The number of points you want in your training set
Expand Down Expand Up @@ -56,7 +57,9 @@ def make_checkerboard_training_set(num_points=0, noise=0.0, randomize=True,
coords.append(coord_point)
# Assign an xor boolean value to the coordinates
for coord_point in coords:
bool_point = np.array([np.round(coord_point[0]) % 2, np.round(coord_point[1]) % 2]).astype(bool)
bool_point = np.array(
[np.round(coord_point[0]) % 2, np.round(coord_point[1]) % 2]
).astype(bool)
bools.append(np.logical_xor(bool_point[0], bool_point[1]))
# If noisy then bit flip
if noise > 0.0:
Expand All @@ -73,7 +76,7 @@ def make_checkerboard_training_set(num_points=0, noise=0.0, randomize=True,
train_out = np.array([[bools[i]]])
else:
train_in = np.append(train_in, np.array([coord]), axis=0)
train_out = np.append(train_out, np.array([[bools[i]]]), axis=1)
train_out = np.append(train_out, np.array([[bools[i]]]), axis=1)

train_out = train_out.T
return train_in, train_out
Expand Down Expand Up @@ -105,12 +108,11 @@ def make_smiley_training_set(num_points=0, delta=0.05):
for coord_point in coords:
x = coord_point[0]
y = coord_point[1]
if (abs(x - 0.65) < delta) & (abs(y - 0.65) < (0.05+delta)):
if (abs(x - 0.65) < delta) & (abs(y - 0.65) < (0.05 + delta)):
bools.append(True)
elif (abs(x - 0.35) < delta) & (abs(y - 0.65) < (0.05+delta)):
elif (abs(x - 0.35) < delta) & (abs(y - 0.65) < (0.05 + delta)):
bools.append(True)
elif ((x > 0.2) & (x < 0.8) &
(abs(y - ((1.5 * (x - 0.5))**2 + 0.25)) < delta)):
elif (x > 0.2) & (x < 0.8) & (abs(y - ((1.5 * (x - 0.5)) ** 2 + 0.25)) < delta):
bools.append(True)
else:
bools.append(False)
Expand All @@ -125,7 +127,7 @@ def make_smiley_training_set(num_points=0, delta=0.05):
train_out = np.array([[bools[i]]])
else:
train_in = np.append(train_in, np.array([coord]), axis=0)
train_out = np.append(train_out, np.array([[bools[i]]]), axis=1)
train_out = np.append(train_out, np.array([[bools[i]]]), axis=1)

train_out = train_out.T
return train_in, train_out
Expand All @@ -139,36 +141,64 @@ def complete_a_picture(viz_client):
:param viz_client: An instance of NumpynetVizClient
"""
# Get a training set for a set of x-y coordinates, this one is part of a checkerboard pattern
x_min = 0.0; x_max = 2.0; y_min = 0; y_max = 1.0
train_in, train_out = make_checkerboard_training_set(num_points=1000, noise=0.00, randomize=True,
x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
x_min = 0.0
x_max = 2.0
y_min = 0
y_max = 1.0
train_in, train_out = make_checkerboard_training_set(
num_points=1000,
noise=0.00,
randomize=True,
x_min=x_min,
x_max=x_max,
y_min=y_min,
y_max=y_max,
)

# Plot he training set
viz_client.plot_2d_classes(train_in, train_out, title="Training data",
x_min=x_min, x_max=x_max,
y_min=y_min, y_max=y_max, delta=0.01)
viz_client.plot_2d_classes(
train_in,
train_out,
title="Training data",
x_min=x_min,
x_max=x_max,
y_min=y_min,
y_max=y_max,
delta=0.01,
)

training_size = train_in.shape[0]
batch_size = round(training_size / 3.0)
num_features = train_in.shape[1]

# Initialize a numpynet object
numpy_net = NumpyNet(num_features, batch_size,
num_hidden=5, hidden_sizes=[4, 8, 16, 8, 4],
activation=["tanh", "tanh", "tanh", "tanh", "tanh", "tanh"],
learning_rate=0.0001,
dropout_rate=None, weight_decay=None,
random_seed=1337)
numpy_net = NumpyNet(
num_features,
batch_size,
num_hidden=5,
hidden_sizes=[4, 8, 16, 8, 4],
activation=["tanh", "tanh", "tanh", "tanh", "tanh", "tanh"],
learning_rate=0.0001,
dropout_rate=None,
weight_decay=None,
random_seed=1337,
)
# Hook the object up to the viz client
numpy_net.set_viz_client(viz_client)

# A basic report of the net to the logs
numpy_net.report_model()

# Train the model!
numpy_net.train(train_in, train_out, epochs=10000,
visualize=True, visualize_percent=1, save_best="./numpynet_best_model.pickle",
debug_visualize=True)
numpy_net.train(
train_in,
train_out,
epochs=10000,
visualize=True,
visualize_percent=1,
save_best="./numpynet_best_model.pickle",
debug_visualize=True,
)

# A silly viz of the network architecture (if the net isn't too huge to make it muddled)
if max(numpy_net.layer_sizes) <= 16:
Expand All @@ -181,7 +211,7 @@ def plot_activations():
y = common.Activation(activation).function(x, deriv=False)
dy = common.Activation(activation).function(x, deriv=True)
viz_client.plot_func(x, y, title=activation)
viz_client.plot_func(x, dy, title="d_"+activation)
viz_client.plot_func(x, dy, title="d_" + activation)


# TODO write this!
Expand All @@ -199,10 +229,12 @@ def paint_a_picture():
def load_a_model(filename, viz_client):
my_net = NumpyNet.load(filename)
prediction_matrix, axis_x, axis_y = common.predict_2d_space(my_net, delta=0.002)
viz_client.plot_2d_prediction(prediction_matrix, axis_x, axis_y, title="Best Prediction")
viz_client.plot_2d_prediction(
prediction_matrix, axis_x, axis_y, title="Best Prediction"
)


if __name__ == '__main__':
if __name__ == "__main__":
"""
Main driver.
"""
Expand Down
3 changes: 2 additions & 1 deletion numpynet/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Activation:
"""
A class to hold all of the activation functions, ensures all have derivatives
"""

function = None
available = ["tanh", "tanhpos", "sigmoid", "relu", "softplus", "leakyrelu"]

Expand Down Expand Up @@ -62,7 +63,7 @@ def _sigmoid(x, deriv=False):
if deriv:
return y * (1.0 - y)
return y

@staticmethod
def _softplus(x, deriv=False):
"""
Expand Down
52 changes: 32 additions & 20 deletions numpynet/loggit.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ class LogObject:
onConsole = None
onFile = None


def __init__(self, filePath=None, fileName=None, header=None, onConsole=True, onFile=True):
def __init__(
self, filePath=None, fileName=None, header=None, onConsole=True, onFile=True
):
"""
Initialize log object.
"""
Expand All @@ -48,10 +49,17 @@ def __init__(self, filePath=None, fileName=None, header=None, onConsole=True, on
self.header = header
self.onConsole = onConsole
self.onFile = onFile
self.startLog(filePath=self.filePath, fileName=self.fileName, header=self.header,
onConsole=self.onConsole, onFile=self.onFile)

def startLog(self, filePath=None, fileName=None, header=None, onConsole=True, onFile=True):
self.startLog(
filePath=self.filePath,
fileName=self.fileName,
header=self.header,
onConsole=self.onConsole,
onFile=self.onFile,
)

def startLog(
self, filePath=None, fileName=None, header=None, onConsole=True, onFile=True
):
"""
Initialize log file with optional path and optional file name.
Parameters:
Expand All @@ -71,10 +79,10 @@ def startLog(self, filePath=None, fileName=None, header=None, onConsole=True, on

# Create Global Logger
try:
self.out = logging.getLogger(str(__main__.__file__)+'_logger')
self.out = logging.getLogger(str(__main__.__file__) + "_logger")

except AttributeError:
self.out = logging.getLogger(str(__name__+'_logger'))
self.out = logging.getLogger(str(__name__ + "_logger"))

# Clear old handlers
self.out.handlers = []
Expand All @@ -83,7 +91,9 @@ def startLog(self, filePath=None, fileName=None, header=None, onConsole=True, on

# create formatter and add to handlers
if self.header is None:
formatter = logging.Formatter("%(asctime)s;%(levelname)s;%(funcName)20s();%(message)s")
formatter = logging.Formatter(
"%(asctime)s;%(levelname)s;%(funcName)20s();%(message)s"
)
elif self.header == "message_only":
formatter = logging.Formatter("%(message)s")
elif self.header == "simple":
Expand All @@ -106,7 +116,7 @@ def startLog(self, filePath=None, fileName=None, header=None, onConsole=True, on

if fileName is None:
# If not provided, the fileName is set to the top level file calling the global logger.
self.fileName = main_filename + '.log'
self.fileName = main_filename + ".log"
else:
self.fileName = fileName

Expand All @@ -121,10 +131,10 @@ def startLog(self, filePath=None, fileName=None, header=None, onConsole=True, on
else: # Something unexpected went wrong so reraise the exception.
raise
else: # No exception, so the file must have been created successfully.
with open(self.fileFullName, 'w') as file_obj:
file_obj.write(main_filename + ' Log File\n')
with open(self.fileFullName, "w") as file_obj:
file_obj.write(main_filename + " Log File\n")
else:
sys.exit('ERROR! Path specified not able to be written to!')
sys.exit("ERROR! Path specified not able to be written to!")

# create console and file handler and set level to debug
file_handle = logging.FileHandler(self.fileFullName)
Expand All @@ -144,23 +154,20 @@ def startLog(self, filePath=None, fileName=None, header=None, onConsole=True, on
standard_handle.setFormatter(formatter)
self.out.addHandler(standard_handle)


def stopLog(self):
"""
Release logging handlers.
"""
self.out.handlers = []


def setLevel(self,level_tag):
def setLevel(self, level_tag):
"""
Sets the logging level
levelStr (str) - a string describing the desired logging level
'INFO', 'DEBUG', 'WARNING', also 'NOTSET'
"""
self.out.setLevel(logging.getLevelName(level_tag))


def changeFileName(self, new_name, header=None, onConsole=True, onFile=True):
"""
Change the name of the log
Expand All @@ -177,16 +184,21 @@ def changeFileName(self, new_name, header=None, onConsole=True, onFile=True):
# Check if name is okay
# Copy old log to new name
new_path, new_filename = os.path.split(new_name)
if new_path == '':
if new_path == "":
new_path = self.filePath
new_full_filename = os.path.join(new_path, new_filename)
if os.access(new_path, os.W_OK):
self.out.handlers = [] # clear old handlers
if self.onFile:
copyfile(self.fileFullName, new_full_filename)
os.remove(self.fileFullName)
self.startLog(filePath=new_path, fileName=new_filename, header=header,
onConsole=onConsole, onFile=onFile)
self.startLog(
filePath=new_path,
fileName=new_filename,
header=header,
onConsole=onConsole,
onFile=onFile,
)
else:
log.out.warning("No permissions to write new log name")

Expand Down
Loading