66

我用TensorFlow2.0训练了一只AI来玩贪吃蛇

 4 years ago
source link: https://www.tuicool.com/articles/vmqyuiM
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近迷上了复古游戏,想起小时候入迷的玩贪吃蛇,真的是乐趣无穷。现在到了2019年了,一切似乎都变得和以前不同,比如,我们可以用AI下围棋,用AI做自动驾驶,有没有可能让一个AI自己学会玩贪吃蛇呢?答案当然是可以!!

先来看看我们的效果:

Ifi2222.png!web

思路

让AI学会贪吃蛇,那幺首先我们需要定义这个游戏环境。有人会说用pygame,或者gtk来做一个界面,其实都显得过于复杂,还没有等到我把AI造出来,但就游戏界面估计就得浪费大把时间。我们直接用OpenCV即可解决这个问题! 大概的代码如下:

如何让AI学习

那幺怎幺让AI知道贪吃蛇的游戏规则呢?也就事说,让AI知道:

你不能吃掉你自己;

你不能碰到墙;

你迟到了红色食物才算是拿到了奖励。

经过我的尝试,我发现,如果采用传统的动态规划的方式去做,既首先从图片着手,来学习预测下一步贪吃蛇的方向,其实很难让Agent学到任何东西,相反,我们的策略是:

    1. 首先我们让AI先在一个小的环境下学习;
    1. 然后逐渐把盘子扩大;
    1. 最后在一个固定大小的棋盘上看看最终效果。

这个思想有点像ProgressiveGAN,也就是循序渐进的让Agent学习,先从小环境着手,小环境学习好了,再加大难度。事实上,实验验证了我们的想法,这个方向无疑是有效果的。

f6aac60c5f83bd52d9fd29bb1502e82d.gif

从图可以看出,这是其中的一个环节,可以看到我们的贪吃蛇最大长度可以达到9,其实已经很不错了,旁边的数字显示它已经自己咬死了自己1841次,可是依旧坚强的活着。。

对于整个模型算法的流程,也非常清晰,简单来说步骤如下:

首先我们定义一个轮回总数,世事无常有轮回,你最多死50000次,每次给你8条命,该怎幺学,贪吃蛇你看着办;

在每个轮回中,我们把每一次尝试的走位记录下来,放到我们的Memery中,这样我们的贪吃蛇才能像蔡徐坤一样风骚的走位;

最后每次轮回死掉了之后,就拿这些记忆去训练我们的Qnetwork;

Qnetwork就这样变得越来越强,因为它记忆了所有的成功尝试和失败的尝试,下一次指导也就越给力,最后每次轮回的时间也就更长,不至于说是落地成佛。。

QNetwork构建

对于这类问题,其实就是一个根据环境进行决策的过程,可以借助强化学习的手段来学习,但作为下一个动作空间的预测模型,还是需要我们构建DNN去拟合,从数据中学习到预测下一步动作的规律,这也是核心。 我们的QNetwork构建采用的是TensorFlow 2.0, 并且采用Keras NN API进行构建。可以说非常的结合潮流。核心的QNetwork构建代码如下:

class QNetwork:
    def __init__(self,input_shape, hidden_units, output_size, learning_rate=0.01):
        self.input_shape = input_shape
        hidden_units_1, hidden_units_2, hidden_units_3 = hidden_units
        self.model = tf.keras.Sequential([
            tf.keras.layers.Dense(units=hidden_units_1, input_dim=input_shape, activation=tf.nn.relu),
            tf.keras.layers.Dense(units=hidden_units_2, activation=tf.nn.relu),
            tf.keras.layers.Dense(units=hidden_units_3, activation=tf.nn.relu),
            tf.keras.layers.Dense(units=output_size, activation=tf.keras.activations.linear)
        ])
        self.model.compile(optimizer = tf.keras.optimizers.Adam(learning_rate), loss='mse',metrics=['accuracy'])
        
    def predict(self, state, batch_size=1):
        return self.model.predict(state, batch_size)
    
    def train(self, states, action_values, batch_size):
        self.model.fit(states, action_values, batch_size=batch_size, verbose=0, epochs=1)

对与这个模型,其实可以采用更深入的架构,我们也会在后续不断地深入探索不同模型的优化效果,让我们的贪吃蛇AI更加的智能。

强化学习训练

我们可以看一下整个训练过程的log:

QfiIrqM.png!web

可以看到,大概5000个Episode之后,得分可以逐渐的增高,说明网络在指导贪吃蛇下一步运动的时候更加的得心应手。从训练的实际gif图也可以看到,现在我们贪吃蛇的最大长度可以达到13,试想一下,随着棋盘的增大,模型的变强,是不是贪吃蛇会变得非常非常的长,以至于超越人类的玩贪吃蛇极限呢??我们拭目以待!!

94af2994dcba1fd799c591669a98d1bb.gif

训练还没有完全,但是你可以看到,这个走位还是很风骚的有木有!!

eeffeaa42765a1e9f2bbe1d499011720.gif

Show Time

最后,到了我们的人工智能表演时间!!!让我们把舞台交给贪吃蛇AI!!!!贪吃蛇,上!

9a21fe66ea1048221c0502bc7862ad6b.gif

这个走位还是非常的风骚的!经过一个晚上的训练,多达30000多次的轮回,我们的贪吃蛇终于可以在长度28的范围之内保证自己屹立不倒,我想这应该比多部分手残少年要强。。比如我。。

总结一下我们的强化学习存在的问题和无法解决的死角点:

虽然强化学习模型可以处理99%的情况,但是不管是设幺场景都会存在那幺1%从来没有见过的情况,大概率此时AI不知道该如何决策,极有可能瞎几把一顿乱走,我们的贪吃蛇倒也还好,但是如果用到了自动驾驶决策里面,那幺解决就是直接见马克思了;

虽然我们的可以将模型无线的复杂化,经过两个周的实验,我们发现并非模型越复杂,AI越强;

更令人琢磨不透的是,并非Episode越久,AI越强,在这期间我们发现,它有一个巅峰时刻,最高平均得分为188分,这相当于是它最高的长度可以达到40步,感兴趣的朋友来魔改一下我们的贪吃蛇,看看你能训练的贪吃蛇Ai可以强大到什幺地步,是否能稳如阿法狗;

贪吃蛇无法预测边界,也就是说如果我们的模型在一个比他训练的环境更大的棋盘上运作,它大概率无法准确预测边界,这也是我们让他从小棋盘开始训练逐渐扩大棋盘大小的原因,但是即便如此,它无法在任意大小的棋盘下准确的找到食物,并且避开边界。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK