AI & Game 2048: Dùng TensorFlow.js để học hàm đánh giá với mạng nơ-ron

Ở phần 1, ta viết bot 2048 dùng expectimax + heuristic “tự chế”. Ở phần 2, ta cho bot tự tinh chỉnh trọng số của heuristic bằng self-play kiểu hill-climbing. Phần 3 này, chơi lớn luôn: ta để một mạng nơ-ron TensorFlow.js tự học hàm giá trị V(board), rồi dùng chính mạng đó để quyết định nước đi. Toàn bộ chạy ngay trong trình duyệt, không cần server, không cần Python – chỉ HTML + JS + TensorFlow.js.

AI & Game 2048: Dùng TensorFlow.js để học hàm đánh giá với mạng nơ-ron

1. Mục tiêu: học hàm giá trị V(board) bằng neural network

Ta muốn một hàm:

V(board) ≈ “độ ngon” của trạng thái này

Sau đó, ở mỗi lượt:

  1. Duyệt qua 4 hướng (Up, Right, Down, Left).
  2. Giả lập nước đi → ra board mới.
  3. Dùng mạng nơ-ron dự đoán V(board_mới).
  4. Chọn hướng có V cao nhất.

Khác với phần 1 & 2 (heuristic tuyến tính), giờ V là hàm phi tuyến do mạng nơ-ron học được từ data self-play.

2. Biểu diễn bàn cờ thành vector đầu vào cho mạng

Mạng nơ-ron không hiểu “bàn 4×4” – nó chỉ hiểu vector số. Ta encode mỗi ô thành 1 số:

  • Empty (0) → 0
  • Tile = 2 → log2(2) = 1
  • Tile = 4 → log2(4) = 2
  • Tile = 8 → 3, v.v.

Để tránh số quá to, ta có thể scale nhẹ, ví dụ chia cho 16:

function encodeBoard(board) {
  const arr = [];
  for (let r = 0; r < 4; r++) {
    for (let c = 0; c < 4; c++) {
      const v = board[r][c];
      if (v === 0) {
        arr.push(0);
      } else {
        arr.push(Math.log2(v) / 16); // scale nhẹ
      }
    }
  }
  return arr; // length = 16
}

Như vậy input cho mạng là vector 16 chiều.

3. Kiến trúc mạng nơ-ron với TensorFlow.js

Ta sẽ dùng một mạng fully-connected nhỏ:

  • Input: 16 chiều.
  • Hidden 1: 64 neurons, ReLU.
  • Hidden 2: 64 neurons, ReLU.
  • Output: 1 neuron (giá trị V(board)).

Code tạo model với TensorFlow.js:

function createModel() {
  const model = tf.sequential();
  model.add(tf.layers.dense({
    inputShape: [16],
    units: 64,
    activation: 'relu',
  }));
  model.add(tf.layers.dense({
    units: 64,
    activation: 'relu',
  }));
  model.add(tf.layers.dense({
    units: 1, // scalar value V(board)
  }));
  model.compile({
    optimizer: tf.train.adam(0.001),
    loss: 'meanSquaredError',
  });
  return model;
}

4. Lấy dữ liệu training từ đâu? Tự chơi và dùng heuristic làm “giáo viên”

Ta cần cặp dữ liệu (board, target_value). Có nhiều hướng:

  • Supervised từ heuristic cũ:
    • Dùng heuristic (phần 1–2) để gán nhãn V_heuristic(board).
    • Train mạng để dự đoán V_heuristic(board).
    • Mạng học cách “bắt chước” heuristic, nhưng có thể generalize tốt hơn.
  • TD-learning / RL thật: target = reward + γ·V(board_next). (phức tạp hơn, để sau).

Trong bài này, để code gọn trên browser, ta dùng cách 1: heuristic đóng vai thầy, mạng đóng vai học trò. Vừa dễ implement, vừa tương thích trực tiếp với code phần 1–2.

Pipeline đơn giản:

  1. Dùng một bot đơn giản (random/heuristic) chơi vài bước → sinh ra nhiều trạng thái board.
  2. Với mỗi board, tính target = heuristicValue(board).
  3. Encode board → vector input → train model để dự đoán target.

Mỗi lần click “Train 1 batch”, ta:

  • Generate N boards (ví dụ 64).
  • Tạo xs (tensor [N, 16]) và ys (tensor [N, 1]).
  • Gọi model.fit(xs, ys).

5. Dùng mạng nơ-ron để chọn nước đi

Khi đã có model, ta đánh giá một board như sau:

function evaluateBoardNN(board, model) {
  return tf.tidy(() => {
    const input = tf.tensor2d([encodeBoard(board)], [1, 16]);
    const output = model.predict(input);
    const value = output.dataSync()[0];
    return value;
  });
}

Chọn nước đi:

function chooseBestMoveWithNN(board, model) {
  const moves = [UP, RIGHT, DOWN, LEFT];
  let bestMove = null;
  let bestValue = -Infinity;

  for (const move of moves) {
    const result = moveBoard(board, move);
    if (!result.moved) continue;
    const value = evaluateBoardNN(result.board, model);
    if (value > bestValue) {
      bestValue = value;
      bestMove = move;
    }
  }

  return bestMove;
}

Để tránh crash khi model chưa train, ta có thể fallback sang heuristic nếu model == null hoặc training chưa xong.

6. Demo: 2048 + TensorFlow.js value network

Demo dưới đây gồm:

  • Bàn 2048 để bạn xem bot chơi.
  • Nút “Train 1 batch (NN)” & “Train 10 batches (NN)”:
    • Bot tự generate data bằng heuristic.
    • Train mạng nơ-ron trên data đó.
  • Nút “Auto-play with NN”:
    • Dùng mạng nơ-ron để chọn nước đi (greedy theo V(board)).

2048 Neural Value Function Demo (TensorFlow.js)

Mạng nơ-ron học hàm V(board) từ heuristic, sau đó dùng để tự chọn nước đi

Score: 0 | Max tile: 0 | Status:

NN training info


7. Tổng kết và hướng phát triển tiếp

Ở phần 3, ta đã:

  • Biến bàn cờ 2048 thành vector đầu vào cho mạng nơ-ron.
  • Dùng TensorFlow.js để build một value network V(board).
  • Lấy heuristic cũ làm “thầy”, tự generate dữ liệu training bằng self-play trong trình duyệt.
  • Dùng chính mạng nơ-ron để chọn nước đi cho bot.

Còn rất nhiều hướng để nâng cấp tiếp:

  • Dùng TD-learning hoặc Q-learning thay vì bắt chước heuristic.
  • Kết hợp expectimax + value network (dùng NN làm evaluation thay heuristic).
  • Dùng replay buffer, schedule learning rate, early stopping, v.v.

Nhưng với 3 phần đến đây, series “AI & 2048” đã đi từ chiến lược tay to → expectimax → self-play tuning → neural value function với TensorFlow.js – đủ để build một con bot 2048 khá “có não” ngay trong trình duyệt.

Bình luận


  • Không có bình luận.

Init Toolbox

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...