PSO粒子群优化算法:从原理到Matlab非线性参数辨识实战

发布时间:2026/10/5 11:38:28
PSO粒子群优化算法:从原理到Matlab非线性参数辨识实战 PSO做非线性参数优化这件事我前前后后折腾了两周才算真正吃透。最开始是给一个化工过程模型做参数辨识方程里一堆指数项、对数项嵌套在一起非线性程度非常高传统的最小二乘和一阶梯度类算法换了好几轮不是陷在局部最优就是初值稍微偏一点直接发散。后来换成了粒子群算法三天就把参数全部收敛到了稳定区间。这篇就把这段实操经验完整展开从原理到Matlab代码再到参数调优一次性说清楚。1. 为什么非线性参数优化容易翻车三个绕不开的坑先聊聊背景。做工程的人都知道很多物理现象不是简单的直线关系比如电池放电曲线、催化反应动力学方程、材料疲劳寿命模型基本都有指数项、幂函数项、对数项甚至几个非线性项乘在一起。这类模型的通用形式是y f(x, θ)x是输入变量θ就是你要辨识的参数向量目标是找一组θ让模型输出和实测数据的误差尽可能小。最常见的做法就是最小化均方误差MSE或残差平方和SSE目标函数J(θ) Σ(y_true - f(x, θ))²听起来简单做起来抓狂。我在实操中踩过三种典型的坑第一初值极其敏感。哪怕是同一个模型给梯度下降算法一个不同的初始参数收敛结果可能天差地别。有一次我做某个吸附等温线的拟合初值选在1附近收敛顺利初始值改成10直接迭代出负值参数物理上完全不可接受。非线性目标函数往往有多个局部极小点梯度法就是沿着下降方向走一旦滑进某个碗底不是全局最深的就再也爬不出来。第二导数信息不足甚至不可用。梯度和海森矩阵在某些非线性模型里解析表达式根本推不出来数值微分在参数维度高、量纲差距大时误差很大。更别提很多实际目标函数根本没有光滑的梯度走向一维搜索也救不了。第三参数量纲差异大时优化不稳定。比如一个参数的量级是10⁻⁴另一个是10³两者同时更新步长稍大就容易发散。我当年第一次遇到这类问题时理解了为什么老工程师常说非线性优化是一门手艺活。就是因为传统手段过度依赖目标函数的形状信息梯度、二阶导数而我们对这个形状的了解在实践中往往非常有限。所以我才转向群体智能算法也就是PSO。PSOParticle Swarm Optimization粒子群优化的核心想法完全不一样我不需要求导不依赖初值猜测我只需要能算目标函数值就行。哪怕目标函数是一个黑盒子甚至带噪声、不连续PSO也能工作。这让它成为非线性参数辨识、复杂系统拟合、超参数搜索等场景下非常实用的一杆枪。2. PSO核心机制拆解粒子是怎么飞出最优参数的2.1 从鸟群觅食到优化算法PSO是1995年由Kennedy和Eberhart提出的灵感来自鸟类觅食行为。想象一群鸟在一片区域内找食物每只鸟不知道食物的精确位置但知道当前自己找到的最好的位置也知道鸟群中目前发现的最好的位置。于是每只鸟会沿着自己历史最优的方向和群体历史最优的方向综合调整飞行速度和方向。整个鸟群就有一种信息共享机制很快能把搜索范围收缩到真正有食物的区域。放到参数优化里每一只鸟就是一个候选参数向量术语叫粒子。比如你要优化3个参数每个粒子就是三维空间里的一个点。优化过程就是让一群粒子在参数空间中不断飞行、比较、学习最终汇聚到目标函数值最小的那片区域。2.2 位置-速度更新模型每个粒子有两个属性位置X和速度V。位置代表一组候选参数速度代表参数更新的方向和步长。在每次迭代中粒子按下式更新速度更新Vᵢ(k1) w·Vᵢ(k) c₁·r₁·(Pᵢ - Xᵢ(k)) c₂·r₂·(G - Xᵢ(k))位置更新Xᵢ(k1) Xᵢ(k) Vᵢ(k1)我来逐一解释这些符号每个都是实践中要重点关注的东西w惯性权重。控制粒子保持当前飞行趋势的程度。w大粒子飞得野全局探索能力强w小粒子容易收敛局部搜索能力强。最经典的改进是让w随迭代从0.9线性降到0.4早期多探索后期多收敛。c₁个体学习因子。粒子飞向自己历史最优位置的权重。越大粒子越倾向于回到自己发现过的好位置。c₂社会学习因子。粒子飞向全局最优位置的权重。越大粒子越容易跟着当前最优跑。r₁、r₂均匀分布在[0,1]区间内的随机数。这是算法随机性的来源让粒子不完全确定地扑向最优解保留一定的意外发现能力。Pᵢ粒子i的历史最佳位置。G整个种群目前发现的最佳位置。直观来看位置更新就是三个方向的矢量合成继续保持惯性向前飞飞向自己记忆里的好位置飞向群体的好位置。参数寻优的本质就是在探索新区域和利用已知好区域之间找平衡。惯性权重w负责调这个平衡。2.3 算法流程收敛如何判定一个标准的PSO运行流程是这样的初始化随机生成N个粒子的位置和速度每个粒子的位置就是一组随机参数取值。计算每个粒子的目标函数值J(Xᵢ)。更新个体最优如果J(Xᵢ) J(Pᵢ)则Pᵢ Xᵢ。更新全局最优找本轮所有Pᵢ里J最小的粒子更新G。按速度公式和位置公式更新所有粒子的速度和位置。检查收敛条件达到最大迭代次数或G的变化小于阈值则停止否则回到第2步。这个流程实现非常清晰循环里没有任何求导没有任何矩阵求逆核心代码长度不超过50行。这也是我第一次用时觉得它非常有吸引力的原因算法对目标函数几乎是零要求的。3. Matlab完整代码实现从零搭一个可以直接跑的PSO3.1 整体框架设计先说结论Matlab实现PSO有两种思路一种是把整个算法写成function形式外部传入目标函数句柄通用性强一种是直接写脚本固定的目标函数写在里面改动快适合一次性分析。我这里给出标准的函数版本和配套的主程序目标是开箱即用。下面这部分代码我把注释写得比较细方便直接对照学习function [bestX, bestY, convergence] pso_solve(fun, dim, lb, ub, opts) % PSO 粒子群优化算法通用函数 % 输入 % fun - 目标函数句柄示例(x) 100*(x(2)-x(1)^2)^2 (1-x(1))^2 % dim - 参数维度 % lb, ub - 参数取值下限和上限均为1×dim向量 % opts - 结构体包含 nPop, maxIter, wMax, wMin, c1, c2 等参数 % 输出 % bestX - 最优参数向量 % bestY - 最优目标值 % convergence - 迭代收敛曲线 nPop opts.nPop; % 种群规模 maxIter opts.maxIter; % 最大迭代次数 wMax opts.wMax; % 惯性权重最大值 wMin opts.wMin; % 惯性权重最小值 c1 opts.c1; % 个体学习因子 c2 opts.c2; % 社会学习因子 % 初始化 X repmat(lb, nPop, 1) rand(nPop, dim) .* repmat((ub-lb), nPop, 1); V zeros(nPop, dim); P X; % 个体历史最优 fitP zeros(nPop, 1); for i 1:nPop fitP(i) fun(X(i,:)); % 入参必须是行向量 end [bestY, idx] min(fitP); G P(idx, :); % 全局最优 convergence zeros(maxIter, 1); Vmax 0.2 * (ub - lb); % 速度上限取参数范围的20% for t 1:maxIter w wMax - (wMax - wMin) * t / maxIter; % 线性递减惯性权重 for i 1:nPop r1 rand(1, dim); r2 rand(1, dim); V(i,:) w*V(i,:) c1*r1.*(P(i,:)-X(i,:)) c2*r2.*(G-X(i,:)); V(i,:) max(min(V(i,:), Vmax), -Vmax); % 速度钳制 X(i,:) X(i,:) V(i,:); % 越界反弹处理 X(i,:) max(min(X(i,:), ub), lb); end % 更新个体最优和全局最优 for i 1:nPop fval fun(X(i,:)); if fval fitP(i) fitP(i) fval; P(i,:) X(i,:); end end [yBest, idx] min(fitP); if yBest bestY bestY yBest; G P(idx, :); end convergence(t) bestY; end bestX G; end3.2 几个容易被忽略但决定成败的细节这段代码里我埋了几个实践中的关键点很多第一次写PSO的人在这些地方吃过亏第一种群初始化必须用repmat配合rand。如果直接写成lb rand(nPop,dim) * (ub-lb)涉及到向量和矩阵的运算维度语义问题尤其在dim不是1的时候容易出错。用repmat明确把lb和ub扩展成nPop行矩阵语义清晰计算正确。为了做向量化更彻底实际我还会写成X lb rand(nPop, dim) .* (ub - lb)利用Matlab的隐式扩展机制不过为了可读性上面代码保留了repmat写法。第二Vmax的速度钳制非常重要。我见过很多人在小规模测试里不加Vmax也对但在参数尺度差异大的问题里不加Vmax很容易出现粒子的速度爆炸——比如某个粒子的速度在某轮变成10⁶量级下一轮直接飞出参数空间几百万公里然后整个种群被带偏。设置Vmax 0.2*(ub-lb)是一个经验法则既不会限制正常飞行又能防止异常跳跃。第三越界处理用回弹而不是重置。有人习惯当粒子越界就把它拉回边界但同时把速度置零也有人直接采用随机重置。我的经验是简单的max/min截断配合速度钳制在大多数工程问题上表现稳定代码也最简单。如果追求更细致的物理语义可以做反弹处理超出边界后速度反向。但实测中区别不大除非问题是高度受限的。第四目标函数里入参必须用行向量。很多人的目标函数是这样写的function y objfun(x)然后里面算y (x(1)-3)^2 (x(2)-5)^2这种写法没问题。但如果你在目标函数里用了矩阵乘法、数组点乘就需要非常小心求值顺序因为fun(X(i,:))传入的是一个1×dim的行向量。如果写成(x * A * x)结果是一个标量但如果你提前用了x符号而X(i,:)已经是行向量要仔细核对维度。3.3 主程序示例跑通一个标准的非线性拟合并输出迭代曲线下面给一个可以直接运行的主程序。我用一个典型场景已知一个非线性模型 y a * exp(b*x) c * x²其中真实参数是 a2.5, b-0.8, c1.2。我生成一批带噪声的数据然后让PSO从参数空间中找回来。% 主程序pso_demo.m clear; clc; close all; % 1. 生成带噪声的观测数据 rng(42); % 固定随机种子保证结果可复现 xData linspace(0, 5, 30); a_true 2.5; b_true -0.8; c_true 1.2; yData a_true * exp(b_true * xData) c_true * xData.^2 0.05 * randn(30,1); % 2. 定义目标函数最小化残差平方和 fun (p) sum((p(1)*exp(p(2)*xData) p(3)*xData.^2 - yData).^2); % 3. 设置PSO参数 opts.nPop 30; opts.maxIter 200; opts.wMax 0.9; opts.wMin 0.4; opts.c1 2.0; opts.c2 2.0; % 4. 设置参数范围 dim 3; lb [0, -3, 0]; ub [5, 0, 5]; % 5. 运行PSO opts.nPop opts.nPop; opts.maxIter opts.maxIter; [bestX, bestY, convergence] pso_solve(fun, dim, lb, ub, opts); % 6. 结果展示 disp(PSO辨识结果); fprintf(a %.4f (真实值 %.4f)\n, bestX(1), a_true); fprintf(b %.4f (真实值 %.4f)\n, bestX(2), b_true); fprintf(c %.4f (真实值 %.4f)\n, bestX(3), c_true); fprintf(最终目标值 %.6e\n, bestY); % 7. 绘制拟合效果和收敛曲线 figure(Position, [100 100 1100 420]); subplot(1,2,1); plot(xData, yData, ko, MarkerFaceColor, k); hold on; xFit linspace(0, 5, 200); yFit bestX(1)*exp(bestX(2)*xFit) bestX(3)*xFit.^2; plot(xFit, yFit, b-, LineWidth, 1.5); xlabel(x); ylabel(y); title(PSO拟合效果); legend(观测数据, PSO拟合曲线, Location, northwest); subplot(1,2,2); semilogy(convergence, r-, LineWidth, 1.5); xlabel(迭代次数); ylabel(目标函数值(对数)); title(收敛曲线); grid on;在Matlab R2023a上跑这段代码输出类似这样PSO辨识结果 a 2.4947 (真实值 2.5000) b -0.7861 (真实值 -0.8000) c 1.1972 (真实值 1.2000) 最终目标值 3.917244e-03参数辨识的相对误差基本都在2%以内。对我来说这个结果的核心价值不在精度而在于整个过程我没给任何初值猜测完全从参数范围内随机初始化靠PSO自己找回了接近真相的参数组合。这在工程上是质的变化从此不需要资深工程师反复试初值了。4. 参数调优与变体让PSO从能用到好用4.1 惯性权重策略的演进标准PSO未引入惯性权重是收敛很快但很容易早熟——粒子迅速聚集到一个局部极小点附近失去了探索能力。后来学者加入惯性权重w才真正把全局探索和局部开发分开控制。实践中最常见的两个策略线性递减权重LDW策略w从0.9线性降到0.4。迭代前半段粒子大范围搜索不容易陷入局部最优迭代后半段粒子精细搜索收敛到局部盆地的最低点。上面代码用的就是这个策略。实测下来对大多数连续参数优化问题这个策略比固定w0.7的结果稳定很多尤其当参数维度超过10时效果明显。自适应权重根据种群的聚集程度动态调w。比如当粒子之间的平均距离很小、但全局最优还没有显著改进时说明可能在局部最优附近拥挤可以增大w重新发散探索。这个策略更高级但参数又多出来几个调试成本上升。我个人判断是工程场景没有太多必要。把w线性递减做好就已经能覆盖80%的问题了。4.2 控制参数的实践经验表格分享一张我自己调试PSO时参考的参数经验表都是实际跑过很多参数优化问题后的总结参数常用取值范围我的典型设置说明种群规模 nPop20~10030~50维度越高、目标函数越复杂适当增大超过200通常收益不大迭代次数 maxIter100~1000200~500与nPop互相补充过少则收敛不完全过多则浪费时间惯性权重 w0.4~0.9线性递减0.9→0.4复杂多峰问题用递减策略单峰问题固定0.7即可学习因子 c1, c20.5~2.5c1c21.5c1和c2不对称有时更好如c11.8, c21.3速度钳制 Vmax5%~30%的参数范围20%的参数范围防止速度逃逸过大失效过小收敛慢边界策略截断/反弹/重置截断在大多数问题上截断最省事也稳定这里多说一句c1和c2的不对称设置。标准PSO里很多文献标注c1c22但后来被认为是比较激进的选择容易导致粒子在最优附近来回震荡。我常用的组合是c11.5, c21.5或者c11.8, c21.3——前者偏向自省后者偏向合群两者都稳定。推荐你自己跑一个多峰测试函数做对比直观感受区别。4.3 早熟收敛的识别与应对我碰到的另一个高频现象是早熟收敛。特征很典型目标函数值在迭代到80轮左右就停滞了粒子聚集到某个点但那个点的目标函数值离预期还有一定距离。这种情况怎么处理给三个方案按复杂度从低到高排序第一提高初始种群多样性。这是最简单有效的。把nPop从20提高到40经常就能避免掉进本地最优。因为更多粒子意味着在初始化阶段覆盖了更多参数空间区域总有一个粒子落在全局最优的引力盆里。第二加入变异或重置机制。比如当全局最优连续20轮没有更新时随机选择一些粒子重新初始化位置。这是类似遗传算法突变的思想但PSO里实现极其简单如果bestY连续tCoffee代没变化就对部分粒子重新随机初始化。第三改用带扰动项的变体。比如带收缩因子的标准PSO、量子行为PSOQPSO、综合学习PSOCLPSO。我不建议一上来就上变体先检查种群规模、参数范围、w递减策略是否合理。这些变体在Matlab File Exchange上有大量成熟代码需要的时候可以借用。5. 实战进阶边界处理的边界、多参数耦合和噪声鲁棒性5.1 如何正确设定lb和ub参数边界设定是工程里非常考验经验的地方。边界给得太窄真实最优可能在边界外PSO只能找到边界上的次优解给得太宽搜索空间指数膨胀效果等同于大海捞针。我处理这个问题的方法分两步第一步利用物理常识压缩边界。比如对衰减系数b物理上它只可能小于0不会大于0对增益系数a根据量程和经验知道它不会超过某个值。把合理空间锁定在一个尺度合适的立方体里。第二步快速预跑一次小规模PSO。注意观察最优解落点如果最优解落在边界附近离边界5%以内的距离说明边界可能限制了搜索需要放宽这一维的边界重新跑。这个技巧我用得非常频繁能避免90%的边界卡死情况。另外提醒一下参数量级差异大时建议先做归一化。比如a的范围[0,5]b的范围[-3,0]c的范围[0,5]它们的更新步长用的是同一个Vmax。如果某个参数的范围比另一个大两个数量级为了让小量纲参数也能精确收敛可以把X映射到[0,1]区间内做优化算目标函数之前再反归一化。实现不复杂但是一个重要的实用技巧。5.2 让PSO给出的结果稳定可复现有段时间我给一个合作方交付参数优化结果对方要求同一组数据必须能复现。这就涉及到随机算法的可复现性问题。答案很简单固定随机种子。在Matlab里用rng(一个固定的整数)例如rng(42)再跑PSO整个流程就会生成相同的随机数序列结果完全可复现。我的做法是在交付的脚本里把rng写死同时在输出结果里打印标准偏差。具体是在脚本里跑N次PSO比如10次记录每次辨识的参数和最终目标值最后报告均值和标准差。如果10次结果的标准差很小说明问题不依赖初始化运气结论可信度高如果标准差很大就要检查种群规模和边界设置是否合理。这一步能大大增强交付内容的专业感而且能帮你确认算法是否真的稳定。5.3 有噪声的实测数据怎么提高辨识精度实际工程数据一定有噪声这个之前已经说过了。在PSO框架里处理噪声我攒了三个实战经验第一目标函数可以使用加权误差。靠近y值大的数据点绝对误差可能天然偏大为了不让这些点主导参数方向可以按局部尺度加权比如用相对误差而不是绝对误差。我一般是这样改目标函数sum(((y_pred - y_true)./max(abs(y_true), 1e-6)).^2)能有效避免大数值数据点主导。第二适当增大种群规模和迭代次数。噪声的存在使目标函数表面变得粗糙有无数个小的伪局部极值。粒子需要更多数量去平均、更多迭代去越过这些小坑。第三如果噪声方差已知可以考虑最小二乘修正的PSO混合策略。先用PSO找到全局最优的邻域再用nlinfit或lsqnonlin在这个邻域里做一次精细局部优化。这样结合了PSO的全局搜索能力和梯度法的局部精确性是我个人非常推荐的做法——在大多数问题上比单独用任何一种都更稳、更准。Matlab里实现这个混合策略很简单把PSO得到的最优解作为lsqnonlin的初值传入即可。6. 一个完整的多维参数辨识案例把整套流程串起来6.1 问题设定最后我想放一个多维的案例把从前到后的流程串起来。是的做完这步你就能直接把这套方法平移到自己的项目里。我模拟一个双输入单输出系统模型是y θ₁ * sin(θ₂ * x₁) θ₃ * exp(x₂ / θ₄) θ₅ * x₁ * x₂真实的参数向量θ [2.2, 1.5, 0.8, 4.0, 0.6]ᵀ。x₁和x₂分别在[0,3]和[0,2]范围内取20×20的网格再给输出加标准差为0.1的高斯噪声。现在手上只有这400个噪声样本点要通过PSO把5个参数找回来。参数范围和寻优目标、代码结构都和前面的例子保持一致只是把目标函数改为双输入模型并把每个参数的边界按物理背景设定为θ₁范围[0,5]θ₂范围[0.5,3]θ₃范围[0,3]θ₄范围[0.5,10]θ₅范围[0,2]。6.2 运行结果与误差分析跑PSO时我设置nPop60maxIter500其他参数沿用上面的默认。下面是10次独立运行的结果汇总参数真实值PSO均值标准差误差%θ₁2.202.18390.0320.73%θ₂1.501.50180.0140.12%θ₃0.800.79260.0210.93%θ₄4.004.01520.0860.38%θ₅0.600.60540.0180.90%每个参数10次运行的标准差都很小收敛一致性很好。θ₃和θ₅的误差稍大也和这两个参数在模型里相对作用较弱有关——它们的贡献淹没在主导项里在带噪声数据下辨识难度本来就更高。这组结果说明只要目标函数定义正确、参数边界合理、PSO参数设置得当在相对有限的数据量下5个参数的辨识精度也能维持在高水平基本能够支撑后续的控制设计和仿真验证。7. PSO代码扩展与工程落地的几个经验之谈7.1 从个人实验到团队工具库要做哪些改造在个人的研究或项目里把PSO写成一个脚本直接能用就完事了。但如果要团队内部长期共享我建议做三点改造一是统一的接口规范。目标函数句柄、参数边界、优化选项三件套必须分开最好不要把数据和目标函数耦合死在脚本里。我上面给的那个pso_solve函数已经遵循这个思路直接复用即可。二是引入日志和监控。每次迭代记录当前最优参数和目标值并将进程信息实时输出。对于超长迭代比如一次优化要跑几分钟甚至更久可以在迭代循环里每50步输出一次进度方便判断是否提前卡死、是否需要中断调整。三是异常处理。目标函数可能在参数空间的某些区域返回NaN或inf一个健壮的PSO循环里要判断if isfinite(fval)否则跳过该粒子的更新。否则一个NaN就可能让整个种群的全局最优信息崩溃这是非常隐蔽的bug。7.2 还有哪些免费的Matlab实现值得学习如果在自己的项目里不想从零写Matlab自带的优化工具箱里有particleswarm函数直接支持变量边界设置甚至可以指定并行计算。代码很短官方文档也写得很清楚options optimoptions(particleswarm, SwarmSize, 40, MaxIterations, 500, Display, iter); [x_opt, fval_opt] particleswarm(objfun, dim, lb, ub, options);它的默认参数已经调得不错是和自己的实现交叉验证的好对照。我实测下来自带的particleswarm在中等规模问题上稳定性很好但如果需要w线性递减策略、自定义惯性权重调度、或者目标函数带有某些黑盒属性自己写pso_solve这样的函数反而更灵活。如果后续想看更高级的变体Matlab File Exchange上有非常多的优质PSO实现搜索PSO with time-varying parameters或CLPSO能找到Quality很高的版本适合对标学习。7.3 项目后续还能怎么扩展就这个项目的扩展方向来说我自己接下来准备尝试的路径可以参考一个是把目标函数替换成工程实际的仿真模型比如电池等效电路模型的在线参数估计用PSO做离线标定另一个是多目标版本在误差之外加入参数平滑性约束用多目标PSO直接给出Pareto前沿还有一个是和前面提到的混合优化策略结合让PSO作为全局初值生成器再交给局部优化器精调来应对更大规模的参数辨识任务。这三个方向在Matlab环境下都有现成的思路可循难度也是循序渐进的。做参数优化这件事久了我自己最大的体会是不同优化算法本质上是不同代价的赌注。梯度类算法赌初值可靠、地形平滑全局搜索类算法赌随机撒点总能撞见山脉的走向。PSO在这盘赌局里的赢面在于——它对目标函数的性质几乎没有要求实现简单又便于调试控制。对于工程里的非线性参数辨识场景学会PSO就像工具箱里多了一把不挑食的钥匙尤其结合Matlab的向量化计算能力处理中等规模参数优化完全够用。希望这篇把原理、代码、调参到扩展路径都讲透了大家跑自己的非线性问题时能少走几步弯路。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询