<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Shunliz个人主页</title>
    <description>Shunliz&apos;s personal blog</description>
    <link>https://shunliz.github.io/</link>
    <atom:link href="https://shunliz.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 09 Apr 2026 08:16:31 +0000</pubDate>
    <lastBuildDate>Thu, 09 Apr 2026 08:16:31 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>机器学习43条军规</title>
        <description>&lt;h1 id=&quot;机器学习43条军规解密谷歌机器学习工程最佳实践&quot;&gt;机器学习43条军规：解密谷歌机器学习工程最佳实践&lt;/h1&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;rule-1-dont-be-afraid-to-launch-a-product-without-machine-learning&quot;&gt;Rule #1: Don’t be afraid to launch a product without machine learning.&lt;/h1&gt;

&lt;p&gt;规则1：不要害怕上线没有机器学习的产品。
中心思想一句话概括：If you think that machine learning will give you a 100% boost, then a heuristic will get you 50% of the way there.&lt;/p&gt;

&lt;h1 id=&quot;rule-2-first-design-and-implement-metrics&quot;&gt;Rule #2: First, design and implement metrics.&lt;/h1&gt;

&lt;p&gt;规则2：在动手之前先设计和实现评价指标。
在构建具体的机器学习系统之前，首先在当前系统中记录尽量详细的历史信息，留好特征数据。这样不仅能够留好特征数据，还能够帮助我们随时了解系统的状态，以及做各种改动时系统的变化。&lt;/p&gt;

&lt;h1 id=&quot;rule-3-choose-machine-learning-over-a-complex-heuristic&quot;&gt;Rule #3: Choose machine learning over a complex heuristic.&lt;/h1&gt;

&lt;p&gt;规则3：不要使用过于复杂的规则系统，使用机器学习系统。
简单来讲，复杂的规则系统难以维护，不可扩展，而我们很简单就可以转为ML系统，变得可维护可扩展。&lt;/p&gt;

&lt;p&gt;ML Phase I: Your First Pipeline&lt;/p&gt;

&lt;p&gt;构建第一个ML系统时，一定要更多关注系统架构的建设。虽然机器学习的算法令人激动，但是基础架构不给力找不到问题时会令人抓狂。&lt;/p&gt;

&lt;h1 id=&quot;rule-4-keep-the-first-model-simple-and-get-the-infrastructure-right&quot;&gt;Rule #4: Keep the first model simple and get the infrastructure right.&lt;/h1&gt;

&lt;p&gt;规则4：第一个模型要简单，但是架构要正确。
第一版模型的核心思想是抓住主要特征、与应用尽量贴合以及快速上线。&lt;/p&gt;

&lt;h1 id=&quot;rule-5-test-the-infrastructure-independently-from-the-machine-learning&quot;&gt;Rule #5: Test the infrastructure independently from the machine learning.&lt;/h1&gt;

&lt;p&gt;规则5：独立于机器学习来测试架构流程。
确保架构是可单独测试的，将系统的训练部分进行封装，以确保其他部分都是可测试的。特别来讲：&lt;/p&gt;

&lt;p&gt;测试数据是否正确进入训练算法。检查具体的特征值是否符合预期。
测试实验环境给出的预测结果与线上预测结果是否一致。&lt;/p&gt;
&lt;h1 id=&quot;rule-6-be-careful-about-dropped-data-when-copying-pipelines&quot;&gt;Rule #6: Be careful about dropped data when copying pipelines.&lt;/h1&gt;

&lt;p&gt;规则6：复制pipeline时要注意丢弃的数据。
从一个场景复制数据到另一个场景时，要注意两边对数据的要求是否一致，是否有数据丢失的情况。&lt;/p&gt;

&lt;h1 id=&quot;rule-7-turn-heuristics-into-features-or-handle-them-externally&quot;&gt;Rule #7: Turn heuristics into features, or handle them externally.&lt;/h1&gt;

&lt;p&gt;规则7：将启发规则转化为特征，或者在外部处理它们。
机器学习系统解决的问题通常都不是新问题，而是对已有问题的进一步优化。这意味着有很多已有的规则或者启发式规则可供使用。这部分信息应该被充分利用（例如基于规则的推荐排序时用到的排序规则）。下面是几种启发式规则可以被使用的方式：&lt;/p&gt;

&lt;p&gt;用启发规则进行预处理。如果启发式规则非常有用，可以这么用。例如在垃圾邮件识别中，如果有发件人已经被拉黑了，那么就不要再去学“拉黑”意味着什么，直接拉黑就好了。
制造特征。可以考虑从启发式规则直接制造一个特征。例如，你使用启发式规则来计算query的相关性，那么就可以把这个相关性得分作为特征使用。后面也可以考虑将计算相关性得分的原始数据作为特征，以期获得更多的信息。
挖掘启发式规则的原始输入。如果有一个app的规则启发式规则综合了下载数、标题文字长度等信息，可以考虑将这些原始信息单独作为特征使用。
修改label。当你觉得启发式规则中包含了样本中没有包含的信息时可以这么用。例如，如果你想最大化下载数，同时还想要追求下载内容的质量。一种可行的方法是将label乘以app的平均star数。在电商领域，也常常用类似的方法，例如在点击率预估的项目中，可考虑对最终下单的商品或者高质量的商品对应的样本增加权重。
已有的启发式规则可以帮助机器学习系统更平滑的过渡，但是也要考虑是否有同等效果更简单的实现方式。&lt;/p&gt;

&lt;p&gt;Monitoring&lt;/p&gt;

&lt;p&gt;概括来讲，要保持好的监控习惯，例如使报警是可应对的，以及建设一个Dashboard页面。&lt;/p&gt;

&lt;h1 id=&quot;rule-8-know-the-freshness-requirements-of-your-system&quot;&gt;Rule #8: Know the freshness requirements of your system.&lt;/h1&gt;

&lt;p&gt;规则8：了解你系统对新鲜度的要求。
如果模型延迟一天更新，你的系统会受到多大的效果影响？如果是一周的延迟呢？或者更久？这个信息可以让我们排布监控的优先级。如果模型一天不更新收入就会下降10%，那么可以考虑让一个工程师全天候监控它。了解系统对新鲜度的要求是决定具体监控方案的第一步。&lt;/p&gt;

&lt;h1 id=&quot;rule-9-detect-problems-before-exporting-models&quot;&gt;Rule #9: Detect problems before exporting models.&lt;/h1&gt;

&lt;p&gt;规则9：在模型上线之前检测问题。
模型上线前一定要做完整性、正确性检查，例如AUC、Calibration、NE等指标的计算确认等。如果是模型上线前出了问题，可以邮件通知，如果是用户正在使用的模型出了问题，就需要电话通知了。&lt;/p&gt;

&lt;h1 id=&quot;rule-10-watch-for-silent-failures&quot;&gt;Rule #10: Watch for silent failures.&lt;/h1&gt;

&lt;p&gt;规则10：关注静默失败。
这是一个非常重要，而又经常容易被忽略的问题。所谓的静默失败指的是全部流程都正常完成，但是背后依赖数据出了问题，导致模型效果逐步下降的问题。这种问题在其他系统中并不常出现，但是在机器学习系统中出现几率会比较高。例如训练依赖的某张数据表很久没有更新了，或者表中的数据含义发生了变化等，再或者数据的覆盖度忽然变少，都会对效果产生很大的影响。解决方法是是对关键数据的统计信息进行监控，并且周期性对关键数据进行人工检查。&lt;/p&gt;

&lt;p&gt;#Rule #11: Give feature column owners and documentation.&lt;/p&gt;

&lt;p&gt;规则11：给特征组分配负责人，并记录文档。
这里的feature column指的是一个特征组，例如用户可能属于的国家这组特征就是一个feature column。&lt;/p&gt;

&lt;p&gt;如果系统庞大，数据繁多，那么知道每组数据由谁生成就变得非常重要。虽然数据都有简单描述，但是关于特征的具体计算逻辑，数据来源等都需要更详细的记录。&lt;/p&gt;

&lt;p&gt;Your Fist Objective&lt;/p&gt;

&lt;p&gt;objective是模型试图优化的值，而metric指的是任何用来衡量系统的值。&lt;/p&gt;

&lt;h1 id=&quot;rule-12-dont-overthink-which-objective-you-choose-to-directly-optimize&quot;&gt;Rule #12: Don’t overthink which objective you choose to directly optimize.&lt;/h1&gt;

&lt;p&gt;规则12：不要过于纠结该优化哪个目标。
机器学习上线的初期，即使你只优化一个目标，很多指标一般都会一起上涨的。所以不用太纠结究竟该优化哪个。&lt;/p&gt;

&lt;p&gt;虽然大佬这么说，但是在我自己的实践经验中，只优化一个目标，系统的整体效果却未必会上涨。典型的如推荐系统的CTR模型，上线之后CTR确实会提升，但是对应的CVR很有可能会下降，这时还需要一个CVR模型，两个模型同时使用才能真正提升系统效果。究其原因，是因为每个目标只关注系统整个过程的一个子过程，贪心地去优化这个子过程，不一定能够得到全局的最优解，通常需要把主要的几个子过程都优化之后，才能取得整体效果的提升。&lt;/p&gt;

&lt;p&gt;Rule #13: Choose a simple, observable and attributable metric for your first objective.&lt;/p&gt;

&lt;p&gt;规则13：为你的第一个objective选择一个简单可观测可归因的metric。
objective应该是简单可衡量的，并且是metric的有效代理。最适合被建模的是可直接观测并被归因的行为，例如：&lt;/p&gt;

&lt;p&gt;链接是否被点击？
软件是否被下载？
邮件是否被转发？
……
尽量不要在第一次就建模非直接效果的行为，例如：&lt;/p&gt;

&lt;p&gt;用户第二天是否会访问？
用户在网站上停留了多久？
日活用户有多少？
非直接指标是很好的metric，可以用ABTest来进行观测，但不适合用作优化指标。此外，千万不要试图学习以下目标：&lt;/p&gt;

&lt;p&gt;用户对产品是否满意？
用户对体验是否满意？
……
这些指标非常重要，但是非常难以学习。应该使用一些代理指标来学习，通过优化代理指标来优化这些非直接指标。为了公司的发展着想，最好有人工来连接机器学习的学习目标和产品业务。&lt;/p&gt;

&lt;p&gt;#　Rule #14: Starting with an interpretable model makes debugging easier.&lt;/p&gt;

&lt;p&gt;规则14：使用可解释性强的模型可降低debug难度。
优先选择预测结果有概率含义、预测过程可解释的模型，可以更容易的确认效果，debug问题。例如，如果使用LR做分类，那么预测过程不外乎一些相乘和相加，如果特征都做了离散化，就只有加法了，这样很容易debug一条样本的预测得分是如何被计算出来的。所以出了问题很容易debug。&lt;/p&gt;

&lt;h1 id=&quot;rule-15-separate-spam-filtering-and-quality-ranking-in-a-policy-layer&quot;&gt;Rule #15: Separate Spam Filtering and Quality Ranking in a Policy Layer.&lt;/h1&gt;

&lt;p&gt;规则15：将垃圾过滤和质量排序的工作分离，放到策略层（policy layer）。
排序系统工作的环境中数据分布是相对静态的，大家为了得到更好的排序，会遵守系统制定的规则。但是垃圾过滤更多是个对抗性质的工作，数据分布会经常变动。所以不应该让排序系统去处理垃圾信息的过滤，而是应该有单独的一层去处理垃圾信息。这也是一种可以推广的思想，那就是：排序层只做排序层的事情，职责尽量单一，其他工作让架构上更合适的模块去处理。此外，为了提升模型效果，应该把垃圾信息从训练数据中去除。&lt;/p&gt;

&lt;p&gt;ML Phase II: Feature Engineering&lt;/p&gt;

&lt;p&gt;前面第一阶段的重点是把数据喂到学习系统中，有了基础的监控指标，有了基础的架构。等这一套系统建立起来后，第二阶段就开始了。&lt;/p&gt;

&lt;p&gt;整体来讲，第二阶段的核心工作是将尽量多的有效特征加入到第一版的系统中，一般都可以取得提升。&lt;/p&gt;

&lt;h1 id=&quot;rule-16-plan-to-launch-and-iterate&quot;&gt;Rule #16: Plan to launch and iterate.&lt;/h1&gt;

&lt;p&gt;规则16：做好持续迭代上线的准备。
简单来说，就是要深刻认识到，系统优化永远没有终点，所以系统设计方面要对迭代非常友好。例如增加删除特征是否足够简单，正确性验证是否足够简单，模型迭代是否可以并行运行，等等。&lt;/p&gt;

&lt;p&gt;这虽然不是一条具体可行动的（actionable）规则，但是这种思想上的准备对整个系统的开发很有帮助。只有真正深刻意识到了系统持续迭代上线的本质，才会在设计在线和离线架构时为持续迭代最好相应的设计，并做好相应的工具，而不是做一锤子系统。&lt;/p&gt;

&lt;h1 id=&quot;rule-17-start-with-directly-observed-and-reported-features-as-opposed-to-learned-features&quot;&gt;Rule #17: Start with directly observed and reported features as opposed to learned features.&lt;/h1&gt;

&lt;p&gt;规则17：优先使用直接观测或收集到的特征，而不是学习出来的特征。
所谓学习出来的特征，指的是用另外的算法学习出来的特征，而非可以直接观测或收集到的简单特征。学习出来的特征由于存在外部依赖，或者计算逻辑复杂，不一定适用于你当前的模型，所以稳定性和有效性会有风险。而直接可观测的特征由于是相对比较客观的，依赖较少的，所以比较稳定。&lt;/p&gt;

&lt;h1 id=&quot;rule-18-explore-with-features-of-content-that-generalize-across-contexts&quot;&gt;Rule #18: Explore with features of content that generalize across contexts.&lt;/h1&gt;

&lt;p&gt;规则18：探索使用可以跨场景的内容特征。
中心思想是在说，要多利用可以在多个场景下使用的特征，例如全局的点击率、浏览量这些特征，可以在多个场景下作为特征使用。这样可以在一些冷启动或者缺乏有效特征的场景下作为特征使用。&lt;/p&gt;

&lt;p&gt;R# ule #19: Use very specific features when you can.&lt;/p&gt;

&lt;p&gt;规则19：尽量使用非常具体的特征。
如果数据量足够大，那么相比少数复杂特征，使用海量简单特征是更简单有效的选择。&lt;/p&gt;

&lt;p&gt;所谓非常具体，指的是覆盖样本量比较少的特征，例如文档的ID或者query的ID等。这样的特征虽然每个只覆盖很少一部分特征，但是只要这一组特征整体能够覆盖率比较高，例如90%，那就是OK的。而且还可以通过正则化来消除覆盖率过低或者相关性差的特征。这也是大家都偏爱大规模ID特征的一个原因，现在很多大厂的排序模型特征都大量使用了大规模ID特征。&lt;/p&gt;

&lt;h1 id=&quot;rule-20-combine-and-modify-existing-features-to-create-new-features-in-human-understandable-ways&quot;&gt;Rule #20: Combine and modify existing features to create new features in human­-understandable ways.&lt;/h1&gt;

&lt;p&gt;规则20：用人类可理解的方式对已有特征进行组合、修改来得到新特征。
离散化和交叉是最常用的两种特征使用方式。其本质都是用特征工程的方式，在不改变使用模型本身的情况下增加模型的非线性。这两种方法本身没什么好说的，值得一致的是，在大规模ID类特征的交叉时，例如一段是query里的关键词，另一端是文档里的关键词，那就会产生很大量级的交叉特征，这时有两种处理方法：&lt;/p&gt;

&lt;p&gt;点积。其实计算query和文档共同包含的关键词数量。
交集。每一维特征的含义是某个词同时出现在了query和文档中，同时出现则该维特征为1，否则为0。
所谓“人类可理解的方式”，我的理解就是离散化和交叉要基于对业务逻辑的理解，不能乱交叉。&lt;/p&gt;

&lt;h1 id=&quot;rule-21-the-number-of-feature-weights-you-can-learn-in-a-linear-model-is-roughly-proportional-to-the-amount-of-data-you-have&quot;&gt;Rule #21: The number of feature weights you can learn in a linear model is roughly proportional to the amount of data you have.&lt;/h1&gt;

&lt;p&gt;规则21：线性模型中可学到的特征权重数量，与训练数据的数量大体成正比。
这背后有复杂的统计原理做支撑，但你只需要知道结论就可以了。这个原则给我们的启示，是要根据数据量来选择特征的生成方式，例如：&lt;/p&gt;

&lt;p&gt;如果你的系统是一个搜索系统，query和文档中有百万级的词，但是你只有千级别的标注样本。那你就别用ID级关键词特征了，而是要考虑点积类特征，把特征数量控制在几十个这个级别。
如果你拥有百万级样本，那么可以将文档和query的关键词进行交叉特征，然后用正则化进行特征选择。这样你会得到百万级特征，但是正则化之后会更少。所以说，千万级样本，十万级特征。
如果你有十亿级或者更高级别的样本，那么你可以使用query和文档的ID级特征，然后加上特征选择和正则化。十亿级样本，千万级特征。
总结起来就是，根据样本决定特征使用方式，样本不够就对特征进行高层次抽象处理，指导和样本量级相匹配。&lt;/p&gt;

&lt;h1 id=&quot;rule-22-clean-up-features-you-are-no-longer-using&quot;&gt;Rule #22: Clean up features you are no longer using.&lt;/h1&gt;

&lt;p&gt;规则22：清理不再使用的特征。
如果某个特征已经没有用，并且它与其他特征的交叉也已经没有用，就应该将其清理掉，保持架构的整洁性。&lt;/p&gt;

&lt;p&gt;在考虑添加或保留哪些特征时，需要统计一下特征的样本覆盖率，例如一些整体覆盖率很低的个性化feature column，只有很少用户能覆盖到，那么大概率这组特征作用不大。但另一方面，如果某个特征覆盖率很低，例如只有1%，但是其区分度非常大，例如90%取值为1的样本都是正样本，那么 这个特征就值得加入或保留。&lt;/p&gt;

&lt;p&gt;Human Analysis of the System&lt;/p&gt;

&lt;p&gt;在更进一步之前，我们需要了解一些机器学习课程上不会教你的内容：如何观察分析模型，并改进它。用作者的话说，这更像是一门艺术 ，但仍然有一些规律可循。&lt;/p&gt;

&lt;h1 id=&quot;rule-23-you-are-not-a-typical-end-user&quot;&gt;Rule #23: You are not a typical end user.&lt;/h1&gt;

&lt;p&gt;规则23：你不是一个典型的终端用户。
这条规则的中心思想是说，虽然吃自己的狗食是必要的，但也不要总是从工程师的角度来衡量模型的好坏。这不仅可能不值当，而且可能看不出问题。所谓不值当，是因为工程师的时间太贵了，这个大家都懂；而所谓看不出问题，是因为工程师自己看自己开发的模型，容易看不出问题，所谓“不识庐山真面目”。&lt;/p&gt;

&lt;p&gt;所以作者认为合理的方法是让真正的终端用户来衡量模型或产品的好坏。要么通过线上ABTest，要么通过众包的方式来做。&lt;/p&gt;

&lt;h1 id=&quot;rule-24-measure-the-delta-between-models&quot;&gt;Rule #24: Measure the delta between models.&lt;/h1&gt;

&lt;p&gt;规则24：离线衡量模型之间的差异。
原文没有说是离线，但我通过上下文理解他说的应该是离线。这一条规则说的是新模型在上线之前，需要先和老模型做差异对比。所谓差异对比，指的是对于同样的输入，新旧两个模型给出的结果是否差异足够大。例如对于同一个query，两个排序模型给出的差异是否足够大。如果离线计算发现差异很小，那也没必要上线测试了，因为上线后差异肯定也大不了。如果差异比较大，那么还需要看差异是不是好的差异。通过观察差异可以得知新模型究竟对数据产生了什么影响，这种影响是好是坏。&lt;/p&gt;

&lt;p&gt;当然，这一切的前提是你需要有一个稳定的对比系统， 起码一个模型和他自己对比的话差异应该非常小，最好是零差异。&lt;/p&gt;

&lt;h1 id=&quot;rule-25-when-choosing-models-utilitarian-performance-trumps-predictive-power&quot;&gt;Rule #25: When choosing models, utilitarian performance trumps predictive power.&lt;/h1&gt;

&lt;p&gt;规则25：当选择模型时，实用性指标比预测能力更重要。
这是一条很有用的经验。虽然我们训练模型时objective一般都是logloss，也就是说实在追求模型的预测能力。但是我们在上层应用中却可能有多种用途，例如可能会用来排序，那么这时具体的预测能力就不如排序能力重要；如果用来划定阈值然后跟根据阈值判断垃圾邮件，那么准确率就更重要。当然大多数情况下这几个指标是一致的。&lt;/p&gt;

&lt;p&gt;除了作者说的这一点，还有一种情况是需要特别注意的，那就是我们在训练时可能会对样本做采样，导致得到的预测值整体偏高或偏低。如果这个预测值是用来直接排序的，那么这个变化关系不大，但如果有其他用处，例如和另外的值相乘，典型的如广告场景下的CTR&lt;em&gt;bid，或者电商推荐排序下的CTR&lt;/em&gt;CVR，在这类场景下，预测值本身的准确性也很重要，就需要对其进行校准（calibrate），使其与采样前的样本点击率对齐。&lt;/p&gt;

