Example #1
0
def generate_dataset(game, output_file_name, total=100, mode="w", **kw):
    if output_file_name:
        output_file = open(output_file_name, mode)
    else:
        print(style("No output file?", Colours.FG.BRIGHT_RED))
        return

    with HidePrintingContext():
        # Concurrently (for total=100, takes around 36 seconds)
        with concurrent.futures.ProcessPoolExecutor(max_workers=8) as pool:
            for result in tqdm(
                    pool.map(_setup_and_play_mp,
                             ((gid, game.__class__, game.model, kw)
                              for gid in range(total)),
                             chunksize=50),
                    ncols=79,
                    desc="Generating data... ",
                    total=total,
            ):
                print(result, file=output_file)

        # Sequentially (for total=100, takes around 1 minute)
        # for gid in tqdm(range(total), ncols=79, desc="Generating data... ", total=total):
        #     result = setup_and_play(gid)
        #     print(result, file=output_file)

    if output_file_name:
        print(
            style("Data saved to: '", Colours.FG.GREEN) +
            style(output_file_name, Colours.FG.BRIGHT_GREEN) + "'")
        output_file.close()
Example #2
0
def print_accuracy(descr, win=0, draw=0, loss=0, result=None):
    if result is not None:
        win, draw, loss = result

    print(f"{descr}: " \
        + style(f"{win * 100:.2f}% wins", Colours.FG.GREEN)    + ", " \
        + style(f"{draw * 100:.2f}% draws", Colours.FG.YELLOW) + ", " \
        + style(f"{loss * 100:.2f}% losses", Colours.FG.RED)   + ".")
Example #3
0
    def play_vs_ai(self,
                   starting=None,
                   legal_only=True,
                   check_early_win=True,
                   prevent_other_win=True,
                   random_move_chance=0.0):
        # Against own model
        player = starting if starting is not None else starting_player()
        self._start_game(player, other_strat_descr="plays also as AI")

        while self.game.status is None:
            if player > 0 and random_move_chance > 0.0 and random.random(
            ) <= random_move_chance:
                move = self.game.random_action(legal_only=legal_only)
            else:
                move = self.predict(ai_player=player,
                                    check_early_win=check_early_win,
                                    prevent_other_win=prevent_other_win)

            if not self.game.is_legal_move(move):
                print(
                    style("Illegal move from player! ", Colours.FG.BRIGHT_RED),
                    player, move)

            print(
                f"{self.print_player_string(player)} adds to column {move}...")
            self.game.play_move(player, move)
            self._add_state(self.game, player, move)
            player = player * -1

        print(f"{self.print_player_string(self.game.status)} wins!")
        return self.game.status
Example #4
0
    def play_vs_smart(self,
                      starting=None,
                      legal_only=True,
                      n=100,
                      check_early_win=True,
                      prevent_other_win=True):
        # Against smart player
        player = starting if starting is not None else starting_player()
        self._start_game(player, other_strat_descr="plays smart")

        while self.game.status is None:
            if player < 0 and self.model:
                move = self.predict(check_early_win=check_early_win,
                                    prevent_other_win=prevent_other_win)
            else:
                move, p = self.game.smart_action(player,
                                                 legal_only=legal_only,
                                                 n=n)
                if not self.game.is_legal_move(move):
                    print(
                        style("Illegal move smart player! ",
                              Colours.FG.BRIGHT_RED), player, move)

            print(
                f"{self.print_player_string(player)} adds to column {move}...")
            self.game.play_move(player, move)
            self._add_state(self.game, player, move)
            player = player * -1

        print(f"{self.print_player_string(self.game.status)} wins!")
        return self.game.status
Example #5
0
    def __init__(self, board=None, print_friendly=False):
        super().__init__()
        self.game = Game(
            board=board)  # Cannot do inheritance due to deepcopy in Game...
        self.states = []

        self.model = None
        self.board_nodes = self.game.width * self.game.height
        self.input_shape = (self.board_nodes + 1, )

        # If True, use another character for the other player so they are distinct
        # when printing without colours, e.g. ■ ▀ • ⦿
        self.print_friendly = print_friendly
        self.__players = {
            -1: style("■", Colours.FG.YELLOW),
            0: " ",
            1: style("•" if self.print_friendly else "■", Colours.FG.RED)
        }
Example #6
0
 def load_existing_model(self, name, basepath="../data/models/"):
     try:
         self.model = load_model(f"{basepath}{name}", compile=True)
         self.model.predict(np.zeros(
             (1, *self.input_shape)))  # Init predictor
     except Exception as e:
         self.model = None
         print(style(f"Could not load model!\n{e}", Colours.FG.RED))
     else:
         self.model.summary()
Example #7
0
    def predict(self,
                ai_player=-1,
                check_early_win=True,
                prevent_other_win=True):
        # Get (move, chance) that AI wins
        ai_move = self._predict_move_probability(ai_player, check_early_win)

        if prevent_other_win:
            other_player_move = self._predict_move_probability(
                ai_player * -1, check_early_win)

            if other_player_move[1] > ai_move[1]:
                print(style("Trying to prevent", Colours.FG.BRIGHT_RED) \
                    + f" {self.print_player_string(ai_player * -1)} from winning...")
                return other_player_move[0]

        return ai_move[0]
