导读:人工智能玩游戏从上个世纪就有着相关的影响与作品,尤其是其中的棋类游戏,其中就有五子棋、围棋、象棋等。从IBM的超级计算机“深蓝”(Deep Blue)以213平的成绩战胜了当时世界排名第一的国际象棋大师加里·卡斯帕罗夫,到2016年“Alpha Go”击败了人类围棋冠军,人工智能玩游戏越来越完善。总体来说,国内在智能博弈领域进行了一系列的研究,尝试将该技术应用到作战推演领域,建立了具有自主产权的博弈平台,技术层面也不断突破,不再局限于传统的行为决策树、专家知识库等,开始将强化学习技术、深度学习技术、遗传模糊算法等引入智能博弈,取得了一系列的关键技术的突破。但是,当前的研究主要聚焦在比较简单的智能博弈环境,对复杂环境及不完全信息的博弈对抗研究仍然需要进一步探索。如今像一些其他的小游戏,例如马里奥、弹球等,人工智能也有着很好的表现。现在本文通过一个2014年代替NOT FOUND 404的网页的小游戏:谷歌小恐龙(Google Chrome Dinosaur)来讲述讲述人工智能与游戏的过程。


一、人工智能如何玩游戏

人工智能首先通过数据的预处理,然后构建模型,对数据进行训练与判断,最后进行测试,也就是开始游戏。具体来看,游戏AI的研究涉及三个方面:首先是对外界环境产生感知的研究;其次,游戏中对话智能的研究;第三,研究游戏中人、智能体和环境的交互。


其中针对于不同游戏来说,模型的选择与构建也有所不同。如今,游戏AI主流的方法为以下四种方式来进行游戏:
1、基于规划的方法;


2、基于强化学习的方法;

3、基于监督学习的方法;

4、混合方法。

本文主要使用的是强化学习的方法和监督学习的方法来分别使用人工智能进行训练,然后使用python控制键盘进行小恐龙的闯关。

二、小游戏介绍

首先我们介绍一下这个小游戏:谷歌小恐龙(Google Chrome Dinosaur),这个游戏的操作十分的简单,玩家只需要在合适的时机进行通过点击‘Space’键跳跃,来躲避障碍物即可。生存的时间越长,得分相应的越高。

然后我们训练的数据集只有两种方式,跳或者不跳[0,1]。比如说左图就是距离障碍物较近,因此我们需要通过按下空格键进行跳跃;右图前方没有障碍物,因此我们不需要进行操作即可。

三、基于强化学习中的Q-Leaning的方法训练

强化学习的主要方式为使用无监督的方式下,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。如下图是一个典型的强化学习的闭环模式,通过环境给人体的反馈进行交互获得奖励,目标是为了让本体收到最大化的收益。通过这种方式使强化学习系统在行动-评价的环境中获得知识,改进行动方案以适应环境。

Q-learning算法,每次更新我们都用到了Q现实和Q估计,而且Q-learningQ(s1,a2)现实中,也包含了一个Q(s2)的最大估计值,将对下一步的衰减的最大估计和当前所得到的奖励当成这一步的现实。然后分析这套算法中一些参数的意义。Epsilon greedy是用在决策上的一种策略,比如epsilon=0.9,就说明有90%的情况我会按照Q表的最优值选择行为,10%的时间使用随机选行为。alpha是学习率,来决定这次的误差有多少是要被学习的,alpha是一个小于1的数。gamma是对未来reward的衰减值。

针对本游戏我们使用Q-learning的强化学习的方法主要是以下几个步骤进行:

1.     预处理:首先要将图像进行处理。先将图片进行裁剪,只留下障碍物与边缘的图像,然后这样可以简化计算,仅仅只需要知道障碍物与边缘之间的距离即可,这样大大简化了计算量。

2.     模型构建:我们把3个卷积层压平,连接到一个512神经元的全连接层(dense layer)上。

这个模型的输出,形状和可能的操作数量一样。模型会预测各种操作的Q值,也就是之前提到的discounted future reward,然后选择数值最高的那个作为最后的值。

代码模型如下:

#model hyper parameters

LEARNING_RATE = 1e-4

img_rows , img_cols = 40,20

img_channels = 4 #We stack 4 frames

ACTIONS = 2

def buildmodel():

print("Now we build the model")

model = Sequential()

model.add(Conv2D(32,(8,8),strides=(4,4),padding='same',input_shape=(img_cols,img_rows,img_channels))) #20*40*4

model.add(Activation('relu'))

model.add(Conv2D(64, (4, 4), strides=(2, 2), padding='same'))

model.add(Activation('relu'))

model.add(Conv2D(64, (3, 3), strides=(1, 1), padding='same'))

model.add(Activation('relu'))

model.add(Flatten())

model.add(Dense(512))

model.add(Activation('relu'))

model.add(Dense(ACTIONS))

adam = Adam(lr=LEARNING_RATE)

model.compile(loss='mse',optimizer=adam)

print("We finish building the model")

return model

3.     训练过程:

1)从无操作开始,得到初始状态initial state(s_t)

2)观察玩游戏的过程,代码中的OBSERVATION表示步数

