1、基本概念

模拟退火算法(Simulated Annealing,SA)是一种模拟固体降温过程的最优化算法。其模拟的过程是首先将固体加温至某一温度,固体内部的粒子随温度上升慢慢变为无序的状态,内能增大,然后让其慢慢冷却,温度下降时,内部的粒子慢慢趋于有序,达到一种平衡态,最后达到常温时成为基态,此时内能减为最小,算法模拟这样一个过程期望能达到最优化的目的。

模拟退火算法最早是由kirkpatrick等人应用于组合优化领域,它是基于Monte-Carlo迭代求解策略的一种随机寻优算法。算法从某一较高温度开始,不断下降温度参数,结合概率跳变性在解空间中随机的寻找目标函数的全局最优解,算法的关键点是其能在降温过程中达到局部最优解的情况下以一定的概率跳出局部最优解并最终趋于全局最优。模拟退火算法是一种通用的优化算法,理论上以概率1收敛于全局最优,在工程中有比较广泛的应用,如VLSI、生成调度、控制工程、机器学习、神经网络、信号处理等领域。

2、算法原理

模拟退火算法分为三部分:初始解、解空间以及目标函数,分别对应物理退火过程中的初始温度、降温以及最终温度。

1)初始解:初始解释算法迭代的起点,试验表明,模拟退火算法是健壮的,即最终解的求得最优解并不十分依赖初始解的选取,从而可任意选择一个初始解。当然,如果初始解选择得当可以加快找到全局最优解。

2)解空间:一般是离散的可行解的集合。

3)目标函数:对优化目标的量化描述,是解空间到某个数集的一个映射,通常表示为若干优化目标的一个和式,应正确体现问题的整体优化要求且较易计算,当解空间包含不可行解时还应包括罚函数。

算法从初始解或称为初始状态开始,在解空间中进行启发式搜索(通常是随机搜索的方式),最终搜索到最优的目标值。

算法的基本过程如下:

  1. 初始化:设定初始温度T,初始解状态S,终止温度T0;
  2. 降温过程:如果T>T0,则循环执行3至6步;
  3. 在解空间中随机搜索一个新解S’;
  4. 计算增量ΔE=E(S′)-E(S),其中C(S)为解S对应的目标函数值或称为评价函数;
  5. 若ΔE<0则接受S′作为新的当前解,否则以概率exp(-ΔE/T)接受S′作为新的当前解;
  6. 如果满足终止条件则输出当前解作为最优解,结束程序。终止条件有两种情况,一是温度已经达到了最低温度T0;二是在连续的取若干个新解都没有跳出当前最优解

算法流程图如下:

Python自然语言处理系列之模拟退火算法-LMLPHP

3、退火方式

模拟退火算法中,退火方式对算法有很大影响。如果温度下降过慢,算法的收敛速度会大大降低。如果温度下降过快,可能会丢失极值点。为了提高模拟退火算法的性能,许多学者提出了退火的各种方式,比较有代表性的有以下几种:

1)Python自然语言处理系列之模拟退火算法-LMLPHP

该方式的特点是温度下降缓慢,算法收敛速度也较慢,但是最终达到全局最优的可能性是最高的

2)Python自然语言处理系列之模拟退火算法-LMLPHP

式中a为可调参数,可以改善退火曲线的形态。其特点是高温区温度下降比较快,低温区下降比较慢,这种退火方式主要期望在低温区收敛到全局最优。

3)Python自然语言处理系列之模拟退火算法-LMLPHP

式中a为可调参数,其特点是温度下降很快,算法的收敛速度快,但是带来的损失是可能不能充分的收敛到全局最优

以上三种退火方式各有优缺点以及适用的场景,需针对具体的应用进行选择。

4、模拟退火算法在英文分词中的应用

(1)问题描述

英文通常不需要分词,因为其本身就是由一个个的英文单词组成,我们考虑一种场景,比如在口语语言处理中,听者必须将连续的语音流分割成单个的词汇,考虑由机器进行分词,这个问题就变得具有挑战性了,考虑下面人为构造的例子,单词边界已被人为去除:

a:doyouseethekitty

b:seethedoggy

c:doyoulikethekitty

d:likethedoggy

如果是由机器来识别单词边界,则需要找到一种算法来对每个句子进行分词。我们可以给每个字符标注一个布尔值来指示这个字符后面是否有一个分词标志,让我们假设说话人会给语言学习者(机器)一个说话时的停顿,这往往是对应一个延长的暂停,分别对应了abcd四个句子块。现在算法的任务就是对这个句子块进行分词,使得每个句子都能有对应的意思。

经过处理后,四个句子变为如下的形式:

text = "doyouseethekittyseethedoggydoyoulikethekittylikethedoggy"

seg1= "0000000000000001000000000010000000000000000100000000000"

seg2= "0100100100100001001001000010100100010010000100010010000"

