콘텐츠로 이동

Feature Extractors

특징 추출 클래스들은 보드 상태에서 머신러닝을 위한 특징을 추출합니다.

BoardFeatureExtractor

BoardFeatureExtractor

Extracts features from a Tetris board for use in learning algorithms.

Features extracted: - Lines cleared (from action) - Number of holes - Bumpiness (variance in column heights) - Total height

extract_features staticmethod

extract_features(board: Board, lines_cleared: int = 0) -> np.ndarray

Extract a feature vector from a board state.

Parameters:

Name Type Description Default
board Board

Board instance to extract features from

required
lines_cleared int

Number of lines cleared (optional context)

0

Returns:

Type Description
ndarray

NumPy array of features: [lines_cleared, holes, bumpiness, height]

Source code in rl_tetris/features/extractors.py
@staticmethod
def extract_features(
    board: Board,
    lines_cleared: int = 0
) -> np.ndarray:
    """
    Extract a feature vector from a board state.

    Args:
        board: Board instance to extract features from
        lines_cleared: Number of lines cleared (optional context)

    Returns:
        NumPy array of features: [lines_cleared, holes, bumpiness, height]
    """
    holes = board.get_holes()
    bumpiness, height = board.get_bumpiness_and_height()

    features = np.array([
        lines_cleared,
        holes,
        bumpiness,
        height
    ], dtype=np.float32)

    return features

extract_features_from_state staticmethod

extract_features_from_state(board_state: List[List[int]], lines_cleared: int = 0, board_height: int = 20, board_width: int = 10) -> np.ndarray

Extract features from a raw board state (without Board instance).

Parameters:

Name Type Description Default
board_state List[List[int]]

2D list representing board state

required
lines_cleared int

Number of lines cleared

0
board_height int

Height of the board

20
board_width int

Width of the board

10

Returns:

Type Description
ndarray

NumPy array of features

Source code in rl_tetris/features/extractors.py
@staticmethod
def extract_features_from_state(
    board_state: List[List[int]],
    lines_cleared: int = 0,
    board_height: int = 20,
    board_width: int = 10
) -> np.ndarray:
    """
    Extract features from a raw board state (without Board instance).

    Args:
        board_state: 2D list representing board state
        lines_cleared: Number of lines cleared
        board_height: Height of the board
        board_width: Width of the board

    Returns:
        NumPy array of features
    """
    # Create a temporary board instance
    temp_board = Board(board_height, board_width)
    temp_board.set_state(board_state)

    return BoardFeatureExtractor.extract_features(temp_board, lines_cleared)

get_feature_dim staticmethod

get_feature_dim() -> int

Get the dimensionality of the feature vector.

Returns:

Type Description
int

Number of features

Source code in rl_tetris/features/extractors.py
@staticmethod
def get_feature_dim() -> int:
    """
    Get the dimensionality of the feature vector.

    Returns:
        Number of features
    """
    return len(BoardFeatureExtractor.get_feature_names())

get_feature_names staticmethod

get_feature_names() -> List[str]

Get the names of features in the order they appear.

Returns:

Type Description
List[str]

List of feature names

Source code in rl_tetris/features/extractors.py
@staticmethod
def get_feature_names() -> List[str]:
    """
    Get the names of features in the order they appear.

    Returns:
        List of feature names
    """
    return [
        "lines_cleared",
        "holes",
        "bumpiness",
        "total_height"
    ]

normalize_features staticmethod

normalize_features(features: np.ndarray, max_lines: int = 4, max_holes: int = 200, max_bumpiness: int = 200, max_height: int = 200) -> np.ndarray

Normalize features to [0, 1] range.

Parameters:

Name Type Description Default
features ndarray

Feature vector to normalize

required
max_lines int

Maximum lines that can be cleared at once

4
max_holes int

Maximum expected holes

200
max_bumpiness int

Maximum expected bumpiness

200
max_height int

Maximum expected total height

200

Returns:

Type Description
ndarray

Normalized feature vector

Source code in rl_tetris/features/extractors.py
@staticmethod
def normalize_features(
    features: np.ndarray,
    max_lines: int = 4,
    max_holes: int = 200,
    max_bumpiness: int = 200,
    max_height: int = 200
) -> np.ndarray:
    """
    Normalize features to [0, 1] range.

    Args:
        features: Feature vector to normalize
        max_lines: Maximum lines that can be cleared at once
        max_holes: Maximum expected holes
        max_bumpiness: Maximum expected bumpiness
        max_height: Maximum expected total height

    Returns:
        Normalized feature vector
    """
    normalized = features.copy()
    max_values = np.array([max_lines, max_holes, max_bumpiness, max_height])

    # Avoid division by zero
    max_values = np.where(max_values == 0, 1, max_values)

    normalized = normalized / max_values
    normalized = np.clip(normalized, 0, 1)

    return normalized

AdvancedFeatureExtractor

AdvancedFeatureExtractor

Bases: BoardFeatureExtractor

Extended feature extractor with additional metrics.

