自然语言处理(NLP) - 数学基础(1) - 排列组合
正如我在<自然语言处理(NLP) - 数学基础(1) - 总述>一文中所提到的NLP所关联的概率论(Probability Theory)知识点是如此的多, 饭只能一口一口地吃了, 我们先开始最为大家熟知和最基础的知识点吧, 排列组合.
虽然排列组合这个知识点大家是相当地熟知, 也是相当地基础, 但是却是十分十分十分地重要.
NLP届掌门人斯坦福大学的Daniel Jurafsky(D. 朱夫斯凯)和科罗拉多大学James H. Martin(J. H. 马丁)在其NLP巨作《自然语言处理综论》一书第二版第5页中提到:“几乎所有的语音处理和语言处理问题都可以这样来表述: 对于某个歧义的输入给出N个可能性, 选择其中概率最高的一个.”
现在让我们来看看排列组合概念的定义吧: 所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序。所谓组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。
See, 与掌门人上面这句话相比, 是如此的相似!
排列组合有两条基本原理组成:
- 加法原理(分类计数法)- 做一件事,完成它可以有n类办法,在第一类办法中有m1种不同的方法,在第二类办法中有m2种不同的方法,……,在第n类办法中有mn种不同的方法,那么完成这件事共有N=m1+m2+m3+…+mn种不同方法。每一种方法都能够直接达成目标。
- 乘法原理(分步计数法). 做一件事,完成它需要分成n个步骤,做第一步有m1种不同的方法,做第二步有m2种不同的方法,……,做第n步有mn种不同的方法,那么完成这件事共有N=m1×m2×m3×…×mn种不同的方法。
如何区分这两个原理呢?
要做一件事,完成它若是有n类办法,是分类问题,第一类中的方法都是独立的,则使用加法原理;做一件事,需要分n个步骤,步与步之间是连续的,只有将分成的若干个互相联系的步骤,依次相继完成,这件事才算完成,则使用乘法原理。
完成一件事的分“类”和“步”是有本质区别的,因此也就将两个原理区分开来了。
根据以上原理衍生出很多方法, 包括且不限于:
- 捆绑法. 指在解决对于某几个元素要求相邻问题时,先整体考虑,将相邻元素视作一个整体参与排序,然后再单独考虑这个整体内部各元素间顺序。注意:其首要特点是相邻,其次捆绑法一般都应用在不同物体的排序问题中。
- 插空法. 某些元素不相邻的排列组合问题,即不邻问题,可采用插空法,即在解决对于某几个元素要求不相邻的问题时,先将其它元素排好,再将指定的不相邻的元素插入已排好元素的间隙或两端位置,从而将问题解决的策略。用这种方法解题思路清晰、简便易懂。
- 插板法. 指在解决若干相同元素分组,要求每组至少有一个元素,采用将比所需分组数目少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即可"并不冲突, 因为:
- 现有云和库API是由各自的厂商和开发者写的, 会有各种差异. 而数学库却是不会有差异的, 用A厂商写出的库去算1+2会等于3, 换了B厂商写出的库去算1+2一样会等于3.
- 从下面的习题答案和对应的代码示例看到, 正确的解题思路才是关键, 解题思路对了接下来的求解就可以扔给Python对应的方法了. 然而解题思路却是要穿透现有云和AI库API的.
在开始写代码做习题之前我们先按照如下链接去热身和确认环境是好的:
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年总结>一文中所说到的”做正确的事情, 然后正确的做事, 比勤劳更重要”的体现吗?
不过再次提醒学术和要面试的同学们, 不要学我把求解过程扔给计算机, 这样会让你面试挂的. 我是从纯工程角度出发的.
如何得出解题思路关键点总结:
- 元素是否相同, 如果元素完全相同则可以直接上组合不用考虑排列.
- 元素类别是否相同
- 元素是否容许相邻
有用链接:
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.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) - 排列组合的更多相关文章
- 自然语言处理(NLP) - 数学基础(1) - 总述
正如我在<2019年总结>里说提到的, 我将开始一系列自然语言处理(NLP)的笔记. 很多人都说, AI并不难啊, 调现有库和云的API就可以啦. 然而实际上并不是这样的. 首先, AI这 ...
- 自然语言处理(NLP) - 数学基础(3) - 概率论基本概念与随机事件
好像所有讲概率论的文章\视频都离不开抛骰子或抛硬币这两个例子, 因为抛骰子的确是概率论产生的基础, 赌徒们为了赢钱就不在乎上帝了才导致概率论能突破宗教的绞杀, 所以我们这里也以抛骰子和抛硬币这两个例子 ...
- 自然语言处理(NLP)之个人小结
一 概述 1.1 自然语言处理四大任务 序列标注 分词 词性标注 命名实体识别 分类任务 文本分类 情感分析 判断句子关系 问答系统 对话系统 阅读理解 生成任务 机器翻译 自动文摘 图像描述生成 1 ...
- 学习sql中的排列组合,在园子里搜着看于是。。。
学习sql中的排列组合,在园子里搜着看,看到篇文章,于是自己(新手)用了最最原始的sql去写出来: --需求----B, C, F, M and S住在一座房子的不同楼层.--B 不住顶层.C 不住底 ...
- .NET平台开源项目速览(11)KwCombinatorics排列组合使用案例(1)
今年上半年,我在KwCombinatorics系列文章中,重点介绍了KwCombinatorics组件的使用情况,其实这个组件我5年前就开始用了,非常方便,麻雀虽小五脏俱全.所以一直非常喜欢,才写了几 ...
- 【原创】开源.NET排列组合组件KwCombinatorics使用(三)——笛卡尔积组合
本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...
- 【原创】开源.NET排列组合组件KwCombinatorics使用(二)——排列生成
本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...
- 【原创】开源.NET排列组合组件KwCombinatorics使用(一)—组合生成
本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...
- hdu1521 排列组合(指数型母函数)
题意: 有n种物品,并且知道每种物品的数量ki.要求从中选出m件物品的排数. (全题文末) 知识点: 普通母函数 指数型母函数:(用来求解多重集的排列问题) n个元素,其中a1,a2, ...
随机推荐
- 【idea】高德地图可以关爱一下高个汽车
现状:1.交通事故时不时能看到大卡车,双层巴士在城市里限高区域时的车祸 原因分析:1.司机对路况不熟,驶入新的限高路,造成事故2.司机对车况不熟,临时换的车驾驶,忘记车高的变化3.司机路况车况都熟,道 ...
- thinkphp5配合datatable插件分页后端处理程序
thinkphp5配合datatable插件分页后端处理程序第一版DataTable.php v.1.0 <?php use think\Db; /** * DataTable.php. */ ...
- 0xe7f001f0!?NDK调试过程,无故抛出SIGSEGV。
arm调试过程,如果抛一个SIGSEGV,地址在 0xe7f001f0 附近,原因居然是因为我在调试.当我使用n指令跳到下一行代码时,往往变成了continue指令一样地执行.还不确定地抛出SIGSE ...
- python中的__str__和__repr__方法
如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class A(object): def __init__(self,name,age): self.name=name se ...
- 【01】主函数main
java和C#非常相似,它们大部分的语法是一样的,但尽管如此,也有一些地方是不同的. 为了更好地学习java或C#,有必要分清它们两者到底在哪里不同. 首先,我们将探讨主函数main. java的主函 ...
- 正确理解 PHP 的重载
PHP 的重载跟 Java 的重载不同,不可混为一谈.Java 允许类中存在多个同名函数,每个函数的参数不相同,而 PHP 中只允许存在一个同名函数.例如,Java 的构造函数可以有多个,PHP 的构 ...
- Java学习笔记 线程池使用及详解
有点笨,参考了好几篇大佬们写的文章才整理出来的笔记.... 字面意思上解释,线程池就是装有线程的池,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程 ...
- 2019-10-31:渗透测试,基础学习,mongodb注入学习
mongodb命令删除文档,db.集合名.remove({键:值})更新文档,db.集合名.update({被更新的对象},{$set:{要更新的内容}}),默认只更新检测到的第一条文档更新全部匹配到 ...
- 新闻实时分析系统 SQL快速离线数据分析
1.Spark SQL概述1)Spark SQL是Spark核心功能的一部分,是在2014年4月份Spark1.0版本时发布的. 2)Spark SQL可以直接运行SQL或者HiveQL语句 3)BI ...
- python接口自动化测试——简单的文件上传代码实现,人人网登陆后上传图片举例
import requests '''人人网登陆,图片上传 '''def loginData(): '''登录请求参数''' data = { 'email': '13484545195', 'ico ...