USF-MSDS501-计算数据科学中文讲义-21-编程导论

28次阅读

共计 4797 个字符,预计需要花费 12 分钟才能阅读完成。

来源:ApacheCN『USF MSDS501 计算数据科学中文讲义』翻译项目

原文:Introduction to programming

译者:飞龙

协议:CC BY-NC-SA 4.0

<!–break–>

计算机科学不仅关于计算机,就跟天文学不仅关于望远镜一样。

— Edsger Dijkstra

我记得面对我的第一个编程任务(1980 年的 BASIC!),我完全没做出来。我甚至不知道如何开始解决这个问题。我很难过,尽管编码对我来说很快就会变得非常自然。我最初的困难的原因现在显而易见:教师完全没有提供将问题转换为正在运行的程序的技术或策略。我必须自己解决这个问题。

在介绍性课程中关注编程语言语法的方法是可以理解的。解决问题不是一种精确,定义好的技能。它更像是一种通过练习磨练的整体能力。因此,教学和评分是具有挑战性的。立即跳转到一些简单的编程语言语句的语法,要容易得多。这种方法具体,原则上易于理解,但完全忽略了我们什么时候以及为什么需要这些语句。可以在这种环境中作为学生而生存的教授,在教其他程序员时通常会继续使用孤注一掷的方法。

在本课程中,我想通过专注于解决问题和学习编写复杂的 Python 代码来纠正这一问题。要做到这一点,我们将遵循一个整体的问题解决策略,包括设计“工作计划”或“算法”,无论是纸上还是头脑中(当你获得更多经验时)。在我们进入编码阶段很久之前,该计划就帮助我们思考问题。计划的一部分是确定一个解决我们问题的合适操作顺序。这是一个棘手的问题,因此我们将通过以下方式缩小解决方案空间的范围:(1)将自己限制在一组通用的操作和数据结构中,(2)应用成熟的方法,我们称之为“向后工作”和“简化为一个已知的解决方案“,最后,(3)利用这个入门课程的主题特性,采用一个适用于大多数数据科学问题的程序大纲。当我们最终进入 Python 编程时,我们将自己局限于该语言的有用子集。目标是教你编程,而不是教你完整的 Python 语言。

请允许我首先区分 编程 (问题解决)和 编码(用特定编程语言表达我们的解决方案)。

编程是什么?

当我们考虑编程时,我们会立即考虑编程语言,因为我们使用特定的语言语法表达自己。但是,这就像向物理学家询问他们讨论物理学的语言。编程 主要是将“单词问题”(项目描述)转换为执行计划。当然,编码(输入代码)的最终行为是必需的,但学习在精神上解决编程问题是最困难的过程,也是最重要的过程。

自然语言也是如此。学习证明数学定理比学习用某种自然语言编写证明更难。实际上,大多数数学语法在自然语言中都是相同的,就像编程语言一样。像在数据科学计划中一样,用 Python 或 R 表达您的想法是编程过程中最简单的部分。也就是说,编写正确的代码通常是该过程中最令人沮丧和耗时的部分,即使对于有经验的程序员也是如此。

编程更多是要表达 什么 而不是 如何 表达。用计算机解决问题意味着识别一系列操作,每个操作都解决了整个问题的一部分。每个操作本身可能是一系列子操作。用 Python 或 R 表达这些操作并不困难。确定哪些操作及其相对顺序是困难的部分。

让我们从解决编程问题的整体策略入手。

解决问题的策略

无论我们尝试编写什么软件,我们都可以遵循解决问题的整体策略。

在任何问题解决的情况下,第一步 是充分理解问题并清楚地确定目标。这可能听起来很明显,但是我们对这个问题的理解中的任何模糊性都可能使我们走错方向。在数据科学环境中,目标通常是我们试图回答的问题,例如“哪个销售区域的同比增长最快?”(摘要统计量),“哪些交易是欺诈性的?”(分类器)或“未来某个日期股票价格是多少?”(预测器)。我们应该能够使用英语单词精确地表达目标和预期输出。如果我们不能这样做,那么 Python 或 R 中没有任何编码的专业知识可以解决问题。我们很快就会看到一些例子。