其中seg1是初始解,seg2是全局最优的目标解,算法采用模拟退火算法通过若干轮迭代达到全局最优。

(2)模拟退火算法引入

  • 初始解:初始解即为上面提到的seg1串。
  • 解空间:解空间是离散的,分别对应的是串中每位为1的情况,每个块(a、b、c、d)都有2的n次幂的分词方法,n为块的长度。
  • 目标函数:目标函数是一个打分函数,该打分函数能够体现分词的一个效果,也就是说分词效果越接近全局最优,分数应越低或越高。

模拟退火算法自身需要考虑三个与温度相关的量:

  • 初始温度:初始温度可设为一个比较高的温度,使得算法有足够的时间收敛到全局最优
  • 降温方式:降温方式采用线性方式,T’=a*T,a是一个小于1的参数,可设为0.99,充分降温,使得搜索解空间更加充分。
  • 终止温度:终止温度与初始温度对应,当初始温度降到终止温度时,算法终止,因此终止温度的选择也与算法达到全局最优解密切相关

(3)算法设计

搜索解空间

搜索解空间就是是寻找最大化目标函数值的0和1的模式,最好的分词包括像“thekitty”这样的“词”,因为数据中没有足够的证据进一步分割这个词。使用模拟退火算法的非确定性搜索即随机搜索:一开始仅搜索短语分词;随机扰动0和1,它们与“温度”成比例;每次迭代温度都会降低,扰动边界会减少

目标函数或代价函数

目标函数是一个打分函数,我们将基于词典的大小和从词典中重构源文本所需的信息量尽力优化它的值。

Python自然语言处理系列之模拟退火算法-LMLPHP

给定一个假设的源文本的分词(左),推导出一个词典和推导表,它能让源文本重构,然后合计每个词项(包括边界标志)与推导表的字符数,作为分词质量的得分;得分值越小表明分词越好。

如上图示的一种分词情况,目标得分包括两个部分,一个分词得分LEXICON,一个是分块得分DERIVATION。LEXICON对分好的每个唯一的词进行算分,分数即为单词长度加上边界1,如doyou的分词得分为单词长度5加上边界1即为6,其他词计算方法类似;分块得分就是买个块包含的单词数量,如第一个1|2|4|6,其得分为4,依次类推,最终得到分词得分为33,分块得分为14,两者相加即为总得目标得分,该目标得分越小则分词效果就越好,也就越接近我们人工识别的目标。

(3)算法伪代码

@text:待分词文本

@segs:初始解,为01串

@iterations:每个温度的迭代次数,目的是在在每次降温时都能找到一个当前最优的解,

这个量是当目标达到一个局部最优时,能够使得算法有一定的概率跳出当前局部最优解,是模拟退火算法中以一定概率接受较差解的一种实现方式,随着温度的降低,这种概率会减小,具体实现是flip_n函数,其跳变的位数与温度正相关。

@a:退火因子

string anneal(text, segs, iterations, a)

T=float(length(segs));

while T > T0

score=evaluate(text, segs)

best_segs=segs

for i=1 to iterations

//flip_n是随机选择n位位进行跳变,这里n为int(round(T)),其与当前温//度相关,温度下降时,跳变的位数会减小,具体实现原理是保证温度下//降时,解跳变的概率会减小,最后返回跳变后的串

guess = flip_n(segs, int(round(T)))

//evalue即是我们上面讨论的目标函数或代价函数

score = evalue(text, guess)

if score < best

best = score

best_segs=guess

score = best

segs = best_segs

T = T*a//降温

//打印每一步的优化结果

print evalue(text, segs), segment(text, segs)

经过程序实际运行,打印过程为,最左边一列是其对应分数

60     ['doyouseetheki', 'tty', 'see', 'thedoggy', 'doyouliketh', 'ekittylike', 'thedoggy']

58     ['doy', 'ouseetheki', 'ttysee', 'thedoggy', 'doy', 'o', 'ulikethekittylike', 'thedoggy']

56     ['doyou', 'seetheki', 'ttysee', 'thedoggy', 'doyou', 'liketh', 'ekittylike', 'thedoggy']

54     ['doyou', 'seethekit', 'tysee', 'thedoggy', 'doyou', 'likethekittylike', 'thedoggy']

53     ['doyou', 'seethekit', 'tysee', 'thedoggy', 'doyou', 'like', 'thekitty', 'like', 'thedoggy']

51     ['doyou', 'seethekittysee', 'thedoggy', 'doyou', 'like', 'thekitty', 'like', 'thedoggy']

42     ['doyou', 'see', 'thekitty', 'see', 'thedoggy', 'doyou', 'like', 'thekitty', 'like', 'thedoggy']

42分是最优结果,对应全局最优的01串是:

'0000100100000001001000000010000100010000000100010000000'

05-12 10:08