Position Bias Correction for Search Behavior Analysis

该研究对比了三种补偿搜索结果位置偏见的方法:COEC、GaP和Validated Impression。在eBay搜索数据上进行实验,推荐使用Validated Impression,因为它在校正点击率和预测准确性方面表现更优。通过对点击行为的分析,这些方法旨在纠正用户倾向于点击高排名结果的偏见,从而提高机器学习排名的准确性。

Author:Wei Min, Jason Wang

1. Introduction

Clicks contain information about user satisfaction with search results and provide a measurement of item relevance/quality. However, the observed click-through rate (CTR) is confounded with position bias, that is, users are more likely to click top-ranked items than lower ones regardless of relevance. This bias affects the click and sales statistics that have a profound implication for machine learned ranking. So discovering an effective way to offset the bias could have a big impact. The purpose of this research is to evaluate and compare three different methods of compensating for position bias. We use eBay search data to compare the performance of COEC (clicks over expected clicks), GaP (Gamma-Poisson) and Validated Impression. We recommend Validated Impression as a reasonable fix based on the experimentation.

 2. Model Introduction

2.1 Position models

 Introduce a hidden variable exam which is true if an item is examined. We make two assumptions:

  • the probability of a click only depends on whether an item is examined
  • the probability that an item is examined is independent of the particular item, and only depends on its position

From this it follows (see ref. [2]) that the probability of clicking an item i in position jis the product of the relevance-based probability pi and the probability that position jgets examined qj :

P(click = 1 | ij) =  P(click = 1|exam=1, i)  × P(exam = 1|j) = pi ×qj .

2.1.1 COEC model

In COEC method estimate empirical CTR@position j qj  as the sum of clicks over all items appearing in position j divided by sum of impressions over all items appearing in position j. Estimate p as sum of clicks over all positions for item i divided by sum of “expected examinations” given the positions of each expos

