Advertisement
alkkofficial

Untitled

Mar 31st, 2023 (edited)
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.39 KB | None | 0 0
  1. # 真零 eval engine with NN
  2. # zan1ling4 | 真零 | (pronounced Jun Ling)
  3. import matplotlib.pyplot as plt
  4. import numpy as np
  5. import pandas as pd
  6. import torch
  7. import torch.nn as nn
  8. import torch.optim as optim
  9. import tqdm
  10. from sklearn.model_selection import train_test_split
  11. import chess
  12.  
  13. # puzzle presets
  14. MAX_MOMENTS = 10
  15. TOTAL_GAMES = 4
  16. board = chess.Board()
  17. files = ["./a.txt","./ab.txt", "./ac.txt"]
  18.  
  19. # pre-training loop
  20.  
  21. final_df = pd.DataFrame()
  22.  
  23. # set up training data
  24.  
  25. for file in files:
  26. with open(file, "r") as f:
  27. contents = f.read()
  28.  
  29. contents = contents.split(" \n")
  30. df_add = pd.DataFrame(columns=["moves", "status"])
  31.  
  32. for game in contents:
  33. if file == "./a.txt": # NOTE: change the filename
  34. d = {"moves": game, "status": "won"}
  35. df_add.loc[len(df_add)] = d
  36. elif file == "./ab.txt":
  37. d = {"moves": game, "status": "lost"}
  38. df_add.loc[len(df_add)] = d
  39. elif file == "./ac.txt":
  40. d = {"moves": game, "status": "drew"}
  41. df_add.loc[len(df_add)] = d
  42. final_df = pd.concat([final_df, df_add], ignore_index=True)
  43. print(final_df)
  44. # define function that takes chess board and turns into AI-understandable matrix
  45.  
  46.  
  47. def board_data(board):
  48. board_array = np.zeros((8, 8, 13), dtype=np.int8)
  49. for i in range(64):
  50. piece = board.piece_at(i)
  51. if piece is not None:
  52. color = int(piece.color)
  53. piece_type = piece.piece_type - 1
  54. board_array[i // 8][i % 8][piece_type + 6 * color] = 1
  55. else:
  56. board_array[i // 8][i % 8][-1] = 1
  57. board_array = board_array.flatten()
  58. return board_array
  59.  
  60.  
  61. game = 0
  62. train_df = pd.DataFrame(
  63. columns=[
  64. "board_data",
  65. "status",
  66. ]
  67. )
  68.  
  69. for index, row in final_df.iterrows():
  70. moves = row["moves"].split(" ")
  71. status = row["status"]
  72. moves = [x for x in moves if x] # removes empty strings in list
  73. if len(moves) <= MAX_MOMENTS:
  74. MAX_MOMENTS = len(moves)
  75. unsampled_idx = [x for x in range(len(moves))]
  76. unsampled_idx.pop(0)
  77. for _ in range(MAX_MOMENTS - 1):
  78. board = chess.Board()
  79. up_to = np.random.choice(unsampled_idx)
  80. unsampled_idx.remove(up_to)
  81. moment = moves[:up_to]
  82. df_add = pd.DataFrame(
  83. columns=[
  84. "board_data",
  85. "status",
  86. ]
  87. )
  88. for move in moment:
  89. board.push(chess.Move.from_uci(move))
  90. ai_moves = board_data(board)
  91.  
  92. counter = 0
  93. d = {
  94. "board_data": ai_moves,
  95. "status": status,
  96. }
  97. df_add.loc[len(df_add)] = d
  98. train_df = pd.concat([train_df, df_add], ignore_index=True)
  99. game += 1
  100. print(train_df)
  101.  
  102. # preprocessing data
  103.  
  104. train_df["status"] = train_df["status"].map(
  105. {"won": 1.0, "lost": -1.0, "drew": 0.0}
  106. ) # target
  107. X = np.array([x for x in train_df["board_data"]])
  108. y = np.array([x for x in train_df["status"]])
  109. # train-test split for model evaluation
  110. X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, shuffle=True)
  111. # Convert to 2D PyTorch tensors
  112. X_train = torch.tensor(X_train, dtype=torch.float32)
  113. y_train = torch.tensor(y_train, dtype=torch.float32).reshape(-1, 1)
  114. X_test = torch.tensor(X_test, dtype=torch.float32)
  115. y_test = torch.tensor(y_test, dtype=torch.float32).reshape(-1, 1)
  116.  
  117.  
  118. class EvalNN(nn.Module):
  119. def __init__(self):
  120. super().__init__()
  121. self.fc1 = nn.Linear(832, 832)
  122. self.hidden_layers = nn.ModuleList()
  123. for _ in range(100):
  124. self.hidden_layers.append(nn.Linear(832, 832))
  125. self.fc_out = nn.Tanh()
  126. self.optimizer = optim.Adam(self.parameters(), lr=1e-3)
  127. self.scheduler = optim.lr_scheduler.StepLR(
  128. self.optimizer, step_size=10, gamma=0.5
  129. )
  130. self.loss = nn.MSELoss()
  131.  
  132. def forward(self, x):
  133. x = torch.relu(self.fc1(x))
  134. for layer in self.hidden_layers:
  135. x = torch.relu(layer(x))
  136. x = self.fc_out(x)
  137. return x
  138.  
  139. def load_weights(self, path):
  140. self.load_state_dict(torch.load(path))
  141.  
  142.  
  143. model = EvalNN()
  144. train_losses = []
  145. test_losses = []
  146. num_epochs = 20
  147.  
  148. for epoch in range(num_epochs):
  149. # Training
  150. model.train()
  151. train_loss = 0.0
  152. for i in tqdm.tqdm(range(X_train.shape[0])):
  153. inputs = X_train[i]
  154. targets = y_train[i]
  155. model.optimizer.zero_grad()
  156. outputs = model(inputs)
  157. loss = model.loss(outputs, targets)
  158. loss.backward()
  159. model.optimizer.step()
  160. train_loss += loss.item()
  161. train_loss /= X_train.shape[0]
  162. train_losses.append(train_loss)
  163.  
  164. # Validation
  165. model.eval()
  166. test_loss = 0.0
  167. with torch.no_grad():
  168. for i in range(X_test.shape[0]):
  169. inputs = X_test[i]
  170. targets = y_test[i]
  171. outputs = model(inputs)
  172. loss = model.loss(outputs, targets)
  173. test_loss += loss.item()
  174. test_loss /= X_test.shape[0]
  175. test_losses.append(test_loss)
  176.  
  177. # Learning rate scheduling
  178. model.scheduler.step()
  179.  
  180. print(
  181. f"Epoch {epoch+1}/{num_epochs}: Train Loss = {train_loss:.6f}, Test Loss = {test_loss:.6f}"
  182. )
  183. plt.plot(train_losses, label="Train Loss")
  184. plt.plot(test_losses, label="Test Loss")
  185. plt.legend()
  186. plt.show()
  187.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement