feat(machinelearning): add cuda support for project 5.
This commit is contained in:
@ -1,5 +1,3 @@
|
|||||||
# A custom autograder for this project
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# A mini-framework for autograding
|
# A mini-framework for autograding
|
||||||
################################################################################
|
################################################################################
|
||||||
@ -222,12 +220,11 @@ def main():
|
|||||||
# Tests begin here
|
# Tests begin here
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
import numpy as np
|
import torch
|
||||||
import matplotlib
|
import matplotlib
|
||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
from torch import nn, Tensor
|
from torch import nn, Tensor
|
||||||
import torch
|
|
||||||
import backend
|
import backend
|
||||||
|
|
||||||
def check_dependencies():
|
def check_dependencies():
|
||||||
@ -240,9 +237,9 @@ def check_dependencies():
|
|||||||
|
|
||||||
for t in range(400):
|
for t in range(400):
|
||||||
angle = t * 0.05
|
angle = t * 0.05
|
||||||
x = np.sin(angle)
|
x = torch.sin(torch.tensor(angle))
|
||||||
y = np.cos(angle)
|
y = torch.cos(torch.tensor(angle))
|
||||||
line.set_data([x,-x], [y,-y])
|
line.set_data([x.item(), -x.item()], [y.item(), -y.item()])
|
||||||
fig.canvas.draw_idle()
|
fig.canvas.draw_idle()
|
||||||
fig.canvas.start_event_loop(1e-3)
|
fig.canvas.start_event_loop(1e-3)
|
||||||
|
|
||||||
@ -279,7 +276,7 @@ def verify_node(node, expected_type, expected_shape, method_name):
|
|||||||
assert False, "If you see this message, please report a bug in the autograder"
|
assert False, "If you see this message, please report a bug in the autograder"
|
||||||
|
|
||||||
if expected_type != 'loss':
|
if expected_type != 'loss':
|
||||||
assert all([(expected is '?' or actual == expected) for (actual, expected) in zip(node.detach().numpy().shape, expected_shape)]), (
|
assert all([(expected == '?' or actual == expected) for (actual, expected) in zip(node.shape, expected_shape)]), (
|
||||||
"{} should return an object with shape {}, got {}".format(
|
"{} should return an object with shape {}, got {}".format(
|
||||||
method_name, expected_shape, node.shape))
|
method_name, expected_shape, node.shape))
|
||||||
|
|
||||||
@ -288,7 +285,7 @@ def check_perceptron(tracker):
|
|||||||
import models
|
import models
|
||||||
|
|
||||||
print("Sanity checking perceptron...")
|
print("Sanity checking perceptron...")
|
||||||
np_random = np.random.RandomState(0)
|
torch.manual_seed(0)
|
||||||
|
|
||||||
# Check that the perceptron weights are initialized to a single vector with `dimensions` entries.
|
# Check that the perceptron weights are initialized to a single vector with `dimensions` entries.
|
||||||
for dimensions in range(1, 10):
|
for dimensions in range(1, 10):
|
||||||
@ -306,16 +303,16 @@ def check_perceptron(tracker):
|
|||||||
# Check that run returns a Tensor, and that the score in the node is correct
|
# Check that run returns a Tensor, and that the score in the node is correct
|
||||||
for dimensions in range(1, 10):
|
for dimensions in range(1, 10):
|
||||||
p = models.PerceptronModel(dimensions)
|
p = models.PerceptronModel(dimensions)
|
||||||
point = np_random.uniform(-10, 10, (1, dimensions))
|
point = torch.empty((1, dimensions)).uniform_(-10, 10)
|
||||||
score = p.run(Tensor(point))
|
score = p.run(point)
|
||||||
verify_node(score, 'tensor', (1,), "PerceptronModel.run()")
|
verify_node(score, 'tensor', (1,), "PerceptronModel.run()")
|
||||||
calculated_score = score.item()
|
calculated_score = score.item()
|
||||||
|
|
||||||
# Compare run output to actual value
|
# Compare run output to actual value
|
||||||
for param in p.parameters():
|
for param in p.parameters():
|
||||||
expected_score = float(np.dot(point.flatten(), param.detach().numpy().flatten()))
|
expected_score = float(torch.dot(point.flatten(), param.detach().flatten()))
|
||||||
|
|
||||||
assert np.isclose(calculated_score, expected_score), (
|
assert torch.isclose(torch.tensor(calculated_score), torch.tensor(expected_score)), (
|
||||||
"The score computed by PerceptronModel.run() ({:.4f}) does not match the expected score ({:.4f})".format(
|
"The score computed by PerceptronModel.run() ({:.4f}) does not match the expected score ({:.4f})".format(
|
||||||
calculated_score, expected_score))
|
calculated_score, expected_score))
|
||||||
|
|
||||||
@ -323,14 +320,14 @@ def check_perceptron(tracker):
|
|||||||
# case when a point lies exactly on the decision boundary
|
# case when a point lies exactly on the decision boundary
|
||||||
for dimensions in range(1, 10):
|
for dimensions in range(1, 10):
|
||||||
p = models.PerceptronModel(dimensions)
|
p = models.PerceptronModel(dimensions)
|
||||||
random_point = np_random.uniform(-10, 10, (1, dimensions))
|
random_point = torch.empty((1, dimensions)).uniform_(-10, 10)
|
||||||
for point in (random_point, np.zeros_like(random_point)):
|
for point in (random_point, torch.zeros_like(random_point)):
|
||||||
prediction = p.get_prediction(Tensor(point))
|
prediction = p.get_prediction(point)
|
||||||
assert prediction == 1 or prediction == -1, (
|
assert prediction == 1 or prediction == -1, (
|
||||||
"PerceptronModel.get_prediction() should return 1 or -1, not {}".format(
|
"PerceptronModel.get_prediction() should return 1 or -1, not {}".format(
|
||||||
prediction))
|
prediction))
|
||||||
|
|
||||||
expected_prediction = np.where(np.dot(point, p.get_weights().data.T) >= 0, 1, -1).item()
|
expected_prediction = torch.where(torch.dot(point.flatten(), p.get_weights().data.T.flatten()) >= 0, torch.tensor(1), torch.tensor(-1)).item()
|
||||||
assert prediction == expected_prediction, (
|
assert prediction == expected_prediction, (
|
||||||
"PerceptronModel.get_prediction() returned {}; expected {}".format(
|
"PerceptronModel.get_prediction() returned {}; expected {}".format(
|
||||||
prediction, expected_prediction))
|
prediction, expected_prediction))
|
||||||
@ -346,27 +343,27 @@ def check_perceptron(tracker):
|
|||||||
dimensions = 2
|
dimensions = 2
|
||||||
for multiplier in (-5, -2, 2, 5):
|
for multiplier in (-5, -2, 2, 5):
|
||||||
p = models.PerceptronModel(dimensions)
|
p = models.PerceptronModel(dimensions)
|
||||||
orig_weights = p.get_weights().data.reshape((1, dimensions)).detach().numpy().copy()
|
orig_weights = p.get_weights().data.reshape((1, dimensions)).detach().clone()
|
||||||
if np.abs(orig_weights).sum() == 0.0:
|
if torch.abs(orig_weights).sum() == 0.0:
|
||||||
# This autograder test doesn't work when weights are exactly zero
|
# This autograder test doesn't work when weights are exactly zero
|
||||||
continue
|
continue
|
||||||
|
|
||||||
point = multiplier * orig_weights
|
point = multiplier * orig_weights
|
||||||
|
|
||||||
sanity_dataset = backend.Custom_Dataset(
|
sanity_dataset = backend.CustomDataset(
|
||||||
x=np.tile(point, (500, 1)),
|
x=point.repeat((500, 1)),
|
||||||
y=np.ones((500, 1)) * -1.0
|
y=torch.ones((500, 1)) * -1.0
|
||||||
)
|
)
|
||||||
|
|
||||||
p.train(sanity_dataset)
|
p.train(sanity_dataset)
|
||||||
new_weights = p.get_weights().data.reshape((1, dimensions)).detach().numpy()
|
new_weights = p.get_weights().data.reshape((1, dimensions)).detach().clone()
|
||||||
|
|
||||||
if multiplier < 0:
|
if multiplier < 0:
|
||||||
expected_weights = orig_weights
|
expected_weights = orig_weights
|
||||||
else:
|
else:
|
||||||
expected_weights = orig_weights - point
|
expected_weights = orig_weights - point
|
||||||
|
|
||||||
if not np.all(new_weights == expected_weights):
|
if not torch.equal(new_weights, expected_weights):
|
||||||
print()
|
print()
|
||||||
print("Initial perceptron weights were: [{:.4f}, {:.4f}]".format(
|
print("Initial perceptron weights were: [{:.4f}, {:.4f}]".format(
|
||||||
orig_weights[0,0], orig_weights[0,1]))
|
orig_weights[0,0], orig_weights[0,1]))
|
||||||
@ -390,7 +387,7 @@ def check_perceptron(tracker):
|
|||||||
|
|
||||||
assert dataset.epoch != 0, "Perceptron code never iterated over the training data"
|
assert dataset.epoch != 0, "Perceptron code never iterated over the training data"
|
||||||
|
|
||||||
accuracy = np.mean(np.where(np.dot(dataset.x, model.get_weights().data.T) >= 0.0, 1.0, -1.0) == dataset.y)
|
accuracy = torch.mean((torch.where(torch.matmul(torch.tensor(dataset.x, dtype=torch.float32), model.get_weights().data.T) >= 0.0, 1.0, -1.0) == torch.tensor(dataset.y)).float())
|
||||||
if accuracy < 1.0:
|
if accuracy < 1.0:
|
||||||
print("The weights learned by your perceptron correctly classified {:.2%} of training examples".format(accuracy))
|
print("The weights learned by your perceptron correctly classified {:.2%} of training examples".format(accuracy))
|
||||||
print("To receive full points for this question, your perceptron must converge to 100% accuracy")
|
print("To receive full points for this question, your perceptron must converge to 100% accuracy")
|
||||||
@ -441,7 +438,7 @@ def check_regression(tracker):
|
|||||||
error = labels - train_predicted
|
error = labels - train_predicted
|
||||||
sanity_loss = torch.mean((error.detach())**2)
|
sanity_loss = torch.mean((error.detach())**2)
|
||||||
|
|
||||||
assert np.isclose(train_loss, sanity_loss), (
|
assert torch.isclose(torch.tensor(train_loss), sanity_loss), (
|
||||||
"RegressionModel.get_loss() returned a loss of {:.4f}, "
|
"RegressionModel.get_loss() returned a loss of {:.4f}, "
|
||||||
"but the autograder computed a loss of {:.4f} "
|
"but the autograder computed a loss of {:.4f} "
|
||||||
"based on the output of RegressionModel()".format(
|
"based on the output of RegressionModel()".format(
|
||||||
@ -484,9 +481,9 @@ def check_digit_classification(tracker):
|
|||||||
model.train(dataset)
|
model.train(dataset)
|
||||||
|
|
||||||
|
|
||||||
test_logits = model.run(torch.tensor(dataset.test_images)).data
|
test_logits = model.run(torch.tensor(dataset.test_images)).detach().cpu()
|
||||||
test_predicted = np.argmax(test_logits, axis=1).detach().numpy()
|
test_predicted = torch.argmax(test_logits, axis=1)
|
||||||
test_accuracy = np.mean(test_predicted == dataset.test_labels)
|
test_accuracy = torch.mean(torch.eq(test_predicted, torch.tensor(dataset.test_labels)).float())
|
||||||
|
|
||||||
accuracy_threshold = 0.97
|
accuracy_threshold = 0.97
|
||||||
if test_accuracy >= accuracy_threshold:
|
if test_accuracy >= accuracy_threshold:
|
||||||
@ -553,10 +550,10 @@ def check_convolution(tracker):
|
|||||||
dataset = backend.DigitClassificationDataset2(model)
|
dataset = backend.DigitClassificationDataset2(model)
|
||||||
|
|
||||||
def conv2d(a, f):
|
def conv2d(a, f):
|
||||||
s = f.shape + tuple(np.subtract(a.shape, f.shape) + 1)
|
s = f.shape + tuple(torch.tensor(a.shape) - torch.tensor(f.shape) + 1)
|
||||||
strd = np.lib.stride_tricks.as_strided
|
strd = torch.as_strided
|
||||||
subM = strd(a, shape = s, strides = a.strides * 2)
|
subM = strd(a, size = s, stride = a.stride() * 2)
|
||||||
return np.einsum('ij,ijkl->kl', f, subM)
|
return torch.einsum('ij,ijkl->kl', f, subM)
|
||||||
|
|
||||||
detected_parameters = None
|
detected_parameters = None
|
||||||
|
|
||||||
@ -575,20 +572,20 @@ def check_convolution(tracker):
|
|||||||
assert grad_y[0] != None, "Node returned from RegressionModel.get_loss() does not depend on the provided labels (y)"
|
assert grad_y[0] != None, "Node returned from RegressionModel.get_loss() does not depend on the provided labels (y)"
|
||||||
|
|
||||||
for matrix_size in (2, 4, 6): #Test 3 random convolutions to test convolve() function
|
for matrix_size in (2, 4, 6): #Test 3 random convolutions to test convolve() function
|
||||||
weights = np.random.rand(2,2)
|
weights = torch.rand(2,2)
|
||||||
input = np.random.rand(matrix_size, matrix_size)
|
input = torch.rand(matrix_size, matrix_size)
|
||||||
student_output = models.Convolve(torch.Tensor(input), torch.Tensor(weights))
|
student_output = models.Convolve(input, weights)
|
||||||
actual_output = conv2d(input,weights)
|
actual_output = conv2d(input,weights)
|
||||||
assert np.isclose(student_output, actual_output).all(), "The convolution returned by Convolve() does not match expected output"
|
assert torch.isclose(student_output, actual_output).all(), "The convolution returned by Convolve() does not match expected output"
|
||||||
|
|
||||||
tracker.add_points(1/2) # Partial credit for testing whether convolution function works
|
tracker.add_points(1/2) # Partial credit for testing whether convolution function works
|
||||||
|
|
||||||
model.train(dataset)
|
model.train(dataset)
|
||||||
|
|
||||||
|
|
||||||
test_logits = model.run(torch.tensor(dataset.test_images)).data
|
test_logits = model.run(torch.tensor(dataset.test_images)).detach().cpu()
|
||||||
test_predicted = np.argmax(test_logits, axis=1).detach().numpy()
|
test_predicted = torch.argmax(test_logits, axis=1)
|
||||||
test_accuracy = np.mean(test_predicted == dataset.test_labels)
|
test_accuracy = torch.mean(torch.eq(test_predicted, torch.tensor(dataset.test_labels)).float())
|
||||||
|
|
||||||
accuracy_threshold = 0.80
|
accuracy_threshold = 0.80
|
||||||
if test_accuracy >= accuracy_threshold:
|
if test_accuracy >= accuracy_threshold:
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import collections
|
import collections
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import os
|
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -10,7 +9,6 @@ from torch import nn
|
|||||||
import torch
|
import torch
|
||||||
from torch.utils.data import Dataset, DataLoader
|
from torch.utils.data import Dataset, DataLoader
|
||||||
|
|
||||||
|
|
||||||
use_graphics = True
|
use_graphics = True
|
||||||
|
|
||||||
def maybe_sleep_and_close(seconds):
|
def maybe_sleep_and_close(seconds):
|
||||||
@ -38,37 +36,24 @@ def get_data_path(filename):
|
|||||||
raise Exception("Could not find data file: {}".format(filename))
|
raise Exception("Could not find data file: {}".format(filename))
|
||||||
return path
|
return path
|
||||||
|
|
||||||
class Custom_Dataset(Dataset):
|
class CustomDataset(Dataset):
|
||||||
def __init__(self, x, y, transform=None):
|
def __init__(self, x, y, transform=None):
|
||||||
assert isinstance(x, np.ndarray)
|
self.x = torch.tensor(x, dtype=torch.float32)
|
||||||
assert isinstance(y, np.ndarray)
|
self.y = torch.tensor(y, dtype=torch.float32)
|
||||||
assert np.issubdtype(x.dtype, np.floating)
|
|
||||||
assert np.issubdtype(y.dtype, np.floating)
|
|
||||||
assert x.ndim == 2
|
|
||||||
assert y.ndim == 2
|
|
||||||
assert x.shape[0] == y.shape[0]
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.transform = transform
|
self.transform = transform
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.x)
|
return len(self.x)
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
def __getitem__(self, idx):
|
||||||
if torch.is_tensor(idx):
|
|
||||||
idx = idx.tolist()
|
|
||||||
|
|
||||||
label = self.y[idx]
|
|
||||||
x = self.x[idx]
|
x = self.x[idx]
|
||||||
|
y = self.y[idx]
|
||||||
sample = {'x': torch.Tensor(x), 'label': torch.Tensor(label)}
|
sample = {'x': x, 'label': y}
|
||||||
|
|
||||||
if self.transform:
|
if self.transform:
|
||||||
sample = self.transform(sample)
|
sample = self.transform(sample)
|
||||||
|
|
||||||
return sample
|
|
||||||
|
|
||||||
|
|
||||||
|
return sample
|
||||||
|
|
||||||
def get_validation_accuracy(self):
|
def get_validation_accuracy(self):
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
@ -76,7 +61,7 @@ class Custom_Dataset(Dataset):
|
|||||||
"In this assignment, only the Digit Classification and Language "
|
"In this assignment, only the Digit Classification and Language "
|
||||||
"Identification datasets have validation data.")
|
"Identification datasets have validation data.")
|
||||||
|
|
||||||
class PerceptronDataset(Custom_Dataset):
|
class PerceptronDataset(CustomDataset):
|
||||||
def __init__(self, model):
|
def __init__(self, model):
|
||||||
points = 500
|
points = 500
|
||||||
x = np.hstack([np.random.randn(points, 2), np.ones((points, 1))])
|
x = np.hstack([np.random.randn(points, 2), np.ones((points, 1))])
|
||||||
@ -103,9 +88,7 @@ class PerceptronDataset(Custom_Dataset):
|
|||||||
self.line = line
|
self.line = line
|
||||||
self.text = text
|
self.text = text
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
def __getitem__(self, idx):
|
||||||
self.epoch += 1
|
self.epoch += 1
|
||||||
|
|
||||||
@ -115,8 +98,6 @@ class PerceptronDataset(Custom_Dataset):
|
|||||||
x = self.x[idx]
|
x = self.x[idx]
|
||||||
y = self.y[idx]
|
y = self.y[idx]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if use_graphics and time.time() - self.last_update > 0.01:
|
if use_graphics and time.time() - self.last_update > 0.01:
|
||||||
w = self.model.get_weights().data.flatten()
|
w = self.model.get_weights().data.flatten()
|
||||||
limits = self.limits
|
limits = self.limits
|
||||||
@ -133,9 +114,9 @@ class PerceptronDataset(Custom_Dataset):
|
|||||||
self.fig.canvas.start_event_loop(1e-3)
|
self.fig.canvas.start_event_loop(1e-3)
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
|
|
||||||
return {'x': torch.tensor(x, dtype=torch.float32), 'label': torch.tensor(y, dtype=torch.float32)}
|
return {'x': x, 'label': y}
|
||||||
|
|
||||||
class RegressionDataset(Custom_Dataset):
|
class RegressionDataset(CustomDataset):
|
||||||
def __init__(self, model):
|
def __init__(self, model):
|
||||||
x = np.expand_dims(np.linspace(-2 * np.pi, 2 * np.pi, num=200), axis=1)
|
x = np.expand_dims(np.linspace(-2 * np.pi, 2 * np.pi, num=200), axis=1)
|
||||||
np.random.RandomState(0).shuffle(x)
|
np.random.RandomState(0).shuffle(x)
|
||||||
@ -161,13 +142,8 @@ class RegressionDataset(Custom_Dataset):
|
|||||||
self.text = text
|
self.text = text
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.x)
|
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
def __getitem__(self, idx):
|
||||||
|
|
||||||
data = super().__getitem__(idx)
|
data = super().__getitem__(idx)
|
||||||
|
|
||||||
x = data['x']
|
x = data['x']
|
||||||
y = data['label']
|
y = data['label']
|
||||||
|
|
||||||
@ -175,18 +151,17 @@ class RegressionDataset(Custom_Dataset):
|
|||||||
|
|
||||||
if use_graphics and time.time() - self.last_update > 0.1:
|
if use_graphics and time.time() - self.last_update > 0.1:
|
||||||
predicted = self.model(torch.tensor(self.x, dtype=torch.float32)).data
|
predicted = self.model(torch.tensor(self.x, dtype=torch.float32)).data
|
||||||
loss = self.model.get_loss(
|
loss = self.model.get_loss(x, y).data
|
||||||
x, y).data
|
|
||||||
self.learned.set_data(self.x[self.argsort_x], predicted[self.argsort_x])
|
self.learned.set_data(self.x[self.argsort_x], predicted[self.argsort_x])
|
||||||
self.text.set_text("processed: {:,}\nloss: {:.6f}".format(
|
self.text.set_text("processed: {:,}\nloss: {:.6f}".format(
|
||||||
self.processed, loss))
|
self.processed, loss))
|
||||||
self.fig.canvas.draw_idle()
|
self.fig.canvas.draw_idle()
|
||||||
self.fig.canvas.start_event_loop(1e-3)
|
self.fig.canvas.start_event_loop(1e-3)
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
|
|
||||||
return {'x': x, 'label': y}
|
return {'x': x, 'label': y}
|
||||||
|
|
||||||
class DigitClassificationDataset(Custom_Dataset):
|
class DigitClassificationDataset(CustomDataset):
|
||||||
def __init__(self, model):
|
def __init__(self, model):
|
||||||
mnist_path = get_data_path("mnist.npz")
|
mnist_path = get_data_path("mnist.npz")
|
||||||
|
|
||||||
@ -252,34 +227,25 @@ class DigitClassificationDataset(Custom_Dataset):
|
|||||||
self.status = status
|
self.status = status
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
|
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
def __getitem__(self, idx):
|
||||||
|
|
||||||
|
|
||||||
data = super().__getitem__(idx)
|
data = super().__getitem__(idx)
|
||||||
|
|
||||||
x = data['x']
|
x = data['x']
|
||||||
y = data['label']
|
y = data['label']
|
||||||
|
|
||||||
if use_graphics and time.time() - self.last_update > 1:
|
if use_graphics and time.time() - self.last_update > 1:
|
||||||
dev_logits = self.model.run(torch.tensor(self.dev_images)).data
|
dev_logits = self.model.run(torch.tensor(self.dev_images, dtype=torch.float32)).detach().cpu()
|
||||||
dev_predicted = np.argmax(dev_logits, axis=1).detach().numpy()
|
dev_predicted = torch.argmax(dev_logits, axis=1)
|
||||||
dev_probs = np.exp(nn.functional.log_softmax(dev_logits))
|
dev_probs = torch.exp(nn.functional.log_softmax(dev_logits, dim=1))
|
||||||
|
|
||||||
dev_accuracy = np.mean(dev_predicted == self.dev_labels)
|
dev_accuracy = torch.mean(torch.eq(dev_predicted, torch.tensor(self.dev_labels)).float())
|
||||||
self.status.set_text(
|
self.status.set_text(
|
||||||
"validation accuracy: "
|
"validation accuracy: {:.2%}".format(dev_accuracy))
|
||||||
"{:.2%}".format(
|
|
||||||
dev_accuracy))
|
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
predicted = dev_predicted[self.dev_labels == i]
|
predicted = dev_predicted[self.dev_labels == i]
|
||||||
probs = dev_probs[self.dev_labels == i][:, i]
|
probs = dev_probs[self.dev_labels == i][:, i]
|
||||||
linspace = np.linspace(
|
linspace = np.linspace(0, len(probs) - 1, self.samples).astype(int)
|
||||||
0, len(probs) - 1, self.samples).astype(int)
|
|
||||||
indices = probs.argsort()[linspace]
|
indices = probs.argsort()[linspace]
|
||||||
for j, (prob, image) in enumerate(zip(
|
for j, (prob, image) in enumerate(zip(probs[indices], self.dev_images[self.dev_labels == i][indices])):
|
||||||
probs[indices],
|
|
||||||
self.dev_images[self.dev_labels == i][indices])):
|
|
||||||
self.images[i][j].set_data(image.reshape((28, 28)))
|
self.images[i][j].set_data(image.reshape((28, 28)))
|
||||||
left = prob * (self.width - 1) * 28
|
left = prob * (self.width - 1) * 28
|
||||||
if predicted[indices[j]] == i:
|
if predicted[indices[j]] == i:
|
||||||
@ -287,29 +253,22 @@ class DigitClassificationDataset(Custom_Dataset):
|
|||||||
self.texts[i][j].set_text("")
|
self.texts[i][j].set_text("")
|
||||||
else:
|
else:
|
||||||
self.images[i][j].set_cmap("Reds")
|
self.images[i][j].set_cmap("Reds")
|
||||||
self.texts[i][j].set_text(predicted[indices[j]])
|
self.texts[i][j].set_text(predicted[indices[j]].detach().cpu().numpy())
|
||||||
self.texts[i][j].set_x(left + 14)
|
self.texts[i][j].set_x(left + 14)
|
||||||
self.images[i][j].set_extent([left, left + 28, 0, 28])
|
self.images[i][j].set_extent([left, left + 28, 0, 28])
|
||||||
self.fig.canvas.draw_idle()
|
self.fig.canvas.draw_idle()
|
||||||
self.fig.canvas.start_event_loop(1e-3)
|
self.fig.canvas.start_event_loop(1e-3)
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
|
|
||||||
if(self.num_items == len(self.x)):
|
|
||||||
self.current_accuracy = self.num_right_items/len(self.x)
|
|
||||||
self.num_right_items = 0
|
|
||||||
self.epoch += 1
|
|
||||||
|
|
||||||
return {'x': x, 'label': y}
|
return {'x': x, 'label': y}
|
||||||
|
|
||||||
def get_validation_accuracy(self):
|
def get_validation_accuracy(self):
|
||||||
dev_logits = self.model.run(torch.tensor(self.dev_images)).data
|
dev_logits = self.model.run(torch.tensor(self.dev_images, dtype=torch.float32)).data
|
||||||
dev_predicted = np.argmax(dev_logits, axis=1).detach().numpy()
|
dev_predicted = torch.argmax(dev_logits, axis=1).detach()
|
||||||
dev_probs = np.exp(nn.functional.log_softmax(dev_logits))
|
dev_accuracy = (dev_predicted == self.dev_labels).mean()
|
||||||
|
|
||||||
dev_accuracy = np.mean(dev_predicted == self.dev_labels)
|
|
||||||
return dev_accuracy
|
return dev_accuracy
|
||||||
|
|
||||||
class LanguageIDDataset(Custom_Dataset):
|
class LanguageIDDataset(CustomDataset):
|
||||||
def __init__(self, model):
|
def __init__(self, model):
|
||||||
self.model = model
|
self.model = model
|
||||||
|
|
||||||
@ -330,7 +289,7 @@ class LanguageIDDataset(Custom_Dataset):
|
|||||||
self.test_buckets = data['test_buckets']
|
self.test_buckets = data['test_buckets']
|
||||||
|
|
||||||
self.epoch = 0
|
self.epoch = 0
|
||||||
self.bucket_weights = self.train_buckets[:,1] - self.train_buckets[:,0]
|
self.bucket_weights = self.train_buckets[:, 1] - self.train_buckets[:, 0]
|
||||||
self.bucket_weights = self.bucket_weights / float(self.bucket_weights.sum())
|
self.bucket_weights = self.bucket_weights / float(self.bucket_weights.sum())
|
||||||
|
|
||||||
self.chars_print = self.chars
|
self.chars_print = self.chars
|
||||||
@ -358,14 +317,12 @@ alphabet above have been substituted with ASCII symbols.""".strip())
|
|||||||
max_word_len = self.dev_x.shape[1]
|
max_word_len = self.dev_x.shape[1]
|
||||||
max_lang_len = max([len(x) for x in self.language_names])
|
max_lang_len = max([len(x) for x in self.language_names])
|
||||||
|
|
||||||
self.predicted_template = u"Pred: {:<NUM}".replace('NUM',
|
self.predicted_template = u"Pred: {:<NUM}".replace('NUM', str(max_lang_len))
|
||||||
str(max_lang_len))
|
|
||||||
|
|
||||||
self.word_template = u" "
|
self.word_template = u" "
|
||||||
self.word_template += u"{:<NUM} ".replace('NUM', str(max_word_len))
|
self.word_template += u"{:<NUM} ".replace('NUM', str(max_word_len))
|
||||||
self.word_template += u"{:<NUM} ({:6.1%})".replace('NUM', str(max_lang_len))
|
self.word_template += u"{:<NUM} ({:6.1%})".replace('NUM', str(max_lang_len))
|
||||||
self.word_template += u" {:<NUM} ".replace('NUM',
|
self.word_template += u" {:<NUM} ".replace('NUM', str(max_lang_len + len('Pred: ')))
|
||||||
str(max_lang_len + len('Pred: ')))
|
|
||||||
for i in range(len(self.language_names)):
|
for i in range(len(self.language_names)):
|
||||||
self.word_template += u"|{}".format(self.language_codes[i])
|
self.word_template += u"|{}".format(self.language_codes[i])
|
||||||
self.word_template += "{probs[" + str(i) + "]:4.0%}"
|
self.word_template += "{probs[" + str(i) + "]:4.0%}"
|
||||||
@ -374,22 +331,21 @@ alphabet above have been substituted with ASCII symbols.""".strip())
|
|||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.train_x)
|
return len(self.train_x)
|
||||||
|
|
||||||
def _encode(self, inp_x, inp_y):
|
def _encode(self, inp_x, inp_y):
|
||||||
xs = []
|
xs = []
|
||||||
for i in range(inp_x.shape[1]):
|
for i in range(inp_x.shape[1]):
|
||||||
|
if np.all(np.array(inp_x[:, i]) == -1):
|
||||||
if np.all(np.array(inp_x[:,i]) == -1):
|
|
||||||
break
|
break
|
||||||
assert not np.any(np.array(inp_x[:,i]) == -1), (
|
assert not np.any(np.array(inp_x[:, i]) == -1), (
|
||||||
"Please report this error in the project: batching by length was done incorrectly in the provided code")
|
"Please report this error in the project: batching by length was done incorrectly in the provided code")
|
||||||
x = np.eye(len(self.chars))[np.array(inp_x[:,i], dtype=int)]
|
x = np.eye(len(self.chars))[np.array(inp_x[:, i], dtype=int)]
|
||||||
xs.append(x)
|
xs.append(x)
|
||||||
y = np.eye(len(self.language_names))[inp_y]
|
y = np.eye(len(self.language_names))[inp_y]
|
||||||
j = [[0 for j in range(47)]]
|
j = [[0 for _ in range(47)]]
|
||||||
|
|
||||||
if(len(inp_x) == 1):
|
if len(inp_x) == 1:
|
||||||
return torch.nn.functional.pad(torch.tensor(xs, dtype=torch.float),(0,0,0,0,0,10 - len(xs))), torch.tensor(y, dtype=torch.float)
|
return nn.functional.pad(torch.tensor(xs, dtype=torch.float), (0, 0, 0, 0, 0, 10 - len(xs))), torch.tensor(y, dtype=torch.float)
|
||||||
|
|
||||||
return torch.tensor(xs, dtype=torch.float), torch.tensor(y, dtype=torch.float)
|
return torch.tensor(xs, dtype=torch.float), torch.tensor(y, dtype=torch.float)
|
||||||
|
|
||||||
@ -416,8 +372,7 @@ alphabet above have been substituted with ASCII symbols.""".strip())
|
|||||||
|
|
||||||
all_predicted.extend(list(predicted.data))
|
all_predicted.extend(list(predicted.data))
|
||||||
all_correct.extend(list(data_y[start:end]))
|
all_correct.extend(list(data_y[start:end]))
|
||||||
sftmax = nn.Softmax()
|
all_predicted_probs = [nn.functional.softmax(torch.tensor(i), dim=-1) for i in all_predicted]
|
||||||
all_predicted_probs = [sftmax(torch.tensor(i)) for i in all_predicted]
|
|
||||||
|
|
||||||
all_predicted = [i.argmax() for i in all_predicted_probs]
|
all_predicted = [i.argmax() for i in all_predicted_probs]
|
||||||
all_correct = np.asarray(all_correct)
|
all_correct = np.asarray(all_correct)
|
||||||
@ -425,34 +380,18 @@ alphabet above have been substituted with ASCII symbols.""".strip())
|
|||||||
return all_predicted_probs, all_predicted, all_correct
|
return all_predicted_probs, all_predicted, all_correct
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
def __getitem__(self, idx):
|
||||||
|
|
||||||
if torch.is_tensor(idx):
|
if torch.is_tensor(idx):
|
||||||
idx = idx.tolist()
|
idx = idx.tolist()
|
||||||
|
|
||||||
|
|
||||||
ret = self._encode(self.train_x[idx:idx+1], self.train_y[idx:idx+1])
|
ret = self._encode(self.train_x[idx:idx+1], self.train_y[idx:idx+1])
|
||||||
return {'x': torch.squeeze(ret[0]), 'label': torch.squeeze(ret[1])}
|
return {'x': torch.squeeze(ret[0]), 'label': torch.squeeze(ret[1])}
|
||||||
|
|
||||||
def get_validation_accuracy(self):
|
def get_validation_accuracy(self):
|
||||||
dev_predicted_probs, dev_predicted, dev_correct = self._predict()
|
dev_predicted_probs, dev_predicted, dev_correct = self._predict('dev')
|
||||||
dev_accuracy = np.mean(dev_predicted == dev_correct)
|
dev_accuracy = (torch.tensor(dev_predicted) == torch.tensor(dev_correct)).float().mean().item()
|
||||||
return dev_accuracy
|
return dev_accuracy
|
||||||
|
|
||||||
def collate(self, batch):
|
|
||||||
'''
|
|
||||||
Padds batch of variable length
|
|
||||||
|
|
||||||
|
class DigitClassificationDataset2(CustomDataset):
|
||||||
'''
|
|
||||||
## get sequence lengths
|
|
||||||
lengths = torch.tensor([ t['x'].shape[0] for t in batch ])
|
|
||||||
## padd
|
|
||||||
batch_x = [ torch.Tensor(t['x']) for t in batch ]
|
|
||||||
batch_y = [ torch.Tensor(t['labels']) for t in batch ]
|
|
||||||
return {'x':batch_x,'label':batch_y}
|
|
||||||
|
|
||||||
|
|
||||||
class DigitClassificationDataset2(Custom_Dataset):
|
|
||||||
def __init__(self, model):
|
def __init__(self, model):
|
||||||
mnist_path = get_data_path("mnist.npz")
|
mnist_path = get_data_path("mnist.npz")
|
||||||
training_size = 200
|
training_size = 200
|
||||||
@ -487,28 +426,20 @@ class DigitClassificationDataset2(Custom_Dataset):
|
|||||||
images = collections.defaultdict(list)
|
images = collections.defaultdict(list)
|
||||||
texts = collections.defaultdict(list)
|
texts = collections.defaultdict(list)
|
||||||
for i in reversed(range(10)):
|
for i in reversed(range(10)):
|
||||||
ax[i] = plt.subplot2grid((30, 1), (3 * i, 0), 2, 1,
|
ax[i] = plt.subplot2grid((30, 1), (3 * i, 0), 2, 1, sharex=ax.get(9))
|
||||||
sharex=ax.get(9))
|
|
||||||
plt.setp(ax[i].get_xticklabels(), visible=i == 9)
|
plt.setp(ax[i].get_xticklabels(), visible=i == 9)
|
||||||
ax[i].set_yticks([])
|
ax[i].set_yticks([])
|
||||||
ax[i].text(-0.03, 0.5, i, transform=ax[i].transAxes,
|
ax[i].text(-0.03, 0.5, i, transform=ax[i].transAxes, va="center")
|
||||||
va="center")
|
|
||||||
ax[i].set_xlim(0, 28 * width)
|
ax[i].set_xlim(0, 28 * width)
|
||||||
ax[i].set_ylim(0, 28)
|
ax[i].set_ylim(0, 28)
|
||||||
for j in range(samples):
|
for j in range(samples):
|
||||||
images[i].append(ax[i].imshow(
|
images[i].append(ax[i].imshow(np.zeros((28, 28)), vmin=0, vmax=1, cmap="Greens", alpha=0.3))
|
||||||
np.zeros((28, 28)), vmin=0, vmax=1, cmap="Greens",
|
texts[i].append(ax[i].text(0, 0, "", ha="center", va="top", fontsize="smaller"))
|
||||||
alpha=0.3))
|
|
||||||
texts[i].append(ax[i].text(
|
|
||||||
0, 0, "", ha="center", va="top", fontsize="smaller"))
|
|
||||||
ax[9].set_xticks(np.linspace(0, 28 * width, 11))
|
ax[9].set_xticks(np.linspace(0, 28 * width, 11))
|
||||||
ax[9].set_xticklabels(
|
ax[9].set_xticklabels(["{:.1f}".format(num) for num in np.linspace(0, 1, 11)])
|
||||||
["{:.1f}".format(num) for num in np.linspace(0, 1, 11)])
|
|
||||||
ax[9].tick_params(axis="x", pad=16)
|
ax[9].tick_params(axis="x", pad=16)
|
||||||
ax[9].set_xlabel("Probability of Correct Label")
|
ax[9].set_xlabel("Probability of Correct Label")
|
||||||
status = ax[0].text(
|
status = ax[0].text(0.5, 1.5, "", transform=ax[0].transAxes, ha="center", va="bottom")
|
||||||
0.5, 1.5, "", transform=ax[0].transAxes, ha="center",
|
|
||||||
va="bottom")
|
|
||||||
plt.show(block=False)
|
plt.show(block=False)
|
||||||
|
|
||||||
self.width = width
|
self.width = width
|
||||||
@ -519,65 +450,46 @@ class DigitClassificationDataset2(Custom_Dataset):
|
|||||||
self.status = status
|
self.status = status
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
|
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
def __getitem__(self, idx):
|
||||||
|
|
||||||
|
|
||||||
data = super().__getitem__(idx)
|
data = super().__getitem__(idx)
|
||||||
|
|
||||||
x = data['x']
|
x = data['x']
|
||||||
y = data['label']
|
y = data['label']
|
||||||
|
|
||||||
if use_graphics and time.time() - self.last_update > 1:
|
if use_graphics and time.time() - self.last_update > 1:
|
||||||
dev_logits = self.model.run(torch.tensor(self.dev_images)).data
|
dev_logits = self.model.run(torch.tensor(self.dev_images, dtype=torch.float32)).detach().cpu()
|
||||||
dev_predicted = np.argmax(dev_logits, axis=1).detach().numpy()
|
dev_predicted = torch.argmax(dev_logits, axis=1)
|
||||||
dev_probs = np.exp(nn.functional.log_softmax(dev_logits))
|
dev_probs = torch.exp(nn.functional.log_softmax(dev_logits, dim=1))
|
||||||
|
|
||||||
dev_accuracy = np.mean(dev_predicted == self.dev_labels)
|
dev_accuracy = torch.mean(torch.eq(dev_predicted, torch.tensor(self.dev_labels)).float())
|
||||||
self.status.set_text(
|
self.status.set_text("validation accuracy: {:.2%}".format(dev_accuracy))
|
||||||
"validation accuracy: "
|
|
||||||
"{:.2%}".format(
|
|
||||||
dev_accuracy))
|
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
predicted = dev_predicted[self.dev_labels == i]
|
predicted = dev_predicted[self.dev_labels == i]
|
||||||
probs = dev_probs[self.dev_labels == i][:, i]
|
probs = dev_probs[self.dev_labels == i][:, i]
|
||||||
linspace = np.linspace(
|
linspace = np.linspace(0, len(probs) - 1, self.samples).astype(int)
|
||||||
0, len(probs) - 1, self.samples).astype(int)
|
|
||||||
indices = probs.argsort()[linspace]
|
indices = probs.argsort()[linspace]
|
||||||
for j, (prob, image) in enumerate(zip(
|
for j, (prob, image) in enumerate(zip(probs[indices], self.dev_images[self.dev_labels == i][indices])):
|
||||||
probs[indices],
|
|
||||||
self.dev_images[self.dev_labels == i][indices])):
|
|
||||||
self.images[i][j].set_data(image.reshape((28, 28)))
|
self.images[i][j].set_data(image.reshape((28, 28)))
|
||||||
left = prob * (self.width - 1) * 28
|
left = (prob * (self.width - 1) * 28).detach().cpu().numpy()
|
||||||
if predicted[indices[j]] == i:
|
if predicted[indices[j]] == i:
|
||||||
self.images[i][j].set_cmap("Greens")
|
self.images[i][j].set_cmap("Greens")
|
||||||
self.texts[i][j].set_text("")
|
self.texts[i][j].set_text("")
|
||||||
else:
|
else:
|
||||||
self.images[i][j].set_cmap("Reds")
|
self.images[i][j].set_cmap("Reds")
|
||||||
self.texts[i][j].set_text(predicted[indices[j]])
|
self.texts[i][j].set_text(predicted[indices[j]].detach().cpu().numpy())
|
||||||
self.texts[i][j].set_x(left + 14)
|
self.texts[i][j].set_x(left + 14)
|
||||||
self.images[i][j].set_extent([left, left + 28, 0, 28])
|
self.images[i][j].set_extent([left, left + 28, 0, 28])
|
||||||
self.fig.canvas.draw_idle()
|
self.fig.canvas.draw_idle()
|
||||||
self.fig.canvas.start_event_loop(1e-3)
|
self.fig.canvas.start_event_loop(1e-3)
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
|
|
||||||
if(self.num_items == len(self.x)):
|
|
||||||
self.current_accuracy = self.num_right_items/len(self.x)
|
|
||||||
self.num_right_items = 0
|
|
||||||
self.epoch += 1
|
|
||||||
|
|
||||||
return {'x': x, 'label': y}
|
return {'x': x, 'label': y}
|
||||||
|
|
||||||
def get_validation_accuracy(self):
|
def get_validation_accuracy(self):
|
||||||
dev_logits = self.model.run(torch.tensor(self.dev_images)).data
|
dev_logits = self.model.run(torch.tensor(self.dev_images, dtype=torch.float32)).data
|
||||||
dev_predicted = np.argmax(dev_logits, axis=1).detach().numpy()
|
dev_predicted = torch.argmax(dev_logits, axis=1).detach()
|
||||||
dev_probs = np.exp(nn.functional.log_softmax(dev_logits))
|
dev_accuracy = torch.mean(torch.eq(dev_predicted, torch.tensor(self.dev_labels)).float())
|
||||||
|
|
||||||
dev_accuracy = np.mean(dev_predicted == self.dev_labels)
|
|
||||||
return dev_accuracy
|
return dev_accuracy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
import models
|
import models
|
||||||
model = models.PerceptronModel(3)
|
model = models.PerceptronModel(3)
|
||||||
@ -598,4 +510,3 @@ def main():
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user