diff --git a/404.html b/404.html index 6c982fa6..908dc47f 100644 --- a/404.html +++ b/404.html @@ -1 +1 @@ -
计算机领域方向庞杂,知识浩如烟海,每个细分领域如果深究下去都可以说学无止境。因此,一个清晰明确的学习规划是非常重要的。我在多年自学的尝试中也走过不少弯路,最终提炼出了下面的内容,供大家参考。
不过,在开始学习之前,先向小白们强烈推荐一个科普向系列视频 Crash Course: Computer Science,在短短 8 个小时里非常生动且全面地科普了关于计算机科学的方方面面:计算机的历史、计算机是如何运作的、组成计算机的各个重要模块、计算机科学中的重要思想等等等等。正如它的口号所说的 Computers are not magic!,希望看完这个视频之后,大家能对计算机科学有个全貌性地感知,从而怀着兴趣去面对下面浩如烟海的更为细致且深入的学习内容。
俗话说:磨刀不误砍柴工。如果你是一个刚刚接触计算机的24k纯小白,学会一些工具将会让你事半功倍。
学会提问:也许你会惊讶,提问也算计算机必备技能吗,还放在第一条?我觉得在开源社区中,学会提问是一项非常重要的能力,它包含两方面的事情。其一是会变相地培养你自主解决问题的能力,因为从形成问题、描述问题并发布、他人回答、最后再到理解回答这个周期是非常长的,如果遇到什么鸡毛蒜皮的事情都希望别人最好远程桌面手把手帮你完成,那计算机的世界基本与你无缘了。其二,如果真的经过尝试还无法解决,可以借助开源社区的帮助,但这时候如何通过简洁的文字让别人瞬间理解你的处境以及目的,就显得尤为重要。推荐阅读提问的智慧这篇文章,这不仅能提高你解决问题的概率和效率,也能让开源社区里无偿提供解答的人们拥有一个好心情。
MIT-Missing-Semester 这门课覆盖了这些工具中绝大部分,而且有相当详细的使用指导,强烈建议小白学习。不过需要注意的一点是,在课程中会不时提到一些与开发流程相关的术语。因此推荐至少在学完计算机导论级别的课程之后进行学习。
翻墙:由于一些众所周知的原因,谷歌、GitHub 等网站在大陆无法访问。然而很多时候,谷歌和 StackOverflow 可以解决你在开发过程中遇到的 99% 的问题。因此,学会翻墙几乎是一个内地 CSer 的必备技能。(考虑到法律问题,这个文档提供的翻墙方式仅对拥有北大邮箱的用户适用)。
命令行:熟练使用命令行是一种常常被忽视,或被认为难以掌握的技能,但实际上,它会极大地提高你作为工程师的灵活性以及生产力。命令行的艺术是一份非常经典的教程,它源于 Quora 的一个提问,但在各路大神的贡献努力下已经成为了一个 GitHub 十万 stars 的顶流项目,被翻译成了十几种语言。教程不长,非常建议大家反复通读,在实践中内化吸收。同时,掌握 Shell 脚本编程也是一项不容忽视的技术,可以参考这个教程。
IDE (Integrated Development Environment):集成开发环境,说白了就是你写代码的地方。作为一个码农,IDE 的重要性不言而喻,但由于很多 IDE 是为大型工程项目设计的,体量较大,功能也过于丰富。其实如今一些轻便的文本编辑器配合丰富的插件生态基本可以满足日常的轻量编程需求。个人常用的编辑器是 VS Code 和 Sublime(前者的插件配置非常简单,后者略显复杂但颜值很高)。当然对于大型项目我还是会采用略重型的 IDE,例如 Pycharm (Python),IDEA (Java) 等等(免责申明:所有的 IDE 都是世界上最好的 IDE)。
Vim:一款命令行编辑工具。这是一个学习曲线有些陡峭的编辑器,不过学会它我觉得是非常有必要的,因为它将极大地提高你的开发效率。现在绝大多数 IDE 也都支持 Vim 插件,让你在享受现代开发环境的同时保留极客的炫酷(yue)。
Emacs:与 Vim 齐名的经典编辑器,同样具有极高的开发效率,同时具有更为强大的扩展性,它既可以配置为一个轻量编辑器,也可以扩展成一个个人定制的 IDE,甚至可以有更多奇技淫巧。
Git:一款代码版本控制工具。Git的学习曲线可能更为陡峭,但出自 Linux 之父 Linus 之手的 Git 绝对是每个学 CS 的童鞋必须掌握的神器之一。
GitHub:基于 Git 的代码托管平台。全世界最大的代码开源社区,大佬集聚地。
GNU Make:一款工程构建工具。善用 GNU Make 会让你养成代码模块化的习惯,同时也能让你熟悉一些大型工程的编译链接流程。
CMake:一款功能比 GNU Make 更为强大的构建工具,建议掌握 GNU Make 之后再加以学习。
LaTex:逼格提升 论文排版工具。
Docker:一款相较于虚拟机更轻量级的软件打包与环境部署工具。
实用工具箱:除了上面提到的这些在开发中使用频率极高的工具之外,我还收集了很多实用有趣的免费工具,例如一些下载工具、设计工具、学习网站等等。
Thesis:毕业论文 Word 写作教程。
私以为一本好的教材应当是以人为本的,而不是炫技式的理论堆砌。告诉读者“是什么”固然重要,但更好的应当是教材作者将其在这个领域深耕几十年的经验融汇进书中,向读者娓娓道来“为什么”以及未来应该“怎么做”。
你以为的开发 —— 在 IDE 里疯狂码代码数小时。
实际上的开发 —— 配环境配几天还没开始写代码。
如果你是 Mac 用户,那么你很幸运,这份指南 将会手把手地带你搭建起整套开发环境。如果你是 Windows 用户,在开源社区的努力下,你同样可以获得与其他平台类似的体验:Scoop。
另外大家可以参考一份灵感来自 6.NULL MIT-Missing-Semester 的 环境配置指南,重点在于终端的美化配置。此外还包括常用软件源(如 GitHub, Anaconda, PyPI 等)的加速与替换以及一些 IDE 的配置与激活教程。
服务器端的运维需要掌握 Linux(或者其他类 Unix 系统)的基本使用以及进程、设备、网络等系统相关的基本概念,小白可以参考中国科学技术大学 Linux 用户协会编写的《Linux 101》在线讲义。如果想深入学习系统运维相关的知识,可以参考 Aspects of System Administration 这门课程。
另外,如果需要学习某个具体的概念或工具,推荐一个非常不错的 GitHub 项目 DevOps-Guide,其中涵盖了非常多的运维方面的基础知识和教程,例如 Docker, Kubernetes, Linux, CI-CD, GitHub Actions 等等。
正如这章开头提到的,这份课程地图仅仅是一个仅供参考的课程规划,我作为一个临近毕业的本科生。深感自己没有权利也没有能力向别人宣扬“应该怎么学”。因此如果你觉得以下的课程分类与选择有不合理之处,我全盘接受,并深感抱歉。你可以在下一节定制属于你的课程地图
以下课程类别中除了含有 基础 和 入门 字眼的以外,并无明确的先后次序,大家只要满足某个课程的先修要求,完全可以根据自己的需要和喜好选择想要学习的课程。
作为大一新生,学好微积分线代是和写代码至少同等重要的事情,相信已经有无数的前人经验提到过这一点,但我还是要不厌其烦地再强调一遍:学好微积分线代真的很重要!你也许会吐槽这些东西岂不是考完就忘,那我觉得你是并没有把握住它们本质,对它们的理解还没有达到刻骨铭心的程度。如果觉得老师课上讲的内容晦涩难懂,不妨参考 MIT 的 Calculus Course 和 18.06: Linear Algebra 的课程 notes,至少于我而言,它帮助我深刻理解了微积分和线性代数的许多本质。顺道再安利一个油管数学网红 3Blue1Brown,他的频道有很多用生动形象的动画阐释数学本质内核的视频,兼具深度和广度,质量非常高。
作为计算机系的学生,及早了解一些信息论的基础知识,我觉得是大有裨益的。但大多信息论课程都面向高年级本科生甚至研究生,对新手极不友好。而 MIT 的 6.050J: Information theory and Entropy 这门课正是为大一新生量身定制的,几乎没有先修要求,涵盖了编码、压缩、通信、信息熵等等内容,非常有趣。
集合论、图论、概率论等等是算法推导与证明的重要工具,也是后续高阶数学课程的基础。但我觉得这类课程的讲授很容易落入理论化与形式化的窠臼,让课堂成为定理结论的堆砌,而无法使学生深刻把握理论的本质,进而造成学了就背,考了就忘的怪圈。如果能在理论教学中穿插算法运用实例,学生在拓展算法知识的同时也能窥见理论的力量和魅力。
UCB CS70 : discrete Math and probability theory 和 UCB CS126 : Probability theory 是 UC Berkeley 的概率论课程,前者覆盖了离散数学和概率论基础,后者则涉及随机过程以及深入的理论内容。两者都非常注重理论和实践的结合,有丰富的算法实际运用实例,后者还有大量的 Python 编程作业来让学生运用概率论的知识解决实际问题。
作为计算机系的学生,培养计算思维是很重要的,实际问题的建模、离散化,计算机的模拟、分析,是一项很重要的能力。而这两年开始风靡的,由 MIT 打造的 Julia 编程语言以其 C 一样的速度和 Python 一样友好的语法在数值计算领域有一统天下之势,MIT 的许多数学课程也开始用 Julia 作为教学工具,把艰深的数学理论用直观清晰的代码展示出来。
ComputationalThinking 是 MIT 开设的一门计算思维入门课,所有课程内容全部开源,可以在课程网站直接访问。这门课利用 Julia 编程语言,在图像处理、社会科学与数据科学、气候学建模三个 topic 下带领学生理解算法、数学建模、数据分析、交互设计、图例展示,让学生体验计算与科学的美妙结合。内容虽然不难,但给我最深刻的感受就是,科学的魅力并不是故弄玄虚的艰深理论,不是诘屈聱牙的术语行话,而是用直观生动的案例,用简练深刻的语言,让每个普通人都能理解。
上完上面的体验课之后,如果意犹未尽的话,不妨试试 MIT 的 18.330 : Introduction to numerical analysis,这门课的编程作业同样会用 Julia 编程语言,不过难度和深度上都上了一个台阶。内容涉及了浮点编码、Root finding、线性系统、微分方程等等方面,整门课的主旨就是让你利用离散化的计算机表示去估计和逼近一个数学上连续的概念。这门课的教授还专门撰写了一本配套的开源教材 Fundamentals of Numerical Computation,里面附有丰富的 Julia 代码实例和严谨的公式推导。
如果你还意犹未尽的话,还有 MIT 的数值分析研究生课程 18.335: Introduction to numerical method 供你参考。
如果世间万物的运动发展都能用方程来刻画和描述,这是一件多么酷的事情呀!虽然几乎任何一所学校的 CS 培养方案中都没有微分方程相关的必修课程,但我还是觉得掌握它会赋予你一个新的视角来审视这个世界。
由于微分方程中往往会用到很多复变函数的知识,所以大家可以参考 MIT18.04: Complex variables functions 的课程 notes 来补齐先修知识。
MIT18.03: differential equations 主要覆盖了常微分方程的求解,在此基础之上 MIT18.152: Partial differential equations 则会深入偏微分方程的建模与求解。掌握了微分方程这一有力工具,相信对于你的实际问题的建模能力以及从众多噪声变量中把握本质的直觉都会有很大帮助。
作为计算机系的学生,我经常听到数学无用论的论断,对此我不敢苟同但也无权反对,但若凡事都硬要争出个有用和无用的区别来,倒也着实无趣,因此下面这些面向高年级甚至研究生的数学课程,大家按兴趣自取所需。
Standford EE364A: Convex Optimization
MIT18.650: Statistics for Applications
Languages are tools, you choose the right tool to do the right thing. Since there's no universally perfect tool, there's no universally perfect language.
作为计算机系的学生,了解一些基础的电路知识,感受从传感器收集数据到数据分析再到算法预测整条流水线,对于后续知识的学习以及计算思维的培养还是很有帮助的。EE16A&B: Designing Information Devices and Systems I&II 是伯克利 EE 学生的大一入门课,其中 EE16A 注重通过电路从实际环境中收集和分析数据,而 EE16B 则侧重从这些收集到的数据进行分析并做出预测行为。
信号与系统是一门我觉得非常值得一上的课,最初学它只是为了满足我对傅里叶变换的好奇,但学完之后我才不禁感叹,傅立叶变换给我提供了一个全新的视角去看待这个世界,就如同微分方程一样,让你沉浸在用数学去精确描绘和刻画这个世界的优雅与神奇之中。
MIT 6.003: signal and systems 提供了全部的课程录影、书面作业以及答案。也可以去看这门课的远古版本
而 UCB EE120: Signal and Systems 关于傅立叶变换的 notes 写得非常好,并且提供了6 个非常有趣的 Python 编程作业,让你实践中运用信号与系统的理论与算法。
算法是计算机科学的核心,也是几乎一切专业课程的基础。如何将实际问题通过数学抽象转化为算法问题,并选用合适的数据结构在时间和内存大小的限制下将其解决是算法课的永恒主题。如果你受够了老师的照本宣科,那么我强烈推荐伯克利的 UCB CS61B: Data Structures and Algorithms 和普林斯顿的 Coursera: Algorithms I & II,这两门课的都讲得深入浅出并且会有丰富且有趣的编程实验将理论与知识结合起来。
以上两门课程都是基于 Java 语言,如果你想学习 C/C++ 描述的版本,可以参考斯坦福的数据结构与基础算法课程 Stanford CS106B/X: Programming Abstractions。偏好 Python 的同学可以学习 MIT 的算法入门课 MIT 6.006: Introduction to Algorithms
对一些更高级的算法以及 NP 问题感兴趣的同学可以学习伯克利的算法设计与分析课程 UCB CS170: Efficient Algorithms and Intractable Problems 或者 MIT 的高阶算法 MIT 6.046: Design and Analysis of Algorithms。
一份“能跑”的代码,和一份高质量的工业级代码是有本质区别的。因此我非常推荐低年级的同学学习一下 MIT 6.031: Software Construction 这门课,它会以 Java 语言为基础,以丰富细致的阅读材料和精心设计的编程练习传授如何编写不易出 bug、简明易懂、易于维护修改的高质量代码。大到宏观数据结构设计,小到如何写注释,遵循这些前人总结的细节和经验,对于你此后的编程生涯大有裨益。
当然,如果你想系统性地上一门软件工程的课程,那我推荐的是伯克利的 UCB CS169: software engineering。但需要提醒的是,和大多学校(包括贵校)的软件工程课程不同,这门课不会涉及传统的 design and document 模式,即强调各种类图、流程图及文档设计,而是采用近些年流行起来的小团队快速迭代 Agile Develepment 开发模式以及利用云平台的 Software as a service 服务模式。
从小我就一直听说,计算机的世界是由 01 构成的,我不理解但大受震撼。如果你的内心也怀有这份好奇,不妨花一到两个月的时间学习 Coursera: Nand2Tetris 这门无门槛的计算机课程。这门麻雀虽小五脏俱全的课程会从 01 开始让你亲手造出一台计算机,并在上面运行俄罗斯方块小游戏。一门课里涵盖了编译、虚拟机、汇编、体系结构、数字电路、逻辑门等等从上至下、从软至硬的各类知识,非常全面。难度上也是通过精心的设计,略去了众多现代计算机复杂的细节,提取出了最核心本质的东西,力图让每个人都能理解。在低年级,如果就能从宏观上建立对整个计算机体系的鸟瞰图,是大有裨益的。
当然,如果想深入现代计算机体系结构的复杂细节,还得上一门大学本科难度的课程 UCB CS61C: Great Ideas in Computer Architecture。UC Berkeley 作为 RISC-V 架构的发源地,在体系结构领域算得上首屈一指。其课程非常注重实践,你会在 Project 中手写汇编构造神经网络,从零开始搭建一个 CPU,这些实践都会让你对计算机体系结构有更为深入的理解,而不是仅停留于“取指译码执行访存写回”的单调背诵里。
计算机系统是一个庞杂而深刻的主题,在深入学习某个细分领域之前,对各个领域有一个宏观概念性的理解,对一些通用性的设计原则有所知晓,会让你在之后的深入学习中不断强化一些最为核心乃至哲学的概念,而不会桎梏于复杂的内部细节和各种 trick。因为在我看来,学习系统最关键的还是想让你领悟到这些最核心的东西,从而能够设计和实现出属于自己的系统。
MIT6.033: System Engineering 是 MIT 的系统入门课,主题涉及了操作系统、网络、分布式和系统安全,除了知识点的传授外,这门课还会讲授一些写作和表达上的技巧,让你学会如何设计并向别人介绍和分析自己的系统。这本书配套的教材 Principles of Computer System Design: An Introduction 也写得非常好,推荐大家阅读。
CMU 15-213: Introduction to Computer System 是 CMU 的系统入门课,内容覆盖了体系结构、操作系统、链接、并行、网络等等,兼具广度和深度,配套的教材 Computer Systems: A Programmer's Perspective 也是质量极高,强烈建议阅读。
没有什么能比自己写个内核更能加深对操作系统的理解了。
操作系统作为各类纷繁复杂的底层硬件虚拟化出一套规范优雅的抽象,给所有应用软件提供丰富的功能支持。了解操作系统的设计原则和内部原理对于一个不满足于当调包侠的程序员来说是大有裨益的。出于对操作系统的热爱,我上过国内外很多操作系统课程,它们各有侧重和优劣,大家可以根据兴趣各取所需。
MIT 6.S081: Operating System Engineering,MIT 著名 PDOS 实验室出品,11 个 Project 让你在一个实现非常优雅的类Unix操作系统xv6上增加各类功能模块。这门课也让我深刻认识到,做系统不是靠 PPT 念出来的,是得几万行代码一点点累起来的。
UCB CS162: Operating System,伯克利的操作系统课,采用和 Stanford 同样的 Project —— 一个教学用操作系统 Pintos。我作为北京大学2022年和2023年春季学期操作系统实验班的助教,引入并改善了这个 Project,课程资源也会全部开源,具体参见课程网站。
NJU: Operating System Design and Implementation,南京大学的蒋炎岩老师开设的操作系统课程。蒋老师以其独到的系统视角结合丰富的代码示例将众多操作系统的概念讲得深入浅出,此外这门课的全部课程内容都是中文的,非常方便大家学习。
HIT OS: Operating System,哈尔滨工业大学的李治军老师开设的中文操作系统课程。李老师的课程基于 Linux 0.11 源码,十分注重代码实践,并站在学生视角将操作系统的来龙去脉娓娓道来。
想必这两年各类 CS 讲座里最常听到的话就是“摩尔定律正在走向终结”,此话不假,当单核能力达到上限时,多核乃至众核架构如日中天。硬件的变化带来的是上层编程逻辑的适应与改变,要想充分利用硬件性能,编写并行程序几乎成了程序员的必备技能。与此同时,深度学习的兴起对计算机算力与存储的要求都达到了前所未有的高度,大规模集群的部署和优化也成为热门技术话题。
CMU 15-418/Stanford CS149: Parallel Computing
不知道你当年选择计算机是不是因为怀着一个中二的黑客梦想,但现实却是成为黑客道阻且长。
UCB CS161: Computer Security 是伯克利的系统安全课程,会涵盖栈攻击、密码学、网站安全、网络安全等等内容。
ASU CSE365: Introduction to Cybersecurity 亚利桑那州立大学的 Web 安全课程,主要涉及注入、汇编与密码学的内容。
ASU CSE466: Computer Systems Security 亚利桑那州立大学的系统安全课程,涉及内容全面。门槛较高,需要对 Linux, C 与 Python 充分熟悉。
掌握这些理论知识之后,还需要在实践中培养和锻炼这些“黑客素养”。CTF 夺旗赛是一项比较热门的系统安全比赛,赛题中会融会贯通地考察你对计算机各个领域知识的理解和运用。北大今年也成功举办了第 0 届和第 1 届,鼓励大家后期踊跃参与,在实践中提高自己。下面列举一些我平时学习(摸鱼)用到的资源:
没有什么能比自己写个 TCP/IP 协议栈更能加深对计算机网络的理解了。
大名鼎鼎的 Stanford CS144: Computer Network,8 个 Project 带你实现整个 TCP/IP 协议栈。
如果你只是想在理论上对计算机网络有所了解,那么推荐计网著名教材《自顶向下方法》的配套学习资源 Computer Networking: A Top-Down Approach。
没有什么能比自己写个关系型数据库更能加深对数据库系统的理解了。
CMU 的著名数据库神课 CMU 15-445: Introduction to Database System 会通过 4 个 Project 带你为一个用于教学的关系型数据库 bustub 添加各种功能。实验的评测框架也免费开源了,非常适合大家自学。此外课程实验会用到 C++11 的众多新特性,也是一个锻炼 C++ 代码能力的好机会。
Berkeley 作为著名开源数据库 postgres 的发源地也不遑多让,UCB CS186: Introduction to Database System 会让你用 Java 语言实现一个支持 SQL 并发查询、B+ 树索引和故障恢复的关系型数据库。
没有什么能比自己写个编译器更能加深对编译器的理解了。
Stanford CS143: Compilers 带你手写编译器。
前后端开发很少在计算机的培养方案里被重视,但其实掌握这项技能还是好处多多的,例如搭建自己的个人主页,抑或是给自己的课程项目做一个精彩的展示网页。
Stanford CS142: Web Applications
其实数据科学和机器学习与深度学习有着很紧密的联系,但可能更侧重于实践。Berkeley 的 UCB Data100: Principles and Techniques of Data Science 通过丰富的编程练习让你在实践中掌握各类数据分析工具和算法,并带领你体验从海量的数据集中提取出想要的结果,并对未来的数据或用户的行为做出相应的预测。但这只是一门基础课,如果想学习工业级别的数据挖掘与分析技术,可以尝试 Stanford 的大数据挖掘课程 CS246: Mining Massive Data Sets。
近十年人工智能应该算是计算机界最火爆的领域。如果你不满足于整日听各路媒体争相报道人工智能相关的进展,而想真正一探究竟,那么非常推荐学习 Harvard 神课 CS50 系列的人工智能课程 Harvard CS50: Introduction to AI with Python。课程短小精悍,覆盖了传统人工智能领域的几大分支,并配有丰富有趣的 Python 编程练习来巩固你对人工智能算法的理解。美中不足的是这门课因为面向在线自学者的缘故内容较为精简,并且不会涉及特别深入的数学理论,如果想要系统深入地学习还需要一门本科生难度的课程,例如 Berkeley 的 UCB CS188: Introduction to Artificial Intelligence。这门课的 Project 复刻了经典游戏糖豆人,让你运用人工智能算法玩游戏,非常有趣。
机器学习领域近些年最重要的进展就是发展出了基于神经网络的深度学习分支,但其实很多基于统计学习的算法依然在数据分析领域有着广泛的应用。如果你之前从未接触过机器学习的相关知识,而且不想一开始就陷入艰深晦涩的数学证明,那么不妨先从 Andrew Ng (吴恩达)的 Coursera: Machine Learning 学起。这门课在机器学习领域基本无人不晓,吴恩达以其深厚的理论功底和出色的表达能力把很多艰深的算法讲得深入浅出,并且非常实用。其配套的作业也是质量相当上乘,可以帮助你快速入门。
但上过这门课只能让你从宏观上对机器学习这一领域有一定了解,如果想真正理解那些“神奇”算法背后的数学原理甚至从事相关领域的科研工作,那么还需要一门更“数学”的课程,例如 Stanford CS229: Machine Learning 或者 UCB CS189: Introduction to Machine Learning。
前几年 AlphaGo 的大热让深度学习进入了大众的视野,不少大学甚至专门成立了相关专业。很多计算机的其他领域也会借助深度学习的技术来做研究,因此基本不管你干啥多少都会接触到一些神经网络、深度学习相关的技术需求。如果想快速入门,同样推荐 Andrew Ng (吴恩达)的 Coursera: Deep Learning,质量无需多言,Coursera 上罕见的满分课程。此外如果你觉得英文课程学习起来有难度,推荐李宏毅老师的 国立台湾大学:机器学习 课程。这门课打着机器学习的名号,却囊括了深度学习领域的几乎所有方向,非常全面,很适合你从宏观上对这个领域有一个大致的了解。而且老师本人也非常幽默,课堂金句频出。
当然因为深度学习领域发展非常迅速,已经拥有了众多研究分支,如果想要进一步深入,可以按需学习下面罗列的代表课程,
Stanford CS231n: CNN for Visual Recognition
Stanford CS224n: Natural Language Processing
Stanford CS224w: Machine Learning with Graphs
UCB CS285: Deep Reinforcement Learning
授人以鱼不如授人以渔。
以上的课程规划难免带有强烈的个人偏好,不一定适合所有人,更多是起到抛砖引玉的作用。如果你想挑选自己感兴趣的方向和内容加以学习,可以参考我在下面列出来的资源。
计算机领域方向庞杂,知识浩如烟海,每个细分领域如果深究下去都可以说学无止境。因此,一个清晰明确的学习规划是非常重要的。我在多年自学的尝试中也走过不少弯路,最终提炼出了下面的内容,供大家参考。
不过,在开始学习之前,先向小白们强烈推荐一个科普向系列视频 Crash Course: Computer Science,在短短 8 个小时里非常生动且全面地科普了关于计算机科学的方方面面:计算机的历史、计算机是如何运作的、组成计算机的各个重要模块、计算机科学中的重要思想等等等等。正如它的口号所说的 Computers are not magic!,希望看完这个视频之后,大家能对计算机科学有个全貌性地感知,从而怀着兴趣去面对下面浩如烟海的更为细致且深入的学习内容。
俗话说:磨刀不误砍柴工。如果你是一个刚刚接触计算机的24k纯小白,学会一些工具将会让你事半功倍。
学会提问:也许你会惊讶,提问也算计算机必备技能吗,还放在第一条?我觉得在开源社区中,学会提问是一项非常重要的能力,它包含两方面的事情。其一是会变相地培养你自主解决问题的能力,因为从形成问题、描述问题并发布、他人回答、最后再到理解回答这个周期是非常长的,如果遇到什么鸡毛蒜皮的事情都希望别人最好远程桌面手把手帮你完成,那计算机的世界基本与你无缘了。其二,如果真的经过尝试还无法解决,可以借助开源社区的帮助,但这时候如何通过简洁的文字让别人瞬间理解你的处境以及目的,就显得尤为重要。推荐阅读提问的智慧这篇文章,这不仅能提高你解决问题的概率和效率,也能让开源社区里无偿提供解答的人们拥有一个好心情。
MIT-Missing-Semester 这门课覆盖了这些工具中绝大部分,而且有相当详细的使用指导,强烈建议小白学习。不过需要注意的一点是,在课程中会不时提到一些与开发流程相关的术语。因此推荐至少在学完计算机导论级别的课程之后进行学习。
翻墙:由于一些众所周知的原因,谷歌、GitHub 等网站在大陆无法访问。然而很多时候,谷歌和 StackOverflow 可以解决你在开发过程中遇到的 99% 的问题。因此,学会翻墙几乎是一个内地 CSer 的必备技能。(考虑到法律问题,这个文档提供的翻墙方式仅对拥有北大邮箱的用户适用)。
命令行:熟练使用命令行是一种常常被忽视,或被认为难以掌握的技能,但实际上,它会极大地提高你作为工程师的灵活性以及生产力。命令行的艺术是一份非常经典的教程,它源于 Quora 的一个提问,但在各路大神的贡献努力下已经成为了一个 GitHub 十万 stars 的顶流项目,被翻译成了十几种语言。教程不长,非常建议大家反复通读,在实践中内化吸收。同时,掌握 Shell 脚本编程也是一项不容忽视的技术,可以参考这个教程。
IDE (Integrated Development Environment):集成开发环境,说白了就是你写代码的地方。作为一个码农,IDE 的重要性不言而喻,但由于很多 IDE 是为大型工程项目设计的,体量较大,功能也过于丰富。其实如今一些轻便的文本编辑器配合丰富的插件生态基本可以满足日常的轻量编程需求。个人常用的编辑器是 VS Code 和 Sublime(前者的插件配置非常简单,后者略显复杂但颜值很高)。当然对于大型项目我还是会采用略重型的 IDE,例如 Pycharm (Python),IDEA (Java) 等等(免责申明:所有的 IDE 都是世界上最好的 IDE)。
Vim:一款命令行编辑工具。这是一个学习曲线有些陡峭的编辑器,不过学会它我觉得是非常有必要的,因为它将极大地提高你的开发效率。现在绝大多数 IDE 也都支持 Vim 插件,让你在享受现代开发环境的同时保留极客的炫酷(yue)。
Emacs:与 Vim 齐名的经典编辑器,同样具有极高的开发效率,同时具有更为强大的扩展性,它既可以配置为一个轻量编辑器,也可以扩展成一个个人定制的 IDE,甚至可以有更多奇技淫巧。
Git:一款代码版本控制工具。Git的学习曲线可能更为陡峭,但出自 Linux 之父 Linus 之手的 Git 绝对是每个学 CS 的童鞋必须掌握的神器之一。
GitHub:基于 Git 的代码托管平台。全世界最大的代码开源社区,大佬集聚地。
GNU Make:一款工程构建工具。善用 GNU Make 会让你养成代码模块化的习惯,同时也能让你熟悉一些大型工程的编译链接流程。
CMake:一款功能比 GNU Make 更为强大的构建工具,建议掌握 GNU Make 之后再加以学习。
LaTex:逼格提升 论文排版工具。
Docker:一款相较于虚拟机更轻量级的软件打包与环境部署工具。
实用工具箱:除了上面提到的这些在开发中使用频率极高的工具之外,我还收集了很多实用有趣的免费工具,例如一些下载工具、设计工具、学习网站等等。
Thesis:毕业论文 Word 写作教程。
私以为一本好的教材应当是以人为本的,而不是炫技式的理论堆砌。告诉读者“是什么”固然重要,但更好的应当是教材作者将其在这个领域深耕几十年的经验融汇进书中,向读者娓娓道来“为什么”以及未来应该“怎么做”。
你以为的开发 —— 在 IDE 里疯狂码代码数小时。
实际上的开发 —— 配环境配几天还没开始写代码。
如果你是 Mac 用户,那么你很幸运,这份指南 将会手把手地带你搭建起整套开发环境。如果你是 Windows 用户,在开源社区的努力下,你同样可以获得与其他平台类似的体验:Scoop。
另外大家可以参考一份灵感来自 6.NULL MIT-Missing-Semester 的 环境配置指南,重点在于终端的美化配置。此外还包括常用软件源(如 GitHub, Anaconda, PyPI 等)的加速与替换以及一些 IDE 的配置与激活教程。
服务器端的运维需要掌握 Linux(或者其他类 Unix 系统)的基本使用以及进程、设备、网络等系统相关的基本概念,小白可以参考中国科学技术大学 Linux 用户协会编写的《Linux 101》在线讲义。如果想深入学习系统运维相关的知识,可以参考 Aspects of System Administration 这门课程。
另外,如果需要学习某个具体的概念或工具,推荐一个非常不错的 GitHub 项目 DevOps-Guide,其中涵盖了非常多的运维方面的基础知识和教程,例如 Docker, Kubernetes, Linux, CI-CD, GitHub Actions 等等。
正如这章开头提到的,这份课程地图仅仅是一个仅供参考的课程规划,我作为一个临近毕业的本科生。深感自己没有权利也没有能力向别人宣扬“应该怎么学”。因此如果你觉得以下的课程分类与选择有不合理之处,我全盘接受,并深感抱歉。你可以在下一节定制属于你的课程地图
以下课程类别中除了含有 基础 和 入门 字眼的以外,并无明确的先后次序,大家只要满足某个课程的先修要求,完全可以根据自己的需要和喜好选择想要学习的课程。
作为大一新生,学好微积分线代是和写代码至少同等重要的事情,相信已经有无数的前人经验提到过这一点,但我还是要不厌其烦地再强调一遍:学好微积分线代真的很重要!你也许会吐槽这些东西岂不是考完就忘,那我觉得你是并没有把握住它们本质,对它们的理解还没有达到刻骨铭心的程度。如果觉得老师课上讲的内容晦涩难懂,不妨参考 MIT 的 Calculus Course 和 18.06: Linear Algebra 的课程 notes,至少于我而言,它帮助我深刻理解了微积分和线性代数的许多本质。顺道再安利一个油管数学网红 3Blue1Brown,他的频道有很多用生动形象的动画阐释数学本质内核的视频,兼具深度和广度,质量非常高。
作为计算机系的学生,及早了解一些信息论的基础知识,我觉得是大有裨益的。但大多信息论课程都面向高年级本科生甚至研究生,对新手极不友好。而 MIT 的 6.050J: Information theory and Entropy 这门课正是为大一新生量身定制的,几乎没有先修要求,涵盖了编码、压缩、通信、信息熵等等内容,非常有趣。
集合论、图论、概率论等等是算法推导与证明的重要工具,也是后续高阶数学课程的基础。但我觉得这类课程的讲授很容易落入理论化与形式化的窠臼,让课堂成为定理结论的堆砌,而无法使学生深刻把握理论的本质,进而造成学了就背,考了就忘的怪圈。如果能在理论教学中穿插算法运用实例,学生在拓展算法知识的同时也能窥见理论的力量和魅力。
UCB CS70 : discrete Math and probability theory 和 UCB CS126 : Probability theory 是 UC Berkeley 的概率论课程,前者覆盖了离散数学和概率论基础,后者则涉及随机过程以及深入的理论内容。两者都非常注重理论和实践的结合,有丰富的算法实际运用实例,后者还有大量的 Python 编程作业来让学生运用概率论的知识解决实际问题。
作为计算机系的学生,培养计算思维是很重要的,实际问题的建模、离散化,计算机的模拟、分析,是一项很重要的能力。而这两年开始风靡的,由 MIT 打造的 Julia 编程语言以其 C 一样的速度和 Python 一样友好的语法在数值计算领域有一统天下之势,MIT 的许多数学课程也开始用 Julia 作为教学工具,把艰深的数学理论用直观清晰的代码展示出来。
ComputationalThinking 是 MIT 开设的一门计算思维入门课,所有课程内容全部开源,可以在课程网站直接访问。这门课利用 Julia 编程语言,在图像处理、社会科学与数据科学、气候学建模三个 topic 下带领学生理解算法、数学建模、数据分析、交互设计、图例展示,让学生体验计算与科学的美妙结合。内容虽然不难,但给我最深刻的感受就是,科学的魅力并不是故弄玄虚的艰深理论,不是诘屈聱牙的术语行话,而是用直观生动的案例,用简练深刻的语言,让每个普通人都能理解。
上完上面的体验课之后,如果意犹未尽的话,不妨试试 MIT 的 18.330 : Introduction to numerical analysis,这门课的编程作业同样会用 Julia 编程语言,不过难度和深度上都上了一个台阶。内容涉及了浮点编码、Root finding、线性系统、微分方程等等方面,整门课的主旨就是让你利用离散化的计算机表示去估计和逼近一个数学上连续的概念。这门课的教授还专门撰写了一本配套的开源教材 Fundamentals of Numerical Computation,里面附有丰富的 Julia 代码实例和严谨的公式推导。
如果你还意犹未尽的话,还有 MIT 的数值分析研究生课程 18.335: Introduction to numerical method 供你参考。
如果世间万物的运动发展都能用方程来刻画和描述,这是一件多么酷的事情呀!虽然几乎任何一所学校的 CS 培养方案中都没有微分方程相关的必修课程,但我还是觉得掌握它会赋予你一个新的视角来审视这个世界。
由于微分方程中往往会用到很多复变函数的知识,所以大家可以参考 MIT18.04: Complex variables functions 的课程 notes 来补齐先修知识。
MIT18.03: differential equations 主要覆盖了常微分方程的求解,在此基础之上 MIT18.152: Partial differential equations 则会深入偏微分方程的建模与求解。掌握了微分方程这一有力工具,相信对于你的实际问题的建模能力以及从众多噪声变量中把握本质的直觉都会有很大帮助。
作为计算机系的学生,我经常听到数学无用论的论断,对此我不敢苟同但也无权反对,但若凡事都硬要争出个有用和无用的区别来,倒也着实无趣,因此下面这些面向高年级甚至研究生的数学课程,大家按兴趣自取所需。
Standford EE364A: Convex Optimization
MIT18.650: Statistics for Applications
Languages are tools, you choose the right tool to do the right thing. Since there's no universally perfect tool, there's no universally perfect language.
作为计算机系的学生,了解一些基础的电路知识,感受从传感器收集数据到数据分析再到算法预测整条流水线,对于后续知识的学习以及计算思维的培养还是很有帮助的。EE16A&B: Designing Information Devices and Systems I&II 是伯克利 EE 学生的大一入门课,其中 EE16A 注重通过电路从实际环境中收集和分析数据,而 EE16B 则侧重从这些收集到的数据进行分析并做出预测行为。
信号与系统是一门我觉得非常值得一上的课,最初学它只是为了满足我对傅里叶变换的好奇,但学完之后我才不禁感叹,傅立叶变换给我提供了一个全新的视角去看待这个世界,就如同微分方程一样,让你沉浸在用数学去精确描绘和刻画这个世界的优雅与神奇之中。
MIT 6.003: signal and systems 提供了全部的课程录影、书面作业以及答案。也可以去看这门课的远古版本
而 UCB EE120: Signal and Systems 关于傅立叶变换的 notes 写得非常好,并且提供了6 个非常有趣的 Python 编程作业,让你实践中运用信号与系统的理论与算法。
算法是计算机科学的核心,也是几乎一切专业课程的基础。如何将实际问题通过数学抽象转化为算法问题,并选用合适的数据结构在时间和内存大小的限制下将其解决是算法课的永恒主题。如果你受够了老师的照本宣科,那么我强烈推荐伯克利的 UCB CS61B: Data Structures and Algorithms 和普林斯顿的 Coursera: Algorithms I & II,这两门课的都讲得深入浅出并且会有丰富且有趣的编程实验将理论与知识结合起来。
以上两门课程都是基于 Java 语言,如果你想学习 C/C++ 描述的版本,可以参考斯坦福的数据结构与基础算法课程 Stanford CS106B/X: Programming Abstractions。偏好 Python 的同学可以学习 MIT 的算法入门课 MIT 6.006: Introduction to Algorithms
对一些更高级的算法以及 NP 问题感兴趣的同学可以学习伯克利的算法设计与分析课程 UCB CS170: Efficient Algorithms and Intractable Problems 或者 MIT 的高阶算法 MIT 6.046: Design and Analysis of Algorithms。
一份“能跑”的代码,和一份高质量的工业级代码是有本质区别的。因此我非常推荐低年级的同学学习一下 MIT 6.031: Software Construction 这门课,它会以 Java 语言为基础,以丰富细致的阅读材料和精心设计的编程练习传授如何编写不易出 bug、简明易懂、易于维护修改的高质量代码。大到宏观数据结构设计,小到如何写注释,遵循这些前人总结的细节和经验,对于你此后的编程生涯大有裨益。
当然,如果你想系统性地上一门软件工程的课程,那我推荐的是伯克利的 UCB CS169: software engineering。但需要提醒的是,和大多学校(包括贵校)的软件工程课程不同,这门课不会涉及传统的 design and document 模式,即强调各种类图、流程图及文档设计,而是采用近些年流行起来的小团队快速迭代 Agile Develepment 开发模式以及利用云平台的 Software as a service 服务模式。
从小我就一直听说,计算机的世界是由 01 构成的,我不理解但大受震撼。如果你的内心也怀有这份好奇,不妨花一到两个月的时间学习 Coursera: Nand2Tetris 这门无门槛的计算机课程。这门麻雀虽小五脏俱全的课程会从 01 开始让你亲手造出一台计算机,并在上面运行俄罗斯方块小游戏。一门课里涵盖了编译、虚拟机、汇编、体系结构、数字电路、逻辑门等等从上至下、从软至硬的各类知识,非常全面。难度上也是通过精心的设计,略去了众多现代计算机复杂的细节,提取出了最核心本质的东西,力图让每个人都能理解。在低年级,如果就能从宏观上建立对整个计算机体系的鸟瞰图,是大有裨益的。
当然,如果想深入现代计算机体系结构的复杂细节,还得上一门大学本科难度的课程 UCB CS61C: Great Ideas in Computer Architecture。UC Berkeley 作为 RISC-V 架构的发源地,在体系结构领域算得上首屈一指。其课程非常注重实践,你会在 Project 中手写汇编构造神经网络,从零开始搭建一个 CPU,这些实践都会让你对计算机体系结构有更为深入的理解,而不是仅停留于“取指译码执行访存写回”的单调背诵里。
计算机系统是一个庞杂而深刻的主题,在深入学习某个细分领域之前,对各个领域有一个宏观概念性的理解,对一些通用性的设计原则有所知晓,会让你在之后的深入学习中不断强化一些最为核心乃至哲学的概念,而不会桎梏于复杂的内部细节和各种 trick。因为在我看来,学习系统最关键的还是想让你领悟到这些最核心的东西,从而能够设计和实现出属于自己的系统。
MIT6.033: System Engineering 是 MIT 的系统入门课,主题涉及了操作系统、网络、分布式和系统安全,除了知识点的传授外,这门课还会讲授一些写作和表达上的技巧,让你学会如何设计并向别人介绍和分析自己的系统。这本书配套的教材 Principles of Computer System Design: An Introduction 也写得非常好,推荐大家阅读。
CMU 15-213: Introduction to Computer System 是 CMU 的系统入门课,内容覆盖了体系结构、操作系统、链接、并行、网络等等,兼具广度和深度,配套的教材 Computer Systems: A Programmer's Perspective 也是质量极高,强烈建议阅读。
没有什么能比自己写个内核更能加深对操作系统的理解了。
操作系统作为各类纷繁复杂的底层硬件虚拟化出一套规范优雅的抽象,给所有应用软件提供丰富的功能支持。了解操作系统的设计原则和内部原理对于一个不满足于当调包侠的程序员来说是大有裨益的。出于对操作系统的热爱,我上过国内外很多操作系统课程,它们各有侧重和优劣,大家可以根据兴趣各取所需。
MIT 6.S081: Operating System Engineering,MIT 著名 PDOS 实验室出品,11 个 Project 让你在一个实现非常优雅的类Unix操作系统xv6上增加各类功能模块。这门课也让我深刻认识到,做系统不是靠 PPT 念出来的,是得几万行代码一点点累起来的。
UCB CS162: Operating System,伯克利的操作系统课,采用和 Stanford 同样的 Project —— 一个教学用操作系统 Pintos。我作为北京大学2022年和2023年春季学期操作系统实验班的助教,引入并改善了这个 Project,课程资源也会全部开源,具体参见课程网站。
NJU: Operating System Design and Implementation,南京大学的蒋炎岩老师开设的操作系统课程。蒋老师以其独到的系统视角结合丰富的代码示例将众多操作系统的概念讲得深入浅出,此外这门课的全部课程内容都是中文的,非常方便大家学习。
HIT OS: Operating System,哈尔滨工业大学的李治军老师开设的中文操作系统课程。李老师的课程基于 Linux 0.11 源码,十分注重代码实践,并站在学生视角将操作系统的来龙去脉娓娓道来。
想必这两年各类 CS 讲座里最常听到的话就是“摩尔定律正在走向终结”,此话不假,当单核能力达到上限时,多核乃至众核架构如日中天。硬件的变化带来的是上层编程逻辑的适应与改变,要想充分利用硬件性能,编写并行程序几乎成了程序员的必备技能。与此同时,深度学习的兴起对计算机算力与存储的要求都达到了前所未有的高度,大规模集群的部署和优化也成为热门技术话题。
CMU 15-418/Stanford CS149: Parallel Computing
不知道你当年选择计算机是不是因为怀着一个中二的黑客梦想,但现实却是成为黑客道阻且长。
UCB CS161: Computer Security 是伯克利的系统安全课程,会涵盖栈攻击、密码学、网站安全、网络安全等等内容。
ASU CSE365: Introduction to Cybersecurity 亚利桑那州立大学的 Web 安全课程,主要涉及注入、汇编与密码学的内容。
ASU CSE466: Computer Systems Security 亚利桑那州立大学的系统安全课程,涉及内容全面。门槛较高,需要对 Linux, C 与 Python 充分熟悉。
掌握这些理论知识之后,还需要在实践中培养和锻炼这些“黑客素养”。CTF 夺旗赛是一项比较热门的系统安全比赛,赛题中会融会贯通地考察你对计算机各个领域知识的理解和运用。北大今年也成功举办了第 0 届和第 1 届,鼓励大家后期踊跃参与,在实践中提高自己。下面列举一些我平时学习(摸鱼)用到的资源:
没有什么能比自己写个 TCP/IP 协议栈更能加深对计算机网络的理解了。
大名鼎鼎的 Stanford CS144: Computer Network,8 个 Project 带你实现整个 TCP/IP 协议栈。
如果你只是想在理论上对计算机网络有所了解,那么推荐计网著名教材《自顶向下方法》的配套学习资源 Computer Networking: A Top-Down Approach。
没有什么能比自己写个关系型数据库更能加深对数据库系统的理解了。
CMU 的著名数据库神课 CMU 15-445: Introduction to Database System 会通过 4 个 Project 带你为一个用于教学的关系型数据库 bustub 添加各种功能。实验的评测框架也免费开源了,非常适合大家自学。此外课程实验会用到 C++11 的众多新特性,也是一个锻炼 C++ 代码能力的好机会。
Berkeley 作为著名开源数据库 postgres 的发源地也不遑多让,UCB CS186: Introduction to Database System 会让你用 Java 语言实现一个支持 SQL 并发查询、B+ 树索引和故障恢复的关系型数据库。
没有什么能比自己写个编译器更能加深对编译器的理解了。
Stanford CS143: Compilers 带你手写编译器。
前后端开发很少在计算机的培养方案里被重视,但其实掌握这项技能还是好处多多的,例如搭建自己的个人主页,抑或是给自己的课程项目做一个精彩的展示网页。
Stanford CS142: Web Applications
其实数据科学和机器学习与深度学习有着很紧密的联系,但可能更侧重于实践。Berkeley 的 UCB Data100: Principles and Techniques of Data Science 通过丰富的编程练习让你在实践中掌握各类数据分析工具和算法,并带领你体验从海量的数据集中提取出想要的结果,并对未来的数据或用户的行为做出相应的预测。但这只是一门基础课,如果想学习工业级别的数据挖掘与分析技术,可以尝试 Stanford 的大数据挖掘课程 CS246: Mining Massive Data Sets。
近十年人工智能应该算是计算机界最火爆的领域。如果你不满足于整日听各路媒体争相报道人工智能相关的进展,而想真正一探究竟,那么非常推荐学习 Harvard 神课 CS50 系列的人工智能课程 Harvard CS50: Introduction to AI with Python。课程短小精悍,覆盖了传统人工智能领域的几大分支,并配有丰富有趣的 Python 编程练习来巩固你对人工智能算法的理解。美中不足的是这门课因为面向在线自学者的缘故内容较为精简,并且不会涉及特别深入的数学理论,如果想要系统深入地学习还需要一门本科生难度的课程,例如 Berkeley 的 UCB CS188: Introduction to Artificial Intelligence。这门课的 Project 复刻了经典游戏糖豆人,让你运用人工智能算法玩游戏,非常有趣。
机器学习领域近些年最重要的进展就是发展出了基于神经网络的深度学习分支,但其实很多基于统计学习的算法依然在数据分析领域有着广泛的应用。如果你之前从未接触过机器学习的相关知识,而且不想一开始就陷入艰深晦涩的数学证明,那么不妨先从 Andrew Ng (吴恩达)的 Coursera: Machine Learning 学起。这门课在机器学习领域基本无人不晓,吴恩达以其深厚的理论功底和出色的表达能力把很多艰深的算法讲得深入浅出,并且非常实用。其配套的作业也是质量相当上乘,可以帮助你快速入门。
但上过这门课只能让你从宏观上对机器学习这一领域有一定了解,如果想真正理解那些“神奇”算法背后的数学原理甚至从事相关领域的科研工作,那么还需要一门更“数学”的课程,例如 Stanford CS229: Machine Learning 或者 UCB CS189: Introduction to Machine Learning。
前几年 AlphaGo 的大热让深度学习进入了大众的视野,不少大学甚至专门成立了相关专业。很多计算机的其他领域也会借助深度学习的技术来做研究,因此基本不管你干啥多少都会接触到一些神经网络、深度学习相关的技术需求。如果想快速入门,同样推荐 Andrew Ng (吴恩达)的 Coursera: Deep Learning,质量无需多言,Coursera 上罕见的满分课程。此外如果你觉得英文课程学习起来有难度,推荐李宏毅老师的 国立台湾大学:机器学习 课程。这门课打着机器学习的名号,却囊括了深度学习领域的几乎所有方向,非常全面,很适合你从宏观上对这个领域有一个大致的了解。而且老师本人也非常幽默,课堂金句频出。
当然因为深度学习领域发展非常迅速,已经拥有了众多研究分支,如果想要进一步深入,可以按需学习下面罗列的代表课程,
UMich EECS 498-007 / 598-005: Deep Learning for Computer Vision
Stanford CS231n: CNN for Visual Recognition
Stanford CS224n: Natural Language Processing
Stanford CS224w: Machine Learning with Graphs
UCB CS285: Deep Reinforcement Learning
授人以鱼不如授人以渔。
以上的课程规划难免带有强烈的个人偏好,不一定适合所有人,更多是起到抛砖引玉的作用。如果你想挑选自己感兴趣的方向和内容加以学习,可以参考我在下面列出来的资源。
斯坦福的 Web 应用开发课程,内容覆盖了 HTML, CSS, JavaScript, ReactJs, NodeJS, ExpressJS, Web安全等等。8 个 Project 会让你在实战中锻炼自己的 Web 开发技巧。
斯坦福的 Web 应用开发课程,内容覆盖了 HTML, CSS, JavaScript, ReactJs, NodeJS, ExpressJS, Web安全等等。8 个 Project 会让你在实战中锻炼自己的 Web 开发技巧。
该课程提供了 React 前端开发和 React Native 移动端开发的最佳实践介绍,完整的同时又提纲挈领。采用 React 和 React Native 的最新版本,课程网站每学期都会更新。对于各门工具迭出的前端开发难能可贵。
同时,该课程也提供了很好的训练机会。在整个学期中,需要为较大作业量做好准备。作业所涉及的技术和知识点会在课上讲解,但不会手把手写代码(个人认为手把手写代码效率非常低,而 Udemy 上多为此类型)。由于不是保姆级课程,如果写作业时对于 React 的某些功能不确定怎么写,建议在动手之前多花些时间仔细阅读 react.dev 上的相关章节。作业的 starter code 提供的训练起点也恰好合适,不用为配 Node.js 环境伤脑筋。
尽管这门课程不要求预先会 Javascript/HTML/CSS,课堂上对 syntax 的介绍比较有限,建议学习和写码遇到语法问题时勤查勤问。
此外,本课程还对 Google 旗下的 ChatBot 开发工具 Dialog Flow 有较为深入的介绍和练习。还对 UX Design 的实用原则和技术有所讲解。
所有课程资料和作业都是开源的,但你需要向授课教师 Cole Nelson (ctnelson2@wisc.edu) 发送电子邮件以获取 X-CS571-ID。该 ID 是向 API 发送 request 必需。在发送邮件时,建议附上自我介绍。目前还不清楚老师是否愿意给所有人提供ID,如果老师表示无法分享,请在 GitHub repo 里提一个 issue。
该课程提供了 React 前端开发和 React Native 移动端开发的最佳实践介绍,完整的同时又提纲挈领。采用 React 和 React Native 的最新版本,课程网站每学期都会更新。对于各门工具迭出的前端开发难能可贵。
同时,该课程也提供了很好的训练机会。在整个学期中,需要为较大作业量做好准备。作业所涉及的技术和知识点会在课上讲解,但不会手把手写代码(个人认为手把手写代码效率非常低,而 Udemy 上多为此类型)。由于不是保姆级课程,如果写作业时对于 React 的某些功能不确定怎么写,建议在动手之前多花些时间仔细阅读 react.dev 上的相关章节。作业的 starter code 提供的训练起点也恰好合适,不用为配 Node.js 环境伤脑筋。
尽管这门课程不要求预先会 Javascript/HTML/CSS,课堂上对 syntax 的介绍比较有限,建议学习和写码遇到语法问题时勤查勤问。
此外,本课程还对 Google 旗下的 ChatBot 开发工具 Dialog Flow 有较为深入的介绍和练习。还对 UX Design 的实用原则和技术有所讲解。
所有课程资料和作业都是开源的,但你需要向授课教师 Cole Nelson (ctnelson2@wisc.edu) 发送电子邮件以获取 X-CS571-ID。该 ID 是向 API 发送 request 必需。在发送邮件时,建议附上自我介绍。目前还不清楚老师是否愿意给所有人提供ID,如果老师表示无法分享,请在 GitHub repo 里提一个 issue。
本课程是介绍如何使用 JavaScript 开发现代Web应用程序。 课程的重点是使用 ReactJS 构建单页面应用程序(SPA),并使用由 Node.js 构建 REST API。该课程还包含介绍 GraphQL 的部分,这是 REST API 的现代替代方案。
课程还包括测试、配置和环境管理,以及使用 MongoDB 来存储应用的数据。
本课程是介绍如何使用 JavaScript 开发现代Web应用程序。 课程的重点是使用 ReactJS 构建单页面应用程序(SPA),并使用由 Node.js 构建 REST API。该课程还包含介绍 GraphQL 的部分,这是 REST API 的现代替代方案。
课程还包括测试、配置和环境管理,以及使用 MongoDB 来存储应用的数据。
MIT 在每年 1 月份会有一个为期 4 周的 Independent Activities Period (IAP),在这个月里,MIT 的学生和老师可以自由地开设很多有趣的课程,而这门网站开发课程就是其中之一。
在一个月的时间里,你会从零开始掌握一个网站的设计、搭建、美化、交互等等核心内容,基本覆盖了 Web 开发的前后端大部分技术栈。如果你不需要系统地学习网络开发,而只是出于兴趣想把它加入自己的技能包里,那么这门课将非常适合你。
MIT 在每年 1 月份会有一个为期 4 周的 Independent Activities Period (IAP),在这个月里,MIT 的学生和老师可以自由地开设很多有趣的课程,而这门网站开发课程就是其中之一。
在一个月的时间里,你会从零开始掌握一个网站的设计、搭建、美化、交互等等核心内容,基本覆盖了 Web 开发的前后端大部分技术栈。如果你不需要系统地学习网络开发,而只是出于兴趣想把它加入自己的技能包里,那么这门课将非常适合你。
计算机领域方向庞杂,知识浩如烟海,每个细分领域如果深究下去都可以说学无止境。因此,一个清晰明确的学习规划是非常重要的。我在多年自学的尝试中也走过不少弯路,最终提炼出了下面的内容,供大家参考。
不过,在开始学习之前,先向小白们强烈推荐一个科普向系列视频 Crash Course: Computer Science,在短短 8 个小时里非常生动且全面地科普了关于计算机科学的方方面面:计算机的历史、计算机是如何运作的、组成计算机的各个重要模块、计算机科学中的重要思想等等等等。正如它的口号所说的 Computers are not magic!,希望看完这个视频之后,大家能对计算机科学有个全貌性地感知,从而怀着兴趣去面对下面浩如烟海的更为细致且深入的学习内容。
俗话说:磨刀不误砍柴工。如果你是一个刚刚接触计算机的24k纯小白,学会一些工具将会让你事半功倍。
学会提问:也许你会惊讶,提问也算计算机必备技能吗,还放在第一条?我觉得在开源社区中,学会提问是一项非常重要的能力,它包含两方面的事情。其一是会变相地培养你自主解决问题的能力,因为从形成问题、描述问题并发布、他人回答、最后再到理解回答这个周期是非常长的,如果遇到什么鸡毛蒜皮的事情都希望别人最好远程桌面手把手帮你完成,那计算机的世界基本与你无缘了。其二,如果真的经过尝试还无法解决,可以借助开源社区的帮助,但这时候如何通过简洁的文字让别人瞬间理解你的处境以及目的,就显得尤为重要。推荐阅读提问的智慧这篇文章,这不仅能提高你解决问题的概率和效率,也能让开源社区里无偿提供解答的人们拥有一个好心情。
MIT-Missing-Semester 这门课覆盖了这些工具中绝大部分,而且有相当详细的使用指导,强烈建议小白学习。不过需要注意的一点是,在课程中会不时提到一些与开发流程相关的术语。因此推荐至少在学完计算机导论级别的课程之后进行学习。
翻墙:由于一些众所周知的原因,谷歌、GitHub 等网站在大陆无法访问。然而很多时候,谷歌和 StackOverflow 可以解决你在开发过程中遇到的 99% 的问题。因此,学会翻墙几乎是一个内地 CSer 的必备技能。(考虑到法律问题,这个文档提供的翻墙方式仅对拥有北大邮箱的用户适用)。
命令行:熟练使用命令行是一种常常被忽视,或被认为难以掌握的技能,但实际上,它会极大地提高你作为工程师的灵活性以及生产力。命令行的艺术是一份非常经典的教程,它源于 Quora 的一个提问,但在各路大神的贡献努力下已经成为了一个 GitHub 十万 stars 的顶流项目,被翻译成了十几种语言。教程不长,非常建议大家反复通读,在实践中内化吸收。同时,掌握 Shell 脚本编程也是一项不容忽视的技术,可以参考这个教程。
IDE (Integrated Development Environment):集成开发环境,说白了就是你写代码的地方。作为一个码农,IDE 的重要性不言而喻,但由于很多 IDE 是为大型工程项目设计的,体量较大,功能也过于丰富。其实如今一些轻便的文本编辑器配合丰富的插件生态基本可以满足日常的轻量编程需求。个人常用的编辑器是 VS Code 和 Sublime(前者的插件配置非常简单,后者略显复杂但颜值很高)。当然对于大型项目我还是会采用略重型的 IDE,例如 Pycharm (Python),IDEA (Java) 等等(免责申明:所有的 IDE 都是世界上最好的 IDE)。
Vim:一款命令行编辑工具。这是一个学习曲线有些陡峭的编辑器,不过学会它我觉得是非常有必要的,因为它将极大地提高你的开发效率。现在绝大多数 IDE 也都支持 Vim 插件,让你在享受现代开发环境的同时保留极客的炫酷(yue)。
Emacs:与 Vim 齐名的经典编辑器,同样具有极高的开发效率,同时具有更为强大的扩展性,它既可以配置为一个轻量编辑器,也可以扩展成一个个人定制的 IDE,甚至可以有更多奇技淫巧。
Git:一款代码版本控制工具。Git的学习曲线可能更为陡峭,但出自 Linux 之父 Linus 之手的 Git 绝对是每个学 CS 的童鞋必须掌握的神器之一。
GitHub:基于 Git 的代码托管平台。全世界最大的代码开源社区,大佬集聚地。
GNU Make:一款工程构建工具。善用 GNU Make 会让你养成代码模块化的习惯,同时也能让你熟悉一些大型工程的编译链接流程。
CMake:一款功能比 GNU Make 更为强大的构建工具,建议掌握 GNU Make 之后再加以学习。
LaTex:逼格提升 论文排版工具。
Docker:一款相较于虚拟机更轻量级的软件打包与环境部署工具。
实用工具箱:除了上面提到的这些在开发中使用频率极高的工具之外,我还收集了很多实用有趣的免费工具,例如一些下载工具、设计工具、学习网站等等。
Thesis:毕业论文 Word 写作教程。
私以为一本好的教材应当是以人为本的,而不是炫技式的理论堆砌。告诉读者“是什么”固然重要,但更好的应当是教材作者将其在这个领域深耕几十年的经验融汇进书中,向读者娓娓道来“为什么”以及未来应该“怎么做”。
你以为的开发 —— 在 IDE 里疯狂码代码数小时。
实际上的开发 —— 配环境配几天还没开始写代码。
如果你是 Mac 用户,那么你很幸运,这份指南 将会手把手地带你搭建起整套开发环境。如果你是 Windows 用户,在开源社区的努力下,你同样可以获得与其他平台类似的体验:Scoop。
另外大家可以参考一份灵感来自 6.NULL MIT-Missing-Semester 的 环境配置指南,重点在于终端的美化配置。此外还包括常用软件源(如 GitHub, Anaconda, PyPI 等)的加速与替换以及一些 IDE 的配置与激活教程。
服务器端的运维需要掌握 Linux(或者其他类 Unix 系统)的基本使用以及进程、设备、网络等系统相关的基本概念,小白可以参考中国科学技术大学 Linux 用户协会编写的《Linux 101》在线讲义。如果想深入学习系统运维相关的知识,可以参考 Aspects of System Administration 这门课程。
另外,如果需要学习某个具体的概念或工具,推荐一个非常不错的 GitHub 项目 DevOps-Guide,其中涵盖了非常多的运维方面的基础知识和教程,例如 Docker, Kubernetes, Linux, CI-CD, GitHub Actions 等等。
正如这章开头提到的,这份课程地图仅仅是一个仅供参考的课程规划,我作为一个临近毕业的本科生。深感自己没有权利也没有能力向别人宣扬“应该怎么学”。因此如果你觉得以下的课程分类与选择有不合理之处,我全盘接受,并深感抱歉。你可以在下一节定制属于你的课程地图
以下课程类别中除了含有 基础 和 入门 字眼的以外,并无明确的先后次序,大家只要满足某个课程的先修要求,完全可以根据自己的需要和喜好选择想要学习的课程。
作为大一新生,学好微积分线代是和写代码至少同等重要的事情,相信已经有无数的前人经验提到过这一点,但我还是要不厌其烦地再强调一遍:学好微积分线代真的很重要!你也许会吐槽这些东西岂不是考完就忘,那我觉得你是并没有把握住它们本质,对它们的理解还没有达到刻骨铭心的程度。如果觉得老师课上讲的内容晦涩难懂,不妨参考 MIT 的 Calculus Course 和 18.06: Linear Algebra 的课程 notes,至少于我而言,它帮助我深刻理解了微积分和线性代数的许多本质。顺道再安利一个油管数学网红 3Blue1Brown,他的频道有很多用生动形象的动画阐释数学本质内核的视频,兼具深度和广度,质量非常高。
作为计算机系的学生,及早了解一些信息论的基础知识,我觉得是大有裨益的。但大多信息论课程都面向高年级本科生甚至研究生,对新手极不友好。而 MIT 的 6.050J: Information theory and Entropy 这门课正是为大一新生量身定制的,几乎没有先修要求,涵盖了编码、压缩、通信、信息熵等等内容,非常有趣。
集合论、图论、概率论等等是算法推导与证明的重要工具,也是后续高阶数学课程的基础。但我觉得这类课程的讲授很容易落入理论化与形式化的窠臼,让课堂成为定理结论的堆砌,而无法使学生深刻把握理论的本质,进而造成学了就背,考了就忘的怪圈。如果能在理论教学中穿插算法运用实例,学生在拓展算法知识的同时也能窥见理论的力量和魅力。
UCB CS70 : discrete Math and probability theory 和 UCB CS126 : Probability theory 是 UC Berkeley 的概率论课程,前者覆盖了离散数学和概率论基础,后者则涉及随机过程以及深入的理论内容。两者都非常注重理论和实践的结合,有丰富的算法实际运用实例,后者还有大量的 Python 编程作业来让学生运用概率论的知识解决实际问题。
作为计算机系的学生,培养计算思维是很重要的,实际问题的建模、离散化,计算机的模拟、分析,是一项很重要的能力。而这两年开始风靡的,由 MIT 打造的 Julia 编程语言以其 C 一样的速度和 Python 一样友好的语法在数值计算领域有一统天下之势,MIT 的许多数学课程也开始用 Julia 作为教学工具,把艰深的数学理论用直观清晰的代码展示出来。
ComputationalThinking 是 MIT 开设的一门计算思维入门课,所有课程内容全部开源,可以在课程网站直接访问。这门课利用 Julia 编程语言,在图像处理、社会科学与数据科学、气候学建模三个 topic 下带领学生理解算法、数学建模、数据分析、交互设计、图例展示,让学生体验计算与科学的美妙结合。内容虽然不难,但给我最深刻的感受就是,科学的魅力并不是故弄玄虚的艰深理论,不是诘屈聱牙的术语行话,而是用直观生动的案例,用简练深刻的语言,让每个普通人都能理解。
上完上面的体验课之后,如果意犹未尽的话,不妨试试 MIT 的 18.330 : Introduction to numerical analysis,这门课的编程作业同样会用 Julia 编程语言,不过难度和深度上都上了一个台阶。内容涉及了浮点编码、Root finding、线性系统、微分方程等等方面,整门课的主旨就是让你利用离散化的计算机表示去估计和逼近一个数学上连续的概念。这门课的教授还专门撰写了一本配套的开源教材 Fundamentals of Numerical Computation,里面附有丰富的 Julia 代码实例和严谨的公式推导。
如果你还意犹未尽的话,还有 MIT 的数值分析研究生课程 18.335: Introduction to numerical method 供你参考。
如果世间万物的运动发展都能用方程来刻画和描述,这是一件多么酷的事情呀!虽然几乎任何一所学校的 CS 培养方案中都没有微分方程相关的必修课程,但我还是觉得掌握它会赋予你一个新的视角来审视这个世界。
由于微分方程中往往会用到很多复变函数的知识,所以大家可以参考 MIT18.04: Complex variables functions 的课程 notes 来补齐先修知识。
MIT18.03: differential equations 主要覆盖了常微分方程的求解,在此基础之上 MIT18.152: Partial differential equations 则会深入偏微分方程的建模与求解。掌握了微分方程这一有力工具,相信对于你的实际问题的建模能力以及从众多噪声变量中把握本质的直觉都会有很大帮助。
作为计算机系的学生,我经常听到数学无用论的论断,对此我不敢苟同但也无权反对,但若凡事都硬要争出个有用和无用的区别来,倒也着实无趣,因此下面这些面向高年级甚至研究生的数学课程,大家按兴趣自取所需。
Standford EE364A: Convex Optimization
MIT18.650: Statistics for Applications
Languages are tools, you choose the right tool to do the right thing. Since there's no universally perfect tool, there's no universally perfect language.
作为计算机系的学生,了解一些基础的电路知识,感受从传感器收集数据到数据分析再到算法预测整条流水线,对于后续知识的学习以及计算思维的培养还是很有帮助的。EE16A&B: Designing Information Devices and Systems I&II 是伯克利 EE 学生的大一入门课,其中 EE16A 注重通过电路从实际环境中收集和分析数据,而 EE16B 则侧重从这些收集到的数据进行分析并做出预测行为。
信号与系统是一门我觉得非常值得一上的课,最初学它只是为了满足我对傅里叶变换的好奇,但学完之后我才不禁感叹,傅立叶变换给我提供了一个全新的视角去看待这个世界,就如同微分方程一样,让你沉浸在用数学去精确描绘和刻画这个世界的优雅与神奇之中。
MIT 6.003: signal and systems 提供了全部的课程录影、书面作业以及答案。也可以去看这门课的远古版本
而 UCB EE120: Signal and Systems 关于傅立叶变换的 notes 写得非常好,并且提供了6 个非常有趣的 Python 编程作业,让你实践中运用信号与系统的理论与算法。
算法是计算机科学的核心,也是几乎一切专业课程的基础。如何将实际问题通过数学抽象转化为算法问题,并选用合适的数据结构在时间和内存大小的限制下将其解决是算法课的永恒主题。如果你受够了老师的照本宣科,那么我强烈推荐伯克利的 UCB CS61B: Data Structures and Algorithms 和普林斯顿的 Coursera: Algorithms I & II,这两门课的都讲得深入浅出并且会有丰富且有趣的编程实验将理论与知识结合起来。
以上两门课程都是基于 Java 语言,如果你想学习 C/C++ 描述的版本,可以参考斯坦福的数据结构与基础算法课程 Stanford CS106B/X: Programming Abstractions。偏好 Python 的同学可以学习 MIT 的算法入门课 MIT 6.006: Introduction to Algorithms
对一些更高级的算法以及 NP 问题感兴趣的同学可以学习伯克利的算法设计与分析课程 UCB CS170: Efficient Algorithms and Intractable Problems 或者 MIT 的高阶算法 MIT 6.046: Design and Analysis of Algorithms。
一份“能跑”的代码,和一份高质量的工业级代码是有本质区别的。因此我非常推荐低年级的同学学习一下 MIT 6.031: Software Construction 这门课,它会以 Java 语言为基础,以丰富细致的阅读材料和精心设计的编程练习传授如何编写不易出 bug、简明易懂、易于维护修改的高质量代码。大到宏观数据结构设计,小到如何写注释,遵循这些前人总结的细节和经验,对于你此后的编程生涯大有裨益。
当然,如果你想系统性地上一门软件工程的课程,那我推荐的是伯克利的 UCB CS169: software engineering。但需要提醒的是,和大多学校(包括贵校)的软件工程课程不同,这门课不会涉及传统的 design and document 模式,即强调各种类图、流程图及文档设计,而是采用近些年流行起来的小团队快速迭代 Agile Develepment 开发模式以及利用云平台的 Software as a service 服务模式。
从小我就一直听说,计算机的世界是由 01 构成的,我不理解但大受震撼。如果你的内心也怀有这份好奇,不妨花一到两个月的时间学习 Coursera: Nand2Tetris 这门无门槛的计算机课程。这门麻雀虽小五脏俱全的课程会从 01 开始让你亲手造出一台计算机,并在上面运行俄罗斯方块小游戏。一门课里涵盖了编译、虚拟机、汇编、体系结构、数字电路、逻辑门等等从上至下、从软至硬的各类知识,非常全面。难度上也是通过精心的设计,略去了众多现代计算机复杂的细节,提取出了最核心本质的东西,力图让每个人都能理解。在低年级,如果就能从宏观上建立对整个计算机体系的鸟瞰图,是大有裨益的。
当然,如果想深入现代计算机体系结构的复杂细节,还得上一门大学本科难度的课程 UCB CS61C: Great Ideas in Computer Architecture。UC Berkeley 作为 RISC-V 架构的发源地,在体系结构领域算得上首屈一指。其课程非常注重实践,你会在 Project 中手写汇编构造神经网络,从零开始搭建一个 CPU,这些实践都会让你对计算机体系结构有更为深入的理解,而不是仅停留于“取指译码执行访存写回”的单调背诵里。
计算机系统是一个庞杂而深刻的主题,在深入学习某个细分领域之前,对各个领域有一个宏观概念性的理解,对一些通用性的设计原则有所知晓,会让你在之后的深入学习中不断强化一些最为核心乃至哲学的概念,而不会桎梏于复杂的内部细节和各种 trick。因为在我看来,学习系统最关键的还是想让你领悟到这些最核心的东西,从而能够设计和实现出属于自己的系统。
MIT6.033: System Engineering 是 MIT 的系统入门课,主题涉及了操作系统、网络、分布式和系统安全,除了知识点的传授外,这门课还会讲授一些写作和表达上的技巧,让你学会如何设计并向别人介绍和分析自己的系统。这本书配套的教材 Principles of Computer System Design: An Introduction 也写得非常好,推荐大家阅读。
CMU 15-213: Introduction to Computer System 是 CMU 的系统入门课,内容覆盖了体系结构、操作系统、链接、并行、网络等等,兼具广度和深度,配套的教材 Computer Systems: A Programmer's Perspective 也是质量极高,强烈建议阅读。
没有什么能比自己写个内核更能加深对操作系统的理解了。
操作系统作为各类纷繁复杂的底层硬件虚拟化出一套规范优雅的抽象,给所有应用软件提供丰富的功能支持。了解操作系统的设计原则和内部原理对于一个不满足于当调包侠的程序员来说是大有裨益的。出于对操作系统的热爱,我上过国内外很多操作系统课程,它们各有侧重和优劣,大家可以根据兴趣各取所需。
MIT 6.S081: Operating System Engineering,MIT 著名 PDOS 实验室出品,11 个 Project 让你在一个实现非常优雅的类Unix操作系统xv6上增加各类功能模块。这门课也让我深刻认识到,做系统不是靠 PPT 念出来的,是得几万行代码一点点累起来的。
UCB CS162: Operating System,伯克利的操作系统课,采用和 Stanford 同样的 Project —— 一个教学用操作系统 Pintos。我作为北京大学2022年和2023年春季学期操作系统实验班的助教,引入并改善了这个 Project,课程资源也会全部开源,具体参见课程网站。
NJU: Operating System Design and Implementation,南京大学的蒋炎岩老师开设的操作系统课程。蒋老师以其独到的系统视角结合丰富的代码示例将众多操作系统的概念讲得深入浅出,此外这门课的全部课程内容都是中文的,非常方便大家学习。
HIT OS: Operating System,哈尔滨工业大学的李治军老师开设的中文操作系统课程。李老师的课程基于 Linux 0.11 源码,十分注重代码实践,并站在学生视角将操作系统的来龙去脉娓娓道来。
想必这两年各类 CS 讲座里最常听到的话就是“摩尔定律正在走向终结”,此话不假,当单核能力达到上限时,多核乃至众核架构如日中天。硬件的变化带来的是上层编程逻辑的适应与改变,要想充分利用硬件性能,编写并行程序几乎成了程序员的必备技能。与此同时,深度学习的兴起对计算机算力与存储的要求都达到了前所未有的高度,大规模集群的部署和优化也成为热门技术话题。
CMU 15-418/Stanford CS149: Parallel Computing
不知道你当年选择计算机是不是因为怀着一个中二的黑客梦想,但现实却是成为黑客道阻且长。
UCB CS161: Computer Security 是伯克利的系统安全课程,会涵盖栈攻击、密码学、网站安全、网络安全等等内容。
ASU CSE365: Introduction to Cybersecurity 亚利桑那州立大学的 Web 安全课程,主要涉及注入、汇编与密码学的内容。
ASU CSE466: Computer Systems Security 亚利桑那州立大学的系统安全课程,涉及内容全面。门槛较高,需要对 Linux, C 与 Python 充分熟悉。
掌握这些理论知识之后,还需要在实践中培养和锻炼这些“黑客素养”。CTF 夺旗赛是一项比较热门的系统安全比赛,赛题中会融会贯通地考察你对计算机各个领域知识的理解和运用。北大今年也成功举办了第 0 届和第 1 届,鼓励大家后期踊跃参与,在实践中提高自己。下面列举一些我平时学习(摸鱼)用到的资源:
没有什么能比自己写个 TCP/IP 协议栈更能加深对计算机网络的理解了。
大名鼎鼎的 Stanford CS144: Computer Network,8 个 Project 带你实现整个 TCP/IP 协议栈。
如果你只是想在理论上对计算机网络有所了解,那么推荐计网著名教材《自顶向下方法》的配套学习资源 Computer Networking: A Top-Down Approach。
没有什么能比自己写个关系型数据库更能加深对数据库系统的理解了。
CMU 的著名数据库神课 CMU 15-445: Introduction to Database System 会通过 4 个 Project 带你为一个用于教学的关系型数据库 bustub 添加各种功能。实验的评测框架也免费开源了,非常适合大家自学。此外课程实验会用到 C++11 的众多新特性,也是一个锻炼 C++ 代码能力的好机会。
Berkeley 作为著名开源数据库 postgres 的发源地也不遑多让,UCB CS186: Introduction to Database System 会让你用 Java 语言实现一个支持 SQL 并发查询、B+ 树索引和故障恢复的关系型数据库。
没有什么能比自己写个编译器更能加深对编译器的理解了。
Stanford CS143: Compilers 带你手写编译器。
前后端开发很少在计算机的培养方案里被重视,但其实掌握这项技能还是好处多多的,例如搭建自己的个人主页,抑或是给自己的课程项目做一个精彩的展示网页。
Stanford CS142: Web Applications
其实数据科学和机器学习与深度学习有着很紧密的联系,但可能更侧重于实践。Berkeley 的 UCB Data100: Principles and Techniques of Data Science 通过丰富的编程练习让你在实践中掌握各类数据分析工具和算法,并带领你体验从海量的数据集中提取出想要的结果,并对未来的数据或用户的行为做出相应的预测。但这只是一门基础课,如果想学习工业级别的数据挖掘与分析技术,可以尝试 Stanford 的大数据挖掘课程 CS246: Mining Massive Data Sets。
近十年人工智能应该算是计算机界最火爆的领域。如果你不满足于整日听各路媒体争相报道人工智能相关的进展,而想真正一探究竟,那么非常推荐学习 Harvard 神课 CS50 系列的人工智能课程 Harvard CS50: Introduction to AI with Python。课程短小精悍,覆盖了传统人工智能领域的几大分支,并配有丰富有趣的 Python 编程练习来巩固你对人工智能算法的理解。美中不足的是这门课因为面向在线自学者的缘故内容较为精简,并且不会涉及特别深入的数学理论,如果想要系统深入地学习还需要一门本科生难度的课程,例如 Berkeley 的 UCB CS188: Introduction to Artificial Intelligence。这门课的 Project 复刻了经典游戏糖豆人,让你运用人工智能算法玩游戏,非常有趣。
机器学习领域近些年最重要的进展就是发展出了基于神经网络的深度学习分支,但其实很多基于统计学习的算法依然在数据分析领域有着广泛的应用。如果你之前从未接触过机器学习的相关知识,而且不想一开始就陷入艰深晦涩的数学证明,那么不妨先从 Andrew Ng (吴恩达)的 Coursera: Machine Learning 学起。这门课在机器学习领域基本无人不晓,吴恩达以其深厚的理论功底和出色的表达能力把很多艰深的算法讲得深入浅出,并且非常实用。其配套的作业也是质量相当上乘,可以帮助你快速入门。
但上过这门课只能让你从宏观上对机器学习这一领域有一定了解,如果想真正理解那些“神奇”算法背后的数学原理甚至从事相关领域的科研工作,那么还需要一门更“数学”的课程,例如 Stanford CS229: Machine Learning 或者 UCB CS189: Introduction to Machine Learning。
前几年 AlphaGo 的大热让深度学习进入了大众的视野,不少大学甚至专门成立了相关专业。很多计算机的其他领域也会借助深度学习的技术来做研究,因此基本不管你干啥多少都会接触到一些神经网络、深度学习相关的技术需求。如果想快速入门,同样推荐 Andrew Ng (吴恩达)的 Coursera: Deep Learning,质量无需多言,Coursera 上罕见的满分课程。此外如果你觉得英文课程学习起来有难度,推荐李宏毅老师的 国立台湾大学:机器学习 课程。这门课打着机器学习的名号,却囊括了深度学习领域的几乎所有方向,非常全面,很适合你从宏观上对这个领域有一个大致的了解。而且老师本人也非常幽默,课堂金句频出。
当然因为深度学习领域发展非常迅速,已经拥有了众多研究分支,如果想要进一步深入,可以按需学习下面罗列的代表课程,
Stanford CS231n: CNN for Visual Recognition
Stanford CS224n: Natural Language Processing
Stanford CS224w: Machine Learning with Graphs
UCB CS285: Deep Reinforcement Learning
授人以鱼不如授人以渔。
以上的课程规划难免带有强烈的个人偏好,不一定适合所有人,更多是起到抛砖引玉的作用。如果你想挑选自己感兴趣的方向和内容加以学习,可以参考我在下面列出来的资源。
计算机领域方向庞杂,知识浩如烟海,每个细分领域如果深究下去都可以说学无止境。因此,一个清晰明确的学习规划是非常重要的。我在多年自学的尝试中也走过不少弯路,最终提炼出了下面的内容,供大家参考。
不过,在开始学习之前,先向小白们强烈推荐一个科普向系列视频 Crash Course: Computer Science,在短短 8 个小时里非常生动且全面地科普了关于计算机科学的方方面面:计算机的历史、计算机是如何运作的、组成计算机的各个重要模块、计算机科学中的重要思想等等等等。正如它的口号所说的 Computers are not magic!,希望看完这个视频之后,大家能对计算机科学有个全貌性地感知,从而怀着兴趣去面对下面浩如烟海的更为细致且深入的学习内容。
俗话说:磨刀不误砍柴工。如果你是一个刚刚接触计算机的24k纯小白,学会一些工具将会让你事半功倍。
学会提问:也许你会惊讶,提问也算计算机必备技能吗,还放在第一条?我觉得在开源社区中,学会提问是一项非常重要的能力,它包含两方面的事情。其一是会变相地培养你自主解决问题的能力,因为从形成问题、描述问题并发布、他人回答、最后再到理解回答这个周期是非常长的,如果遇到什么鸡毛蒜皮的事情都希望别人最好远程桌面手把手帮你完成,那计算机的世界基本与你无缘了。其二,如果真的经过尝试还无法解决,可以借助开源社区的帮助,但这时候如何通过简洁的文字让别人瞬间理解你的处境以及目的,就显得尤为重要。推荐阅读提问的智慧这篇文章,这不仅能提高你解决问题的概率和效率,也能让开源社区里无偿提供解答的人们拥有一个好心情。
MIT-Missing-Semester 这门课覆盖了这些工具中绝大部分,而且有相当详细的使用指导,强烈建议小白学习。不过需要注意的一点是,在课程中会不时提到一些与开发流程相关的术语。因此推荐至少在学完计算机导论级别的课程之后进行学习。
翻墙:由于一些众所周知的原因,谷歌、GitHub 等网站在大陆无法访问。然而很多时候,谷歌和 StackOverflow 可以解决你在开发过程中遇到的 99% 的问题。因此,学会翻墙几乎是一个内地 CSer 的必备技能。(考虑到法律问题,这个文档提供的翻墙方式仅对拥有北大邮箱的用户适用)。
命令行:熟练使用命令行是一种常常被忽视,或被认为难以掌握的技能,但实际上,它会极大地提高你作为工程师的灵活性以及生产力。命令行的艺术是一份非常经典的教程,它源于 Quora 的一个提问,但在各路大神的贡献努力下已经成为了一个 GitHub 十万 stars 的顶流项目,被翻译成了十几种语言。教程不长,非常建议大家反复通读,在实践中内化吸收。同时,掌握 Shell 脚本编程也是一项不容忽视的技术,可以参考这个教程。
IDE (Integrated Development Environment):集成开发环境,说白了就是你写代码的地方。作为一个码农,IDE 的重要性不言而喻,但由于很多 IDE 是为大型工程项目设计的,体量较大,功能也过于丰富。其实如今一些轻便的文本编辑器配合丰富的插件生态基本可以满足日常的轻量编程需求。个人常用的编辑器是 VS Code 和 Sublime(前者的插件配置非常简单,后者略显复杂但颜值很高)。当然对于大型项目我还是会采用略重型的 IDE,例如 Pycharm (Python),IDEA (Java) 等等(免责申明:所有的 IDE 都是世界上最好的 IDE)。
Vim:一款命令行编辑工具。这是一个学习曲线有些陡峭的编辑器,不过学会它我觉得是非常有必要的,因为它将极大地提高你的开发效率。现在绝大多数 IDE 也都支持 Vim 插件,让你在享受现代开发环境的同时保留极客的炫酷(yue)。
Emacs:与 Vim 齐名的经典编辑器,同样具有极高的开发效率,同时具有更为强大的扩展性,它既可以配置为一个轻量编辑器,也可以扩展成一个个人定制的 IDE,甚至可以有更多奇技淫巧。
Git:一款代码版本控制工具。Git的学习曲线可能更为陡峭,但出自 Linux 之父 Linus 之手的 Git 绝对是每个学 CS 的童鞋必须掌握的神器之一。
GitHub:基于 Git 的代码托管平台。全世界最大的代码开源社区,大佬集聚地。
GNU Make:一款工程构建工具。善用 GNU Make 会让你养成代码模块化的习惯,同时也能让你熟悉一些大型工程的编译链接流程。
CMake:一款功能比 GNU Make 更为强大的构建工具,建议掌握 GNU Make 之后再加以学习。
LaTex:逼格提升 论文排版工具。
Docker:一款相较于虚拟机更轻量级的软件打包与环境部署工具。
实用工具箱:除了上面提到的这些在开发中使用频率极高的工具之外,我还收集了很多实用有趣的免费工具,例如一些下载工具、设计工具、学习网站等等。
Thesis:毕业论文 Word 写作教程。
私以为一本好的教材应当是以人为本的,而不是炫技式的理论堆砌。告诉读者“是什么”固然重要,但更好的应当是教材作者将其在这个领域深耕几十年的经验融汇进书中,向读者娓娓道来“为什么”以及未来应该“怎么做”。
你以为的开发 —— 在 IDE 里疯狂码代码数小时。
实际上的开发 —— 配环境配几天还没开始写代码。
如果你是 Mac 用户,那么你很幸运,这份指南 将会手把手地带你搭建起整套开发环境。如果你是 Windows 用户,在开源社区的努力下,你同样可以获得与其他平台类似的体验:Scoop。
另外大家可以参考一份灵感来自 6.NULL MIT-Missing-Semester 的 环境配置指南,重点在于终端的美化配置。此外还包括常用软件源(如 GitHub, Anaconda, PyPI 等)的加速与替换以及一些 IDE 的配置与激活教程。
服务器端的运维需要掌握 Linux(或者其他类 Unix 系统)的基本使用以及进程、设备、网络等系统相关的基本概念,小白可以参考中国科学技术大学 Linux 用户协会编写的《Linux 101》在线讲义。如果想深入学习系统运维相关的知识,可以参考 Aspects of System Administration 这门课程。
另外,如果需要学习某个具体的概念或工具,推荐一个非常不错的 GitHub 项目 DevOps-Guide,其中涵盖了非常多的运维方面的基础知识和教程,例如 Docker, Kubernetes, Linux, CI-CD, GitHub Actions 等等。
正如这章开头提到的,这份课程地图仅仅是一个仅供参考的课程规划,我作为一个临近毕业的本科生。深感自己没有权利也没有能力向别人宣扬“应该怎么学”。因此如果你觉得以下的课程分类与选择有不合理之处,我全盘接受,并深感抱歉。你可以在下一节定制属于你的课程地图
以下课程类别中除了含有 基础 和 入门 字眼的以外,并无明确的先后次序,大家只要满足某个课程的先修要求,完全可以根据自己的需要和喜好选择想要学习的课程。
作为大一新生,学好微积分线代是和写代码至少同等重要的事情,相信已经有无数的前人经验提到过这一点,但我还是要不厌其烦地再强调一遍:学好微积分线代真的很重要!你也许会吐槽这些东西岂不是考完就忘,那我觉得你是并没有把握住它们本质,对它们的理解还没有达到刻骨铭心的程度。如果觉得老师课上讲的内容晦涩难懂,不妨参考 MIT 的 Calculus Course 和 18.06: Linear Algebra 的课程 notes,至少于我而言,它帮助我深刻理解了微积分和线性代数的许多本质。顺道再安利一个油管数学网红 3Blue1Brown,他的频道有很多用生动形象的动画阐释数学本质内核的视频,兼具深度和广度,质量非常高。
作为计算机系的学生,及早了解一些信息论的基础知识,我觉得是大有裨益的。但大多信息论课程都面向高年级本科生甚至研究生,对新手极不友好。而 MIT 的 6.050J: Information theory and Entropy 这门课正是为大一新生量身定制的,几乎没有先修要求,涵盖了编码、压缩、通信、信息熵等等内容,非常有趣。
集合论、图论、概率论等等是算法推导与证明的重要工具,也是后续高阶数学课程的基础。但我觉得这类课程的讲授很容易落入理论化与形式化的窠臼,让课堂成为定理结论的堆砌,而无法使学生深刻把握理论的本质,进而造成学了就背,考了就忘的怪圈。如果能在理论教学中穿插算法运用实例,学生在拓展算法知识的同时也能窥见理论的力量和魅力。
UCB CS70 : discrete Math and probability theory 和 UCB CS126 : Probability theory 是 UC Berkeley 的概率论课程,前者覆盖了离散数学和概率论基础,后者则涉及随机过程以及深入的理论内容。两者都非常注重理论和实践的结合,有丰富的算法实际运用实例,后者还有大量的 Python 编程作业来让学生运用概率论的知识解决实际问题。
作为计算机系的学生,培养计算思维是很重要的,实际问题的建模、离散化,计算机的模拟、分析,是一项很重要的能力。而这两年开始风靡的,由 MIT 打造的 Julia 编程语言以其 C 一样的速度和 Python 一样友好的语法在数值计算领域有一统天下之势,MIT 的许多数学课程也开始用 Julia 作为教学工具,把艰深的数学理论用直观清晰的代码展示出来。
ComputationalThinking 是 MIT 开设的一门计算思维入门课,所有课程内容全部开源,可以在课程网站直接访问。这门课利用 Julia 编程语言,在图像处理、社会科学与数据科学、气候学建模三个 topic 下带领学生理解算法、数学建模、数据分析、交互设计、图例展示,让学生体验计算与科学的美妙结合。内容虽然不难,但给我最深刻的感受就是,科学的魅力并不是故弄玄虚的艰深理论,不是诘屈聱牙的术语行话,而是用直观生动的案例,用简练深刻的语言,让每个普通人都能理解。
上完上面的体验课之后,如果意犹未尽的话,不妨试试 MIT 的 18.330 : Introduction to numerical analysis,这门课的编程作业同样会用 Julia 编程语言,不过难度和深度上都上了一个台阶。内容涉及了浮点编码、Root finding、线性系统、微分方程等等方面,整门课的主旨就是让你利用离散化的计算机表示去估计和逼近一个数学上连续的概念。这门课的教授还专门撰写了一本配套的开源教材 Fundamentals of Numerical Computation,里面附有丰富的 Julia 代码实例和严谨的公式推导。
如果你还意犹未尽的话,还有 MIT 的数值分析研究生课程 18.335: Introduction to numerical method 供你参考。
如果世间万物的运动发展都能用方程来刻画和描述,这是一件多么酷的事情呀!虽然几乎任何一所学校的 CS 培养方案中都没有微分方程相关的必修课程,但我还是觉得掌握它会赋予你一个新的视角来审视这个世界。
由于微分方程中往往会用到很多复变函数的知识,所以大家可以参考 MIT18.04: Complex variables functions 的课程 notes 来补齐先修知识。
MIT18.03: differential equations 主要覆盖了常微分方程的求解,在此基础之上 MIT18.152: Partial differential equations 则会深入偏微分方程的建模与求解。掌握了微分方程这一有力工具,相信对于你的实际问题的建模能力以及从众多噪声变量中把握本质的直觉都会有很大帮助。
作为计算机系的学生,我经常听到数学无用论的论断,对此我不敢苟同但也无权反对,但若凡事都硬要争出个有用和无用的区别来,倒也着实无趣,因此下面这些面向高年级甚至研究生的数学课程,大家按兴趣自取所需。
Standford EE364A: Convex Optimization
MIT18.650: Statistics for Applications
Languages are tools, you choose the right tool to do the right thing. Since there's no universally perfect tool, there's no universally perfect language.
作为计算机系的学生,了解一些基础的电路知识,感受从传感器收集数据到数据分析再到算法预测整条流水线,对于后续知识的学习以及计算思维的培养还是很有帮助的。EE16A&B: Designing Information Devices and Systems I&II 是伯克利 EE 学生的大一入门课,其中 EE16A 注重通过电路从实际环境中收集和分析数据,而 EE16B 则侧重从这些收集到的数据进行分析并做出预测行为。
信号与系统是一门我觉得非常值得一上的课,最初学它只是为了满足我对傅里叶变换的好奇,但学完之后我才不禁感叹,傅立叶变换给我提供了一个全新的视角去看待这个世界,就如同微分方程一样,让你沉浸在用数学去精确描绘和刻画这个世界的优雅与神奇之中。
MIT 6.003: signal and systems 提供了全部的课程录影、书面作业以及答案。也可以去看这门课的远古版本
而 UCB EE120: Signal and Systems 关于傅立叶变换的 notes 写得非常好,并且提供了6 个非常有趣的 Python 编程作业,让你实践中运用信号与系统的理论与算法。
算法是计算机科学的核心,也是几乎一切专业课程的基础。如何将实际问题通过数学抽象转化为算法问题,并选用合适的数据结构在时间和内存大小的限制下将其解决是算法课的永恒主题。如果你受够了老师的照本宣科,那么我强烈推荐伯克利的 UCB CS61B: Data Structures and Algorithms 和普林斯顿的 Coursera: Algorithms I & II,这两门课的都讲得深入浅出并且会有丰富且有趣的编程实验将理论与知识结合起来。
以上两门课程都是基于 Java 语言,如果你想学习 C/C++ 描述的版本,可以参考斯坦福的数据结构与基础算法课程 Stanford CS106B/X: Programming Abstractions。偏好 Python 的同学可以学习 MIT 的算法入门课 MIT 6.006: Introduction to Algorithms
对一些更高级的算法以及 NP 问题感兴趣的同学可以学习伯克利的算法设计与分析课程 UCB CS170: Efficient Algorithms and Intractable Problems 或者 MIT 的高阶算法 MIT 6.046: Design and Analysis of Algorithms。
一份“能跑”的代码,和一份高质量的工业级代码是有本质区别的。因此我非常推荐低年级的同学学习一下 MIT 6.031: Software Construction 这门课,它会以 Java 语言为基础,以丰富细致的阅读材料和精心设计的编程练习传授如何编写不易出 bug、简明易懂、易于维护修改的高质量代码。大到宏观数据结构设计,小到如何写注释,遵循这些前人总结的细节和经验,对于你此后的编程生涯大有裨益。
当然,如果你想系统性地上一门软件工程的课程,那我推荐的是伯克利的 UCB CS169: software engineering。但需要提醒的是,和大多学校(包括贵校)的软件工程课程不同,这门课不会涉及传统的 design and document 模式,即强调各种类图、流程图及文档设计,而是采用近些年流行起来的小团队快速迭代 Agile Develepment 开发模式以及利用云平台的 Software as a service 服务模式。
从小我就一直听说,计算机的世界是由 01 构成的,我不理解但大受震撼。如果你的内心也怀有这份好奇,不妨花一到两个月的时间学习 Coursera: Nand2Tetris 这门无门槛的计算机课程。这门麻雀虽小五脏俱全的课程会从 01 开始让你亲手造出一台计算机,并在上面运行俄罗斯方块小游戏。一门课里涵盖了编译、虚拟机、汇编、体系结构、数字电路、逻辑门等等从上至下、从软至硬的各类知识,非常全面。难度上也是通过精心的设计,略去了众多现代计算机复杂的细节,提取出了最核心本质的东西,力图让每个人都能理解。在低年级,如果就能从宏观上建立对整个计算机体系的鸟瞰图,是大有裨益的。
当然,如果想深入现代计算机体系结构的复杂细节,还得上一门大学本科难度的课程 UCB CS61C: Great Ideas in Computer Architecture。UC Berkeley 作为 RISC-V 架构的发源地,在体系结构领域算得上首屈一指。其课程非常注重实践,你会在 Project 中手写汇编构造神经网络,从零开始搭建一个 CPU,这些实践都会让你对计算机体系结构有更为深入的理解,而不是仅停留于“取指译码执行访存写回”的单调背诵里。
计算机系统是一个庞杂而深刻的主题,在深入学习某个细分领域之前,对各个领域有一个宏观概念性的理解,对一些通用性的设计原则有所知晓,会让你在之后的深入学习中不断强化一些最为核心乃至哲学的概念,而不会桎梏于复杂的内部细节和各种 trick。因为在我看来,学习系统最关键的还是想让你领悟到这些最核心的东西,从而能够设计和实现出属于自己的系统。
MIT6.033: System Engineering 是 MIT 的系统入门课,主题涉及了操作系统、网络、分布式和系统安全,除了知识点的传授外,这门课还会讲授一些写作和表达上的技巧,让你学会如何设计并向别人介绍和分析自己的系统。这本书配套的教材 Principles of Computer System Design: An Introduction 也写得非常好,推荐大家阅读。
CMU 15-213: Introduction to Computer System 是 CMU 的系统入门课,内容覆盖了体系结构、操作系统、链接、并行、网络等等,兼具广度和深度,配套的教材 Computer Systems: A Programmer's Perspective 也是质量极高,强烈建议阅读。
没有什么能比自己写个内核更能加深对操作系统的理解了。
操作系统作为各类纷繁复杂的底层硬件虚拟化出一套规范优雅的抽象,给所有应用软件提供丰富的功能支持。了解操作系统的设计原则和内部原理对于一个不满足于当调包侠的程序员来说是大有裨益的。出于对操作系统的热爱,我上过国内外很多操作系统课程,它们各有侧重和优劣,大家可以根据兴趣各取所需。
MIT 6.S081: Operating System Engineering,MIT 著名 PDOS 实验室出品,11 个 Project 让你在一个实现非常优雅的类Unix操作系统xv6上增加各类功能模块。这门课也让我深刻认识到,做系统不是靠 PPT 念出来的,是得几万行代码一点点累起来的。
UCB CS162: Operating System,伯克利的操作系统课,采用和 Stanford 同样的 Project —— 一个教学用操作系统 Pintos。我作为北京大学2022年和2023年春季学期操作系统实验班的助教,引入并改善了这个 Project,课程资源也会全部开源,具体参见课程网站。
NJU: Operating System Design and Implementation,南京大学的蒋炎岩老师开设的操作系统课程。蒋老师以其独到的系统视角结合丰富的代码示例将众多操作系统的概念讲得深入浅出,此外这门课的全部课程内容都是中文的,非常方便大家学习。
HIT OS: Operating System,哈尔滨工业大学的李治军老师开设的中文操作系统课程。李老师的课程基于 Linux 0.11 源码,十分注重代码实践,并站在学生视角将操作系统的来龙去脉娓娓道来。
想必这两年各类 CS 讲座里最常听到的话就是“摩尔定律正在走向终结”,此话不假,当单核能力达到上限时,多核乃至众核架构如日中天。硬件的变化带来的是上层编程逻辑的适应与改变,要想充分利用硬件性能,编写并行程序几乎成了程序员的必备技能。与此同时,深度学习的兴起对计算机算力与存储的要求都达到了前所未有的高度,大规模集群的部署和优化也成为热门技术话题。
CMU 15-418/Stanford CS149: Parallel Computing
不知道你当年选择计算机是不是因为怀着一个中二的黑客梦想,但现实却是成为黑客道阻且长。
UCB CS161: Computer Security 是伯克利的系统安全课程,会涵盖栈攻击、密码学、网站安全、网络安全等等内容。
ASU CSE365: Introduction to Cybersecurity 亚利桑那州立大学的 Web 安全课程,主要涉及注入、汇编与密码学的内容。
ASU CSE466: Computer Systems Security 亚利桑那州立大学的系统安全课程,涉及内容全面。门槛较高,需要对 Linux, C 与 Python 充分熟悉。
掌握这些理论知识之后,还需要在实践中培养和锻炼这些“黑客素养”。CTF 夺旗赛是一项比较热门的系统安全比赛,赛题中会融会贯通地考察你对计算机各个领域知识的理解和运用。北大今年也成功举办了第 0 届和第 1 届,鼓励大家后期踊跃参与,在实践中提高自己。下面列举一些我平时学习(摸鱼)用到的资源:
没有什么能比自己写个 TCP/IP 协议栈更能加深对计算机网络的理解了。
大名鼎鼎的 Stanford CS144: Computer Network,8 个 Project 带你实现整个 TCP/IP 协议栈。
如果你只是想在理论上对计算机网络有所了解,那么推荐计网著名教材《自顶向下方法》的配套学习资源 Computer Networking: A Top-Down Approach。
没有什么能比自己写个关系型数据库更能加深对数据库系统的理解了。
CMU 的著名数据库神课 CMU 15-445: Introduction to Database System 会通过 4 个 Project 带你为一个用于教学的关系型数据库 bustub 添加各种功能。实验的评测框架也免费开源了,非常适合大家自学。此外课程实验会用到 C++11 的众多新特性,也是一个锻炼 C++ 代码能力的好机会。
Berkeley 作为著名开源数据库 postgres 的发源地也不遑多让,UCB CS186: Introduction to Database System 会让你用 Java 语言实现一个支持 SQL 并发查询、B+ 树索引和故障恢复的关系型数据库。
没有什么能比自己写个编译器更能加深对编译器的理解了。
Stanford CS143: Compilers 带你手写编译器。
前后端开发很少在计算机的培养方案里被重视,但其实掌握这项技能还是好处多多的,例如搭建自己的个人主页,抑或是给自己的课程项目做一个精彩的展示网页。
Stanford CS142: Web Applications
其实数据科学和机器学习与深度学习有着很紧密的联系,但可能更侧重于实践。Berkeley 的 UCB Data100: Principles and Techniques of Data Science 通过丰富的编程练习让你在实践中掌握各类数据分析工具和算法,并带领你体验从海量的数据集中提取出想要的结果,并对未来的数据或用户的行为做出相应的预测。但这只是一门基础课,如果想学习工业级别的数据挖掘与分析技术,可以尝试 Stanford 的大数据挖掘课程 CS246: Mining Massive Data Sets。
近十年人工智能应该算是计算机界最火爆的领域。如果你不满足于整日听各路媒体争相报道人工智能相关的进展,而想真正一探究竟,那么非常推荐学习 Harvard 神课 CS50 系列的人工智能课程 Harvard CS50: Introduction to AI with Python。课程短小精悍,覆盖了传统人工智能领域的几大分支,并配有丰富有趣的 Python 编程练习来巩固你对人工智能算法的理解。美中不足的是这门课因为面向在线自学者的缘故内容较为精简,并且不会涉及特别深入的数学理论,如果想要系统深入地学习还需要一门本科生难度的课程,例如 Berkeley 的 UCB CS188: Introduction to Artificial Intelligence。这门课的 Project 复刻了经典游戏糖豆人,让你运用人工智能算法玩游戏,非常有趣。
机器学习领域近些年最重要的进展就是发展出了基于神经网络的深度学习分支,但其实很多基于统计学习的算法依然在数据分析领域有着广泛的应用。如果你之前从未接触过机器学习的相关知识,而且不想一开始就陷入艰深晦涩的数学证明,那么不妨先从 Andrew Ng (吴恩达)的 Coursera: Machine Learning 学起。这门课在机器学习领域基本无人不晓,吴恩达以其深厚的理论功底和出色的表达能力把很多艰深的算法讲得深入浅出,并且非常实用。其配套的作业也是质量相当上乘,可以帮助你快速入门。
但上过这门课只能让你从宏观上对机器学习这一领域有一定了解,如果想真正理解那些“神奇”算法背后的数学原理甚至从事相关领域的科研工作,那么还需要一门更“数学”的课程,例如 Stanford CS229: Machine Learning 或者 UCB CS189: Introduction to Machine Learning。
前几年 AlphaGo 的大热让深度学习进入了大众的视野,不少大学甚至专门成立了相关专业。很多计算机的其他领域也会借助深度学习的技术来做研究,因此基本不管你干啥多少都会接触到一些神经网络、深度学习相关的技术需求。如果想快速入门,同样推荐 Andrew Ng (吴恩达)的 Coursera: Deep Learning,质量无需多言,Coursera 上罕见的满分课程。此外如果你觉得英文课程学习起来有难度,推荐李宏毅老师的 国立台湾大学:机器学习 课程。这门课打着机器学习的名号,却囊括了深度学习领域的几乎所有方向,非常全面,很适合你从宏观上对这个领域有一个大致的了解。而且老师本人也非常幽默,课堂金句频出。
当然因为深度学习领域发展非常迅速,已经拥有了众多研究分支,如果想要进一步深入,可以按需学习下面罗列的代表课程,
UMich EECS 498-007 / 598-005: Deep Learning for Computer Vision
Stanford CS231n: CNN for Visual Recognition
Stanford CS224n: Natural Language Processing
Stanford CS224w: Machine Learning with Graphs
UCB CS285: Deep Reinforcement Learning
授人以鱼不如授人以渔。
以上的课程规划难免带有强烈的个人偏好,不一定适合所有人,更多是起到抛砖引玉的作用。如果你想挑选自己感兴趣的方向和内容加以学习,可以参考我在下面列出来的资源。
This is Stanford's Web Application course covers HTML, CSS, JavaScript, ReactJs, NodeJS, ExpressJS, Web Security, and more. Eight projects will enhance your web development skills in practice.
This is Stanford's Web Application course covers HTML, CSS, JavaScript, ReactJs, NodeJS, ExpressJS, Web Security, and more. Eight projects will enhance your web development skills in practice.
This course provides a comprehensive but concise introduction to the best practices of React front-end development and React Native mobile development. It focuses on the latest versions of React and React Native and is updated every semester. It is a valuable resource for tackling the complexities of front-end development.
The course also offers a good training ground. Be prepared for a significant workload throughout the semester. The techniques and knowledge points involved in the homework will be explained in class, but code won't be written hand by hand (I personally think that hand-holding code writing is very inefficient, and most courses on Udemy are of this type). As this isn't a hand-holding course, if you are unsure about how to write React code when doing homework, I recommend spending extra time carefully reading the relevant chapters on react.dev before diving in. The starter code also provides you with a great starting point, saving you from coping with Node.js environment settings.
Although this course doesn't require prior knowledge of Javascript/HTML/CSS, the classroom introduction to syntax is relatively limited. It's recommended to frequently consult resources and ask questions when encountering syntax issues during learning and coding.
This course also includes an introduction to and practices for Dialog Flow, a ChatBot development tool by Google. You can also find content related to UX development (on the practical side) in this course.
All course materials and assignments are open-source, but you will need to request an X-CS571-ID header from the instructor, Cole Nelson (ctnelson2@wisc.edu). The header will be necessary for API request. When sending an email, it is advisable to include a brief self-introduction. It is unclear whether the instructor is willing to give everyone an ID. If you got turned down, please raise an issue for this GitHub repo.
This course provides a comprehensive but concise introduction to the best practices of React front-end development and React Native mobile development. It focuses on the latest versions of React and React Native and is updated every semester. It is a valuable resource for tackling the complexities of front-end development.
The course also offers a good training ground. Be prepared for a significant workload throughout the semester. The techniques and knowledge points involved in the homework will be explained in class, but code won't be written hand by hand (I personally think that hand-holding code writing is very inefficient, and most courses on Udemy are of this type). As this isn't a hand-holding course, if you are unsure about how to write React code when doing homework, I recommend spending extra time carefully reading the relevant chapters on react.dev before diving in. The starter code also provides you with a great starting point, saving you from coping with Node.js environment settings.
Although this course doesn't require prior knowledge of Javascript/HTML/CSS, the classroom introduction to syntax is relatively limited. It's recommended to frequently consult resources and ask questions when encountering syntax issues during learning and coding.
This course also includes an introduction to and practices for Dialog Flow, a ChatBot development tool by Google. You can also find content related to UX development (on the practical side) in this course.
All course materials and assignments are open-source, but you will need to request an X-CS571-ID header from the instructor, Cole Nelson (ctnelson2@wisc.edu). The header will be necessary for API request. When sending an email, it is advisable to include a brief self-introduction. It is unclear whether the instructor is willing to give everyone an ID. If you got turned down, please raise an issue for this GitHub repo.
This course serves as an introduction to modern web application development with JavaScript. The main focus is on building single page applications with ReactJS that use REST APIs built with Node.js. The course also contains a section on GraphQL, a modern alternative to REST APIs.
The course covers testing, configuration and environment management, and the use of MongoDB for storing the application’s data.
This course serves as an introduction to modern web application development with JavaScript. The main focus is on building single page applications with ReactJS that use REST APIs built with Node.js. The course also contains a section on GraphQL, a modern alternative to REST APIs.
The course covers testing, configuration and environment management, and the use of MongoDB for storing the application’s data.
Independent Activities Period (IAP) is a four-week period in January during which faculty and students are freed from the rigors of regularly scheduled classes for flexible teaching and learning and for independent study and research, and that's how this web development course was born.
Within a month, you will master the core content of designing, building, beautifying, and publishing a website from scratch, basically covering full-stack web development. If you don't need to learn web development systematically, but just want to add it to your toolkit out of interest, then this class will be perfect for you.
Independent Activities Period (IAP) is a four-week period in January during which faculty and students are freed from the rigors of regularly scheduled classes for flexible teaching and learning and for independent study and research, and that's how this web development course was born.
Within a month, you will master the core content of designing, building, beautifying, and publishing a website from scratch, basically covering full-stack web development. If you don't need to learn web development systematically, but just want to add it to your toolkit out of interest, then this class will be perfect for you.

