def test_inversions(self): for s in symmetries.SYMMETRIES: with self.subTest(symmetry=s): self.assertEqualNPArray( self.feat, symmetries.apply_symmetry_feat( s, symmetries.apply_symmetry_feat( symmetries.invert_symmetry(s), self.feat))) self.assertEqualNPArray( self.feat, symmetries.apply_symmetry_feat( symmetries.invert_symmetry(s), symmetries.apply_symmetry_feat(s, self.feat))) self.assertEqualNPArray( self.pi, symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, s, symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, symmetries.invert_symmetry(s), self.pi))) self.assertEqualNPArray( self.pi, symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, symmetries.invert_symmetry(s), symmetries.apply_symmetry_pi(utils_test.BOARD_SIZE, s, self.pi)))
def analyze_symmetries(sgf_file, dual_network): with open(sgf_file) as f: sgf_contents = f.read() iterator = sgf_wrapper.replay_sgf(sgf_contents) differences = [] stddevs = [] # For every move in the game, get the corresponding network values for all # eight symmetries. for i, pwc in enumerate(iterator): feats = features.extract_features(pwc.position) variants = [symmetries.apply_symmetry_feat(s, feats) for s in symmetries.SYMMETRIES] values = dual_network.sess.run( dual_network.inference_output['value_output'], feed_dict={dual_network.inference_input: variants}) # Get the difference between the maximum and minimum outputs of the # value network over all eight symmetries; also get the standard # deviation of the eight values. differences.append(max(values) - min(values)) stddevs.append(np.std(values)) differences.sort() percentiles = [differences[i * len(differences) // 100] for i in range(100)] worst = differences[-1] avg_stddev = np.mean(stddevs) return (percentiles, worst, avg_stddev)
def find_symmetry(self, x, pi, x2, pi2): for sym in symmetries.SYMMETRIES: x_equal = (x == symmetries.apply_symmetry_feat(sym, x2)).all() pi_equal = (pi == symmetries.apply_symmetry_pi(sym, pi2)).all() if x_equal and pi_equal: return sym self.assertTrue(False, "No rotation makes {} equal {}".format(pi, pi2))
def find_symmetry(x, pi, x2, pi2): for sym in symmetries.SYMMETRIES: x_equal = (x == symmetries.apply_symmetry_feat(sym, x2)).all() pi_equal = (pi == symmetries.apply_symmetry_pi(sym, pi2)).all() if x_equal and pi_equal: return sym assert False, "No rotation makes {} equal {}".format( pi1.reshape((go.N, go.N)), pi2((go.N, go.N)))
def test_compositions(self): test_cases = [ ('rot90', 'rot90', 'rot180'), ('rot90', 'rot180', 'rot270'), ('identity', 'rot90', 'rot90'), ('fliprot90', 'rot90', 'fliprot180'), ('rot90', 'rot270', 'identity'), ] for s1, s2, composed in test_cases: with self.subTest(s1=s1, s2=s2, composed=composed): self.assertEqualNPArray(symmetries.apply_symmetry_feat( composed, self.feat), symmetries.apply_symmetry_feat( s2, symmetries.apply_symmetry_feat(s1, self.feat))) self.assertEqualNPArray( symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, composed, self.pi), symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, s2, symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, s1, self.pi)))
def test_compositions(self): test_cases = [ ('rot90', 'rot90', 'rot180'), ('rot90', 'rot180', 'rot270'), ('identity', 'rot90', 'rot90'), ('fliprot90', 'rot90', 'fliprot180'), ('rot90', 'rot270', 'identity'), ] for s1, s2, composed in test_cases: with self.subTest(s1=s1, s2=s2, composed=composed): self.assertEqualNPArray( symmetries.apply_symmetry_feat(composed, self.feat), symmetries.apply_symmetry_feat( s2, symmetries.apply_symmetry_feat(s1, self.feat))) self.assertEqualNPArray( symmetries.apply_symmetry_pi(utils_test.BOARD_SIZE, composed, self.pi), symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, s2, symmetries.apply_symmetry_pi(utils_test.BOARD_SIZE, s1, self.pi)))
def find_symmetry(self, x, pi, x2, pi2): for sym in symmetries.SYMMETRIES: #print (sym, type(x), type(symmetries.apply_symmetry_feat(sym, x2))) #print (x.shape, symmetries.apply_symmetry_feat(sym, x2).shape) #print (pi.shape, symmetries.apply_symmetry_pi(sym, pi2).shape) x_equal = (x == symmetries.apply_symmetry_feat(sym, x2)).all() pi_equal = (pi == symmetries.apply_symmetry_pi(sym, pi2)).all() if x_equal and pi_equal: return sym assert False, "No rotation makes {} equal {}".format( pi, pi2)
def test_uniqueness(self): all_symmetries_f = [ symmetries.apply_symmetry_feat(s, self.feat) for s in symmetries.SYMMETRIES ] all_symmetries_pi = [ symmetries.apply_symmetry_pi(utils_test.BOARD_SIZE, s, self.pi) for s in symmetries.SYMMETRIES ] for f1, f2 in itertools.combinations(all_symmetries_f, 2): self.assertNotEqualNPArray(f1, f2) for pi1, pi2 in itertools.combinations(all_symmetries_pi, 2): self.assertNotEqualNPArray(pi1, pi2)
def test_uniqueness(self): all_symmetries_f = [ symmetries.apply_symmetry_feat( s, self.feat) for s in symmetries.SYMMETRIES ] all_symmetries_pi = [ symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, s, self.pi) for s in symmetries.SYMMETRIES ] for f1, f2 in itertools.combinations(all_symmetries_f, 2): self.assertNotEqualNPArray(f1, f2) for pi1, pi2 in itertools.combinations(all_symmetries_pi, 2): self.assertNotEqualNPArray(pi1, pi2)
def test_inversions(self): for s in symmetries.SYMMETRIES: with self.subTest(symmetry=s): self.assertEqualNPArray( self.feat, symmetries.apply_symmetry_feat( s, symmetries.apply_symmetry_feat( symmetries.invert_symmetry(s), self.feat))) self.assertEqualNPArray( self.feat, symmetries.apply_symmetry_feat( symmetries.invert_symmetry(s), symmetries.apply_symmetry_feat( s, self.feat))) self.assertEqualNPArray( self.pi, symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, s, symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, symmetries.invert_symmetry(s), self.pi))) self.assertEqualNPArray( self.pi, symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, symmetries.invert_symmetry(s), symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, s, self.pi)))
def test_proper_move_transform(self): # Check that the reinterpretation of 362 = 19*19 + 1 during symmetry # application is consistent with coords.from_flat move_array = np.arange(utils_test.BOARD_SIZE**2 + 1) coord_array = np.zeros([utils_test.BOARD_SIZE, utils_test.BOARD_SIZE]) for c in range(utils_test.BOARD_SIZE**2): coord_array[coords.from_flat(utils_test.BOARD_SIZE, c)] = c for s in symmetries.SYMMETRIES: with self.subTest(symmetry=s): transformed_moves = symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, s, move_array) transformed_board = symmetries.apply_symmetry_feat( s, coord_array) for new_coord, old_coord in enumerate(transformed_moves[:-1]): self.assertEqual( old_coord, transformed_board[coords.from_flat( utils_test.BOARD_SIZE, new_coord)])
def test_proper_move_transform(self): # Check that the reinterpretation of 362 = 19*19 + 1 during symmetry # application is consistent with coords.from_flat move_array = np.arange(utils_test.BOARD_SIZE ** 2 + 1) coord_array = np.zeros([utils_test.BOARD_SIZE, utils_test.BOARD_SIZE]) for c in range(utils_test.BOARD_SIZE ** 2): coord_array[coords.from_flat(utils_test.BOARD_SIZE, c)] = c for s in symmetries.SYMMETRIES: with self.subTest(symmetry=s): transformed_moves = symmetries.apply_symmetry_pi( utils_test.BOARD_SIZE, s, move_array) transformed_board = symmetries.apply_symmetry_feat(s, coord_array) for new_coord, old_coord in enumerate(transformed_moves[:-1]): self.assertEqual( old_coord, transformed_board[ coords.from_flat(utils_test.BOARD_SIZE, new_coord)])
def analyze_symmetries(sgf_file, load_file): with open(sgf_file) as f: sgf_contents = f.read() iterator = sgf_wrapper.replay_sgf(sgf_contents) net = dual_net.DualNetwork(load_file) for i, pwc in enumerate(iterator): if i < 200: continue feats = features.extract_features(pwc.position) variants = [symmetries.apply_symmetry_feat(s, feats) for s in symmetries.SYMMETRIES] values = net.sess.run( net.inference_output['value_output'], feed_dict={net.inference_input['pos_tensor']: variants}) mean = np.mean(values) stdev = np.std(values) all_vals = sorted(zip(values, symmetries.SYMMETRIES)) print("{:3d} {:.3f} +/- {:.3f} min {:.3f} {} max {:.3f} {}".format( i, mean, stdev, *all_vals[0], *all_vals[-1]))
def analyze_symmetries(sgf_file, load_file): with open(sgf_file) as f: sgf_contents = f.read() iterator = sgf_wrapper.replay_sgf(sgf_contents) net = dual_net.DualNetwork(load_file) for i, pwc in enumerate(iterator): if i < 200: continue feats = features.extract_features(pwc.position) variants = [ symmetries.apply_symmetry_feat(s, feats) for s in symmetries.SYMMETRIES ] values = net.sess.run( net.inference_output['value_output'], feed_dict={net.inference_input['pos_tensor']: variants}) mean = np.mean(values) stdev = np.std(values) all_vals = sorted(zip(values, symmetries.SYMMETRIES)) print("{:3d} {:.3f} +/- {:.3f} min {:.3f} {} max {:.3f} {}".format( i, mean, stdev, *all_vals[0], *all_vals[-1]))