Example #8
0
    def _predict_move_probability(self, player, check_early_win=True):
        # Predict chance of winning for each move
        # and return column with highest chance.
        max_probability = (0, 0.0)

        print(self.print_player_string(player) + ": Testing cols: |", end="")

        for move in range(self.game.width):
            if not self.game.is_legal_move(move):
                print(style(f" {0.0:.3f} |", Colours.FG.BRIGHT_RED), end="")
                continue

            test_game = Game(board=self.game.board.copy())
            test_game.play_move(player, move)

            if check_early_win and test_game.status == player:
                # Win reached
                print(" win", end="")
                max_probability = (move, 1.0)
                break

            # Get prediction for move (make board positive by adding 1)
            test_input = np.concatenate(
                (test_game.board.flatten(), [player])).reshape(
                    (1, *self.input_shape)) + 1
            prediction = self.model.predict(test_input)[0][
                player + 1]  # [[player_0_prob, draw (?), player_1_prob]]

            if np.isnan(prediction):
                raise Exception("Error: prediction is NaN?")

            print(f" {prediction:.3f} |", end="")

            if prediction > max_probability[1]:
                max_probability = (move, prediction)

        print(
            f"  => Predicted move at col {max_probability[0]} with {max_probability[1] * 100:.2f}%"
        )
        return max_probability
Example #9
0
        # Build, train and save new model
        train_data, test_data = game.prepare_data(data_input, train_ratio=0.85)
        game.build_network(trained_name)
        game.train(train_data,
                   test_data,
                   epochs=15,
                   batch_size=200,
                   show_plot=True,
                   save_plot_path=f"../data/models/{trained_name}.png")
        game.save_model(trained_name)
    else:
        # Or load pre-trained
        game.load_existing_model(trained_name)

    if not game.has_model():
        print(style("No model ready! Exiting...", Colours.FG.BRIGHT_RED))
        exit(1)

    check_early_win = True
    prevent_other_win = True

    if any((check_early_win, prevent_other_win)):
        print(style("Using options: ", Colours.FG.MAGENTA) \
            + style("check_early_win", Colours.FG.BRIGHT_GREEN if check_early_win else Colours.FG.BRIGHT_BLACK) + ", "\
            + style("prevent_other_win", Colours.FG.BRIGHT_GREEN if prevent_other_win else Colours.FG.BRIGHT_BLACK))

    input(
        style("Model ready. Press enter to start tests or play.",
              Colours.FG.MAGENTA))

    # Test games
Example #10
0
    def train(self,
              train_data,
              test_data,
              epochs=10,
              batch_size=200,
              show_plot=False,
              save_plot_path=""):
        print("Training model...")

        train_x, train_y = train_data

        hist = self.model.fit(train_x,
                              train_y,
                              validation_data=test_data,
                              shuffle=True,
                              epochs=epochs,
                              batch_size=batch_size)

        test_score, test_acc = self.model.evaluate(test_data[0],
                                                   test_data[1],
                                                   verbose=0)

        print(style("Final accuracy on training set : ", Colours.FG.MAGENTA) \
            + style(f"{hist.history['accuracy'][-1] * 100:.2f}%", Colours.FG.BRIGHT_MAGENTA))
        print(style("Average accuracy while training: ", Colours.FG.MAGENTA) \
            + style(f"{np.average(np.array(hist.history['val_accuracy'])) * 100:.2f}%", Colours.FG.BRIGHT_MAGENTA))
        print(style("Average accuracy on test set   : ", Colours.FG.MAGENTA) \
            + style(f"{test_acc * 100:.2f}% (score={test_score:.4f})", Colours.FG.BRIGHT_MAGENTA))

        if show_plot or save_plot_path:
            plt.style.use("ggplot")
            plt.figure()
            plt.plot(
                np.arange(0, epochs),
                [1.0] * epochs,
                "r--",
                label="Accuracy target",
            )
            plt.plot(np.arange(0, epochs),
                     hist.history["loss"],
                     "cyan",
                     label="train_loss")
            plt.plot(np.arange(0, epochs),
                     hist.history["val_loss"],
                     "blue",
                     label="val_loss")
            plt.plot(np.arange(0, epochs),
                     hist.history["accuracy"],
                     "yellow",
                     label="train_acc")
            plt.plot(np.arange(0, epochs),
                     hist.history["val_accuracy"],
                     "orange",
                     label="val_acc")

            # Optionally plot other metrics?
            for k, v in hist.history.items():
                if k not in ("loss", "val_loss", "accuracy", "val_accuracy"):
                    plt.plot(np.arange(0, epochs), v, label=k)

            plt.title("Training Loss and Accuracy")
            plt.xlabel("Epoch #")
            plt.ylabel("Loss/Accuracy")
            plt.legend(loc="lower left")
            plt.xlim(0, epochs - 1)
            plt.ylim(bottom=0)
            if save_plot_path: plt.savefig(save_plot_path)
            if show_plot: plt.show()

        self.model.predict(np.zeros((1, *self.input_shape)))  # Init predictor