&lt;h1 id=&quot;rule-26-look-for-patterns-in-the-measured-errors-and-create-new-features&quot;&gt;Rule #26: Look for patterns in the measured errors, and create new features.&lt;/h1&gt;

&lt;p&gt;规则26：在错误中发现模式，并创建新特征。
这算是一种用来提升模型效果的通用思路。具体来说，指的是观察训练数据中模型预测错误的样本，看看是否能够通过添加额外特征来使得这条样本被模型预测正确。之所以使用训练集中的数据，是因为这部分数据是模型已经试图优化过的，这里面的错误，是模型知道自己搞错了，目前学不出来的，所以如果你给它足够好的其他特征，它或许就能把这条样本学对了。&lt;/p&gt;

&lt;p&gt;一旦发现错误的模式，就可以在当前系统之外寻找新的特征。例如，如果你发现当前系统倾向于错误地把长文章排到后面，那么就可以加入文章长度这一特征，让系统去学习文章长度的相关性和重要性。&lt;/p&gt;

&lt;h1 id=&quot;rule-27-try-to-quantify-observed-undesirable-behavior&quot;&gt;Rule #27: Try to quantify observed undesirable behavior.&lt;/h1&gt;

&lt;p&gt;规则27：尽量将观测到的负面行为量化。
如果在系统中观察到了模型没有优化到的问题，典型的例如推荐系统逼格不够这种问题，这时应该努力将这种不满意转化为具体的数字，具体来讲可以通过人工标注等方法标注出不满意的物品，然后进行统计。如果问题可以被量化，后面就可以将其用作特征、objective或者metric。整体原则就是“先量化，再优化”。&lt;/p&gt;

&lt;p&gt;多说一句，这里的优化，不一定是用模型来优化，而是指的整体优化。比如推荐系统逼格这种问题，模型可能很难优化，但是只要能量化出来，就可以通过其他方法来尽量减少，例如单独去学习有逼格物品的特征，或者在召回阶段进行一定倾斜。&lt;/p&gt;

&lt;h1 id=&quot;rule-28-be-aware-that-identical-short-term-behavior-does-not-imply-identical-long-term-behavior&quot;&gt;Rule #28: Be aware that identical short-­term behavior does not imply identical long­-term behavior.&lt;/h1&gt;

&lt;p&gt;规则28：要注意短期内观察到的类似行为不一定会长期存在。
假设你搞了个系统，通过学习每个具体的文档ID和query ID，计算出了每个query下每个文档的点击率。通过离线对比和ABTest，你发现这个系统的行为和当前系统的行为一毛一样，而这个系统又更简单，所以你就把这个系统上线了。后面你会发现这个系统在任何query下都不会给出任何新的文档。奇怪吗？一点都不奇怪，因为你只让它记住了之前的历史数据，它对新数据没有任何信息。&lt;/p&gt;

&lt;p&gt;所以唯一能够衡量一个系统是否长期有效的方法，就是让它使用该模型在线上时收集到的真实数据上进行训练。当然这有难度。&lt;/p&gt;

&lt;p&gt;往大了说，作者这条规则其实说的是个系统或者模型的泛化能力，如果一个系统或者模型不能对新数据做出很好的预测，那么无论他的离线表现如何，都不能代表它的真正能力。再换个角度来看，一个系统必须具有持续学习适应新数据的能力，才能是一个合格的机器学习系统，否则就只是个学舌的鹦鹉。&lt;/p&gt;

&lt;p&gt;Training-Serving Skew&lt;/p&gt;

&lt;p&gt;训练和服务之间的差异问题时一个大话题，主要原因包括训练时与服务时数据获取方式不同、训练时与服务时数据分布不同以及模型和算法之间的反馈循环等。作者说这种差异在G家的多条产品线上出现过，都产生了负面影响。但要我说这绝对不仅仅是谷歌的问题，谷歌绝对是做的比较好的了，各种中小厂里面这种问题只多不少，所以这部分的经验是非常宝贵的。解决这类问题的核心是对系统和数据的变化进行监控，确保一切差异都在监控之内，不会悄悄进入系统。&lt;/p&gt;

&lt;h1 id=&quot;rule-29-the-best-way-to-make-sure-that-you-train-like-you-serve-is-to-save-the-set-of-features-used-at-serving-time-and-then-pipe-those-features-to-a-log-to-use-them-at-training-time&quot;&gt;Rule #29: The best way to make sure that you train like you serve is to save the set of features used at serving time, and then pipe those features to a log to use them at training time.&lt;/h1&gt;

&lt;p&gt;规则29：保证服务与训练一致性的最好方法是将服务时的特征保存下来，然后通过日志将特征喂到训练过程中去。
这句话基本道出了保证差异最小化的核心套路。这种基于特征日志的方法可以极大提升效果，同时能够减少代码复杂度。谷歌的很多团队也正在往这种做法上迁移。&lt;/p&gt;

&lt;h1 id=&quot;rule-30-importance-weight-sampled-data-dont-arbitrarily-drop-it&quot;&gt;Rule #30: Importance weight sampled data, don’t arbitrarily drop it!&lt;/h1&gt;

&lt;p&gt;规则30：对采样样本做重要性赋权，不要随意丢弃！
这是作者唯一用了感叹号的一条，可想而知背后的辛酸。当我们有太多训练数据时，我们会只取其中的一部分。但这是错误的。正确的做法是，如果你给某条样本30%的采样权重，那么在训练时就给它10/3的训练权重。通过这样的重要性赋权（importance weight），整个训练结果的校准性（calibration）就还能够保证。&lt;/p&gt;

&lt;p&gt;多说一句，这个校准性非常的重要，尤其对于广告系统，或者多个预测值相加或相乘来得到最终结果的系统。如果单个值没有校准，偏低或偏高，那么在相乘或相加之后其含义就会不正确。如果直接使用模型预测值进行排序，校准性就没那么重要，因为校准性不会影响排序，只会影响具体的值。&lt;/p&gt;

&lt;h1 id=&quot;rule-31-beware-that-if-you-join-data-from-a-table-at-training-and-serving-time-the-data-in-the-table-may-change&quot;&gt;Rule #31: Beware that if you join data from a table at training and serving time, the data in the table may change.&lt;/h1&gt;

&lt;p&gt;规则31：如果你在训练时和服务时都在join一张表，那么要注意这张表的数据可能会发生变化。
比如说某张表里存着一些文档的特征，你在离线训练之前要去这个表里取这些特征用来训练，但这里就有个风险，那就是这个表里的数据在你离线取的时候和在线服务的时候数据不一样，发生了变化。最好的解决方式就是在服务端将特征记录在日志中，这样能保证数据的一致性。或者如果这张表的变化频率比较低，也可以考虑对其做小时级或天级备份，以此来减少这种差异。但要记住这种方法并不能彻底解决这个问题。&lt;/p&gt;

&lt;h1 id=&quot;rule-32-reuse-code-between-your-training-pipeline-and-your-serving-pipeline-whenever-possible&quot;&gt;Rule #32: Re­use code between your training pipeline and your serving pipeline whenever possible.&lt;/h1&gt;

&lt;p&gt;规则32：尽量在训练pipeline和服务pipeline之间复用代码。
训练一般是离线批量进行的，而服务则是在线流式进行的，这两者之间虽然在处理数据的方式上存在着较大差异，但仍然有很多代码可以共享。这些代码的共享可以从代码层面介绍训练和服务之间的差异。换句话说，日志记录特征是从数据角度消除差异，那么代码复用就是从代码角度消除差异，双管齐下，效果更好。&lt;/p&gt;

&lt;h1 id=&quot;rule-33-if-you-produce-a-model-based-on-the-data-until-january-5th-test-the-model-on-the-data-from-january-6th-and-after&quot;&gt;Rule #33: If you produce a model based on the data until January 5th, test the model on the data from January 6th and after.&lt;/h1&gt;

&lt;p&gt;规则33：如果训练数据是1月5日之前的，那么测试数据要从1月6日开始。
这条规则的主要目的是让测试结果与线上结果更加接近，因为我们在使用模型时就是在用服务当天之前的数据训练，然后来预测当天的数据。这样得到的测试结果虽然可能会偏低，但却更加真实。&lt;/p&gt;

&lt;h1 id=&quot;rule-34-in-binary-classification-for-filtering-such-as-spam-detection-or-determining-interesting-emails-make-small-short-term-sacrifices-in-performance-for-very-clean-data&quot;&gt;Rule #34: In binary classification for filtering (such as spam detection or determining interesting e­mails), make small short-­term sacrifices in performance for very clean data.&lt;/h1&gt;

&lt;p&gt;规则34：在为过滤服务的二分类问题中（例如垃圾邮件过滤），可以为了干净的数据牺牲一些短期效果。
在过滤类的任务中，被标记为负的样本是不会展示给用户的，例如可能会把75%标记为负的样本阻拦住不展现给用户。但如果你只从展示给用户的结果中获取下次训练的样本，显然你的训练样本是有偏的。&lt;/p&gt;

&lt;p&gt;更好的做法是使用一定比例的流量（例如1%）专门收集训练数据，在这部分流量中的用户会看到所有的样本。这样显然会影响线上的真实过滤效果，但是会收集到更好的数据，更有利于系统的长远发展。否则系统会越训练越偏，慢慢就不可用了。同时还能保证至少过滤掉74%的负样本，对系统的影响也不是很大。&lt;/p&gt;

&lt;p&gt;但是如果你的系统会过滤掉95%或者更多的负样本，这种做法就不那么可行了。即使如此，为了准确衡量模型的效果，你仍然可以通过构造一个更小的数据集（0.1%或者更小）来测试。十万级别的样本足够给出准确的评价指标了。&lt;/p&gt;

&lt;h1 id=&quot;rule-35-beware-of-the-inherent-skew-in-ranking-problems&quot;&gt;Rule #35: Beware of the inherent skew in ranking problems.&lt;/h1&gt;

&lt;p&gt;规则35：注意排序问题中固有的数据偏置。
当新的排序算法对线上排序结果产生了重大改变时，你其实是改变了算法将来会看到的数据。这时这种偏置就会出现。这种问题有以下几种方法来解决，核心思想都是更偏重模型已经看到过的数据。&lt;/p&gt;

&lt;p&gt;对覆盖更多query（或类似角色，根据业务不同）的特征给予更强的正则化。这样模型会更偏重只覆盖一部分样本的特征，而不是泛化性特征。这样会阻止爆品出现在不相关query的结果中。
只允许特征取正的权重值。这样任何好特征都会比“未知”特征要好。
不要使用只和文档相关的特征。这是第一条的极端情况，否则会导致类似哈利波特效应的情况出现，也就是一条在任何query下都受欢迎的文档不会到处都出现。去除掉只和文档相关的特征会阻止这种情况发生。&lt;/p&gt;
&lt;h1 id=&quot;rule-36-avoid-feedback-loops-with-positional-features&quot;&gt;Rule #36: Avoid feedback loops with positional features.&lt;/h1&gt;

&lt;p&gt;规则36：使用位置特征来避免反馈回路。
大家都知道排序位置本身就会影响用户是否会对物品产生互动，例如点击。所以如果模型中没有位置特征，本来由于位置导致的影响会被算到其他特征头上去，导致模型不够准。可以用加入位置特征的方法来避免这种问题，具体来讲，在训练时加入位置特征，预测时去掉位置特征，或者给所有样本一样的位置特征。这样会让模型更正确地分配特征的权重。&lt;/p&gt;

&lt;p&gt;需要注意的是，位置特征要保持相对独立，不要与其他特征发生关联。可以将位置相关的特征用一个函数表达，然后将其他特征用另外的函数表达，然后组合起来。具体应用中，可以通过位置特征不与任何其他特征交叉来实现这个目的。&lt;/p&gt;

&lt;h1 id=&quot;rule-37-measure-trainingserving-skew&quot;&gt;Rule #37: Measure Training/Serving Skew.&lt;/h1&gt;

&lt;p&gt;规则37：衡量训练和服务之间的差异。
整体来讲有多种原因会导致这种差异，我们可以将其进行细分为以下几部分：&lt;/p&gt;

&lt;p&gt;训练集和测试集之间的差异。这种差异会经常存在，而且不一定是坏事。
测试集和“第二天”数据间的差异。这种差异也会一直存在，而这个“第二天”数据上的表现是我们应该努力优化的，例如通过正则化。这两者之间差异如果过大，可能是因为用到了一些时间敏感的特征，导致模型效果变化明显。
“第二天”数据和线上数据间的差异。如果同样一条样本，在训练时给出的结果和线上服务时给出的结果不一致，那么这意味着工程实现中出现了bug。
ML Phase III: Slowed Growth, Optimization Refinement, and Complex Models&lt;/p&gt;

&lt;p&gt;一般会有一些明确的信号来标识第二阶段的尾声。首先，每月的提升会逐步降低。你开始在不同指标之间做权衡，有的上升有的下降。嗯，游戏变得有趣了。既然收益不容易获得了，机器学习就得变得更复杂了。&lt;/p&gt;

&lt;p&gt;在前两个阶段，大部分团队都可以过得很开心，但到了这个阶段，每个团队都需要找到适合自己的路。&lt;/p&gt;

&lt;h1 id=&quot;rule-38-dont-waste-time-on-new-features-if-unaligned-objectives-have-become-the-issue&quot;&gt;Rule #38: Don’t waste time on new features if unaligned objectives have become the issue.&lt;/h1&gt;

&lt;p&gt;规则38：如果objective没有达成一致，不要在新特征上浪费时间。
当系统整体达到一个稳定期，大家会开始关注机器学习系统优化目标以外的一些问题。这个时候，目标就不如之前那么清晰，那么如果目标没有确定下来的话，先不要在特征上浪费时间。&lt;/p&gt;

&lt;h1 id=&quot;rule-39-launch-decisions-are-a-proxy-for-longterm-product-goals&quot;&gt;Rule #39: Launch decisions are a proxy for long­term product goals.&lt;/h1&gt;

&lt;p&gt;规则39：上线决策是长期产品目标的代理。
这句话读起来有点别扭，作者举了几个例子来说明，我觉得核心就是在讲一件事情：系统、产品甚至公司的长远发展需要通过多个指标来综合衡量，而新模型是否上线要综合考虑这些指标。所谓代理，指的就是优化这些综合指标就是在优化产品、公司的长远目标。&lt;/p&gt;

&lt;p&gt;决策只有在所有指标都在变好的情况下才会变得简单。但常常事情没那么简单，尤其是当不同指标之间无法换算的时候，例如A系统有一百万日活和四百万日收入，B系统有两百万日活和两百万日收入，你会从A切换到B吗？或者反过来？答案是或许都不会，因为你不知道某个指标的提升是否会cover另外一个指标的下降。&lt;/p&gt;

&lt;p&gt;关键是，没有任何一个指标能回答：“五年后我的产品在哪里”？&lt;/p&gt;

&lt;p&gt;而每个个体，尤其是工程师们，显然更喜欢能够直接优化的目标，而这也是机器学习系统常见的场景 。现在也有一些多目标学习系统在试图解决这种问题。但仍然有很多目标无法建模为机器学习问题，比如用户为什么会来访问你的网站等等。作者说这是个AI-complete问题，也常被称为强AI问题，简单来说就是不能用某个单一算法解决的问题。&lt;/p&gt;

&lt;h1 id=&quot;rule-40-keep-ensembles-simple&quot;&gt;Rule #40: Keep ensembles simple.&lt;/h1&gt;

&lt;p&gt;规则40：ensemble策略保持简单。
什么叫简单的ensemble？作者认为，只接受其他模型的输出作为输入，不附带其他特征的ensemble，叫做简单的ensemble。换句话说，你的模型要么是单纯的ensemble模型，要么是普通的接收大量特征的基模型。&lt;/p&gt;

&lt;p&gt;除了保持简单，ensemble模型最好还能具有一些良好的性质。例如，某个基模型的性能提升不能降低组合模型的性能。以及，基模型最好都是可解释的（例如是校准的)，这样基模型的变化对上层的组合模型来说也是可解释的。同时，一个基模型预测概率值的提升不会降低组合模型的预测概率值。&lt;/p&gt;

&lt;h1 id=&quot;rule-41-when-performance-plateaus-look-for-qualitatively-new-sources-of-information-to-add-rather-than-refining-existing-signals&quot;&gt;Rule #41: When performance plateaus, look for qualitatively new sources of information to add rather than refining existing signals.&lt;/h1&gt;

&lt;p&gt;规则41：当效果进入稳定期，寻找本质上新的信息源，而不是优化已有的信号。
你加了一些用户的人口统计学特征，你加了一些文档的文字特征，等等，但是关键指标上的提升还不到1%。现在咋整？&lt;/p&gt;

&lt;p&gt;这时就应该考虑加一些根本上不同的特征，例如用户再过去一天、一周看过的文档历史，或者另外一个数据源的数据。总之，要加入完全不同的维度的特征。此外也可以尝试使用深度学习，但同时也要调整你对ROI的预期，并且要评估增加的复杂度换来的收益是否值得。&lt;/p&gt;

&lt;h1 id=&quot;rule-42-dont-expect-diversity-personalization-or-relevance-to-be-as-correlated-with-popularity-as-you-think-they-are&quot;&gt;Rule #42: Don’t expect diversity, personalization, or relevance to be as correlated with popularity as you think they are.&lt;/h1&gt;

&lt;p&gt;规则42：多样性，个性化或者相关性与流行度的相关性关系可能要比你想的弱很多。
多样性意味着内容或者来源的多样性；个性化意味着每个用户得到不一样的东西；相关性意味着一个query的返回结果相比其他query与这个query更相关。所以这三个指标的含义都是与普通不一样。&lt;/p&gt;

&lt;p&gt;但问题在于普通的东西很难被打败。&lt;/p&gt;

&lt;p&gt;如果你的衡量指标是点击、停留时长、观看数、分享数等等，你本质上是在衡量东西的流行度。有的团队有时会希望学到一个多样化的个性化模型。为此，会加入个性化特征和多样化特征，但是最后会发现这些特征并没有得到预期的权重。&lt;/p&gt;

&lt;p&gt;这并不能说明多样性、个性化和相关性不重要。像前文指出，可以通过后续的处理来增加多样性或相关性。如果这时看到长期目标提升了，你就可以确定多样性/相关性是有用的。这时你就可以选择继续使用后续处理的方式，或者根据多样性和相关性直接修改要优化的objective。&lt;/p&gt;

&lt;h1 id=&quot;rule-43-your-friends-tend-to-be-the-same-across-different-products-your-interests-tend-not-to-be&quot;&gt;Rule #43: Your friends tend to be the same across different products. Your interests tend not to be.&lt;/h1&gt;

&lt;p&gt;规则43：你在不同产品上的好友一般是一样的，但你的兴趣通常会不一样。
谷歌经常在不同产品上使用同样的好友关系预测模型，并且取得了很好的效果，这证明不同的产品上好友关系是可以迁移的，毕竟他们是固定的同一批人。但他们尝试将一个产品上的个性化特征使用到另外一个产品上时却常常得不到好结果。可行的做法是使用一个数据源上的原始数据来预测另外数据源上的行为，而不是使用加工后的特征。此外，用户在另一个数据源上的行为历史也会有用。&lt;/p&gt;

&lt;h1 id=&quot;总结&quot;&gt;总结&lt;/h1&gt;

&lt;p&gt;从上面洋洋洒洒43条经验之谈中不难看出，大神作者认为，对于大多数机器学习应用场景来说，我们需要解决的问题大多数都是工程问题，解决这些工程问题需要的并不是复杂的理论，更多是对细节、架构、过程的仔细推敲和精致追求。而这些是我们非大神的普通人可以做到的，如果说大神做的是95分以上的系统，那么我们只要对工程架构、过程和细节做好足够的优化，我们也可以做出至少80分的系统。&lt;/p&gt;
</description>
        <pubDate>Sun, 29 Oct 2017 16:09:00 +0000</pubDate>
        <link>https://shunliz.github.io/ml/2017/10/29/google-ml-rule.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/ml/2017/10/29/google-ml-rule.html</guid>
        
        <category>ml</category>
        
        
        <category>ml</category>
        
      </item>
    
      <item>
        <title>常见机器学习方法总结</title>
        <description>&lt;p&gt;这里总结了常见的几个机器学习算法：朴素贝叶斯、决策树、逻辑回归、线性回归、KNN、SVM、Boosting、聚类、pLSA、LDA、GDBT、Regularization、异常检测、EM算法、Apriori、FP-Growth，从优点、缺点、需要注意的地方等几个方面进行了分析和讨论。&lt;/p&gt;

&lt;p&gt;原文链接：http://www.chinakdd.com/article-oyU85v018dQL0Iu.html&lt;/p&gt;

&lt;h1 id=&quot;朴素贝叶斯&quot;&gt;朴素贝叶斯&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;如果给出的特征向量长度可能不同，这是需要归一化为通长度的向量（这里以文本分类为例），比如说是句子单词的话，则长度为整个词汇量的长度，对应位置是该单词出现的次数。 　　&lt;/li&gt;
  &lt;li&gt;计算公式如下：&lt;/li&gt;
&lt;/ol&gt;

\[p(c_{i}|w) = \frac{p(w|c_{i})p(c_{i})}{p(w))}\]