The English version is still under development, please check this issue if you want to contribute.
This is a self-learning guide to computer science, and a memento of my three years of self-learning at university.
It is also a gift to the young students at Peking University. It would be a great encouragement and comfort to me if this book could be of even the slightest help to you in your college life.
The book is currently organized to include the following sections (if you have other good suggestions, or would like to join the ranks of contributors, please feel free to email zhongyinmin@pku.edu.cn or ask questions in the issue).
In my freshman year, I was a novice who knew nothing about computers. I installed a giant IDE Visual Studio and fight with OJ every day. With my high school maths background, I did pretty well in maths courses, but I felt struggled to learn courses in my major. When it came to programming, all I could do was open up that clunky IDE, create a new project that I didn't know exactly what it was for, and then cin, cout, for loops, and then CE, RE, WA loops. I was in a state where I was desperately trying to learn well but I didn't know how to learn. I listened carefully in class but I couldn't solve the homework problems. I spent almost all my spare time doing the homework after class, but the results were disappointing. I still retain the source code of the project for Introduction to Computing course —— a single 1200-line C++ file with no header files, no class abstraction, no unit tests, no makefile, no version control. The only good thing is that it can run, the disadvantage is the complement of "can run". For a while I wondered if I wasn't cut out for computer science, as all my childhood imaginings of geekiness had been completely ruined by my first semester's experience.
It all turned around during the winter break of my freshman year, when I had a hankering to learn Python. I overheard someone recommend CS61A, a freshman introductory course at UC Berkeley on Python. I'll never forget that day, when I opened the CS61A course website. It was like Columbus discovering a new continent, and I opened the door to a new world.
I finished the course in 3 weeks and for the first time I felt that CS could be so fulfilling and interesting, and I was shocked that there existed such a great course in the world.
To avoid any suspicion of pandering to foreign courses, I will tell you about my experience of studying CS61A from the perspective of a pure student.
Course website developed by course staffs: The course website integrates all the course resources into one, with a well organised course schedule, links to all slides, recorded videos and homework, detailed and clear syllabus, list of exams and solutions from previous years. Aesthetics aside, this website is so convenient for students.
Textbook written by course instructor: The course instructor has adapted the classic MIT textbook Structure and Interpretation of Computer Programs (SICP) into Python (the original textbook was based on Scheme). This is a great way to ensure that the classroom content is consistent with the textbook, while adding more details. The entire book is open source and can be read directly online.
Various, comprehensive and interesting homework: There are 14 labs to reinforce the knowledge gained in class, 10 homework assignments to practice, and 4 projects each with thousands of lines of code, all with well-organized skeleton code and babysitting instructions. Unlike the old-school OJ and Word document assignments, each lab/homework/project has a detailed handout document, fully automated grading scripts, and CS61A staffs have even developed an automated assignment submission and grading system. Of course, one might say "How much can you learn from a project where most of code are written by your teaching assistants?" . For someone who is new to CS and even stumbling over installing Python, this well-developed skeleton code allows students to focus on reinforcing the core knowledge they've learned in class, but also gives them a sense of achievement that they already can make a little game despite of learning Python only for a month. It also gives them the opportunity to read and learn from other people's high quality code so that they can reuse it later. I think in the freshman year, this kind of skeleton code is absolutely beneficial. The only bad thing perhaps is for the instructors and teaching assistants, as developing such assignments can conceivably require a considerable time commitment.
Weekly discussion sessions: The teaching assistants will explain the difficult knowledge in class and add some supplementary materials which may not be covered in class. Also, there will be exercises from exams of previous years. All the exercises are written in LaTeX with solutions.
In CS61A, You don't need any prerequesites about CS at all. You just need to pay attention, spend time and work hard. The feeling that you do not know what to do, that you are not getting anything in return for all the time you put in, is gone. It suited me so well that I fell in love with self-learning.
Imagine that if someone could chew up the hard knowledge and present it to you in a vivid and straightforward way, with so many fancy and varied projects to reinforce your theoretical knowledge, you'd think they were really trying their best to make you fully grasp the course, and it was even an insult to the course builders not to learn it well.
If you think I'm exaggerating, start with CS61A, because it's where my dreams began.
In the 2020 Fall semester, I worked as a teaching assistant for the class Introduction to Computer Systems at Peking University. At that time, I had been studying totally on my own for over a year. I enjoyed this style of learning immensely. To share this joy, I have made a CS Self-learning Materials List for students in my seminar. It was purely on a whim at the time, as I wouldn't dare to encourage my students to skip classes and study on their own.
But after another year of maintenance, the list has become quite comprehensive, covering most of the courses in Computer Science, Artificial Intelligence and Soft Engineering, and I have built separate repositories for each course, summarising the self-learning materials that I used.
In my last college year, when I opened up my curriculum book, I realized that it was already a subset of my self-learning list. By then, it was only two and a half years after I had started my self-learning journey. Then, a bold idea came to my mind: perhaps I could create a self-learning book, write down the difficulty I encountered and the interest I found during these years of self-learning, hoping to make it easy for students who may also enjoy self-learning to start their wonderful self-learning journey.
If you can build up the whole CS foundation in less than three years, have relatively solid mathematical skills and coding ability, experience dozens of projects with thousands of lines of code, master at least C/C++/Java/JS/Python/Go/Rust and other mainstream programming languages, have a good understanding of algorithms, circuits, architectures, networks, operating systems, compilers, artificial intelligence, machine learning, computer vision, natural language processing, reinforcement learning, cryptography, information theory, game theory, numerical analysis, statistics, distributed systems, parallel computing, database systems, computer graphics, web development, cloud computing, supercomputing etc. I think you will be confident enough to choose the area you are interested in, and you will be quite competitive in both industry and academia.
I firmly believe that if you have read to this line, you do not lack the ability and committment to learn CS well, you just need a good teacher to teach you a good course. And I will try my best to pick such courses for you, based on my three years of experience.
For me, the biggest advantage of self-learning is that I can adjust the pace of learning entirely according to my own progress. For difficult parts, I can watch the videos over and over again, Google it online and ask questions on StackOverflow until I have it all figured out. For those that I mastered relatively quickly, I could skip them at twice or even three times the speed.
Another great thing about self-learning is that you can learn from different perspectives. I have taken core courses such as architectures, networking, operating systems, and compilers from different universities. Different instructors may have different views on the same knowledge, which will broaden your horizon.
A third advantage of self-learning is that you do not need to go to the class, listening to the boring lectures.
Of course, as a big fan of self-learning, I have to admit that it has its disadvantages.
The first is the difficulty of communication. I'm actually a very keen questioner, and I like to follow up all the points I don't understand. But when you're facing a screen and you hear a teacher talking about something you don't understand, you can't go to the other end of the network and ask him or her for clarification. I try to mitigate this by thinking independently and making good use of Google, but it would be great to have a few friends to study together. You can refer to README for more information on participating a community group.
The second thing is that these courses are basically in English. From the videos to the slides to the assignments, all in English. You may struggle at first, but I think it's a challenge that if you overcome, it will be extremely rewarding. Because at the moment, as reluctant as I am, I have to admit that in computer science, a lot of high quality documentation, forums and websites are all in English.
The third, and I think the most difficult one, is self-discipline. Because have no DDL can sometimes be a really scary thing, especially when you get deeper, many foreign courses are quite difficult. You have to be self-driven enough to force yourself to settle down, read dozens of pages of Project Handout, understand thousands of lines of skeleton code and endure hours of debugging time. With no credits, no grades, no teachers, no classmates, just one belief - that you are getting better.
As I said in the beginning, anyone who is interested in learning computer science on their own can refer to this book. If you already have some basic skills and are just interested in a particular area, you can selectively pick and choose what you are interested in to study. Of course, if you are a novice who knows nothing about computers like I did back then, and just begin your college journey, I hope this book will be your cheat sheet to get the knowledge and skills you need in the least amount of time. In a way, this book is more like a course search engine ordered according to my experience, helping you to learn high quality CS courses from the world's top universities without leaving home.
Of course, as an undergraduate student who has not yet graduated, I feel that I am not in a position nor have the right to preach one way of learning. I just hope that this material will help those who are also self-motivated and persistent to gain a richer, more varied and satisfying college life.
I would like to express my sincere gratitude to all the professors who have made their courses public for free. These courses are the culmination of decades of their teaching careers, and they have chosen to selflessly make such a high quality CS education available to all. Without them, my university life would not have been as fulfilling and enjoyable. Many of the professors would even reply with hundreds of words in length after I had sent them a thank you email, which really touched me beyond words. They also inspired me all the time that if decide to do something, do it with all heart and soul.
There is a limit to how much one person can do, and this book was written by me under a heavy research schedule, so there are inevitably imperfections. In addition, as I work in the area of systems, many of the courses focus on systems, and there is relatively little content related to advanced mathematics, computing theory, and advanced algorithms. If any of you would like to share your self-learning experience and resources in other areas, you can directly initiate a Pull Request in the project, or feel free to contact me by email (zhongyinmin@pku.edu.cn).

