正如我在<自然语言处理(NLP) - 数学基础(1) - 总述>一文中所提到的NLP所关联的概率论(Probability Theory)知识点是如此的多, 饭只能一口一口地吃了, 我们先开始最为大家熟知和最基础的知识点吧, 排列组合.

虽然排列组合这个知识点大家是相当地熟知, 也是相当地基础, 但是却是十分十分十分地重要.

NLP届掌门人斯坦福大学的Daniel Jurafsky(D. 朱夫斯凯)和科罗拉多大学James H. Martin(J. H. 马丁)在其NLP巨作《自然语言处理综论》一书第二版第5页中提到:“几乎所有的语音处理和语言处理问题都可以这样来表述: 对于某个歧义的输入给出N个可能性, 选择其中概率最高的一个.”

现在让我们来看看排列组合概念的定义吧: 所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序。所谓组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。

See, 与掌门人上面这句话相比, 是如此的相似!

排列组合有两条基本原理组成:

  1. 加法原理(分类计数法)- 做一件事,完成它可以有n类办法,在第一类办法中有m1种不同的方法,在第二类办法中有m2种不同的方法,……,在第n类办法中有mn种不同的方法,那么完成这件事共有N=m1+m2+m3+…+mn种不同方法。每一种方法都能够直接达成目标。
  2. 乘法原理(分步计数法). 做一件事,完成它需要分成n个步骤,做第一步有m1种不同的方法,做第二步有m2种不同的方法,……,做第n步有mn种不同的方法,那么完成这件事共有N=m1×m2×m3×…×mn种不同的方法。

如何区分这两个原理呢?

要做一件事,完成它若是有n类办法,是分类问题,第一类中的方法都是独立的,则使用加法原理;做一件事,需要分n个步骤,步与步之间是连续的,只有将分成的若干个互相联系的步骤,依次相继完成,这件事才算完成,则使用乘法原理。

完成一件事的分“类”和“步”是有本质区别的,因此也就将两个原理区分开来了。

根据以上原理衍生出很多方法, 包括且不限于:

  1. 捆绑法. 指在解决对于某几个元素要求相邻问题时,先整体考虑,将相邻元素视作一个整体参与排序,然后再单独考虑这个整体内部各元素间顺序。注意:其首要特点是相邻,其次捆绑法一般都应用在不同物体的排序问题中。
  2. 插空法. 某些元素不相邻的排列组合问题,即不邻问题,可采用插空法,即在解决对于某几个元素要求不相邻的问题时,先将其它元素排好,再将指定的不相邻的元素插入已排好元素的间隙或两端位置,从而将问题解决的策略。用这种方法解题思路清晰、简便易懂。
  3. 插板法. 指在解决若干相同元素分组,要求每组至少有一个元素,采用将比所需分组数目少1的板插入元素之间形成分组的解题策略。

因为本节是第一节, 所以在做习题和代码示例之前, 我们需要去安装Python 3和对应的开发工具Visual Studio Code, 同时建议先照着Getting Started with Python in VS Code过一遍. (预计耗时要1-3个小时,包括update Xcode, 要注意安排好时间).

如果是时间赶, 可以使用python online editor去做. https://www.tutorialspoint.com/python/index.htm

从学术和参加算法比赛的角度来讲, 我们应该尽量不要用任何库. 然而现在我是从工程的角度出发, 所以我会使用到大名鼎鼎的NLP工具包NLTK以及Python里的数学库Scipy 和 itertools (虽然本节不会用全三个库, 但是以后的章节会全用到的)

这点和前文所讲的"AI并不只是调现有云和库API即可"并不冲突, 因为:

  1. 现有云和库API是由各自的厂商和开发者写的, 会有各种差异. 而数学库却是不会有差异的, 用A厂商写出的库去算1+2会等于3, 换了B厂商写出的库去算1+2一样会等于3.
  2. 从下面的习题答案和对应的代码示例看到, 正确的解题思路才是关键, 解题思路对了接下来的求解就可以扔给Python对应的方法了. 然而解题思路却是要穿透现有云和AI库API的.

在开始写代码做习题之前我们先按照如下链接去热身和确认环境是好的:

Python搭建虚拟环境以避免包污染

https://blog.csdn.net/qq_41185868/article/details/79682406 安装Python的Scipy包

如果遇到ssl证书问题则参考这篇文章去解决https://www.cnblogs.com/jiyanjiao-702521/p/9960071.html

如果还是遇到错误, 那就去按照https://www.jianshu.com/p/dbf20c6792fe 这篇文章一劳永逸的解决问题, 不过需要下载Anaconda, 大概要五六百M, 记得是要用bash安装. 安装完之后就可以sudo conda install scipy了, 然后再用Anaconda navigator去lanunch VS Code.

