def test_default_value(self):

        state = GameState()

        value = CNNValue(
            ["board", "liberties", "sensibleness", "capture_size"])
        value.eval_state(state)
    def test_batch_eval_state(self):

        value = CNNValue(
            ["board", "liberties", "sensibleness", "capture_size"])
        results = value.batch_eval_state([GameState(), GameState()])
        self.assertEqual(len(results), 2)  # one result per GameState
        self.assertTrue(isinstance(results[0], np.float64))
        self.assertTrue(isinstance(results[1], np.float64))
    def test_save_load(self):
        value = CNNValue(
            ["board", "liberties", "sensibleness", "capture_size"])

        model_file = 'TESTVALUE.json'
        weights_file = 'TESTWEIGHTS.h5'
        model_file2 = 'TESTVALUE2.json'
        weights_file2 = 'TESTWEIGHTS2.h5'

        # test saving model/weights separately
        value.save_model(model_file)
        value.model.save_weights(weights_file, overwrite=True)
        # test saving them together
        value.save_model(model_file2, weights_file2)

        copyvalue = CNNValue.load_model(model_file)
        copyvalue.model.load_weights(weights_file)

        copyvalue2 = CNNValue.load_model(model_file2)

        for w1, w2 in zip(copyvalue.model.get_weights(),
                          copyvalue2.model.get_weights()):
            self.assertTrue(np.all(w1 == w2))

        os.remove(model_file)
        os.remove(weights_file)
        os.remove(model_file2)
        os.remove(weights_file2)
    def test_save_load(self):
        self.value.save_model('.tmp.value.json')
        copy = CNNValue.load_model('.tmp.value.json')

        # test that loaded class is also an instance of CNNValue
        self.assertTrue(isinstance(copy, CNNValue))
        os.remove('.tmp.value.json')
    def test_probabilistic_player(self):

        gs = GameState(size=9)

        value = CNNValue(["board", "ones", "turns_since"], board=9)
        player = ValuePlayer(value)
        for i in range(10):
            move = player.get_move(gs)
            self.assertNotEqual(move, go.PASS)
            gs.do_move(move)
    def test_sensible_probabilistic(self):

        gs = GameState()

        value = CNNValue(["board", "ones", "turns_since"])
        player = ValuePlayer(value)
        empty = (10, 10)
        for x in range(19):
            for y in range(19):
                if (x, y) != empty:
                    gs.do_move((x, y), go.BLACK)
        gs.set_current_player(go.BLACK)
        self.assertEqual(player.get_move(gs), go.PASS)
    def test_output_size(self):

        state = GameState()

        value19 = CNNValue(
            ["board", "liberties", "sensibleness", "capture_size"], board=19)
        output = value19.forward(value19.preprocessor.state_to_tensor(state))
        self.assertEqual(output.shape, (1, 1))

        state = GameState(size=13)

        value13 = CNNValue(
            ["board", "liberties", "sensibleness", "capture_size"], board=13)
        output = value13.forward(value13.preprocessor.state_to_tensor(state))
        self.assertEqual(output.shape, (1, 1))
Exemple #8
0
def train(metadata, out_directory, verbose, weight_file, meta_file):
    # set resume
    resume = weight_file is not None

    # load model from json spec
    policy = CNNValue.load_model(metadata["model_file"])
    model_features = policy.preprocessor.get_feature_list()
    model = policy.model
    # load weights
    if resume:
        model.load_weights(
            os.path.join(out_directory, FOLDER_WEIGHT, weight_file))

    # features of training data
    dataset = h5.File(metadata["training_data"])

    # Verify that dataset's features match the model's expected features.
    validate_feature_planes(verbose, dataset, model_features)

    # create metadata file and the callback object that will write to it
    # and saves model  at the same time
    # the MetadataWriterCallback only sets 'epoch', 'best_epoch' and 'current_batch'.
    # We can add in anything else we like here
    meta_writer = EpochDataSaverCallback(meta_file, out_directory, metadata)

    # get train/validation/test indices
    train_indices, val_indices, test_indices \
        = load_train_val_test_indices(verbose, metadata['symmetries'], len(dataset["states"]),
                                      metadata["batch_size"], out_directory)

    # create dataset generators
    train_data_generator = threading_shuffled_hdf5_batch_generator(
        dataset["states"], dataset["winners"], train_indices,
        metadata["batch_size"], metadata)
    val_data_generator = threading_shuffled_hdf5_batch_generator(
        dataset["states"],
        dataset["winners"],
        val_indices,
        metadata["batch_size"],
        validation=True)

    # check if step decay has to be applied
    if metadata["decay_every"] is None:
        # use normal decay without momentum
        lr_scheduler_callback = LrDecayCallback(metadata["learning_rate"],
                                                metadata["decay"])
    else:
        # use step decay
        lr_scheduler_callback = LrStepDecayCallback(metadata["learning_rate"],
                                                    metadata["decay_every"],
                                                    metadata["decay"], verbose)

    sgd = SGD(lr=metadata["learning_rate"])
    model.compile(loss='mean_squared_error',
                  optimizer=sgd,
                  metrics=["accuracy"])

    if verbose:
        print("STARTING TRAINING")

    # check that remaining epoch > 0
    if metadata["epochs"] <= len(metadata["epoch_logs"]):
        raise ValueError("No more epochs to train!")

    model.fit_generator(
        generator=train_data_generator,
        steps_per_epoch=(metadata["epoch_length"] / metadata["batch_size"]),
        epochs=(metadata["epochs"] - len(metadata["epoch_logs"])),
        callbacks=[meta_writer, lr_scheduler_callback],
        validation_data=val_data_generator,
        validation_steps=(len(val_indices) / metadata["batch_size"]))
 def setUp(self):
     self.value = CNNValue(['board', 'ones', 'turns_since'])