&lt;p&gt;其中一项条件概率可以通过朴素贝叶斯条件独立展开。要注意一点就是&lt;/p&gt;

\[p(w|c_{i})\]

&lt;p&gt;的计算方法，而由朴素贝叶斯的前提假设可知,&lt;/p&gt;

\[p(w_{0}，w_{1}，w_{2}...w_{N}|c_{i})=p(w_{0}|c_{i})p(w_{1}|c_{i})p(w_{2}|c_{i})... p(w_{N}|c_{i})\]

&lt;p&gt;因此一般有两种，一种是在类别为ci的那些样本集中，找到wj出现次数的总和，然后除以该样本的总和；第二种方法是类别为ci的那些样本集中，找到wj出现次数的总和，然后除以该样本中所有特征出现次数的总和.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;如果&lt;/li&gt;
&lt;/ol&gt;

\[p(w|c_{i})\]

&lt;p&gt;中的某一项为0，则其联合概率的乘积也可能为0，即2中公式的分子为0，为了避免这种现象出现，一般情况下会将这一项初始化为1，当然为了保证概率相等，分母应对应初始化为2（这里因为是2类，所以加2，如果是k类就需要加k，术语上叫做laplace光滑）。&lt;/p&gt;

&lt;h3 id=&quot;朴素贝叶斯的优点&quot;&gt;朴素贝叶斯的优点：&lt;/h3&gt;

&lt;p&gt;　　对小规模的数据表现很好，适合多分类任务，适合增量式训练。&lt;/p&gt;

&lt;h3 id=&quot;缺点&quot;&gt;缺点：&lt;/h3&gt;

&lt;p&gt;　　对输入数据的表达形式很敏感。&lt;/p&gt;

&lt;h1 id=&quot;决策树&quot;&gt;决策树&lt;/h1&gt;

&lt;p&gt;决策树中很重要的一点就是选择一个属性进行分枝，因此要注意一下信息增益的计算公式，并深入理解它。&lt;/p&gt;

&lt;p&gt;信息熵的计算公式如下:&lt;/p&gt;

\[H=-\sum_{i=1}^{n}p(x_{i})log_{2}p(x_{i})\]

&lt;p&gt;其中的n代表有n个分类类别（比如假设是2类问题，那么n=2）。分别计算这2类样本在总样本中出现的概率p1和p2，这样就可以计算出未选中属性分枝前的信息熵。&lt;/p&gt;

&lt;p&gt;现在选中一个属性xi用来进行分枝，此时分枝规则是：如果xi=vx的话，将样本分到树的一个分支；如果不相等则进入另一个分支。很显然，分支中的样本很有可能包括2个类别，分别计算这2个分支的熵H1和H2,计算出分枝后的总信息熵H’=p1H1 p2H2.，则此时的信息增益ΔH=H-H’。以信息增益为原则，把所有的属性都测试一边，选择一个使增益最大的属性作为本次分枝属性。&lt;/p&gt;

&lt;h3 id=&quot;决策树的优点&quot;&gt;决策树的优点：&lt;/h3&gt;

&lt;p&gt;　　计算量简单，可解释性强，比较适合处理有缺失属性值的样本，能够处理不相关的特征；&lt;/p&gt;

&lt;h3 id=&quot;缺点-1&quot;&gt;缺点：&lt;/h3&gt;

&lt;p&gt;　　容易过拟合（后续出现了随机森林，减小了过拟合现象）；&lt;/p&gt;

&lt;h1 id=&quot;逻辑回归&quot;&gt;逻辑回归&lt;/h1&gt;

&lt;p&gt;Logistic是用来分类的，是一种线性分类器，需要注意的地方有： 　　&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;logistic函数表达式为：&lt;/li&gt;
&lt;/ol&gt;

\[h_{\theta}(x)=g(\theta^Tx)=\frac{1}{1+e^{\theta^Tx}}\]

\[g(z) = \frac {1}{1+e^{-z}}\]

&lt;p&gt;其导数形式为：&lt;/p&gt;

\[g&apos;(z) = \frac{\mathrm{d}}{\mathrm{d} z}\frac {1}{1+e^{-z}}=\frac {1}{(1+e^{-z})^2}(e^{-z})=\frac {1}{1+e^{-z}}(1-\frac {1}{1+e^{-z}})=g(z)(1-g(z))\]

&lt;ol&gt;
  &lt;li&gt;logsitc回归方法主要是用最大似然估计来学习的，所以单个样本的后验概率为：&lt;/li&gt;
&lt;/ol&gt;

\[p(y|x;\theta)=(h_{\theta}(x))^y(1-h_{\theta}(x))^{(1-y)}\]

&lt;p&gt;到整个样本的后验概率：&lt;/p&gt;

\[L(\theta)=p(\vec{y}|X;\theta)=\prod_{i=1}^{m}p(y^i|x^i;\theta)=\prod_{i=1}^{m}(h_{\theta}(x^i))^{y^i}(1-h_{\theta}(x^i))^{1-y^i}\]

&lt;p&gt;其中：&lt;/p&gt;

\[p(y=1|x;\theta)=h_{\theta}(x)\]

\[p(y=0|x;\theta)=1-h_{\theta}(x)\]

&lt;p&gt;通过对数进一步化简为：&lt;/p&gt;

\[l(\theta)=logL(\theta)=\sum_{i=1}^{m}y^ilogh(x^i)+(1-y^i)log(1-h(x^i))\]

&lt;p&gt;　　&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;其实它的loss function为-l(θ)，因此我们需使loss function最小，可采用梯度下降法得到。梯度下降法公式为:&lt;/li&gt;
&lt;/ol&gt;

\[\frac{\partial }{\partial \theta_{j}}l(\theta)=(y\frac {1}{g(\theta^Tx)}-(1-y)\frac{1}{1-g(\theta^Tx)})\frac{\partial }{\partial \theta_{j}}g(\theta^Tx)=\left (y\frac{1}{g(\theta^Tx)}-(1-y)\frac{1}{1-g(\theta^Tx)}\right )\]

\[=\left ( y\frac{1}{g(\theta^Tx)}-(1-y)\frac {1}{1-g(\theta^Tx)} \right )g(\theta^Tx)(1-g(\theta^Tx)\frac{\partial }{\partial \theta_{j}}\theta^Tx\]

\[=(y(1-g(\theta^Tx))-(1-y)g(\theta^Tx))x_{j}=(y-h_{\theta(x)})x_{j}\]

\[\theta_{j}:=\theta_{j}+\alpha(y^i-h_{\theta}(x^i))x^i_{j}\]

&lt;h3 id=&quot;logistic回归优点&quot;&gt;Logistic回归优点:&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;实现简单&lt;/li&gt;
  &lt;li&gt;分类时计算量非常小，速度很快，存储资源低；&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;缺点-2&quot;&gt;缺点：&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;容易欠拟合，一般准确度不太高&lt;/li&gt;
  &lt;li&gt;只能处理两分类问题（在此基础上衍生出来的softmax可以用于多分类），且必须线性可分；&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;线性回归&quot;&gt;线性回归&lt;/h1&gt;

&lt;p&gt;线性回归才是真正用于回归的，而不像logistic回归是用于分类，其基本思想是用梯度下降法对最小二乘法形式的误差函数进行优化，当然也可以用normal equation直接求得参数的解，结果为：&lt;/p&gt;

\[\hat{w}=(X^TX)^{-1}X^Ty\]

&lt;p&gt;而在LWLR（局部加权线性回归）中，参数的计算表达式为:&lt;/p&gt;

\[\hat{w}=(X^TWX)^{-1}X^TWy\]

&lt;p&gt;因为此时优化的是：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Fit \theta to minimize \(\sum_{i}^{n}w^{(i)}(y^{(i)}-\theta^Tx^{(i)})^2\)&lt;/li&gt;
  &lt;li&gt;Outpu \(\theta^Tx\).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;由此可见LWLR与LR不同，LWLR是一个非参数模型，因为每次进行回归计算都要遍历训练样本至少一次。&lt;/p&gt;

&lt;h3 id=&quot;线性回归优点&quot;&gt;线性回归优点：&lt;/h3&gt;

&lt;p&gt;　　实现简单，计算简单；&lt;/p&gt;

&lt;h3 id=&quot;缺点-3&quot;&gt;缺点：&lt;/h3&gt;

&lt;p&gt;　　不能拟合非线性数据；&lt;/p&gt;

&lt;h1 id=&quot;knn-算法&quot;&gt;KNN 算法&lt;/h1&gt;

&lt;p&gt;KNN即最近邻算法，其主要过程为:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;计算训练样本和测试样本中每个样本点的距离（常见的距离度量有欧式距离，马氏距离等）.&lt;/li&gt;
  &lt;li&gt;对上面所有的距离值进行排序&lt;/li&gt;
  &lt;li&gt;选前k个最小距离的样本；&lt;/li&gt;
  &lt;li&gt;根据这k个样本的标签进行投票，得到最后的分类类别；&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;如何选择一个最佳的K值，这取决于数据。一般情况下，在分类时较大的K值能够减小噪声的影响。但会使类别之间的界限变得模糊。一个较好的K值可通过各种启发式技术来获取，比如，交叉验证。另外噪声和非相关性特征向量的存在会使K近邻算法的准确性减小。&lt;/p&gt;

&lt;p&gt;近邻算法具有较强的一致性结果。随着数据趋于无限，算法保证错误率不会超过贝叶斯算法错误率的两倍。对于一些好的K值，K近邻保证错误率不会超过贝叶斯理论误差率。&lt;/p&gt;

&lt;p&gt;注：马氏距离一定要先给出样本集的统计性质，比如均值向量，协方差矩阵等。关于马氏距离的介绍如下：
&lt;img src=&quot;../../../../images/mlalg/2730002-542eef3266466179.png&quot; alt=&quot;img&quot; /&gt;
　　&lt;/p&gt;

&lt;h3 id=&quot;knn算法的优点&quot;&gt;KNN算法的优点：&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;思想简单，理论成熟，既可以用来做分类也可以用来做回归&lt;/li&gt;
  &lt;li&gt;可用于非线性分类&lt;/li&gt;
  &lt;li&gt;训练时间复杂度为O(n)&lt;/li&gt;
  &lt;li&gt;准确度高，对数据没有假设，对outlier不敏感；&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;缺点-4&quot;&gt;缺点：&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;计算量大&lt;/li&gt;
  &lt;li&gt;样本不平衡问题（即有些类别的样本数量很多，而其它样本的数量很少）； 　　&lt;/li&gt;
  &lt;li&gt;需要大量的内存；&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;svm&quot;&gt;SVM&lt;/h1&gt;

&lt;p&gt;要学会如何使用libsvm以及一些参数的调节经验，另外需要理清楚svm算法的一些思路&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;svm中的最优分类面是对所有样本的几何裕量最大（为什么要选择最大间隔分类器，请从数学角度上说明？网易深度学习岗位面试过程中有被问到。答案就是几何间隔与样本的误分次数间存在关系： ，其中的分母就是样本到分类间隔距离，分子中的R是所有样本中的最长向量值），即：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;\(max_{\gamma,w,b}\)  \(\gamma\)&lt;/p&gt;

\[s.t. y^{(i)}(wTx^{(i)}+b)\geqslant \gamma,  i=1,....,m\]

\[||w||=1\]

&lt;p&gt;经过一系列推导可得为优化下面原始目标&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;\(min_{\gamma,w,b}\)  $$ \frac{1}{2}&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;w&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;^2  $$&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

\[s.t. y^{(i)}(wTx^{(i)}+b)\geqslant 1, i=1,....,m\]

&lt;ol&gt;
  &lt;li&gt;下面来看看拉格朗日理论：
&lt;img src=&quot;../../../../images/mlalg/2730002-e21a8f7f5dbde417.png&quot; alt=&quot;img2&quot; /&gt;
可以将1中的优化目标转换为拉格朗日的形式（通过各种对偶优化，KKD条件），最后目标函数为：
&lt;img src=&quot;../../../../images/mlalg/2730002-de785d4d6434ce3c.png&quot; alt=&quot;img3&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我们只需要最小化上述目标函数，其中的α为原始优化问题中的不等式约束拉格朗日系数&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;对2中最后的式子分别w和b求导可得：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;\(w=\sum_{i=1}^{m}\alpha_{i}y^{(i)}x^{(i)}\)    \(\frac{\partial }{\partial b}\iota (w,b,\alpha)=\sum_{i=1}^{m}\alpha_{i}y^{(i)}
=0\)&lt;/p&gt;

&lt;p&gt;由上面第1式子可以知道，如果我们优化出了α，则直接可以求出w了，即模型的参数搞定。而上面第2个式子可以作为后续优化的一个约束条件。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;对2中最后一个目标函数用对偶优化理论可以转换为优化下面的目标函数：
&lt;img src=&quot;../../../../images/mlalg/2730002-c9665bbd6cc6a021.png&quot; alt=&quot;imgs&quot; /&gt;
而这个函数可以用常用的优化方法求得α，进而求得w和b&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;按照道理，svm简单理论应该到此结束。不过还是要补充一点，即在预测时有：&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;../../../../images/mlalg/2730002-6b3f644bfc36301e.png&quot; alt=&quot;imgs2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;那个尖括号我们可以用核函数代替，这也是svm经常和核函数扯在一起的原因&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;最后是关于松弛变量的引入，因此原始的目标优化公式为：
&lt;img src=&quot;../../../../images/mlalg/2730002-ddbd8dff10b593d2.png&quot; alt=&quot;imgs3&quot; /&gt;
此时对应的对偶优化公式为：
&lt;img src=&quot;../../../../images/mlalg/2730002-acfb48aadcab6aed.png&quot; alt=&quot;imgs4&quot; /&gt;
与前面的相比只是α多了个上界。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;svm算法优点&quot;&gt;SVM算法优点：&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;可用于线性/非线性分类，也可以用于回归&lt;/li&gt;
  &lt;li&gt;低泛化误差&lt;/li&gt;
  &lt;li&gt;容易解释&lt;/li&gt;
  &lt;li&gt;计算复杂度较低；&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;缺点-5&quot;&gt;缺点:&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;对参数和核函数的选择比较敏感；&lt;/li&gt;
  &lt;li&gt;原始的SVM只比较擅长处理二分类问题；&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;boosting&quot;&gt;Boosting&lt;/h1&gt;

&lt;p&gt;主要以Adaboost为例，首先来看看Adaboost的流程图，如下：
&lt;img src=&quot;../../../../images/mlalg/2730002-23267500beb81bac.png&quot; alt=&quot;imgss1&quot; /&gt;
从图中可以看到，在训练过程中我们需要训练出多个弱分类器（图中为3个），每个弱分类器是由不同权重的样本（图中为5个训练样本）训练得到（其中第一个弱分类器对应输入样本的权值是一样的），而每个弱分类器对最终分类结果的作用也不同，是通过加权平均输出的，权值见上图中三角形里面的数值。那么这些弱分类器和其对应的权值是怎样训练出来的呢？ 　　下面通过一个例子来简单说明。 　　书中（machine learning in action）假设的是5个训练样本，每个训练样本的维度为2，在训练第一个分类器时5个样本的权重各为0.2.&lt;/p&gt;

&lt;p&gt;注意这里样本的权值和最终训练的弱分类器组对应的权值α是不同的，样本的权重只在训练过程中用到，而α在训练过程和测试过程都有用到。&lt;/p&gt;

&lt;p&gt;现在假设弱分类器是带一个节点的简单决策树，该决策树会选择2个属性（假设只有2个属性）的一个，然后计算出这个属性中的最佳值用来分类.&lt;/p&gt;

&lt;p&gt;Adaboost的简单版本训练过程如下:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;训练第一个分类器，样本的权值D为相同的均值。通过一个弱分类器，得到这5个样本（请对应书中的例子来看，依旧是machine learning in action）的分类预测标签。与给出的样本真实标签对比，就可能出现误差(即错误)。如果某个样本预测错误，则它对应的错误值为该样本的权重，如果分类正确，则错误值为0. 最后累加5个样本的错误率之和，记为ε。 　　&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;通过ε来计算该弱分类器的权重α，公式如下：&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

\[\alpha=\frac {1}{2}ln\left ( \frac {(1-\varepsilon )}{\varepsilon}
 \right )\]

&lt;ol&gt;
  &lt;li&gt;通过α来计算训练下一个弱分类器样本的权重D，如果对应样本分类正确，则减小该样本的权重，公式为：&lt;/li&gt;
&lt;/ol&gt;

\[D_{i}^{(t+1)}=\frac {D_{i}^{(t)}e^{-\alpha}}{Sum(D)}\]

&lt;p&gt;如果样本分类错误，则增加该样本的权重，公式为：&lt;/p&gt;

&lt;p&gt;\(D^{(t+1)}_{i}=\frac {D^{(t)}_{i}e^\alpha}{Sum(D)}\)
　　&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;循环步骤1,2,3来继续训练多个分类器，只是其D值不同而已。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;测试过程如下：&lt;/p&gt;

&lt;p&gt;输入一个样本到训练好的每个弱分类中，则每个弱分类都对应一个输出标签，然后该标签乘以对应的α，最后求和得到值的符号即为预测标签值。&lt;/p&gt;

&lt;h3 id=&quot;boosting算法的优点&quot;&gt;Boosting算法的优点：&lt;/h3&gt;

&lt;p&gt;　　低泛化误差；容易实现，分类准确率较高，没有太多参数可以调；&lt;/p&gt;

&lt;h3 id=&quot;缺点-6&quot;&gt;缺点：&lt;/h3&gt;

&lt;p&gt;　　对outlier比较敏感；&lt;/p&gt;

&lt;h1 id=&quot;聚类&quot;&gt;聚类&lt;/h1&gt;

&lt;p&gt;根据聚类思想划分:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;基于划分的聚类:
K-means, k-medoids(每一个类别中找一个样本点来代表),CLARANS. k-means是使下面的表达式值最小：&lt;/li&gt;
&lt;/ol&gt;

\[V=\sum_{i=1}^{k}\sum_{x_{j}\epsilon S_{i}}(x_{j}-\mu _{i})^2\]

&lt;h3 id=&quot;k-means算法的优点&quot;&gt;k-means算法的优点：&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;k-means算法是解决聚类问题的一种经典算法，算法简单、快速。 2. 对处理大数据集，该算法是相对可伸缩的和高效率的，因为它的复杂度大约是O(nkt)，其中n是所有对象的数目，k是簇的数目,t是迭代的次数。通常k«n。这个算法通常局部收敛。&lt;/li&gt;
  &lt;li&gt;算法尝试找出使平方误差函数值最小的k个划分。当簇是密集的、球状或团状的，且簇与簇之间区别明显时，聚类效果较好。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;缺点-7&quot;&gt;缺点：&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;k-平均方法只有在簇的平均值被定义的情况下才能使用，且对有些分类属性的数据不适合。&lt;/li&gt;
  &lt;li&gt;要求用户必须事先给出要生成的簇的数目k。&lt;/li&gt;
  &lt;li&gt;对初值敏感，对于不同的初始值，可能会导致不同的聚类结果。&lt;/li&gt;
  &lt;li&gt;不适合于发现非凸面形状的簇，或者大小差别很大的簇。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;对于”噪声”和孤立点数据敏感，少量的该类数据能够对平均值产生极大影响。 　　&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;基于层次的聚类:
自底向上的凝聚方法，比如AGNES。自上向下的分裂方法，比如DIANA。&lt;/li&gt;
  &lt;li&gt;基于密度的聚类： 　　DBSACN,OPTICS,BIRCH(CF-Tree),CURE. 　　&lt;/li&gt;
  &lt;li&gt;基于网格的方法： 　　STING, WaveCluster. 　　&lt;/li&gt;
  &lt;li&gt;基于模型的聚类： 　　EM,SOM,COBWEB.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;以上这些算法的简介可参考聚类（百度百科）。&lt;/p&gt;

&lt;h1 id=&quot;推荐系统&quot;&gt;推荐系统&lt;/h1&gt;

&lt;p&gt;推荐系统的实现主要分为两个方面：基于内容的实现和协同滤波的实现。&lt;/p&gt;

&lt;p&gt;基于内容的实现：&lt;/p&gt;

&lt;p&gt;不同人对不同电影的评分这个例子，可以看做是一个普通的回归问题，因此每部电影都需要提前提取出一个特征向量(即x值)，然后针对每个用户建模，即每个用户打的分值作为y值，利用这些已有的分值y和电影特征值x就可以训练回归模型了(最常见的就是线性回归)。这样就可以预测那些用户没有评分的电影的分数。（值得注意的是需对每个用户都建立他自己的回归模型）&lt;/p&gt;

&lt;p&gt;从另一个角度来看，也可以是先给定每个用户对某种电影的喜好程度（即权值），然后学出每部电影的特征，最后采用回归来预测那些没有被评分的电影。&lt;/p&gt;

&lt;p&gt;当然还可以是同时优化每个用户对不同类型电影的热爱程度以及每部电影的特征。具体可以参考Ng在coursera上的ml教程：https://www.coursera.org/course/ml 　&lt;/p&gt;

&lt;p&gt;基于协同滤波的实现：&lt;/p&gt;

&lt;p&gt;协同滤波（CF）可以看做是一个分类问题，也可以看做是矩阵分解问题。协同滤波主要是基于每个人自己的喜好都类似这一特征，它不依赖于个人的基本信息。比如刚刚那个电影评分的例子中，预测那些没有被评分的电影的分数只依赖于已经打分的那些分数，并不需要去学习那些电影的特征。&lt;/p&gt;

&lt;p&gt;SVD将矩阵分解为三个矩阵的乘积，公式如下所示：&lt;/p&gt;

\[Data_{m\times n}=U_{m\times m}\Sigma_{m\times n}V^T_{n\times n}\]

&lt;p&gt;中间的矩阵sigma为对角矩阵，对角元素的值为Data矩阵的特征值，且已经从大到小排列好了。即使去掉特征值小的那些特征，依然可以很好的重构出原始矩阵。如下图所示：
&lt;img src=&quot;../../../../images/mlalg/2730002-78206fc55cc41297.png&quot; alt=&quot;images11&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其中更深的颜色代表去掉小特征值重构时的三个矩阵。&lt;/p&gt;

&lt;p&gt;m代表商品的个数，n代表用户的个数，则U矩阵的每一行代表商品的属性，现在通过降维U矩阵（取深色部分）后，每一个商品的属性可以用更低的维度表示（假设为k维）。这样当新来一个用户的商品推荐向量X，则可以根据公式XU1inv(S1)得到一个k维的向量，然后在V’中寻找最相似的那一个用户（相似度测量可用余弦公式等），根据这个用户的评分来推荐（主要是推荐新用户未打分的那些商品）。具体例子可以参考网页：&lt;a href=&quot;http://blog.csdn.net/wuyanyi/article/details/7964883&quot;&gt;SVD在推荐系统中的应用&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;另外关于SVD分解后每个矩阵的实际含义可以参考google吴军的数学之美一书（不过个人感觉吴军解释UV两个矩阵时好像弄反了，不知道大家怎样认为）。或者参考machine learning in action其中的svd章节。&lt;/p&gt;

&lt;h1 id=&quot;plsa&quot;&gt;pLSA&lt;/h1&gt;

&lt;p&gt;pLSA由LSA发展过来，而早期LSA的实现主要是通过SVD分解。pLSA的模型图如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../../../../images/mlalg/2730002-5ab0df3e061f44fb.png&quot; alt=&quot;images11&quot; /&gt;&lt;/p&gt;

&lt;p&gt;公式中的意义如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../../../../images/mlalg/2730002-5f26bddd158e7559.png&quot; alt=&quot;images11&quot; /&gt;&lt;/p&gt;

&lt;p&gt;具体可以参考&lt;a href=&quot;http://bcmi.sjtu.edu.cn/ds/download.html&quot;&gt;2010龙星计划：机器学习中对应的主题模型那一讲&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;lda&quot;&gt;LDA&lt;/h1&gt;

&lt;p&gt;主题模型，概率图如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../../../../images/mlalg/2730002-0cf7d399d85f8a96.jpg&quot; alt=&quot;images11&quot; /&gt;
和pLSA不同的是LDA中假设了很多先验分布，且一般参数的先验分布都假设为Dirichlet分布，其原因是共轭分布时先验概率和后验概率的形式相同。&lt;/p&gt;

&lt;h1 id=&quot;gdbt&quot;&gt;GDBT&lt;/h1&gt;

&lt;p&gt;GBDT(Gradient Boosting Decision Tree) 又叫 MART（Multiple Additive Regression Tree)，好像在阿里内部用得比较多（所以阿里算法岗位面试时可能会问到），它是一种迭代的决策树算法，该算法由多棵决策树组成，所有树的输出结果累加起来就是最终答案。它在被提出之初就和SVM一起被认为是泛化能力（generalization)较强的算法。近些年更因为被用于搜索排序的机器学习模型而引起大家关注。&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;GBDT是回归树，不是分类树。其核心就在于，每一棵树是从之前所有树的残差中来学习的。为了防止过拟合，和Adaboosting一样，也加入了boosting这一项。 　　关于GDBT的介绍可以可以参考：GBDT（MART） [迭代决策树入门教程&lt;/td&gt;
      &lt;td&gt;简介](http://hi.baidu.com/hehehehello/item/96cc42e45c16e7265a2d64ee)。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;regularization&quot;&gt;Regularization&lt;/h1&gt;

&lt;p&gt;作用是（网易电话面试时有问到）：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;数值上更容易求解；&lt;/li&gt;
  &lt;li&gt;特征数目太大时更稳定；&lt;/li&gt;
  &lt;li&gt;控制模型的复杂度，光滑性。复杂性越小且越光滑的目标函数泛化能力越强。而加入规则项能使目标函数复杂度减小，且更光滑。&lt;/li&gt;
  &lt;li&gt;减小参数空间；参数空间越小，复杂度越低。&lt;/li&gt;
  &lt;li&gt;系数越小，模型越简单，而模型越简单则泛化能力越强（Ng宏观上给出的解释）。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;异常检测&quot;&gt;异常检测&lt;/h1&gt;

&lt;p&gt;可以估计样本的密度函数，对于新样本直接计算其密度，如果密度值小于某一阈值，则表示该样本异常。而密度函数一般采用多维的高斯分布。如果样本有n维，则每一维的特征都可以看作是符合高斯分布的，即使这些特征可视化出来不太符合高斯分布，也可以对该特征进行数学转换让其看起来像高斯分布，比如说x=log(x c), x=x^(1/c)等。异常检测的算法流程如下：
&lt;img src=&quot;../../../../images/mlalg/2730002-5d2752afde8862da.png&quot; alt=&quot;images22&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其中的ε也是通过交叉验证得到的，也就是说在进行异常检测时，前面的p(x)的学习是用的无监督，后面的参数ε学习是用的有监督。那么为什么不全部使用普通有监督的方法来学习呢（即把它看做是一个普通的二分类问题）？主要是因为在异常检测中，异常的样本数量非常少而正常样本数量非常多，因此不足以学习到好的异常行为模型的参数，因为后面新来的异常样本可能完全是与训练样本中的模式不同。&lt;/p&gt;

&lt;p&gt;另外，上面是将特征的每一维看成是相互独立的高斯分布，其实这样的近似并不是最好的，但是它的计算量较小，因此也常被使用。更好的方法应该是将特征拟合成多维高斯分布，这时有特征之间的相关性，但随之计算量会变复杂，且样本的协方差矩阵还可能出现不可逆的情况（主要在样本数比特征数小，或者样本特征维数之间有线性关系时）。 　　上面的内容可以参考Ng的https://www.coursera.org/course/ml&lt;/p&gt;

&lt;h1 id=&quot;em-算法&quot;&gt;EM 算法&lt;/h1&gt;

&lt;p&gt;有时候因为样本的产生和隐含变量有关（隐含变量是不能观察的），而求模型的参数时一般采用最大似然估计，由于含有了隐含变量，所以对似然函数参数求导是求不出来的，这时可以采用EM算法来求模型的参数的（对应模型参数个数可能有多个），EM算法一般分为2步：&lt;/p&gt;

&lt;p&gt;E步：选取一组参数，求出在该参数下隐含变量的条件概率值；
M步：结合E步求出的隐含变量条件概率，求出似然函数下界函数（本质上是某个期望函数）的最大值。&lt;/p&gt;

&lt;p&gt;重复上面2步直至收敛。&lt;/p&gt;

&lt;p&gt;公式如下所示：&lt;/p&gt;

&lt;p&gt;(E-step) 对每一个i， 另：&lt;/p&gt;

\[Q_{i}(z^{(i)}):=p(z^{(i)}|x^{(i)};\theta)\]

&lt;p&gt;(M-step),另：
\(\theta:=argmax_{\theta}\sum_{i}\sum_{z^{(i)}}Q_{i}(Z^{(i)})log\frac {p(x^{(i)},z^{(i)};\theta)}{Q_{i}(z^{(i)})}\)&lt;/p&gt;

&lt;p&gt;M步公式中下界函数的推导过程：&lt;/p&gt;

\[\sum_{i}logp(x^{(i)};\theta)=\sum_{i}log\sum_{z^{(i)}}p(x^{(i)},z^{(i)};\theta)=\sum_{i}log\sum_{z^{(i)}}Q_{i}(z^{(i)})\frac {p(x^{(i)},z^{(i)};\theta)}{Q_{i}^{(i)}}\geq \sum_{i}\sum_{z^{(i)}}Q_{i}(z^{(i)})log\frac{p(x^{(i)},z^{(i)};\theta)}{Q_{i}(z^{(i)})}\]

&lt;p&gt;EM算法一个常见的例子就是GMM模型，每个样本都有可能由k个高斯产生，只不过由每个高斯产生的概率不同而已，因此每个样本都有对应的高斯分布（k个中的某一个），此时的隐含变量就是每个对应的某个高斯分布。&lt;/p&gt;

&lt;p&gt;GMM的E步公式如下：&lt;/p&gt;

\[w^{(i)}_{j}:=p(z^{(i)}=j|x^{(i)};\psi ,\mu,\Sigma)\]

&lt;p&gt;M步公式如下：&lt;/p&gt;

&lt;p&gt;\(\psi_{j}:=\frac{1}{m}\sum_{i=1}^{m}w_{j}^{(i)}\)
\(\mu_{j}:=\frac{\sum_{i=1}^{m}w_{j}^{(i)}x^{(i)}}{\sum_{i=1}^{m}w_{j}^{(i)}}\)
\(\Sigma _{j}:=\frac{\sum_{i=1}^{m}w_{j}^{(i)}(x^{(i)}-\mu_{j})(x^{(i)}-\mu_{j})^T}{\sum_{i=1}^{m}w_{j}^{(i)}}\)&lt;/p&gt;

&lt;p&gt;关于EM算法可以参考Ng的cs229课程资料 或者网易公开课：&lt;a href=&quot;http://v.163.com/special/opencourse/machinelearning.html&quot;&gt;斯坦福大学公开课 ：机器学习课程&lt;/a&gt;。&lt;/p&gt;

&lt;h1 id=&quot;apriori&quot;&gt;Apriori&lt;/h1&gt;

&lt;p&gt;Apriori是关联分析中比较早的一种方法，主要用来挖掘那些频繁项集合。其思想是：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;如果一个项目集合不是频繁集合，那么任何包含它的项目集合也一定不是频繁集合；&lt;/li&gt;
  &lt;li&gt;如果一个项目集合是频繁集合，那么它的任何非空子集也是频繁集合；&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Aprioir需要扫描项目表多遍，从一个项目开始扫描，舍去掉那些不是频繁的项目，得到的集合称为L，然后对L中的每个元素进行自组合，生成比上次扫描多一个项目的集合，该集合称为C，接着又扫描去掉那些非频繁的项目，重复…&lt;/p&gt;

&lt;p&gt;看下面这个例子:&lt;/p&gt;

&lt;p&gt;元素项目表格：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../../../../images/mlalg/2730002-f90e4253262ac682.png&quot; alt=&quot;imagesss1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;如果每个步骤不去掉非频繁项目集，则其扫描过程的树形结构如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../../../../images/mlalg/2730002-cf21f4706df257d2.png&quot; alt=&quot;imagesss2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在其中某个过程中，可能出现非频繁的项目集，将其去掉（用阴影表示）为：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../../../../images/mlalg/2730002-207aab36bd8d6ba6.png&quot; alt=&quot;imagesss2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;上面的内容主要参考的是machine learning in action这本书。&lt;/p&gt;

&lt;h1 id=&quot;fp-growth&quot;&gt;FP-Growth&lt;/h1&gt;

&lt;p&gt;FP Growth是一种比Apriori更高效的频繁项挖掘方法，它只需要扫描项目表2次。其中第1次扫描获得当个项目的频率，去掉不符合支持度要求的项，并对剩下的项排序。第2遍扫描是建立一颗FP-Tree(frequent-patten tree)。接下来的工作就是在FP-Tree上进行挖掘。 比如说有下表：
&lt;img src=&quot;../../../../images/mlalg/2730002-f869d7b535a4e6eb.png&quot; alt=&quot;imagesss3&quot; /&gt;
它所对应的FP_Tree如下：
&lt;img src=&quot;../../../../images/mlalg/2730002-00286049bc7582ed.png&quot; alt=&quot;imagesss3&quot; /&gt;
然后从频率最小的单项P开始，找出P的条件模式基，用构造FP_Tree同样的方法来构造P的条件模式基的FP_Tree，在这棵树上找出包含P的频繁项集。&lt;/p&gt;

&lt;p&gt;依次从m,b,a,c,f的条件模式基上挖掘频繁项集，有些项需要递归的去挖掘，比较麻烦，比如m节点，具体的过程可以参考博客：&lt;a href=&quot;http://blog.sina.com.cn/s/blog_68ffc7a40100uebg.html&quot;&gt;Frequent Pattern 挖掘之二(FP Growth算法)&lt;/a&gt;，里面讲得很详细。&lt;/p&gt;
</description>
        <pubDate>Sat, 27 May 2017 16:09:00 +0000</pubDate>
        <link>https://shunliz.github.io/ml/2017/05/27/common-ml-algrithom.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/ml/2017/05/27/common-ml-algrithom.html</guid>
        
        <category>ML</category>
        
        
        <category>ML</category>
        
      </item>
    
      <item>
        <title>常用数学公式</title>
        <description>&lt;p&gt;&lt;img src=&quot;http://www.mohu.org/info/symbols/1.GIF&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.mohu.org/info/symbols/int.GIF&quot; alt=&quot;img2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.mohu.org/info/symbols/frac.GIF&quot; alt=&quot;img3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.mohu.org/info/symbols/vec.GIF&quot; alt=&quot;img4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.mohu.org/info/symbols/brace.GIF&quot; alt=&quot;img5&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.mohu.org/info/symbols/overline.GIF&quot; alt=&quot;img6&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.mohu.org/info/symbols/sqrt.GIF&quot; alt=&quot;img&quot; /&gt;
&lt;img src=&quot;http://www.mohu.org/info/symbols/foot.gif&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;

&lt;p&gt;x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}&lt;/p&gt;