https://www.geeksforgeeks.org/permutation-and-combination-in-python/

https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.perm.html

https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.comb.html

https://www.nltk.org/api/nltk.html#nltk.probability.ConditionalFreqDist 里的nltk.util.choose(n, k) (本节不会用到, 以后章节会)

然后开始做题

捆绑法

题目: 六个各不相同的元素进行排列, 其中指定的两个元素必须要排在一起, 总共有多少种排法?

答案: 这指定的两个元素需要捆绑成一个元素进行排列, 然后这捆绑在一起的元素内部在进行排列. 最后使用分步计数法(即乘法原理)进行相乘. 所以应该是n5.5  X  n2.2 = 240种

代码实现:

from scipy.special import perm
result = perm(5, 5, exact=True) * perm(2,2, exact=True)
print(result)

插空法

题目: 对6个各不相同的A类元素和4个各不相同的B类元素进行排列, 任意两个B类元素不得相邻, 总共有多少种排法?

答案: 因为B元素不得相邻, 则需要使用插空法, 先排6个A元素A6,6 , 在6+1个空位置中再对4个B元素进行排列 a 4 7, 最后使用分步计数法(即乘法原理)进行相乘得出为604800种

代码实现

from scipy.special import perm
result = perm(6, 6, exact=True) * perm(7,4, exact=True)
print(result)

插板法

题目:将8个完全相同的元素分成3组, 每组至少要有一个元素, 总共有多少排法?

答案: 首先因为元素是完全相同的, 所以不需要排列, 因此这是个组合问题. 然后使用插板法, 将n个相同元素分成m组, 且每组必须有元素就相当于在n-1个空中插m-1个板, C2,7 共21种 (不是42种是因为是求解组合而不是排列)

代码实现

from scipy.special import comb
result = comb(7, 2, exact=True)
print(result)

如果时间紧急没有办法装Python环境这怎么办?

So easy, 使用https://www.calculator.net/permutation-and-combination-calculator.html 进行在线求解就行了,.

或者使用手机或者iPad下载microsoft math resolver去求解即可.

以上两个事实再次证明了, 正确的解题思路才是关键, 只要解题思路正确了, 后面的求解过程是很方便很easy的. 这点不就是我在<2019年总结>一文中所说到的”做正确的事情, 然后正确的做事, 比勤劳更重要”的体现吗?

不过再次提醒学术和要面试的同学们, 不要学我把求解过程扔给计算机, 这样会让你面试挂的. 我是从纯工程角度出发的.

如何得出解题思路关键点总结:

  1. 元素是否相同, 如果元素完全相同则可以直接上组合不用考虑排列.
  2. 元素类别是否相同
  3. 元素是否容许相邻

有用链接:

https://betterexplained.com/articles/easy-permutations-and-combinations/

https://www.csharp-console-examples.com/loop/foreach-statement/permutation-and-combination-calculator-in-c/ 这是一个C#的排列组合的简单示例,

https://www.beatthegmat.com/mba/2009/10/12/permutations-and-combinations-an-easy-method

https://study.com/academy/lesson/permutation-combination-problems-practice.html

https://www.mathplanet.com/education/pre-algebra/probability-and-statistic/combinations-and-permutations

https://www.wikihow.com/Calculate-Combinations

https://www.mathsisfun.com/combinatorics/combinations-permutations.html

为了方便搜索资料, 现在列出本节所用到的英文术语名词:

概率论 - Probability Theory

排列组合 - permutation and combination

加法原理(分类计数法)- Addition rule 或者Addition theorem 或者Addition Principle

乘法原理(分步计数法)- Multiplication rule 或者Multiplication theorem或者Multiplication Principle

捆绑法 - bonding method (百度百科上的翻译是错的, 这才是对的)

插空法 - Interpolation method

插板法 - plate insertion method (目前尚存疑)

感悟:

真的是长江后浪推前浪啊, 现在的本科生直接就用英语原版的数学教材, 一旦毕业再工作个三五年就能秒杀很多十几年经验的人. 中国很多程序员35岁失业其中两个原因就是第一大学教材越到后面越先进, 后来甚至用上了英语原版的教材. 第二就是当年读书的英语教学水平远差于现在的英语教学水平, 从而导致三到五年工作经验的程序员无论是理论基础还是英语水平都超越了十几年工作经验的程序员.

不过没关系啦, 虽然落后了, 努力再追上不就行了吗

自然语言处理(NLP) - 数学基础(1) - 排列组合的更多相关文章

  1. 自然语言处理(NLP) - 数学基础(1) - 总述

    正如我在<2019年总结>里说提到的, 我将开始一系列自然语言处理(NLP)的笔记. 很多人都说, AI并不难啊, 调现有库和云的API就可以啦. 然而实际上并不是这样的. 首先, AI这 ...

  2. 自然语言处理(NLP) - 数学基础(3) - 概率论基本概念与随机事件

    好像所有讲概率论的文章\视频都离不开抛骰子或抛硬币这两个例子, 因为抛骰子的确是概率论产生的基础, 赌徒们为了赢钱就不在乎上帝了才导致概率论能突破宗教的绞杀, 所以我们这里也以抛骰子和抛硬币这两个例子 ...

  3. 自然语言处理(NLP)之个人小结

    一 概述 1.1 自然语言处理四大任务 序列标注 分词 词性标注 命名实体识别 分类任务 文本分类 情感分析 判断句子关系 问答系统 对话系统 阅读理解 生成任务 机器翻译 自动文摘 图像描述生成 1 ...

  4. 学习sql中的排列组合,在园子里搜着看于是。。。

    学习sql中的排列组合,在园子里搜着看,看到篇文章,于是自己(新手)用了最最原始的sql去写出来: --需求----B, C, F, M and S住在一座房子的不同楼层.--B 不住顶层.C 不住底 ...

  5. .NET平台开源项目速览(11)KwCombinatorics排列组合使用案例(1)

    今年上半年,我在KwCombinatorics系列文章中,重点介绍了KwCombinatorics组件的使用情况,其实这个组件我5年前就开始用了,非常方便,麻雀虽小五脏俱全.所以一直非常喜欢,才写了几 ...

  6. 【原创】开源.NET排列组合组件KwCombinatorics使用(三)——笛卡尔积组合

           本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...

  7. 【原创】开源.NET排列组合组件KwCombinatorics使用(二)——排列生成

           本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...

  8. 【原创】开源.NET排列组合组件KwCombinatorics使用(一)—组合生成

           本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...

  9. hdu1521 排列组合(指数型母函数)

    题意: 有n种物品,并且知道每种物品的数量ki.要求从中选出m件物品的排数.         (全题文末) 知识点: 普通母函数 指数型母函数:(用来求解多重集的排列问题) n个元素,其中a1,a2, ...

随机推荐

  1. Webpack 4 Tree Shaking 终极优化指南

    几个月前,我的任务是将我们组的 Vue.js 项目构建配置升级到 Webpack 4.我们的主要目标之一是利用 tree-shaking 的优势,即 Webpack 去掉了实际上并没有使用的代码来减少 ...

  2. ASP.NET Core 1.0: 指定Static File中的文件作为default page

    指定一个网站的default page是很容易的事情.譬如IIS Management中,可以通过default page来指定,而默认的index.html, index.htm之类,则早已经被设置 ...

  3. 宋宝华:Linux设备驱动框架里的设计模式之——模板方法(Template Method)

    本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 宋宝华 来源: 微信公众号linux阅码场(id: linuxdev) 前言 <设计模式>这本经典 ...

  4. iOS核心动画高级技巧-2

    3. 图层几何学 图层几何学 不熟悉几何学的人就不要来这里了 --柏拉图学院入口的签名 在第二章里面,我们介绍了图层背后的图片,和一些控制图层坐标和旋转的属性.在这一章中,我们将要看一看图层内部是如何 ...

  5. 领扣(LeetCode)数字转换为十六进制数 个人题解

    给定一个整数,编写一个算法将这个数转换为十六进制数.对于负整数,我们通常使用 补码运算 方法. 注意: 十六进制中所有字母(a-f)都必须是小写. 十六进制字符串中不能包含多余的前导零.如果要转化的数 ...

  6. 深入ObjC GCD中的dispatch group工作原理。

    本文是基于GCD的支持库libdispatch的源代码分析的结果或是用于作为源代码阅读的参考,尽量不帖代码,力求用UML图来说明工作流. 本文参考的源代码版本为v501.20.1,如有兴趣请自行到苹果 ...

  7. pod删除主要流程源码解析

    本文以v1.12版本进行分析 当一个pod删除时,client端向apiserver发送请求,apiserver将pod的deletionTimestamp打上时间.kubelet watch到该事件 ...

  8. PostGIS 使用Mysql_fdw同步ArcGIS填坑记录

    ##实现Mysql_fdw数据同步过程中,出现过很多坑,开此贴记录一下 1.触发器记录 这里insert的时候,采用过insert into f_pressureline select new.*,出 ...

  9. Spring与Shiro整合

    Spring整合篇--Shiro 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 什么是Shiro? 链接:https://www.cnblogs.com/StanleyBlogs/ ...

  10. scikit-learn_cookbook1: 高性能机器学习-NumPy

    源码下载 在本章主要内容: NumPy基础知识 加载iris数据集 查看iris数据集 用pandas查看iris数据集 用NumPy和matplotlib绘图 最小机器学习配方 - SVM分类 介绍 ...