extract_advanced_features staticmethod

extract_advanced_features(board: Board, lines_cleared: int = 0) -> np.ndarray

Extract an extended feature vector with additional metrics.

Parameters:

Name Type Description Default
board Board

Board instance

required
lines_cleared int

Number of lines cleared

0

Returns:

Type Description
ndarray

Extended feature vector

Source code in rl_tetris/features/extractors.py
@staticmethod
def extract_advanced_features(board: Board, lines_cleared: int = 0) -> np.ndarray:
    """
    Extract an extended feature vector with additional metrics.

    Args:
        board: Board instance
        lines_cleared: Number of lines cleared

    Returns:
        Extended feature vector
    """
    # Get basic features
    basic_features = BoardFeatureExtractor.extract_features(board, lines_cleared)

    # Get additional features
    column_heights = board.get_column_heights()
    max_height = max(column_heights) if column_heights else 0
    min_height = min(column_heights) if column_heights else 0
    height_variance = np.var(column_heights) if column_heights else 0

    # Count complete rows
    complete_rows = sum(1 for i in range(board.height) if board.is_row_full(i))

    # Calculate height-weighted holes
    board_state = board.get_state()
    weighted_holes = AdvancedFeatureExtractor._get_weighted_holes(board_state)

    # Wells (gaps between columns)
    wells = AdvancedFeatureExtractor._count_wells(column_heights)

    advanced_features = np.array([
        *basic_features,
        max_height,
        min_height,
        height_variance,
        complete_rows,
        weighted_holes,
        wells
    ], dtype=np.float32)

    return advanced_features

get_feature_dim staticmethod

get_feature_dim() -> int

Get dimensionality of advanced features.

Source code in rl_tetris/features/extractors.py
@staticmethod
def get_feature_dim() -> int:
    """Get dimensionality of advanced features."""
    return len(AdvancedFeatureExtractor.get_feature_names())

get_feature_names staticmethod

get_feature_names() -> List[str]

Get names of advanced features.

Source code in rl_tetris/features/extractors.py
@staticmethod
def get_feature_names() -> List[str]:
    """Get names of advanced features."""
    return [
        "lines_cleared",
        "holes",
        "bumpiness",
        "total_height",
        "max_height",
        "min_height",
        "height_variance",
        "complete_rows",
        "weighted_holes",
        "wells"
    ]

Usage Examples

기본 특징 추출

from rl_tetris.core import Board
from rl_tetris.features import BoardFeatureExtractor

board = Board(height=20, width=10)
# ... 게임 진행 ...

# 특징 추출
features = BoardFeatureExtractor.extract_features(board, lines_cleared=2)
print(features)  # [2, 5, 8, 15] - [lines, holes, bumpiness, height]

# 특징 이름
names = BoardFeatureExtractor.get_feature_names()
print(names)  # ['lines_cleared', 'holes', 'bumpiness', 'total_height']

# 특징 차원
dim = BoardFeatureExtractor.get_feature_dim()
print(dim)  # 4

고급 특징 추출

from rl_tetris.features import AdvancedFeatureExtractor

# 고급 특징 추출 (10개 특징)
features = AdvancedFeatureExtractor.extract_features(board, lines_cleared=2)
print(features.shape)  # (10,)

# 특징 이름
names = AdvancedFeatureExtractor.get_feature_names()
print(names)
# ['lines_cleared', 'holes', 'bumpiness', 'total_height',
#  'max_height', 'weighted_holes', 'row_transitions',
#  'column_transitions', 'wells', 'hole_depth']

정규화

# 특징 정규화
normalized = BoardFeatureExtractor.normalize_features(features)
print(normalized)  # 정규화된 값들

Features Description

Basic Features (4)

  1. lines_cleared: 클리어된 줄 수
  2. holes: 블록 아래의 빈 공간 수
  3. bumpiness: 인접한 열 간 높이 차이의 합
  4. total_height: 모든 열 높이의 합

Advanced Features (10)

기본 4개 + 추가 6개:

  1. max_height: 가장 높은 열의 높이
  2. weighted_holes: 가중치가 적용된 구멍 수
  3. row_transitions: 행 내 블록 변화 수
  4. column_transitions: 열 내 블록 변화 수
  5. wells: 양쪽이 막힌 빈 공간 수
  6. hole_depth: 구멍의 평균 깊이

Custom Feature Extractor

자신만의 특징 추출기를 만들 수 있습니다:

import numpy as np
from rl_tetris.core import Board

class CustomExtractor:
    @staticmethod
    def extract_features(board: Board, lines_cleared: int = 0):
        heights = board.get_column_heights()
        holes = board.get_holes()

        # 커스텀 특징
        avg_height = np.mean(heights)
        max_height = max(heights)
        height_variance = np.var(heights)

        return np.array([
            lines_cleared,
            holes,
            avg_height,
            max_height,
            height_variance
        ], dtype=np.float32)

# 사용
features = CustomExtractor.extract_features(board, 2)

See Also