视觉机器学习读书笔记--------遗传算法
遗传算法起始于20世纪60年代,受达尔文进化论的启发,借鉴生物学中的遗传、突变、自然选择以及杂交等思想,是一种模拟自然界生物进化机制的启发式搜索方法。
一、算法原理
针对现实世界中的最优化问题,遗传算法通常是使一定数量的候选解抽象表示的种群向更好的种群进化的过程。遗传算法的进化过程从完全随机生成的种群开始,随后逐代向适应度更高的种群进化。在进化的每一代中,整个种群的适应度按照一定规则被评价,基于个体的适应度高低从当前种群中随机选择多个个体,通常个体自然选择和基因突变操作而产生新种群,生成的新种群在算法的下一次迭代中成为当前种群。
在遗传算法中,需解决的问题的解通常被称为基因个体,它通常以参数列表的形式进行标示,被称作染色体或基因串。其中染色体通常以编码形式体现,即表达为简单的字符串或数字串。
一般情况下,遗传算法并不能直接处理待解决问题的空间解参数,我们需要把这些参数转换成由遗传空间中基因按照一定结构组成的染色体,这一过程称为编码。评估编码策略需满足以下三个准则:
完备性,问题空间中所有的候选解都能作为算法空间中染色体的表现。
健全性,算法空间中的染色体能够对应所有问题空间中的候选解。
非冗余性,染色体和候选解通常可以一一对应。
遗传算法中通常采用的编码技术有二进制编码、浮点数编码、字符编码等。二进制编码是最常用的编码方式,这种编码方式通常由二进制字符集{0,1}产生的0,1编码来表示问题空间的候选解。这种编码方式通常简单易行,符合最小字符集的编码原则,并且可以通过采用模式定理进行分析。
遗传算法的实现原理如下:
首先,算法根据需要解决问题随机生成一定规模的种群,同时算法也可以对这个随机生成种群的过程进行干扰,以便提高初始个体种群的质量。在算法的进化过程中,群体中的所有个体被评价,并通过计算个体的适应度函数得到一个适应度值。种群中个体按照适应度值得高低进行排序,算法基于适应度的高低进行选择操作。
然后,算法产生下一代个体并组成个体种群,这一过程通常选择操作,交叉操作和突变操作来完成。选择根据新个体的适应度进行,同时并不意味着以适应度高低作为导向,因为单纯选择适应度高的个体将可能导致算法收敛到局部最优解,称之为早熟。
接着,算法经过一系列的选择、交叉和突变操作产生新个体将不同于初始一代的群体个体,逐渐向增加群体整体适应度的方向进展,适应度高的个体总是更多地被选择去构成下一代,适应度低的个体在进化过程中逐渐被淘汰。该过程不断重复,每个个体被评价,计算出适应度两个个体交叉突变,产生下一代,一直到满足设定的停止条件为止。
最后,直到终止条件满足为止。
遗传算法的终止条件有进化代数的限制、计算耗费资源的限制、个体满足最优值条件、群体进化不会产生适应度更高的个体等。
遗传算法的流程如图所示:
二、算法改进
群体算法的共同特征问题如下:首先针对需要解决的生成一组候选解,然后根据适应度函数的计算方法计算群体中个体的适应度值,保留某些适应度高的个体,放弃适应度低的个体;再对保留下来的个体进行交叉变异等操作,生成新的个体。
遗传算法是解决搜索问题的一种通用算法,对初始种群的选择有一定的依赖性,并行机制的潜在能力没有得到充分利用,在适应度函数选择不当时有可能收敛于局部最优。
2.1 适应度函数设计
遗传算法中的适应度函数与进化算法中的个体适应度函数性质相似,表示个体对环境的适应能力。遗传算法的适应度函数用来评价群体中个体适应度高低的程度。
遗传算法在进化过程中通常不依赖于外界环境信息,仅采用适应度函数对个体进行评估,并采用适应度函数作为后续操作的依据。通常,在遗传算法中,个体的适应度函数要通过比较对个体进行排序,并根据个体的适应度计算个体的选择概率,因此个体的适应度函数值为正值。
遗传算法中适应度函数的设计要求通常需要满足单值、连续、非负、最大化、计算量小、通用性强等特点。在解决实际问题时,适应度函数的计算方法直接影响到算法的性能,因此算法适应度函数的设计需要结合待解决的实际问题的本身特点而定。
2.2 初始群体的选取
在遗传算法中随机产生的初始群体在解空间中的分布时往往有两种极端情况,一种是较均匀分布,一种是较集中的聚集。
通常均匀分布的初始群体含有更高的多样性,初始群体散布在各个子空间中,经过遗传收敛到全局最优解的可能性很大。
而集中分布的初始群体主要集中在局部,经过遗传操作收敛到子空间的局部最优解便产生停滞现象,初始种群的产生采用完全的随机方式,不利于扩大搜索空间和收敛到全局最优解。
根据解决问题的固有知识,首先需要减少最优解所占空间在整个问题空间中的分布范围;然后在此范围内设定初始群体;随后随机生成一定数目的个体;并从中挑出最好的个体加到初始群体中,该过程不断迭代,直到初始群体中个体数目达到预选确定的规模。
三. 算法仿真
车牌识别是计算机视觉在智能交通领域的重要应用方向,包括车牌定位、字符分割和字符识别等环节。
在车牌识别中定位最关键,存在以下两大难题:
a.复杂的背景干扰,很难提取出适合各种情况的车牌特征;
b.车牌图像易受天气、光照、污染等因素影响。
3.1 图像预处理
图像预处理的好坏直接影响车牌定位的准确性,由于车牌定位基于二值图像,因此要对彩色图像进行灰度化和二值化。
彩色图像转换为灰度图像,常用标准转化方法如下:
f(x,y)=0.30R(x,y)+0.59G(x,y)+0.11B(x,y)
基于摄像机采集的车辆图像受到环境影响很大,在二值化时不能采用固定阈值,可以采用OTSU方法实现二值化,如下图所示。OTSU是1972年提出的最大类间方差方法,是最优的阈值自动选择方法。
3.2 车牌特征提取
车牌目标区域居于如下特点:
a.车牌底色与车身、字符颜色有较大差异;
b.牌照的长宽比变化有一定范围;
c.车牌内字符之间的间隔、灰度比较均匀;
d.车牌内字符有多个,呈水平排列;
e.在牌照的矩形区域内存在丰富边缘,文理特征较规则。
二值化后的车牌图像的显著特征是字符纹理特征,纹理特征的描述方法有结构法、谱方法和统计法,常用多尺度滤波技术,使用滤波器组获取图像纹理特征向量。由于二值化的车牌图像的纹理特征主要集中在水平方向上,体现为一定疏密度的黑白像素分布。因此,可以通过采用反应不同疏密度的一维滤波器组在水平方想上对二值图像进行滤波,获得车牌图像的纹理特征如下:
L1=[-1 0 1]
L2=[-1 -1 1 1]/2
L3=[-1 -1 0 1]/2
车牌区域图像纹理特征具有分布空间的均匀性,对滤波后的图像采用标准差δi表示纹理特征值:
其中,f(x,y)为图像数据,u为图像的平均能量:
可以得到车牌区域的特征描述向量为:
T=[δ1 δ2 δ3]
通过对待定局部区域图像进行滤波处理,获得特征向量T,将其与车牌特征描述向量进行比较,得到该区域作为车牌区域的可能性。
3.3 基于遗传算法的车牌定位
车牌提取是寻找最符合牌照特征区域的过程,是在参量空间内寻找最优解的过程,而寻找参量空间的全局最优解是遗传算法最擅长的。
标准遗传算法存在着“早熟”缺陷,即过早收敛于局部值。遗传算法中的交叉概率Pc和编译概率Pm的选择影响算法的行为和性能,直接影响算法的收敛性。交叉概率Pc越大,新个体产生的速度就越快。但是Pc过大,遗传模式被破坏的可能性就越大,使得具有高适应度的个体结构很快就会被破坏;但是Pc过小,会使搜索过程过慢,一直停滞不前。变异概率Pm过小,不易产生新的个体结构;Pm过大,遗传算法将变成纯粹的随机概率搜索算法。针对不同的优化问题,需要反复实验来确定Pc和Pm,这是繁琐的工作,很难找到适合每个问题的最佳值。
在自适应遗传算法中,交叉概率Pc和变异概率Pm按下面规划进行自适应调整:
其中,fmax表示群体中最大适应度;favg表示每代群体的平均适应值;f为要交叉的两个个体中较大适应值;f为要变异个体的适应度值;k1,k2,k3,k4在[0,1]中取值。
在适应度值越接近最大适应度值时,Pc和Pm方法在群体处于进化后期时比较合适,此时群体中每个个体都表现出比较优异的性能,不宜对个体进行较大的改变以免破坏个体优良的性能结构;但是这种调整方式在群体处于进化初期阶段时,进化过程略显缓慢,在进化初期阶段群体中的较优良个体几乎处于不发生变化的状态,此时的优良个体不一定是优化问题的全局最优解,容易成为局部最优解。
针对以上问题改进Pc和Pm方法,使群体中最大适应值个体的Pc和Pm不为0,并分别提高到Pc1和Pc2.
其中,Pc1=0.9, Pc2=0.6, Pm1=0.1, Pm2=0.01,提高群体中表现优良的个体的Pc和Pm,使其不会处于近乎停滞不前的状态。因此,自适应的Pc和Pm能够提供相对于某个解的最佳Pc和Pm。在保证群体多样性的同时,确保算法收敛性。
车牌搜索范围为整幅图像,可变的参量有车片图像的位置,以及车牌区域的宽度和高度,可以唯一确定车牌的可能区域。实际车牌的大小固定在一个范围内,固定特定车牌区域的大小,比图像中车牌实际区域要大一些,车牌精度定位可以去掉此多余区域。
在遗传算法中采用联赛选择算子,由于二进制编码的局部搜索能力较差,因此直接采用二维实数编码[Xin,Yin]. 针对实数编码采用算数交叉算子,并不是简单的基因交换,二是对基因进行线性组合:
Pchild1=αPparent1+(1-α)Pparent2
Pchild2=(1-α)Pparent1+αPparent2
其中,α是(0,1)间均匀分布的随机变量。为了简化变异操作,采用直接产生一个新个体来代替要变异的个体,而个体是否要变异由Pm决定。
根据在待定区域获得的纹理特征向量,将其与车牌的纹理特征进行比较,就可以获得该待定区域为车牌区域的可能性。距离度量为:
其中,δgi是实际根据车牌统计得到的纹理特征向量,δi为待定区域计算得到的纹理特征向量。在搜索过程中,当有最优个体特征矢量距离差d<0.01,认为找到车牌区域,算法停止。
车牌定位是车牌识别系统中的关键,实际图像中的噪声、复杂背景等干扰会使定位十分困难。经典遗传算法存在早熟缺陷,如下图所示,改进的自适应遗传算法能根据适应值自动调整交叉概率Pc和变异概率Pm,可以很好地解决“早熟”问题。
四、算法特点
遗传算法在传统的计算数学研究中经常用于求解最优化问题,是进化计算方法的一种。遗传算法在很复杂的解集环境中,可以很快地找到良好的解集。不仅可成功应用于解决旅行商问题、背包问题、背箱问题、图形划分问题等传统领域,而且在解决生产调度问题、机器人制造、图像处理、人工生命等方面也获得了广泛应用。
4.1 遗传算法的优点
遗传算法一般从问题解的串集开始搜索,而并不是从单个解开始搜索。这是遗传算法与传统进化计算方法的区别。
传统进化算法一般采用单点搜索机制,因此这种方法容易导致局部最优解。遗传算法可以同时处理种群中的多个个体,可以对搜索空间中的多个不同的解进行评估,因此可以使算法减少陷入局部最优解的风险;同时也可以使算法更容易实现并行化。
遗传算法在求解过程中通常不借助搜索空间或其他辅助信息,而仅采用适应度函数对个体进行评估,并进行相应的遗传变异等操作。遗传算法的适应度函数不仅没有连续可微的的约束,而且适应度函数的定义域也可以任意设定,这便使得遗传算法的应用范围大大扩展。遗传算法通常不采用确定性规则,而采用有规律的变迁规则来对搜索方向进行指导。遗传算法通常具有自组织、自适应和自学习性,在利用获得的信息进行组织搜索时,适应度高的个体具有较高的生存概率,更加容易获得适应环境的基因结构。
4.2 遗传算法的不足
对于任何优化问题,遗传算法的参数调节都会影响收敛速度,具体参数包括种群规模、初始种群个体、交叉概率、变异概率和个体自适应函数等。参数选择没有实用的上下限,初始种群的数量很重要,过多会占用大量系统资源,过少会忽略掉最优解。变异率非常重要,太大会导致丢失最优解,过小会导致过早收敛于局部最优。在适应度函数选择不当时,可能收敛于局部最优,不能达到全局最优解。遗传算法不能解决大海捞针问题,所谓的大海捞针问题就是没有确切的适应度函数表征个体好坏的问题。从而使算法的进化失去导向。
五、实验
1.车牌图像分割实验
% read demo image a=imread('testcard.jpg'); % disp demo image figure(1),imshow(a),title('Original Image') % get dimension of image [m,n]=size(a); %返回矩阵的行数,列数 a0=double(a); % 对于灰度图像,uint8表示范围是[0 255] ,double表示范围是[0 1] h=1; a1=zeros(m,n); % Calculate 1D histogram for i=1:m for j=1:n for k=-h:h for w=-h:h; p=i+k; q=j+w; if (p<=0)|( p>m) p=i; end if (q<=0)|(q>n) q=j; end a1(i,j)=a0(p,q)+a1(i,j); end end a2(i,j)=uint8(1/9*a1(i,j)); end end fxy=zeros(256,256); % Calculate 2D histogram for i=1:m for j=1:n c=a0(i,j); d=double(a2(i,j)); fxy(c+1,d+1)=fxy(c+1,d+1)+1; end end Pxy=fxy/m/n; P0=zeros(256,256); Ui=zeros(256,256); Uj=zeros(256,256); P0(1,1)=Pxy(1,1); for i=2:256 P0(1,i)=P0(1,i-1)+Pxy(1,i); end for i=2:256 P0(i,1)=P0(i-1,1)+Pxy(i,1); end for i=2:256 for j=2:256 P0(i,j)=P0(i,j-1)+P0(i-1,j)-P0(i-1,j-1)+Pxy(i,j); end end P1=ones(256,256)-P0; Ui(1,1)=0; for i=2:256 Ui(1,i)=Ui(1,i-1)+(1-1)*Pxy(1,i); end for i=2:256 Ui(i,1)=Ui(i-1,1)+(i-1)*Pxy(i,1); end for i=2:256 for j=2:256 Ui(i,j)=Ui(i,j-1)+Ui(i-1,j)-Ui(i-1,j-1)+(i-1)*Pxy(i,j); end end Uj(1,1)=0; for i=2:256 Uj(1,i)=Uj(1,i-1)+(i-1)*Pxy(1,i); end for i=2:256 Uj(i,1)=Uj(i-1,1)+(1-1)*Pxy(i,1); end for i=2:256 for j=2:256 Uj(i,j)=Uj(i,j-1)+Uj(i-1,j)-Uj(i-1,j-1)+(j-1)*Pxy(i,j); end end uti=0; utj=0; for i=1:256 for j=1:256 uti=uti+(i-1)*Pxy(i,j); utj=utj+(j-1)*Pxy(i,j); end end % Calculate max variance hmax=0; for i=1:256 for j=1:256 if P0(i,j)~=0&P1(i,j)~=0 h(i,j)=((uti*P0(i,j)-Ui(i,j))^2+(utj*P0(i,j)-Uj(i,j))^2)/(P1(i,j)*P0(i,j)); else h(i,j)=0; end end end hmax=max(h(:)); for i=1:256 for j=1:256 if h(i,j)==hmax s=i-1; t=j-1; continue; end end end % the result z=ones(m,n); for i=1:m for j=1:n if a(i,j)<=s&a2(i,j)<=t z(i,j)=0; end end end % disp the result image figure(2),imshow(z),title('GA-based car plate number segmentation');
the result
2.车牌识别实验
function main clc;clear all;close all; img=imread('testcard.jpg'); defaultConfig.xy = 10*rand(50,2); defaultConfig.dmat = []; defaultConfig.popSize = 100; defaultConfig.numIter = 1e4; defaultConfig.showProg = true; defaultConfig.showResult = true; defaultConfig.showWaitbar = false; % define the position of the plate number; aa=[157,226];bb=[140,140];cc=[163,163];dd=[141,163];ee=[157,157];ff=[226,226]; % Interpret user configuration inputs if ~nargin userConfig = struct(); elseif isstruct(varargin{1}) userConfig = varargin{1}; else try userConfig = struct(varargin{:}); catch error('Expected inputs are either a structure or parameter/value pairs'); end end % Override default configuration with user inputs configStruct = get_config(defaultConfig,userConfig); % Extract configuration xy = configStruct.xy; dmat = configStruct.dmat; popSize = configStruct.popSize; numIter = configStruct.numIter; showProg = configStruct.showProg; showResult = configStruct.showResult; showWaitbar = configStruct.showWaitbar; if isempty(dmat) nPoints = size(xy,1); a = meshgrid(1:nPoints); dmat = reshape(sqrt(sum((xy(a,:)-xy(a',:)).^2,2)),nPoints,nPoints); end % Verify Inputs [N,dims] = size(xy); [nr,nc] = size(dmat); if N ~= nr || N ~= nc error('Invalid XY or DMAT inputs!') end n = N; % Sanity Checks popSize = 4*ceil(popSize/4); numIter = max(1,round(real(numIter(1)))); showProg = logical(showProg(1)); showResult = logical(showResult(1)); showWaitbar = logical(showWaitbar(1)); % Initialize the Population pop = zeros(popSize,n); pop(1,:) = (1:n); for k = 2:popSize pop(k,:) = randperm(n); end % Run the GA globalMin = Inf; totalDist = zeros(1,popSize); distHistory = zeros(1,numIter); tmpPop = zeros(4,n); newPop = zeros(popSize,n); if showProg % figure('Name','TSP_GA | Current Best Solution','Numbertitle','off'); hAx = gca; end if showWaitbar hWait = waitbar(0,'Searching for near-optimal solution ...'); end for iter = 1:numIter % Evaluate Each Population Member (Calculate Total Distance) for p = 1:popSize d = dmat(pop(p,n),pop(p,1)); % Closed Path for k = 2:n d = d + dmat(pop(p,k-1),pop(p,k)); end totalDist(p) = d; end % Find the Best Route in the Population [minDist,index] = min(totalDist); distHistory(iter) = minDist; if minDist < globalMin globalMin = minDist; optRoute = pop(index,:); if showProg % Plot the Best Route rte = optRoute([1:n 1]); % if dims > 2, plot3(hAx,xy(rte,1),xy(rte,2),xy(rte,3),'r.-'); % else plot(hAx,xy(rte,1),xy(rte,2),'r.-'); end % title(hAx,sprintf('Total Distance = %1.4f, Iteration = %d',minDist,iter)); drawnow; end end % Genetic Algorithm Operators randomOrder = randperm(popSize); for p = 4:4:popSize rtes = pop(randomOrder(p-3:p),:); dists = totalDist(randomOrder(p-3:p)); [ignore,idx] = min(dists); %#ok bestOf4Route = rtes(idx,:); routeInsertionPoints = sort(ceil(n*rand(1,2))); I = routeInsertionPoints(1); J = routeInsertionPoints(2); for k = 1:4 % Mutate the Best to get Three New Routes tmpPop(k,:) = bestOf4Route; switch k case 2 % Flip tmpPop(k,I:J) = tmpPop(k,J:-1:I); case 3 % Swap tmpPop(k,[I J]) = tmpPop(k,[J I]); case 4 % Slide tmpPop(k,I:J) = tmpPop(k,[I+1:J I]); otherwise % Do Nothing end end newPop(p-3:p,:) = tmpPop; end pop = newPop; % Update the waitbar if showWaitbar && ~mod(iter,ceil(numIter/325)) waitbar(iter/numIter,hWait); end end if showWaitbar close(hWait); end % if showResult % % Plots the GA Results % % figure('Name','TSP_GA | Results','Numbertitle','off'); % % subplot(2,2,1); % pclr = ~get(0,'DefaultAxesColor'); % if dims > 2, plot3(xy(:,1),xy(:,2),xy(:,3),'.','Color',pclr); % else plot(xy(:,1),xy(:,2),'.','Color',pclr); end % title('City Locations'); % subplot(2,2,2); % imagesc(dmat(optRoute,optRoute)); % title('Distance Matrix'); % subplot(2,2,3); % rte = optRoute([1:n 1]); % if dims > 2, plot3(xy(rte,1),xy(rte,2),xy(rte,3),'r.-'); % else plot(xy(rte,1),xy(rte,2),'r.-'); end % title(sprintf('Total Distance = %1.4f',minDist)); % subplot(2,2,4); % plot(distHistory,'b','LineWidth',2); % title('Best Solution History'); % set(gca,'XLim',[0 numIter+1],'YLim',[0 1.1*max([1 distHistory])]); % end imshow(img);hold on; plot(aa,bb,'w.-',aa,cc,'w.-',ee,dd,'w.-',ff,dd,'w.-'); % Return Output if nargout resultStruct = struct( ... 'xy', xy, ... 'dmat', dmat, ... 'popSize', popSize, ... 'numIter', numIter, ... 'showProg', showProg, ... 'showResult', showResult, ... 'showWaitbar', showWaitbar, ... 'optRoute', optRoute, ... 'minDist', minDist); varargout = {resultStruct}; end figure(2); subimg=img(dd(1):dd(2),aa(1):aa(2)); imshow(subimg); end % Subfunction to override the default configuration with user inputs function config = get_config(defaultConfig,userConfig) % Initialize the configuration structure as the default config = defaultConfig; % Extract the field names of the default configuration structure defaultFields = fieldnames(defaultConfig); % Extract the field names of the user configuration structure userFields = fieldnames(userConfig); nUserFields = length(userFields); % Override any default configuration fields with user values for i = 1:nUserFields userField = userFields{i}; isField = strcmpi(defaultFields,userField); if nnz(isField) == 1 thisField = defaultFields{isField}; config.(thisField) = userConfig.(userField); end end end
the result :
参考书籍:视觉机器学习20讲,清华大学出版社