问题解决过程的第二步 (或可能是第一步的一部分)是手动写出一些输入 – 输出对。这样做有助于我们了解程序需要做什么以及如何执行。我们将要看到,这种技术不仅适用于整体输入和输出,而且适用于设计函数(可重用的代码段)。 如果我们无法手动识别和执行操作,我们无法使用代码自动执行操作。此外,列出一堆案例通常会突出特殊情况,例如“当输入为负时,输出应为空”。换句话说,程序不应该以负数作为输入而崩溃。程序员称之为 测试驱动设计

在求职面试设置中,此步骤意味着立即尝试绘制问题的几个实例。例如,如果要求以某种方式处理数字列表,首先将三个或四个数字放在板上或纸上。这自然会带来一些面试官期待你提出的重要问题,比如数据的来源以及它是否适合内存等 ……

第三步 是弄清楚我们实现目标所需的数据或输入,即我们的原材料。没有正确的数据,我们无法解决问题。例如,我曾指导过一个学生实习团队,其目标是确定某个网站的哪些客户会升级到专业帐户。学生只有已升级的用户数据,没有拒绝升级的用户数据。哎呀!如果您只有苹果的数据,则无法构建苹果与橙子分类器。如果您没有所需的所有数据,那么将此要求确定为问题解决过程的一部分非常重要。数据采集通常需要编程,我们将回顾下面的主题,作为我们通用计划大纲的一部分。

在这一点上,我们实际上已经设定了解决问题所需的阶段,我们根本没有考虑过代码。我们从最终结果开始,然后确定了我们需要的数据。输入 – 输出对巧妙地包含了我们需要执行的计算。一开始,我们有已知的数据,最后,我们有预期的输出或作品。好的,进入编程步骤。

第四步 是确定计算预期结果的操作顺序。有时这被称为 算法 并且涉及规划输入数据上的特定操作和子操作,逐渐将其转换为预期输出。

前四个步骤是所谓的费曼技巧的关键部分,其中包括写下已分配任务或问题的完整说明,就像你对非专家解释它那样。直到你可以简单地写下来,而不会混淆语言或术语,你自己不明白这个问题。在你完成这个阶段之前,没有必要继续下去。(教师经常开玩笑,学习新主题的最佳方法是教授关于该主题的课程!)

第五步 中,我们将计划中的操作转换为实际的可执行代码。这一步需要整本书,但这里总结了我的建议。从最简单的子操作开始,确保它们先工作。然后编写使用这些子操作的较大操作。如果出现问题,您就会知道新代码中的子操作可能没有经过测试。在这个阶段,我们通常会发现第四步中的设计问题,因此我们通常会重复四五次。测试功能和修复错误称为 调试

最后,第六步 是检查我们的整体结果的正确性。最明显的检查是比较程序的输出与步骤 3 中的已知输入 - 输出对。然后,最重要的是,在第 3 步到第 5 步中使用未考虑的输入来测试程序。这是对程序通用性的重要测试。如果程序输出错误,则返回第 4 步来查看错误。

而现在,出于现实因素。世界是一个非常混乱的地方,因为我们开始知道最少的问题,所以我们通常需要通过一些或所有这些步骤重复或反弹。例如,假设我们正在构建一个苹果与橙子分类器,上面的过程使程序不能很好地区分这两个水果。也许我们只有大小和形状的数据。我们可能会认为分类器需要颜色数据,所以它回到第二步(可能是第三步),然后是第六步再次检查结果。

制定计划和程序

程序是一系列操作,用于转换数据或执行计算,它最终产生预期输出。编程 是设计程序的行为:识别操作及其适当的顺序。换句话说,编程就是为计算机提出一个工作计划,我们经常用半精确的英文描述,叫做 伪代码 。这是上一节中的 第四步

另一方面,编码 是将这种高级伪代码转换为编程语言语法的行为。随着您获得更多经验,在没有伪代码步骤的情况下,直接从工作计划变成代码变得更容易。

在第一次学习编程时,将已建立的模式,模板,策略和常见的数据转换操作用作拐杖,是有帮助的。例如,在下一节中将查看数据科学程序的模板,它们在整个程序中的大多数情况下都可以使用!在 Python 中的编程模式中,我们将看到许多模式,您可以拼凑起来创建程序。

