机器学习很有趣!第二章:用机器学习制作超级马里奥的关卡

作者:Adam Geitgey

原文:https://medium.com/@ageitgey/machine-learning-is-fun-part-2-a26a10b68df3

翻译:拼命先生

转载请联系译者!

 

第一章中我们说到,机器学习使用通用算法告诉您一些有关数据的有趣的结论,而无需针对您正在解决的问题编写任何特定的代码。(如果您还没有阅读第1章,请立即阅读!)。

这一次,我们要用其中一种通用算法做一件很酷的事情  -  创建看起来像人类制作的视频游戏关卡。我们将构建一个神经网络,提供给它已存在的超级马里奥关卡,然后就等着看他创造一个心的超级马里奥关卡!

我们的算法将生成的一个关卡

就像第1章一样,本指南适用于对机器学习充满好奇但又不知道从哪里开始的人。为了让任何人都可以达到这个目标 - 意味着文章中有很多有很多概括性的描述,但谁在乎呢?如果这让人们对ML更感兴趣,那么任务就完成了。


做出更智能准确的猜测

回到第一章,我们创建了一个简单的算法,根据房屋的各特征属性估算其价值。我们给出了一个房子的如下数据:

我们最终得到了这个简单的估算函数:

def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
    price = 0

    # 一小撮这个
    price += num_of_bedrooms * 0.123

    # 一大撮这个
    price += sqft * 0.41

    # 也许再来一把这个
    price += neighborhood * 0.57

    return price

换句话说,我们通过将每个属性乘以权重,再把这些乘积求和,来估计房屋的价值。

让我们不使用代码,而是用一个图片来表示相同的函数:

箭头表示了函数中的权重

然而,该算法仅适用于结果与输入具有线性关系的简单问题。如果房价背后的真相不是那么简单怎么办?例如,对于大房子和小房子来说,地段可能很重要,但对于中型房屋来说根本不重要。我们怎样才能在模型中捕捉到那种复杂的细节?

为了更聪明,我们可以使用不同的权重多次运行此算法,收集各种权重下的估算结果:

让我们试着用4中不同的方式来解决问题

现在,我们有了四种不同的估价方法。我们将这四种估价方法汇总到一个最终估计当中。我们再把们放到同样的算法当中再算一遍(当然这次我们使用的权重不同)!

我们的新的超级答案结合了我们四种不同的尝试来解决问题。因此,它可以模拟比我们在一个简单模型中更复杂的案例。

什么是神经网络?

让我们将我们的四次尝试整合成一个大图:

这就是一个神经网络!每个节点都知道如何接受一组输入,对它们应用权重并计算输出值。通过将大量这些节点链接在一起,我们可以对复杂函数进行建模。

为了保持这种简介性,我跳过了很多内容(包括特征缩放激活函数),但最重要的部分是这些下面这些基本内容

  • 我们做了一个简单的估计函数,它接受一组输入并将它们乘以权重以得到输出。将这个简单的函数称为神经元
  • 通过将大量简单的神经元链接在一起,我们可以模拟那些无法通过单个神经元建模的复杂函数。

就像乐高一样!我们不能用一个LEGO块搭建摩天大楼,但如果我们有足够的基本LEGO块的话,我们就可以搭建成任何东西:

也许未来动物都是用塑料积木搭成的??那只能去未来一探究竟了!

给我们的神经网络记忆的能力

我们看到的神经网络总是在给出相同的输入时返回相同的答案。这是因为它没有记忆,在编程术语中,称它是无状态算法

在许多情况下(比如估算房子的价格),无状态算法正是你想要的。但是这种模型却做不到随着时间的推移对数据模式做出反应。

想象一下,我递给你一个键盘,并要求你写一个故事。但在你开始之前,我的工作就是猜你要输入的第一个字母。我应该猜些什么字母呢?

我可以利用我的英语知识来增加猜测正确的几率。例如,您可能会在单词的开头键入一个常见的字母。如果我看过你过去写的故事,我可以根据你在故事开头经常使用的词进一步缩小范围。一旦我获得了所有这些数据,我就可以用它来建立一个神经网络,算出你用任何一个字母作为开头的可能性。

我们的模型可能如下所示:

但是让我们把这个问题变得更难一点儿。假设我需要猜测你在故事中的任何一点将要输入的下一个字母是什么。这是一个更有趣的问题。

让我们用欧内斯特·海明威的《太阳照常升起》的前几个单词作为例子:

Robert Cohn was once middleweight boxi

接下来会写什么字母?

你可能猜到了'n' - 这个词可能是拳击。我们是根据在句子中看到的字母以及我们对英语常用词汇的了解来猜测的。此外,“中量级”这个词给了我们一个额外的线索,我们正在谈论拳击。

换句话说,如果我们知道了之前出现的字母,并将其与我们对英语规则的了解相结合,那么很容易猜到下一个字母。

要使用神经网络解决这个问题,我们需要在模型中添加状态(state)。每当我们向神经网络询问答案时,我们也会保存一组中间计算结果,并在下次作为输入的一部分重新使用它们。这样,我们的模型就能根据之前的输入调整其预测。

在我们的模型中跟踪状态,使得不仅可以预测故事中最可能的第一个字母,而且可以预测任意位置的最可能的下一个字母。

这就是循环神经网络(Recurrent Neural Network,简称 RNN)的基本概念。我们每次使用它时都会更新网络。这使它能够根据最近看到的内容更新其预测。只要我们给它足够的内存,它甚至可以模拟出长期的规律。

猜测一个字母有什么用?

预测故事中的下一个字母可能看起来毫无用处。到底意义何在呢?

一个很酷的用途可能是手机键盘的自动输入预测:

下一个最可能的字母是“t”

但是如果我们把这个想法发挥到极致呢?如果我们让我们的模型一直去预测下一个字母,永远不停止,那会怎样? 机器会不会自己写出一个完整的故事?

生成一个故事

刚刚我们看到了如何猜测海明威《太阳照常升起》中的下一个字母的。现在让我们来试一试写一个海明威式(写作风格)的故事吧!

让我们用安德烈·卡帕西(Andrej Karpathy)写的循环神经网络实现来完成我们的目标。安德烈是斯坦福的一位深度学习研究者。有关用 RNNs 生成文字,他写过一篇非常棒的导论。你可以在 GitHub 上查看这个模型的代码

让我们用《太阳照常升起》中的文字构建我们的模型。全书共有 362,239 个词,使用了 84 个不同的字符(包括标点符号和大小写字母等)。和真实世界的问题相比,这组数据其实已经非常小了。如果想要更好地模仿海明威的文风,我们需要的样本文本长度可能是这本小说长度的几倍。但是这本《太阳照常升起》已经足够展示制作我们模型的过程了。

当我们刚开始训练 RNN 的时候,它猜测的并不准确。这是它经过 100 个循环训练之后的结果:

hjCTCnhoofeoxelif edElobe negnk e iohehasenoldndAmdaI ayio pe e h’e btentmuhgehi bcgdltt. gey heho grpiahe.

Ddelnss.eelaishaner” cot AAfhB ht ltny

ehbih a”on bhnte ectrsnae abeahngy

amo k ns aeo?cdse nh a taei.rairrhelardr er deffijha [2]

 

你可以看到的是机器已经知道单词之间应该有空格,这正是我们想要的。

1000 个循环之后,结果看起来更靠谱一点:

 

hing soor ither. And the caraos, and the crowebel for figttier and ale the room of me? Streat was not to him Bill-stook of the momansbed mig out ust on the bull, out here. I been soms

inick stalling that aid.

“Hon’t me and acrained on .Hw’s don’t you for the roed,” In’s pair.”

“Alough marith him.”[3]

 

我们的模型已经开始识别出句子的基本构成模式了。它已经学会给句子加上句号,甚至学会了用引号。还成功的拼出了一些单词,但大部分依然在胡扯。

经过几千次交互训练之后,他看起来很棒:

 

He went over to the gate of the café. It was like a country bed.

“Do you know it’s been me.”

“Damned us,” Bill said.

“I was dangerous,” I said. “You were she did it and think I would a fine cape you,” I said.

“I can’t look strange in the cab.”

“You know I was this is though,” Brett said.

“It’s a fights no matter?”

“It makes to do it.”

“You make it?”

“Sit down,” I said. “I wish I wasn’t do a little with the man.”

“You found it.”

“I don’t know.”

“You see, I’m sorry of chatches,” Bill said. “You think it’s a friend off back and make you really drunk.”

他跑到了咖啡厅的门口。它像是一个乡下的床一样。

 “你知道这是我。” 
 “诅咒我们,”比尔说。
 “我很危险,”我说。“你是她做到了,并认为我会很好的披着你,”我说。
 “我在驾驶室里看起来并不奇怪。” 
 “你知道我就是这样,”布雷特说。
 “无论如何都是打架?” 
 “这样做。” 
 “你做到了吗?” 
 “坐下来,”我说。“我希望我不跟那个男人做点什么。” 
 “你找到了。” 
 “我不知道。” 
 “你看,我很抱歉聊天,”比尔说。“你认为这是一个朋友,让你真的喝醉了。”

 

到此时,算法已经收集到了海明威写作的基本风格——简短而直接的对话形式。甚至有一些话语开始能被人类理解。

和原文中的句子作比较:

 

There were a few people inside at the bar, and outside, alone, sat Harvey Stone. He had a pile of saucers in front of him, and he needed a shave.

“Sit down,” said Harvey, “I’ve been looking for you.”

“What’s the matter?”

“Nothing. Just looking for you.”

“Been out to the races?”

“No. Not since Sunday.”

“What do you hear from the States?”

“Nothing. Absolutely nothing.”

“What’s the matter?”

酒吧里面有几个人,外面独自一人坐在哈维斯通。他面前有一堆碟子,他需要刮胡子。
 “坐下,”哈维说,“我一直都在找你。” 
 “怎么了?” 
 “没什么。只是在寻找你。“ 
 ”参加比赛了?“ 
 ”不。不是从星期天开始。“ 
 ”你从州里听到了什么?“ 
 ”没什么。绝对没有。“ 
 ”什么事?“

 

即使我们只是寻找每个字符之间的规律,我们的算法也已经用恰当的格式重新出一篇看起来可信的文章。这非常厉害!

我们也不用完全从头生成文本。我们可以把前几个字母放到算法当中去,让它找到后面的几个字母。

让我们一起来模仿海明威著作的封面,来伪造书名和作者玩玩吧!我们规定最开始的字母分别为「Er」、「He」、「The S」。

真正的书在左边,我们计算机生成的傻乎乎的书在右边

看起来不错呀!

但是真正让人脑洞大开的部分是,这个算法能够找出任何数据序列中的规律。他可以轻松创作出食谱或者是假的奥巴马的演讲。但为什么一定要限定是人类语言呢?这个算法也可以用来处理任何有规律可循的数据。

不用马里奥,智造马里奥

2015年,任天堂在 Wii U 平台上发布了超级马里奥制造

每个孩子的梦想

在这个游戏中,你可以用编辑器创造出你自己的超级马里奥关卡,并把它们上传到互联网上和朋友们一起玩。你可以使用游戏中所有经典的道具和敌人来创造你自己的关卡。这就像是一个为成年人设计的乐高积木玩具。

所以问题来了,我们能够使用创作海明威的模型来制作马里奥么?

首先,我们需要一组数据来训练我们的模型。我们会使用马里奥兄弟 1985 年版所有的室外关卡的数据。

最棒的圣诞节,谢谢爸爸和妈妈

这个游戏有32个关卡,其中约70%都相同风格的户外场景。所以我们会保留这些。

为了获得每个关卡的设计,我得到了游戏的原始副本并编写了一个程序将游戏关卡的设计提取出来。超级马里奥兄弟是一款有着30年历史的游戏,网上有很多资源可以帮助你弄清楚游戏内存中存储的关卡。从旧视频游戏中提取关卡数据是一项有趣的编程练习,您应该尝试一下。

这是游戏的第一关(你可能还记得,如果你曾经玩过它):

如果仔细观察,我们可以看到关卡是由一个个简单的网格类型的物品构成的:

我们可以很容易地将这个网格表示为一个字符序列,其中一个字符代表每个对象:

-------------------------- 
------------------------ - 
-------------------------- 
#??#------------------ ---- 
-------------------------- 
-------------------- ------ 
-------------------------- 
-  ## ------ =  -  = ----- ----- ==  - 
-------- ==  -  == -------- ===  - 
------- ===  -  ===  - ----- ====  - 
------ ====  -  ==== ---- =====  - 
============== =========== -

我们用一个字符替换了关卡中的每个对象:

  • ' - '是一个空白区域
  • '=' 是一个坚实的块
  • '#'是一块易碎的砖
  • '?'是一个硬币块

......等等,为关卡中每种不同类型的对象使用不同的字母。

我最终得到了如下所示的文本文件:

原始关卡

用文本表示

仔细观察这个文本文档,你会发现如果以“行”的顺序观察,并没有什么规律可循:

逐行阅读,并没有什么规律,你会发现很多行就是空白的

当你把关卡理解为连续的列的时候,规律就浮现出来了:

一列一列的看,规律就显现出来了,比如每一列都以“=”结尾

因此,为了使算法能够在我们的数据中找到规律,我们需要逐列提供数据。确定输入数据的最有效的表达方法(称为特征选择)也是使用机器学习算法的关键技巧之一。

为了训练模型,我需要将文本文件旋转90度。这样可以确保将这些字符按照更容易发现规律的方式输入模型:

----------- = 
-------#--- = 
-------#--- = 
-------?--- = 
- -----#--- = 
----------- = 
----------- = 
---------- @ = 
---- ------ @ = 
----------- = 
----------- = 
----------- = 
------ --- PP = 
--------- PP = 
---------- == 
--------- === 
-------- == == 
------- ===== 
------ ====== 
----- ======= 
--- ========= 
--- =========

培训我们的模型

正如我们在创建海明威散文模型时所看到的那样,模型随着我们的训练而得到改善。

经过一番训练后,我们的模型产生了一堆垃圾:

-------------------------- 
LL + <&= ------ P ------------- 
-------- 
--------------------- T  - # - 
----- 
-  =  -  =  -  = --- --------- =  - & -  T -------------- 
-------------------- 
- -  = ------ $  -  =# -  = -_ 
-------------- = ---- = <---- 
------- b 
-

它好像理解了应该有很多'-'和'=',还不错,但它尚未找到规律。

几千次迭代后,它开始看起来比较像样了:

- 
----------- = 
---------- = 
-------- PP = 
-------- PP = 
----- ------ = 
----------- = 
----------- = 
-------?--- = 
------- ---- = 
----------- =

该模型几乎已经发现每条线的长度应该相同。它甚至已经开始弄清楚Mario的一些逻辑:马里奥的管道总是两个块宽,至少两个块高,所以数据中的“P”应该出现在2x2簇中。那太酷了!

通过更多的培训,模型可以生成完全有效的数据:

-------- PP = 
-------- PP = 
---------- = 
---------- = 
-------- -  = 
--- PPP = --- = 
--- PPP = --- = 
---------- =

让我们从模型中采样整个级别的数据并将其水平旋转:

用我们的模型创造的一整关

这个数据看起来棒极了!并且有几个令人敬畏的事情需要注意:

  • 它将一个Lakitu(漂浮在云上的怪物)放在水平开始的天空中 - 就像在真正的马里奥关卡一样。
  • 它知道漂浮在空中的管道应该放在固体块的顶部而不是悬挂在空中。
  • 它将敌人置于恰当的位置。
  • 它不会创造阻止玩家前进的任何东西。
  • 这感觉就像是超级马里奥兄弟一关真实关卡,因为它是基于游戏的原版关卡创造出来的。

最后,让我们使用这个关卡,并在Super Mario Maker中重新创建它:

我们的把关卡数据输入到编辑器以后得到的关卡,也可以看一下关卡视频!

自己动手玩玩吧!

如果您有超级马里奥制造商,你可以通过网页版书签收藏或者是用关卡代码 4AC9–0000–0157-F3C3 来找到这一关

 

玩具与现实世界的应用

我们用来训练模型的循环神经网络算法,就是真实世界中,许多公司用来解决语音识别和语言翻译等难题的同类算法。是什么让我们的模型成为“玩具”而不是尖端科技的,就是数据量。我们的模型是从非常少的数据生成的,要创造一个非常好的模型,我们需要更多原版超级马里奥兄弟里面的关卡数据

如果我们能够访问任天堂拥有的数十万用户创建的超级马里奥关卡,我们就可以制作出令人惊叹的模型。但我们不能 - 因为任天堂不会让我们拥有它们。大公司不会免费提供他们的数据。

随着机器学习在更多行业变得越来越重要,优秀程序和糟糕程序之间的区别在于您需要多少数据来训练模型。这就是为什么谷歌和Facebook这样的公司不择手段的需要你的数据!

例如,Google最近开源了TensorFlow,它是用于构建大型机器学习应用程序的软件工具包。免费提供这种重要并且实用的技术,这对谷歌来说是一个非常重要的决定。你要知道这可是和谷歌翻译使用的是相同的功能。

但如果没有谷歌在各种语言中的大量数据,你就无法成为谷歌翻译的竞争对手。数据是谷歌的优势所在。想想下次打开Google地图位置记录Facebook位置历史记录时,请注意它会记录下您曾经去过的每个地方。

进一步阅读

在机器学习中,永远不止有一种方法来解决问题。在决定如何预处理数据以及使用哪些算法时,您有无限的选择。通常结合多种方法可以获得比任何单一方法更好的结果。

读者向我发送了其他有趣的方法来生成超级马里奥级别的链接:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值