3)预测一个操作的效果

4)在Replay Memory中存储经验

5)训练阶段,从Replay Memory里随机选择一组,用它来训练模型

6)如果game over了,就重开一局

训练代码实现如下:

def trainNetwork(model,game_state):

# store the previous observations in replay memory

D = deque() #load from file system

# get the first state by doing nothing

do_nothing = np.zeros(ACTIONS)

do_nothing[0] =1 #0 => do nothing,

#1=> jump

x_t, r_0, terminal = game_state.get_state(do_nothing) # get next step after performing the action

s_t = np.stack((x_t, x_t, x_t, x_t), axis=2).reshape(1,20,40,4) # stack 4 images to create placeholder input reshaped 1*20*40*4

OBSERVE = OBSERVATION

epsilon = INITIAL_EPSILON

t = 0

while (True): #endless running

loss = 0

Q_sa = 0

action_index = 0

r_t = 0 #reward at t

a_t = np.zeros([ACTIONS]) # action at t

#choose an action epsilon greedy

if random.random() <= epsilon: #randomly explore an action

print("----------Random Action----------")

action_index = random.randrange(ACTIONS)

a_t[action_index] = 1

else: # predict the output

q = model.predict(s_t)    #input a stack of 4 images, get the prediction

max_Q = np.argmax(q)     # chosing index with maximum q value

action_index = max_Q

a_t[action_index] = 1    # o=> do nothing, 1=> jump

#We reduced the epsilon (exploration parameter) gradually

if epsilon > FINAL_EPSILON and t > OBSERVE:

epsilon -= (INITIAL_EPSILON - FINAL_EPSILON) / EXPLORE

#run the selected action and observed next state and reward

x_t1, r_t, terminal = game_state.get_state(a_t)

last_time = time.time()

x_t1 = x_t1.reshape(1, x_t1.shape[0], x_t1.shape[1], 1) #1x20x40x1

s_t1 = np.append(x_t1, s_t[:, :, :, :3], axis=3) # append the new image to input stack and remove the first one

# store the transition in D

D.append((s_t, action_index, r_t, s_t1, terminal))

D.popleft() if len(D) > REPLAY_MEMORY

#only train if done observing; sample a minibatch to train on

trainBatch(random.sample(D, BATCH)) if t > OBSERVE

s_t = s_t1

t = t + 1

print("TIMESTEP", t, "/ EPSILON", epsilon, "/ ACTION", action_index, "/ REWARD", r_t,"/ Q_MAX " , np.max(Q_sa), "/ Loss ", loss)


四、基于监督学习中的CNN的方法训练

本方法与上一个方法最大的区别就在于是否有监督,即查看输入是否有标签(label),有的话则是监督学习,否则为无监督学习。通俗一点来说就是当你在辨认某一事物的时候我们是否有人告诉你这个事物实际上是什么,如果有人告诉你他们的具体名称则为监督学习;如果你是根据其特征样子、形状体型等差异来进行学习并且进行分类,此时为无监督学习。下图为监督学习模型选择表。

同时本方法使用CNN(即卷积神经网络),最近也是十分的常见与流行。因此我们需要了解并且熟悉本方法的概念。

1.     卷积

离散卷积的本质其实就是一个加权求和的一个过程。

CNN中卷积的本质就是利用共享参数的过滤器filter/kernel,通过计算中心像素点及相邻像素点的加权和来构成feature map实现空间特征的提取,加权系数就是卷积核的权重系数。左边红色框内数字与卷积核所做卷积运算所得结果为右边红色框内的3,图中给出了在步长stride=1的情况下,卷积运算所得新的表格的边长的计算公式(其中f即为filter边长)。

2.     填充

由于我们使用卷积的过程中由于卷积核运算导致了我们的最后的表格减少,因此我们需要有填充的方法来增加缺少的部分。为了使得大小为6*6的图像(N2)经卷积运算后大小不变,可以事先填充,将其变为8*8的图像(这里用0填充),经过卷积运算可以得到6*6的图像(N3)。称这种图像经卷积运算后大小不变的填充方式为same(在许多CNN的模型如VGG-16中都会用到same方式的卷积运算)。

3.     池化

在这一步是为了减少计算量,这样可以大大加速人工智能的学习时间,但是这一步其实不是必须的。池化也分为很多种,有最大值池化和平均值池化,区别在于在池化范围内选择的值为最大值还是平均值为最终的值。:

当然多通道也是有着同样的方式:

针对本游戏我们使用CNN的监督学习的方法主要是以下几个步骤进行:

1、收集数据

我们需要在自己玩游戏的情况下不停的进行截图作为训练集,我们将使用pillow模块来实现截图。然后放到特定的文件夹下。

2、构建CNN模型


使用CNN模型进行训练,具体代码如下:
import tflearn


from tflearn.layers.conv import conv_2d, max_pool_2d

from tflearn.layers.core import input_data, dropout, fully_connected

from tflearn.layers.estimator import regression

from tflearn.layers.normalization import local_response_normalization

def alexnet(width, height, lr):

# 模型输入:截图和键盘操作

network = input_data(shape=[None, width, height, 1], name='input')

# 卷积层

