def setUp(self): """General Utilities Testing Configuration. Sets up the necessary information to begin testing. """ self.data_shape = 100, 20 self.label = '`visualization`' self.max_suplots = 20 self.n_tests = 20 self.name = __name__ self.shapes = {} self.wrappers = { n: _ModelWrapperClass(m) for n, m in _active_models.iteritems() } p_to_shape = lambda p: p.shape """callable: Maps parameters to their matrix dimensions.""" for name, ModelWrapper in self.wrappers.iteritems(): ModelWrapper.model = dict(X=_random_matrix(self.data_shape)) self.shapes[name] = _compose(tuple, map)(p_to_shape, ModelWrapper._model.params) # Model string should indicate that all parameters are set at this # point. self.assertIsNotNone(ModelWrapper._model.params) del ModelWrapper._model.params # Model string should indicate unset parameters at this point. self.assertIsNone(ModelWrapper._model.params)
def test_random_visualization_plot_feature(self): """`visualization.Visualization.plot_feature`: Randomized Validator. Tests the behavior of `Visualization.plot_feature` by feeding it randomly generated arguments. Raises: AssertionError: If `Visualization.plot_feature` needs debugging. """ for i in range(self.n_tests): for ModelWrapper in self.wrappers.values(): X = _random_matrix(self.data_shape) """np.matrix: Random-valued feature set.""" Y = _random_matrix((self.data_shape[0], 1)) """np.matrix: Random-valued observation set.""" v = Visualization("Title", (3, 3)) """Visualization: Plotter instance.""" # Intialize model parameters to random values. ModelWrapper.model = dict(X=X) for i in range(9): x, y, error = v._plot_feature(X, Y, i, ModelWrapper) """(list of float, :obj:`list of float`): X- and y-values to plot.""" # `x` should be a list of floats. self.assertIsInstance(x, list) map(_appendargs(self.assertIsInstance, float), x) # Number of `x` values should match number of data points in # `X`. self.assertEqual(len(x), X.shape[0]) # `x` values should match all values in `X`. self.assertEqual(*map(_np.linalg.norm, [x, X[:, i]])) # `y` should be a dict. self.assertIsInstance(y, dict) for j, values in _compose(enumerate, y.values)(): # `values` should be a list of floats. self.assertIsInstance(values, list) map(_appendargs(self.assertIsInstance, float), values) # Number of values in `values` should match number of # data points in `Y`. self.assertEqual(len(values), Y.shape[0]) if j == 0: # Observation values should match all values in `Y`. self.assertEqual( *map(_np.linalg.norm, [values, Y[:, 0]])) v.close()
def test_random_batches(self): """`stats.batches`: Randomized Validator. Tests the behavior of `batches` by feeding it randomly generated arguments. Raises: AssertionError: If `batches` needs debugging. """ n, d = self.data_shape """(int, int): Number of data points and number of features.""" step_size = _compose(int, _np.floor)((n - 1) / float(self.n_tests)) """int: Amount by which to increase batch-size `k` after each iteration.""" for k in range(1, n, step_size): X = _random_matrix(self.data_shape) """np.matrix: Random-valued feature set.""" Y = _random_matrix((self.data_shape[0], 1)) """np.matrix: Random-valued observation set.""" target_len = max(2, int(_np.floor(n / float(min(n, k))))) """int: Expected number of batches.""" buckets = batches(X, Y, k) """list of np.matrix: Test input.""" # `buckets` should be a list. self.assertIsInstance(buckets, list) # Each bucket `b` in `buckets` should be a matrix. for b in buckets: self.assertIsInstance(b, _np.matrix) # Number of buckets should match the total number of data points # (floor) divided by the number of data points per bucket. self.assertEqual(len(buckets), target_len) # Total number of data points across all buckets should match # original number of data points. self.assertEqual(sum([b.shape[0] for b in buckets]), n) norm_buckets = sum([ sum([_np.linalg.norm(b[j, :])**2 for j in range(b.shape[0])]) for b in buckets ]) """float: Sum of the sum of the norms of all rows in all buckets.""" norm = sum( [_np.linalg.norm(X[i, :])**2 + Y[i, 0]**2 for i in range(n)]) """float: Sum of the norms of all rows in feature set plus the square of all data points in observation set.""" # The norms of all bucket rows and the norms of the original dataset # should match when summed. self.assertAlmostEqual(norm_buckets, norm)
def test_random_shuffle_batches(self): """`stats.shuffle_batches`: Randomized Validator. Tests the behavior of `shuffle_batches` by feeding it randomly generated arguments. Raises: AssertionError: If `shuffle_batches` needs debugging. """ extract_shape = lambda b: b.shape """callable: Returns the dimensions of the given matrix.""" row_norms = lambda b: _np.linalg.norm(b, axis=1) """callable: Returns the sum of all row norms in `b`.""" aslist = lambda A: A.T[0, :].tolist()[0] """callable: Maps vectors to lists.""" is_row_equal = lambda r: _compose(all, aslist)(r[0, :]) """callable: Determines whether all entries are set to `True` in given element-wise equality row vector.""" are_rows_equal = lambda v: v if isinstance(v, bool) \ else _prependargs(_compose(all, map), is_row_equal)(v) """callable: Determines whether all entries are set to `True` in given element-wise equality matrix vector.""" for i in range(self.n_tests): X = _random_matrix(self.data_shape) """np.matrix: Random-valued feature set.""" Y = _random_matrix((self.data_shape[0], 1)) """np.matrix: Random-valued observation set.""" b = batches(X, Y, 29) """list of np.matrix: Random-valued batches.""" b_hat = shuffle_batches(b) """list of np.matrix: Test input.""" shapes = map(extract_shape, b) """list of (int, int): Input batch shapes.""" shapes_hat = map(extract_shape, b_hat) """list of (int, int): Output batch shapes.""" # Re-ordered batches should be a list of np.matrix instances. self.assertIsInstance(b_hat, list) map(_appendargs(self.assertIsInstance, _np.matrix), b_hat) # Shapes and norms should match. self.assertTrue( _compose(all, map)(lambda shape: shape in shapes, shapes_hat)) self.assertAlmostEqual(*map( _prependargs(_compose(sum, map), _compose(sum, row_norms)), [b, b_hat])) # Batches should be in different order. batches_not_equal = map(lambda (b1, b2): b1 != b2, zip(b, b_hat)) """np.matrix: Element-wise equality matrix of all batches.""" _compose(self.assertTrue, any, map)(are_rows_equal, batches_not_equal)
def test_edge_cases_visualization_subplot(self): """`visualization.Visualization.subplot`: Edge Case Validator. Tests the behavior of `Visualization.subplot` with edge cases. Raises: Exception: If at least one `Exception` raised is not of the expected kind. """ x = _compose(list, _np.random.uniform)(0.0, 100.0, size=self.data_shape[0]) """list of float: Random x-values.""" values = { name: _compose(list, _np.random.uniform)(0.0, 100.0, size=self.data_shape[0]) \ for name in ["observations", "predictions"] } """:obj:`list of float`: Contains all y-values.""" v = Visualization("Title", (1, 1)) """Visualization: Plotter instance.""" for ModelWrapper in self.wrappers.values(): with self.assertRaises(IndexError): # Suplot index out of range. v._subplot(1, x, values) with self.assertRaises(TypeError): # Empty `x`-values. v._subplot([], values, 0) with self.assertRaises(TypeError): # Empty `y`-values. v._subplot(x, {}, 0) v.close()
def test_random_visualization_best_fit_lines(self): """`visualization.Visualization.best_fit_lines`: Randomized Validator. Tests the behavior of `Visualization.best_fit_lines` by feeding it randomly generated arguments. Raises: AssertionError: If `Visualization.best_fit_lines` needs debugging. """ for i in range(self.n_tests): v = Visualization("Title", (3, 3)) """Visualization: Plotter instance.""" for i in range(9): x = _compose(list, _np.random.uniform)(0.0, 100.0, size=self.data_shape[0]) """list of float: Random x-values.""" values = { name: _compose(list, _np.random.uniform)(0.0, 100.0, size=self.data_shape[0]) \ for name in ["observations", "predictions"] } """:obj:`list of float`: Contains all y-values.""" lines = v._best_fit_lines(x, values, i) """list of matplotlib.lines.Line2D: Test input.""" # Best-fit lines should be a list of Line2D instances. self.assertIsInstance(lines, list) map(_appendargs(self.assertIsInstance, _Line2D), lines) unique_x = _compose(list, _np.unique)(x) """list of float: X-values with duplicates removed.""" for line in lines: x_data = line.get_xdata() """list of float: X-values in actual best-fit line.""" y_data = line.get_ydata() """list of float: Y-values in actual best-fit line.""" # Number of x- and y-values in all lines should match number # of unique values in `x`. self.assertEqual(*map(_np.linalg.norm, [x_data, unique_x])) self.assertEqual(*map(len, [y_data, unique_x])) m = (y_data[1] - y_data[0]) / (x_data[1] - x_data[0]) """float: Best-fit line gradient.""" b = y_data[0] - m * x_data[0] """float: Y-intercept.""" computed_y_vals = map(lambda val: m * val + b, x_data) """list of float: Y-values computed analytically.""" # All lines should be rewritable in linear terms. self.assertAlmostEqual( *map(_np.linalg.norm, [computed_y_vals, y_data])) v.close()
def test_invalid_args_visualization_subplot(self): """`visualization.Visualization.subplot`: Argument Validator. Tests the behavior of `Visualization.subplot` with invalid argument counts and values. Raises: Exception: If at least one `Exception` raised is not of the expected kind. """ x = _compose(list, _np.random.uniform)(0.0, 100.0, size=self.data_shape[0]) """list of float: Random x-values.""" values = { name: _compose(list, _np.random.uniform)(0.0, 100.0, size=self.data_shape[0]) \ for name in ["observations", "predictions"] } """:obj:`list of float`: Contains all y-values.""" v = Visualization("Title", (1, 1)) """Visualization: Plotter instance.""" with self.assertRaises(TypeError): # No arguments. v._subplot() with self.assertRaises(TypeError): # Only one argument. v._subplot(x) with self.assertRaises(TypeError): # Only two arguments. v._subplot(x, values) with self.assertRaises(TypeError): # Too many arguments. v._subplot(x, values, 0, "Title", "X-label", "Y-label", True, "extra") with self.assertRaises(TypeError): # Invalid keyword. v._subplot(x, values, 0, key="value") with self.assertRaises(TypeError): # `None` instead of list `x`. v._subplot(None, values, 0) with self.assertRaises(TypeError): # np.matrix instead of list `x`. v._subplot(_np.matrix(x), values, 0) with self.assertRaises(TypeError): # `None` instead of dict of lists `values`. v._subplot(x, None, 0) with self.assertRaises(TypeError): value_list = {k: _np.matrix(val) for k, val in values.iteritems()} """:obj:`np.matrix`: Lists in `values` mapped to matrices.""" # Dict of np.matrix instead of dict of lists `values`. v._subplot(x, value_list, 0) with self.assertRaises(TypeError): # List instead of dict of lists `values`. v._subplot(x, x, 0) with self.assertRaises(TypeError): # Incompatible x- and y-values. values_hat = { name: _compose(list, _np.random.uniform)(0.0, 100.0, size=self.data_shape[1]) \ for name in ["observations", "predictions"] } """:obj:`list of float`: Contains all y-values.""" v._subplot(x, values, 0) with self.assertRaises(TypeError): # `None` instead of int `subplot`. v._subplot(x, values, None) with self.assertRaises(TypeError): # Float instead of int `subplot`. v._subplot(x, values, 5.6) with self.assertRaises(TypeError): # Non-string `title`. v._subplot(x, values, 0, title=["hello", "bye"]) with self.assertRaises(TypeError): # Non-string `xlabel`. v._subplot(x, values, 0, xlabel=["hello", "bye"]) with self.assertRaises(TypeError): # Non-string `ylabel`. v._subplot(x, values, 0, ylabel=["hello", "bye"])