Como automatizar jogos com inteligência artificial
I. Introdução
A ideia de deixar a IA jogar já existia desde o século passado, quando estava mais inclinada aos jogos de tabuleiro. Como gamão, xadrez, etc. No século passado, "Deep Blue" derrotou o campeão de xadrez e, em 2016, "Alpha Go" derrotou o campeão humano de Go.
Até agora, a IA está envolvida em mais do que apenas jogos de tabuleiro. Para jogos como Super Mario e King of Glory, a IA também pode ter um desempenho melhor. Hoje usaremos um exemplo prático para discutir o tópico da IA jogando jogos automaticamente. Este artigo usará um algoritmo de aprendizado de máquina muito simples para permitir que a IA jogue automaticamente o jogo Google Dinosaur.
2. Google Dinosaurs e Aprendizagem Supervisionada
2.1. Google Dinossauro
Se você estiver usando o navegador Chrome, acredito que deve ter visto o seguinte dinossauro:
Quando usamos o Chrome para desconectar da Internet para acessar a página da web, esse dinossauro será exibido, ou digite diretamente: chrome://dino na barra de endereços para acessar o jogo diretamente.
A jogabilidade é muito simples, basta pressionar a barra de espaço. Por exemplo, na imagem da esquerda abaixo, se você está prestes a encontrar um obstáculo, você precisa pressionar o espaço, enquanto a imagem da direita abaixo não tem nenhum obstáculo (ou está longe do obstáculo), você não precisa apertar o botão.
Claro, há também o caso dos pássaros, que também podemos classificar como saltadores. Todos podem jogar.
2.2. Aprendizado supervisionado
Jogar jogos é frequentemente implementado usando um método chamado aprendizado por reforço, e este artigo usa um método de aprendizado supervisionado relativamente simples.
Este artigo usará o algoritmo de regressão logística para implementar, o código é o seguinte:
from sklearn.linear_model import LogisticRegression # 逻辑回归模型
from sklearn.model_selection import train_test_split # 数据集拆分
# 1、准备数据
X = [
# 天河区的坐标
[1, 1],
[1, 2],
[2, 0],
[3, 2],
[3, 3],
# 花都区的坐标
[7, 7],
[6, 7],
[7, 6],
[8, 6],
[8, 5]
]
y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
# 2、拆分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 3、定义模型
model = LogisticRegression()
# 4、填充数据并训练
model.fit(X_train, y_train)
# 5、评估模型
score1 = model.score(X_train, y_train)
score2 = model.score(X_test, y_test)
print(score1, score2)
# 6、预测
input = [
[4, 4]
]
pred = model.predict(input)
print(pred)
Para obter uma explicação da regressão logística, consulte: Python constrói redes neurais rapidamente
.
Podemos pensar em jogar o jogo como um problema de classificação, ou seja, um problema de classificação binária em que a entrada é a imagem do jogo atual e a saída é 0 e 1 (0 significa pular, 1 significa não pular). Para que a IA jogue o jogo automaticamente, precisamos fazer algumas coisas. Eles são os seguintes:
- Jogue o jogo e colete algumas fotos que precisam pular e outras que não precisam de barras
- Escolha um algoritmo de classificação apropriado e treine um modelo
- Capture a tela do jogo atual, preveja o resultado e determine se você precisa pular
- Se você precisar pular, use o programa para controlar o teclado e pressione a tecla de salto
Vamos completar o acima por sua vez.
3. Colete dados
Para coletar dados, precisamos continuar fazendo capturas de tela enquanto jogamos. Aqui, podemos usar Pillow
módulos para obter capturas de tela. Pillow
O módulo precisa ser instalado separadamente. A instrução de instalação é a seguinte:
pip install pillow
O código para a captura de tela é o seguinte:
import time
from PIL import ImageGrab # 截图
time.sleep(3)
while True:
# 截图
img = ImageGrab.grab()
# print(img.size) # 960 540 480 270
img = img.resize((960, 540))
# 保存图片
img.save(f'imgs/{
str(time.time())}.jpg')
# 修改name
time.sleep(0.1)
Depois de executar o programa, você pode alternar para o Chrome para iniciar o jogo. Após um período de tempo, vamos capturar algumas imagens, que são mais ou menos as seguintes:
Neste momento, é a vez da inteligência humana jogar. Colocamos manualmente as cenas que decidimos pular para o imgs/jump
diretório e colocamos as cenas que não achamos que não precisamos pular para o imgs/none
diretório. . Então você pode ir para o próximo passo.As fotos capturadas aqui geralmente não precisam pular muito, e todas podem ser coletadas várias vezes.
Depois que a coleção estiver completa, podemos ler a imagem e convertê-la em um array unidimensional. Esta parte do código é a seguinte:
import os
import cv2
# 所有图片的全路径
files = [os.path.join(jump_path, jump) for jump in os.listdir(jump_path)] + \
[os.path.join(none_path, none) for none in os.listdir(none_path)]
X = []
y = [0] * len(os.listdir(jump_path)) + [1] * len(os.listdir(none_path))
# 遍历jump目录下的图片
for idx, file in enumerate(files):
filepath = os.path.join(none_path, file)
x = cv2.imread(filepath, 0).reshape(-1)
X.append(x)
Agora X
e y
são nossas características e objetivos. Com X
e y
, você pode começar a treinar o modelo.
4. Treinamento do modelo de classificação
O código para a parte de treinamento é muito simples e podemos salvar o modelo após a conclusão do treinamento. código mostrar como abaixo:
import os
import cv2
import joblib
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
jump_path = os.path.join('imgs', 'jump') # 需要跳的图片的根目录
none_path = os.path.join('imgs', 'none') # 不需要跳的图片的根目录
# 所有图片的全路径
files = [os.path.join(jump_path, jump) for jump in os.listdir(jump_path)] + \
[os.path.join(none_path, none) for none in os.listdir(none_path)]
X = []
y = [0] * len(os.listdir(jump_path)) + [1] * len(os.listdir(none_path))
# 遍历jump目录下的图片
for file in files:
x = cv2.imread(file, 0).reshape(-1)
X.append(x)
# 2、拆分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 3、定义模型
model = LogisticRegression(max_iter=500)
# 4、训练模型
model.fit(X_train, y_train)
# 5、评估模型
train_score = model.score(X_train, y_train)
test_score = model.score(X_test, y_test)
print(train_score, test_score)
# 保存模型
joblib.dump(model, 'auto_play.m')
A taxa de precisão do treinamento no meu computador está acima de 90% e o efeito geral ainda é bom. Existem algumas áreas para melhoria embora. Aqui estão alguns pontos:
- Apenas a parte central da imagem afetará a próxima operação, então você pode optar por fazer algum processamento na imagem de treinamento. Defina as partes superior e inferior para 0. Se este processamento for feito, o mesmo processamento deverá ser feito na aplicação real.
- Essas imagens podem não ser adequadas para portabilidade para outros computadores devido à resolução e outros motivos. Todos podem optar por usar um modelo mais complexo, como uma rede CNN.
- Como é complicado coletar dados manualmente, você pode optar por fazer algum aprimoramento de dados.
Aqui não fazemos essas melhorias e usamos diretamente o modelo mais simples.
5. Jogue o jogo automaticamente
Jogar jogos automaticamente requer a ajuda do módulo pynput, que é instalado da seguinte forma:
pip install pynput
Podemos usar o seguinte código para conseguir pressionar a barra de espaço do teclado:
from pynput import keyboard
from pynput.keyboard import Key
# 创建键盘
kb = keyboard.Controller()
# 按下空格键
kb.press(Key.space)
Depois de saber como controlar o teclado, podemos usar o modelo para interceptar a previsão, como julgar se deve pressionar o espaço, o código é o seguinte:
import time
import cv2
import joblib
import numpy as np
from PIL import ImageGrab
from pynput import keyboard
from pynput.keyboard import Key
time.sleep(3)
# 0、创建键盘
kb = keyboard.Controller()
# 1、加载模型
model = joblib.load('auto_play.m')
while True:
# 2、准备数据
ImageGrab.grab().resize((960, 540)).save('current.jpg') # 保存当前屏幕截屏
x = cv2.imread('current.jpg', 0).reshape(-1)
x = [x]
# 3、预测
pred = model.predict(x)
print(pred)
# 如果需要跳,则按下空格
if pred[0] == 0:
kb.press(Key.space)
Depois de executar o programa acima, abra o navegador para iniciar o jogo. Código do programa e arquivos de imagem: https://download.csdn.net/download/ZackSock/86543410
Endereço do GitHub: https://github.com/IronSpiderMan/AutoPlayGoogleDino