network = conv_2d(network, 96, 11, strides=4, activation='relu')

# 池化层

network = max_pool_2d(network, 3, strides=2)

network = local_response_normalization(network)

network = conv_2d(network, 256, 5, activation='relu')     # 卷积层

network = max_pool_2d(network, 3, strides=2)

network = local_response_normalization(network)

network = conv_2d(network, 384, 3, activation='relu')     # 卷积层

network = conv_2d(network, 384, 3, activation='relu')     # 卷积层

network = conv_2d(network, 256, 3, activation='relu')     # 卷积层

network = max_pool_2d(network, 3, strides=2)

network = local_response_normalization(network)

# 全连接层

network = fully_connected(network, 4096, activation='tanh')

network = dropout(network, 0.5)

network = fully_connected(network, 4096, activation='tanh')

network = dropout(network, 0.5)

network = fully_connected(network, 2, activation='softmax')

network = regression(network, optimizer='momentum',

loss='categorical_crossentropy',

learning_rate=lr, name='targets')

model = tflearn.DNN(network, checkpoint_path='model_alexnet',

max_checkpoints=1, tensorboard_verbose=2, tensorboard_dir='log')

return model

3、训练模型

将收集到的数据集进行打乱与分类成训练集和测试集,然后将训练集投入神经网络中进行训练,然后得到最后的模型。具体代码如下:

import numpy as np

from Cnn_model import alexnet

import warnings

from random import shuffle

import time

warnings.filterwarnings("ignore")

# 缩放后规格

WIDTH = 160

HEIGHT = 40

LR = 1e-3

EPOCHS = 10

MODEL_NAME = 'dinosaur' # 模型名称

# 创建模型

model = alexnet(WIDTH, HEIGHT, LR)

# 加载模型

model.load(MODEL_NAME)

hm_data = 30

for i in range(EPOCHS):

for i in range(8, hm_data + 1):

train_data = np.load('training_data-{}.npy'.format(i), allow_pickle=True)

# 随机打乱数据集

# shuffle(train_data)

# 训练集

train = train_data[:-100]

# 测试集

test = train_data[-100:]

X = np.array([i[0] for i in train]).reshape([-1, WIDTH, HEIGHT, 1])

Y = [i[1] for i in train]

test_x = np.array(([i[0] for i in test])).reshape([-1, WIDTH, HEIGHT, 1])

test_y = [i[1] for i in test]

# 将数据投喂给神经网络

model.fit({'input': X}, {'targets': Y}, n_epoch=1, validation_set=({'input': test_x}, {'targets': test_y}),

snapshot_step=500, show_metric=True, run_id=MODEL_NAME)

# 保存模型

model.save(MODEL_NAME)

五、人工智能与游戏

如今人工智能游戏方面有着越来越大的发展和光明的前景,尤其是如今有着很多家公司也有发展,例如DeepMind企业和OpenAI公司在这方面都有着出色的表现。这两个企业都处于人工智能的前沿的发展,其中DeepMind企业在20163月份发明了让人印象深刻的AlphaGo,以41击败韩国围棋冠军李世石(Lee Se-dol),之后又以3:0的战绩打败了柯杰;在后面的2017年又开发了AlphaGoZero在自我训练了3天后以100-0的战绩赢得了AlphaGo。在后面也有着Alpha Zero可以进行其他的棋类游戏,象棋、围棋和五子棋等,还在30多款雅达利游戏中也有着很好的表现。

“游戏提供了一个现实世界和未来虚拟世界的中间通道,在游戏领域我们可以最早地看到未来是什么样。作为人工智能研究领域的专家,李文新认为游戏是研究AI的绝佳途径之一。其中游戏可以作为度量人工智能的方式之一,具有着较好的判断该算法的好与坏、适合与否的工具。

如今虽然人工智能发展的很快,但是“智能”的说法还是有着模糊的定义,很多时候我们是通过完成不同难度级的任务来衡量智能,所以很多游戏实际上也是在检验人类的智能。而我们让机器做人类也觉得困难的事,这件事本身就是在度量人工智能。

六、引用

相关项目来源:

https://github.com/IronSpiderMan/AutoPlayGoogleDino;

https://github.com/ravi72munde/Chrome-Dino-Reinforcement-Learning

引用文献:

[1]朱鹏,李佳宁. 北京大学人工智能研究院副院长李文新:游戏是度量人工智能一种方式 提供了链接现实与虚拟的通道[N]. 每日经济新闻,2022-06-21(004).DOI:10.28571/n.cnki.nmrjj.2022.001993.

[2]孙宇祥,彭益辉,李斌,周佳炜,张鑫磊,周献中.智能博弈综述:游戏AI对作战推演的启示[J].智能科学与技术学报,2022,4(02):157-173.

[3]胡珉琦. 电子游戏:人工智能的另类训练场[N]. 中国科学报,2021-10-21(003).DOI:10.28514/n.cnki.nkxsb.2021.003457.

阅读次数:7488
吉林省人工智能学会
(2022-12-06 12:22:00)

备案号:吉ICP备19005669号-1

Copyright © 2010 吉林省人工智能学会From:3.138.32.53

二维码