\[x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}\]

&lt;p&gt;\sum_{i=1}^{n}\dfrac{ 1 } {n!} = e&lt;/p&gt;

\[\sum_{i=1}^{n}\dfrac{ 1 } {n!} = e\]

&lt;p&gt;e^x  = 1+ x+ \dfrac{x^2}{2!}+…….\dfrac{x^n}{n!}&lt;/p&gt;

\[e^x  = 1+ x+ \dfrac{x^2}{2!}+.......\dfrac{x^n}{n!}\]

&lt;p&gt;e^1 = e = 1+ \dfrac{1}{2!}+ 
x =1&lt;/p&gt;

\[e^1 = e = 1+ \dfrac{1}{2!}+\]

&lt;p&gt;f(x) = f(x_0)+f’(x_0)(x-x_0)+\dfrac{f’‘(x_0)}{2!}(x-x_0)^2+………+\dfrac{f^n(x_0)}{n!}(x-x_0)^n&lt;/p&gt;

\[f(x) = f(x_0)+f&apos;(x_0)(x-x_0)+\dfrac{f&apos;&apos;(x_0)}{2!}(x-x_0)^2+.........+\dfrac{f^n(x_0)}{n!}(x-x_0)^n\]

&lt;p&gt;x = \dfrac{-b \pm \sqrt{b^2 - 4ac}}{2a}&lt;/p&gt;

\[x = \dfrac{-b \pm \sqrt{b^2 - 4ac}}{2a}\]

&lt;p&gt;\lim_{x \to \infty}(1+\frac{1}{x})^{x} = e&lt;/p&gt;

\[\lim_{x \to \infty}(1+\frac{1}{x})^{x} = e\]

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;cos\theta =\frac{A \cdot B }{&lt;/td&gt;
      &lt;td&gt;A&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;\times B&lt;/td&gt;
      &lt;td&gt;}=\frac{\sum_{i=1}^{n}(A_{i}\times B_{i})}{\sqrt{\sum_{i=1}^{n}A_{i}^{2}} \times \sqrt{\sum_{i=1}^{n}B_{i}^{2}} }&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

\[cos\theta =\frac{A \cdot B }{|A||\times B|}=\frac{\sum_{i=1}^{n}(A_{i}\times B_{i})}{\sqrt{\sum_{i=1}^{n}A_{i}^{2}} \times \sqrt{\sum_{i=1}^{n}B_{i}^{2}} }\]

\[f(z) = tanh(z) = \dfrac{e^z-e^{-z}}{e^z+e^{-z}}\]

\[f^{&apos;}(z)=1-f(z)^{2}\]

\[J(W,b;x,y)=\frac{1}{2}||h_{W,b}(x)-y||^{2}\]

\[J(W,b)=[\frac{1}{m}\sum_{i=1}^{m}J(W,b;x^{i},y^{i})]+\frac{\lambda}{2}\sum_{l=1}^{n_{l}-1}\sum_{i=1}^{s_{t}}\sum_{j=1}^{s_{t}+1}(W_{ji}^l)^2 = [\frac{1}{m}\sum_{i=1}^{m}\frac{1}{2}||h_{W,b}(x)-y||^{2}]+\frac{\lambda}{2}\sum_{l=1}^{n_{l}-1}\sum_{i=1}^{s_{t}}\sum_{j=1}^{s_{t}+1}(W_{ji}^l)^2\]

</description>
        <pubDate>Fri, 28 Apr 2017 16:09:00 +0000</pubDate>
        <link>https://shunliz.github.io/math/2017/04/28/math-formula-in-latex.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/math/2017/04/28/math-formula-in-latex.html</guid>
        
        <category>math</category>
        
        <category>latex</category>
        
        
        <category>math</category>
        
      </item>
    
      <item>
        <title>iptables DNAT 与 SNAT 详解</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://shunliz.github.io/images/network/213457311.gif&quot; alt=&quot;img1&quot; /&gt;
&lt;img src=&quot;https://shunliz.github.io/images/network/213457974.gif&quot; alt=&quot;img2&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;这个target是用来做目的网络地址转换的，就是重写包的目的IP地址。如果一个包被匹配了，那么和它属于同一个流的所有的包都会被自动转换，然后就可以被路由到正确的主机或网络。DNAT target是非常有用的。比如，你的web服务器在LAN内部，而且没有可以在Internet上使用的真实IP地址，那就可以使用这个target让防火墙把所有到它自己HTTP端口的包转发给LAN内部真正的web服务器。目的地址也可以是一个范围，这样的话，DNAT会为每一个流随机分配一个地址。因此，我们可以用这个target做某种类型的负载平衡。

注意，DNAT target只能用在nat表的PREOUTING 和 OUTPUT 链中，或者是被这两条链调用的链里。但还要注意的是，包含DNAT target的连不能被除此之外的其他链调用，如POSTROUTING。

iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10

Explanation指定要写入IP头的地址，这也是包要被转发到的地方。上面的例子就是把所有发往地址15.45.23.67的包都转发到一段LAN使用的私有地址中，即192.168.1.1到192.168.1.10。如前所述，在这种情况下，每个流都会被随机分配一个要转发到的地址，但同一个流总是使用同一个地址。我们也可以只指定一个IP地址作为参数，这样所有包都被转发到同一台机子。我们还可以在地址后指定一个或一个范围的端口。比如：--to-destination 192.168.1.1:80或192.168.1.1:80-100。SNAT的语法和这个target的一样，只是目的不同罢了。要注意，只有先用--protocol指定了TCP或UDP协议，才能使用端口。
因为DNAT要做很多工作，所以我要再啰嗦一点。我们通过一个例子来大致理解一下它是如何工作的。比如，我想通过Internet连接发布我们的网站，但是HTTP server在我们的内网里，而且我们对外只有一个合法的IP，就是防火墙那个对外的IP——$INET_IP。防火墙还有一个内网的IP——$LAN_IP，HTTP server的IP是%HTTP_IP（当然这是内网的了）。为了完成我们的设想，要做的第一件事就是把下面这个简单的规则加入到nat表的PREROUTING链中：

 iptables -t nat -A PREROUTING --dst$INET_IP -p tcp --dport 80 -j DNAT / --to-destination $HTTP_IP
 
现在，所有从Internet来的、到防火墙的80端口去的包都会被转发（或称作被DNAT）到在内网的HTTP服务器上。如果你在Internet上试验一下，一切正常吧。再从内网里试验一下，完全不能用吧。这其实是路由的问题。下面我们来好好分析这个问题。为了容易阅读，我们把在外网上访问我们服务器的那台机子的IP地址记为$EXT_BOX。

包从地址为$EXT_BOX的机子出发，去往地址为$INET_IP的机子。

包到达防火墙。

防火墙DNAT（也就是转发）这个包，而且包会经过很多其他的链检验及处理。

包离开防火墙向$HTTP_IP前进。

包到达HTTP服务器，服务器就会通过防火墙给以回应，当然，这要求把防火墙作为HTTP到达$EXT_BOX的网关。一般情况下，防火墙就是HTTP服务器的缺省网关。

防火墙再对返回包做Un-DNAT（就是照着DNAT的步骤反过来做一遍），这样就好像是防火墙自己回复了那个来自外网的请求包。

返回包好像没经过这么复杂的处理、没事一样回到$EXT_BOX。
现在，我们来考虑和HTTP服务器在同一个内网（这里是指所有机子不需要经过路由器而可以直接互相访问的网络，不是那种把服务器和客户机又分在不同子网的情况）的客户访问它时会发生什么。我们假设客户机的IP为$LAN_BOX，其他设置同上。