如上所述,您还可以使用两种策略或一般准则来处理程序设计过程:

  • 从最终结果开始,向后工作,询问每个步骤的先决条件。换句话说,步骤 i 之前的一个或多个处理步骤,计算步骤 i 所需的数据或值。例如,在计算平均值之前,我们无法打印某些数字的平均值。在我们对这些数字求和之前,我们无法计算平均值。我们不能综合,直到我们将这些数字加载到内存等 …
  • 使用已知解决方案将新问题归约或简化为现有问题的变体。要应用这种新方法,请询问您尝试解决的问题与您有解决方案的其他问题之间的区别。

这两种技术在建筑,工程和数学方面都是众所周知的。例如,想象一下你想在离地面 10 英尺的地方竖立一尊沉重的雕像。结构工程师可能会认为沉重的雕像需要一个直的金属底座。然后,为了支撑所有这些重量,四个 10 英尺的钢梁应该支撑金属底座。钢梁应在地面上有深层混凝土基座,等等。这是从最终结果倒退的。

作为重用的一个例子,建造一座新吊桥的工程师不会像以前从未建造过这样的东西那样。他们可能会采用并调整现有的设计来适应新的情况。

另外,计划重用通常用于开其他学科的玩笑。例如,来自物理学家笑话的集合,这里有一个变体:

一位物理学家和一位数学家正坐在教职员休息室里。突然间,咖啡机着火了。物理学家抓起一个水桶,跳向水槽,把水桶装满水,灭火。第二天,同样的两个人坐在同一个休息室。咖啡机再次着火。这一次,数学家站起来,拿起一个桶,把桶交给物理学家,从而 将问题归约到先前解决的问题

练习 :给定一个包含十进制数字的字符串,例如s = "501",打印出各个数字的总和。在这种情况下,输出应为6 = 5 + 0 + 1。提示:int('9') 产生值 9。从期望的结果,求和,向后工作,找出你需要的东西。例如,结果是数字的总和。这意味着我们需要数字。要获取数字,我们可以遍历字符串的字符,或者我们可以将字符串转换为字符列表并迭代它。在我们迭代时,我们可以求和数字值。总而言之,我们需要初始化一个临时结果变量,可能称为n

练习 :在A 中给出数字列表,原地反转数字(意思是没有单独的 A 的副本,以及不创建新的列表来返回)。首先在白板上写一个例子。此练习对于在图像项目中的翻转图像非常有用。

如果您遇到困难,或只是检查您的答案,您可以查看我的答案。

现在我们已经有了解决问题的整体策略,让我们来看一个程序大纲,它将帮助我们上手您需要构建的任何数据科学程序。

数据科学程序模板

经验丰富的程序员从一组通用心智模板中抽取起点。有桌面 GUI 应用程序,机器学习分类器,Web 服务器等模板 …. 模板提供程序的整体结构,程序员只需根据特定问题进行定制。

依靠心智模板甚至物理模板非常常见,而不仅仅是编程。律师拥有合同的通用模板,编剧有各种电影类型的通用脚本。例如,大多数动作电影都是这样的:遇见坏人;遇见英雄;追逐场景;英雄克服了很大的困难来打败坏人和他的仆从。由于所需的精度,编程与编写法律文档最相似。丢失的单词或标点可能导致程序崩溃或合同签字人破产。(例如,参见毁坏 NASA 火箭的错别字)。

获得作为程序员的经验,意味着识别代码中的模式,并在脑海中创建通用模板来供将来使用。在开始使用时,您可以通过重用现有的代码库和使用相关模板,来依赖其他程序员的经验。这将我们引领到以下通用数据科学程序模板,该模板适用于您可能遇到的大多数问题:

1. 获取数据,这意味着找到合适的文件或从 Web 收集数据并存储在文件或数据库中
2. 从磁盘或数据库加载数据,并放入组织成数据结构的内存
2. 规范化,过滤,清理或以其他方式准备数据
3. 处理数据,这可能意味着训练机器学习模型,转换数据,计算摘要统计量或优化成本函数
4. 输出结果,可以是任何东西,从简单地将答案打印,到保存数据到磁盘以及生成奇特的可视化

为特定问题编写程序意味着要弄清楚每个步骤是什么,尽管并非所有程序都会使用每一步。

致谢。与 Kathi Fisler 的对话,为这里总结的有原则的,有计划的编程方法提供了很多灵感。有关设计秘籍的更多信息,请参阅通过自举从计算到代数的解决单词问题的转移技巧。

正文完
 0