def compute(self): """Returns the classification regions of network restricted to line. Returns a list with one tuple (pre_regions, corresponding_labels) for each line in self.lines. pre_regions is a list of tuples of endpoints that partition each input line. """ if self.computed: return self.classifications self.partial_compute() self.classifications = [] classify_network = Network([ArgMaxLayer()]) for pre, post in self.transformed_lines: # First, we take each of the linear regions and split them where # the ArgMax changes. lines = list(zip(post[:-1], post[1:])) classify_transformed_lines = classify_network.exactlines( lines, compute_preimages=False, include_post=False) split_pre = [] split_post = [] for i, endpoints in enumerate(classify_transformed_lines): pre_delta = pre[i + 1] - pre[i] post_delta = post[i + 1] - post[i] for point_ratio in endpoints: point_pre = pre[i] + (point_ratio * pre_delta) point_post = post[i] + (point_ratio * post_delta) if i == 0 or not point_ratio == 0.0: split_pre.append(point_pre) split_post.append(point_post) # Now, in each of the resulting regions, we compute the # corresponding label. region_labels = [] for i in range(len(split_pre) - 1): mid_post = 0.5 * (split_post[i] + split_post[i + 1]) region_labels.append(np.argmax(mid_post)) # Finally, we merge segments with the same classification. merged_pre = [] merged_labels = [] for i, label in enumerate(region_labels): if not merged_labels or label != merged_labels[-1]: merged_pre.append(split_pre[i]) merged_labels.append(label) merged_pre.append(split_pre[-1]) regions = list(zip(merged_pre[:-1], merged_pre[1:])) self.classifications.append((regions, merged_labels)) self.computed = True return self.classifications
def test_exactlines(): import pysyrenn.frontend.transformer_client transform_lines_ = pysyrenn.frontend.transformer_client.transform_lines input_dims = np.random.randint(1, 32) output_dims = np.random.randint(1, 64) weights = np.random.uniform(size=(input_dims, output_dims)) biases = np.random.uniform(size=(output_dims)) fullyconnected_layer = FullyConnectedLayer(weights, biases) relu_layer = ReluLayer() network = Network([fullyconnected_layer, relu_layer]) lines = list(np.random.uniform(size=(100, 2, input_dims))) def transform_lines_mock(query_network, query_lines, query_include_post=False): assert query_network.serialize() == network.serialize() if len(query_lines) == 1: assert np.allclose(query_lines, lines[:1]) else: assert np.allclose(query_lines, lines) output_lines = [] for i, line in enumerate(query_lines): output_lines.append((np.array([0.0, 1.0 / float(i + 1), 1.0]), np.array([float(2.0 * i)]))) return output_lines pysyrenn.frontend.transformer_client.transform_lines = transform_lines_mock ratios = network.exactlines(lines, compute_preimages=False, include_post=False) assert np.allclose( ratios, np.array([[0.0, 1.0 / float(i + 1), 1.0] for i in range(100)])) ratio = network.exactline(*lines[0], compute_preimages=False, include_post=False) assert np.allclose(ratio, ratios[0]) def interpolate(line_i, ratio): start, end = lines[line_i] return start + (ratio * (end - start)) preimages = network.exactlines(lines, compute_preimages=True, include_post=False) assert np.allclose( preimages, np.array([[ interpolate(i, 0.0), interpolate(i, 1.0 / float(i + 1)), interpolate(i, 1.0) ] for i in range(100)])) preimage = network.exactline(*lines[0], compute_preimages=True, include_post=False) assert np.allclose(preimage, preimages[0]) transformed = network.exactlines(lines, compute_preimages=True, include_post=True) pre, post = zip(*transformed) assert np.allclose( pre, np.array([[ interpolate(i, 0.0), interpolate(i, 1.0 / float(i + 1)), interpolate(i, 1.0) ] for i in range(100)])) assert np.allclose(post, np.array([[float(2.0 * i)] for i in range(100)])) transformed_single = network.exactline(*lines[0], compute_preimages=True, include_post=True) assert np.allclose(transformed_single[0], transformed[0][0]) assert np.allclose(transformed_single[1], transformed[0][1])