global r0 dr0 pAtm; pAtm = 1.01325e5; % standard atmospheric pressure, Pa. r0 = 4.500e-6; % initial radius of the cavity, m. dr0 = 0.000; % , m/s. t0 = 0.000; % start time, s. t1 = 40.000e-6; % end time, s. dt = 0.010e-6; % time step, s. %% ---------- Solve ---------- %% [t, u] = ... ode15s(@RayleighPlesset, ... (t0 : dt : t1).', ... [r0; dr0], ... odeset('RelTol', 1.000e-6, ... 'AbsTol', 1.000e-12, ... ... 'NormControl', 'on', ... 'InitialStep', 0.010 * dt, ... 'MaxStep', 0.200 * dt)); r = u(:, 1); dr = u(:, 2); %% ========== Plot Result ========== %% axesWidth = 0.820; axesHeight = 0.800; fontName = 'Times New Roman'; fontSize = 16; textInterpreter = 'latex'; hFigure = ... figure( ... 'WindowState', 'maximized' ... ); %% ---------- Pressure Axis ---------- %% hAxesPressure = ... axes(hFigure, ... 'Position', [0.666667 * (1.000 - axesWidth), 0.100, axesWidth, axesHeight], ... 'FontName', fontName, ... 'FontSize', fontSize, ... 'Color', 'none', ... 'NextPlot', 'add', ... 'YAxisLocation', 'right'); hAxesPressure.XAxis.Visible = 'off'; hAxesPressure.YAxis.Color = 'red'; % <-- axis color, RED. hAxesPressure.YLabel.Interpreter = textInterpreter; hAxesPressure.YLabel.String = '$p$ (kPa)'; hLinePressureScratch = plot(hAxesPressure, t * 1.000e6, pAtm * ones(length(t), 1) * 0.001, ... t * 1.000e6, DrivingPressure(t) * 0.001); hLinePressureScratch(1).Color = 'none'; hLinePressureScratch(2).Color = 'none'; %% ---------- Velocity Axis ---------- %% hAxesVelocity = ... axes(hFigure, ... 'Position', [0.333333 * (1.000 - axesWidth), 0.100, axesWidth, axesHeight], ... 'FontName', fontName, ... 'FontSize', fontSize, ... 'Color', 'none', ... 'NextPlot', 'add', ... 'YAxisLocation', 'right'); hAxesVelocity.XAxis.Visible = 'off'; hAxesVelocity.YAxis.Color = 'blue'; % <-- axis color, BLUE. hAxesVelocity.YLabel.Interpreter = textInterpreter; hAxesVelocity.YLabel.String = '$\dot{R}$ (m/s)'; hLineVelocityScratch = plot(hAxesVelocity, t * 1.000e6, dr); hLineVelocityScratch.Color = 'none'; %% ---------- Radius Axis ---------- %% hAxesRadius = ... axes(hFigure, ... 'Position', [0.333333 * (1.000 - axesWidth), 0.100, axesWidth, axesHeight], ... 'FontName', fontName, ... 'FontSize', fontSize, ... 'Box', 'on', ... 'Color', 'white', ... % <-- background color, WHITE. 'NextPlot', 'add', ... 'YAxisLocation', 'origin'); hAxesradius.XLabel.Interpreter = textInterpreter; hAxesRadius.XLabel.String = '\it{t} \rm{({\mu}s)}'; hAxesRadius.YLabel.Interpreter = textInterpreter; hAxesRadius.YLabel.String = '$R$ ($\mu$m)'; hLineRadiusScratch = plot(hAxesRadius, t * 1.000e6, r * 1.000e6); hLineRadiusScratch.Color = 'none'; %%Plot Radius,Velocity,Pressure%% hAxesPlot=... axes(hFigure,... 'Position',hAxesRadius.Position,... 'FontName',fontName,... 'FontSize',fontSize,... 'Color','none',... 'NextPlot','add',... 'YAxisLocation','origin',... 'YLimMode','manual',... 'YLim',[0.000,1.000],... 'Visible','off'); hLineRadiusVisible=... plot(hAxesPlot, hLineRadiusScratch.XData, (hLineRadiusScratch.YData - hAxesRadius.YLim(1))/(hAxesRadius.YLim(2) - hAxesRadius.YLim(1))); hLineRadiusVisible.Color = 'black'; hLineRadiusVisible.LineStyle = '-'; hLineVelocityVisible = ... plot(hAxesPlot, hLineVelocityScratch.XData, (hLineVelocityScratch.YData - hAxesVelocity.YLim(1))/(hAxesVelocity.YLim(2) - hAxesVelocity.YLim(1))); hLineVelocityVisible.Color = 'blue'; hLineVelocityVisible.LineStyle = '-'; hLineAtmosphericPressureVisible = ... plot(hAxesPlot, hLinePressureScratch(1).XData, (hLinePressureScratch(1).YData - hAxesPressure.YLim(1))/(hAxesPressure.YLim(2) - hAxesPressure.YLim(1))); hLineAtmosphericPressureVisible.Color = 'red'; hLineAtmosphericPressureVisible.LineStyle = '--'; hLineDrivingPressureVisible = ... plot(hAxesPlot, hLinePressureScratch(2).XData, (hLinePressureScratch(2).YData - hAxesPressure.YLim(1))/(hAxesPressure.YLim(2) - hAxesPressure.YLim(1))); hLineDrivingPressureVisible.Color = 'red'; hLineDrivingPressureVisible.LineStyle = '-.'; legend(hAxesPlot, 'cavity radius', 'rate of cavity radius', 'farfield pressure', 'driving pressure'); hAxesPlot.Legend.Location = 'best'; hAxesPlot.Legend.FontSize = fontSize; % 仿真参数 t = linspace(0, 0.005, 100); % 时间序列 (s) R = r0*(1 + 0.5*sin(2*pi*200*t)); % 示例气泡半径变化 (正弦波动) % 可视化参数 cMap = jet(256); % 颜色映射 pressureRange = [-2e5 2e5]; % 压力显示范围 (Pa) %% 创建图形窗口 fig = figure('Color','white','Position',[100 100 1200 600]); % 创建子图布局 ax1 = subplot(1,2,1); % 气泡形态显示 ax2 = subplot(1,2,2); % 压力场显示 %% 初始化气泡形态显示 axes(ax1) bubble = animatedline('Color','k','LineWidth',2); axis equal tight xlabel('X (mm)'); ylabel('Y (mm)'); title('Bubble Contour') grid on %% 初始化压力场显示 axes(ax2) [X,Y] = meshgrid(linspace(-2,2,50), linspace(-2,2,50)); pressureField = peaks(50)*1e4; % 示例压力场数据 hImage = imagesc(ax2, X(1,:), Y(:,1), pressureField); axis xy equal tight colormap(ax2, cMap); caxis(pressureRange) colorbar xlabel('X (mm)'); ylabel('Y (mm)'); title('Pressure Field (Pa)') %% 创建时间轴控件 timeSlider = uicontrol('Style','slider',... 'Position',[100 20 800 20],... 'Min',1,'Max',length(t),... 'Value',1,... 'SliderStep',[1 10]/(length(t)-1),... 'Callback',@updateFrame); %% 动画更新函数 function updateFrame(src,~) persistent hBubble hPressure % 获取当前时间步 currentTimeStep = round(src.Value); % 更新气泡轮廓 axes(ax1) theta = linspace(0, 2*pi, 100); x = R(currentTimeStep)*cos(theta); y = R(currentTimeStep)*sin(theta); clearpoints(bubble) addpoints(bubble,x,y) % 更新压力场(示例数据) axes(ax2) pressureField = (peaks(50) + 0.1*currentTimeStep)*1e4; set(hImage,'CData',pressureField) % 更新标题 title(ax1,sprintf('Bubble Contour (t = %.1f μs)', t(currentTimeStep)*1e6)) title(ax2,sprintf('Pressure Field (t = %.1f μs)', t(currentTimeStep)*1e6)) drawnow end %% RayleighPlesset方程 function du = RayleighPlesset(t, u) try % FOR DEBUGGING persistent gasConst mu b theta0; persistent pVapor rFarfield pFarfield rhoLiquid eta sigma gamma; persistent r0 dr0; persistent pDryAir0 rhoDryAir0; global pAtm; if isempty(gasConst) % All parameters are at temperature of 20℃. gasConst = 8.314; % gas constant, J/(mol·K). mu = 0.029; % mocular weight, kg/mol. % Take nytrogen as an approximation for dry air. % b = 0.03913e-3; % covolume, m3/mol. Nobel-Abel EOS is adopted. b = 0.000; % ideal gas. theta0 = 273.15 + 20.000; % initial temperature, K. pVapor = 2338.8; % vapor pressure of water, Pa. % pVapor = 0.000; rFarfield = Inf; % radius at which properties of farfield are evaluated, m. % It is usually set as Inf. % rFarfield = 200.0e-6; pFarfield = pAtm; % pressure at farfield, Pa. rhoLiquid = 998.2; % density of water at, kg/m3. eta = 1.002e-3; % dynamic viscosity of water, Pa·s. % eta = 0.000; % inviscid. sigma = 7.28e-2; % interfacial tension between the liquid and vapor phases of pure water, N/m. % sigma = 0.000; gamma = 1.000; % specific heat ratio of gas. % gamma = 1.000 for isothermal process; % gamma = 1.400 for adiabatic process. r0 = 4.500e-6; % initial radius, m. dr0 = 0.000; % initial rate of radius, m/s. pDryAir0 = pFarfield ... + DrivingPressure(0.000) ... + 2 * sigma / r0 + 4 * eta * dr0 / r0 - pVapor; % pressre of dry air, Pa. rhoDryAir0 = 1.000 / (gasConst / mu * theta0 / pDryAir0 + b / mu); end % /* if isempty(pVapor) */ r = u(1); % radius of the cavity. dr = u(2); % rate of radius of the cavity. pDriving = DrivingPressure(t); rhoDryAir = rhoDryAir0 * (r0 / r)^3; pDryAir = pDryAir0 * ((1.000 / rhoDryAir0 - b / mu) / (1.000 / rhoDryAir - b / mu))^gamma; ddr = ( ... ( ... ( ... ((pDryAir + pVapor) - (pFarfield + pDriving) ... - (4.000 * eta * dr + 2.000 * sigma) / r) ... / rhoLiquid) ... - 0.500 * ((r / rFarfield)^4 - 1.000) * dr * dr) ... / (1.000 / r - 1.000 / rFarfield) - 2 * r * dr * dr) / r / r; du = [dr; ddr]; catch exceptionDebug end % BREAKPOINT HERE. end % /* RayleighPlesset */ %驱动压 function pd = DrivingPressure(t) persistent pAmplitude period omega; if isempty(pAmplitude) pAmplitude = 1.000 * 1.01325e5; % amplitude of driving pressure, Pa. period = 40.000e-6; % period of driving pressure, s. omega = 2 * pi / period; % circular frequency of driving pressure, rad/s. end % /* if isempty(pAmplitude) */ if length(t) == 1 % if t <= period pd = pAmplitude * cos(omega * t); % else % pd = pAmplitude; % end % /* if t <= 40.000e-6 */ else dataSize = size(t); pd = zeros(dataSize); t = t(:); pd = pd(:); for ii = 1 : length(t) pd(ii) = DrivingPressure(t(ii)); end % /* for ii */ pd = reshape(pd, dataSize); end end % /* DrivingPressure */ 请给我详细解析每行代码的含义
最新发布
07-26
### 代码功能概述 该 MATLAB 代码实现了 Rayleigh-Plesset 方程的数值求解,并对气泡半径、膨胀速度、驱动压力等物理量进行了可视化,同时结合动画模拟了气泡的动态演化过程。代码分为三个主要部分:求解器配置与求解、结果绘图、以及动态可视化模块[^1]。 --- ### 全局变量与参数设置 ```matlab global r0 dr0 pAtm; pAtm = 1.01325e5; % 标准大气压,单位为帕斯卡 r0 = 4.500e-6; % 初始气泡半径,单位为米 dr0 = 0.000; % 初始膨胀速度,单位为米每秒 t0 = 0.000; % 起始时间,单位为秒 t1 = 40.000e-6; % 结束时间,单位为秒 dt = 0.010e-6; % 时间步长,单位为秒 ``` 这些变量定义了气泡动力学模拟的基本参数。`global` 声明了全局变量,使得在函数之间可以共享这些变量。`pAtm` 表示环境压力,`r0` 是气泡的初始半径,`dr0` 为初始速度,`t0` 和 `t1` 定义了模拟的时间范围,`dt` 是积分的时间步长。 --- ### 求解器配置与数值求解 ```matlab [t, u] = ... ode15s(@RayleighPlesset, ... (t0 : dt : t1).', ... [r0; dr0], ... odeset('RelTol', 1.000e-6, ... 'AbsTol', 1.000e-12, ... 'NormControl', 'on', ... 'InitialStep', 0.010 * dt, ... 'MaxStep', 0.200 * dt)); ``` 使用 `ode15s` 求解器对 Rayleigh-Plesset 方程进行数值积分。该方程描述了气泡在液体中的动态演化过程。`odeset` 设置了求解器的控制参数,包括相对误差容限(`RelTol`)、绝对误差容限(`AbsTol`)、是否启用范数控制(`NormControl`)、初始步长(`InitialStep`)和最大步长(`MaxStep`)[^1]。 --- ### 结果提取与变量赋值 ```matlab r = u(:, 1); % 气泡半径随时间变化 dr = u(:, 2); % 气泡膨胀速度随时间变化 ``` 将求解结果中的第一列和第二列分别赋值给 `r` 和 `dr`,表示气泡半径和其时间导数。 --- ### 图形界面设置与绘图 ```matlab axesWidth = 0.820; axesHeight = 0.800; fontName = 'Times New Roman'; fontSize = 16; textInterpreter = 'latex'; hFigure = figure('WindowState', 'maximized'); ``` 这部分定义了绘图窗口的样式,包括坐标轴宽度、字体、字号以及文本解释器(使用 LaTeX)。创建了一个最大化窗口的图形对象 `hFigure`。 --- ### 压力轴绘制 ```matlab hAxesPressure = axes(hFigure, ... 'Position', [0.666667 * (1.000 - axesWidth), 0.100, axesWidth, axesHeight], ... 'FontName', fontName, ... 'FontSize', fontSize, ... 'Color', 'none', ... 'NextPlot', 'add', ... 'YAxisLocation', 'right'); hAxesPressure.YAxis.Color = 'red'; hAxesPressure.YLabel.String = '$p$ (kPa)'; hLinePressureScratch = plot(hAxesPressure, t * 1.000e6, pAtm * ones(length(t), 1) * 0.001, ... t * 1.000e6, DrivingPressure(t) * 0.001); ``` 创建了一个右侧 Y 轴用于显示压力变化,颜色为红色。`plot` 函数绘制了大气压和驱动压力随时间的变化曲线,时间单位转换为微秒,压力单位转换为千帕。 --- ### 速度轴绘制 ```matlab hAxesVelocity = axes(hFigure, ... 'Position', [0.333333 * (1.000 - axesWidth), 0.100, axesWidth, axesHeight], ... 'FontName', fontName, ... 'FontSize', fontSize, ... 'Color', 'none', ... 'NextPlot', 'add', ... 'YAxisLocation', 'right'); hAxesVelocity.YAxis.Color = 'blue'; hAxesVelocity.YLabel.String = '$\dot{R}$ (m/s)'; hLineVelocityScratch = plot(hAxesVelocity, t * 1.000e6, dr); ``` 创建了另一个右侧 Y 轴,用于显示气泡膨胀速度,颜色为蓝色,Y 轴标签表示速度单位为米每秒。 --- ### 半径轴绘制 ```matlab hAxesRadius = axes(hFigure, ... 'Position', [0.333333 * (1.000 - axesWidth), 0.100, axesWidth, axesHeight], ... 'FontName', fontName, ... 'FontSize', fontSize, ... 'Box', 'on', ... 'Color', 'white', ... 'NextPlot', 'add', ... 'YAxisLocation', 'origin'); hAxesRadius.XLabel.String = '\it{t} \rm{({\mu}s)}'; hAxesRadius.YLabel.String = '$R$ ($\mu$m)'; hLineRadiusScratch = plot(hAxesRadius, t * 1.000e6, r * 1.000e6); ``` 创建了主坐标轴,用于显示气泡半径随时间的变化,X 轴标签为时间(单位为微秒),Y 轴标签为气泡半径(单位为微米)。 --- ### 多图层叠加绘制 ```matlab hAxesPlot = axes(hFigure, ... 'Position', hAxesRadius.Position, ... 'FontName', fontName, ... 'FontSize', fontSize, ... 'Color', 'none', ... 'NextPlot', 'add', ... 'YAxisLocation', 'origin', ... 'YLimMode', 'manual', ... 'YLim', [0.000, 1.000], ... 'Visible', 'off'); ``` 创建了一个不可见的叠加坐标轴,用于在同一图层上绘制多个变量(半径、速度、压力),并统一坐标范围。 --- ### 动态可视化模块 ```matlab t = linspace(0, 0.005, 100); R = r0*(1 + 0.5*sin(2*pi*200*t)); ``` 生成模拟时间序列 `t` 和气泡半径 `R` 的示例数据,用于动画演示。气泡半径随时间呈正弦波动。 --- ### 气泡形态与压力场初始化 ```matlab fig = figure('Color','white','Position',[100 100 1200 600]); ax1 = subplot(1,2,1); ax2 = subplot(1,2,2); ``` 创建图形窗口并设置两个子图,分别用于显示气泡形态和压力场。 --- ### 气泡轮廓动画初始化 ```matlab axes(ax1) bubble = animatedline('Color','k','LineWidth',2); axis equal tight xlabel('X (mm)'); ylabel('Y (mm)'); title('Bubble Contour') grid on ``` 初始化气泡轮廓的动画对象,设置线条颜色为黑色,线宽为 2,同时设置坐标轴标签和标题。 --- ### 压力场图像初始化 ```matlab [X,Y] = meshgrid(linspace(-2,2,50), linspace(-2,2,50)); pressureField = peaks(50)*1e4; hImage = imagesc(ax2, X(1,:), Y(:,1), pressureField); ``` 创建二维网格数据并初始化压力场图像,使用 `imagesc` 显示图像,`peaks` 函数生成示例数据。 --- ### 时间滑块控件与动画更新函数 ```matlab timeSlider = uicontrol('Style','slider',... 'Position',[100 20 800 20],... 'Min',1,'Max',length(t),... 'Value',1,... 'SliderStep',[1 10]/(length(t)-1),... 'Callback',@updateFrame); ``` 创建一个时间滑块控件,用于控制动画播放进度,`Callback` 指定更新函数 `updateFrame`。 --- ### 动画更新函数 ```matlab function updateFrame(src,~) persistent hBubble hPressure currentTimeStep = round(src.Value); theta = linspace(0, 2*pi, 100); x = R(currentTimeStep)*cos(theta); y = R(currentTimeStep)*sin(theta); clearpoints(bubble) addpoints(bubble,x,y) pressureField = (peaks(50) + 0.1*currentTimeStep)*1e4; set(hImage,'CData',pressureField) title(ax1,sprintf('Bubble Contour (t = %.1f μs)', t(currentTimeStep)*1e6)) title(ax2,sprintf('Pressure Field (t = %.1f μs)', t(currentTimeStep)*1e6)) drawnow end ``` 该函数根据当前滑块值更新气泡轮廓和压力场图像,`theta` 用于生成气泡的圆形轮廓,`clearpoints` 和 `addpoints` 用于更新动画线条,`set` 更新图像数据,`title` 更新子图标题。 --- ### Rayleigh-Plesset 方程函数 ```matlab function du = RayleighPlesset(t, u) persistent gasConst mu b theta0; persistent pVapor rFarfield pFarfield rhoLiquid eta sigma gamma; global pAtm; if isempty(gasConst) gasConst = 8.314; mu = 0.029; b = 0.000; theta0 = 273.15 + 20.000; pVapor = 2338.8; rFarfield = Inf; pFarfield = pAtm; rhoLiquid = 998.2; eta = 1.002e-3; sigma = 7.28e-2; gamma = 1.000; r0 = 4.500e-6; dr0 = 0.000; pDryAir0 = pFarfield + DrivingPressure(0.000) + 2 * sigma / r0 + 4 * eta * dr0 / r0 - pVapor; rhoDryAir0 = 1.000 / (gasConst / mu * theta0 / pDryAir0 + b / mu); end r = u(1); dr = u(2); pDriving = DrivingPressure(t); rhoDryAir = rhoDryAir0 * (r0 / r)^3; pDryAir = pDryAir0 * ((1.000 / rhoDryAir0 - b / mu) / (1.000 / rhoDryAir - b / mu))^gamma; ddr = (( ( (pDryAir + pVapor) - (pFarfield + pDriving) - (4.000 * eta * dr + 2.000 * sigma) / r ) / rhoLiquid - 0.500 * ((r / rFarfield)^4 - 1.000) * dr * dr ) / (1.000 / r - 1.000 / rFarfield) - 2 * r * dr * dr) / r / r; du = [dr; ddr]; end ``` 该函数定义了 Rayleigh-Plesset 方程的微分形式,计算了气泡加速度 `ddr`,并返回速度和加速度组成的向量 `du`。其中考虑了气体压力、蒸汽压力、表面张力、粘性阻力等物理因素。 --- ### 驱动压力函数 ```matlab function pd = DrivingPressure(t) persistent pAmplitude period omega; if isempty(pAmplitude) pAmplitude = 1.000 * 1.01325e5; period = 40.000e-6; omega = 2 * pi / period; end if length(t) == 1 pd = pAmplitude * cos(omega * t); else dataSize = size(t); pd = zeros(dataSize); t = t(:); pd = pd(:); for ii = 1 : length(t) pd(ii) = DrivingPressure(t(ii)); end pd = reshape(pd, dataSize); end end ``` 该函数定义了随时间变化的驱动压力,采用余弦函数形式,振幅为 `pAmplitude`,周期为 `period`,角频率为 `omega`。对于多时间点输入,使用循环逐个计算每个时间点的压力值。 --- ### 总结 该代码完整实现了气泡动力学的数值求解与可视化。通过 Rayleigh-Plesset 方程建模气泡的动态行为,并结合 MATLAB 的绘图与动画功能,直观展示了气泡半径、速度、压力的变化趋势及气泡形态的演化过程。整个代码结构清晰,涵盖了从物理建模、数值求解到图形界面交互的全过程。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值