正如我在<自然语言处理(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. Redis实战--使用Jedis实现百万数据秒级插入

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 当我们 ...

  2. Python多线程与队列

    Python多线程与Queue队列多线程在感官上类似于同时执行多个程序,虽然由于GIL的存在,在Python中无法实现线程的真正并行,但是对于某些场景,多线程仍不失为一个有效的处理方法: 1,不紧急的 ...

  3. js中call、apply和bind到底有什么区别?

    介绍 在js中,每个函数的原型都指向Function.prototype对象(js基于原型链的继承).因此,每个函数都会有apply,call,和bind方法,这些方法继承于Function. 它们的 ...

  4. 使用 MUI 自制 弹出层

    使用 MUI 自制 弹出层 <div class="zp-mask" style="display: none; width: 100%;height: 100%; ...

  5. python主线程与子线程的结束顺序

    引用自 主线程退出对子线程的影响--YuanLi 的一段话: 对于程序来说,如果主进程在子进程还未结束时就已经退出,那么Linux内核会将子进程的父进程ID改为1(也就是init进程),当子进程结束后 ...

  6. 【Elasticsearch 7 探索之路】(四)Analyzer 分析

    上一篇,什么是倒排索引以及原理是什么.本篇讲解 Analyzer,了解 Analyzer 是什么 ,分词器是什么,以及 Elasticsearch 内置的分词器,最后再讲解中文分词是怎么做的. 一.A ...

  7. Python和BeautifulSoup进行网页爬取

    在大数据.人工智能时代,我们通常需要从网站中收集我们所需的数据,网络信息的爬取技术已经成为多个行业所需的技能之一.而Python则是目前数据科学项目中最常用的编程语言之一.使用Python与Beaut ...

  8. tensorflow:模型的保存和训练过程可视化

    在使用tf来训练模型的时候,难免会出现中断的情况.这时候自然就希望能够将辛辛苦苦得到的中间参数保留下来,不然下次又要重新开始. 保存模型的方法: #之前是各种构建模型graph的操作(矩阵相乘,sig ...

  9. iptables简单命令

    IPTables是基于Netfilter基本架构实现的一个可扩展的数据报高级管理系统或核外配置工具,利用table.chain.rule三级来存储数据报的各种规则.Netfilter-iptables ...

  10. ##* %%* linux变量处理

    链接来自他们分享,,,, 如有侵权,请联系本人删除,本人将立即删除.停止分享. https://blog.csdn.net/fengzijinliang/article/details/4252021 ...