The English version is still under development, please check this issue if you want to contribute.
This is a self-learning guide to computer science, and a memento of my three years of self-learning at university.
It is also a gift to the young students at Peking University. It would be a great encouragement and comfort to me if this book could be of even the slightest help to you in your college life.
The book is currently organized to include the following sections (if you have other good suggestions, or would like to join the ranks of contributors, please feel free to email zhongyinmin@pku.edu.cn or ask questions in the issue).
In my freshman year, I was a novice who knew nothing about computers. I installed a giant IDE Visual Studio and fight with OJ every day. With my high school maths background, I did pretty well in maths courses, but I felt struggled to learn courses in my major. When it came to programming, all I could do was open up that clunky IDE, create a new project that I didn't know exactly what it was for, and then cin, cout, for loops, and then CE, RE, WA loops. I was in a state where I was desperately trying to learn well but I didn't know how to learn. I listened carefully in class but I couldn't solve the homework problems. I spent almost all my spare time doing the homework after class, but the results were disappointing. I still retain the source code of the project for Introduction to Computing course —— a single 1200-line C++ file with no header files, no class abstraction, no unit tests, no makefile, no version control. The only good thing is that it can run, the disadvantage is the complement of "can run". For a while I wondered if I wasn't cut out for computer science, as all my childhood imaginings of geekiness had been completely ruined by my first semester's experience.
It all turned around during the winter break of my freshman year, when I had a hankering to learn Python. I overheard someone recommend CS61A, a freshman introductory course at UC Berkeley on Python. I'll never forget that day, when I opened the CS61A course website. It was like Columbus discovering a new continent, and I opened the door to a new world.
I finished the course in 3 weeks and for the first time I felt that CS could be so fulfilling and interesting, and I was shocked that there existed such a great course in the world.
To avoid any suspicion of pandering to foreign courses, I will tell you about my experience of studying CS61A from the perspective of a pure student.
Course website developed by course staffs: The course website integrates all the course resources into one, with a well organised course schedule, links to all slides, recorded videos and homework, detailed and clear syllabus, list of exams and solutions from previous years. Aesthetics aside, this website is so convenient for students.
Textbook written by course instructor: The course instructor has adapted the classic MIT textbook Structure and Interpretation of Computer Programs (SICP) into Python (the original textbook was based on Scheme). This is a great way to ensure that the classroom content is consistent with the textbook, while adding more details. The entire book is open source and can be read directly online.
Various, comprehensive and interesting homework: There are 14 labs to reinforce the knowledge gained in class, 10 homework assignments to practice, and 4 projects each with thousands of lines of code, all with well-organized skeleton code and babysitting instructions. Unlike the old-school OJ and Word document assignments, each lab/homework/project has a detailed handout document, fully automated grading scripts, and CS61A staffs have even developed an automated assignment submission and grading system. Of course, one might say "How much can you learn from a project where most of code are written by your teaching assistants?" . For someone who is new to CS and even stumbling over installing Python, this well-developed skeleton code allows students to focus on reinforcing the core knowledge they've learned in class, but also gives them a sense of achievement that they already can make a little game despite of learning Python only for a month. It also gives them the opportunity to read and learn from other people's high quality code so that they can reuse it later. I think in the freshman year, this kind of skeleton code is absolutely beneficial. The only bad thing perhaps is for the instructors and teaching assistants, as developing such assignments can conceivably require a considerable time commitment.
Weekly discussion sessions: The teaching assistants will explain the difficult knowledge in class and add some supplementary materials which may not be covered in class. Also, there will be exercises from exams of previous years. All the exercises are written in LaTeX with solutions.
In CS61A, You don't need any prerequesites about CS at all. You just need to pay attention, spend time and work hard. The feeling that you do not know what to do, that you are not getting anything in return for all the time you put in, is gone. It suited me so well that I fell in love with self-learning.
Imagine that if someone could chew up the hard knowledge and present it to you in a vivid and straightforward way, with so many fancy and varied projects to reinforce your theoretical knowledge, you'd think they were really trying their best to make you fully grasp the course, and it was even an insult to the course builders not to learn it well.
If you think I'm exaggerating, start with CS61A, because it's where my dreams began.
In the 2020 Fall semester, I worked as a teaching assistant for the class Introduction to Computer Systems at Peking University. At that time, I had been studying totally on my own for over a year. I enjoyed this style of learning immensely. To share this joy, I have made a CS Self-learning Materials List for students in my seminar. It was purely on a whim at the time, as I wouldn't dare to encourage my students to skip classes and study on their own.
But after another year of maintenance, the list has become quite comprehensive, covering most of the courses in Computer Science, Artificial Intelligence and Soft Engineering, and I have built separate repositories for each course, summarising the self-learning materials that I used.
In my last college year, when I opened up my curriculum book, I realized that it was already a subset of my self-learning list. By then, it was only two and a half years after I had started my self-learning journey. Then, a bold idea came to my mind: perhaps I could create a self-learning book, write down the difficulty I encountered and the interest I found during these years of self-learning, hoping to make it easy for students who may also enjoy self-learning to start their wonderful self-learning journey.
If you can build up the whole CS foundation in less than three years, have relatively solid mathematical skills and coding ability, experience dozens of projects with thousands of lines of code, master at least C/C++/Java/JS/Python/Go/Rust and other mainstream programming languages, have a good understanding of algorithms, circuits, architectures, networks, operating systems, compilers, artificial intelligence, machine learning, computer vision, natural language processing, reinforcement learning, cryptography, information theory, game theory, numerical analysis, statistics, distributed systems, parallel computing, database systems, computer graphics, web development, cloud computing, supercomputing etc. I think you will be confident enough to choose the area you are interested in, and you will be quite competitive in both industry and academia.
I firmly believe that if you have read to this line, you do not lack the ability and committment to learn CS well, you just need a good teacher to teach you a good course. And I will try my best to pick such courses for you, based on my three years of experience.
For me, the biggest advantage of self-learning is that I can adjust the pace of learning entirely according to my own progress. For difficult parts, I can watch the videos over and over again, Google it online and ask questions on StackOverflow until I have it all figured out. For those that I mastered relatively quickly, I could skip them at twice or even three times the speed.
Another great thing about self-learning is that you can learn from different perspectives. I have taken core courses such as architectures, networking, operating systems, and compilers from different universities. Different instructors may have different views on the same knowledge, which will broaden your horizon.
A third advantage of self-learning is that you do not need to go to the class, listening to the boring lectures.
Of course, as a big fan of self-learning, I have to admit that it has its disadvantages.
The first is the difficulty of communication. I'm actually a very keen questioner, and I like to follow up all the points I don't understand. But when you're facing a screen and you hear a teacher talking about something you don't understand, you can't go to the other end of the network and ask him or her for clarification. I try to mitigate this by thinking independently and making good use of Google, but it would be great to have a few friends to study together. You can refer to README for more information on participating a community group.
The second thing is that these courses are basically in English. From the videos to the slides to the assignments, all in English. You may struggle at first, but I think it's a challenge that if you overcome, it will be extremely rewarding. Because at the moment, as reluctant as I am, I have to admit that in computer science, a lot of high quality documentation, forums and websites are all in English.
The third, and I think the most difficult one, is self-discipline. Because have no DDL can sometimes be a really scary thing, especially when you get deeper, many foreign courses are quite difficult. You have to be self-driven enough to force yourself to settle down, read dozens of pages of Project Handout, understand thousands of lines of skeleton code and endure hours of debugging time. With no credits, no grades, no teachers, no classmates, just one belief - that you are getting better.
As I said in the beginning, anyone who is interested in learning computer science on their own can refer to this book. If you already have some basic skills and are just interested in a particular area, you can selectively pick and choose what you are interested in to study. Of course, if you are a novice who knows nothing about computers like I did back then, and just begin your college journey, I hope this book will be your cheat sheet to get the knowledge and skills you need in the least amount of time. In a way, this book is more like a course search engine ordered according to my experience, helping you to learn high quality CS courses from the world's top universities without leaving home.
Of course, as an undergraduate student who has not yet graduated, I feel that I am not in a position nor have the right to preach one way of learning. I just hope that this material will help those who are also self-motivated and persistent to gain a richer, more varied and satisfying college life.
I would like to express my sincere gratitude to all the professors who have made their courses public for free. These courses are the culmination of decades of their teaching careers, and they have chosen to selflessly make such a high quality CS education available to all. Without them, my university life would not have been as fulfilling and enjoyable. Many of the professors would even reply with hundreds of words in length after I had sent them a thank you email, which really touched me beyond words. They also inspired me all the time that if decide to do something, do it with all heart and soul.
There is a limit to how much one person can do, and this book was written by me under a heavy research schedule, so there are inevitably imperfections. In addition, as I work in the area of systems, many of the courses focus on systems, and there is relatively little content related to advanced mathematics, computing theory, and advanced algorithms. If any of you would like to share your self-learning experience and resources in other areas, you can directly initiate a Pull Request in the project, or feel free to contact me by email (zhongyinmin@pku.edu.cn).
伯克利的人工智能入门课,课程 notes 写得非常深入浅出,基本不需要观看课程视频。课程内容的安排基本按照人工智能的经典教材 Artificial intelligence: A Modern Approach 的章节顺序,覆盖了搜索剪枝、约束满足问题、马尔可夫决策过程、强化学习、贝叶斯网络、隐马尔可夫模型以及基础的机器学习和神经网络的相关内容。
2018年秋季学期的版本免费开放了 gradescope,大家可以在线完成书面作业并实时得到测评结果。同时课程的 6 个 Project 也是质量爆炸,复现了经典的 Packman(吃豆人)小游戏,会让你利用学到的 AI 知识,去实现相关算法,让你的吃豆人在迷宫里自由穿梭,躲避鬼怪,收集豆子。
伯克利的人工智能入门课,课程 notes 写得非常深入浅出,基本不需要观看课程视频。课程内容的安排基本按照人工智能的经典教材 Artificial intelligence: A Modern Approach 的章节顺序,覆盖了搜索剪枝、约束满足问题、马尔可夫决策过程、强化学习、贝叶斯网络、隐马尔可夫模型以及基础的机器学习和神经网络的相关内容。
2018年秋季学期的版本免费开放了 gradescope,大家可以在线完成书面作业并实时得到测评结果。同时课程的 6 个 Project 也是质量爆炸,复现了经典的 Packman(吃豆人)小游戏,会让你利用学到的 AI 知识,去实现相关算法,让你的吃豆人在迷宫里自由穿梭,躲避鬼怪,收集豆子。
A very basic introductory AI course, what makes it stand out is the 12 well-designed programming assignments, all of which will use the learned knowledge to implement a simple game AI, such as using reinforcement learning to play Nim game, using max-min search with alpha-beta pruning to sweep mines, and so on. It's perfect for newbies to get started or bigwigs to relax.
All the resources and assignments used by @PKUFlyingPig in this course are maintained in PKUFlyingPig/cs50_ai - GitHub.
A very basic introductory AI course, what makes it stand out is the 12 well-designed programming assignments, all of which will use the learned knowledge to implement a simple game AI, such as using reinforcement learning to play Nim game, using max-min search with alpha-beta pruning to sweep mines, and so on. It's perfect for newbies to get started or bigwigs to relax.
All the resources and assignments used by @PKUFlyingPig in this course are maintained in PKUFlyingPig/cs50_ai - GitHub.
讲解计算机体系结构,授课教师是 Onur Mutlu 教授。本课程根据课程描述应该是DDCA的进阶课程,课程目标是学习如何为类MIPS处理器设计控制和数据通路硬件,如何通过流水线和简单的超标量执行使机器指令同时执行,以及如何设计快速的内存和存储系统。根据同学反馈,从课程本身的难度上说,至少高于 CS61C ,课程的部分内容十分前沿,B站搬运UP主建议大家作为卡内基梅隆大学18-447的补充。所提供的阅读材料十分丰富,相当于听了一学期讲座。
以下是官网的介绍:
We will learn the fundamental concepts of the different parts of modern computing systems, as well as the latest major research topics in Industry and Academia. We will extensively cover memory systems (including DRAM and new Non-Volatile Memory technologies, memory controllers, flash memory), new paradigms like processing-in-memory, parallel computing systems (including multicore processors, coherence and consistency, GPUs), heterogeneous computing, interconnection networks, specialized systems for major data-intensive workloads (e.g. graph analytics, bioinformatics, machine learning), etc. We will focus on fundamentals as well as cutting-edge research. Significant attention will be given to real-life examples and tradeoffs, as well as critical analysis of modern computing systems.
编程实践采取 Verilog 设计和模拟类 MIPS 流水线处理器的寄存器传输(RT)实现,以此加强对理论课程的理解。因此前几个实验会有 verilog 的 CPU 流水线编程。同时还将使用C语言开发一个周期精确的处理器模拟器,并使用该模拟器探索处理器设计选项。
国内有高校引入了这门课,因此有需要的同学可以搜索到一些资源。
讲解计算机体系结构,授课教师是 Onur Mutlu 教授。本课程根据课程描述应该是DDCA的进阶课程,课程目标是学习如何为类MIPS处理器设计控制和数据通路硬件,如何通过流水线和简单的超标量执行使机器指令同时执行,以及如何设计快速的内存和存储系统。根据同学反馈,从课程本身的难度上说,至少高于 CS61C ,课程的部分内容十分前沿,B站搬运UP主建议大家作为卡内基梅隆大学18-447的补充。所提供的阅读材料十分丰富,相当于听了一学期讲座。
以下是官网的介绍:
We will learn the fundamental concepts of the different parts of modern computing systems, as well as the latest major research topics in Industry and Academia. We will extensively cover memory systems (including DRAM and new Non-Volatile Memory technologies, memory controllers, flash memory), new paradigms like processing-in-memory, parallel computing systems (including multicore processors, coherence and consistency, GPUs), heterogeneous computing, interconnection networks, specialized systems for major data-intensive workloads (e.g. graph analytics, bioinformatics, machine learning), etc. We will focus on fundamentals as well as cutting-edge research. Significant attention will be given to real-life examples and tradeoffs, as well as critical analysis of modern computing systems.
编程实践采取 Verilog 设计和模拟类 MIPS 流水线处理器的寄存器传输(RT)实现,以此加强对理论课程的理解。因此前几个实验会有 verilog 的 CPU 流水线编程。同时还将使用C语言开发一个周期精确的处理器模拟器,并使用该模拟器探索处理器设计选项。
国内有高校引入了这门课,因此有需要的同学可以搜索到一些资源。
This is the last course in Berkeley's CS61 series, which dives into the internal of computer architecture and will make you understand how the C language is translated into RISC-V assembly language and executed on the CPU. Unlike Nand2Tetris, this course is much more difficult and more in-depth, covering pipelining, cache, virtual memory, and concurrency-related content.
The projects are very innovative and interesting. Project1 is a warmup assignment in C. In 2020Fall, you will implement the famous Game of Life. Project2 requires you to write a fully-connected neural network in RISC-V assembly to classify handwritten digits in MNIST dataset, which is a great exercise to write assembly code. In Project3, you will use Logisim, a digital circuit simulation software, to build a two-stage pipeline CPU from scratch and run RISC-V assembly code on it. In Project4 you will implement a toy version of Numpy, using OpenMP, SIMD, and other techniques to speed up matrix operations.
In a word, this is the best computer architecture course I have ever taken.
All the resources and assignments used by @PKUFlyingPig in this course are maintained in PKUFlyingPig/CS61C-summer20 - GitHub.
This is the last course in Berkeley's CS61 series, which dives into the internal of computer architecture and will make you understand how the C language is translated into RISC-V assembly language and executed on the CPU. Unlike Nand2Tetris, this course is much more difficult and more in-depth, covering pipelining, cache, virtual memory, and concurrency-related content.
The projects are very innovative and interesting. Project1 is a warmup assignment in C. In 2020Fall, you will implement the famous Game of Life. Project2 requires you to write a fully-connected neural network in RISC-V assembly to classify handwritten digits in MNIST dataset, which is a great exercise to write assembly code. In Project3, you will use Logisim, a digital circuit simulation software, to build a two-stage pipeline CPU from scratch and run RISC-V assembly code on it. In Project4 you will implement a toy version of Numpy, using OpenMP, SIMD, and other techniques to speed up matrix operations.
In a word, this is the best computer architecture course I have ever taken.
All the resources and assignments used by @PKUFlyingPig in this course are maintained in PKUFlyingPig/CS61C-summer20 - GitHub.
This course is one of CMU's most reputable courses, and is known for its extensive content and difficult projects. The course covers assembly language, computer architecture, operating systems, compilation and linking, parallelism, networking, etc. As an introductory course of computer system, it has both breadth and depth, and does require considerable perseverance and coding skills if you learn it on your own.
The textbook for this course, known as CSAPP, was written by Professor Bryant, Dean of the School of Computer Science at CMU. This is also the first computer textbook that I read carefully from the start to the end, although it was tough, I gained a lot from it.
Peking University purchased the copyright of the course and opened a similar one, but you can have access to all of the course resources on its official homepage (see the link below for details).
This course is so famous that you can easily have access to the project solutions on the Internet. But if you really want to practice your coding skills, it is highly recommended to implement the projects on your own.
After completing this course, your understanding of computer systems will definitely go up a notch.
If you have trouble with Chapter 7 Linking, I recommend reading the book Programmer's Self-Cultivation, subtitled link. load and library. This book can complete our understanding of program linking, and I believe after reading this book you will have a deeper comprehension of program linking, ELF files, and dynamic libraries. It is highly recommended to be read as a supplementary material after reading CSAPP and having a certain understanding of computer systems.
This course is one of CMU's most reputable courses, and is known for its extensive content and difficult projects. The course covers assembly language, computer architecture, operating systems, compilation and linking, parallelism, networking, etc. As an introductory course of computer system, it has both breadth and depth, and does require considerable perseverance and coding skills if you learn it on your own.
The textbook for this course, known as CSAPP, was written by Professor Bryant, Dean of the School of Computer Science at CMU. This is also the first computer textbook that I read carefully from the start to the end, although it was tough, I gained a lot from it.
Peking University purchased the copyright of the course and opened a similar one, but you can have access to all of the course resources on its official homepage (see the link below for details).
This course is so famous that you can easily have access to the project solutions on the Internet. But if you really want to practice your coding skills, it is highly recommended to implement the projects on your own.
After completing this course, your understanding of computer systems will definitely go up a notch.
If you have trouble with Chapter 7 Linking, I recommend reading the book Programmer's Self-Cultivation, subtitled link. load and library. This book can complete our understanding of program linking, and I believe after reading this book you will have a deeper comprehension of program linking, ELF files, and dynamic libraries. It is highly recommended to be read as a supplementary material after reading CSAPP and having a certain understanding of computer systems.
In this course, Onur Mutlu, a great expert in the field of Computer Architecture, will teach you about digital circuits and computer architecture. The course is entirely from the perspective of a computer designer, starting with transistors and logic gates and extending to microarchitecture, caches, and virtual memory. It also covers many of the latest research advances in the field of computer architecture. After learning, you will master digital circuits, hardware description language Verilog, MIPS instruction set, CPU design and performance analysis, pipelining, cache, virtual memory, and so on.
There are 9 labs in the course. You will use the Basys 3 FPGA board and Vivado to design and synthesize the circuits, starting from combinational and sequential circuits, and eventually assembly into a complete CPU. Except for assignment solutions, all the course materials are open source.
In this course, Onur Mutlu, a great expert in the field of Computer Architecture, will teach you about digital circuits and computer architecture. The course is entirely from the perspective of a computer designer, starting with transistors and logic gates and extending to microarchitecture, caches, and virtual memory. It also covers many of the latest research advances in the field of computer architecture. After learning, you will master digital circuits, hardware description language Verilog, MIPS instruction set, CPU design and performance analysis, pipelining, cache, virtual memory, and so on.
There are 9 labs in the course. You will use the Basys 3 FPGA board and Vivado to design and synthesize the circuits, starting from combinational and sequential circuits, and eventually assembly into a complete CPU. Except for assignment solutions, all the course materials are open source.
As one of the most popular courses on Coursera, tens of thousands of people give it a full score, and over four hundred colleges and high schools teach it. It guides the students who may have no preparatory knowledge in computer science to build a whole computer from Nand logic gates and finally run the Tetris game on it.
Sounds cool, right? It's even cooler when you implement it!
The course is divided into hardware modules and software modules respectively.
In the hardware modules, you will dive into a world based on 0 and 1, create various logic gates from Nand gates, and construct a CPU step by step to run a simplified instruction set designed by the course instructors.
In the software modules, you will first write a compiler to compile a high-level language Jack which is designed by the instructors into byte codes that can run on virtual machines. Then you will further translate the byte codes into assembly language that can run on the CPU you create in the hardware modules. You will also develop a simple operating system that enables your computer to support GUI.
Finally, you can use Jack to create the Tetris game, compile it into assembly language, run it on your self-made CPU, and interact with it through the OS built by yourself. After taking this course, you will have a comprehensive and profound understanding of the entire computer architecture, which might be extremely helpful to your subsequent learning.
You may think that the course is too difficult. Don't worry, because it is completely designed for laymen. In the instructors' expectations, even high school students can understand the content. So as long as you keep pace with the syllabus, you can finish it within a month.
This course extracts the essence of computers while omitting the tedious and complex details in modern computer systems that are designed for efficiency and performance. Surely you will enjoy the elegance and magic of computers in a relaxing and jolly journey.
All the resources and assignments used by @PKUFlyingPig are maintained in PKUFlyingPig/NandToTetris - GitHub.
As one of the most popular courses on Coursera, tens of thousands of people give it a full score, and over four hundred colleges and high schools teach it. It guides the students who may have no preparatory knowledge in computer science to build a whole computer from Nand logic gates and finally run the Tetris game on it.
Sounds cool, right? It's even cooler when you implement it!
The course is divided into hardware modules and software modules respectively.
In the hardware modules, you will dive into a world based on 0 and 1, create various logic gates from Nand gates, and construct a CPU step by step to run a simplified instruction set designed by the course instructors.
In the software modules, you will first write a compiler to compile a high-level language Jack which is designed by the instructors into byte codes that can run on virtual machines. Then you will further translate the byte codes into assembly language that can run on the CPU you create in the hardware modules. You will also develop a simple operating system that enables your computer to support GUI.
Finally, you can use Jack to create the Tetris game, compile it into assembly language, run it on your self-made CPU, and interact with it through the OS built by yourself. After taking this course, you will have a comprehensive and profound understanding of the entire computer architecture, which might be extremely helpful to your subsequent learning.
You may think that the course is too difficult. Don't worry, because it is completely designed for laymen. In the instructors' expectations, even high school students can understand the content. So as long as you keep pace with the syllabus, you can finish it within a month.
This course extracts the essence of computers while omitting the tedious and complex details in modern computer systems that are designed for efficiency and performance. Surely you will enjoy the elegance and magic of computers in a relaxing and jolly journey.
All the resources and assignments used by @PKUFlyingPig are maintained in PKUFlyingPig/NandToTetris - GitHub.
随着贡献者的不断增多,本书的内容也不断扩展,想把书中所有的课程全部学完是不切实际也没有必要的,甚至会起到事倍功半的反效果,吃力而不讨好。为了更好地贴合读者,让这本书真正为你所用,我将读者按照需求大致分为了如下三类,大家可以结合切身实际,精准地规划属于自己的自学方案。
如果你刚刚进入大学校园或者还在低年级,并且就读的是计算机方向或者想要转到计算机方向,那么你很幸运,因为学习是你的本业,你可以有充足的时间和自由来学习自己感兴趣的东西,不会有工作的压力和生活的琐碎,不必过于纠结“学了有没有用”,“能不能找到工作”这类功利的想法。那么该如何安排自己的学业呢?我觉得首要的一点就是要打破在高中形成的“按部就班”式的被动学习。作为一个小镇做题家,我深知国内大部分高中会把大家一天当中的每一分钟都安排得满满当当,你只需要被动地跟着课表按部就班地完成一个个既定的任务。只要足够认真,结果都不会太差。但步入大学的校门,自由度一下子变大了许多。首先所有的课外时间基本都由你自由支配,没有人为你整理知识点,总结提纲,考试也不像高中那般模式化。如果你还抱着高中那种“乖学生”的心态,老老实实按部就班,结果未必如你所愿。因为专业培养方案未必就是合理,老师的教学未必就会负责,认真出席课堂未必就能听懂,甚至考试内容未必就和讲的有关系。说句玩笑话,你或许会觉得全世界都与你为敌,而你只能指望自己。
那么现状就是这么个现状,你想改变,也得先活过去,并且拥有足够的能力去质疑它。而在低年级,打好基础很重要。这里的基础是全方面的,课内的知识固然重要,但计算机很大程度上还是强调实践,因此有很多课本外的能力需要培养,而这恰恰是国内的计算机本科教育很欠缺的一点。我根据个人的体验总结出了下面几点建议,供大家参考。
其一就是了解如何写“优雅”的代码。国内的很多大一编程入门课都会讲成极其无聊的语法课,其效果还不如直接让学生看官方文档。事实上,在刚开始接触编程的时候,让学生试着去了解什么样的代码是优雅的,什么样的代码 "have bad taste" 是大有裨益的。一般来说,编程入门课会先介绍过程式编程(例如 C 语言)。但即便是面向过程编程,模块化 和 封装 的思想也极其重要。如果你只想着代码能在 OpenJudge 上通过,写的时候图省事,用大段的复制粘贴和臃肿的 main 函数,长此以往,你的代码质量将一直如此。一旦接触稍微大一点的项目,无尽的 debug 和沟通维护成本将把你吞没。因此,写代码时不断问自己,是否有大量重复的代码?当前函数是否过于复杂(Linux 提倡每个函数只需要做好一件事)?这段代码能抽象成一个函数吗?一开始你可能觉得很不习惯,甚至觉得这么简单的题需要如此大费周章吗?但记住好的习惯是无价的,C 语言初中生都能学会,凭什么公司要招你去当程序员呢?
学过面向过程编程后,大一下学期一般会讲面向对象编程(例如 C++ 或 Java)。这里非常推荐大家看 MIT 6.031: Software Construction 这门课的 Notes,会以 Java 语言为例非常详细地讲解如何写出“优雅”的代码。例如 Test-Driven 的开发、函数 Specification 的设计、异常的处理等等等等。除此之外,既然接触了面向对象,那么了解一些常见的设计模式也是很有必要的。因为国内的面向对象课程同样很容易变成极其无聊的语法课,让学生纠结于各种继承的语法,甚至出一些无聊的脑筋急转弯一样的题目,殊不知这些东西在地球人的开发中基本不会用到。面向对象的精髓是让学生学会自己将实际的问题抽象成若干类和它们之间的关系,而设计模式则是前人总结出来的一些精髓的抽象方法。这里推荐大话设计模式 这本书,写得非常浅显易懂。
其二就是尝试学习一些能提高生产力的工具和技能,例如 Git、Shell、Vim。这里强烈推荐学习 MIT missing semester 这门课,也许一开始接触这些工具用起来会很不习惯,但强迫自己用,熟练之后开发效率会直线提高。此外,还有很多应用也能极大提高的你生产力。一条定律是:一切需要让手离开键盘的操作,都应该想办法去除。例如切换应用、打开文件、浏览网页这些都有相关插件可以实现快捷操作(例如 Mac 上的 Alfred)。如果你发现某个操作每天都会用到,并且用时超过1秒,那就应该想办法把它缩减到0.1秒。毕竟以后数十年你都要和电脑打交道,形成一套顺滑的工作流是事半功倍的。最后,学会盲打!如果你还需要看着键盘打字,那么赶紧上网找个教程学会盲打,这将极大提高你的开发效率。
其三就是平衡好课内和自学。我们质疑现状,但也得遵守规则,毕竟绩点在保研中还是相当重要的。因此在大一,我还是建议大家尽量按照自己的课表学习,但辅以一些优质的课外资源。例如微积分线代可以参考 MIT 18.01/18.02 和 MIT 18.06 的课程 Notes。假期可以通过 UCB CS61A 来学习 Python。同时做到上面第一、第二点说的,注重好的编程习惯和实践能力的培养。就个人经验,大一的数学课学分占比相当大,而且数学考试的内容方差是很大的,不同学校不同老师风格迥异,自学也许能让你领悟数学的本质,但未必能给你一个好成绩。因此考前最好有针对性地刷往年题,充分应试。
在升入大二之后,计算机方向的专业课将居多,此时大家可以彻底放飞自我,进入自学的殿堂了。具体可以参考 一份仅供参考的CS学习规划,这是我根据自己三年自学经历总结提炼出来的全套指南,每门课的特点以及为什么要上这门课我都做了简单的介绍。对于你课表上的每个课程,这份规划里应该都会有相应的国外课程,而且在质量上我相信基本是全方位的碾压。由于计算机方向的专业知识基本是一样的,而且高质量的课程会让你从原理上理解知识点,对于国内大多照本宣科式的教学来说基本是降维打击。一般来说只要考前将老师“辛苦”念了一学期的 PPT 拿来突击复习两天,取得一个不错的卷面分数并不困难。如果有课程大作业,则可以尽量将国外课程的 Lab 或者 Project 修改一番以应付课内的需要。我当时上操作系统课,发现老师还用着早已被国外学校淘汰的课程实验,便邮件老师换成了自己正在学习的 MIT 6.S081 的 xv6 Project,方便自学的同时还无意间推动了课程改革。总之,灵活变通是第一要义,你的目标是用最方便、效率最高的方式掌握知识,所有与你这一目标违背的所谓规定都可以想方设法地去“糊弄”。凭着这份糊弄劲儿,我大三之后基本没有去过线下课堂(大二疫情在家呆了大半年),对绩点也完全没有影响。
最后,希望大家少点浮躁和功利,多一些耐心和追求。很多人发邮件问我自学需不需要很强的自制力,我觉得得关键得看你自己想要什么。如果你依然抱着会一门编程语言便能月薪过万的幻想,想分一杯互联网的红利,那么我说再多也是废话。其实我最初的自学并没有太多功利的想法,只是单纯的好奇和本能的求知欲。自学的过程也没有所谓的“头悬梁,锥刺股”,该吃吃,该玩玩,不知不觉才发现竟然攒下了这么多资料。现如今中美的对抗已然成为趋势,而我们还在“卑微”地“师夷长技”,感叹国外高质量课程的同时也时常会有一种危机感。这一切靠谁来改变呢?靠的是刚刚入行的你们。所以,加油吧,少年!
如果你已经本科毕业开始读研或者走上了工作岗位,亦或是从事着其他领域的工作想要利用业余时间转码,那么你也许并没有充足的业余时间来系统地学完 一份仅供参考的CS学习规划 里的内容,但又想弥补本科时期欠下的基础。考虑到这部分读者通常有一定的编程经验,入门课程没有必要再重复学习。而且从实用角度来说,由于工作的大体方向已经确定,确实没有太大必要对于每个计算机分支都有特别深入的研究,更应该侧重一些通用性的原则和技能。因此我结合自身经历,选取了个人感觉最重要也是质量最高的几门核心专业课,希望能更好地加深读者对计算机的理解。学完这些课程,无论你具体从事的是什么工作,我相信你将不可能沦为一个普通的调包侠,而是对计算机的底层运行逻辑有更深入的了解。
如果你对于计算机领域的核心专业课都掌握得相当扎实,而且已经确定了自己的工作或研究方向,那么书中还有很多未在 一份仅供参考的CS学习规划 提到的课程供你探索。
随着贡献者的不断增多,左侧的目录中将不断增加新的分支,例如 机器学习进阶 和 机器学习系统。并且同一个分支下都有若干同类型课程,它们来自不同的学校,有着不同的侧重点和课程实验,例如 操作系统 分支下就包含了麻省理工、伯克利还有南京大学三个学校的课程。如果你想深耕一个领域,那么学习这些同类的课程会给你不同的角度来看待类似的知识。同时,本书作者还计划联系一些相关领域的科研工作者来分享某个细分领域的科研学习路径,让 CS自学指南 在追求广度的同时,实现深度上的提高。
如果你想贡献这方面的内容,欢迎和作者邮件联系 zhongyinmin@pku.edu.cn
随着贡献者的不断增多,本书的内容也不断扩展,想把书中所有的课程全部学完是不切实际也没有必要的,甚至会起到事倍功半的反效果,吃力而不讨好。为了更好地贴合读者,让这本书真正为你所用,我将读者按照需求大致分为了如下三类,大家可以结合切身实际,精准地规划属于自己的自学方案。
如果你刚刚进入大学校园或者还在低年级,并且就读的是计算机方向或者想要转到计算机方向,那么你很幸运,因为学习是你的本业,你可以有充足的时间和自由来学习自己感兴趣的东西,不会有工作的压力和生活的琐碎,不必过于纠结“学了有没有用”,“能不能找到工作”这类功利的想法。那么该如何安排自己的学业呢?我觉得首要的一点就是要打破在高中形成的“按部就班”式的被动学习。作为一个小镇做题家,我深知国内大部分高中会把大家一天当中的每一分钟都安排得满满当当,你只需要被动地跟着课表按部就班地完成一个个既定的任务。只要足够认真,结果都不会太差。但步入大学的校门,自由度一下子变大了许多。首先所有的课外时间基本都由你自由支配,没有人为你整理知识点,总结提纲,考试也不像高中那般模式化。如果你还抱着高中那种“乖学生”的心态,老老实实按部就班,结果未必如你所愿。因为专业培养方案未必就是合理,老师的教学未必就会负责,认真出席课堂未必就能听懂,甚至考试内容未必就和讲的有关系。说句玩笑话,你或许会觉得全世界都与你为敌,而你只能指望自己。
那么现状就是这么个现状,你想改变,也得先活过去,并且拥有足够的能力去质疑它。而在低年级,打好基础很重要。这里的基础是全方面的,课内的知识固然重要,但计算机很大程度上还是强调实践,因此有很多课本外的能力需要培养,而这恰恰是国内的计算机本科教育很欠缺的一点。我根据个人的体验总结出了下面几点建议,供大家参考。
其一就是了解如何写“优雅”的代码。国内的很多大一编程入门课都会讲成极其无聊的语法课,其效果还不如直接让学生看官方文档。事实上,在刚开始接触编程的时候,让学生试着去了解什么样的代码是优雅的,什么样的代码 "have bad taste" 是大有裨益的。一般来说,编程入门课会先介绍过程式编程(例如 C 语言)。但即便是面向过程编程,模块化 和 封装 的思想也极其重要。如果你只想着代码能在 OpenJudge 上通过,写的时候图省事,用大段的复制粘贴和臃肿的 main 函数,长此以往,你的代码质量将一直如此。一旦接触稍微大一点的项目,无尽的 debug 和沟通维护成本将把你吞没。因此,写代码时不断问自己,是否有大量重复的代码?当前函数是否过于复杂(Linux 提倡每个函数只需要做好一件事)?这段代码能抽象成一个函数吗?一开始你可能觉得很不习惯,甚至觉得这么简单的题需要如此大费周章吗?但记住好的习惯是无价的,C 语言初中生都能学会,凭什么公司要招你去当程序员呢?
学过面向过程编程后,大一下学期一般会讲面向对象编程(例如 C++ 或 Java)。这里非常推荐大家看 MIT 6.031: Software Construction 这门课的 Notes,会以 Java 语言为例非常详细地讲解如何写出“优雅”的代码。例如 Test-Driven 的开发、函数 Specification 的设计、异常的处理等等等等。除此之外,既然接触了面向对象,那么了解一些常见的设计模式也是很有必要的。因为国内的面向对象课程同样很容易变成极其无聊的语法课,让学生纠结于各种继承的语法,甚至出一些无聊的脑筋急转弯一样的题目,殊不知这些东西在地球人的开发中基本不会用到。面向对象的精髓是让学生学会自己将实际的问题抽象成若干类和它们之间的关系,而设计模式则是前人总结出来的一些精髓的抽象方法。这里推荐大话设计模式 这本书,写得非常浅显易懂。
其二就是尝试学习一些能提高生产力的工具和技能,例如 Git、Shell、Vim。这里强烈推荐学习 MIT missing semester 这门课,也许一开始接触这些工具用起来会很不习惯,但强迫自己用,熟练之后开发效率会直线提高。此外,还有很多应用也能极大提高的你生产力。一条定律是:一切需要让手离开键盘的操作,都应该想办法去除。例如切换应用、打开文件、浏览网页这些都有相关插件可以实现快捷操作(例如 Mac 上的 Alfred)。如果你发现某个操作每天都会用到,并且用时超过1秒,那就应该想办法把它缩减到0.1秒。毕竟以后数十年你都要和电脑打交道,形成一套顺滑的工作流是事半功倍的。最后,学会盲打!如果你还需要看着键盘打字,那么赶紧上网找个教程学会盲打,这将极大提高你的开发效率。
其三就是平衡好课内和自学。我们质疑现状,但也得遵守规则,毕竟绩点在保研中还是相当重要的。因此在大一,我还是建议大家尽量按照自己的课表学习,但辅以一些优质的课外资源。例如微积分线代可以参考 MIT 18.01/18.02 和 MIT 18.06 的课程 Notes。假期可以通过 UCB CS61A 来学习 Python。同时做到上面第一、第二点说的,注重好的编程习惯和实践能力的培养。就个人经验,大一的数学课学分占比相当大,而且数学考试的内容方差是很大的,不同学校不同老师风格迥异,自学也许能让你领悟数学的本质,但未必能给你一个好成绩。因此考前最好有针对性地刷往年题,充分应试。
在升入大二之后,计算机方向的专业课将居多,此时大家可以彻底放飞自我,进入自学的殿堂了。具体可以参考 一份仅供参考的CS学习规划,这是我根据自己三年自学经历总结提炼出来的全套指南,每门课的特点以及为什么要上这门课我都做了简单的介绍。对于你课表上的每个课程,这份规划里应该都会有相应的国外课程,而且在质量上我相信基本是全方位的碾压。由于计算机方向的专业知识基本是一样的,而且高质量的课程会让你从原理上理解知识点,对于国内大多照本宣科式的教学来说基本是降维打击。一般来说只要考前将老师“辛苦”念了一学期的 PPT 拿来突击复习两天,取得一个不错的卷面分数并不困难。如果有课程大作业,则可以尽量将国外课程的 Lab 或者 Project 修改一番以应付课内的需要。我当时上操作系统课,发现老师还用着早已被国外学校淘汰的课程实验,便邮件老师换成了自己正在学习的 MIT 6.S081 的 xv6 Project,方便自学的同时还无意间推动了课程改革。总之,灵活变通是第一要义,你的目标是用最方便、效率最高的方式掌握知识,所有与你这一目标违背的所谓规定都可以想方设法地去“糊弄”。凭着这份糊弄劲儿,我大三之后基本没有去过线下课堂(大二疫情在家呆了大半年),对绩点也完全没有影响。
最后,希望大家少点浮躁和功利,多一些耐心和追求。很多人发邮件问我自学需不需要很强的自制力,我觉得得关键得看你自己想要什么。如果你依然抱着会一门编程语言便能月薪过万的幻想,想分一杯互联网的红利,那么我说再多也是废话。其实我最初的自学并没有太多功利的想法,只是单纯的好奇和本能的求知欲。自学的过程也没有所谓的“头悬梁,锥刺股”,该吃吃,该玩玩,不知不觉才发现竟然攒下了这么多资料。现如今中美的对抗已然成为趋势,而我们还在“卑微”地“师夷长技”,感叹国外高质量课程的同时也时常会有一种危机感。这一切靠谁来改变呢?靠的是刚刚入行的你们。所以,加油吧,少年!
如果你已经本科毕业开始读研或者走上了工作岗位,亦或是从事着其他领域的工作想要利用业余时间转码,那么你也许并没有充足的业余时间来系统地学完 一份仅供参考的CS学习规划 里的内容,但又想弥补本科时期欠下的基础。考虑到这部分读者通常有一定的编程经验,入门课程没有必要再重复学习。而且从实用角度来说,由于工作的大体方向已经确定,确实没有太大必要对于每个计算机分支都有特别深入的研究,更应该侧重一些通用性的原则和技能。因此我结合自身经历,选取了个人感觉最重要也是质量最高的几门核心专业课,希望能更好地加深读者对计算机的理解。学完这些课程,无论你具体从事的是什么工作,我相信你将不可能沦为一个普通的调包侠,而是对计算机的底层运行逻辑有更深入的了解。
如果你对于计算机领域的核心专业课都掌握得相当扎实,而且已经确定了自己的工作或研究方向,那么书中还有很多未在 一份仅供参考的CS学习规划 提到的课程供你探索。
随着贡献者的不断增多,左侧的目录中将不断增加新的分支,例如 机器学习进阶 和 机器学习系统。并且同一个分支下都有若干同类型课程,它们来自不同的学校,有着不同的侧重点和课程实验,例如 操作系统 分支下就包含了麻省理工、伯克利还有南京大学三个学校的课程。如果你想深耕一个领域,那么学习这些同类的课程会给你不同的角度来看待类似的知识。同时,本书作者还计划联系一些相关领域的科研工作者来分享某个细分领域的科研学习路径,让 CS自学指南 在追求广度的同时,实现深度上的提高。
如果你想贡献这方面的内容,欢迎和作者邮件联系 zhongyinmin@pku.edu.cn
从最初的想法开始,到断断续续完成这本书,再到树洞的热烈反响,我很激动,但也五味杂陈。原来在北大这个园子里,也有那么多人,对自己的本科生涯并不满意。而这里,可是囊括了中国非常优秀的一帮年轻人。所以问题出在哪里?我不知道。
我只是个籍籍无名的本科生呀,只是一个单纯的求学者,我的目标只是想快乐地、自由地、高质量地掌握那些专业知识,我想,正在看这本书的大多数本科生也是如此,谁想付出时间但却收效甚微呢?又是谁迫使大家带着痛苦去应付呢?我不知道。
我写这本书绝不是为了鼓励大家翘课自学,试问谁不想在课堂上和那么多优秀的同学济济一堂,热烈讨论呢?谁不想遇到问题直接找老师答疑解惑呢?谁不想辛苦学习的成果可以直接化作学校承认的学分绩点呢?可如果一个兢兢业业、按时到堂的学生收获的却是痛苦,而那个一学期只有考试会出席的学生却学得自得其乐,这公平吗?我不知道。
我只是不甘,不甘心这些通过高考战胜无数人进入高校的学子本可以收获一个更快乐的本科生涯,但现实却留给了他们遗憾。我反问自己,本科教育究竟应该带给我们什么呢?是学完所有这些课程吗?倒也未必,它也许只适合我这种nerd。但我觉得,本科教育至少得展现它应有的诚意,一种分享知识的诚意,一种以人为本的诚意,一种注重学生体验的诚意。它至少不应该是一种恶意,一种拼比知识的恶意,一种胜者为王的恶意,一种让人学无所得的恶意。但这一切能改变吗?我不知道。
我只知道我做了应该做的事情,学生们会用脚投票,树洞的关注量和回帖数证明了这样一份资料是有价值的,也道出了国内CS本科教育和国外的差距。也许这样的改变是微乎其微的,但别忘了我只是一个籍籍无名的本科生,是北大信科一千多名本科生中的普通一员,是中国几百万在读本科生中的一分子,如果有更多的人站出来,每个人做一点点,也许是分享一个帖子,也许是当一门课的助教,也许是精心设计一门课的lab,更或许是将来获得教职之后开设一门高质量的课程,出版一本经典的教材。本科教育真的有什么技术壁垒吗?我看未必,教育靠的是诚意,靠的是育人之心。
今天是2021年12月12日,我期待在不久的将来这个帖子会被遗忘,大家可以满心欢喜地选着自己培养方案上的课程,做着学校自行设计的各类编程实验,课堂没有签到也能济济一堂,学生踊跃地发言互动,大家的收获可以和努力成正比,那些曾经的遗憾和痛苦可以永远成为历史。我真的很期待那一天,真的真的真的很期待。
PKUFlyingPig
2021年12月12日写于燕园
从最初的想法开始,到断断续续完成这本书,再到树洞的热烈反响,我很激动,但也五味杂陈。原来在北大这个园子里,也有那么多人,对自己的本科生涯并不满意。而这里,可是囊括了中国非常优秀的一帮年轻人。所以问题出在哪里?我不知道。
我只是个籍籍无名的本科生呀,只是一个单纯的求学者,我的目标只是想快乐地、自由地、高质量地掌握那些专业知识,我想,正在看这本书的大多数本科生也是如此,谁想付出时间但却收效甚微呢?又是谁迫使大家带着痛苦去应付呢?我不知道。
我写这本书绝不是为了鼓励大家翘课自学,试问谁不想在课堂上和那么多优秀的同学济济一堂,热烈讨论呢?谁不想遇到问题直接找老师答疑解惑呢?谁不想辛苦学习的成果可以直接化作学校承认的学分绩点呢?可如果一个兢兢业业、按时到堂的学生收获的却是痛苦,而那个一学期只有考试会出席的学生却学得自得其乐,这公平吗?我不知道。
我只是不甘,不甘心这些通过高考战胜无数人进入高校的学子本可以收获一个更快乐的本科生涯,但现实却留给了他们遗憾。我反问自己,本科教育究竟应该带给我们什么呢?是学完所有这些课程吗?倒也未必,它也许只适合我这种nerd。但我觉得,本科教育至少得展现它应有的诚意,一种分享知识的诚意,一种以人为本的诚意,一种注重学生体验的诚意。它至少不应该是一种恶意,一种拼比知识的恶意,一种胜者为王的恶意,一种让人学无所得的恶意。但这一切能改变吗?我不知道。
我只知道我做了应该做的事情,学生们会用脚投票,树洞的关注量和回帖数证明了这样一份资料是有价值的,也道出了国内CS本科教育和国外的差距。也许这样的改变是微乎其微的,但别忘了我只是一个籍籍无名的本科生,是北大信科一千多名本科生中的普通一员,是中国几百万在读本科生中的一分子,如果有更多的人站出来,每个人做一点点,也许是分享一个帖子,也许是当一门课的助教,也许是精心设计一门课的lab,更或许是将来获得教职之后开设一门高质量的课程,出版一本经典的教材。本科教育真的有什么技术壁垒吗?我看未必,教育靠的是诚意,靠的是育人之心。
今天是2021年12月12日,我期待在不久的将来这个帖子会被遗忘,大家可以满心欢喜地选着自己培养方案上的课程,做着学校自行设计的各类编程实验,课堂没有签到也能济济一堂,学生踊跃地发言互动,大家的收获可以和努力成正比,那些曾经的遗憾和痛苦可以永远成为历史。我真的很期待那一天,真的真的真的很期待。
PKUFlyingPig
2021年12月12日写于燕园