教学是一种形式上的创作。创作有着艺术性和个人性。我们的经验不足支撑写出一篇“如何高效的教深度学习”,但我们尝试的一些方法、走过的弯路、积累下来的材料也许对诸位感兴趣的老师和同学有所帮助。所以特意在这里分享出来。
在过去三年中,我所在的亚马逊云服务(AWS)人工智能部门(AI)急速的扩张了好几十倍,侧面反映了行业的火爆。但我观察这个市场的扩张并没有想象中的那样发展迅猛。原因之一是AI的头号玩家深度学习的入门门槛依然很高。虽然它比机器学习更实用,但比起其他学科来说仍然很复杂。例如如果100个人学数据库(AWS的重要收入来源),可能50个人能用学到的知识来解决实际问题。但同样这些人来学深度学习,谨慎乐观估计10个学完后可以上手就很好了。如果AI一波热潮褪去,开发者学习热情降低,市场扩张随之变慢,那冬天就不远了。
我跟多位部门同事合作对亚马逊内部员工和AWS客户进行过培训(工作的副业之一),17年的时候跟Aston一起在国内做过十九期直播。去年年底的时候萌发录一个更加正式的质量更高的MOOC的想法。但担心线上课程不能实时得到反馈,所以难易度难以包括,所以想先面对面的教一遍积累些经验。
首选是去Stanford,因为离家近(踩单车15分钟)。但Stanford已经有几门深度学习课程同时在开。幸运的是Berkeley仍有空位,而且他们非常乐意我们去教。联系上Berkeley到AWS上层批准一周内就搞定,即使是我们明确说明了将会在半年之类每周两天不在办公室。这一点上我非常喜欢亚马逊,它推崇做一些有长远影响的项目,并鼓励快速尝试。
入职当天两个有意思的小插曲。一是被告知Berkeley是公立学校,职员算政府人员,需要宣誓战争发生时要为美国而战。我说这我没做好心理准备,要不不要发我工资,当我是个志愿者好了。这样我也安心去实验教学。
二是我去的伯克利统计系是世界上最好的统计系之一了吧(这里老师觉得就是世界第一,很像我读过的CMU计算机系和我老婆读过的MIT计算机和电子工程系,他们老师都觉得自己是世界第一😂)。楼上办公室坐着各大山头,Michael Jordan,Peter Bartlett,Bin Yu,一堆如雷贯耳名字。但统计系这栋楼是我去过的学校里面最破的,没有之一。以至于约助教见面时他们委婉的建议去隔壁楼的公共空间,那里更敞亮更现代。
(分配到的办公室。看这地板、这凳子、这黑板,这墙、这窗。拍于中午十二点。)
深度学习的兴起不过短短7、8年,今天的学术界仍然热火朝天,新模型新应用依旧层出不穷。如何在大量的、没有经过长时间检验的文献中选取教学内容颇费脑力。例如去年年末出现的BERT和GPT等模型使得我们意识到基于self-attention的transformer类模型可能未来跟卷积神经网络和循环神经网络一样重要,于是教到一半的时候特意挪出了一节半课来介绍。学生后来反馈这对他们的课程项目很有帮助。
深度学习知识点可以简单且粗暴的分成两类:实用的和好玩的。实用类包括各类卷积和循环神经网络,以及它们在计算机视觉和自然语言处理中常见问题的应用。这类模型可以用来解决人类几秒内能判断的事情,从而替代人来做重复性的工作,有着广泛的应用场景。好玩的包括用生成对抗网络来生成图片,和用增强学习来打各种游戏。这类模型具有一定的创造力,可以做高大上的演示,大家喜闻乐见,但技术落地目前有些不明朗。
我们希望学生在学完这门课后能够掌握和使用常见的模型。不管他们以后是去工业界找相关职位还是继续读研深造,都能打下坚实基础。所以教学大纲是偏向实用和基础类技术。
但我们不能开一门纯实用课程。仅仅教授神经网络的各种构造大法可能在聪明的Berkeley学生眼里跟回字有四样写法一样可笑。课里不仅要讲HOW,也要解释WHY。但深度学习里理论工作并不多,而且大有今天提出来一种解释过不了几天就被打脸的可能。所以课上只能把各方观点都摆一摆,加上点自己的看法,然后提醒大家要有辨别精神,因为今天说的猜测可能都是错的。此外,我们还补充了些相关的数学、统计学习和优化的经典知识和理论来增加深度。
在知识点外的另一个重要点是动手能力。一个我很喜欢的比喻是知识积累是内存,手速就是CPU。内存决定能跑多大的程序(工作的深度),CPU决定多块能跑完这个程序。对于初学者来说CPU比内存重要,因为内存可以从别人那里借。例如在课程项目中,Alex、助教和我充当了内存的职责。但CPU是借不到的,不能动手不仅做不出课程项目,完成作业都可能悬。。
在课程中我们基本对每个讲到的算法都过了一遍代码实现,有些基础的甚至是两种不同的实现,一种是从零开始方便理解的,一种是实际中使用的。我感觉整门课至少一半时间在讲代码。带来的问题是覆盖的知识点少了。但好处是每个讲过的点都把细节说透了。一般先是公式和图片讲模型设计思路和与其他类似模型的联系和区别。然后是代码讲细节的实现,说明每个模块的数据输入和输出,和现场演示实验效果。这也是我个人信奉的一种学习方式,先一头扎进去弄懂所有细节,然后再抬头思考它背后的思想。
每个课时的安排在下图。Alex觉得我们覆盖了深度学习20%的内容,我读论文少,所以比较乐观的觉得覆盖了60%的话题,和每个话题里面重要的50%知识点,所以也有个30%的内容。对于一门入门课来说,已经是相当丰富了。
早在两年前我们就着手写一本深度学习的教材。当时的情况是Ian Goodfellow的书是当时最好的入门书,新而且全面。但它只做了一般的模型描述而没有如何实际使用它们以及效果怎么样。而且几年没更新似乎有点赶不上时代了。同时网上有大量的关于模型实现类的文章,但过于零散而且每个人写作风格迥异。我们想要一本既能讲原理、又有实现和实际使用、不断更新、而且容易读的书。
在过去两年的摸索中,这本教材在传统意义的书上往前走了几步:
书的每一章用文字、数学、图示和代码来多方面介绍一个知识点。它是一个Jupyter记事本,可以独立运行。包含20个左右的文字和代码块,可以15分钟左右读完。
源文件是Markdown,不保存执行输出,并开源在Github上。这样方便更多人贡献和改动审阅,同时可以很容易的不断加新章节。
任何改动都会触发持续集成服务重新执行记事本来获得执行输出,这样保证代码的正确性。一个记事本的执行时间控制在不超过十分钟。这对展示复杂模型的训练颇为挑战。
执行无误后直接用三种格式发布在网上:含有执行输出的Jupyter记事本,可以直接浏览的HTML,和适合打印的PDF。
可以像LaTeX那样方便的索引图、表、公式和文献。
每一章都有可以讨论的链接。
目前书的英文版发布在 http://d2l.ai/,中文版在 http://zh.d2l.ai/。
这本书代码的实现很多是基于MXNet(一开始的目标是为MXNet写个好点文档),我们也考虑过要不要提供一个Pytorch或者Keras的版本。后来发现这个担心比较多余。框架就是一个工具,工具之间的那些不同带来的困难比起理解模型和调出结果来小很多。课上发现就算是没有接触过这些工具的学生,用MXNet做作业,然后在基于不管用啥框架实现的现有算法再开发做项目并没有多大困难。或者说困难都不来自工具本身,特别是算法实现都在课上讲过一遍的情况下。
教材是给学生课前课后阅读使用。上课中需要将教材变成幻灯片。虽然想过是不是可以让教材直接自动生成幻灯片,但没有找到特别好的办法。原因是书和幻灯片的表现形式很不一样。书中文字是书面的、详细的、和严谨的。幻灯片则是口语的、简单的、和生动的。
举个例子,下图是书中介绍物体检测和边界框的一节。
在幻灯片版本中,我首先用两页介绍物体识别,第一页是突出跟前面一直讲的图片分类的区别,然后是一个实际中的应用(顺便介绍下自动驾驶这个应用)。接着是过渡页表示一个单元的开始,和简略的介绍边界框。跟书相比,幻灯片在表现上更加简单,而且更强调生动性。
按照这个思路,书中每一节的文字被重新做成一个幻灯片单元。一般5页左右,讲课中每页平均花时2分钟。然后删掉文字保存代码,再使用Jupyter来做幻灯片演示(参考这个例子)。通常一个代码单元是10页,一页平均需要讲一分钟。
这样书的每一节被做成了两个幻灯片单元,一共讲20分钟。Berkeley一节课80分钟,一节课可以讲4节。一共上了26节课,讲了大约100节,基本覆盖了整本书的内容。
机器学习类课程都喜欢录像(可能是Andrew Ng开了一个好头)。录像有两个场景,一个是主体是幻灯片,讲师在角落。另一个主体是黑板。
过去几年里我们尝试了各种DIY手段来通过便宜的器材来录制准专业的视频。下图是这次使用的器材。
录像用的是一个4K微单④,放在讲台前4米的三脚架上①,用HDMI线③和转录头②跟笔记本相连。4K主要是为场景二准备,但因为我们定到的教室的黑板不是很好,所以这个场景用得不多,而且经常课堂中忘了切换。后来发现其实用手机就足够了,例如iPhone加上EpocCam这个应用,然后用个小三脚架放在笔记本的后面。这样极大减轻每次要携带的设备,而且降低了器材成本。但注意不要用笔记本自带的前置摄像头,那个效果不行。
声音质量很关键。千万不要用笔记本自带的麦克风,人稍微离远点就听不清。我们将一个无线麦克风挂在身上⑦,它跟hub⑧相连,然后再接到笔记本上。后来发现如果走动不频繁的话,用固定麦克风效果也很好⑤,而且容易连接(我们买的这个主要是为MOOC用,比较重,如果要携带的话可以买小点的)。
录制软件用的是OBS,游戏主播常用。强大,但不是很稳定,而且耗资源,特别是在连了很多设备的情况下。于是专门用了个新的高配MacBook Pro⑨,保证除了上课外不会动它,而且有足够的计算资源现场运行程序。OBS出错概率不小,建议每次开始时和中间都要查一下录制是不是正常。否则重新录视频很痛苦,因为没有学生在现场,气氛很不一样。
物理键盘⑥很方便,一个键配置成开始和停止录制,另外两个是切换场景。它的主要好处是LED背景显示当前状态,可以时不时看下录制是不是正常。因为每个单元录一个视频,一节课通常录7,8个,前几节课常忘了点开始。这个键盘可以时不时看下录制是不是正常。不过我觉得一个更好的办法是用一个iPad做一个扩展显示器,将OBS放在上面,这样可以真正看到录制状态。
通常我们会把课程视频在一两天内上传到YouTube。但这样直接导致来上课的学生锐减。坚持来上课的学生可能学习动机更大,每次互动的时候都感觉大家掌握不错,进而导致一路向前讲,基本把整本书讲完了。这比原计划多讲了20%。我觉得可能视频在一周后上传比较好,这样学生需要来上课才能完成一周后要交的作业,从而容易在课堂上把握节奏。
深度学习里大部分模型训练都需要GPU来加速,但学生通常都没有自己的GPU(当然他们是不这么觉得,很多学生课后指着自己系统中显示的Intel集成显卡的来跟我说你看我是有GPU的)。一个方便的办法是使用Google的Colab(当时提供K80,现在是T4了),但只能同时训练一个任务,做作业还行,但课程项目不够。我们提供的另一个途径是使用AWS上用GPU实例,而且我们提供经费。
教学生在云上用GPU实例比想象中要困难些。虽然课上手把手教过,但好长一段时间的答疑时间里都是问如何使用云。而且很多学生经常开了实例忘关,或者用了特别贵的GPU实例,导致月底会有很高的账单(前些天一位同事苦着脸跟我抱怨说,资助的一个项目的一个学生为了赶一篇论文在AWS上烧了30万美元,老师自然掏腰包不起,只好我们补。差点掏空了我们全年的资助资金)。
这门课里我们大概发放了3万美金的AWS兑换码。主要麻烦的地方是都是学生问我要,然后我手动回,发了好几百封邮件。还要答疑诸如为什么兑换不了。这一块还在思考如何改进。
我们一共布置了10次作业,一周一个。绝大部分是代码实现题。一个作业预计耗时是半天。对于工作量较大的,我们让每个课程项目团队一起合作完成。这样他们可以提前熟悉各个队员。对于个人作业我们鼓励讨论,但需要每个人独立将答案写下来。
颇受欢迎的几个作业是参加Kaggle竞赛。我们提供一个基础模型和几个改进思路,然后学生去调参数,并上传预测结果报告得分。之后我们会排名出前三个队,每个队奖励$500的AWS兑换码。
这十个作业里面有两个设计得不是特别好。都是模型训练题,但我们没有事先实现并跑一遍,没想到一个过于容易,一个太难。下次还是不能偷这个懒。
考试只有期中考试,这是为了期末大家有更多时间做项目。考试开卷,但不能带电脑。其中一道题是一段LeNet的训练代码,特意改错了6个地方,让大家来指出问题。整体大家做得还不错,这样说明前半课程知识点掌握还不错。如果允许的话,我还是建议要有期末考试,这样促使学生去复习课程的后半段内容。
课程项目占比课程分数的一半,是我们很看中的部分。因为应用学到的知识去创造性的解决一个有意思的问题是我们能提供的最好学习体验。但对于老师和学生都相当不容易。
在我们过去的经验中选择单干的学生经常最后做得不是很好,这次我们强制要求一个项目至少有四个成员。第一堂课中Alex让每个人跟坐在边上的人花三分钟认识下,然后跟坐在后面的人花三分钟认识下,这样方便学生在课上没有熟人的情况下组队。如果最后实在落单了,我们就随机在人数少的队里加人。最后一共行程了二十个项目。
考虑到本科生可能缺乏项目经验,所以我们设置了多个中间环节。包括三周内定好题目获得10%分数,课程1/3的时候需要做中期演讲和写中期报告(20%分数),必须跟助教见一次面讨论项目(10%分数)。
我们观察到学生遇到的主要困难是低估项目的难度。首先深度学习极大的拓展了机器学习的应用场景,图片、视频、音频、游戏、金融、医疗、社交网络,基本都可以用神经网络来处理。但很多有意思的数据可能会带来大量计算量(例如视频)和工作量(例如对医疗数据的预处理),远不是新手能驾驭。
其次,大家喜欢好玩的模型,诸如生成对抗模型和增强学习。但这两类模型都比较难训练,例如生成对抗模型中需要在生成器和辨别器之间取得纳什平衡,训练经常不稳定。但教学大纲专注实用类模型,导致没讲这两大类模型。于是学生发现他们选的模型比作业和课上看到的要难很多。
最后是学生都很自信,演讲水平很高。中期演讲质量很高。不仅好几个项目的创意我特别喜欢,而且讲得也特别好。例如每个项目是给三分钟报告时间,很多组都是三个人轮流讲,每人一分钟,时间把握特别好。对比5年前我在CMU做机器学习课助教,我觉得这一届特别优秀。这本是优点,但让我和Alex都过于乐观。
转折点出现在期中考试后。我们开始督促学生将重心放到课程项目上,答疑时间(每周两小时)里也主要是询问他们进度怎么样。一开始会跟他们说一些想法,例如这里有篇刚出来的论文,你们可以读读。基本是抱着做出来可以发个论文或者创个业的心态。画完饼后双方都很愉快。但任何事情不能拔苗助长。很快发现大多项目进度缓慢,经常一两周后查看进展时发现都困在找数据或者读论文。
眼看课程不到一个月就要结束了,不论是我们还是学生都开始有些着急了。于是将每周的答疑时间增加到了6个小时(每节课前的3小时),而且承担了(无良)项目经理职责。进度不理想的团队在每次聊完后都会很慎重其事的说,回去备好咖啡红牛熬夜吧,过两天我们再来看进展。
最后一周最让人抓狂。一个小组在一个小时后就要做报告的时候过来问从网上下的一个模型在他们抓的数据做预测能不能过关。我说,不行,你得“训练”下这个模型。还有学生什么活都没干然后称自己这样那样了,找来学校的特殊学生关心部门说能不能这样那样。
很欣慰的是好几个我们特别担心的项目最终找到了自己的出路。还有一两个项目一开始很关注但中间有点失望,因为感觉他们一直在走弯路而且也不是很理会我们的建议,但最后拿出了惊喜的结果。最终结果比预想的要好。
同时,这里面还是有很多可以改进的地方:
需要根据学生课程项目的选题来调整教学大纲。例如,虽然我们针对性的将BERT从最后往挪了两周(有好几个组获益),但应该在内容上加入生成对抗模型。
需要及早帮学生正确估计项目的复杂度,和正确的估计自己的能力。
跟助教更好的沟通,使得他们将时间多分配来帮助解决一些项目中的一些实际问题,曾在CMU看到过一门本科生的编程课里,每周学生坐在一起编程(也许是写作业),然后5,6个助教现场答疑,感觉效果会很好。
一开始要强调最后最终项目报告需要列出每个成员的项目贡献,然后我们再按比例给分。这样也许能减少一些学生抱着浑水摸鱼的侥幸心理。
一开始我以为在教材已经写好了的情况下,开门课应该很轻松。但即使是在只要上一半课的的情况下,我每周仍然要花费一半的工作时间在上面。时间的大头包括:
一节课的幻灯片需要花费十多个小时,通常是整个周末和两个工作日晚上(因为带娃要花更多时间)。不过我观察到Alex只用花2、3个小时。
因为我英语口语很一般,而且不善于演讲,一节课前我需要花2、3小时演练。即使是中文讲课,提前花30分钟想一想怎么讲也是很有必要。同时我也观察到Alex只需要上课前花十分钟过一遍幻灯片就行。
答疑时间和跟助教沟通,前面每周3小时,之后增加到每周7小时。
回邮件,上传视频,更新网页之类每周一小时。
这门课给我带来了很大的负担。这里也特别感谢我的家庭、公司的老板们和小伙伴们支持这一个“不务正业”的实验项目。
上好一门课很难,需要付出大量时间和精力。一门经典的课程通常是好几个老师经过数年的积累的结果。这对深度学习这一新的学科尤为挑战。希望我们的经验和走过的弯路的能启发之后的广大师生。
此外,所有上课相关的材料都使用CC BY-NC-SA 4.0协议(非商业目的下自由使用)公布在网上:
课程主页:http://courses.d2l.ai/berkeley-stat-157/
所有课件和习题:https://github.com/d2l-ai/berkeley-stat-157
教材的英文版:http://d2l.ai/ 和中文版:http://zh.d2l.ai/
最后,可能也是最重要的:
如果你打算使用这些材料来教类似的课程,可以向免费获取AWS计算资源。这里特别感谢AWS中国团队费老师、Shawn、Leo,Vivian和锴哥的支持。具体信息请参考 http://zh.d2l.ai/aws4learn.html
教材中文纸质版6月即将销售。有全彩豪华版和黑白经济版两个版本。因为我们不拿稿费,所以跟出版社协商到了很低的售价。感谢Aston和我们的编辑海玲付出的巨大努力。预售链接在:
京东自营:https://item.jd.com/12527061.html
当当自营:http://product.dangdang.com/27871474.html
天猫:https://detail.tmall.com/item.htm?spm=a230r.1.14.252.1a504944ZpMkT3&id=594658766444&ns=1&abbucket=7