精华内容
下载资源
问答
  • [Matlab]LMS滤波器设计

    千次阅读 多人点赞 2019-11-30 16:39:31
    由于它具有更强的适应性更优的滤波性能。从而在工程实际中,尤其在信息处理技术中得到了广泛的应用。自适应滤波存在于信号处理、控制、图像处理等许多不同领域,它是一种智能更有针对性的滤波方法,通常用于去噪。 ...

    [Matlab]自适应(LMS)滤波器设计

    ​ 自适应滤波是近年以来发展起来的一种最佳滤波方法。它是在维纳滤波,Kalman滤波等线性滤波基础上发展起来的一种最佳滤波方法。由于它具有更强的适应性和更优的滤波性能。从而在工程实际中,尤其在信息处理技术中得到了广泛的应用。自适应滤波存在于信号处理、控制、图像处理等许多不同领域,它是一种智能更有针对性的滤波方法,通常用于去噪。

    背景介绍

    ​ 自适应滤波的研究对象是具有不确定的系统或信息过程。这里的“不确定性”是指所研究的处理信息过程及其环境的数学模型不是完全确定的。其中包含一些未知因素和随机因素。

    任何一个实际的信息过程都具有不同程度的不确定性,这些不确定性有时表现在过程内部,有时表现在过程外部。从过程内部来讲,描述研究对象即信息动态过程的数学模型的结构和参数是设计者事先并不一定能确切知道的。作为外部环境对信息过程的影响,可以等效地用扰动来表示。这些扰动通常是不可测的,它们可能是确定性的,也可能是随机的。此外,还有一些测量噪音 [1] 也以不同的途径影响信息过程。这些扰动和噪声的统计特性常常是未知的。面对这些客观存在的各式各样的不确定性,如何综合处理该信息过程,并使得某一些指定的性能指标达到最优或近似最优,这就是自适应滤波所要解决的问题。

    LMS与维纳滤波器(Wiener Filter)的区别
    • 这里介绍的LMS/NLMS,通常逐点处理,对应思路是:随机梯度下降;
    • 对于Wiener Filter,给定准则函数J,随机/批量梯度都可以得出最优解;
    • LMS虽然基于梯度下降,但准则仅仅是统计意义且通常引入误差,可以定义为 J 0 J_0 J0,简而言之J通常不等于 J 0 J_0 J0,得出的最优解 w o w_{o} wo,自然也通常不等于维纳最优解;
    • 分析LMS通常会分析稳定性,稳定性是基于Wiener解,之前已给出分析。但LMS是Wiener解的近似,所以:迭代步长的稳定性,严格适用于Wiener解,对于LMS只是一种近似参考,并没有充分的理论依据
    LMS与维纳滤波器原理

    自适应滤波器的原理 如图1所示。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lbYS4vum-1575102876943)(G:\研究生\项目小组任务\笔记\第四周和第五周笔记\7.jpg)]

    图中x(k)表示k时刻的输入信号值,y(k)表示 k时刻的输出信号值,d(k)表示k 的参考信号值或所期望响应信号值,误差信号e(k)为d(k)与y(k)之差。自适应数字滤波器的滤波参数受误差信号e(k)的控制,根据e(k)的值而自动调整,使之适合下一时刻的输入x(k+1),以便使输出y(k+1)接近于所期望的参考信号d(k+1)。

    自适应滤波器可以分为线性自适应滤波器和非线性自适应滤波器。非线性自适应滤波器包括Voetlrra滤波器和基于神经网络的自适应滤波器。非线性自适应滤波器具有更强的信号处理 [3] 能力。但是,由于非线性自适应滤波器的计算较复杂,实际用得最多的仍然是线性自适应滤波器。

    典型算法

    对自适应滤波算法 [4] 的研究是当今自适应信号处理中最为活跃的研究课题之一。自适应滤波算法广泛应用于系统辨识回波消除自适应谱线增强、自适应信道均衡、语音线性预测、自适应天线阵等诸多领域中。总之,寻求收敛速度快,计算复杂性低,数值稳定性好的自适应滤波算法是研究人员不断努力追求的目标。虽然线性自适应滤波器和相应的算法具有结构简单、计算复杂性低的优点而广泛应用于实际,但由于对信号的处理能力有限而在应用中受到限制。由于非线性自适应滤波器,如Voletrra滤波器和基于神经网络的自适应滤波器,具有更强的信号处理能力,已成为自适应信号处理中的一个研究热点。其中较典型的几种算法包括:

    1. LMS自适应滤波算法
    2. RLS自适应滤波算法
    3. 变换域自适应滤波算法
    4. 仿射投影算法
    5. 共扼梯度算法
    6. 基于子带分解的自适应滤波算法
    7. 基于QR分解的自适应滤波算法
    算法性能评价

    变步长的自适应滤波算法 [6] 虽然解决了收敛速度、时变系统跟踪速度与收敛精度方面对算法调整步长因子u的矛盾,但变步长中的其它参数的选取还需实验来确定,应用起来不太方便。对RLS算法的各种改进,其目的均是保留RLS算法收敛速度快的特点而降低其计算复杂性。变换域类算法亦是想通过作某些正交变换使输入信号自相关矩阵的特征值发散程度变小,提高收敛速度。而仿射投影算法的性能介于LMS算法和RLS算法之间。共扼梯度自适应滤波算法的提出是为了降低RLS类算法的复杂性和克服某些快速RLS算法存在的数值稳定性问题。信号的子带分解能降低输入信号的自相关矩阵的特征值发散程度,从而加快自适应滤波算法的收敛速度,同时便于并行处理,带来了一定的灵活性。矩阵的QR分解具有良好的数值稳定性。

    自适应(LMS)滤波器设计(1):
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % 输入参数:
    %     xn   输入的信号序列      (列向量)
    %     dn   所期望的响应序列    (列向量)
    %     M    滤波器的阶数        (标量)
    %     mu   收敛因子(步长)      (标量) 要求大于0,小于xn的相关矩阵最大特征值的倒数    
    % 输出参数:
    %     W    滤波器的权值矩阵     (矩阵)
    %          大小为M x itr,
    %     en   误差序列(itr x 1)    (列向量)  
    %     yn   实际输出序列         (列向量)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function [yn,W,en]=LMS1(xn,dn,M,mu)
    itr = length(xn);
    en = zeros(itr,1);     % 误差序列,en(k)表示第k次迭代时预期输出与实际输入的误差
    W  = zeros(M,itr);     % 每一行代表一个加权参量,每一列代表-次迭代,初始为0
    % 迭代计算
    for k = M:itr              % 第k次迭代
        x = xn(k:-1:k-M+1);    % 滤波器M个抽头的输入
        y = W(:,k-1).' * x;    % 滤波器的输出
        en(k) = dn(k) - y ;    % 第k次迭代的误差
        W(:,k) = W(:,k-1) + 2*mu*en(k)*x; % 滤波器权值计算的迭代式
    end
    % 求最优时滤波器的输出序列  r如果没有yn返回参数可以不要下面的
    yn = inf * ones(size(xn)); % inf 是无穷大的意思
    for k = M:length(xn)
        x = xn(k:-1:k-M+1);
        yn(k) = W(:,end).'* x;%用最后得到的最佳估计得到输出
    end
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%%%案例分析
    clc;clear all; close all;  
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % 周期信号的产生 
    t=0:0.5:100;
    xs=30*sin(t);
    figure;
    subplot(2,1,1);
    plot(t,xs);grid;
    ylabel('幅值/v');
    xlabel('时间/t');
    title('{输入原始性信号}');
    % 噪声信号的产生
    randn('state',sum(200*clock));
    xn=randn(1,201);
    subplot(2,1,2);
    plot(t,xn);grid;
    ylabel('幅值/v');
    xlabel('时间/t');
    title('{随机噪声信号}');
    
    % 信号滤波
    xn = xs+xn;
    xn = xn.' ;   % 输入信号序列
    dn = xs.' ;   % 预期结果序列
    M  = 20 ;   % 滤波器的阶数
    
    rho_max = max(eig(xn*xn.'));   % 输入信号相关矩阵的最大特征值
    mu = (1/rho_max) ;    % 收敛因子 0 < mu < 1/rho
    [yn,W,en] = LMS1(xn,dn,M,mu);
    
    % 绘制滤波器输入信号
    figure;
    subplot(2,1,1);
    plot(t,xn);grid;
    ylabel('幅值');
    xlabel('时间');
    title('{滤波器输入信号}');
    
    % 绘制自适应滤波器输出信号
    subplot(2,1,2);
    plot(t,yn);grid;
    ylabel('幅值');
    xlabel('时间');
    title('{自适应滤波器输出信号}');
    
    % 绘制自适应滤波器输出信号,预期输出信号和两者的误差
    figure 
    plot(t,yn,'b.-',t,dn,'g--',t,dn-yn,'r');grid;
    legend('自适应滤波器输出','预期输出','误差');
    ylabel('幅值');
    xlabel('时间');
    title('{自适应滤波器}');
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8OvcmaHQ-1575102876944)(G:\研究生\项目小组任务\笔记\第四周和第五周笔记\LMS.bmp)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OJlh77mG-1575102876946)(G:\研究生\项目小组任务\笔记\第四周和第五周笔记\LMS_S.bmp)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IZ8z4iwL-1575102876947)(G:\研究生\项目小组任务\笔记\第四周和第五周笔记\LMS_E(X)].bmp)

    自适应(LMS)滤波器设计(2)–DSP-2 最陡下降法:
    %LMS算法
    % 输入参数:
    %     Y   输入的信号序列      (列向量)
    %     X   所期望的响应序列    (列向量)
    %     COUNT 输入信号长度数     (标量)
    %     mu   收敛因子(步长)      (标量) 要求大于0,小于xn的相关矩阵最大特征值的倒数    
    % 输出参数:
    %     W    滤波器的权值矩阵     (矩阵)
    %          大小为M x itr,
    %     en   误差序列(itr x 1)    (列向量)  
    %     yn   实际输出序列         (列向量)
    function [e,w1,w2]=LMS(COUNT,X,Y,u)
    e=zeros(1,COUNT);
    w1=zeros(1,COUNT);
    w2=zeros(1,COUNT);
    w1(1)=3;
    w2(1)=-4;
    for i=1:COUNT
        if(i-1==0)
           yy=w1(i)*X(i)+w2(i)*X(16); 
        else
           yy=w1(i)*X(i)+w2(i)*X(i-1);
        end;
        
        e(i)=Y(i)-yy;
        
        if(i<COUNT)
            w1(i+1)=w1(i)+u*e(i)*X(i);
        end;
        if(0==i-1)
            w2(i+1)=w2(i)+u*e(i)*X(16);
        else
            if(i<COUNT)
                w2(i+1)=w2(i)+u*e(i)*X(i-1);
            end;
        end;
    end;
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    Expectation函数实现
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function EX=Expectation(x,y,N)
    EX=0;
    for n=1:1:N
        EX=EX+x(n)*y(n)/N;
    end;
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %最陡下降法
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function [w1,w2]=Steepest_Algorithm(R,P,u,COUNT)
    VGn=zeros(2,1);
    H=zeros(2,1);
    w1=zeros(1,COUNT);
    w2=zeros(1,COUNT);
    w1(1)=3;
    w2(1)=-4;
    for i=1:COUNT
        H=[w1(i),w2(i)]';
        VGn=2*R*H-2*P';
        w1(i+1)=w1(i)-0.5*u*VGn(1,1);
        w2(i+1)=w2(i)-0.5*u*VGn(2,1);
    end;
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    clc;clear all; close all;  
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    COUNT=300;
    n=1:COUNT;
    N=sin(2*n*pi/16+pi/10);
    X=2^0.5*sin(2*n*pi/16);
    X1=2^0.5*sin(2*(n-1)*pi/16);
    S=sqrt(0.05)*randn(1,COUNT);
    %随机信号
    Y=S+X;
    figure
    subplot(311)
    plot(n,X);
    title('信号图');
    subplot(312)
    plot(n,S);
    title('噪声图');
    subplot(313)
    plot(n,Y);
    title('信号加噪声图');
    %误差性能曲面及等值线
    ESS=0.05;
    ENN=Expectation(N,N,16);
    EXX=Expectation(X,X,16);
    R(1,1)=EXX;
    R(2,2)=EXX;
    EXX1=Expectation(X,X1,16);
    R(1,2)=EXX1;
    R(2,1)=EXX1;
    EYY=ENN+ESS;
    EYX=Expectation(N,X,16);
    EYX1=Expectation(N,X1,16);
    P=zeros(1,2);
    P(1)=EYX;
    P(2)=EYX1;
    x = -4:0.05:6;
    y = -5:0.05:5;
    [h0,h1] = meshgrid(x,y);
    z=EYY+R(1,1)*h0.*h0+2*R(1,2)*h0.*h1+R(2,2)*h1.*h1-2*P(1)*h0-2*P(2)*h1;
    figure
    subplot(1,2,1);
    mesh(h0,h1,z);
    xlabel('h0');
    ylabel('h1');
    title('误差性能曲面图');
    subplot(1,2,2);
    V=0.2:0.2:3;
    contour(h0,h1,z,V);
    xlabel('h0');
    ylabel('h1');
    title('等值线');
    hold on;
    %LMS算法
    u=0.4;
    [e,w1,w2]=LMS(COUNT,X,Y,u);
    length(w1);
    length(w2);
    plot(w1,w2);
    hold on;
    % DSP-2 最陡下降法
    [w1,w2]=Steepest_Algorithm(R,P,u,COUNT);
    plot(w1,w2);
    %LMS算法中一次和多次实验中梯度估计和平均值随时间n的变化情况
    Jn=zeros(1,COUNT);
    Jn=e.^2;
    figure
    subplot(1,2,1);
    plot(n,Jn);
    title('LMS算法中1次实验梯度估计');
    %200次实验
    e_avr=zeros(1,COUNT);
    w1_avr=zeros(1,COUNT);
    w2_avr=zeros(1,COUNT);
    for i=1:200
        S=sqrt(0.05)*randn(1,COUNT);
        Y=S+N;
        [e,w1,w2]=LMS(COUNT,X,Y,u);
        e_avr=e_avr+e./100;
        w1_avr=w1_avr+w1./100;
        w2_avr=w2_avr+w2./100;
    end;
    subplot(1,2,2);
    Jn=e_avr.^2;
    plot(n,Jn);
    title('LMS算法中200次实验梯度估计曲线图');
    figure
    plot(w1_avr,w2_avr);
    xlabel('h0');
    ylabel('h1');
    title('LMS算法200次实验中H(n)的平均轨迹曲线图');
    
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1LoqoqFc-1575102876949)(G:\研究生\项目小组任务\笔记\第四周和第五周笔记\lsm_ss.bmp)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YPLMuSdY-1575102876949)(G:\研究生\项目小组任务\笔记\第四周和第五周笔记\lms_fft.bmp)]

    在这里插入图片描述

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GXU6CVCl-1575102876949)(G:\研究生\项目小组任务\笔记\第四周和第五周笔记\lsm_200.bmp)]

    展开全文
  • 混沌遗传算法的基本思想是利用具有精致内在规律的混沌序列来控制遗传操作中的交叉变异,以取代原有的在一定概率下完全随机的交叉变异操作,包括确定是否进行交叉或变异操作以及确定交叉或变异操作的具体位置等两个...
    摘要:提出了一种基于混沌遗传算法的无人机航迹路径优化方法,属于无人机航迹规划技术领域。混沌遗传算法的基本思想是利用具有精致内在规律的混沌序列来控制遗传操作中的交叉和变异,以取代原有的在一定概率下完全随机的交叉和变异操作,包括确定是否进行交叉或变异操作以及确定交叉或变异操作的具体位置等两个方面,这使得遗传操作从短期看似随机的,而从长期看,则存在着某种精致的内在关系,有利于避免完全随机操作“盲目性”。遗传算法存在着早熟问题、收敛速度的问题以及自身参数选取存在困难。本发明把遗传算法的全局搜索能力和混沌优化的局部搜索能力有机地结合起来,一定程度上避免了遗传算法的早熟现象、求得的解精度高、收敛频率高,收敛速度快,同时该发明提出的方法具有较好的实时性和快速性,搜索到的航迹更逼近实际的无人机最优航迹;可应用于机器人路径规划、城市车辆路径规划等领域。
    
    1)无人机介绍
           新一代无人飞行器(Unmanned Aerial Vehicle,UAV)要替代有人驾驶飞机在非结构化环境中执行侦察、作战,已具备一定的自主飞行能力,受到世界各国的广泛关注,然而在遭遇到非预见的威胁或者任务变更时,任务、航迹规划系统是无人机实现自主飞行和自主攻击的关键。无人机路径规划主要解决在某一特定场景中,寻找到达目标的最佳飞行路径,降低无人机执行任务过程中的被损毁概率,从而提高工作效能。
          本文以无人机路径规划为研究对象,提出了基于混沌遗传优化算法的无人机航迹规划方法,主要工作为:(1)研究了无人机航迹规划基础模型和算法,建立了地形和威胁模型。 (2) 提出了一种混沌映射方案将初始种群均匀的分布在多维空间中。(3)混沌交叉、混沌变异的遗传航迹规划方法。该发明有效地克服了无人机航迹规划中局部最优与信息处理量之间的矛盾,提高了全局航迹优化的收敛速度。
    2)混沌算法介绍
    1混沌及其特性
           一般将由确定性方程得到的具有随机性的运动状态称为混沌,混沌状态广泛存在于自然现象和社会现象中,是非线性系统中一种较为普遍的现象,其行为复 杂且类似随机。但看似一片混乱的混沌变化过程并不完全混乱,而是存在着精细的内在规律性。一个混沌变量在一定范围内有如下特点:随机性,即它的表现同随机变量一样杂乱;遍历性,即它可以不重复地历经空间内的所有状态;规律性,该变量是由确定的达代方程导出的。混沌优化方法是一种新颖的优化方法,它利用混沌系统特有的遍历性来实现全局最优,而且它不要求目标函数具有连续性和可微性的性质。其基本思想是首先产生一组与优化变量相同数目的混沌变量,用类似载波的方式将混沌引入优化变量使其呈现混沌状态,同时把混沌运动的遍历范围放大到优化变量的取值范围,然后直接利用混沌变量搜索。由于混沌运动具有随机性、遍历性、对初始条件的敏感性等特点,基于混沌的搜索技术无疑会比其它随机搜索更具优越性。
    2混沌随机数生成器
           当前的混沌优化算法多采用Logistic 作为混沌序列的生成方法,将混沌映射引入遗传算法中。Logistic 映射方程为  
      x n+1 =μx n (1-x n ), n=0,1,…,k   (1) 其中μ 为控制参量,当μ=4 时,Logistic 映射在U(0,1)满区间内非稳定运动,迭代得到的数列具有伪随机性。当3.569945972<μ≤4时,特别是比较靠近4时,迭代生成的值是一种伪随机分布的状态。在遗传算法中,对解分布未知的问题,初始种群需要尽可能地均匀分布在多维空间中,对生成种群的均匀性要求较高。Logistic 映射生成的序列分布在边界点较多,在内部较分散。这种分布可以体现某些问题的解域的情况,但对大部分高维优化问题,尤其是全局最优点的位置未知的情况,均匀分布更具有普遍意义。
    An(1996)曾经研究了混沌映射(chaoticmapping)产生随机数的方法,该文使用的初始种群随机数生成器是An 提出的混沌映射随机数生成器。 本发明使用An 混沌映射生成的随机数作为遗传算法的初始种群。利用混沌系统对初值敏感的特点,迭代生成n 个序列得到M 个混沌变量,将M 个混沌变量映射到相应优化空间中得到初始种群。
    此递推式可产生周期为无穷的序列,其经验分布的极限分布为:
    F(y)=(Ln(y+1/2)+ Ln2)/ Ln3   (3)
    根据产生随机数中的熟知理论,得到公式(4):
     X i =(Ln(y+1/2)+ Ln2)/ Ln3        (4)
    得到的序列{x n }可看做是U(0,1)分布的随机数列。因序列{ x n }是无限不循环的,所以上述方法理论上可以产生周期为无限的U(0,1)分布的随机数列。由图1容易看出, An提出的映射所产生的序列均匀性更好。事实上, 由随机数参数检验法的结果表明, An提出的映射性质更优良。
    3 算法基本思想
           遗传算法在种群的进化过程中,采用的是完全随机的搜索方式,代与代之间除了通过交叉概率和变异概率等参数控制外几乎没什么必然的联系。这种模式虽然在实际应用中被证明是有效的,但存在早熟收敛、收敛速度慢等效率低的问题。另一方面,从混沌学的角度来看,生物进化的模式是“随机+反馈"其中的随机是由系统内部引起的,是系统本身的特性,混沌是系统进化和获得信息的来源。这种生物进化模式同传统模式相比更接近于真实的生物进化模式。因此引入混沌的遗传算法将会有更好的结果。
    混沌遗传算法的基本思想主要体现以下几个方面:
    (1)初始化。确定群体规模Nl,进化总代数M,混沌交叉和混沌变异区间Lc,Lm。
    (2)用随机方法在[0, l]上产生一列初始值:x 1 ,x 2 …x l ,映射到优化变量的可行域[a,b]得初始种群。
    (3)评价。计算种群中个体的适值,并按适值高低进行排序,如个体中的目标值有满足终止条件的,则结束,否则,进入下一步;
    (4)选择。淘汰种群中适值较低的10%个体,将适值较高的90%个体作为进行交叉操作的种群从;
    (5)混沌交叉。在种群NZ中随机选择两个配对个体,按混沌交叉规律进行交叉操作,直至产生NZ个新个体;
    (6)混沌变异。对经过混沌交叉产生的新个体,按混沌变异规律进行变异操作;
    (7)将经上述操作得到的新个体,连同原父代中适值较高10%个体一起构成新一代群体;
    (8)过滤。对群体中完全相同或极为相似的个体进行过滤操作,保留其中一个,而对与之相同或相似的其它个体进行概率为1的较大范围内的混沌变异操作,以保证群体的多样性,然后转向步骤(3)。
    在上述算法中,选择操作采用直接淘汰适应值最差的一些个体,而对大部分适应值较高的个体进行其它的遗传操作,并在产生新个体的同时,保留了种群中适应值最高的一些个体,以保证在遗传操作过程中,优秀个体不至于马上被“破坏”,而导致“退化”可能性,从而使算法具有好的一致收敛特性。步骤7的过滤操作,目的在于剔除掉群体中的相同或极为相似的个体,增加群体的多样性,避免算法陷入局部极小。

     

    展开全文
  • 假定视频图像序列中每个背景图像像素点灰度观测的时序变化由白噪声引起,利用建立的初始化背景高斯统计模型对每帧图像进行归一化,得到了背景像灰度比值的分布符合标准柯西分布的结论,解决了柯西分布的模型参量估计...
  • 应用改进的粒子群算法,结合双向反射分布函数五参量模型,获得了测量光谱范围内各波长(间隔1 nm)对应的共381组五参量值。利用五参量模型计算了目标样片的光谱双向反射分布函数及其方向半球反射率(DHR),并与实验测量...
  • 关于java的参数传递(传递、引用传递传值、传引用等) 2018年01月28日 02:16:17 ZytheMoon 阅读数:776   所谓参数传递就是用函数调用所给出的实参(实际参数)向函数定义所给出的形参(形式参数)设置...

    关于java的参数传递(值传递、引用传递和传值、传引用等)

    2018年01月28日 02:16:17 ZytheMoon 阅读数:776

     

    所谓参数传递就是用函数调用所给出的实参(实际参数)向函数定义所给出的形参(形式参数)设置初始值的过程。基本的有三种参数分别为:

    (1)传值: 

    (2)传址(即是传指针)

    (3)传引用

    以上这些都是根据参数的类型来分别的,是指传递的东西是什么,而不是指传递过程,但是在传递过程中也有和它们比较混淆的名词,这就是是值传递和引用传递,总体上函数调用可以分为两类,是根据传递时的过程来区分为:值传递与引用传递。这个值传递和引用传递实际与传递的东西无关。

     

    一般对于值传递和引用传递会有这么几种错误理解:第一种是:Java是引用传递,会理解为Java的形参是对象的引用所以才叫引用传递。问题在于引用传递这个词不是这个意思而是形容调用方式而不是参数本质的类型的。所以即使有人因为明白引用本身也是个值,然后觉得Java其实是值传递了,虽然答案是对的其实这种理解也是错的。这种理解叫“传递的是值”而非“值传递”,在下面会解释这个问题。然后第二种是:值类型是值传递,引用类型用的是引用传递。第三种是:认为所有的都是值传递,因为引用本质上也是个值,本质就是个指针嘛。第四种是:常出现在C++程序员中,声明的参数是引用类型的,就是引用传递;声明的参数是一般类型或指针的就是值传递。也有人把指针归为引用传递,因为它比较特殊,所以归为哪边都不合适。

     

    值传递与引用传递,在计算机领域是专有名词。值传递和引用传递,属于函数调用时参数的求值策略,按值调用表示方法接收的是调用者提供的值,按引用调用表示方法接收的是调用者提供的变量地址,一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值,按...调用(call by)是用来描述各种语言中方法参数的传递方式,这是对调用函数时,求值和传值的方式的描述,而非传递的内容的类型(内容指:是值类型还是引用类型,是值还是指针)。值类型/引用类型,是用于区分两种内存分配方式,值类型在调用栈上分配,引用类型在堆上分配。一个描述内存分配方式,一个描述参数求值策略,两者之间无任何依赖或约束关系。

    所以:

    值传递:方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值。被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

     

    引用传递:方法调用时,实际参数的引用被传递给方法中相对应的形式参数,函数接收的是被引用的内存地址,在方法执行中形参和实参作用等同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。被调函数的形式参数虽然也作为局部变量在堆栈中开辟了引用空间,但是这时已经相当于是主调函数放进来的实参变量的别名。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。所以被调函数对形参做的任何操作都影响了主调函数中的实参变量。就是说此时如果对目标对象进行修改内存中的数据也会改变。

     

    在java中方法参数传递方式是按值传递。如果参数是基本类型,传递的是基本类型的字面量值的拷贝。如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。传值的方式传引用。 或者说传值的方式传地址。

     

    在函数调用过程中,调用方提供实参,这些实参可以是常量:Call(1);也可以是变量:Call(x);也可以是他们的组合:Call(2 * x + 1);也可以是对其它函数的调用:Call(GetNumber());但是所有这些实参的形式,都统称为表达式。求值即是指对这些表达式的简化并求解其值的过程。

     

    求值策略(值传递和引用传递)的关注的点在于,这些表达式在调用函数的过程中,求值的时机、值的形式的选取等问题。求值的时机,可以是在函数调用前,也可以是在函数调用后,由被调用者自己求值。

     

    而且,除了值传递和引用传递,还有一些其它的求值策略。这些求值策略的划分依据是:求值的时机(调用前还是调用中)和值本身的传递方式。

    求值策略求值时间传值方式
    值传递调用前值的结果(是原值的副本)
    引用传递调用前原值(原始对象)
    名传递调用后与值无关的一个名

     

    下表列出了一些二者在行为表象上的区别。

     值传递引用传递
    根本区别会创建副本不创建副本
    所以函数中无法改变原始对象函数中可以改变原始对象

     

    这里的改变是指把一个变量指向另一个对象,而不是指仅仅改变属性或是成员什么的,比如Java,所以说Java是Pass by value,原因是它调用时进行Copy,实参不能指向另一个对象,而不是因为被传递的东西本质上是个Value,这么讲计算机上什么不是Value。

     

    所以这些行为就像在上面提到的与参数类型是值类型还是引用类型无关。对于值传递,无论是值类型还是引用类型,都会在调用栈上创建一个副本,不同的是对于值类型而言,这个副本就是整个原始值的复制。而对于引用类型而言,由于引用类型的实例在堆中,在栈上只有它的一个引用(一般情况下是指针),其副本也只是这个引用的复制,而不是整个原始对象的复制。这便引出了值类型和引用类型的最大区别:值类型用做参数会被复制,但是很多人误以为这个区别是值类型的特性,其实这是值传递带来的效果,和值类型本身没有关系只是最终结果是这样。

     

    求值策略定义的是函数调用时的行为,并不对具体实现方式做要求,但是指针由于其汇编级支持的特性,成为实现引用传递方式的首选。但是纯理论上,你完全可以不用指针,比如用一个全局的参数名到对象地址的HashTable来实现引用传递,只是这样效率太低,所以根本没有哪个编程语言会这样做。所以对于Java的函数调用方式最准确的描述是:参数藉由值传递方式,传递的值是个引用。在字面上与Java总是传值的事实冲突,于是对于Java,Python、Ruby、JavaScript等语言使用的这种求值策略,起了一个更贴切名字,叫Call by sharing即共享传参。

     

    在上面对于传递的参数种类和参数的传递方式进行了分析,现在看一下在传递参数种类的不同前提下,传递参数的过程会有什么变化:

    传值:是把实参的值赋值给行参那么对行参的修改,不会影响实参的值函数参数压栈的是参数的副本,任何的修改是在副本上作用,没有作用在原来的变量上。 

     

    传地址:是传值的一种特殊方式,只是他传递的是引用地址,不是普通的基本类型,那么传地址以后实参和行参都指向同一个对象,但是压栈的是指针变量的副本,当你对指针解指针操作时其值是指向原来的那个变量所以对原来变量操作。

     

    传引用:真正的以引用别名的方式传递参数,传递以后行参和实参都是同一个对象只是他们名字不同而已,对行参的修改将影响实参的值,压栈的是引用别名的副本。由于引用是指向某个变量的,对引用的操作其实就是对他指向的变量的操作。(作用和传指针一样,只是引用少了解指针的草纸)  

     

     

    前面讨论了各种求值策略的内涵。下面以C++的代码为例看一个例子来区分开函数调用的行为和函数传递的值的区别:

     

    #include <iostream>

    using namespace std;

    void ByValue(int a)

    {

    a = a + 1;

    }

     

    void ByRef(int& a)

    {

    a = a + 1;

    }

     

    void ByPointer1(int* a)

    {

    int b=0;

    a = &b;

    }

     

    void ByPointer2(int* a)

    {

    int b=0;

    *a = b;

    }

    int main(int argc, const char * argv[]) {

    int v = 1;

    ByValue(v);

    cout<<v<<endl;

    ByRef(v);

    cout<<v<<endl;

    // Pass by Value

    int *vp = &v;

    ByPointer1(vp);

    cout<<*vp<<endl;

    // Pass by Reference

    ByPointer2(&v);

    cout<<v<<endl;

    return 0;

    }

    Main函数里的前两种方式没有什么好说,第一个是值传递,第二个函数是引用传递,但是后面两种,同一个函数,一次调用是Call by reference, 一次是Call by value。因为:ByPointer(vp)没有改变vp其实是做了一次复制,所以改变的只是复制没有改变vp的指向,而ByPointer(&v)改变了v。你可能认为这传递的其实是v的地址,而ByPointer无法改变v的地址,所以这是Call by value。但是v的地址是个纯数据在调用的方代码中并不存在,对于调用者而言只有v的确被ByPointer函数改了,这个结果,正是Call by reference的行为。从行为考虑,才是求值策略的本意。如果把所有东西都抽象成值,从数据考虑问题,那根本就没有必要引入求值策略的概念去混淆视听。

     

    C语言不支持引用,只支持指针,但是如上文所见,使用指针的函数,不能通过签名明确其求值策略。所以C++引入了引用,它的求值策略可以确定是Pass by reference。于是C++的语言本身支持Call by value和Call by reference两种求值策略,但是却提供了三种语法去做这俩事儿。而C#的设计就相对合理,函数声明里,有ref/out,就是引用传递,没有ref/out,就是值传递,与参数类型无关。

     

    而对于之上的程序就和其他的程序一样运行永远都是在栈中进行的,因而参数传递时,只存在传递基本类型和对象引用的问题。不会直接传对象本身。所以Java在方法调用传递参数时,因为没有指针,所以它都是进行传值调用(这点可以参考C的传值调用)。因此,很多书里面都说Java是进行传值调用,这点没有问题,而且也简化的C中复杂性。但是传引用的错觉是如何造成的呢?在运行栈中,基本类型和引用的处理是一样的都是传值,所以如果是传引用的方法调用,也同时可以理解为“传引用值”的传值调用,即引用的处理跟基本类型是完全一样的。但是当进入被调用方法时,被传递的这个引用的值,被程序解释(或者查找)到堆中的对象,这个时候才对应到真正的对象。如果此时进行修改,修改的是引用对应的对象,而不是引用本身,即:修改的是堆中的数据。所以这个修改是可以保持的了。

     

      Java中程序员无法直接操作指针,对于传值还是传地址很模糊,但我们知道java中变量分为两类,一类是基本变量,一类是引用。其实当我们把实参a,b传进函数后,就相当于把a,b的值分别传给了函数用于接收a,b的局部变量,那么不管是传进去引用还是值,实参a,b的值都不会被改变,因为操作的时函数中接收a,b传递的值的局部变量,函数执行完毕,这两个局部变量也就不存在了。那为什么传进去引用可以修改a,b的值呢,这是不违反我上面说的原理的,传引用相当于把a,b的内存地址传递进函数,函数的局部变量接收了a,b的地址,a,b的引用地址是无法在函数内部被改变的,但是a,b指向的值是可以改变的。

        

    Java中无论传值还是传引用都是传的参数的副本,副本只在函数内部有效。而当传引用时,传进去的是自己副本的地址,地址无法被改变但是地址指向的值可以被改变。所以说java中都可以看做是传值,普通类型参数传递的是参数的值的副本,在函数内部值修改副本,无法对原始数据产生影响,当引用作为参数时,传递的是引用类型的地址,函数内部接收引用的地址的副本,对引用地址所指向的值可以进行修改,但引用的地址是无法修改的,相当于引用地址的值无法修改。String和StringBuffer作为参数为什么不同,相信了解String特性的都知道,String生成实例之后他的值无法修改,如果对它进行修改会产生新的对象,所以String的地址传入函数内部,函数内部对它指向的值进行操作,最终却生成了另外一个对象,而上面所说无法对原String的地址修改,所以对于新生成的String对象无法影响原来的String对象,并且它的生命周期只在函数内部。

     

    在说说当参数类型不同而且参数传递过程也不同的互相混杂情况下的效率问题:

    从传递效率上:这里所说传递效率是调用被调函数的代码将实参传递到被调函数体内的过程。这个效率不能一概而论。对于内建的int  char   short long float等4字节或以下的数据类型而言,实际上传递时也只需要传递1-4个字节,而使用指针传递时在32位cpu中传递的是32位的指针,4个字节,都是一条指令,这种情况下值传递和指针传递的效率是一样的,而传递double  long long等8字节的数据时,在32位cpu中,其传值效率比传递指针要慢,因为8个字节需要2次取完。而在64位的cpu上,传值和传址的效率是一样的。再说引用传递,这个要看编译器具体实现,引用传递最显然的实现方式是使用指针,这种情况下与指针的效率是一样的,而有些情况下编译器是可以优化的,采用直接寻址的方式,这种情况下,效率比传值调用和传址调用都要快,与上面说的采用全局变量方式传递的效率相当。再说自定义的数据类型,class  struct定义的数据类型。这些数据类型在进行传值调用时生成临时对象会执行构造函数,而且当临时对象销毁时会执行析构函数,如果构造函数和析构函数执行的任务比较多,或者传递的对象尺寸比较大,那么传值调用的消耗就比较大。这种情况下,采用传址调用和采用传引用调用的效率大多数下相当,正如上面所说,某些情况下引用传递可能被优化,总体效率稍高于传址调用。

    从执行效率上:这里所说的执行效率,是指在被调用的函数体内执行时的效率。因为传值调用时,当值被传到函数体内,临时对象生成以后,所有的执行任务都是通过直接寻址的方式执行的,而指针和大多数情况下的引用则是以间接寻址的方式执行的,所以实际的执行效率会比传值调用要低。如果函数体内对参数传过来的变量进行操作比较频繁,执行总次数又多的情况下,传址调用和大多数情况下的引用参数传递会造成比较明显的执行效率损失。所以具体的执行效率要结合实际情况,通过比较传递过程的资源消耗和执行函数体消耗之和来选择哪种情况比较合适。而就引用传递和指针传递的效率上比,引用传递的效率始终不低于指针传递,所以从这种意义上讲,在c++中进行参数传递时优先使用引用传递而不是指针。

     

    结合上面的分析,关于值传递和引用传递可以得出这样的结论:

    (1)基本数据类型传值,对形参的修改不会影响实参;

    (2)引用类型传引用,形参和实参指向同一个内存地址(同一个对象),所以对参数的修改会影响到实际的对象;

    (3)String, Integer, Double等immutable的类型特殊处理,可以理解为传值,最后的操作不会修改实参对象。

     

     

    传值:是把实参的值赋值给行参那么对行参的修改,不会影响实参的值函数参数压栈的是参数的副本,任何的修改是在副本上作用,没有作用在原来的变量上。 

     

    传地址:是传值的一种特殊方式,只是他传递的是引用地址,不是普通的基本类型,那么传地址以后实参和行参都指向同一个对象,但是压栈的是指针变量的副本,当你对指针解指针操作时其值是指向原来的那个变量所以对原来变量操作。

     

    传引用:真正的以引用别名的方式传递参数,传递以后行参和实参都是同一个对象只是他们名字不同而已,对行参的修改将影响实参的值,压栈的是引用别名的副本。由于引用是指向某个变量的,对引用的操作其实就是对他指向的变量的操作。(作用和传指针一样,只是引用少了解指针的草纸)  

     

    在最后说几个在参数传递过程中一些共同的有用的技术:

    1. const关键字:当你的参数是作为输入参数时,你总不希望你的输入参数被修改,否则有可能产生逻辑错误,这时可以在声明函数时在参数前加上const关键字,防止在实现时意外修改函数输入,对于使用你的代码的程序员也可以告诉他们这个参数是输入,而不加const关键字的参数也可能是输出。

     

    2. 默认值:给参数添加一个默认值是一个很方便的特性,这样你就可以定义一个具有好几个参数的函数,然后给那些不常用的参数一些默认值,客户代码如果认为那些默认值正是他们想要的,调用函数时只需要填一些必要的实参就行了,这样就省去了重载好几个函数的麻烦。

     

    3.参数顺序。当同个函数名有不同参数时,如果有相同的参数尽量要把参数放在同一位置上,以方便客户端代码。

    展开全文
  • Argument(参量)用来表示“出现在目标(或类型的实例)中的”。 换句话说,Arguments(参量)就是对 Parameters(参数)的具体化。 转载于:https://www.cnblogs.com/zhwl/archive/2011/04/05/2006039.html...

    Parameter(参数)用来表示“出现在子句(或类型定义)头部的变量”,

    Argument(参量)用来表示“出现在目标(或类型的实例)中的值”。

    换句话说,Arguments(参量)就是对 Parameters(参数)的具体化。

    转载于:https://www.cnblogs.com/zhwl/archive/2011/04/05/2006039.html

    展开全文
  • 并根据一定的通信系统参量,利用蒙特卡罗方法模拟了水下目标接收信号的时间空间分布。蒙特卡罗估计误差与平均比值的上限小于0.3%。根据模拟的结果,得出了优化的接收系统采样时隙接收望远镜视场角,进而计算了...
  • 该方法通过增加目标透射光辐射强度的反演过程,同时引入修正参数,对目标透射光辐射强度进行校正,有效避免了传统水下偏振差分成像模型中由全局参量直接反演场景图像造成的图像失真局部灰度为负数的情况。...
  • 目标检测系列(一)——基础内容

    千次阅读 2019-04-03 20:17:37
    目标检测是给定一个图像,找到其中的目标及其位置,并对目标进行分类,目标检测通常是在一组固定的类上进行训练的,所有模型只能定位分类已训练的那些类,而且目标的位置通常都是边界矩阵的形式(包含左上角位置...
  • 迄今为止我都是把 Parameter(参数)用来表示“出现在子句(或类型定义)头部的变量”,而把 Argument(参量)用来表示“出现在目标(或类型的实例)中的”。换句话说,Arguments(参量)就是对 Parameters(参数...
  • 背景:非极大抑制算法(Non-maximum suppression, NMS)的本质是搜索局部极大,抑制非极大元素。在目标检测之中用到非常多。 目的:搞懂此算法原理且看懂代码。 目录 一、算法解析 1.1 算法概览 1.2 算法...
  • 雷达系统 学习笔记(六)——相控阵雷达1

    千次阅读 多人点赞 2018-05-19 12:34:07
    目标在相对于阵轴法线的θ方向上,相邻两振源回波相位差 ψ ψ ψ ,则波程差为 d s i n θ d s i n θ dsinθ ,由波程差引起的相位差为: ψ = 2 π λ d s i n θ ψ = 2 π λ d s i n θ ψ=\frac{2π}{λ...
  • 电磁场边问题求解方法 1、解析方法:规则,经典问题,13个坐标系下可分离变量 2、高频近似算法:PO/GTD/PTD/UTD/ITD/SBR 2.1 散射问题:超电大目标定性电磁散射预估 2.2 辐射问题:已知电流分布计算某场点处电磁场...
  • 卡尔曼滤波matlab程序实现

    千次阅读 多人点赞 2019-08-22 11:12:16
    假定快时刻的温度、测量为23.9摄氏度,房间真实温度为24摄氏度,温度计在该时刻测量为24.5摄氏度,偏差为0.4摄氏度。利用k-1时刻温度测量第k时刻的温度,其预计偏差为: P(k|k-1)=P(k-1)+Q=0.02 卡尔曼增益...
  •  逻辑回归模型分解如下: (1)首先将不同维度的属性值和对应的一组权重加和:  公式如下: z = w0+w1x1+w2x2+...+wm*xm。(其中x1,x2,...,xm是某样本数据的各个特征,维度为m)  ps:这里就是一个线性回归。W...
  • 如果出现这个错误说明你传的参量是超过了一千个;列如,你拼接了1001个id; 如何解决那,我这里提供两种方法: 1.每1000条加一个or in 列: 原:select p.* from t_premium p where p.premium_id in ('0','1'....
  • RANSAC通过反复选择数据中的一组随机子集来达成目标。被选取的子集被假设为局内点,并用下述方法进行验证: [list] [*]有一个模型适应于假设的局内点,即所有的未知参数都能从假设的局内点计算得出。 [*]用1中得到的...
  • 第三篇:激活函数损失函数 在这一章,我们将简要介绍一下激活函数损失函数~ 激活函数 看神经网络中的一个神经元,为了简化,假设该神经元接受三个输入,分别为x1,x2,x3x_1, x_2, x_3x1​,x2​,x3​,那么z=∑...
  • ANSIUNICODE字符串处理常用函数

    千次阅读 2018-05-30 11:22:29
    ANSIUNICODE字符串处理函数 在windows中ANSIUNICODE字符串操作分别提供了相应的函数,也提供了一套兼容两者的函数。比如: #ifdef UNICODE   #define _tcscpy wcscpy  #else   #define _tcscpy strcpy...
  • 神经网络中Epoch、Iteration、Batchsize相关理解说明

    万次阅读 多人点赞 2017-11-21 22:59:49
    微信公众号 看了半年论文,对这三个概念总是模棱两可,不是很清楚。所以呢!我就花了半天时间,收集网上写的很好的关于这三...batch_size将影响到模型的优化程度速度。 为什么需要有Batch_Size: batchsize的正...
  • n+1(包括最外层参量进栈);但是,若每趟排序之后,枢轴位置均偏向子序列的一端,则为最坏情况,栈的最大深度为n。  如果在一趟划分之后比较分割所得两部分的长度,且先对长度短的子序列中的记录进行快速...
  • 然而,在实际工作过程中,由于探测器噪声等因素的影响,平均半径计算与理论存在一定的偏差,从而对校正过程产生影响。对噪声下平均半径的计算误差以及阈值对误差的影响进行了理论仿真分析,结果表明存在最优...
  • 十四、图像直方图 十五、直方图反向投影 十六、模板匹配 十七、图像二化 十八、超大图像二化 十九、高斯金字塔拉普拉斯金字塔 二十、图像梯度 二十一、Canny边缘检测算法
  •  函数 cv::meanShift 在给定反向投影初始搜索窗口位置的情况下,用迭代方法寻找目标中心。当搜索窗口中心的移动小于某个给定时或者函数已经达到最大迭代次数时停止迭代。 函数返回迭代次数。 int mean...
  • YOLO中参数函数说明

    万次阅读 2017-04-01 21:12:20
    YOLO:you only look once中参数函数说明 1、画出的Box:为包围物体的ground truth。 2、lable标签: x y w h,(x,y)是box的位置,w,h是为box的宽度高度是图片的宽度,高度的比值。在生成的lable中是这样的
  • 深度学习图像处理目标检测图像分割计算机视觉 05--深度学习基础摘要一、卷积层二、池化层三、全连接层四、误差反向传播4.1 池化层的误差反向传播4.2 卷积层的误差反向传播五、代码实现六、论文6.1 摘要6.2 论文结构...
  • MATLAB运动目标增强

    2021-08-25 11:53:44
    运动目标的检测跟踪是图像处理技术在视频序列图像处理方面的一个重要应用,在航天、交通、机器人视觉、视频监控、公共场所客流数据监测等场合发挥着重要作用。本文介绍了一种基于MATLAB的简易的从视频播放的帧图像...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,026
精华内容 1,610
关键字:

参量值和目标值