class TestCNNValue(unittest.TestCase):

    def setUp(self):
        self.value = CNNValue(['board', 'ones', 'turns_since'])

    def test_save_load(self):
        self.value.save_model('.tmp.value.json')
        copy = CNNValue.load_model('.tmp.value.json')

        # test that loaded class is also an instance of CNNValue
        self.assertTrue(isinstance(copy, CNNValue))
        os.remove('.tmp.value.json')

    # test shape
    def test_ouput_shape(self):

        gs = GameState()

        val = self.value.eval_state(gs)
        self.assertTrue(isinstance(val, np.float64))

    def testTrain(self):
        model = 'tests/test_data/minimodel_value.json'
        data = 'tests/test_data/hdf5/value_training_features.hdf5'
        output = 'tests/test_data/.tmp.training/'
        args = ['train', output, model, data, '--epochs', '1', '-l', '160']
        handle_arguments(args)

        # remove temporary files
        os.remove(os.path.join(output, FILE_METADATA))
        os.remove(os.path.join(output, FILE_TRAIN))
        os.remove(os.path.join(output, FILE_VALIDATE))
        os.remove(os.path.join(output, FILE_TEST))
        os.remove(os.path.join(output, FOLDER_WEIGHT, 'weights.00000.hdf5'))
        os.rmdir(os.path.join(output, FOLDER_WEIGHT))
        os.rmdir(output)

    def testResumeLearning(self):
        model = 'tests/test_data/minimodel_value.json'
        data = 'tests/test_data/hdf5/value_training_features.hdf5'
        output = 'tests/test_data/.tmp.resume-training/'
        args = ['train', output, model, data, '--epochs', '1', '-l', '160']
        handle_arguments(args)

        # resume learning
        args = ['train', output, model, data, '--epochs', '2', '-l', '160',
                '--weights', 'weights.00000.hdf5']
        handle_arguments(args)

        # remove temporary files
        os.remove(os.path.join(output, FILE_METADATA))
        os.remove(os.path.join(output, FILE_TRAIN))
        os.remove(os.path.join(output, FILE_VALIDATE))
        os.remove(os.path.join(output, FILE_TEST))
        os.remove(os.path.join(output, FOLDER_WEIGHT, 'weights.00000.hdf5'))
        os.remove(os.path.join(output, FOLDER_WEIGHT, 'weights.00001.hdf5'))
        os.rmdir(os.path.join(output, FOLDER_WEIGHT))
        os.rmdir(output)

    def testStateAmount(self):
        output = 'tests/test_data/.tmp.state-amount/'
        # create folder
        if not os.path.exists(output):
            os.makedirs(output)

        # shuffle file locations for train/validation/test set
        shuffle_file_train = os.path.join(output, FILE_TRAIN)
        shuffle_file_val = os.path.join(output, FILE_VALIDATE)
        shuffle_file_test = os.path.join(output, FILE_TEST)

        # create shuffle files
        create_and_save_shuffle_indices([.9, .05, .05], 1000000000,
                                        1033, shuffle_file_train,
                                        shuffle_file_val, shuffle_file_test)

        # load from .npz files
        # load training set
        train_indices = load_indices_from_file(shuffle_file_train)
        # count unique rows
        unique_indices = len(np.vstack({tuple(row) for row in train_indices}))
        self.assertTrue(unique_indices == 7438)

        # load validation set
        val_indices = load_indices_from_file(shuffle_file_val)
        # count unique rows
        unique_indices = len(np.vstack({tuple(row) for row in val_indices}))
        self.assertTrue(unique_indices == 413)

        # load training set
        test_indices = load_indices_from_file(shuffle_file_test)
        # count unique rows
        unique_indices = len(np.vstack({tuple(row) for row in test_indices}))
        self.assertTrue(unique_indices == 413)

        # combine all set rows
        combined_indices = np.concatenate((train_indices, val_indices, test_indices), axis=0)
        # count unique rows
        unique_indices = len(np.vstack({tuple(row) for row in combined_indices}))
        self.assertTrue(unique_indices == (7438 + 413 + 413))

        # remove temporary files
        os.remove(shuffle_file_train)
        os.remove(shuffle_file_val)
        os.remove(shuffle_file_test)
        os.rmdir(output)