包离开$LAN_BOX，去往$INET_IP。

包到达防火墙。
包被DNAT，而且还会经过其他的处理。但是包没有经过SNAT的处理，所以包还是使用它自己的源地址，就是$LAN_BOX（译者注：这就是IP传输包的特点，只根据目的地的不同而改变目的地址，但不因传输过程要经过很多路由器而随着路由器改变其源地址，除非你单独进行源地址的改变。其实这一步的处理和对外来包的处理是一样的，只不过内网包的问题就在于此，所以这里交代一下原因）。

包离开防火墙，到达HTTP服务器。
HTTP服务器试图回复这个包。它在路由数据库中看到包是来自同一个网络的一台机子，因此它会把回复包直接发送到请求包的源地址（现在是回复包的目的地址），也就是$LAN_BOX。
回复包到达客户机，但它会很困惑，因为这个包不是来自它访问的那台机子。这样，它就会把这个包扔掉而去等待“真正”的回复包。
针对这个问题有个简单的解决办法，因为这些包都要进入防火墙，而且它们都去往需要做DNAT才能到达的那个地址，所以我们只要对这些包做SNAT操作即可。比如，我们来考虑上面的例子，如果对那些进入防火墙而且是去往地址为$HTTP_IP、端口为80的包做SNAT操作，那么这些包就好像是从$LAN_IP来的了。这样，HTTP服务器就会把回复包发给防火墙，而防火墙会再对包做Un-DNAT操作，并把包发送到客户机。解决问题的规则如下：

iptables -t -nat -A POSTROUTING -p tcp --dst$HTTP_IP --dport 80 -j SNAT / --to-source $LAN_IP

要记住，按运行的顺序POSTROUTING链是所有链中最后一个，因此包到达这条链时，已经被做过DNAT操作了，所以我们在规则里要基于内网的地址$HTTP_IP（包的目的地）来匹配包。
警告：我们刚才写的这条规则会对日志产生很大影响，这种影响应该说是很不好的，因为来自Internet包在防火墙内先后经过了DNAT和SNAT处理，才能到达HTTP服务器（上面的例子），所以HTTP服务器就认为包是防火墙发来的，而不知道真正的源头是其他的IP。这样， 当它记录服务情况时，所有访问记录的源地址都是防火墙的IP而不是真正的访问源。我们如果想根据这些记录来了解访问情况就不可能了。因此上面提供的“简单办法”并不是一个明智的选择，但它确实可以解决“能够访问”的问题，只是没有考虑到日志而已。
其他的服务也有类似的问题。比如，你在LAN内建立了SMTP服务器，那你就要设置防火墙以便能转发SMTP的数据流。这样你就创建了一个开放SMTP的中继服务器，随之而来的就是日志的问题了。
一定要注意，这里所说的问题只是针对没有建立DMZ或类似结构的网络，并且内网的用户访问的是服务器的外网地址而言的。（译者注：因为如果建立的DMZ，或者服务器和客户机又被分在不同的子网里，那就不需要这么麻烦了。因为所有访问的源头都不在服务器所在的网里，所以就没有必要做SNAT去改变包的源地址了，从而记录也就不是问题了。如果内网客户是直接访问服务器的内网地址那就更没事了）
比较好的解决办法是为你的LAN在内网建立一台单独的DNS服务器（译者注：这样，内网客户使用网站名访问HTTP服务器时，DNS就可以把他解析成内网地址。客户机就可以直接去访问HTTP服务器的内网地址了，从而避免了通过防火墙的操作，而且包的源地址也可以被HTTP服务器的日志使用，也就没有上面说的日志问题了。），或者干脆建立DMZ得了（这是最好的办法，但你要有钱哦，因为用的设备多啊）。
对上面的例子应该考虑再全面些，现在还有一个问题没解决，就是防火墙自己要访问HTTP服务器时会发生什么，能正常访问吗？你觉得呢:)很可惜，现在的配置还是不行，仔细想想就明白了。我们这里讨论的基础都是假设机子访问的是HTTP服务器的外网地址，那客户机就会看到页面内容，不过这不是它想看到的（它想要的在DNAT上了），如果没有HTTP服务，客户就只能收到错误信息了。前面给出的规则之所以不起作用是因为从防火墙发出的请求包不会经过那两条链。还记得防火墙自己发出的包经过哪些链吧:) 我们要在nat表的OUTPUT链中添加下面的规则：

iptables -t nat -A OUTPUT --dst$INET_IP -p tcp --dport 80 -j DNAT / --to-destination $HTTP_IP

有了最后这条规则，一切都正常了。和HTTP服务器不在同一个网的机子能正常访问服务了，和它在一个网内的机子也可以正常访问服务了，防火墙本身也可以正常访问服务了，没有什么问题了。这种心情，套用《大话西游》里的一句话，就是“世界又清静了”。（不要说你不知道什么是《大话西游》）
我想大家应该能明白这些规则只是说明了数据包是如何恰当的被DNAT和SNAT的。除此之外，在filter表中还需要其他的规则（在FORWARD链里），以允许特定的包也能经过前面写的（在POSTROUTING链和OUTPUT链里的）规则。千万不要忘了，那些包在到达FORWARD链之前已经在PREROUTING链里被DNAT过了，也就是说它们的目的地址已经被改写，在写规则时要注意这一点。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;snat-target&quot;&gt;SNAT target&lt;/h1&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;这个target是用来做源网络地址转换的，就是重写包的源IP地址。当我们有几个机子共享一个Internet连接时，就能用到它了。先在内核里打开ip转发功能，然后再写一个SNAT规则，就可以把所有从本地网络出去的包的源地址改为Internet连接的地址了。如果我们不这样做而是直接转发本地网的包的话，Internet上的机子就不知道往哪儿发送了应答了，因为在本地网里我们一般使用的是IANA组织专门指定的一段地址，它们是不能在Internet上使用的。SNAT target的作用就是让所有从本地网出发的包看起来都是从一台机子发出的，这台机子一般就是防火墙。
SNAT只能用在nat表的POSTROUTING链里。只要连接的第一个符合条件的包被SNAT了，那么这个连接的其他所有的包都会自动地被SNAT，而且这个规则还会应用于这个连接所在的流的所有数据包。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;postrouting链&quot;&gt;POSTROUTING链&lt;/h1&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;我们最后的任务应该是构造网络地址转换，对吧？至少对我来说是的。我们在nat表的POSTROUTING里只加入了一条规则，它会对所有从Internet接口（对我来说，这是eth0）发出的包进行NAT操作。在所有的例子脚本里，都有一些变量，它们要给以正确的配置。选项-t指定要在哪个表里插入规则，这里是nat表。命令-A说明我们要把规则添加到POSTROUTING链末尾。-o$INET_IFACE指定要匹配所有从接口INET_IFACE出去的包，这里我们使用的是eth0。最后，我们把target设置为SNAT。这样，所有匹配此规则的包都会由SNAT target处理之后，它们的源地址就是Internet接口的地址了。不要忘了SNAT可是一定要有IP地址的，用--to-source来设置哦。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;prerouting链&quot;&gt;PREROUTING链&lt;/h1&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;顾名思义，PREROUTING链（nat表的）是在路由之前做网络地址转换工作的。然后，包再经过路由，就会被送到filter表的INPUT或FORWARD链。我们在这里讨论这个链的唯一原因是，我们觉得有责任再次指出你不应该在此链中做任何过滤。PREROUTING链只会匹配流的第一个包，也就是说，这个流的所有其他包都不会被此链检查。事实上，在这个脚本中，我们根本没有用到PREROUTING链。如果你想对一些包做DNAT操作，例如，你把web service放在了局域网内，这里就是你放置规则的地方，有关PREROUTING链的详细信息在章节表和链中。
iptables -L命令还可以查看nat表和mangle表的内容哦
iptables -L -t nat
cat /proc/net/ip_conntrack | less
iptables -F -t nat (清除NAT表)
iptables --list 查看过滤表
新的规则存盘
./iptables save
在/proc/net/ip_conntrack文件里也有包的流向
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Fri, 28 Apr 2017 16:09:00 +0000</pubDate>
        <link>https://shunliz.github.io/network/2017/04/28/snat-dnat-iptables.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/network/2017/04/28/snat-dnat-iptables.html</guid>
        
        <category>SNAT,</category>
        
        <category>DNAT,</category>
        
        <category>Iptables</category>
        
        
        <category>network</category>
        
      </item>
    
      <item>
        <title>Scikit-learn 线性回归总结</title>
        <description>&lt;p&gt;　　　　scikit-learn对于线性回归提供了比较多的类库，这些类库都可以用来做线性回归分析，本文就对这些类库的使用做一个总结，重点讲述这些线性回归算法库的不同和各自的使用场景。&lt;/p&gt;

&lt;p&gt;　　　　线性回归的目的是要得到输出向量YY和输入特征XX之间的线性关系，求出线性回归系数θθ,也就是 Y=XθY=Xθ。其中YY的维度为mx1，XX的维度为mxn，而θθ的维度为nx1。m代表样本个数，n代表样本特征的维度。&lt;/p&gt;

&lt;p&gt;　　　　为了得到线性回归系数θθ，我们需要定义一个损失函数，一个极小化损失函数的优化方法，以及一个验证算法的方法。损失函数的不同，损失函数的优化方法的不同，验证方法的不同，就形成了不同的线性回归算法。scikit-learn中的线性回归算法库可以从这这三点找出各自的不同点。理解了这些不同点，对不同的算法使用场景也就好理解了。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;LinearRegression
　　　　损失函数：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　LinearRegression类就是我们平时说的最常见普通的线性回归，它的损失函数也是最简单的，如下：&lt;/p&gt;

&lt;p&gt;　　　　J(θ)=12(Xθ−Y)T(Xθ−Y)J(θ)=12(Xθ−Y)T(Xθ−Y)
　　　　损失函数的优化方法：&lt;/p&gt;

&lt;p&gt;　　　　对于这个损失函数，一般有梯度下降法和最小二乘法两种极小化损失函数的优化方法，而scikit中的LinearRegression类用的是最小二乘法。通过最小二乘法，可以解出线性回归系数θθ为：&lt;/p&gt;

&lt;p&gt;　　　　θ=(XTX)−1XTYθ=(XTX)−1XTY
　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　LinearRegression类并没有用到交叉验证之类的验证方法，需要我们自己把数据集分成训练集和测试集，然后训练优化。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　一般来说，只要我们觉得数据有线性关系，LinearRegression类是我们的首先。如果发现拟合或者预测的不好，再考虑用其他的线性回归库。如果是学习线性回归，推荐先从这个类开始第一步的研究。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Ridge
　　　　损失函数：　&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　由于第一节的LinearRegression没有考虑过拟合的问题，有可能泛化能力较差，这时损失函数可以加入正则化项，如果加入的是L2范数的正则化项，这就是Ridge回归。损失函数如下：&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;　　　　J(θ)=12(Xθ−Y)T(Xθ−Y)+12α&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;θ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;22J(θ)=12(Xθ−Y)T(Xθ−Y)+12α&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;θ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;22&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;　　　　其中αα为常数系数，需要进行调优。&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;θ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;θ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;2为L2范数。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;　　　　Ridge回归在不抛弃任何一个特征的情况下，缩小了回归系数，使得模型相对而言比较的稳定，不至于过拟合。&lt;/p&gt;

&lt;p&gt;　　　　损失函数的优化方法：&lt;/p&gt;

&lt;p&gt;　　　　对于这个损失函数，一般有梯度下降法和最小二乘法两种极小化损失函数的优化方法，而scikit中的Ridge类用的是最小二乘法。通过最小二乘法，可以解出线性回归系数θθ为：&lt;/p&gt;

&lt;p&gt;　　　　θ=(XTX+αE)−1XTYθ=(XTX+αE)−1XTY
　　　　其中E为单位矩阵。&lt;/p&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　Ridge类并没有用到交叉验证之类的验证方法，需要我们自己把数据集分成训练集和测试集，需要自己设置好超参数αα。然后训练优化。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　一般来说，只要我们觉得数据有线性关系，用LinearRegression类拟合的不是特别好，需要正则化，可以考虑用Ridge类。但是这个类最大的缺点是每次我们要自己指定一个超参数αα，然后自己评估αα的好坏，比较麻烦，一般我都用下一节讲到的RidgeCV类来跑Ridge回归，不推荐直接用这个Ridge类，除非你只是为了学习Ridge回归。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;RidgeCV
　　　　RidgeCV类的损失函数和损失函数的优化方法完全与Ridge类相同，区别在于验证方法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　RidgeCV类对超参数αα使用了交叉验证，来帮忙我们选择一个合适的αα。在初始化RidgeCV类时候，我们可以传一组备选的αα值，10个，100个都可以。RidgeCV类会帮我们选择一个合适的αα。免去了我们自己去一轮轮筛选αα的苦恼。　　&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　一般来说，只要我们觉得数据有线性关系，用LinearRegression类拟合的不是特别好，需要正则化，可以考虑用RidgeCV类。不是为了学习的话就不用Ridge类。为什么这里只是考虑用RidgeCV类呢？因为线性回归正则化有很多的变种，Ridge只是其中的一种。所以可能需要比选。如果输入特征的维度很高，而且是稀疏线性关系的话，RidgeCV类就不合适了。这时应该主要考虑下面几节要讲到的Lasso回归类家族。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Lasso
　　　　损失函数：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　线性回归的L1正则化通常称为Lasso回归，它和Ridge回归的区别是在损失函数上增加了的是L1正则化的项，而不是L2正则化项。L1正则化的项也有一个常数系数αα来调节损失函数的均方差项和正则化项的权重，具体Lasso回归的损失函数表达式如下：　　&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;　　　　J(θ)=12m(Xθ−Y)T(Xθ−Y)+α&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;θ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;1J(θ)=12m(Xθ−Y)T(Xθ−Y)+α&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;θ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;　　　　其中n为样本个数，αα为常数系数，需要进行调优。&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;θ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;θ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;1为L1范数。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;　　　　Lasso回归可以使得一些特征的系数变小，甚至还是一些绝对值较小的系数直接变为0。增强模型的泛化能力。&lt;/p&gt;

&lt;p&gt;　　　　损失函数的优化方法：&lt;/p&gt;

&lt;p&gt;　　　　Lasso回归的损失函数优化方法常用的有两种，坐标轴下降法和最小角回归法。Lasso类采用的是坐标轴下降法，后面讲到的LassoLars类采用的是最小角回归法&lt;/p&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　Lasso类并没有用到交叉验证之类的验证方法，和Ridge类类似。需要我们自己把数据集分成训练集和测试集，需要自己设置好超参数αα。然后训练优化。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　一般来说，对于高维的特征数据，尤其线性关系是稀疏的，我们会采用Lasso回归。或者是要在一堆特征里面找出主要的特征，那么Lasso回归更是首选了。但是Lasso类需要自己对αα调优，所以不是Lasso回归的首选，一般用到的是下一节要讲的LassoCV类。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;LassoCV　　　　
　　　　LassoCV类的损失函数和损失函数的优化方法完全与Lasso类相同，区别在于验证方法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　LassoCV类对超参数αα使用了交叉验证，来帮忙我们选择一个合适的αα。在初始化LassoCV类时候，我们可以传一组备选的αα值，10个，100个都可以。LassoCV类会帮我们选择一个合适的αα。免去了我们自己去一轮轮筛选αα的苦恼。　&lt;/p&gt;

&lt;p&gt;　　　　使用场景：　　&lt;/p&gt;

&lt;p&gt;　　　　LassoCV类是进行Lasso回归的首选。当我们面临在一堆高位特征中找出主要特征时，LassoCV类更是必选。当面对稀疏线性关系时，LassoCV也很好用。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;LassoLars
　　　　LassoLars类的损失函数和验证方法与Lasso类相同，区别在于损失函数的优化方法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　损失函数的优化方法：&lt;/p&gt;

&lt;p&gt;　　　　Lasso回归的损失函数优化方法常用的有两种，坐标轴下降法和最小角回归法。LassoLars类采用的是最小角回归法，前面讲到的Lasso类采用的是坐标轴下降法。　　　&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　LassoLars类需要自己对αα调优，所以不是Lasso回归的首选，一般用到的是下一节要讲的LassoLarsCV类。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;LassoLarsCV
　　　　LassoLarsCV类的损失函数和损失函数的优化方法完全与LassoLars类相同，区别在于验证方法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　LassoLarsCV类对超参数αα使用了交叉验证，来帮忙我们选择一个合适的αα。在初始化LassoLarsCV类时候，我们可以传一组备选的αα值，10个，100个都可以。LassoLarsCV类会帮我们选择一个合适的αα。免去了我们自己去一轮轮筛选αα的苦恼。　&lt;/p&gt;

&lt;p&gt;　　　　使用场景：　　&lt;/p&gt;

&lt;p&gt;　　　　LassoLarsCV类是进行Lasso回归的第二选择。第一选择是前面讲到LassoCV类。那么LassoLarsCV类有没有适用的场景呢？换句话说，用最小角回归法什么时候比坐标轴下降法好呢？场景一：如果我们想探索超参数αα更多的相关值的话，由于最小角回归可以看到回归路径，此时用LassoLarsCV比较好。场景二： 如果我们的样本数远小于样本特征数的话，用LassoLarsCV也比LassoCV好。其余场景最好用LassoCV。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;LassoLarsIC
　　　　LassoLarsIC类的损失函数和损失函数的优化方法完全与LassoLarsCV类相同，区别在于验证方法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　LassoLarsIC类对超参数αα没有使用交叉验证，而是用 Akaike信息准则(AIC)和贝叶斯信息准则(BIC)。此时我们并不需要指定备选的αα值，而是由LassoLarsIC类基于AIC和BIC自己选择。用LassoLarsIC类我们可以一轮找到超参数αα，而用K折交叉验证的话，我们需要K+1轮才能找到。相比之下LassoLarsIC类寻找αα更快。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　从验证方法可以看出，验证ααLassoLarsIC比LassoLarsCV快很多。那么是不是LassoLarsIC类一定比LassoLarsCV类好呢？ 不一定！由于使用了AIC和BIC准则，我们的数据必须满足一定的条件才能用LassoLarsIC类。这样的准则需要对解的自由度做一个适当的估计。该估计是来自大样本（渐近结果），并假设该模型是正确的（即这些数据确实是由假设的模型产生的）。当待求解的问题的条件数很差的时候（比如特征个数大于样本数量的时候），这些准则就会有崩溃的风险。所以除非我们知道数据是来自一个模型确定的大样本，并且样本数量够大，我们才能用LassoLarsIC。而实际上我们得到的数据大部分都不能满足这个要求，实际应用中我没有用到过这个看上去很美的类。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;ElasticNet
　　　　损失函数：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　ElasticNet可以看做Lasso和Ridge的中庸化的产物。它也是对普通的线性回归做了正则化，但是它的损失函数既不全是L1的正则化，也不全是L2的正则化，而是用一个权重参数ρρ来平衡L1和L2正则化的比重，形成了一个全新的损失函数如下：　　&lt;/p&gt;

&lt;p&gt;　　　　J(θ)=12m(Xθ−Y)T(Xθ−Y)+αρ||θ||1+α(1−ρ)2||θ||22J(θ)=12m(Xθ−Y)T(Xθ−Y)+αρ||θ||1+α(1−ρ)2||θ||22
　　　　其中αα为正则化超参数，ρρ为范数权重超参数。&lt;/p&gt;

&lt;p&gt;　　　　损失函数的优化方法：&lt;/p&gt;

&lt;p&gt;　　　　ElasticNet回归的损失函数优化方法常用的有两种，坐标轴下降法和最小角回归法。ElasticNet类采用的是坐标轴下降法。&lt;/p&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　ElasticNet类并没有用到交叉验证之类的验证方法，和Lasso类类似。需要我们自己把数据集分成训练集和测试集，需要自己设置好超参数αα和ρρ。然后训练优化。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　ElasticNet类需要自己对αα和ρρ调优，所以不是ElasticNet回归的首选，一般用到的是下一节要讲的ElasticNetCV类。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;ElasticNetCV
　　　　ElasticNetCV类的损失函数和损失函数的优化方法完全与ElasticNet类相同，区别在于验证方法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　ElasticNetCV类对超参数αα和 ρρ使用了交叉验证，来帮忙我们选择合适的αα和ρρ。在初始化ElasticNetCV类时候，我们可以传一组备选的αα值和ρρ，10个，100个都可以。ElasticNetCV类会帮我们选择一个合适的αα和ρρ。免去了我们自己去一轮轮筛选αα和ρρ的苦恼。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　ElasticNetCV类用在我们发现用Lasso回归太过（太多特征被稀疏为0），而用Ridge回归又正则化的不够（回归系数衰减的太慢）的时候。一般不推荐拿到数据就直接就上ElasticNetCV。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;OrthogonalMatchingPursuit
　　　　损失函数：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　OrthogonalMatchingPursuit（OMP）算法和普通的线性回归损失函数的区别是增加了一个限制项，来限制回归系数中非0元素的最大个数。形成了一个全新的损失函数如下：&lt;/p&gt;

