Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import pandas as pd
- import seaborn as sns
- import sys
- import pygame
- import matplotlib.pyplot as plt
- from sklearn.metrics import mean_squared_error
- from sklearn.datasets import load_breast_cancer, load_digits
- from sklearn.model_selection import train_test_split
- from sklearn.metrics import precision_score, recall_score, accuracy_score
- import random
- class MultiNeuralNetwork:
- def __init__(self, type='reg', learning_rate=0.01, epochs=100000, hidden_layers=[10], C=1):
- self.type = type # 'reg', 'binary', 'multi'
- self.learning_rate = learning_rate
- self.epochs = epochs
- self.hidden_layers = hidden_layers
- self.C = C
- self.weights = []
- self.biases = []
- self.loss_ = []
- self.epochs_ = []
- def sigmoid(self, z):
- return 1 / (1 + np.exp(-z))
- def sigmoid_derivative(self, z):
- s = self.sigmoid(z)
- return s * (1 - s)
- def linear(self, z, C=1):
- return z * C
- def softmax(self, z):
- exp_values = np.exp(z - np.max(z))
- return exp_values / np.sum(exp_values, axis=0)
- def initialize_parameters(self, input_size, output_size):
- layers = [input_size] + self.hidden_layers + [output_size]
- self.weights = [np.random.randn(layers[i], layers[i + 1]) * np.sqrt(1 / layers[i]) for i in range(len(layers) - 1)]
- self.biases = [np.random.randn(layers[i + 1]) * 0.01 for i in range(len(layers) - 1)]
- def calc_out(self, x):
- try:
- input_size = x.shape[1]
- except:
- x = x.reshape(-1, 1)
- input_size = x.shape[1]
- for epoch in range(self.epochs):
- y_pred = []
- for i, x_sample in enumerate(x):
- inputs, activations, outputs = [x_sample], [], []
- input = x_sample
- len_ = len(self.weights)
- d_weights, d_biases = [None] * len_ , [None] * len_
- for idx, _ in enumerate(zip(self.weights, self.biases)):
- w, b = _[0], _[1]
- activation = np.dot(input, w) + b
- activations.append(activation)
- if w.shape[1] == 1 and self.type == 'reg':
- output = self.linear(activation, C=self.C)
- outputs.append(output)
- elif w.shape[1] == 1 and self.type == 'binary':
- output = self.sigmoid(activation)
- outputs.append(output)
- elif idx == (len_-1) and self.type == 'multi':
- output = self.softmax(activation)
- outputs.append(output)
- else:
- input = self.sigmoid(activation)
- outputs.append(input)
- inputs.append(input)
- y_pred.append(output)
- return np.array(y_pred), inputs, activations
- def learn(self, inputs, activations, expected_output, output):
- output_size = len(output) if self.type == 'multi' else 1
- len_ = len(self.weights)
- d_weights, d_biases = [None] * len_ , [None] * len_
- if self.type == 'multi':
- delta = output - np.eye(output_size)[expected_output]
- else:
- delta = output - expected_output
- d_biases[len_-1] = delta * self.C
- d_weights[len_-1] = np.dot(inputs[len_-1].reshape(-1, 1), d_biases[len_-1].reshape(-1, 1).T)
- for idx in reversed(range(len_ - 1)):
- d_biases[idx] = np.dot(d_biases[idx+1], self.weights[idx+1].T * self.sigmoid_derivative(activations[idx]))
- d_weights[idx] = np.dot(inputs[idx].reshape(-1, 1), d_biases[idx].reshape(-1, 1).T)
- for idx in (range(len_)):
- self.weights[idx] -= self.learning_rate * d_weights[idx]
- self.biases[idx] -= self.learning_rate * d_biases[idx]
- def predict(self, x):
- try:
- _ = x.shape[1]
- except:
- x = x.reshape(-1, 1)
- y_pred = []
- len_ = len(self.weights)
- for x_sample in x:
- input = x_sample
- for idx, _ in enumerate(zip(self.weights, self.biases)):
- w, b = _[0], _[1]
- activation = np.dot(input, w) + b
- if w.shape[1] == 1 and self.type == 'reg':
- output = self.linear(activation, C=self.C)
- elif w.shape[1] == 1 and self.type == 'binary':
- output = (self.sigmoid(activation) > 0.5).astype(int)
- elif idx == (len_-1) and self.type == 'multi':
- output = np.argmax(self.softmax(activation))
- else:
- input = self.sigmoid(activation)
- y_pred.append(output)
- return np.array(y_pred)
- def save_to_file(self, fname):
- try:
- with open(fname, "wb") as file:
- for w in self.weights:
- np.save(file, w)
- for b in self.biases:
- np.save(file, b)
- print(f"Weights and biases saved to {fname}")
- except Exception as e:
- print(f"Error saving weights: {e}")
- def load_from_file(self, fname):
- try:
- with open(fname, "rb") as file:
- self.weights = [np.load(file) for _ in range(len(self.weights))]
- self.biases = [np.load(file) for _ in range(len(self.biases))]
- print(f"Weights and biases loaded from {fname}")
- except Exception as e:
- print(f"Error loading weights: {e}")
- def plot_results(y1, accuracy):
- x1 = np.arange(1, len(y1) + 1)
- plt.figure(figsize=(10, 5))
- plt.xlabel('Number of Episodes', fontsize=18)
- plt.ylabel('log(Number of Successes)', fontsize=18)
- plt.xticks(fontsize=16)
- plt.yticks(fontsize=16)
- plt.plot(x1, np.log(y1), c='red')
- plt.scatter(x1, np.log(y1), c='red')
- plt.show()
- plt.figure(figsize=(10, 5))
- plt.xlabel('Number of Episodes', fontsize=18)
- plt.ylabel('Accuracy', fontsize=18)
- plt.xticks(fontsize=16)
- plt.yticks(fontsize=16)
- plt.plot(x1, accuracy, c='red')
- plt.scatter(x1, accuracy, c='red')
- plt.show()
- class Ball:
- def __init__(self, size):
- self.step = 5
- self.delta_x = random.randint(-10, 10)
- self.pygame_object = pygame.Surface((size, size))
- self.pygame_object.fill((255, 0, 0))
- self.rect = self.pygame_object.get_rect()
- self.rect.x = random.randint(0, window_w - size)
- self.rect.y = 0
- def move(self):
- self.rect.x += self.delta_x
- self.rect.y += self.step
- if self.rect.x <= 0 or self.rect.x + self.rect.w >= window_w:
- self.delta_x = -self.delta_x
- if self.rect.y <= 0:
- self.step = abs(self.step)
- class Player:
- def __init__(self, width, height, x_pos, step, color=(180, 180, 0)):
- self.step = step
- self.width = width
- self.height = height
- self.x_pos = x_pos
- self.pygame_object = pygame.Surface((width, height))
- self.pygame_object.fill(color)
- self.rect = self.pygame_object.get_rect()
- self.rect.x = x_pos
- self.rect.y = window_h - height
- def move(self, direction):
- if direction == "->" and self.rect.x < window_w - self.width:
- self.rect.x += self.step
- elif direction == "<-" and self.rect.x > 0:
- self.rect.x -= self.step
- elif direction == "stay":
- pass
- window_w = 400
- window_h = 400
- ball_size = 15
- player_width = 100
- player_height = 10
- player_step = 10
- filename = 'weights_temp.dat'
- player_x_pos = (window_w - player_width) / 2
- ball = Ball(ball_size)
- player = Player(player_width, player_height, player_x_pos, player_step)
- model = MultiNeuralNetwork(type='multi', learning_rate=0.1, epochs=1, hidden_layers=[5])
- model.initialize_parameters(input_size=2, output_size=3)
- epoches = 200
- # pygame.init()
- # window = pygame.display.set_mode((window_w, window_h))
- time_delay = 10
- actions = []
- num_of_successes_in_episode = 0
- num_of_episodes = 0
- y_true, y_pred = [], []
- accuracy_arr = []
- while True:
- # pygame.time.delay(time_delay)
- input = np.array([[(player.rect.x + player.rect.w / 2) / window_w, (ball.rect.x + ball.rect.w / 2) / window_w]])
- temp = model.calc_out(input)
- output, inputs, activations = temp[0][0], temp[1], temp[2]
- # for event in pygame.event.get():
- # if event.type == pygame.QUIT:
- # actions.append(num_of_successes_in_episode)
- # plot_results(actions, accuracy_arr)
- # pygame.quit()
- # sys.exit()
- if np.argmax(output) == 0:
- move_to = "<-"
- elif np.argmax(output) == 1:
- move_to = "stay"
- elif np.argmax(output) == 2:
- move_to = "->"
- player.move(move_to)
- ball.move()
- if ball.rect.colliderect(player.rect):
- ball.step = -abs(ball.step)
- num_of_successes_in_episode += 1
- if ball.rect.x + ball.rect.w / 2 < player.rect.x + player.rect.x*0.3333:
- expected_output = np.array([0]) # Вліво
- elif ball.rect.x + ball.rect.w / 2 > player.rect.x + player.rect.w - player.rect.x*0.3333:
- expected_output = np.array([2]) # Вправо
- else:
- expected_output = np.array([1]) # На місці
- y_true.append(expected_output[0])
- y_pred.append(np.argmax(output))
- model.learn(inputs=inputs, activations=activations, expected_output=expected_output[0], output=output)
- if (ball.rect.y + ball.rect.h >= window_h) or num_of_successes_in_episode >= 10000:
- num_of_episodes += 1
- actions.append(num_of_successes_in_episode)
- num_of_successes_in_episode = 0
- accuracy = accuracy_score(np.array(y_true), np.array(y_pred))*100
- accuracy_arr.append(accuracy)
- print(f'game{num_of_episodes}: accuracy={round(accuracy, 2)}%, num_of_successes_in_episode={actions[-1]}')
- y_true, y_pred = [], []
- if num_of_episodes >= 30:
- model.save_to_file(filename)
- plot_results(actions, accuracy_arr)
- # pygame.quit()
- # sys.exit()
- break
- ball.rect.y = 0
- ball.rect.x = random.randint(0, window_w - ball_size)
- player.x_pos = player_x_pos
- # window.fill((0, 0, 0))
- # window.blit(player.pygame_object, player.rect)
- # window.blit(ball.pygame_object, ball.rect)
- # pygame.display.update()
- window_w = 400
- window_h = 400
- ball_size = 15
- player_width = 100
- player_height = 10
- player_step = 10
- filename = 'weights_temp.dat'
- winning_score = 5
- black = (0, 0, 0)
- white = (255, 255, 255)
- class Ball:
- def __init__(self, size):
- self.step = random.choice([-5, 5])
- self.delta_x = random.randint(-10, 10)
- self.pygame_object = pygame.Surface((size, size))
- self.pygame_object.fill((255, 0, 0))
- self.rect = self.pygame_object.get_rect()
- self.rect.x = random.randint(0, window_w - size)
- self.rect.y = window_h / 2 - size / 2
- class Player:
- def __init__(self, width, height, x_pos, y_pos, step, color=(180, 180, 0)):
- self.step = step
- self.width = width
- self.height = height
- self.pygame_object = pygame.Surface((width, height))
- self.pygame_object.fill(color)
- self.rect = self.pygame_object.get_rect()
- self.rect.x = x_pos
- self.rect.y = y_pos
- self.score = 0
- def movement(self, distance):
- self.rect.x += distance
- if self.rect.x <= 0:
- self.rect.x = 0
- if self.rect.x >= window_w - self.width:
- self.rect.x = window_w - self.width
- ball = Ball(ball_size)
- player_horizontal_position = (window_w - player_width) / 2
- human = Player(player_width, player_height, player_horizontal_position, window_h - player_height, player_step, color=(0, 255, 0))
- comp = Player(player_width, player_height, player_horizontal_position, 0, player_step, color=(0, 0, 255))
- model.load_from_file(filename)
- pygame.init()
- window = pygame.display.set_mode((window_w, window_h))
- font_winner = pygame.font.Font(None, 32)
- font_score = pygame.font.Font(None, 48)
- time_delay = 10
- paused = True
- done = False
- distance = 0
- while not done:
- if paused:
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- done = True
- if event.type == pygame.KEYDOWN:
- if event.key == pygame.K_RIGHT:
- distance = player_step
- if event.key == pygame.K_LEFT:
- distance = -player_step
- if event.key == pygame.K_SPACE:
- paused = not paused
- if event.key == pygame.K_ESCAPE:
- human.score = 0
- comp.score = 0
- paused = not paused
- if event.type == pygame.KEYUP:
- if event.key in (pygame.K_RIGHT, pygame.K_LEFT):
- distance = 0
- if not paused:
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- done = True
- if event.type == pygame.KEYDOWN:
- if event.key == pygame.K_RIGHT:
- distance = player_step
- if event.key == pygame.K_LEFT:
- distance = -player_step
- if event.type == pygame.KEYUP:
- if event.key in (pygame.K_RIGHT, pygame.K_LEFT):
- distance = 0
- human.movement(distance)
- pygame.time.delay(time_delay)
- input = np.array([[(comp.rect.x + comp.rect.w / 2) / window_w, (ball.rect.x + ball.rect.w / 2) / window_w]])
- output = model.predict(input)[0]
- if output == 0: move_to = '<-'
- elif output == 2: move_to = '->'
- else: move_to == 'stay'
- if move_to == '->' and comp.rect.x < window_w - comp.width:
- comp.rect.x += comp.step
- elif move_to == '<-' and comp.rect.x > 0:
- comp.rect.x -= comp.step
- ball.rect.x += ball.delta_x
- ball.rect.y += ball.step
- if ball.rect.x <= 0:
- ball.delta_x = -ball.delta_x
- ball.rect.x = 0
- if ball.rect.x + ball.rect.w >= window_w:
- ball.delta_x = -ball.delta_x
- ball.rect.x = window_w - ball.rect.w
- if ball.rect.y <= 0:
- ball.step = -ball.step
- if ball.rect.colliderect(comp.rect):
- ball.delta_x = random.randint(-9, 9)
- ball.step = -ball.step
- if ball.rect.colliderect(human.rect):
- ball.delta_x = random.randint(-9, 9)
- ball.step = -ball.step
- if ball.rect.y > window_h or ball.rect.y < 0:
- if ball.rect.y > window_h:
- comp.score += 1
- else:
- human.score += 1
- ball.rect.y = window_h / 2 - ball_size / 2
- ball.rect.x = random.randint(0, window_w - ball_size)
- ball.step = random.choice([-5, 5])
- human.rect.x = player_horizontal_position
- comp.rect.x = player_horizontal_position
- paused = True
- distance = 0
- pygame.display.set_caption(f'Ping Pong Game | Comp ({comp.score}) : Human ({human.score})')
- if human.score >= winning_score or comp.score >= winning_score:
- if human.score >= winning_score:
- winner = 'You win !!!'
- else:
- winner = 'Computer wins !!!'
- text_winner = font_winner.render(winner, True, white)
- text_winner_rect = text_winner.get_rect()
- text_winner_rect.center = (window_w // 2, window_h // 2)
- window.fill(black)
- window.blit(text_winner, text_winner_rect)
- pygame.display.update()
- pygame.time.delay(3000)
- done = True
- if not done:
- window.fill(black)
- window.blit(human.pygame_object, human.rect)
- window.blit(comp.pygame_object, comp.rect)
- window.blit(ball.pygame_object, ball.rect)
- pygame.display.update()
- pygame.quit()
- sys.exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement