原文:Machine Learning is Fun! Part 2 -- Using Machine Learning to generate Super Mario Maker levelsgit
做者:Adam Geitgeygithub
翻译:Kaiser(微博:王司图)web
在系列的Part 1中咱们已经讲过,机器学习是用普适的算法从数据中挖掘出有趣的东西,而无需针对具体问题写代码。算法
此次咱们将见识一种普适算法的炫酷表现——创造乱真的游戏关卡。咱们将创建一个神经网络,导入已有的超级马里奥数据,而后创造新的关卡。编程
正如Part 1同样,本系列教程适合全部对机器学习感兴趣、但殊不知从何开始的读者。但愿全部人都能读懂——因此不免会有些粗疏。不过但凡能把一我的带进ML的坑里,也就算没白写。bash
在Part 1中,咱们写了一个简单的算法来根据房产的属性预测价格,数据以下表所示:网络
预测函数是这样的:less
def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
price = 0
# 加少许配方1
price += num_of_bedrooms * 0.123
# 加大把配方2
price += sqft * 0.41
# 适量的配方3
price += neighborhood * 0.57
return price
复制代码
也就是说,房价的预测值是由每种属性乘以权重再相加获得的。用图形来表示:机器学习
可是这个算法只对很简单的线性问题有效,若是房价背后的真实规律没有那么简单呢?好比周边环境可能对特别大或特别小的房子影响显著,但对于中间房型则没有什么影响。如何才能捕捉到这些复杂细节呢?编辑器
为了更加的机智,咱们能够用不一样的权重屡次执行算法,每一组权重对应不一样的边界状况。
如今咱们有四个价格预测了,而后再把这4个组合成最终结果,而且也是经过加权(只是权重值变了)。
新的_超级答案_结合了四次求解尝试,因此相比于初始的简单模型,可以模拟更多的状况。
把个人四次求解尝试整合到一张大图里:
这就是一个神经网络!那个节点都有一组输入,执行加权计算,产生一个输出值。把这些节点串起来就可以对复杂函数进行建模了。
为了节省篇幅,这里我跳过了不少内容(好比特征缩放和激励函数),可是最重要的部分仍是如下几点基本思想:
咱们用简单的函数,对输入进行加权得到输出,这个简单函数就叫神经元。
把许多简单的神经元链在一块儿,就能够对单个神经元描述不了的复杂问题进行建模。
就像乐高同样,单个积木块或许作不出什么,但只要有足够多的积木,就什么都能搭建。
给定相同的输入,此前的神经网络也会给出相同的输出,用编程术语叫无状态算法(stateless algorithm)。
在不少实例(好比房价预测)中,这正是咱们想要的。可是这类模型没法应对数据中的时变模式。
想象一下,我给了你一个键盘,让写个故事。在开始以前,我要猜你会写哪一个字母,那么我该怎么猜呢?
我能够利用个人英语知识来增长命中率,好比你写的第一个字母每每是一个单词的首字母。若是我看过你的过往文章,还能够进一步根据你的文风收缩范围。若是我有所有数据,我就能够搭建一个神经网络,来计算你写下一个字母的几率。
模型多是这样:
再来看一个更有挑战的问题,随便在故事里定个位,而后我要猜你的_下一个_字母,这就更有意思了。
用海明威的《太阳照常升起》做为例子:
Robert Cohn was once middleweight boxi
下一个字母是什么?
你大概会猜'n'——这个词应该是_boxing_。这样的猜想是基于咱们已知的经常使用英语单词积累。同时,'middleweight' 也给出了额外的线索指向boxing。
下一个字母好猜,是由于咱们归入了其以前的句子,并结合已有的语言知识。
若是要用神经网络来解决这个问题,咱们须要在模型中添加一个_状态(state)_,每次咱们向神经网络询问答案的时候,还会得到一个中间计算,并在下次看成输入的一部分重复利用。如此一来,咱们的模型就会根据以前的输入调整预测结果。
跟着状态走,虽然不能猜_第一个_字母,但却能够根据前面的字母猜_下一个_。
这就是_循环神经网络(Recurrent Neural Network)_的基本思路。每次使用,咱们都是在更新网络,这就能够基于以前最多见的输入,去更新预测。只要“记忆力”足够,这就能够对数据的时变模式进行建模。
猜想故事里的下一个字母挺起来没有什么卵用,那还提这茬干吗?
手机输入法的自动补全就是一个应用:
往计算状况再想一想,若是咱们让模型猜完一个再猜一个,如此循环往复——咱们就可让计算机本身来写个故事了!
知道了如何猜海明威句子里的下一个字母,让咱们试着产生一个完整的海明威风格故事。
咱们将使用Andrej Karpathy开发的循环神经网络。Andrej是斯坦福大学的深度学习研究者,而且他写了一个极好的循环神经网络文本生成入门,你能够在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
能够看见词与词之间已经有空格了。
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.”
模型已经识别出了基本句型模式,而且知道在句末加句号,给对话加引号,个别单词已经能读懂了,但整篇还是一派胡言。
又通过几千次迭代以后,如今已经看起来很是好了:
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%是在室外,因此就从这下手。
为了获取每一个关卡的设计,我写了一个程序从游戏中提取出关卡设计,超级马里奥已有三十多年历史,因此网上关于游戏设计的资源很是多。从老游戏中提取数据也是个颇有意思的编程练习,你也能够试一试。
凑近了看,游戏关卡实际上是由一组物体网格构成的:
咱们能够用一组字符来表明这个网格,每一个字符就是一个物体:
--------------------------
--------------------------
--------------------------
#??#----------------------
--------------------------
--------------------------
--------------------------
-##------=--=----------==-
--------==--==--------===-
-------===--===------====-
------====--====----=====-
=========================-
复制代码
每一个物体是一个字符:
字符替换后的效果就是这样:
观察文本文件能够发现,马里奥的关卡若是逐行来看,并无什么模式:
可是若是逐列来看,模式就很明显了:
为了让算法可以识别模式,须要逐列输入数据。从输入数据中找出最有效的表征方式(即特征选择)是用好机器学习算法关键。
为了训练模型,咱们把文本文件反转90度,这让特征更加显而易见:
-----------=
-------#---=
-------#---=
-------?---=
-------#---=
-----------=
-----------=
----------@=
----------@=
-----------=
-----------=
-----------=
---------PP=
---------PP=
----------==
---------===
--------====
-------=====
------======
-----=======
---=========
---=========
复制代码
就像模仿海明威文风的例子同样,模型是越训练越好的。只通过不多量训练的结果,看起来真垃圾:
--------------------------
LL+<&=------P-------------
--------
---------------------T--#--
-----
-=--=-=------------=-&--T--------------
--------------------
--=------$-=#-=-_
--------------=----=<----
-------b
-
复制代码
大概摸索出了'-'和'='出现的比较多,但仅仅如此,没有真正发现什么模式。
通过几千次迭代,开始有点样子了:
--
-----------=
----------=
--------PP=
--------PP=
-----------=
-----------=
-----------=
-------?---=
-----------=
-----------=
复制代码
模型已经基本知道了每行的长度应该一致,而且也开始发现了游戏中的一些特色:管子老是两块宽、至少两块长,因此"P"以2X2的小组出现,这很不错!
在更多的训练以后,模型已经生成了不少有效的数据:
--------PP=
--------PP=
----------=
----------=
----------=
---PPP=---=
---PPP=---=
----------=
复制代码
来看看模型生成的完整关卡(转回横版):
看起来至关好!有几个亮点值得注意:
开始有一个Lakitu(空中浮游怪)在天上——就像真实的马里奥关卡同样。
空中的管子必须底部有砖块,而不能孤立地飘在半空。
怪物的分布比较合理。
不会出现组织玩家前进的死路。
感受上确实很像一个真实的关卡。
若是你有超级马里奥编辑器的话,你能够经过bookmarking it online或者查找代码4AC9-0000-0157-F3C3来玩这一关卡。
咱们用来训练模型的循环神经网络算法,跟现实世界里不少公司用来解决难题(如语音识别,机器翻译)的算法是同样的。但咱们的模型只创建在不多的数据量之上,因此只能算是一种“玩具”而不能动真格的。原版超级马里奥游戏里的关卡数不足以训练出一个真正好的模型。
若是咱们能像任天堂同样,拿到数以十万计的玩家自制关卡数据,咱们就能够作个更强的模型了。不过任天堂不会坐视其发生的,大公司都不会免费开放数据。
随着机器学习在不少行业里愈来愈重要,好程序和坏程序的差异愈来愈多地体如今,训练模型的数据量。这就是为何Google和Facebook等公司如此须要你的数据。
好比Google最近开源了用于搭建大规模机器学习应用的软件包TensorFlow,Google免费开放了如此重要而强力的技术,引发了巨大反响,而TensorFlow正是支撑Google Translate的后台。
但如若是没有Google在每种语言上留下的海量数据宝藏,你也不可能作出Google Translate的对手,数据才是Google真正的杀手锏。下次当你打开Google Maps Location History或Facebook Location History的时候,留意它们记录了你的一切所到之处。