我自认为自己是个奥迪亚的维基人。我通过写文章和纠正文章错误给很多维基项目贡献了 奥迪亚 （ Odia ） 知识（这是在印度的奥里萨邦的主要语言），比如维基百科和维基文库，我也为用印地语和英语写的维基文章做贡献。我对维基的爱从我第 10 次考试（像在美国的 10 年级学生的年级考试）之后看到的英文维基文章孟加拉解放战争开始。一不小心我打开了印度维基文章的链接，并且开始阅读它。在文章左边有用奥迪亚语写的东西，所以我点击了一下, 打开了一篇在奥迪亚维基上的 ଭାରତ/Bhārat 文章。发现了用母语写的维基让我很激动！一个邀请读者参加 2014 年 4 月 1 日召开的第二届布巴内斯瓦尔研讨会的旗帜广告引起了我的好奇。我过去从来没有为维基做过贡献，只用它做过研究，我并不熟悉开源和社区贡献流程。再加上，当时我只有 15 岁。我注册了，在研讨会上有很多语言爱好者，他们全比我大。尽管我害怕，我父亲还是鼓励我去参与。他起了非常重要的作用—他不是一个维基媒体人，和我不一样，但是他的鼓励给了我改变奥迪亚维基的动力和参加社区活动的勇气。我觉得关于奥迪亚语言和文学的知识很多需要改进，有很多错误的观念和知识缺口，所以，我帮助组织关于奥迪亚维基的活动和和研讨会，我完成了如下列表：在奥迪亚维基发起 3 次主要的 edit-a-thons ：2015 年妇女节、2016年妇女节、abd Nabakalebara edit-a-thon 2015在全印度发起了征集檀车节图片的比赛在谷歌的两大事件（谷歌I/O大会扩展和谷歌开发节）中代表奥迪亚维基在2015 Perception 和第一次 Open Access India 会议我在维基项目当编辑直到去年（ 2015 年 1 月）为止，当我出席孟加拉语维基百科的十周年会议和毗瑟挐活动时，互联网和社会中心主任，邀请我参加培训师培训计划。我的开始超越奥迪亚维基，为GLAM的活动举办聚会和培训新的维基人。这些经验告诉我作为一个贡献者该如何为社区工作。Ravi，在当时印度维基的总监，在我的旅程也发挥了重要作用。他非常相信我，让我参与到了 Wiki Loves Food，维基共享中的公共摄影比赛，组织方是 2016 印度维基会议。在 2015 的 Loves Food 活动期间，我的团队在维基共享中加入了 10000+ 采用 CC BY-SA 协议的图片。Ravi 进一步坚定了我的信心，和我分享了很多关于维基媒体运动的信息，以及他自己在 奥迪亚维基百科 13 周年的经历。不到一年后，在 2015 年十二月，我成为了网络与社会中心的获取知识计划的项目助理（ CIS-A2K 运动）。我自豪的时刻之一是在印度普里的研讨会，我们给奥迪亚维基媒体社区带来了 20 个新的维基人。现在，我在一个名为 WikiTungi 普里的非正式聚会上指导着维基人。我和这个小组一起工作，把奥迪亚 Wikiquotes 变成一个真实的计划项目。在奥迪亚维基我也致力于缩小性别差距。八个女编辑也正帮助组织聚会和研讨会，参加 Women's History month edit-a-thon。在我四年短暂而令人激动的旅行之中，我也参与到 维基百科的教育项目，通讯团队，两个全球的 edit-a-thons： Art and Feminsim 和 Menu Challenge。我期待着更多的到来！我还要感谢 Sameer 和 Anna（都是之前维基百科教育计划的成员）。via: https://opensource.com/life/16/4/my-open-source-story-sailesh-patnaik作者：Sailesh Patnaik 译者：hkurj 校对：wxy本文由 LCTT 原创翻译，Linux中国 荣誉推出
Python 单元测试：assertTrue 是真值，assertFalse 是假值
在这篇文章中，我们将介绍单元测试的布尔断言方法 assertTrue 和 assertFalse 与身份断言 assertIs 之间的区别。定义下面是目前单元测试模块文档中关于 assertTrue 和 assertFalse 的说明，代码进行了高亮：assertTrue(expr, msg=None)assertFalse(expr, msg=None)测试该表达式是真值（或假值）。注：这等价于bool(expr) is True而不等价于expr is True（后一种情况请使用 assertIs(expr, True)）。Mozilla 开发者网络中定义 真值 如下：在一个布尔值的上下文环境中能变成“真”的值在 Python 中等价于：bool(expr) is True 这个和 assertTrue 的测试目的完全匹配。因此该文档中已经指出 assertTrue 返回真值，assertFalse 返回假值。这些断言方法从接受到的值构造出一个布尔值，然后判断它。同样文档中也建议我们根本不应该使用 assertTrue 和 assertFalse。在实践中怎么理解？我们使用一个非常简单的例子 - 一个名称为 always_true 的函数，它返回 True。我们为它写一些测试用例，然后改变代码，看看测试用例的表现。作为开始，我们先写两个测试用例。一个是“宽松的”：使用 assertTrue 来测试真值。另外一个是“严格的”：使用文档中建议的 assertIs 函数。import unittest from func import always_true class TestAlwaysTrue(unittest.TestCase): def test_assertTrue(self): """ always_true returns a truthy value """ result = always_true() self.assertTrue(result) def test_assertIs(self): """ always_true returns True """ result = always_true() self.assertIs(result, True) 下面是 func.py 中的非常简单的函数代码：def always_true(): """ I'm always True. Returns: bool: True """ return True 当你运行时，所有测试都通过了：always_true returns True ... ok always_true returns a truthy value ... ok ---------------------------------------------------------------------- Ran 2 tests in 0.004s OK 开心ing~现在，某个人将 always_true 函数改变成下面这样：def always_true(): """ I'm always True. Returns: bool: True """ return 'True' 它现在是用返回字符串 "True" 来替代之前反馈的 True （布尔值）。（当然，那个“某人”并没有更新文档 - 后面我们会增加难度。）这次结果并不如开心了：always_true returns True ... FAIL always_true returns a truthy value ... ok ====================================================================== FAIL: always_true returns True ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/assertttt/test.py", line 22, in test_is_true self.assertIs(result, True) AssertionError: 'True' is not True ---------------------------------------------------------------------- Ran 2 tests in 0.004s FAILED (failures=1) 只有一个测试用例失败了！这意味着 assertTrue 给了我们一个 误判 （ false-positive ） 。在它不应该通过测试时，它通过了。很幸运的是我们第二个测试是使用 assertIs 来写的。因此，跟手册上了解到的信息一样，为了保证 always_true 的功能和更严格测试的结果保持一致，应该使用 assertIs 而不是 assertTrue。使用断言的辅助方法使用 assertIs 来测试返回 True 和 False 来冗长了。因此，如果你有个项目需要经常检查是否是返回了 True 或者 False，那们你可以自己编写一些断言的辅助方法。这好像并没有节省大量的代码，但是我个人觉得提高了代码的可读性。def assertIsTrue(self, value): self.assertIs(value, True) def assertIsFalse(self, value): self.assertIs(value, False) 总结一般来说，我的建议是让测试越严格越好。如果你想测试 True 或者 False，听从文档的建议，使用 assertIs。除非不得已，否则不要使用 assertTrue 和 assertFalse。如果你面对的是一个可以返回多种类型的函数，例如，有时候返回布尔值，有时候返回整形，那么考虑重构它。这是代码的异味。在 Python 中，抛出一个异常比使用 False 表示错误更好。此外，如果你确实想使用断言来判断函数的返回值是否是真，可能还存在第二个代码异味 - 代码是正确封装了吗？如果 assertTrue 和 assertFalse 是根据正确的 if 语句来执行，那么值得检查下你是否把所有你想要的东西都封装在合适的位置。也许这些 if 语句应该封装在测试的函数中。测试开心！via: http://jamescooke.info/python-unittest-asserttrue-is-truthy-assertfalse-is-falsy.html作者：James Cooke 译者：chunyang-wen 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
据 Net Market Share 的数据，全球的 Linux 桌面用户的份额已经连续四个月超过了 2% 。我们之前报道过，今年六月份时 Linux 桌面的市场份额首次突破了 2%，并于次月达到了历史最高点 2.33%。那些将 Linux 作为主要桌面的用户们为这个份额做出了贡献。显然，从 这个图表的趋势来看，使用 Linux 作为桌面的用户越来越多了。不过，不同的分析公司由于采样范围和分析方法的不同，其报告的数据、图表会有些不同，但是从总体的趋势来看，都是呈现向上增长的。Net Market Share 的报告是基于全球 4 万个网站的访客得出的，4 万个网站也是一个比较大的数量了，当然，与整个互联网相比还是较小。事实上，我们并不能真正摸清 Linux 具体的市场份额，因为有太多的发行版、内核版本和浏览器了，而且有些专门在隐私保护方面做了不少的工作，因此这部分我们的采集不到的。
科学音频处理（三）：如何使用 Octave 的高级数学技术处理音频文件
我们的数字音频处理技术第三部分涵盖了信号调制内容，将解释如何进行 调幅 （ Amplitude Modulation ） 、 颤音效果 （ Tremolo Effect ） 和 频率变化 （ Frequency Variation ） 。调制调幅正如它的名字暗示的那样， 影响正弦信号的振幅变化依据传递的信息而不断改变。正弦波因为承载着大量的信息被称作 载波 （ carrier ） 。这种调制技术被用于许多的商业广播和市民信息传输波段（AM）。为何要使用调幅技术？调制发射假设信道是免费资源，有天线就可以发射和接收信号。这要求有效的电磁信号发射天线，它的大小和要被发射的信号的波长应该是同一数量级。很多信号，包括音频成分，通常在 100 赫兹或更低。对于这些信号，如果直接发射，我们就需要建立长达 300 公里的天线。如果通过信号调制将信息加载到 100MHz 的高频载波中，那么天线仅仅需要 1 米（横向长度）。集中调制与多通道假设多个信号占用一个通道，调制可以将不同的信号不同频域位置，以便接收者选择该特定信号。使用集中调制（“复用”）的应用有遥感探测数据、立体声调频收音机和长途电话等。克服设备限制的调制信号处理设备，比如过滤器、放大器，以及可以用它们简单组成的设备，它们的性能依赖于信号在频域中的境况以及高频率和低频信号的关系。调制可以用于传递信号到频域中的更容易满足设计需求的位置。调制也可以将“宽带信号“（高频和低频的比例很大的信号）转换成”窄带“信号。音频特效许多音频特效由于引人注目和处理信号的便捷性使用了调幅技术。我们可以说出很多，比如颤音、合唱、镶边等等。这种实用性就是我们关注它的原因。颤音效果颤音效果是调幅最简单的应用，为实现这样的效果，我们会用周期信号改变（乘）音频信号，使用正弦或其他。>> tremolo='tremolo.ogg'; >> fs=44100; >> t=0:1/fs:10; >> wo=2*pi*440*t; >> wa=2*pi*1.2*t; >> audiowrite(tremolo, cos(wa).*cos(wo),fs); 这将创造一个正弦形状的信号，它的效果就像‘颤音’。在真实音频文件中的颤音现在我们将展示真实世界中的颤音效果。首先，我们使用之前记录过男性发声 ‘A’ 的音频文件。这个信号图就像下面这样：>> [y,fs]=audioread('A.ogg'); >> plot(y); 现在我们将创建一个完整的正弦信号，使用如下的参数：增幅 = 1频率= 1.5Hz相位 = 0>> t=0:1/fs:4.99999999; >> t=t(:); >> w=2*pi*1.5*t; >> q=cos(w); >> plot(q); 注意： 当我们创建一组时间值时，默认情况下，它是以列的格式呈现，如, 1x220500 的值。为了乘以这样的值，必须将其变成行的形式（220500x1）。这就是 t=t(:) 命令的作用。我们将创建第二份 ogg 音频格式的文件，它包含了如下的调制信号：>> tremolo='tremolo.ogg'; >> audiowrite(tremolo, q.*y,fs); 频率变化我们可以改变频率实现一些有趣的音效，比如原音变形，电影音效，多人比赛。正弦频率调制的影响这是正弦调制频率变化的演示代码，根据方程：Y=Ac*Cos(wo*Cos(wo/k)) 这里：Ac = 增幅wo = 基频k = 标量除数>> fm='fm.ogg'; >> fs=44100; >> t=0:1/fs:10; >> w=2*pi*442*t; >> audiowrite(fm, cos(cos(w/1500).*w), fs); >> [y,fs]=audioread('fm.ogg'); >> figure (); plot (y); 信号图：你可以使用几乎任何类型的周期函数频率调制。本例中，我们仅仅用了一个正弦函数。请大胆的改变函数频率，用复合函数，甚至改变函数的类型。via: https://www.howtoforge.com/tutorial/ubuntu-octave-audio-processing-part-3/作者：David Duarte 译者：theArcticOcean 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
换操作系统对每个人来说都是一件大事——尤其是许多用户根本不清楚操作系统是什么。然而，从 Windows 切换到 Linux 特别地困难。这两个操作系统有着不同的前提和优先级，以及不同的处理方式。结果导致 Linux 新手容易混淆，因为他们在 Windows 上面得到经验不再适用。例如，这里有 7 个 Windows “难民”开始使用 Linux 的时候会犯的错误（没有先后顺序）：7. 选择错误的 Linux 发行版Linux 有几百个不同的版本，或者按他们的称呼叫做 发行版 （ distribution ） 。其中许多是专门针对不同的版本或用户的。选择了错误的版本，你与 Linux 的第一次亲密体验将很快变成一个噩梦。如果你是在朋友的帮助下切换的话，确认他们的建议是适合你，而不是他们。有大量的文章可以帮助到你，你只需要关注前 20 名左右的或者列在 Distrowatch 的即可，就不太可能会搞错。更好的做法是，在你安装某个发行版之前先试试它的 Live DVD。Live DVD 是在外设上运行发行版的，这样可以允许你在不对硬盘做任何改动的情况下对其进行测试。事实上，除非你知道怎么让硬盘在 Linux 下可访问，否则你是不会看到你的硬盘的。6. 期待什么都是一样的由于经验有限，许多 Windows 用户不知道新的操作系统意味着新的程序和新的处理方式。事实上你的 Windows 程序是无法在 Linux 上运行的，除非你用 WINE 或者 Windows 虚拟机。而且你还不能用 MS Office 或者 PhotoShop —— 你必须要学会使用 LibreOffice 和 Krita。经过这些年，这些应用可能会有和 Windows 上的应用类似的功能，但它们的功能可能具有不同的名称，并且会从不同的菜单或工具栏获得。就连很多想当然的都不一样了。Windows 用户会特别容易因为他们有多个桌面环境可以选择而大吃一惊——至少有一个主要的和很多次要的桌面环境。5. 安装软件的时候不知所措在 Windows 上，新软件是作为一个完全独立的程序来安装的。通常它囊括了其它所需的依赖库。有两种叫做 Flatpak 和 Snap 的软件包服务目前正在 Linux 上引进类似的安装系统，但是它们对于移动设备和嵌入式设备来说太大了。更多情况下，Linux 依赖于包管理系统，它会根据已安装的包来判断软件的依赖包是否是必需的，从而提供其它所需的依赖包。笔记本和工作站上的包管理本质上相当于手机或平板电脑上的 Google Play：它速度很快，并且不需要用于安装的物理介质。不仅如此，它还可以节省 20%-35% 的硬盘空间，因为依赖包不会重复安装。4. 假想软件会自动更新好Linux 用户认为控制权很重要。Linux 提供更新服务，不过默认需要用户手动运行。例如，大多数发行版会让你知道有可用的软件更新，但是你需要选择安装这些更新。如果你选择更新的话，你甚至可以单独决定每一个更新。例如，你可能不想更新到新的内核，因为你安装了一些东西需要使用当前的内核。又或者你想要安装所有的安全性更新，但不想把发行版更新到一个新的版本。一切都由你来选择。3. 忘记密码许多 Windows 用户因为登录不方便而忘记密码。又或者为了方便起见，经常运行一个管理账户。在 Linux 上这两种做法都不容易。许多发行版使用 sudo 来避免以 root 登录，特别是那些基于 Ubuntu 的发行版，而其它发行版大多数是安装为禁止 root 运行图形界面。但是，如果你在 Linux 上成功绕开了这些限制，请注意你的大部分 Linux 安全性优势都会无效（其实在 Windows 上也不推荐这样做）。对了，你是不是在安装程序上看到一个自动登录的选项？那是在不常用的情景下使用的，例如不包含隐私信息的虚拟机。2. 担心没有碎片整理和杀毒软件Linux 偶尔需要进行碎片整理，不过只有在恢复分区或者分区差不多满了的时候。并且由于固态硬盘越来越火，碎片整理正在变成过去时，尽管固态硬盘确实需要在任何操作系统上定期运行 trim。同样地，只有当你安装的 Linux 经常传输文件给 Windows 机器的时候，杀毒软件才是一个主要问题。很少有 Linux 病毒或恶意软件存在，并且日常使用非 root 用户、使用强密码、经常备份当前文件就已经足够阻止病毒了。1. 认为自己没有软件可用Windows 上的软件是收费的，大多数类别由一家公司独占——例如，办公套装 MS Office 以及图形和设计的 Adobe。这些条件鼓励用户坚持使用相同的应用程序，尽管它们错漏百出。在 Linux 上，故事情节不一样了。只有少数高端程序是收费的，而且几乎每一类软件都有两三个替代品，所有这些可用的软件都可以在 10 分钟或者更短的时间内下载好。如果一个替代品不合你口味，你可以删掉它然后毫不费力就可以再装一个其它的。在 Linux 上，你几乎总会有选择。过渡期可能没有那么多建议可以让 Windows 用户充分准备好切换到 Linux。即使说新用户应该保持开放的心态也是没什么用的，因为他们的期望总是太高，以至于许多用户都没有意识到自己有如此高的期望。Linux 新手可以做的最好的事情就是调整心态，并且花一点时间来适应它们。过渡期会需要一些功夫，不过，从长远来看，你的多次尝试终会得到回报。via: http://www.datamation.com/open-source/7-mistakes-new-linux-users-make.html作者：Bruce Byfield 译者：OneNewLife 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
毫无疑问，Vim 是一个开箱即用并能够胜任编程任务的编辑器，但实际上是该编辑器中的插件帮你实现这些方便的功能。在 开发者的实用 Vim 插件（一），我们已经讨论两个编程相关的 Vim 插件——标签侧边栏（Tagbar）和定界符自动补齐（delimitMate）。作为相同系列，我们在本文讨论另一个非常有用、专门为软件开发正定制的插件——语法高亮插件。请注意：本教程中列举的所有例示、命令和说明都是在 Ubuntu 16.04 环境下进行测试的，并且，我们使用的 Vim 版本是 7.4。语法高亮（Syntastic）插件假如你的软件开发工作涉及到 C/C++ 语言，毫无疑问的说，遇到编译错误也是你每天工作中的一部分。很多时候，编译错误是由源代码之中的语法不正确造成的，因为开发者在浏览源码的时候很少能够一眼就看出所有这些错误。那么 Vim 中是否存在一种插件可以让你不经编译源码就可以显示出语法错误呢？当然是有这样一种插件的，其名字就是 Syntastic。“Syntastic 是 Vim 用来检验语法的插件，通过外部语法校验器校验文件并将错误呈现给用户。该过程可以在需要时进行，或者在文件保存的时候自动进行。”该插件 官方文档 如是说。“如果检测到语法错误就会提示用户，因为不用编译代码或者执行脚本就可以知道语法错误，用户也就乐享与此了。”安装过程和第一部分提到的方法类似，你只需要运行下列命令即可：cd ~/.vim/bundle/ git clone https://github.com/scrooloose/syntastic.git 一旦你成功安装这个插件（即上述命令执行成功），你就不需要进行任何配置了——当 Vim 启动时会自动加载这个插件。现在，打开一个源码文件并用 :w Vim 命令保存即可使用这个插件了。等待片刻之后，如果在源码中有语法错误的好，就会高亮显示出来。比如，看看一下截图你就会明白该插件是如何高亮显示语法错误的：在每行之前的 >> 表示该行中有语法错误。了解确切的错误或者想知道是什么东西错了，将光标移到该行——错误描述就会展示在 Vim 窗口的最底下。这样，不用进行编译你就能够修复大多数语法相关的错误。再往下，如果你运行 :Errors 命令，就会展现当前源文件中所有语法相关错误的描述。比如，我运行 :Errors 命令就是下图的效果：请记住，:Errors 展现的语法错误是不会自动更新的，这意味着在你修复错误之后，你需要重新运行 :Errors 命令，编辑器底部的错误描述才会消除。值得一提的是，还有 许多配置选项 能够使得 Syntastic 插件使用起来更加友好。比如，你可以在你的 .vimrc 中添加下列内容，然后 :Errors 就可以在修复错误之后自动更新它的底部描述。let g:syntastic_always_populate_loc_list = 1 添加以下内容，以确保在你打开文件时 Syntastic 插件自动高亮显示错误。let g:syntastic_check_on_open = 1 类似的，你也可以在保存或打开文件时让光标跳转到检测到的第一个问题处，将下列行放到你的 .vimrc 文件之中：let g:syntastic_auto_jump = 1 这个值也可以指定为其它两个值： 2 和 3，其官方文档的解释如下：“如果设置为 2 的话，光标就会跳到检测到的第一个问题，当然，只有这个问题是一个错误的时候才跳转；设置为 3 的话，如果存在错误，则会跳到第一个错误。所有检测到的问题都会有警告，但光标不会跳转。”以下信息可能对你有帮助：“使用 :SyntasticCheck 来手动检测错误。使用 :Errors 打开错误位置列表并使用 :lclose 来关闭。使用 :SyntasticReset 可以清除掉错误列表，使用 :SyntasticToggleMode 来切换激活（在写到 buffer 时检测）和被动（即手动检测）检测错误。”注意：Syntastic 并不局限于 C/C++ 所写的代码，它同时也支持很多的编程语言——点击 此处 了解更多相关信息。结论毫无疑问的，Syntastic 是一个非常有用的 Vim 插件，因为在出现语法相关错误时候，它至少能够让免去频繁编译的麻烦，而且不用说，同时也节约了你不少的时间。正如你所看到的一样，配置好几个主要选项之后，Syntastic 变得非常好用了。为了帮助你了解这些设置，官方文档中包含了一份“推荐设置”——跟着文档进行设置即可。加入你遇到一些错误、有些疑问或者问题，你也可以查询一下 FAQ。via: https://www.howtoforge.com/tutorial/vim-editor-plugins-for-software-developers-2-syntastic/作者：Ansh 译者：GHLandy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
构建你的数据科学作品集：机器学习项目
这是这个系列发布的第三篇关于如何构建数据 科学作品集 （ Data Science Portfolio ） 的文章。如果你喜欢这个系列并且想继续关注，你可以在订阅页面的底部找到链接。数据科学公司在决定雇佣时越来越关注你在数据科学方面的 作品集 （ Portfolio ） 。这其中的一个原因是，这样的作品集是判断某人的实际技能的最好的方法。好消息是构建这样的作品集完全要看你自己。只要你在这方面付出了努力，你一定可以取得让这些公司钦佩的作品集。构建高质量的作品集的第一步就是知道需要什么技能。公司想要在数据科学方面拥有的、他们希望你能够运用的主要技能有：沟通能力协作能力技术能力数据推理能力动机和主动性任何好的作品集都由多个项目表现出来，其中每个都能够表现出以上一到两点。这是本系列的第三篇，本系列我们主要讲包括如何打造面面俱到的数据科学作品集。在这一篇中，我们主要涵盖了如何构建组成你的作品集的第二个项目，以及如何创建一个端对端的机器学习项目。在最后，我们将拥有一个展示你的数据推理能力和技术能力的项目。如果你想看一下的话，这里有一个完整的例子。一个端到端的项目作为一个数据科学家，有时候你会拿到一个数据集并被问如何用它来讲故事。在这个时候，沟通就是非常重要的，你需要用它来完成这个事情。像我们在前一篇文章中用过的，类似 Jupyter notebook 这样的工具，将对你非常有帮助。在这里你能找到一些可以用的报告或者总结文档。不管怎样，有时候你会被要求创建一个具有操作价值的项目。具有操作价值的项目将直接影响到公司的日常业务，它会使用不止一次，经常是许多人使用。这个任务可能像这样 “创建一个算法来预测周转率”或者“创建一个模型来自动对我们的文章打标签”。在这种情况下，技术能力比讲故事更重要。你必须能够得到一个数据集，并且理解它，然后创建脚本处理该数据。这个脚本要运行的很快，占用系统资源很小。通常它可能要运行很多次，脚本的可使用性也很重要，并不仅仅是一个演示版。可使用性是指整合进操作流程，并且甚至是是面向用户的。端对端项目的主要组成部分:理解背景浏览数据并找出细微差别创建结构化项目，那样比较容易整合进操作流程运行速度快、占用系统资源小的高性能代码写好安装和使用文档以便其他人用为了有效的创建这种类型的项目，我们可能需要处理多个文件。强烈推荐使用 Atom 这样的文本编辑器或者 PyCharm 这样的 IDE。这些工具允许你在文件间跳转，编辑不同类型的文件，例如 markdown 文件，Python 文件，和 csv 文件等等。结构化你的项目还利于版本控制，并上传一个类似 Github 这样的协作开发工具上也很有用。Github 上的这个项目在这一节中我们将使用 Pandas 和 scikit-learn 这样的库，我们还将大量用到 Pandas DataFrames，它使得 python 读取和处理表格数据更加方便。找到好的数据集为一个端到端的作品集项目的找到好的数据集很难。在内存和性能的限制下，数据集需要尽量的大。它还需要是实际有用的。例如，这个数据集，它包含有美国院校的录取标准、毕业率以及毕业以后的收入，是个很好的可以讲故事的数据集。但是，不管你如何看待这个数据，很显然它不适合创建端到端的项目。比如，你能告诉人们他们去了这些大学以后的未来收入，但是这个快速检索却并不足够呈现出你的技术能力。你还能找出院校的招生标准和更高的收入相关，但是这更像是常理而不是你的技术结论。这里还有内存和性能约束的问题，比如你有几千兆的数据，而且当你需要找到一些差异时，就需要对数据集一遍遍运行算法。一个好的可操作的数据集可以让你构建一系列脚本来转换数据、动态地回答问题。一个很好的例子是股票价格数据集，当股市关闭时，就会给算法提供新的数据。这可以让你预测明天的股价，甚至预测收益。这不是讲故事，它带来的是真金白银。一些找到数据集的好地方：/r/datasets – 有上百的有趣数据的 subreddit（Reddit 是国外一个社交新闻站点，subreddit 指该论坛下的各不同版块）。Google Public Datasets – 通过 Google BigQuery 使用的公开数据集。Awesome datasets – 一个数据集列表，放在 Github 上。当你查看这些数据集时，想一下人们想要在这些数据集中得到什么答案，哪怕这些问题只想过一次（“房价是如何与标准普尔 500 指数关联的?”），或者更进一步（“你能预测股市吗?”）。这里的关键是更进一步地找出问题，并且用相同的代码在不同输入（不同的数据）上运行多次。对于本文的目标，我们来看一下 房利美 （ Fannie Mae ） 贷款数据。房利美是一家在美国的政府赞助的企业抵押贷款公司，它从其他银行购买按揭贷款，然后捆绑这些贷款为贷款证券来转卖它们。这使得贷款机构可以提供更多的抵押贷款，在市场上创造更多的流动性。这在理论上会带来更多的住房和更好的贷款期限。从借款人的角度来说，它们大体上差不多，话虽这样说。房利美发布了两种类型的数据 – 它获得的贷款的数据，和贷款偿还情况的数据。在理想的情况下，有人向贷款人借钱，然后还款直到还清。不管怎样，有些人多次不还，从而丧失了抵押品赎回权。抵押品赎回权是指没钱还了被银行把房子给收走了。房利美会追踪谁没还钱，并且哪个贷款需要收回抵押的房屋（取消赎回权）。每个季度会发布此数据，发布的是滞后一年的数据。当前可用是 2015 年第一季度数据。“贷款数据”是由房利美发布的贷款发放的数据，它包含借款人的信息、信用评分，和他们的家庭贷款信息。“执行数据”，贷款发放后的每一个季度公布，包含借贷人的还款信息和是否丧失抵押品赎回权的状态，一个“贷款数据”的“执行数据”可能有十几行。可以这样理解，“贷款数据”告诉你房利美所控制的贷款，“执行数据”包含该贷款一系列的状态更新。其中一个状态更新可以告诉我们一笔贷款在某个季度被取消赎回权了。一个没有及时还贷的房子就这样的被卖了选择一个角度这里有几个我们可以去分析房利美数据集的方向。我们可以：预测房屋的销售价格。预测借款人还款历史。在获得贷款时为每一笔贷款打分。最重要的事情是坚持单一的角度。同时关注太多的事情很难做出效果。选择一个有着足够细节的角度也很重要。下面的角度就没有太多细节：找出哪些银行将贷款出售给房利美的多数被取消赎回权。计算贷款人的信用评分趋势。找到哪些类型的家庭没有偿还贷款的能力。找到贷款金额和抵押品价格之间的关系。上面的想法非常有趣，如果我们关注于讲故事，那是一个不错的角度，但是不是很适合一个操作性项目。在房利美数据集中，我们将仅使用申请贷款时有的那些信息来预测贷款是否将来会被取消赎回权。实际上, 我们将为每一笔贷款建立“分数”来告诉房利美买还是不买。这将给我们打下良好的基础，并将组成这个漂亮的作品集的一部分。理解数据我们来简单看一下原始数据文件。下面是 2012 年 1 季度前几行的贷款数据：100000853384|R|OTHER|4.625|280000|360|02/2012|04/2012|31|31|1|23|801|N|C|SF|1|I|CA|945||FRM| 100003735682|R|SUNTRUST MORTGAGE INC.|3.99|466000|360|01/2012|03/2012|80|80|2|30|794|N|P|SF|1|P|MD|208||FRM|788 100006367485|C|PHH MORTGAGE CORPORATION|4|229000|360|02/2012|04/2012|67|67|2|36|802|N|R|SF|1|P|CA|959||FRM|794 下面是 2012 年 1 季度的前几行执行数据：100000853384|03/01/2012|OTHER|4.625||0|360|359|03/2042|41860|0|N|||||||||||||||| 100000853384|04/01/2012||4.625||1|359|358|03/2042|41860|0|N|||||||||||||||| 100000853384|05/01/2012||4.625||2|358|357|03/2042|41860|0|N|||||||||||||||| 在开始编码之前，花些时间真正理解数据是值得的。这对于操作性项目优为重要，因为我们没有交互式探索数据，将很难察觉到细微的差别，除非我们在前期发现他们。在这种情况下，第一个步骤是阅读房利美站点的资料：概述有用的术语表常见问答贷款和执行文件中的列贷款数据文件样本执行数据文件样本在看完这些文件后后，我们了解到一些能帮助我们的关键点：从 2000 年到现在，每季度都有一个贷款和执行文件，因数据是滞后一年的，所以到目前为止最新数据是 2015 年的。这些文件是文本格式的，采用管道符号|进行分割。这些文件是没有表头的，但我们有个文件列明了各列的名称。所有一起，文件包含 2200 万个贷款的数据。由于执行数据的文件包含过去几年获得的贷款的信息，在早些年获得的贷款将有更多的执行数据（即在 2014 获得的贷款没有多少历史执行数据）。这些小小的信息将会为我们节省很多时间，因为这样我们就知道如何构造我们的项目和利用这些数据了。构造项目在我们开始下载和探索数据之前，先想一想将如何构造项目是很重要的。当建立端到端项目时，我们的主要目标是：创建一个可行解决方案有一个快速运行且占用最小资源的解决方案容易可扩展写容易理解的代码写尽量少的代码为了实现这些目标，需要对我们的项目进行良好的构造。一个结构良好的项目遵循几个原则：分离数据文件和代码文件从原始数据中分离生成的数据。有一个 README.md 文件帮助人们安装和使用该项目。有一个 requirements.txt 文件列明项目运行所需的所有包。有一个单独的 settings.py 文件列明其它文件中使用的所有的设置例如，如果从多个 Python 脚本读取同一个文件，让它们全部 import 设置并从一个集中的地方获得文件名是有用的。有一个 .gitignore 文件，防止大的或密码文件被提交。分解任务中每一步可以单独执行的步骤到单独的文件中。例如，我们将有一个文件用于读取数据，一个用于创建特征，一个用于做出预测。保存中间结果，例如，一个脚本可以输出下一个脚本可读取的文件。这使我们无需重新计算就可以在数据处理流程中进行更改。我们的文件结构大体如下：loan-prediction ├── data ├── processed ├── .gitignore ├── README.md ├── requirements.txt ├── settings.py 创建初始文件首先，我们需要创建一个 loan-prediction 文件夹，在此文件夹下面，再创建一个 data 文件夹和一个 processed 文件夹。data 文件夹存放原始数据，processed 文件夹存放所有的中间计算结果。其次，创建 .gitignore 文件，.gitignore 文件将保证某些文件被 git 忽略而不会被推送至 GitHub。关于这个文件的一个好的例子是由 OSX 在每一个文件夹都会创建的 .DS_Store 文件，.gitignore 文件一个很好的范本在这里。我们还想忽略数据文件，因为它们实在是太大了，同时房利美的条文禁止我们重新分发该数据文件，所以我们应该在我们的文件后面添加以下 2 行：data processed 这里是该项目的一个关于 .gitignore 文件的例子。再次，我们需要创建 README.md 文件，它将帮助人们理解该项目。后缀 .md 表示这个文件采用 markdown 格式。Markdown 使你能够写纯文本文件，同时还可以添加你想要的神奇的格式。这里是关于 markdown 的导引。如果你上传一个叫 README.md 的文件至 Github，Github 会自动处理该 markdown，同时展示给浏览该项目的人。例子在这里。至此，我们仅需在 README.md 文件中添加简单的描述：Loan Prediction ----------------------- Predict whether or not loans acquired by Fannie Mae will go into foreclosure. Fannie Mae acquires loans from other lenders as a way of inducing them to lend more. Fannie Mae releases data on the loans it has acquired and their performance afterwards [here](http://www.fanniemae.com/portal/funding-the-market/data/loan-performance-data.html). 现在，我们可以创建 requirements.txt 文件了。这会帮助其它人可以很方便地安装我们的项目。我们还不知道我们将会具体用到哪些库，但是以下几个库是需要的：pandas matplotlib scikit-learn numpy ipython scipy 以上几个是在 python 数据分析任务中最常用到的库。可以认为我们将会用到大部分这些库。这里是该项目 requirements.txt 文件的一个例子。创建 requirements.txt 文件之后，你应该安装这些包了。我们将会使用 python3。如果你没有安装 python，你应该考虑使用 Anaconda，它是一个 python 安装程序，同时安装了上面列出的所有包。最后，我们可以建立一个空白的 settings.py 文件，因为我们的项目还没有任何设置。获取数据一旦我们有了项目的基本架构，我们就可以去获得原始数据。房利美对获取数据有一些限制，所以你需要去注册一个账户。在创建完账户之后，你可以找到在这里的下载页面，你可以按照你所需要的下载或多或少的贷款数据文件。文件格式是 zip，在解压后当然是非常大的。为了达到我们这个文章的目的，我们将要下载从 2012 年 1 季度到 2015 年 1 季度的所有数据。接着我们需要解压所有的文件。解压过后，删掉原来的 .zip 格式的文件。最后，loan-prediction 文件夹看起来应该像下面的一样：loan-prediction ├── data │ ├── Acquisition_2012Q1.txt │ ├── Acquisition_2012Q2.txt │ ├── Performance_2012Q1.txt │ ├── Performance_2012Q2.txt │ └── ... ├── processed ├── .gitignore ├── README.md ├── requirements.txt ├── settings.py 在下载完数据后，你可以在 shell 命令行中使用 head 和 tail 命令去查看文件中的行数据，你看到任何的不需要的数据列了吗？在做这件事的同时查阅列名称的 pdf 文件可能有帮助。读入数据有两个问题让我们的数据难以现在就使用：贷款数据和执行数据被分割在多个文件中每个文件都缺少列名标题在我们开始使用数据之前，我们需要首先明白我们要在哪里去存一个贷款数据的文件，同时到哪里去存储一个执行数据的文件。每个文件仅仅需要包括我们关注的那些数据列，同时拥有正确的列名标题。这里有一个小问题是执行数据非常大，因此我们需要尝试去修剪一些数据列。第一步是向 settings.py 文件中增加一些变量，这个文件中同时也包括了我们原始数据的存放路径和处理出的数据存放路径。我们同时也将添加其他一些可能在接下来会用到的设置数据：DATA_DIR = "data" PROCESSED_DIR = "processed" MINIMUM_TRACKING_QUARTERS = 4 TARGET = "foreclosure_status" NON_PREDICTORS = [TARGET, "id"] CV_FOLDS = 3 把路径设置在 settings.py 中使它们放在一个集中的地方，同时使其修改更加的容易。当在多个文件中用到相同的变量时，你想改变它的话，把他们放在一个地方比分散放在每一个文件时更加容易。这里的是一个这个工程的示例 settings.py 文件第二步是创建一个文件名为 assemble.py，它将所有的数据分为 2 个文件。当我们运行 Python assemble.py，我们在处理数据文件的目录会获得 2 个数据文件。接下来我们开始写 assemble.py 文件中的代码。首先我们需要为每个文件定义相应的列名标题，因此我们需要查看列名称的 pdf 文件，同时创建在每一个贷款数据和执行数据的文件的数据列的列表：HEADERS = { "Acquisition": [ "id", "channel", "seller", "interest_rate", "balance", "loan_term", "origination_date", "first_payment_date", "ltv", "cltv", "borrower_count", "dti", "borrower_credit_score", "first_time_homebuyer", "loan_purpose", "property_type", "unit_count", "occupancy_status", "property_state", "zip", "insurance_percentage", "product_type", "co_borrower_credit_score" ], "Performance": [ "id", "reporting_period", "servicer_name", "interest_rate", "balance", "loan_age", "months_to_maturity", "maturity_date", "msa", "delinquency_status", "modification_flag", "zero_balance_code", "zero_balance_date", "last_paid_installment_date", "foreclosure_date", "disposition_date", "foreclosure_costs", "property_repair_costs", "recovery_costs", "misc_costs", "tax_costs", "sale_proceeds", "credit_enhancement_proceeds", "repurchase_proceeds", "other_foreclosure_proceeds", "non_interest_bearing_balance", "principal_forgiveness_balance" ] } 接下来一步是定义我们想要保留的数据列。因为我们要预测一个贷款是否会被撤回，我们可以丢弃执行数据中的许多列。我们将需要保留贷款数据中的所有数据列，因为我们需要尽量多的了解贷款发放时的信息（毕竟我们是在预测贷款发放时这笔贷款将来是否会被撤回）。丢弃数据列将会使我们节省下内存和硬盘空间，同时也会加速我们的代码。SELECT = { "Acquisition": HEADERS["Acquisition"], "Performance": [ "id", "foreclosure_date" ] } 下一步，我们将编写一个函数来连接数据集。下面的代码将：引用一些需要的库，包括 settings。定义一个函数 concatenate，目的是：获取到所有 data 目录中的文件名。遍历每个文件。如果文件不是正确的格式 (不是以我们需要的格式作为开头)，我们将忽略它。通过使用 Pandas 的 read\_csv 函数及正确的设置把文件读入一个 DataFrame。设置分隔符为｜，以便所有的字段能被正确读出。数据没有标题行，因此设置 header 为 None 来进行标示。从 HEADERS 字典中设置正确的标题名称 – 这将会是我们的 DataFrame 中的数据列名称。仅选择我们加在 SELECT 中的 DataFrame 的列。把所有的 DataFrame 共同连接在一起。把已经连接好的 DataFrame 写回一个文件。import os import settings import pandas as pd def concatenate(prefix="Acquisition"): files = os.listdir(settings.DATA_DIR) full = [] for f in files: if not f.startswith(prefix): continue data = pd.read_csv(os.path.join(settings.DATA_DIR, f), sep="|", header=None, names=HEADERS[prefix], index_col=False) data = data[SELECT[prefix]] full.append(data) full = pd.concat(full, axis=0) full.to_csv(os.path.join(settings.PROCESSED_DIR, "{}.txt".format(prefix)), sep="|", header=SELECT[prefix], index=False) 我们可以通过调用上面的函数，通过传递的参数 Acquisition 和 Performance 两次以将所有的贷款和执行文件连接在一起。下面的代码将：仅在命令行中运行 python assemble.py 时执行。将所有的数据连接在一起，并且产生 2 个文件：processed/Acquisition.txtprocessed/Performance.txtif __name__ == "__main__": concatenate("Acquisition") concatenate("Performance") 我们现在拥有了一个漂亮的，划分过的 assemble.py 文件，它很容易执行，也容易建立。通过像这样把问题分解为一块一块的，我们构建工程就会变的容易许多。不用一个可以做所有工作的凌乱脚本，我们定义的数据将会在多个脚本间传递，同时使脚本间完全的彼此隔离。当你正在一个大的项目中工作时，这样做是一个好的想法，因为这样可以更加容易修改其中的某一部分而不会引起其他项目中不关联部分产生预料之外的结果。一旦我们完成 assemble.py 脚本文件，我们可以运行 python assemble.py 命令。你可以在这里查看完整的 assemble.py 文件。这将会在 processed 目录下产生 2 个文件：loan-prediction ├── data │ ├── Acquisition_2012Q1.txt │ ├── Acquisition_2012Q2.txt │ ├── Performance_2012Q1.txt │ ├── Performance_2012Q2.txt │ └── ... ├── processed │ ├── Acquisition.txt │ ├── Performance.txt ├── .gitignore ├── assemble.py ├── README.md ├── requirements.txt ├── settings.py 计算来自执行数据的值接下来我们会计算来自 processed/Performance.txt 中的值。我们要做的就是推测这些资产是否被取消赎回权。如果能够计算出来，我们只要看一下关联到贷款的执行数据的参数 foreclosure_date 就可以了。如果这个参数的值是 None，那么这些资产肯定没有收回。为了避免我们的样例中只有少量的执行数据，我们会为每个贷款计算出执行数据文件中的行数。这样我们就能够从我们的训练数据中筛选出贷款数据，排除了一些执行数据。下面是我认为贷款数据和执行数据的关系：在上面的表格中，贷款数据中的每一行数据都关联到执行数据中的多行数据。在执行数据中，在取消赎回权的时候 foreclosure_date 就会出现在该季度，而之前它是空的。一些贷款还没有被取消赎回权，所以与执行数据中的贷款数据有关的行在 foreclosure_date 列都是空格。我们需要计算 foreclosure_status 的值，它的值是布尔类型，可以表示一个特殊的贷款数据 id 是否被取消赎回权过，还有一个参数 performance_count ，它记录了执行数据中每个贷款 id 出现的行数。 计算这些行数有多种不同的方法：我们能够读取所有的执行数据，然后我们用 Pandas 的 groupby 方法在 DataFrame 中计算出与每个贷款 id 有关的行的行数，然后就可以查看贷款 id 的 foreclosure_date 值是否为 None 。这种方法的优点是从语法上来说容易执行。它的缺点需要读取所有的 129236094 行数据，这样就会占用大量内存，并且运行起来极慢。我们可以读取所有的执行数据，然后在贷款 DataFrame 上使用 apply 去计算每个贷款 id 出现的次数。这种方法的优点是容易理解。缺点是需要读取所有的 129236094 行数据。这样会占用大量内存，并且运行起来极慢。我们可以在迭代访问执行数据中的每一行数据，而且会建立一个单独的计数字典。这种方法的优点是数据不需要被加载到内存中，所以运行起来会很快且不需要占用内存。缺点是这样的话理解和执行上可能有点耗费时间，我们需要对每一行数据进行语法分析。加载所有的数据会非常耗费内存，所以我们采用第三种方法。我们要做的就是迭代执行数据中的每一行数据，然后为每一个贷款 id 在字典中保留一个计数。在这个字典中，我们会计算出贷款 id 在执行数据中出现的次数，而且看看 foreclosure_date 是否是 None 。我们可以查看 foreclosure_status 和 performance_count 的值 。我们会新建一个 annotate.py 文件，文件中的代码可以计算这些值。我们会使用下面的代码：导入需要的库定义一个函数 count_performance_rows 。打开 processed/Performance.txt 文件。这不是在内存中读取文件而是打开了一个文件标识符，这个标识符可以用来以行为单位读取文件。迭代文件的每一行数据。使用分隔符|分开每行的不同数据。检查 loan_id 是否在计数字典中。如果不存在，把它加进去。loan_id 的 performance_count 参数自增 1 次，因为我们这次迭代也包含其中。如果 date 不是 None ，我们就会知道贷款被取消赎回权了，然后为foreclosure\_status` 设置合适的值。import os import settings import pandas as pd def count_performance_rows(): counts = {} with open(os.path.join(settings.PROCESSED_DIR, "Performance.txt"), 'r') as f: for i, line in enumerate(f): if i == 0: # Skip header row continue loan_id, date = line.split("|") loan_id = int(loan_id) if loan_id not in counts: counts[loan_id] = { "foreclosure_status": False, "performance_count": 0 } counts[loan_id]["performance_count"] += 1 if len(date.strip()) > 0: counts[loan_id]["foreclosure_status"] = True return counts 获取值只要我们创建了计数字典，我们就可以使用一个函数通过一个 loan_id 和一个 key 从字典中提取到需要的参数的值：def get_performance_summary_value(loan_id, key, counts): value = counts.get(loan_id, { "foreclosure_status": False, "performance_count": 0 }) return value[key] 上面的函数会从 counts 字典中返回合适的值，我们也能够为贷款数据中的每一行赋一个 foreclosure_status 值和一个 performance_count 值。如果键不存在，字典的 get 方法会返回一个默认值，所以在字典中不存在键的时候我们就可以得到一个可知的默认值。转换数据我们已经在 annotate.py 中添加了一些功能，现在我们来看一看数据文件。我们需要将贷款到的数据转换到训练数据集来进行机器学习算法的训练。这涉及到以下几件事情:转换所有列为数字。填充缺失值。为每一行分配 performance_count 和 foreclosure_status。移除出现执行数据很少的行（performance_count 计数低）。我们有几个列是文本类型的，看起来对于机器学习算法来说并不是很有用。然而，它们实际上是分类变量，其中有很多不同的类别代码，例如 R，S 等等. 我们可以把这些类别标签转换为数值：通过这种方法转换的列我们可以应用到机器学习算法中。还有一些包含日期的列 (first_payment_date 和 origination_date）。我们可以将这些日期放到两个列中：在下面的代码中，我们将转换贷款数据。我们将定义一个函数如下：在 acquisition 中创建 foreclosure_status 列，并从 counts 字典中得到值。在 acquisition 中创建 performance_count 列，并从 counts 字典中得到值。将下面的列从字符串转换为整数：channelsellerfirst_time_homebuyerloan_purposeproperty_typeoccupancy_statusproperty_stateproduct_type将 first_payment_date 和 origination_date 分别转换为两列：通过斜杠分离列。将第一部分分离成 month 列。将第二部分分离成 year 列。删除该列。最后，我们得到 first_payment_month、first_payment_year、rigination_month 和 origination_year。所有缺失值填充为 -1。def annotate(acquisition, counts): acquisition["foreclosure_status"] = acquisition["id"].apply(lambda x: get_performance_summary_value(x, "foreclosure_status", counts)) acquisition["performance_count"] = acquisition["id"].apply(lambda x: get_performance_summary_value(x, "performance_count", counts)) for column in [ "channel", "seller", "first_time_homebuyer", "loan_purpose", "property_type", "occupancy_status", "property_state", "product_type" ]: acquisition[column] = acquisition[column].astype('category').cat.codes for start in ["first_payment", "origination"]: column = "{}_date".format(start) acquisition["{}_year".format(start)] = pd.to_numeric(acquisition[column].str.split('/').str.get(1)) acquisition["{}_month".format(start)] = pd.to_numeric(acquisition[column].str.split('/').str.get(0)) del acquisition[column] acquisition = acquisition.fillna(-1) acquisition = acquisition[acquisition["performance_count"] > settings.MINIMUM_TRACKING_QUARTERS] return acquisition 聚合到一起我们差不多准备就绪了，我们只需要再在 annotate.py 添加一点点代码。在下面代码中，我们将：定义一个函数来读取贷款的数据。定义一个函数来写入处理过的数据到 processed/train.csv。如果该文件在命令行以 python annotate.py 的方式运行：读取贷款数据。计算执行数据的计数，并将其赋予 counts。转换 acquisition DataFrame。将acquisition DataFrame 写入到 train.csv。def read(): acquisition = pd.read_csv(os.path.join(settings.PROCESSED_DIR, "Acquisition.txt"), sep="|") return acquisition def write(acquisition): acquisition.to_csv(os.path.join(settings.PROCESSED_DIR, "train.csv"), index=False) if __name__ == "__main__": acquisition = read() counts = count_performance_rows() acquisition = annotate(acquisition, counts) write(acquisition) 修改完成以后，确保运行 python annotate.py 来生成 train.csv 文件。 你可以在这里找到完整的 annotate.py 文件。现在文件夹看起来应该像这样：loan-prediction ├── data │ ├── Acquisition_2012Q1.txt │ ├── Acquisition_2012Q2.txt │ ├── Performance_2012Q1.txt │ ├── Performance_2012Q2.txt │ └── ... ├── processed │ ├── Acquisition.txt │ ├── Performance.txt │ ├── train.csv ├── .gitignore ├── annotate.py ├── assemble.py ├── README.md ├── requirements.txt ├── settings.py 找到误差标准我们已经完成了训练数据表的生成，现在我们需要最后一步，生成预测。我们需要找到误差的标准，以及该如何评估我们的数据。在这种情况下，因为有很多的贷款没有被取消赎回权，所以根本不可能做到精确的计算。我们需要读取训练数据，并且计算 foreclosure_status 列的计数，我们将得到如下信息：import pandas as pd import settings train = pd.read_csv(os.path.join(settings.PROCESSED_DIR, "train.csv")) train["foreclosure_status"].value_counts() False 4635982 True 1585 Name: foreclosure_status, dtype: int64 因为只有很少的贷款被取消赎回权，只需要检查正确预测的标签的百分比就意味着我们可以创建一个机器学习模型，来为每一行预测 False，并能取得很高的精确度。相反，我们想要使用一个度量来考虑分类的不平衡，确保我们可以准确预测。我们要避免太多的误报率（预测贷款被取消赎回权，但是实际没有），也要避免太多的漏报率（预测贷款没有别取消赎回权，但是实际被取消了）。对于这两个来说，漏报率对于房利美来说成本更高，因为他们买的贷款可能是他们无法收回投资的贷款。所以我们将定义一个漏报率，就是模型预测没有取消赎回权但是实际上取消了，这个数除以总的取消赎回权数。这是“缺失的”实际取消赎回权百分比的模型。下面看这个图表：通过上面的图表，有 1 个贷款预测不会取消赎回权，但是实际上取消了。如果我们将这个数除以实际取消赎回权的总数 2，我们将得到漏报率 50%。 我们将使用这个误差标准，因此我们可以评估一下模型的行为。设置机器学习分类器我们使用交叉验证预测。通过交叉验证法，我们将数据分为3组。按照下面的方法来做：用组 1 和组 2 训练模型，然后用该模型来预测组 3用组 1 和组 3 训练模型，然后用该模型来预测组 2用组 2 和组 3 训练模型，然后用该模型来预测组 1将它们分割到不同的组，这意味着我们永远不会用相同的数据来为其预测训练模型。这样就避免了过拟合。如果过拟合，我们将错误地拉低了漏报率，这使得我们难以改进算法或者应用到现实生活中。Scikit-learn 有一个叫做 crossvalpredict ，它可以帮助我们理解交叉算法.我们还需要一种算法来帮我们预测。我们还需要一个分类器来做二元分类。目标变量 foreclosure_status 只有两个值， True 和 False。这里我们用 逻辑回归算法，因为它能很好的进行二元分类，并且运行很快，占用内存很小。我们来说一下它是如何工作的：不使用像随机森林一样多树结构，也不像支持向量机一样做复杂的转换，逻辑回归算法涉及更少的步骤和更少的矩阵。我们可以使用 scikit-learn 实现的逻辑回归分类器算法。我们唯一需要注意的是每个类的权重。如果我们使用等权重的类，算法将会预测每行都为 false，因为它总是试图最小化误差。不管怎样，我们重视有多少贷款要被取消赎回权而不是有多少不能被取消。因此，我们给逻辑回归类的 class_weight 关键字传递 balanced 参数，让算法可以为不同 counts 的每个类考虑不同的取消赎回权的权重。这将使我们的算法不会为每一行都预测 false，而是两个类的误差水平一致。做出预测既然完成了前期准备，我们可以开始准备做出预测了。我将创建一个名为 predict.py 的新文件，它会使用我们在最后一步创建的 train.csv 文件。下面的代码：导入所需的库创建一个名为 cross_validate 的函数：使用正确的关键词参数创建逻辑回归分类器创建用于训练模型的数据列的列表，移除 id 和 foreclosure_status 列交叉验证 train DataFrame返回预测结果import os import settings import pandas as pd from sklearn import cross_validation from sklearn.linear_model import LogisticRegression from sklearn import metrics def cross_validate(train): clf = LogisticRegression(random_state=1, class_weight="balanced") predictors = train.columns.tolist() predictors = [p for p in predictors if p not in settings.NON_PREDICTORS] predictions = cross_validation.cross_val_predict(clf, train[predictors], train[settings.TARGET], cv=settings.CV_FOLDS) return predictions 预测误差现在，我们仅仅需要写一些函数来计算误差。下面的代码：创建函数 compute_error：使用 scikit-learn 计算一个简单的精确分数（与实际 foreclosure_status 值匹配的预测百分比）创建函数 compute_false_negatives：为了方便，将目标和预测结果合并到一个 DataFrame查找漏报率找到原本应被预测模型取消赎回权，但实际没有取消的贷款数目除以没被取消赎回权的贷款总数目def compute_error(target, predictions): return metrics.accuracy_score(target, predictions) def compute_false_negatives(target, predictions): df = pd.DataFrame({"target": target, "predictions": predictions}) return df[(df["target"] == 1) & (df["predictions"] == 0)].shape[0] / (df[(df["target"] == 1)].shape[0] + 1) def compute_false_positives(target, predictions): df = pd.DataFrame({"target": target, "predictions": predictions}) return df[(df["target"] == 0) & (df["predictions"] == 1)].shape[0] / (df[(df["target"] == 0)].shape[0] + 1) 聚合到一起现在，我们可以把函数都放在 predict.py。下面的代码：读取数据集计算交叉验证预测计算上面的 3 个误差打印误差def read(): train = pd.read_csv(os.path.join(settings.PROCESSED_DIR, "train.csv")) return train if __name__ == "__main__": train = read() predictions = cross_validate(train) error = compute_error(train[settings.TARGET], predictions) fn = compute_false_negatives(train[settings.TARGET], predictions) fp = compute_false_positives(train[settings.TARGET], predictions) print("Accuracy Score: {}".format(error)) print("False Negatives: {}".format(fn)) print("False Positives: {}".format(fp)) 一旦你添加完代码，你可以运行 python predict.py 来产生预测结果。运行结果向我们展示漏报率为 .26，这意味着我们没能预测 26% 的取消贷款。这是一个好的开始，但仍有很多改善的地方！你可以在这里找到完整的 predict.py 文件。你的文件树现在看起来像下面这样：loan-prediction ├── data │ ├── Acquisition_2012Q1.txt │ ├── Acquisition_2012Q2.txt │ ├── Performance_2012Q1.txt │ ├── Performance_2012Q2.txt │ └── ... ├── processed │ ├── Acquisition.txt │ ├── Performance.txt │ ├── train.csv ├── .gitignore ├── annotate.py ├── assemble.py ├── predict.py ├── README.md ├── requirements.txt ├── settings.py 撰写 README既然我们完成了端到端的项目，那么我们可以撰写 README.md 文件了，这样其他人便可以知道我们做的事，以及如何复制它。一个项目典型的 README.md 应该包括这些部分：一个高水准的项目概览，并介绍项目目的任何必需的数据和材料的下载地址安装命令如何安装要求依赖使用命令如何运行项目每一步之后会看到的结果如何为这个项目作贡献扩展项目的下一步计划这里 是这个项目的一个 README.md 样例。下一步恭喜你完成了端到端的机器学习项目！你可以在这里找到一个完整的示例项目。一旦你完成了项目，把它上传到 Github 是一个不错的主意，这样其他人也可以看到你的文件夹的部分项目。这里仍有一些留待探索数据的角度。总的来说，我们可以把它们分割为 3 类： 扩展这个项目并使它更加精确，发现其他可以预测的列，并探索数据。这是其中一些想法：在 annotate.py 中生成更多的特性切换 predict.py 中的算法尝试使用比我们发表在这里的更多的房利美数据添加对未来数据进行预测的方法。如果我们添加更多数据，我们所写的代码仍然可以起作用，这样我们可以添加更多过去和未来的数据。尝试看看是否你能预测一个银行原本是否应该发放贷款（相对地，房利美是否应该获得贷款）移除 train 中银行在发放贷款时间的不知道的任何列当房利美购买贷款时，一些列是已知的，但之前是不知道的做出预测探索是否你可以预测除了 foreclosure_status 的其他列你可以预测在销售时资产值是多少？探索探索执行数据更新之间的细微差别你能否预测借款人会逾期还款多少次?你能否标出的典型贷款周期?将数据按州或邮政编码标出你看到一些有趣的模式了吗?如果你建立了任何有趣的东西,请在评论中让我们知道!如果你喜欢这篇文章，或许你也会喜欢阅读“构建你的数据科学作品集”系列的其他文章：用数据讲故事如何搭建一个数据科学博客构建一个可以帮你找到工作的数据科学作品集的关键找到数据科学用的数据集的 17 个地方via: https://www.dataquest.io/blog/data-science-portfolio-machine-learning/作者：Vik Paruchuri 译者：kokialoves, zky001, vim-kakali, cposture, ideas4u 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
ORWL：能够删除被篡改数据的微型开源计算机
在当今这个信息时代，安全是最重要的。恐怕没有人会希望自己的重要数据落入到坏人的手里。但是即便是无安全防护的硬件同样面临不少威胁，而大多数时候人们还只是对软件采取安全防护措施。ORWL 就是来改变这件事的。ORWL 是什么？ORWL 宣称是社区里“造得最安全的家用电脑”。 它是一台小型的飞碟形计算机，在设计上全面考虑了物理安全性。物理安全很重要，因为一旦有人获得了从物理上访问你的计算机的途径，那么就 Game Over 了，这是信息安全专业人员中的一个老生常谈。ORWL 的基本规格包括英特尔 Skylake M3 处理器、USB-C 和微型 HDMI 接口、8GB 内存、120G 固态硬盘、蓝牙、Wifi 和 NFC 技术。目前它支持的操作系统有 Ubuntu 16.04、Qubes OS，以及 Windows 10 等，开箱即用。你只需要有一个显示器，键盘和鼠标就可以开始使用它了。ORWL 是开源的ORWL 是完全开源的。这意味着，如果有人想设计一台自己的计算机或者对 ORWL 作出改进的话，原理图和设计文件、软件、固件、所有东西都是可以获取的。ORWL 是如何工作的？ORWL 使用自加密固态硬盘（SSD）。一个安全微控制器集成到其主板上来产生和存储加密密匙。一旦核实了系统的完整性和已验证用户，它就使用密匙来解密固态硬盘（SSD）。无论对 ORWL 进行任何类型的篡改，密匙都会立即删除固态硬盘（SSD）上的无用数据为了完成身份验证，ORWL 有一个使用和智能卡类似技术的密匙卡。它使用 NFC 技术来验证用户，同时使用蓝牙来检测用户是否在当前使用范围内。如果用户不在附近（不在使用范围内），ORWL 将会自动锁定。整个 ORWL 系统被包裹在一个到处伴有压力开关的活动翻盖网格里。安全微控制器持续监控专用惯性测量部件，活动翻盖网格，内部温度和电源输入电压，以用于检测篡改。这将防止访问内部组件，比如试图破坏翻盖将会触发安全微控制器从而删除加密密匙。此外，出于安全考虑，动态随机存储器（DRAM）也焊有外壳。这并不是全部安全防护措施，ORWL 还有更多详细的措施来确保设备绝对的物理安全性，包括冷启动防护，直接存储器访问（DMA）攻击防御等。更多信息可以在 ORWL 引导页找到。这儿是一个关于它如何工作的快速视频。ORWL 是信息安全的最终答案吗？令人沮丧的是，ORWL 并不是信息安全的最终答案。ORWL 只能为计算机提供物理安全，尽管这很强大并且看起来 极酷 （ totally ninja ） ，但是还有许多来自其他方面的攻击会损坏你的系统。然而，ORWL 确实从整体上提高了计算机的安全性。你认为 ORWL 怎么样？通过评论让我们知道你的想法。via: https://itsfoss.com/orwl-physically-secure-computer/作者：Munif Tanjim 译者：ucasFL 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
操作系统安全是现在最重要的事情，而 Linux 则是一个主要被讨论的部分。首先要解决的问题之一就是：我们如何确定提交到上游的补丁已经进行了代码审核？Wolfram Sang 从 2008 年开始成为一名 Linux 内核开发者，他经常在各地召开的 Linux 峰会上发表讲话，比如在 2016 年柏林 Linux 峰会，他提出了如何提高内核开发实践的想法。让我们来看看他的观点。在 2013 年的时候，你曾在爱丁堡（Edinburgh）提醒 ELCE 委员会，如果不作出改变，那么子系统的潜在问题和其他争议问题将会逐渐扩大。他们做出改变了吗？你所提及的那些事件发生了吗？是的，在某些程度上来说。当然了，Linux 内核是一个很多部分组成的项目，所以给以 Linux 各个子系统更多关注应该放在一个更重要的位置。然而，有太多的子系统“只是拼图中的一块”，所以通常来说，这些子系统的潜在问题还未被解决。你曾指出代码审核人数是一个大问题。为何你觉得 Linux 内核开发社区没有足够的代码审核人员呢？理由之一就是，大多数开发者实际上只是编写代码，而读代码并不多。这本是没有什么错，但却说明了并非每个人都是代码审核人员，所以我们真的应该鼓励每个人都进行代码审核。我所看到另一件事就是，但我们要请人员加入我们的社区时，最重要的考核就是补丁贡献数量。我个人认为这是很正常的，并且在初期总贡献量少的时候是非常好的做法。但是随着越来越多的人员，特别是公司的加入，我们就碰到源码审核的问题。但是别误解了，有着数量可观的贡献是很棒的。但目前需要指出的是，参与社区有着更多内涵，比方说如何为下一步发展负责。有些部分在改善，但是还不够。你认为更多的代码审核人员培训或者审核激励措施是否会有帮助？我最主要的观点就是要指出，现今仍存在问题。是的，目前为止我们做到很好，但不意味着全都做的很好。我们也有类似扩张方面的问题。让人们了解事实，是希望能够让一些团体对此感兴趣并参与其中。尽管，我并不认为我们需要特殊的训练。我所熟悉的一些代码审核人员都非常棒或者很有天赋，只是这类人太少或者他们的空闲时间太少。首先就是需要有这种内在动力，至于其它的，边做边学就非常好了。这又是我想要指出的优势之一：审核补丁能够使你成为更出色的代码开发者。依你之见，是否有那么一个受欢迎的大项目在扩张这方面做的很好，可以供我们借鉴？我还真不知道有这么一个项目，如果有的话随时借鉴。我很专注于 Linux 内核，所以可能会存在一些偏见。然而在我看来，Linux 内核项目在规模大小、贡献数量和多样性方面真的很特别。所以当我想要找另一个项目来寻找灵感以便改善工作流是很正常的想法，目前我们的扩张问题真的比较特别。而且我发现，看看其他子系统在内核中做了什么是一个很有的方法。你曾说安全问题是我们每个人都该想到的事情，那用户应该做些什么来避免或者改善安全问题的危险？在今年（2016年）柏林 Linux 峰会我的谈话是针对开发层面的。安全隐患可能来自于没有正确审核的补丁中。我并不想要用户亲自解决这种问题，我更希望这些安全问题永远不会出现。当然这是不可能的，但这仍然是我处理问题所首选的方法。我很好奇这个庞大社区如何改善这些问题。是否有你希望用户定期以文件形式提交的某些类型的错误报告？需要定期检查的区域却因为某些原因没有注意到的？我们并不缺少错误报告。我所担心的是：由于代码审核人员的短缺造成补丁不完整，从而导致更多的错误报告。所以，到时候不仅需要处理大量的贡献，还需要处理更多错误或者进行版本回退。你是否还有什么事情希望我们读者知道，以了解你所在的努力？Linux 内核的特殊性，常常让我牢记着，在底层它就是代码而已。via: https://opensource.com/business/16/10/linux-kernel-review作者：Deb Nicholson 译者：GHLandy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
NitroShare：内网多操作系统间快捷文件共享工具
网络的最重要用途之一就是实现文件共享的目的。现在，虽然有多种方式可以让在同一网络中的 Linux 和 Windows 以及 MacOS X 用户之间共享文件，但这篇文章，我们只打算介绍 NitroShare。这是一款跨平台、开源以及易于使用的应用软件，可以在本地网络（内网）中共享文件。NitroShare 大大简化了本地网络的文件共享操作，一旦安装上，它就会与操作系统无缝集成。Ubuntu 系统中，从应用程序显示面板中可以简单的打开，在 Windows 系统中，在系统托盘中可以找到它。此外，在装有 NitroShare 的机器上，它会自动检测在同一网段的其它安装了它的设备，用户只需选择好需要传输到的设备，就可以直接向其传输文件。NitroShare 的特性如下：跨平台，即可以运行于 Linux， Windows 和 MacOS X 系统设置容易，无需配置易于使用支持在本地网络上自动发现运行着 Nitroshare 设备的能力安全性上支持可选的 TLS ( 传输层安全协议 （ Transport Layer Security ） ) 编码传输方式支持网络高速传输功能支持文件和目录（Windows 上的文件夹）传输支持对发送文件、连接设备等这些的桌面通知功能最新版本的 NitroShare 是使用 Qt5 开发的，它做了一些重大的改进，例如：用户界面焕然一新简化设备发现过程移除不同版本传输文件大小的限制为了使用方便，已经去除配置向导Linux 系统中安装 NitroshareNitroShare 可运行于各种各样的现代 Linux 发行版和桌面环境。Debian Sid 和 Ubuntu 16.04+NitroShare 已经包含在 Debian 和 Ubuntu 的软件源仓库中，所以可以很容易的就安装上，使用如下命令：$ sudo apt-get install nitroshare 但安装的版本可能已经过期了。要安装最新的版本的话，可按照如下的命令添加最新的 PPA。$ sudo apt-add-repository ppa:george-edison55/nitroshare $ sudo apt-get update $ sudo apt-get install nitroshare Fedora 24-23最近，NitroShare 已经包含在 Fedora 源仓库中了，可以按如下命令安装：$ sudo dnf install nitroshare Arch Linux在 Arch Linux 系统中，NitroShare 包在 AUR 上已经可用了，可以用如下命令来构建/安装：# wget https://aur.archlinux.org/cgit/aur.git/snapshot/nitroshare.tar.gz # tar xf nitroshare.tar.gz # cd nitroshare # makepkg -sri Linux 中使用 NitroShare注意：如我前面所述，在本地网络中，您想要共享文件的其它机器设备都需要安装上 NitroShare 并运行起来。在成功安装后，在系统 dash 面板里或系统菜单里搜索 NitroShare，然后启动。NitroShare 非常容易使用，你可从该应用或托盘图标上找到“发送文件”、“发送目录”、“查看传输”等选项。选择文件后，点击“打开”继续选择目标设备，如下图所示。如果在本地网络有设备正的运行 NitroShare 的话，选择相应的设备然后点击“确定”。如果需要，在 NitroShare 的配置 -- 通用标签页里，您可以增加设备的名字，设置默认文件下载位置，在高级设置里您能设置端口、缓存、超时时间等等。主页：https://nitroshare.net/index.html这就是所要介绍的，如果您有关于 Nitroshare 的任何问题，可以在下面的评论区给我们分享。您也可以给我们提供一些建议，告诉一些可能我们不知道的很不错的跨平台文件共享应用程序。via: http://www.tecmint.com/nitroshare-share-files-between-linux-ubuntu-windows/作者：Aaron Kili 译者：runningwater 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出