"vscode:/vscode.git/clone" did not exist on "bf669606eb84e12dc1ecf15b23c1eedab204d660"
features.py 3.1 KB
Newer Older
Yanhui Liang's avatar
Yanhui Liang committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Features used by AlphaGo Zero, in approximate order of importance.

Feature                 # Notes
Stone History           16 The stones of each color during the last 8 moves.
Ones                    1  Constant plane of 1s
All features with 8 planes are 1-hot encoded, with plane i marked with 1
only if the feature was equal to i. Any features >= 8 would be marked as 8.

This file includes the features from from AlphaGo Zero (AGZ) as NEW_FEATURES.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import go
import numpy as np


def planes(num_planes):
  # to specify the number of planes in the features. For example, for a 19x19
  # go board, the input stone feature will be in the shape of [19, 19, 16],
  # where the third dimension is the num_planes.
  def deco(f):
    f.planes = num_planes
    return f
  return deco


@planes(16)
def stone_features(board_size, position):
  """Create the 16 planes of features for a given position.

  Args:
    board_size: the go board size.
    position: a given go board status.

  Returns:
    The 16 plane features.
  """
  # a bit easier to calculate it with axis 0 being the 16 board states,
  # and then roll axis 0 to the end.
  features = np.zeros([16, board_size, board_size], dtype=np.uint8)

  num_deltas_avail = position.board_deltas.shape[0]
  cumulative_deltas = np.cumsum(position.board_deltas, axis=0)
  last_eight = np.tile(position.board, [8, 1, 1])
  # apply deltas to compute previous board states
  last_eight[1:num_deltas_avail + 1] -= cumulative_deltas
  # if no more deltas are available, just repeat oldest board.
  last_eight[num_deltas_avail + 1:] = last_eight[num_deltas_avail].reshape(
      1, board_size, board_size)

  features[::2] = last_eight == position.to_play
  features[1::2] = last_eight == -position.to_play
  return np.rollaxis(features, 0, 3)


@planes(1)
def color_to_play_feature(board_size, position):
  if position.to_play == go.BLACK:
    return np.ones([board_size, board_size, 1], dtype=np.uint8)
  else:
    return np.zeros([board_size, board_size, 1], dtype=np.uint8)

NEW_FEATURES = [
    stone_features,
    color_to_play_feature
]

NEW_FEATURES_PLANES = sum(f.planes for f in NEW_FEATURES)


def extract_features(board_size, position, features=None):
  if features is None:
    features = NEW_FEATURES
  return np.concatenate([feature(board_size, position) for feature in features],
                        axis=2)