&lt;p&gt;　　　　J(θ)=12(Xθ−Y)T(Xθ−Y)J(θ)=12(Xθ−Y)T(Xθ−Y)
　　　　subject to ||θ||0≤nnon−zero−coefs||θ||0≤nnon−zero−coefs ,其中(||θ||0(||θ||0代表θθ的L0范数，即非0回归系数的个数。&lt;/p&gt;

&lt;p&gt;　　　　损失函数的优化方法：　　　&lt;/p&gt;

&lt;p&gt;　　　　OrthogonalMatchingPursuit类使用前向选择算法来优化损失函数。它是最小角回归算法的缩水版。虽然精度不如最小角回归算法，但是运算速度很快。&lt;/p&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　OrthogonalMatchingPursuit类并没有用到交叉验证之类的验证方法，和Lasso类类似。需要我们自己把数据集分成训练集和测试集，需要自己选择限制参数nnon−zero−coefsnnon−zero−coefs。然后训练优化。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　OrthogonalMatchingPursuit类需要自己选择nnon−zero−coefsnnon−zero−coefs，所以不是OrthogonalMatchingPursuit回归的首选，一般用到的是下一节要讲的OrthogonalMatchingPursuitCV类，不过如果你已经定好了nnon−zero−coefsnnon−zero−coefs的值，那用OrthogonalMatchingPursuit比较方便。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;OrthogonalMatchingPursuitCV
　　　　OrthogonalMatchingPursuitCV类的损失函数和损失函数的优化方法完全与OrthogonalMatchingPursuit类相同，区别在于验证方法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　OrthogonalMatchingPursuitCV类使用交叉验证，在S折交叉验证中以MSE最小为标准来选择最好的nnon−zero−coefsnnon−zero−coefs。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　OrthogonalMatchingPursuitCV类通常用在稀疏回归系数的特征选择上，这点和LassoCV有类似的地方。不过由于它的损失函数优化方法是前向选择算法，精确度较低，一般情况不是特别推荐用，用LassoCV就够，除非你对稀疏回归系数的精确个数很在意，那可以考虑用OrthogonalMatchingPursuitCV。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;MultiTaskLasso
　　　　从这节到第16节，类里面都带有一个“MultiTask”的前缀。不过他不是编程里面的多线程，而是指多个线性回归模型共享样本特征，但是有不同的回归系数和特征输出。具体的线性回归模型是Y=XWY=XW。其中X是mxn维度的矩阵。W为nxk维度的矩阵，Y为mxk维度的矩阵。m为样本个数，n为样本特征，而k就代表多个回归模型的个数。所谓的“MultiTask”这里其实就是指k个线性回归的模型一起去拟合。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　损失函数：&lt;/p&gt;

&lt;p&gt;　　　　由于这里是多个线性回归一起拟合，所以损失函数和前面的都很不一样：&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;　　　　J(W)=12m(&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;XW−Y&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)2Fro+α&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;21J(W)=12m(&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;XW−Y&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)Fro2+α&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;21&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;　　　　其中， (&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;XW−Y&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)Fro(&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;XW−Y&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)Fro是Y=XWY=XW的Frobenius范数。而&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;21&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;21代表W的各列的根平方和之和。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;　　　　损失函数的优化方法：　　　&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskLasso类使用坐标轴下降法来优化损失函数。&lt;/p&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskLasso类并没有用到交叉验证之类的验证方法，和Lasso类类似。需要我们自己把数据集分成训练集和测试集，需要自己设置好超参数αα。然后训练优化。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskLasso类需要自己对αα调优，所以不是共享特征协同回归的首选，一般用到的是下一节要讲的MultiTaskLassoCV类。　　　&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;MultiTaskLassoCV
　　　　MultiTaskLassoCV类的损失函数和损失函数的优化方法完全与MultiTaskLasso类相同，区别在于验证方法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskLassoCV类对超参数αα使用了交叉验证，来帮忙我们选择一个合适的αα。在初始化LassoLarsCV类时候，我们可以传一组备选的αα值，10个，100个都可以。MultiTaskLassoCV类会帮我们选择一个合适的αα。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskLassoCV是多个回归模型需要一起共享样本特征一起拟合时候的首选。它可以保证选到的特征每个模型都用到。不会出现某个模型选到了某特征而另一个模型没选到这个特征的情况。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;MultiTaskElasticNet
　　　　损失函数：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　MultiTaskElasticNet类和MultiTaskLasso类的模型是相同的。不过损失函数不同。损失函数表达式如下：&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;　　　　J(W)=12m(&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;XW−Y&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)2Fro+αρ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;21+α(1−ρ)2(&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)2FroJ(W)=12m(&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;XW−Y&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)Fro2+αρ&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;21+α(1−ρ)2(&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)Fro2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;　　　　其中， (&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;XW−Y&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)Fro(&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;XW−Y&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;)Fro是Y=XWY=XW的Frobenius范数。而&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;21&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;21代表W的各列的根平方和之和。&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;　　　　损失函数的优化方法：　　　&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskElasticNet类使用坐标轴下降法来优化损失函数。&lt;/p&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskElasticNet类并没有用到交叉验证之类的验证方法，和Lasso类类似。需要我们自己把数据集分成训练集和测试集，需要自己设置好超参数αα和ρρ。然后训练优化。　&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskElasticNet类需要自己对αα调优，所以不是共享特征协同回归的首选，如果需要用MultiTaskElasticNet，一般用到的是下一节要讲的MultiTaskElasticNetCV类。　&lt;/p&gt;

&lt;p&gt;　　　　&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;MultiTaskElasticNetCV
　　　　MultiTaskElasticNetCV类的损失函数和损失函数的优化方法完全与MultiTaskElasticNet类相同，区别在于验证方法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　验证方法：&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskElasticNetCV类对超参数αα和 ρρ使用了交叉验证，来帮忙我们选择合适的αα和ρρ。在初始化MultiTaskElasticNetCV类时候，我们可以传一组备选的αα值和ρρ，10个，100个都可以。ElasticNetCV类会帮我们选择一个合适的αα和ρρ。免去了我们自己去一轮轮筛选αα和ρρ的苦恼。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　MultiTaskElasticNetCV是多个回归模型需要一起共享样本特征一起拟合时候的两个备选之一，首选是MultiTaskLassoCV。如果我们发现用MultiTaskLassoCV时回归系数衰减的太快，那么可以考虑用MultiTaskElasticNetCV。　　　&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;BayesianRidge
　　　　第17和18节讲的都是贝叶斯回归模型。贝叶斯回归模型假设先验概率，似然函数和后验概率都是正态分布。先验概率是假设模型输出Y是符合均值为XθXθ的正态分布，正则化参数αα被看作是一个需要从数据中估计得到的随机变量。回归系数θθ的先验分布规律为球形正态分布，超参数为λλ。我们需要通过最大化边际似然函数来估计超参数αα和λλ，以及回归系数θθ。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　此处对损失函数即负的最大化边际似然函数不多讨论，不过其形式和Ridge回归的损失函数很像，所以也取名BayesianRidge。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　如果我们的数据有很多缺失或者矛盾的病态数据，可以考虑BayesianRidge类，它对病态数据鲁棒性很高，也不用交叉验证选择超参数。但是极大化似然函数的推断过程比较耗时，一般情况不推荐使用。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;ARDRegression
　　　　ARDRegression和BayesianRidge很像，唯一的区别在于对回归系数θθ的先验分布假设。BayesianRidge假设θθ的先验分布规律为球形正态分布，而ARDRegression丢掉了BayesianRidge中的球形高斯的假设，采用与坐标轴平行的椭圆形高斯分布。这样对应的超参数λλ有n个维度，各不相同。而上面的BayesianRidge中球形分布的θθ对应的λλ只有一个。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;　　　　ARDRegression也是通过最大化边际似然函数来估计超参数αα和λλ向量，以及回归系数θθ。&lt;/p&gt;

&lt;p&gt;　　　　使用场景：&lt;/p&gt;

&lt;p&gt;　　　　如果我们的数据有很多缺失或者矛盾的病态数据，可以考虑BayesianRidge类，如果发现拟合不好，可以换ARDRegression试一试。因为ARDRegression对回归系数先验分布的假设没有BayesianRidge严格，某些时候会比BayesianRidge产生更好的后验结果。&lt;/p&gt;

&lt;p&gt;以上就是scikit-learn中线性回归的一个总结，希望可以帮到朋友们。&lt;/p&gt;

</description>
        <pubDate>Wed, 26 Apr 2017 16:09:00 +0000</pubDate>
        <link>https://shunliz.github.io/ml/2017/04/26/scikit-learn-lr.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/ml/2017/04/26/scikit-learn-lr.html</guid>
        
        <category>ML</category>
        
        <category>Scikit-learn</category>
        
        
        <category>ML</category>
        
      </item>
    
      <item>
        <title>libnetwork设计思想</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://github.com/docker/libnetwork/blob/master/docs/cnm-model.jpg?raw=true&quot; alt=&quot;libnetwork&quot; /&gt;&lt;/p&gt;

&lt;p&gt;libnetwork实现了一个叫做Container Network Model (CNM)的东西，也就是说起希望成为容器的标准网络模型、框架。其包含了下面几个概念：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Sandbox。对于Sandbox大家就认为是一个namespace即可。联系我们前面Kubernetes中说的Pod，Sandbox其实就是传统意义上的虚拟机的意思。&lt;/li&gt;
  &lt;li&gt;Endpoint。Neutron中和Endpoint相对的概念我想应该是VNIC，也就是虚拟机的虚拟网卡（也可以看成是VIF）。当Sandbox要和外界通信的时候就是通过Endpoint连接到外界的，最简单的情况就是连接到一个Bridge上。&lt;/li&gt;
  &lt;li&gt;Network。libnetwork中的Network大家就认为是Neutron中的network即可，更加贴切点的话可以认为是Neutron中的一个拥有一个subnet的network。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;上面这三个概念就是libnetwork的CNM的核心概念，熟悉了Neutron后并不会对这几个概念在理解上有多大问题。下面我们看下libnetwork为了对外提供这几个概念而暴露的编程结构体：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;NetworkController。用于获取一个控制器，可以认为通过这个控制器可以对接下来的所有网络操作进行操作。Neutron中并没有这么一个概念，因为Neutron中的网络是由agent通过轮询或者消息的方式来间接操作的，而不是由用户使用docker命令直接在本机进行操作。&lt;/li&gt;
  &lt;li&gt;Driver。这里的Driver类似于Neutron中的core_plugin或者是ml2下的各种driver，表示的是底层网络的实现方法。比如有bridge的driver，也有基于vxlan的overlay的driver等等。这个概念和Neutron中的driver概念基本上是一样的。&lt;/li&gt;
  &lt;li&gt;Network。这里的Network结构体就是对应的上面CNM中的Network，表示建立了一个网络。通过这个结构体可以对建立的网络进行操作。&lt;/li&gt;
  &lt;li&gt;Endpoint。这里的Endpoint结构体就是对应上面CNM中的Endpoint，表示建立了一个VNIC或者是VIF。通过这个结构体可以对Endpoint进行操作。&lt;/li&gt;
  &lt;li&gt;Sandbox。这里的Sandbox结构体就是对应上面CNM中的Sandbox，表示建立了一个独立的名字空间。可以类比Nova的虚拟机或者是Kubernetes的Pod，亦或是独立的Docker容器。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;接着我们看下一般使用libnetwork的方法，具体的步骤一般是下面这样的：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;获取一个NetworkController对象用于进行下面的操作。获取对象的时候指定Driver。&lt;/li&gt;
  &lt;li&gt;通过NetworkController对象的NewNetwork()建立一个网络。这里最简单的理解就是现在我们有了一个bridge了。&lt;/li&gt;
  &lt;li&gt;通过网络的CreateEndpoint()在这个网络上建立Endpoint。这里最简单的理解就是每建立一个Endpoint，我们上面建立的bridge上就会多出一个VIF口等着虚拟机或者Sandbox连上来。假设这里使用的是veth，则veth的一头目前接在了bridge中，另一头还暴露在外面。&lt;/li&gt;
  &lt;li&gt;调用上面建立的Endpoint的Join方法，提供容器信息，于是libnetwork的代码就会建立一个Sandbox对象（一般这里的Sandbox就是容器的namespace，所以不会重复建立），然后将第三步建立的veth的一头接入到这个Sandbox中，也就是将其放到Sandbox的namespace中。&lt;/li&gt;
  &lt;li&gt;当Sandbox的生命周期结束时，调用Endpoint的Leave方法使其从这个Network中解绑。简单的说就是将veth从Sandbox的namespace中拿出来回到物理机上。&lt;/li&gt;
  &lt;li&gt;如果一个Endpoint无用了，则可以调用Delete方法删除。&lt;/li&gt;
  &lt;li&gt;如果一个Network无用了，则可以调用Delete方法删除。&lt;/li&gt;
&lt;/ol&gt;

</description>
        <pubDate>Thu, 09 Mar 2017 18:42:09 +0000</pubDate>
        <link>https://shunliz.github.io/docker/network/2017/03/09/libnetwork-design.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/docker/network/2017/03/09/libnetwork-design.html</guid>
        
        <category>Docker</category>
        
        <category>network</category>
        
        
        <category>Docker</category>
        
        <category>network</category>
        
      </item>
    
      <item>
        <title>闲言碎语</title>
        <description>&lt;h1 id=&quot;年轻人应拒绝的工作&quot;&gt;【年轻人应拒绝的工作】&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;摧毁身体的，如喝酒要喝到吐的；&lt;/li&gt;
  &lt;li&gt;摧毁心灵的，如莫名其妙就有钱有权的；&lt;/li&gt;
  &lt;li&gt;摧毁形象的，如成天和不务正业的在一起；&lt;/li&gt;
  &lt;li&gt;摧毁成长的，如公司只管赚钱不培训的；&lt;/li&gt;
  &lt;li&gt;摧毁品德的，名利目前得不少却会落个骂名的；&lt;/li&gt;
  &lt;li&gt;摧毁未来的，合作的人不注重未来。学会说不，为更好的未来。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;http://ww2.sinaimg.cn/bmiddle/71ced708jw1drhfdhz7jij.jpg&quot; alt=&quot;img1&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;管理心理好主管应做的8件事&quot;&gt;【管理心理：好主管应做的8件事】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;给下属争取更多利益，而非公司能给的额度，下属会以绩效的方式翻倍回报；&lt;/li&gt;
  &lt;li&gt;花时间分享你的经验和观点；&lt;/li&gt;
  &lt;li&gt;和下属直接沟通，即使是坏消息；&lt;/li&gt;
  &lt;li&gt;背后给下属支持；&lt;/li&gt;
  &lt;li&gt;热情表扬；&lt;/li&gt;
  &lt;li&gt;分配责任，而非工作；&lt;/li&gt;
  &lt;li&gt;用人所长；&lt;/li&gt;
  &lt;li&gt;让下属知道尊重需赢得。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;facebook-励志标语&quot;&gt;【Facebook 励志标语】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;Done is better than perfect. 比完美更重要的是完成；&lt;/li&gt;
  &lt;li&gt;Move fast and break things 快速行动，破除陈规；&lt;/li&gt;
  &lt;li&gt;Stay focused and keep shipping. 保持专注，持续发布。&lt;/li&gt;
  &lt;li&gt;Code wins arguments.代码赢得争论。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;什么样的男人最受欢迎&quot;&gt;【什么样的男人最受欢迎】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;工作起来专注专业，甚至让人着迷；&lt;/li&gt;
  &lt;li&gt;娱乐起来玩得很开，偶尔可以发发疯；&lt;/li&gt;
  &lt;li&gt;对待家人有担当，负起自己要负的责；&lt;/li&gt;
  &lt;li&gt;对待朋友豪爽大气，绝不扭捏或者耍心眼；&lt;/li&gt;
  &lt;li&gt;对生活永远充满激情，可以切换不同状态；&lt;/li&gt;
  &lt;li&gt;办事利索高效，做人简单坦诚，人生目标坚定明确，生涯规划清晰合理。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;人生心语&quot;&gt;【人生心语】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;心里种上快乐，就不会长出痛苦。&lt;/li&gt;
  &lt;li&gt;心里充满善意，就不会滋生恶念。&lt;/li&gt;
  &lt;li&gt;心里播下爱种，心中就会长出爱心。&lt;/li&gt;
  &lt;li&gt;有慈悲就不会有敌人，有智慧就不会滋生烦恼。&lt;/li&gt;
  &lt;li&gt;有功不可以记功，有过不可以忘过。&lt;/li&gt;
  &lt;li&gt;有怨不可以记怨，有恩不可以忘恩。&lt;/li&gt;
  &lt;li&gt;屋宽还不如心宽，身安还不如心安&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;人生三大追求&quot;&gt;【人生三大追求】&lt;/h1&gt;
&lt;p&gt;人努力奋斗一生，大多是为了实现三大自由：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;财务自由：有足够金钱养活自己和家人，需要用钱时不发愁；&lt;/li&gt;
  &lt;li&gt;时间自由：有可支配时间灵活安排工作、休息和娱乐；&lt;/li&gt;
  &lt;li&gt;心灵自由：跟随自己内心，不让梦想憋屈。实现自由最容易的时间段，不是未来的某天而是现在。你同意吗？&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;http://ww4.sinaimg.cn/bmiddle/71ced708jw1drg9xf366zj.jpg&quot; alt=&quot;egales&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;做人十心机&quot;&gt;【做人十心机】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;做人不能太单纯 ，适度伪装自己 。&lt;/li&gt;
  &lt;li&gt;凡事留余地 ，要留退路 ，&lt;/li&gt;
  &lt;li&gt;话不说绝， 口无遮拦难成大事 。&lt;/li&gt;
  &lt;li&gt;成熟而不世故 。&lt;/li&gt;
  &lt;li&gt;心态好 想得开活得不累&lt;/li&gt;
  &lt;li&gt;懂方圆之道：没事不惹事，来事不怕事 。&lt;/li&gt;
  &lt;li&gt;不可少二礼:礼仪与礼物&lt;/li&gt;
  &lt;li&gt;人在江湖飘 防挨朋友刀&lt;/li&gt;
  &lt;li&gt;偶尔”势利眼” 寻可靠伙伴&lt;/li&gt;
  &lt;li&gt;放下面子来做人。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;杜月笙看人秘籍&quot;&gt;【杜月笙看人秘籍】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;一群人中最安静的人，往往最有实力。&lt;/li&gt;
  &lt;li&gt;胆小的男孩一般能成大事。&lt;/li&gt;
  &lt;li&gt;打仗前思后想才是帅才。&lt;/li&gt;
  &lt;li&gt;流泪的男人一定有爱心。&lt;/li&gt;
  &lt;li&gt;爱骂人的人，内心都很恐惧。&lt;/li&gt;
  &lt;li&gt;重情之人，难有爱情之幸福。当你说岀爱字，你就处于了被动。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;豁达人生必须把握五个要点&quot;&gt;【豁达人生必须把握五个要点】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;当识人，识人不必探尽，探尽则多怨。&lt;/li&gt;
  &lt;li&gt;当知人，知人不必言尽，言尽则无友。&lt;/li&gt;
  &lt;li&gt;当责人，责人不必苛尽，苛尽则众远。&lt;/li&gt;
  &lt;li&gt;当敬人，敬人不必卑尽，卑尽则少骨。&lt;/li&gt;
  &lt;li&gt;当让人，让人不必退尽，退尽则路艰。&lt;/li&gt;
  &lt;li&gt;有境界，能看远；有肚量，能看宽；有涵养，能自持；有锋芒，能内敛。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;冯仑人生智慧&quot;&gt;【冯仑人生智慧——】&lt;/h1&gt;
&lt;p&gt;择高处立，就平处坐，向宽处行。&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;做事眼光要高，坚持理想，超越金钱，跳出自我，叫高处立；&lt;/li&gt;
  &lt;li&gt;做事心气儿不能太高，要照顾周围，跟大家很好地相处，这叫平处坐；&lt;/li&gt;
  &lt;li&gt;做事有了这两个基础，方法、眼界、人脉越来越宽，就能向宽处行。每天问问自己，&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这3点你做到了吗？&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;一个男人，经历了生死、爱恨、委屈、是非这四堂课会变得更成熟，经历的痛苦越多，男人就越发变得宽容、坚强、睿智、勇敢、幽默。—《伟大是熬出来的》&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;我们这一生要走很多路，有笔直坦途，有羊肠阡陌，有繁华也有荒凉。无论如何，路要自己走，苦要自己吃，任何人无法给予全部依赖。没有所谓的无路可走，即使孤独跋涉，寂寞坚守，只要你愿意走，踩过的都是路。你以为走不过去的，跨过去回头看看，也不过如此。不回避不退缩，未来终将到来！&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;女孩买了条裤子，一试太长，请奶奶帮忙剪短，奶奶说忙；找妈妈，也没空；找姐姐，更没空。女孩失望地入睡了。奶奶忙完家务想起小孙女的裤子，就把裤子剪短了一点；姐姐回来又把裤子剪短了；妈妈回来也把裤子剪短了，最后裤子没法穿了。——管理的弊端就在于：要么都不管，要么都来管！&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;品味人生&quot;&gt;【品味人生】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;善良的人被别人利用，不善良的人利用别人。&lt;/li&gt;
  &lt;li&gt;女人用情商玩男人，男人用智商玩女人。&lt;/li&gt;
  &lt;li&gt;人人都讲理时有理可走遍天下，人人都不讲理时有理将寸步难行。&lt;/li&gt;
  &lt;li&gt;站在天堂看地狱，人生就像情景剧，站在地狱看天堂，为谁辛苦为谁忙。&lt;/li&gt;
  &lt;li&gt;天才一定都是不正常的人，不正常的人不一定都是天才。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;最适合做合伙人的10类人&quot;&gt;【最适合做合伙人的10类人】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;彼此是谈得来的朋友。&lt;/li&gt;
  &lt;li&gt;有共同的人生价值观。&lt;/li&gt;
  &lt;li&gt;彼此能充分了解信任。&lt;/li&gt;
  &lt;li&gt;遇事彼此易沟通。&lt;/li&gt;
  &lt;li&gt;彼此有奉献牺牲精神。&lt;/li&gt;
  &lt;li&gt;彼此宽容大度。&lt;/li&gt;
  &lt;li&gt;志趣要能基本相投。&lt;/li&gt;
  &lt;li&gt;彼此能坚定支持对方。&lt;/li&gt;
  &lt;li&gt;彼此有一定专业背景。&lt;/li&gt;
  &lt;li&gt;有共同理想。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;做人为何要低调&quot;&gt;【做人为何要低调？】&lt;/h1&gt;
&lt;p&gt;真正有大智慧和大才华的人，必定是低调的。才华和智慧像悬在精神深处的皎洁明月，早已照彻了他们的心性。他们行走在尘世间，眼神是慈祥的，脸色是和蔼的，腰身是谦恭的，心底是平和的，灵魂是宁静的。正所谓，大智慧大智若愚，大才华朴实无华。&lt;/p&gt;

&lt;h1 id=&quot;男人最不该做的7件事&quot;&gt;【男人最不该做的7件事】&lt;/h1&gt;
&lt;p&gt;一、没有目标（不知道自己该干嘛，混日子）。&lt;/p&gt;

&lt;p&gt;二、浪费时间（比如游戏或者滥情）。&lt;/p&gt;

&lt;p&gt;三、不独立（等着别人来搭救）。&lt;/p&gt;

&lt;p&gt;四、被动的活着（别人说什么就做什么，要么就什么也不做）。&lt;/p&gt;

&lt;p&gt;五、不规划自己的人生。&lt;/p&gt;

&lt;p&gt;六、不学习吸收信息。&lt;/p&gt;

&lt;p&gt;七、不接受爱情。&lt;/p&gt;

&lt;h1 id=&quot;论水平&quot;&gt;【论水平】&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;思想水平不仅在看得见，更在看得穿；不仅在想得到，更在想得透。&lt;/li&gt;
  &lt;li&gt;阅历水平不仅在经受过，更在体验过；不仅在浏览，更在总览。&lt;/li&gt;
  &lt;li&gt;处世水平不仅在和平，更在平和；不仅在有友，更在无仇。&lt;/li&gt;
  &lt;li&gt;办事水平不仅在利落，更在稳妥；不仅在成事，更在开拓。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;人之最&quot;&gt;【人之最】&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;人最悲哀的，并不是昨天失去得太多，而是沉浸于昨天的悲哀之中；&lt;/li&gt;
  &lt;li&gt;人最愚蠢的，并不是没有发现眼前的陷阱，而是第二次又掉了进去；&lt;/li&gt;
  &lt;li&gt;人最寂寞的，并不是想等的人还没有来，而是这个人已从心里走了出去；&lt;/li&gt;
  &lt;li&gt;人最无聊的，并不是随便拨通一个电话号码，而是别人拨错时，他还一直的说下去。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;【人生“势利表”：你能看清第几行？】&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ww2.sinaimg.cn/bmiddle/61e44a60jw1draokeyxb8j.jpg&quot; alt=&quot;eye&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Sun, 05 Mar 2017 13:00:09 +0000</pubDate>
        <link>https://shunliz.github.io/life/2017/03/05/words-of-life.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/life/2017/03/05/words-of-life.html</guid>
        
        <category>life</category>
        
        
        <category>life</category>
        
      </item>
    
      <item>
        <title>一份优秀BP的写作指南</title>
        <description>&lt;h1 id=&quot;一份优秀bp的写作指南&quot;&gt;一份优秀BP的写作指南&lt;/h1&gt;

&lt;p&gt;一般教人创业的文章都会从为什么创业、该不该创业等很无趣的话题开始，但在这里我们抛去那些无聊的理论，从最实操的层面入手，在具象的操作中反过来寻找该不该创业及该如何创业的答案。&lt;/p&gt;

&lt;p&gt;试想，如果你作为一个创业者，除了在家埋头想点子、出门找合伙人等，真正迈出创业实操的第一步是什么？答案是写一个商业计划书。&lt;/p&gt;

&lt;p&gt;百度百科中对于商业计划书的官方定义是：商业计划书，是公司、企业或项目单位为了达到招商融资和其它发展目标，根据一定的格式和内容要求而编辑整理的一个向受众全面展示公司和项目目前状况、未来发展潜力的书面材料。&lt;/p&gt;

&lt;p&gt;我做创投这么久，见过的商业计划书大概要奔一万份去了，其中绝大多数都是惨不忍睹。字面上来看，商业计划书的解释很简单，但要真正写好却是个技术活。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;商业计划书中，常见的主要问题&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;太花哨、不朴实。各种格式、字体，看起来就是一家不靠谱的团队做的不靠谱公司。&lt;/li&gt;
  &lt;li&gt;篇幅过长、没有重点，试想投资人看计划书就好像HR看简历一样，是不会有那么多时间在无价值信息中挑选有价值的亮点的。&lt;/li&gt;
  &lt;li&gt;有根本性的错误。比如计算的市场容量明显有误，计划书相当于留给投资人的第一印象，出现此类错误，完败在起跑线上。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;那么，一份规范的商业计划书应该长什么样？&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;其实，对于“好的商业计划书”，世界上并不存在一个标准答案。但至少你应该有一个意识，就是商业计划书不是拿来糊弄人的，敷衍了事或只做表面美化的功夫，最终害的都是自己。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;如美国红杉所说，他们希望商业计划书以最少的文字提供最多的信息，而以下的15到20页PPT就已经完全足够&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;下面就以红杉BP为例，具体讲解的十页商业计划书该如何打动投资人。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第一页：公司目标&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;用一句最简单的话来定义公司的目标。或者说用一句话说清楚你到底是要做一个什么事情，如果一句话讲不清楚这件事，要么这不是一个真正值得做的事，要么就是你还没有想清楚。&lt;/p&gt;

&lt;p&gt;&lt;em&gt;eg:比如滴滴就是做所有人的出行平台，摩拜就打了个错位说要做短距离出行平台，再比如携程就是主打旅行一站式服务等等。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第二页：现存问题&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;描述现在市场上用户的痛点，讲清楚现在这些用户是如何应对或解决这些痛点的。只要能把这一页说清，所有人就都能理解现在市场上的客观情况是怎么样的。&lt;/p&gt;

&lt;p&gt;&lt;em&gt;eg:比如我们还是以滴滴为例，在过去用户的痛点很简单，就是打不到车，用户的解决办法大多情况下也只有一个，就是在路边等待。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第三页：解决方案&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;陈述完客观问题，就要给解决方案了。在这一页中，你要通过实际的案例，来说明你是如何解决这个问题的，并且证明给大家你的公司存在的价值。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第四页：为什么是现在？&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这是一个非常重要又常常被忽视的问题，这个问题等同于另一个问题：为什么在你之前没有人做这件事？所以你必须在这页中从历史的维度来进行市场分析，讲述大趋势是如何变化的，为什么这个问题现在会出现，或为什么你的解决方案现在才管用？&lt;/p&gt;

&lt;p&gt;&lt;em&gt;eg：原因可以从以下角度分析：如科技的发展、政策的变化等。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第五页：市场大小&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;简单来分，市场大小有三类：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;总潜在市场（Total Addressable Market）&lt;/li&gt;
  &lt;li&gt;可服务市场（Service Available Market）&lt;/li&gt;
  &lt;li&gt;可获得服务市场（Service Obtainable Market）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;计算市场大小是个学问，建议创业者综合多方考虑，分析点至少要涵盖以上三方面，这样做不仅是为了获得投资人的青睐，更是对自己负责，便于今后的业务开展，而不是持“先拿到钱再说”这样走一步看一步的态度。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第六页：市场竞争&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;知己知彼，百战不殆的道理大家都懂。世界上不存在没有竞争的市场，要么就是外部竞争，要么就是内部竞争。在这一页中，你需要列出你所知道的所有竞争者的名单，附带你的竞争分析。概括来说一句话，也就是：为什么你比别人都好。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第七页：产品&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;不管是实体产品、线上产品还是各种虚拟服务，在这页中，你需要讲清楚你的产品线和构成，解释清楚你产品的功能、特征、知识产权情况等等。此外，还要附带一个产品的发展规划，告诉大家未来产品还会如何演进。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第八页：商业模式&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;商业模型是个很虚的东西，很多人总说这个词，却不理解他的真实含义。到底什么是商业模式？一句话回答，即：君子爱财，取之有道，你的“道”是什么。在这页里，你要讲清你的产品如何定价，你的用户终身价值如何，你的销售渠道如何布局。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第九页：团队&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;终于到团队了，团队就是创始人和核心管理层，及外部顾问。我之前看过很多商业计划书，要么就是没有团队，要么就是把所有人都列上。投资人提供的是财力，创业者提供的是人力，这一部分存在的意义就是向投资人说明你的人力配得上他的财力，同时也是对内政的梳理。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第十页：财务数据&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这是商业计划书的最后一页。财务数据这一页，就是基本的流水、现金流、损益表等等，再加上核心的运营数据。&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;可能以上有的部分会需要用2到3页展现，但最终会在15 – 20页之间。商业计划书作为递交给投资人的公司简历，至少从页数上来讲没有那么复杂。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;插播一个小概念：Elevator&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pitch，中文一般翻译为电梯法则、或电梯游说，这个词来源于麦肯锡公司的一个实际案例。当年，麦肯锡一个咨询师在电梯中遇到了客户所在公司的董事长，董事长要求其更新下目前项目的进展，但很遗憾，这个咨询师没有能够在电梯上下的短短30秒内说清楚结果，最终麦肯锡就失去了这个客户。&lt;/p&gt;

&lt;p&gt;所以当你准备完商业计划书以后，不妨用电梯法则来考验一下自己，看看自己是否能在最短的时间内把问题的重点表达清楚，并且吸引到对方呢？&lt;/p&gt;
</description>
        <pubDate>Wed, 22 Feb 2017 06:08:09 +0000</pubDate>
        <link>https://shunliz.github.io/business/2017/02/22/how-to-write-bp.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/business/2017/02/22/how-to-write-bp.html</guid>
        
        <category>business</category>
        
        
        <category>business</category>
        
      </item>
    
      <item>
        <title>10年老员工谈Google的软件工程实践（三）</title>
        <description>&lt;h1 id=&quot;4-people-management&quot;&gt;4. People management&lt;/h1&gt;

&lt;h2 id=&quot;41-roles&quot;&gt;4.1. Roles&lt;/h2&gt;

&lt;p&gt;As we’ll explain in more detail below, Google separates the engineering and management career progression ladders, separates the tech lead role from management, embeds research within engineering, and supports engineers with product managers, project managers, and site reliability engineers (SREs). It seems likely that at least some of these practices are important to sustaining the culture of innovation that has developed at Google.&lt;/p&gt;

&lt;p&gt;Google has a small number of different roles within engineering. Within each role, there is a career progression possible, with a sequence of levels, and the possibility of promotion (with associated improvement to compensation, e.g. salary) to recognize performance at the next level.&lt;/p&gt;

&lt;p&gt;The main roles are these:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Engineering Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the only people management role in this list. Individuals in other roles such as Software Engineer may manage people, but Engineering Managers always manage people. Engineering Managers are often former Software Engineers, and invariably have considerable technical expertise, as well as people skills.&lt;/p&gt;

&lt;p&gt;There is a distinction between technical leadership and people management.
Engineering Managers do not necessarily lead projects; projects are led by a Tech Lead, who can be an Engineering Manager, but who is more often a Software Engineer. A project’s Tech Lead has the final say for technical decisions in that project.&lt;/p&gt;

&lt;p&gt;Managers are responsible for selecting Tech Leads, and for the performance of their teams. They perform coaching and assisting with career development, do performance evaluation (using input from peer feedback, see below), and are responsible for some aspects of compensation. They are also responsible for some parts of the hiring process.&lt;/p&gt;

&lt;p&gt;Engineering Managers normally directly manage anywhere between 3 and 30 people, although 8 to 12 is most common.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Software Engineer (SWE)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most people doing software development work have this role. The hiring bar for software engineers at Google is very high; by hiring only exceptionally good software engineers, a lot of the software problems that plague other organizations are avoided or minimized.&lt;/p&gt;

&lt;p&gt;Google has separate career progression sequences for engineering and management. Although it is possible for a Software Engineer to manage people, or to transfer to the Engineering Manager role, managing people is not a requirement for promotion, even at the highest levels. At the higher levels, showing leadership is required, but that can come in many forms. For example creating great software that has a huge impact or is used by very many other engineers is sufficient. This is important, because it means that people who have great technical skills but lack the desire or skills to manage people still have a good career progression path that does not require them to take a management track. This avoids the problem that some organizations suffer where people end up in management positions for reasons of career advancement but neglect the people management of the people in their team.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Research Scientist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hiring criteria for this role are very strict, and the bar is extremely high, requiring demonstrated exceptional research ability evidenced by a great publication record &lt;em&gt;and&lt;/em&gt; ability to write code. Many very talented people in academia who would be able to qualify for a Software Engineer role would not qualify for a Research Scientist role at Google; most of the people with PhDs at Google are Software Engineers rather than Research Scientists. Research scientists are evaluated on their research contributions, including their publications, but apart from that and the different title, there is not really that much difference between the Software Engineer and Research Scientist role at Google. Both can do original research and publish papers, both can develop new product ideas and new technologies, and both can and do write code and develop products. Research Scientists at Google usually work alongside Software Engineers, in the same teams and working on the same products or the same research. This practice of embedding research within engineering contributes greatly to the ease with which new research can be incorporated into shipping products.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Site Reliability Engineer (SRE)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The maintenance of operational systems is done by software engineering teams, rather than traditional sysadmin types, but the hiring requirements for software engineering skills for the SRE are slightly lower than the requirements for the Software Engineering position. The nature and purpose of the SRE role is explained very well and in detail in the SRE book [7], so we won’t discuss it further here.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Product Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Product Managers are responsible for the management of a product; as advocates for the product users, they coordinate the work of software engineers, evangelizing features of importance to those users, coordinating with other teams, tracking bugs and schedules, and ensuring that everything needed is in place to produce a high quality product. Product Managers usually do NOT write code themselves, but work with software engineers to ensure that the right code gets written.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Program Manager / Technical Program Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Program Managers have a role that is broadly similar to Product Manager, but rather than managing a product, they manage projects, processes, or operations (e.g. data collection). Technical Program Managers are similar, but also require specific technical expertise relating to their work, e.g. linguistics for dealing with speech data.&lt;/p&gt;

&lt;p&gt;The ratio of Software Engineers to Product Managers and Program Managers varies across the organization, but is generally high, e.g. in the range 4:1 to 30:1.&lt;/p&gt;

&lt;h2 id=&quot;42-facilities&quot;&gt;4.2. Facilities&lt;/h2&gt;

&lt;p&gt;Google is famous for it’s fun facilities, with features like slides, ball pits, and games rooms.&lt;/p&gt;

&lt;p&gt;That helps attract and retain good talent. Google’s excellent cafes, which are free to employees, provide that function too, and also subtly encourage Googlers to stay in the office; hunger is never a reason to leave. The frequent placement of “microkitchens” where employees can grab snacks and drinks serves the same function too, but also acts as an important source of informal idea exchange, as many conversations start up there. Gyms, sports, and on-site massage help keep employees fit, healthy, and happy, which improves productivity and retention.&lt;/p&gt;

&lt;p&gt;The seating at Google is open-plan, and often fairly dense. While controversial [20], this encourages communication, sometimes at the expense of individual concentration, and is economical.&lt;/p&gt;

&lt;p&gt;Employees are assigned an individual seat, but seats are re-assigned fairly frequently (e.g. every 6-12 months, often as a consequence of the organization expanding), with seating chosen by managers to facilitate and encourage communication, which is always easier between adjacent or nearly adjacent individuals.&lt;/p&gt;

&lt;p&gt;Google’s facilities all have meeting rooms fitted with state-of-the-art video conference facilities, where connecting to the other party for a prescheduled calendar invite is just a single tap on the screen.&lt;/p&gt;

&lt;h2 id=&quot;43-training&quot;&gt;4.3. Training&lt;/h2&gt;

&lt;p&gt;Google encourages employee education in many ways:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;New Googlers (“Nooglers”) have a mandatory initial training course.&lt;/li&gt;
  &lt;li&gt;Technical staff (SWEs and research scientists) start by doing “Codelabs”: short online
training courses in individual technologies, with coding exercises.&lt;/li&gt;
  &lt;li&gt;Google offers employees a variety of online and in-person training courses.&lt;/li&gt;
  &lt;li&gt;Google also offers support for studying at external institutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, each Noogler is usually appointed an official “Mentor” and a separate “Buddy” to help get them up to speed. Unofficial mentoring also occurs via regular meetings with their manager, team meetings, code reviews, design reviews, and informal processes.&lt;/p&gt;

&lt;h2 id=&quot;44-transfers&quot;&gt;4.4 Transfers&lt;/h2&gt;

&lt;p&gt;Transfers between different parts of the company are encouraged, to help spread knowledge and technology across the organization and improve cross-organization communication. Transfers between projects and/or offices are allowed for employees in good standing after 12 months in a position. Software engineers are also encouraged to do temporary assignments in other parts of the organization, e.g. a six-month “rotation” (temporary assignment) in SRE (Site Reliability Engineering).&lt;/p&gt;

&lt;h2 id=&quot;45-performance-appraisal-and-rewards&quot;&gt;4.5. Performance appraisal and rewards&lt;/h2&gt;

&lt;p&gt;Feedback is strongly encouraged at Google. Engineers can give each other explicit positive feedback via “peer bonuses” and “kudos”. Any employee can nominate any other employee for a “peer bonus” – a cash bonus of $100 – up to twice per year, for going beyond the normal call of duty, just by filling in a web form to describe the reason. Team-mates are also typically notified when a peer bonus is awarded. Employees can also give “kudos”, formalized statements of praise which provide explicit social recognition for good work, but with no financial reward; for “kudos” there is no requirement that the work be beyond the normal call of duty, and no limit on the number of times that they can be bestowed.&lt;/p&gt;

&lt;p&gt;Managers can also award bonuses, including spot bonuses, e.g. for project completion. And as with many companies, Google employees get annual performance bonuses and equity awards based on their performance.&lt;/p&gt;

&lt;p&gt;Google has a very careful and detailed promotion process, which involves nomination by self or manager, self-review, peer reviews, manager appraisals; the actual decisions are then made by promotion committees based on that input, and the results can be subject to further review by promotion appeals committees. Ensuring that the right people get promoted is critical to maintaining the right incentives for employees.&lt;/p&gt;

&lt;p&gt;Poor performance, on the other hand, is handled with manager feedback, and if necessary with performance improvement plans, which involve setting very explicit concrete performance targets and assessing progress towards those targets. If that fails, termination for poor performance is possible, but in practice this is extremely rare at Google.&lt;/p&gt;

&lt;p&gt;Manager performance is assessed with feedback surveys; every employee is asked to fill in an survey about the performance of their manager twice a year, and the results are anonymized and aggregated and then made available to managers. This kind of upward feedback is very important for maintaining and improving the quality of management throughout the organization.&lt;/p&gt;

&lt;h1 id=&quot;5-conclusions&quot;&gt;5. Conclusions&lt;/h1&gt;

&lt;p&gt;We have briefly described most of the key software engineering practices used at Google. Of course Google is now a large and diverse organization, and some parts of the organization have different practices. But the practices described here are generally followed by most teams at Google.&lt;/p&gt;

&lt;p&gt;With so many different software engineering practices involved, and with so many other reasons for Google’s success that are not related to our software engineering practices, it is extremely difficult to give any quantitative or objective evidence connecting individual practices with improved outcomes. However, these practices are the ones that have stood the test of time at Google, where they have been subject to the collective subjective judgement of many thousands of excellent software engineers.&lt;/p&gt;

&lt;p&gt;For those in other organizations who are advocating for the use of a particular practice that happens to be described in this paper, perhaps it will help to say “it’s good enough for Google”.&lt;/p&gt;

&lt;h1 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h1&gt;

&lt;p&gt;Special thanks to Alan Donovan for his extremely detailed and constructive feedback, and thanks also to Yaroslav Volovich, Urs Ho?lzle, Brian Strope, Alexander Gutkin, Alex Gruenstein and Hameed Husaini for their very helpful comments on earlier drafts of this paper.&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;p&gt;[1] Build in the Cloud: Accessing Source Code, Nathan York, http://google-engtools.blogspot.com/2011/06/build-in-cloud-accessing-source-code.html&lt;/p&gt;

&lt;p&gt;[2] Build in the Cloud: How the Build System works, Christian Kemper, http://google-engtools.blogspot.com/2011/08/build-in-cloud-how-build-system-works.htm&lt;/p&gt;

&lt;p&gt;[3] Build in the Cloud: Distributing Build Steps, Nathan York http://google-engtools.blogspot.com/2011/09/build-in-cloud-distributing-build-steps.html&lt;/p&gt;

&lt;p&gt;[4] Build in the Cloud: Distributing Build Outputs, Milos Besta, Yevgeniy Miretskiy and Jeff Cox http://google-engtools.blogspot.com/2011/10/build-in-cloud-distributing-build.html&lt;/p&gt;

&lt;p&gt;[5] Testing at the speed and scale of Google, Pooja Gupta, Mark Ivey, and John Penix, Google engineering tools blog, June 2011.
http://google-engtools.blogspot.com/2011/ 06/testing-at-speed-and-scale-of-google.html&lt;/p&gt;

&lt;p&gt;[6] Building Software at Google Scale Tech Talk, Michael Barnathan, Greg Estren, Pepper Lebeck-Jone, Google tech talk, http://www.youtube.com/watch?v=2qv3fcXW1mg&lt;/p&gt;

&lt;p&gt;[7] Site Reliability Engineering, Betsy Beyer, Chris Jones, Jennifer Petoff, Niall Richard Murphy, O’Reilly Media, April 2016, ISBN 978-1-4919-2909-4.
https://landing.google.com/sre/book.html&lt;/p&gt;

&lt;p&gt;[8] How Google Works, Eric Schmidt, Jonathan Rosenberg. http://www.howgoogleworks.net&lt;/p&gt;

&lt;p&gt;[9] What would Google Do?: Reverse-Engineering the Fastest Growing Company in the History of the World, Jeff Jarvis, Harper Business, 2011. https://books.google.co.uk/books/about/What_Would_Google_Do.html?id=GvkEcAAACAAJ&amp;amp;re dir_esc=y&lt;/p&gt;

&lt;p&gt;[10] The Search: How Google and Its Rivals Rewrote the Rules of Business and Transformed Our Culture, John Battelle, 8 September 2005. https://books.google.co.uk/books/about/The_Search.html?id=4MY8PgAACAAJ&amp;amp;redir_esc=y 
[11] The Google Story, David A. Vise, Pan Books, 2008. http://www.thegooglestory.com/&lt;/p&gt;

&lt;p&gt;[12] Searching for Build Debt: Experiences Managing Technical Debt at Google, J. David Morgenthaler, Misha Gridnev, Raluca Sauciuc, and Sanjay Bhansali. http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37755.pdf&lt;/p&gt;

&lt;p&gt;[13] Development at the speed and scale of Google, A. Kumar, December 2010, presentation, QCon. http: //www.infoq.com/presentations/Development-at-Google&lt;/p&gt;

&lt;p&gt;[14] How Google Tests Software, J. A. Whittaker, J. Arbon, and J. Carollo, Addison-Wesley, 2012.&lt;/p&gt;

&lt;p&gt;[15] Release Engineering Practices and Pitfalls, H. K. Wright and D. E. Perry, in Proceedings of the 34th International Conference on Software Engineering (ICSE ’12), IEEE, 2012, pp. 1281–1284. http://www.hyrumwright.org/papers/icse2012.pdf&lt;/p&gt;

&lt;p&gt;[16] Large-Scale Automated Refactoring Using ClangMR, H. K. Wright, D. Jasper, M. Klimek, C. Carruth, Z. Wan, in Proceedings of the 29th International Conference on Software Maintenance (ICSM ’13), IEEE, 2013, pp. 548–551.&lt;/p&gt;

&lt;p&gt;[17] Why Google Stores Billions of Lines of Code in a Single Repository, Rachel Potvin, presentation. https://www.youtube.com/watch?v=W71BTkUbdqE&lt;/p&gt;

&lt;p&gt;[18] The Motivation for a Monolithic Codebase, Rachel Potvin, Josh Levenberg, to be published in Communications of the ACM, July 2016.&lt;/p&gt;

&lt;p&gt;[19] Scaling Mercurial at Facebook, Durham Goode, Siddharth P. Agarwa, Facebook blog post, January 7th, 2014. https://code.facebook.com/posts/218678814984400/scaling-mercurial-at-facebook/&lt;/p&gt;

&lt;p&gt;[20] Why We (Still) Believe In Private Offices, David Fullerton, Stack Overflow blog post, January 16th, 2015. https://blog.stackoverflow.com/2015/01/why-we-still-believe-in-private-offices/&lt;/p&gt;

&lt;p&gt;[21] Continuous Integration at Google Scale, John Micco, presentation, EclipseCon, 2013. http://eclipsecon.org/2013/sites/eclipsecon.org.2013/files/2013-03-24%20Continuous%20Integr ation%20at%20Google%20Scale.pdf&lt;/p&gt;
</description>
        <pubDate>Tue, 14 Feb 2017 00:03:09 +0000</pubDate>
        <link>https://shunliz.github.io/software-engineering/2017/02/14/ten-year-old-googler-3.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/software-engineering/2017/02/14/ten-year-old-googler-3.html</guid>
        
        <category>software-engineering</category>
        
        
        <category>software-engineering</category>
        
      </item>
    
      <item>
        <title>10年老员工谈Google的软件工程实践（二）</title>
        <description>&lt;h2 id=&quot;24-testing&quot;&gt;2.4. Testing&lt;/h2&gt;

&lt;p&gt;Unit Testing is strongly encouraged and widely practiced at Google. All code used in production is expected to have unit tests, and the code review tool will highlight if source files are added without corresponding tests. Code reviewers usually require that any change which adds new functionality should also add new tests to cover the new functionality. Mocking frameworks &lt;strong&gt;&lt;em&gt;which allow construction of lightweight unit tests even for code with dependencies on heavyweight libraries&lt;/em&gt;&lt;/strong&gt; are quite popular.&lt;/p&gt;

&lt;p&gt;Integration testing and regression testing are also widely practiced.&lt;/p&gt;

&lt;p&gt;As discussed in “Presubmit Checks” above, testing can be automatically enforced as part of the code review and commit process.&lt;/p&gt;

&lt;p&gt;Google also has automated tools for measuring test coverage. The results are also integrated as an optional layer in the source code browser.&lt;/p&gt;

&lt;p&gt;Load testing prior to deployment is also de rigueur at Google. Teams are expected to produce a table or graph showing how key metrics, particularly latency and error rate, vary with the rate of incoming requests.&lt;/p&gt;

&lt;h2 id=&quot;25-bug-tracking&quot;&gt;2.5. Bug tracking&lt;/h2&gt;

&lt;p&gt;Google uses a bug tracking system called Buganizer for tracking issues: bugs, feature requests, customer issues, and processes &lt;strong&gt;&lt;em&gt;such as releases or clean-up efforts&lt;/em&gt;&lt;/strong&gt;. Bugs are categorized into hierarchical components and each component can have a default assignee and default email list to CC. When sending a source change for review, engineers are prompted to associate the change with a particular issue number.&lt;/p&gt;

&lt;p&gt;It is common (though not universal) for teams at Google to regularly scan through open issues in their component(s), prioritizing them and where appropriate assigning them to particular engineers. Some teams have a particular individual responsible for bug triage, others do bug triage in their regular team meetings. Many teams at Google make use of labels on bugs to indicate whether bugs have been triaged, and which release(s) each bug is targeted to be fixed in.&lt;/p&gt;

&lt;h2 id=&quot;26-programming-languages&quot;&gt;2.6. Programming languages&lt;/h2&gt;

&lt;p&gt;Software engineers at Google are strongly encouraged to program in one of four officially-approved programming languages at Google: C++, Java, Python, or Go. Minimizing the number of different programming languages used reduces obstacles to code reuse and programmer collaboration.&lt;/p&gt;

&lt;p&gt;There are also Google style guides for each language, to ensure that code all across the company is written with similar style, layout, naming conventions, etc. In addition there is a company-wide readability training process, whereby experienced engineers who care about code readability train other engineers in how to write readable, idiomatic code in a particular language, by reviewing a substantial change or series of changes until the reviewer is satisfied that the author knows how to write readable code in that language. Each change that adds non-trivial new code in a particular language must be approved by someone who has passed this “readability” training process in that language.&lt;/p&gt;

&lt;p&gt;In addition to these four languages, many specialized domain-specific languages are used for particular purposes (e.g. the build language used for specifying build targets and their dependencies).&lt;/p&gt;

&lt;p&gt;Interoperation between these different programming languages is done mainly using Protocol Buffers. Protocol Buffers is a way of encoding structured data in an efficient yet extensible way. It includes a domain-specific language for specifying structured data, together with a compiler that takes in such descriptions and generates code in C++, Java, Python, for constructing, accessing, serializing, and deserializing these objects. Google’s version of Protocol Buffers is integrated with Google’s RPC libraries, enabling simple cross-language RPCs, with serialization and deserialization of requests and responses handled automatically by the RPC framework.&lt;/p&gt;

&lt;p&gt;Commonality of process is a key to making development easy even with an enormous code base and a diversity of languages: there is a single set of commands to perform all the usual software engineering tasks (such as check out, edit, build, test, review, commit, file bug report, etc.) and the same commands can be used no matter what project or language. Developers don’t need to learn a new development process just because the code that they are editing happens to be part of a different project or written in a different language.&lt;/p&gt;

&lt;h2 id=&quot;27-debugging-and-profiling-tools&quot;&gt;2.7. Debugging and Profiling tools&lt;/h2&gt;

&lt;p&gt;Google servers are linked with libraries that provide a number of tools for debugging running servers. In case of a server crash, a signal handler will automatically dump a stack trace to a log file, as well as saving the core file. If the crash was due to running out of heap memory, the server will dump stack traces of the allocation sites of a sampled subset of the live heap objects. There are also web interfaces for debugging that allow examining incoming and outgoing RPCs (including timing, error rates, rate limiting, etc.), changing command-line flag values (e.g. to increase logging verbosity for a particular module), resource consumption, profiling, and more.&lt;/p&gt;

&lt;p&gt;These tools greatly increase the overall ease of debugging to the point where it is rare to fire up a traditional debugger such as gdb.&lt;/p&gt;

&lt;h2 id=&quot;28-release-engineering&quot;&gt;2.8. Release engineering&lt;/h2&gt;

&lt;p&gt;A few teams have dedicated release engineers, but for most teams at Google, the release engineering work is done by regular software engineers.&lt;/p&gt;

&lt;p&gt;Releases are done frequently for most software; weekly or fortnightly releases are a common goal, and some teams even release daily. This is made possible by automating most of the normal release engineering tasks. Releasing frequently helps to keep engineers motivated (it’s harder to get excited about something if it won’t be released until many months or even years into the future) and increases overall velocity by allowing more iterations, and thus more opportunities for feedback and more chances to respond to feedback, in a given time.&lt;/p&gt;

&lt;p&gt;A release typically starts in a fresh workspace, by syncing to the change number of the latest “green” build (i.e. the last change for which all the automatic tests passed), and making a release branch. The release engineer can select additional changes to be “cherry-picked”, i.e. merged from the main branch onto the release branch. Then the software will be rebuilt from scratch and the tests are run. If any tests fail, additional changes are made to fix the failures and those additional changes are cherry-picked onto the release branch, after which the software will be rebuilt and the tests rerun. When the tests all pass,the built executable(s) and data file(s) are packaged up. All of these steps are automated so that the release engineer need only run some simple commands, or even just select some entries on a menu-driven UI, and choose which changes (if any) to cherry pick.&lt;/p&gt;

&lt;p&gt;Once a candidate build has been packaged up, it is typically loaded onto a “staging” server for further integration testing by small set of users (sometimes just the development team).&lt;/p&gt;

&lt;p&gt;A useful technique involves sending a copy of (a subset of) the requests from production traffic to the staging server, but also sending those same requests to the current production servers for actual processing. The responses from the staging server are discarded, and the responses from the live production servers are sent back to the users. This helps ensure that any issues that might cause serious problems (e.g. server crashes) can be detected before putting the server into production.&lt;/p&gt;

&lt;p&gt;The next step is to usually roll out to one or more “canary” servers that are processing a subset of the live production traffic. Unlike the “staging” servers, these are processing and responding to real users.&lt;/p&gt;

&lt;p&gt;Finally the release can be rolled out to all servers in all data centers. For very high-traffic, high-reliability services, this is done with a gradual roll-out over a period of a couple of days, to help reduce the impact of any outages due to newly introduced bugs not caught by any of the previous steps.&lt;/p&gt;

&lt;p&gt;For more information on release engineering at Google, see chapter 8 of the SRE book [7]. See also [15].&lt;/p&gt;

&lt;h2 id=&quot;29-launch-approval&quot;&gt;2.9. Launch approval&lt;/h2&gt;

&lt;p&gt;The launch of any user-visible change or significant design change requires approvals from a number of people outside of the core engineering team that implements the change. In particular approvals (often subject to detailed review) are required to ensure that code complies with legal requirements, privacy requirements, security requirements, reliability requirements (e.g. having appropriate automatic monitoring to detect server outages and automatically notify the appropriate engineers), business requirements, and so forth.&lt;/p&gt;

&lt;p&gt;The launch process is also designed to ensure that appropriate people within the company are notified whenever any significant new product or feature launches.&lt;/p&gt;

&lt;p&gt;Google has an internal launch approval tool that is used to track the required reviews and approvals and ensure compliance with the defined launch processes for each product. This tool is easily customizable, so that different products or product areas can have different sets of required reviews and approvals.&lt;/p&gt;

&lt;p&gt;For more information about launch processes, see chapter 27 of the SRE book [7].&lt;/p&gt;

&lt;h2 id=&quot;210-post-mortems&quot;&gt;2.10. Post-mortems&lt;/h2&gt;

&lt;p&gt;Whenever there is a significant outage of any of our production systems, or similar mishap, the people involved are required to write a post-mortem document. This document describes the incident, including title, summary, impact, timeline, root cause(s), what worked/what didn’t, and action items. The focus is on the problems, and how to avoid them in future, not on the people or apportioning blame. The impact section tries to quantify the effect of the incident, in terms of duration of outage, number of lost queries (or failed RPCs, etc.), and revenue. The timeline section gives a timeline of the events leading up to the outage and the steps taken to diagnose and rectify it. The what worked/what didn’t section describes the lessons learnt – which practices helped to quickly detect and resolve the issue, what went wrong, and what concrete actions (preferably filed as bugs assigned to specific people) can be take to reduce the likelihood and/or severity of similar problems in future.&lt;/p&gt;

&lt;p&gt;For more information on post-mortem culture at Google, see chapter 15 of the SRE book [7].&lt;/p&gt;

&lt;h2 id=&quot;211-frequent-rewrites&quot;&gt;2.11. Frequent rewrites&lt;/h2&gt;

&lt;p&gt;Most software at Google gets rewritten every few years.&lt;/p&gt;

&lt;p&gt;This may seem incredibly costly. Indeed, it does consume a large fraction of Google’s resources. However, it also has some crucial benefits that are key to Google’s agility and long-term success. In a period of a few years, it is typical for the requirements for a product to change significantly, as the software environment and other technology around it change, and as changes in technology or in the marketplace affect user needs, desires, and expectations. Software that is a few years old was designed around an older set of requirements and is typically not designed in a way that is optimal for current requirements. Furthermore, it has typically accumulated a lot of complexity. Rewriting code cuts away all the unnecessary accumulated complexity that was addressing requirements which are no longer so important. In addition, rewriting code is a way of transferring knowledge and a sense of ownership to newer team members. This sense of ownership is crucial for productivity: engineers naturally put more effort into developing features and fixing problems in code that they feel is “theirs”. Frequent rewrites also encourage mobility of engineers between different projects which helps to encourage cross-pollination of ideas. Frequent rewrites also help to ensure that code is written using modern technology and methodology.&lt;/p&gt;

&lt;h1 id=&quot;3-project-management&quot;&gt;3. Project management&lt;/h1&gt;

&lt;h2 id=&quot;31-20-time&quot;&gt;3.1. 20% time&lt;/h2&gt;

&lt;p&gt;Engineers are permitted to spend up to 20% of their time working on any project of their choice, without needing approval from their manager or anyone else. This trust in engineers is extremely valuable, for several reasons.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Firstly, it allows anyone with a good idea, even if it is an idea that others would not immediately recognize as being worthwhile, to have sufficient time to develop a prototype, demo, or presentation to show the value of their idea.&lt;/li&gt;
  &lt;li&gt;Secondly, it provides management with visibility into activity that might otherwise be hidden. In other companies that don’t have an official policy of allowing 20% time, engineers sometimes work on “skunkwork” projects without informing management. It’s much better if engineers can be open about such projects, describing their work on such projects in their regular status updates, even in cases where their management may not agree on the value of the project. Having a company-wide official policy and a culture that supports it makes this possible.&lt;/li&gt;
  &lt;li&gt;Thirdly, by allowing engineers to spend a small portion of their time working on more fun stuff, it keeps engineers motivated and excited by what they do, and stops them getting burnt out, which can easily happen if they feel compelled to spend 100% of their time working on more tedious tasks. The difference in productivity between engaged, motivated engineers and burnt out engineers is a lot more than 20%.&lt;/li&gt;
  &lt;li&gt;Fourthly, it encourages a culture of innovation. Seeing other engineers working on fun experimental 20% projects encourages everyone to do the same.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;32-objectives-and-key-results-okrs&quot;&gt;3.2. Objectives and Key Results (OKRs)&lt;/h2&gt;

&lt;p&gt;Individuals and teams at Google are required to explicitly document their goals and to assess their progress towards these goals. Teams set quarterly and annual objectives, with measurable key results that show progress towards these objectives. This is done at every level of the company, going all the way up to defining goals for the whole company. Goals for individuals and small teams should align with the higher-level goals for the broader teams that they are part of and with the overall company goals. At the end of each quarter, progress towards the measurable key results is recorded and each objective is given a score from 0.0 (no progress) to 1.0 (100% completion). OKRs and OKR scores are normally made visible across Google (with occasional exceptions for especially sensitive information such as highly confidential projects), but they not used directly as input to an individual’s performance appraisal.&lt;/p&gt;

&lt;p&gt;OKRs should be set high: the desired target overall average score is 65%, meaning that a team is encouraged to set as goals about 50% more tasks than they are likely to actually accomplish. If a team scores significantly higher than that, they are encouraged to set more ambitious OKRs for the following quarter (and conversely if they score significantly lower than that, they are encouraged to set their OKRs more conservatively the next quarter).&lt;/p&gt;

&lt;p&gt;OKRs provide a key mechanism for communicating what each part of the company is working on, and for encouraging good performance from employees via social incentives… engineers know that their team will have a meeting where the OKRs will be scored, and have a natural drive to try to score well, even though OKRs have no direct impact on performance appraisals orcompensation.&lt;/p&gt;

&lt;p&gt;Defining key results that are objective and measurable helps ensure that this human drive to perform well is channelled to doing things that have real concrete measurable impact on progress towards shared objectives.&lt;/p&gt;

&lt;h2 id=&quot;33-project-approval&quot;&gt;3.3 Project approval&lt;/h2&gt;

&lt;p&gt;Although there is a well-defined process for launch approvals, Google does not have a well-defined process for project approval or cancellation. Despite having been at Google for nearly 10 years, and now having become a manager myself, I still don’t fully understand how such decisions are made. In part this is because the approach to this is not uniform across the company. Managers at every level are responsible and accountable for what projects their teams work on, and exercise their discretion as they see fit. In some cases, this means that such decisions are made in a quite bottom-up fashion, with engineers being given freedom to choose which projects to work on, within their team’s scope. In other cases, such decisions are made in a much more top-down fashion, with executives or managers making decisions about which projects will go ahead, which will get additional resources, and which will get cancelled.&lt;/p&gt;

&lt;h2 id=&quot;34-corporate-reorganizations&quot;&gt;3.4 Corporate reorganizations&lt;/h2&gt;

&lt;p&gt;Occasionally an executive decision is made to cancel a large project, and then the many engineers who had been working on that project may have to find new projects on new teams.&lt;/p&gt;

&lt;p&gt;Similarly there have been occasional “defragmentation” efforts, where projects that are split across multiple geographic locations are consolidated into a smaller number of locations, with engineers in some locations being required to change team and/or project in order to achieve this. In such cases, engineers are generally given freedom to choose their new team and role from within the positions available in their geographic location, or in the case of defragmentation, they may also be given the option of staying on the same team and project by moving to a different location.&lt;/p&gt;

&lt;p&gt;In addition, other kinds of corporate reorganizations, such as merging or splitting teams and changes in reporting chains, seem to be fairly frequent occurrences, although I don’t know how Google compares with other large companies on that. In a large, technology-driven organization, somewhat frequent reorganization may be necessary to avoid organizational inefficiencies as the technology and requirements change.&lt;/p&gt;
</description>
        <pubDate>Tue, 14 Feb 2017 00:02:09 +0000</pubDate>
        <link>https://shunliz.github.io/software-engineering/2017/02/14/ten-year-old-googler-2.html</link>
        <guid isPermaLink="true">https://shunliz.github.io/software-engineering/2017/02/14/ten-year-old-googler-2.html</guid>
        
        <category>software-engineering</category>
        
        
        <category>software-engineering</category>
        
      </item>
    
  </channel>
</rss>
