banner
二階堂春希

春希のブログ

山雨欲来风满楼,故攻八面以铸无双。 孤战非所望,俗安不可期。
tg_channel
telegram
twitter
github

機場用戶選擇套餐的數學建模

前段時間,有個機場主找到我,希望我提供數學上的幫助,幫助他們計算用戶會選擇什麼套餐。我回覆,需要必要的數據來建立數學模型。但他們拒絕給我提供數據,可能原因是沒有收集或者脫敏麻煩。

於是,經過協商,我為他們建立不需要數據、且可以根據數據調整的模型,並且順帶給出一些降低成本的方案;他們給我更高的報酬。

儘管我強烈懷疑他們能夠通過這個模型獲得到的利潤需要多久才能填補聘用我的費用,但我還是給了他們做。並且,他們允許我把這個模型部分開源出來。

他們的機場用的是 PHP,但我為了方便計算,用的是 pytorch,我想他們似乎還需要找個會 Python 的來跑起來這個模型。

模型參數#

假設用戶的預算服從的分布的概率密度函數為b(x1)b(x_1),流量需求服從的分布的概率密度函數為t(x2)t(x_2),節點質量需求服從的概率密度函數為q(x3)q(x_3)

假設用戶對以上 3 種因素側重比例的概率密度函數為a(y1,y2)a(y_1,y_2),定義為:

  • y1(0,1)y_1\in(0,1),y2(0,1)y_2\in(0,1)y1+y2<1y_1+y_2<1,否則a(y1,y2)=0a(y_1,y_2)=0
  • y1y_1為預算的權重,y2y_2為流量的權重,1y1y21-y_1-y_2為質量的權重

每種套餐都有價格、流量、質量 3 個屬性。假設當用戶思考買哪一種套餐時,會按照層次分析法決策。上述 bb, tt, qq 的參數需要參數估計。

P=(pr1,pr2,pr3,,prn)P=(p_{r1},p_{r2},p_{r3},\cdots,p_{rn})', T=(t1,t2,t3,,tn)T=(t_1,t_2,t_3,\cdots,t_n)', Q=(q1,q2,q3,,qn)Q=(q_1,q_2,q_3,\cdots,q_n)' 為產品數組向量,分別為產品的價格、流量、質量。產品數組向量由產品性質決定,不需要參數估計。

import torch

# 定義套餐的價格、流量、質量
packageNumber = 3
packagePrice = [1, 2, 3]
packageTrafficLimit = [1, 2, 3]
packageQuality = [1, 2, 3]

層次分析法量化#

對於預算的滿意度,可以定義為f(pr,x1)=10prx1f(p_r,x_1)=10^{-\frac{p_r}{x_1}},其中prp_r為套餐價格,x1x_1為預算

對於流量的滿意度,可以定義為g(t,x2)=4tx234g(t,x_2)=\sqrt{\displaystyle\frac{4t}{x_2}-\frac{3}{4}}(當根號下為 0 以下時定義為 0),其中tt為套餐流量,x2x_2為套餐需求

對於節點質量的滿意度,可以定義為h(q,x3)=qx33h(q,x_3)=\sqrt[3]{\displaystyle\frac{q}{x_3}},其中qq為節點質量量化指標,x3x_3為節點質量需求。

用戶會選擇滿意度

y110prx1+y24tx234+y3qx33y_1\cdot10^{\displaystyle-\frac{p_r}{x_1}}+y_2\sqrt{\displaystyle\frac{4t}{x_2}-\frac{3}{4}} + y_3\sqrt[3]{\displaystyle\frac{q}{x_3}}

最大的套餐

並且,如果對套餐的滿意度都小於 0.1,那麼他將不會選擇這個套餐。

寫成向量形式,則有:

SATISFY=[f(P,x1),g(T,x2),h(Q,x3)]Y\text{SATISFY} = [f(P,x_1),g(T,x_2),h(Q,x_3)]'Y
SELECT={maxSATISFYPACKAGE, SATISFY>0.1, SATISFY0.1SELECT=\begin{cases} \max_{\text{SATISFY}} \text{PACKAGE},\ \text{SATISFY}>0.1\\ \varnothing,\ \text{SATISFY}\leq 0.1 \end{cases}

對應的 Python 代碼為

# 定義用戶參數與套餐到滿意度的映射
def user_satisfaction(vector_x, vector_y, pr, t, q):
    # 確保 X 和 Y 是 torch 張量
    vector_x = torch.tensor(vector_x, dtype=torch.float32)
    vector_y = torch.tensor(vector_y, dtype=torch.float32)
    
    term1 = vector_y[:, 0] * 10 ** (-pr / vector_x[:, 0])
    term2 = vector_y[:, 1] * torch.sqrt(4 * t / vector_x[:, 1] - 0.75)
    term3 = vector_y[:, 2] * (q / vector_x[:, 2]) ** (1 / 3)
    
    return term1 + term2 + term3

用戶建模#

用戶預算分布#

預算可以認為大致是服從帕累托分布的,假設初始參數為x1Par(1,0.6)x_1\sim Par(1,0.6),即

b(x1)=0.6x11.6(x1>1)b(x_1) = \frac{0.6}{x_1^{1.6}} (x_1>1)

其中 0.6 需要參數估計以獲得準確值。

帕累托分布通常用來描述不平等的分布,例如財富或收入,以及對應的預算。在現實世界中,財富分布往往是高度不平等的,少數人擁有大部分財富。因此,為了反映用戶預算,使用帕累托分布應該是合適的。

此外,帕累托分布與所謂的 “80/20 規則” 密切相關,即 80% 的效果(如消費)來自 20% 的原因(如消費者)。在許多經濟模型中,這種現象是普遍存在的,比如少數消費者貢獻了大部分的消費支出。

帕累托分布的兩個參數中,第一個參數為截止值,當x1<1x_1<1時,b(x1)=0b(x_1)=0。截止值無法參數估計,但假設為 1 是合適的。

流量需求分布#

流量需求可以認為近似服從正態分布,參數為x2N(130,302)x_2\sim N(130,30^2),即

t(x2)=1402πe12(x212040)2t(x_2)=\frac{1}{40\sqrt{2\pi}}e^{-\displaystyle\frac{1}{2}\left(\frac{x_2-120}{40}\right)^2}

這兩個參數都需要參數估計。

質量需求分布#

如果量化質量為1101\sim10,其中 1 為完全靈車機場,10 為全 IPLC 多入口智能解析機場(性能接近遊戲加速器),那麼質量需求也可以認為是服從帕累托分布的,參數為x3Par(1,2)x_3\sim Par(1,2),即

q(x3)=2x32q(x_3)=\frac{2}{x_3^2}

這個帕累托分布同樣只有第二個參數需要參數估計。

權重分布#

注意到y1y_1, y2y_2, y3y_3的分布實際上被均勻地放在了一個等邊三角形上。這個等邊三角形是一個三棱錐的底面。這個三棱錐的 3 個側面都是直角邊邊上為 1 的直角三角形。

等邊三角形的 3 個頂點分別表示其中一個權重為 1 而另外兩個權重為 0 的情況。

在使用(y1,y2)(y_1,y_2)表示時,3 種情況分別對應(0,0)(0,0), (1,0)(1,0), (0,1)(0,1)。而為了讓y1,y2,y3y_1,y_2,y_3變成更加均勻的等邊三角形,需要將這個區域線性變換為(3+1,0)(-\sqrt{3}+1,0), (31,1)(\sqrt{3}-1,1), (31,1)(\sqrt{3}-1,-1)。這個線性變換很容易求得。

首先把(3+1,0)(-\sqrt{3}+1,0)(0,0)(0,0)對齊,那麼其他兩個點是(3,1)(\sqrt{3},1), (3,1)(\sqrt{3},-1)。於是,變換矩陣為

[3311][1001]1=[3311]\begin{bmatrix} \sqrt{3} & \sqrt{3} \\ 1 & -1 \end{bmatrix} \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}^{-1}= \begin{bmatrix} \sqrt{3} & \sqrt{3} \\ 1 & -1 \end{bmatrix}

平移向量為(1,0)(-1,0),即

[y1y2]=[3311][y1y2]+[10]\begin{bmatrix} y_1' \\ y_2' \end{bmatrix}= \begin{bmatrix} \sqrt{3} & \sqrt{3} \\ 1 & -1 \end{bmatrix} \begin{bmatrix} y_1 \\ y_2 \end{bmatrix}+ \begin{bmatrix} -1 \\ 0 \end{bmatrix}

不過,對於 3 種因素的側重,可以認為一般人根本不在乎節點質量,而只考慮節點的價格和流量。所以,可以選擇截半邊的二元正態分布。截取之前的參數為

(y1,y2)N([1/21/2],[1/9001/9])(y_1,y_2)\sim \mathcal{N}\left( \begin{bmatrix} 1/2 \\ 1/2 \end{bmatrix}, \begin{bmatrix} 1/9 && 0 \\ 0 && 1/9 \end{bmatrix} \right)

即概率密度函數為

a(y1,y2)=9πe92[(x11/2)2+(x21/2)2]a(y_1,y_2)= \frac{9}{\pi}e^{\displaystyle -\frac{9}{2}\left[(x_1-1/2)^2+(x_2-1/2)^2\right]}

這兩個參數應該也是不需要參數估計的。

from torch.distributions import Pareto, Normal
from torch.distributions.multivariate_normal import MultivariateNormal

# 定義用戶預算分布
user_budget_distribution = Pareto(1, 0.6)
# 定義用戶流量需求分布
user_traffic_demand_distribution = Normal(130, 30)
# 定義用戶質量需求分布
user_quality_demand_distribution = Pareto(1, 2)
# 定義用戶側重分布
user_weight_mean = torch.tensor([0.5, 0.5])
user_weight_covariance = torch.tensor([[1 / 9, 0], [0, 1 / 9]])
user_weight_distribution = MultivariateNormal(user_weight_mean, user_weight_covariance)

# 生成樣本
sample_size = 10000     # 樣本數量
user_budget_sample = user_budget_distribution.sample((sample_size,))
user_traffic_demand_sample = user_traffic_demand_distribution.sample((sample_size,))
user_quality_demand_sample = user_quality_demand_distribution.sample((sample_size,))
user_weight_sample = user_weight_distribution.sample((sample_size,))

# 模擬用戶選擇套餐
y_1 = user_weight_sample[:, 0]
y_2 = user_weight_sample[:, 1]
y_3 = 1 - y_1 - y_2
user_sample = torch.stack([user_budget_sample, user_traffic_demand_sample, user_quality_demand_sample], dim=1)
user_weight_sample = torch.stack([y_1, y_2, y_3], dim=1)
user_satisfaction_of_packages = []
for i in range(packageNumber):
    pr = packagePrice[i]
    t = packageTrafficLimit[i]
    q = packageQuality[i]
    satisfactions = user_satisfaction(user_sample, user_weight_sample, pr, t, q)
    user_satisfaction_of_packages.append(satisfactions)
    
user_satisfaction_of_packages = torch.stack(user_satisfaction_of_packages, dim=1)
max_values, max_indices = torch.max(user_satisfaction_of_packages, dim=1)
indices = torch.where(max_values < 0.1, torch.tensor(-1), max_indices)

參數估計#

綜上,需要估計的參數有:

  • 用戶預算的帕累托分布kk參數:kbk_b
  • 流量需求分布的均值和方差:μt\mu_t,σt2\sigma^2_t
  • 質量需求的帕累托分布kk參數:kqk_q

似乎是可以通過神經網絡估計出這幾個參數,不過我沒去研究,初始參數又不是不能用。

最小化成本#

參數定義#

假設用戶的節點偏好為

R=[r1r2rn]R = \begin{bmatrix} r_1 \\ r_2 \\ \vdots \\ r_n \end{bmatrix}

且規定i=1nri=1\sum_{i=1}^n r_i = 1

用戶在各節點實際使用的流量為

U=[u1u2un]=uRU= \begin{bmatrix} u_1 \\ u_2 \\ \vdots \\ u_n \end{bmatrix} = uR

其中,uu為用戶實際使用的總流量。

這裡假設用戶不會因為差點用超流量而改用不喜歡的節點。

不考慮每個節點能夠承載的用戶數量限制,假設用戶會先用完節點的流量而不是因為請求導致節點超載。於是,假設各個節點的邊際成本為

C=[c1c2cn]C=\begin{bmatrix} c_1 \\ c_2 \\ \vdots \\ c_n \end{bmatrix}

則成本為CU=uCRC'U=uC'R

這裡假設了邊際成本為常數,但一般機場是規模經濟(邊際成本隨用量降低)的。

若定價為prp_r,則邊際利潤為pruCRp_r-uC'R

於是,得到利潤數據,平均每個套餐的利潤為

rˉ=pruˉCR\bar{r} = p_r - \bar{u}C'R

超售問題#

為了確定節點的流量邊際成本,需要計算超售比,因為cn=ctn/Rosc_n=c_{tn}/R_{os},其中ctnc_{tn}為實際流量邊際成本,RosR_{os}為超售比。

為了確保不會因為超售太多而導致可用性下降,定義RamaxRa_{max}為超售可用性,意義為:有RamaxRa_{max}的概率不會因為超售而不可用。

這裡定義超參數Ramax=1104=99.99%Ra_{max}=1-10^{-4}=99.99\%

對於套餐g1,g2,,gng_1,g_2,\cdots,g_n,設用戶實際使用總流量的概率密度函數為fn(u)f_{n}(u),則對於某一個節點,使用的流量的概率密度函數為rnfn(urn)r_nf_n(ur_n)

設節點實際的流量為trt_r,則為滿足可用性,需要

Pr{u<tr}RamaxPr\{u<t_r\} \geq Ra_{max}

n0trrnfn(urn)durn=n0tr/rnfn(u)duRamax\sum_n\int_0^{t_r} r_nf_n(ur_n) dur_n=\sum_n\int_0^{t_r/r_n}f_n(u)du\geq Ra_{max}

例如,假設只有 1 個套餐,這個套餐的限額為 150G,對於日本節點,倍率為 1,用戶的偏好程度為 0.5,使用的流量服從正態分布uN(80,100)u\sim N(80,100),那麼,trt_r應該為58.59558.595,超售比為2.54232.5423

用戶使用的流量在與之前參數估計得到的用戶需求流量大致相同,但有一定誤差。這是因為,用戶往往會高估自己需要使用的流量。不過,假設用戶實際使用的流量等於用戶流量需求可能是可行的,因為留一點流量上的冗餘是問題不大的。

因為

Ros=trnrntR_{os}=\frac{t_r}{\sum_n r_nt}

trt_r可以求解方程得到,

所以RosR_{os}可以由數據分析得到。

最大期望利潤問題#

最大期望利潤問題,也就是使得

nfnrnˉ=fn(pr,nunˉCR)\sum_n f_n\bar{r_n} =f_n\left( p_{r,n} - \bar{u_n}C'R\right)

最大的问题。(其中 $f_n$ 為選擇率)

由於CCRR都是基本不變的量,而且在參數估計出用戶的需求分布後,fnf_n只取決於套餐的屬性,unˉ\bar{u_n}也是穩定的,所以最大利潤問題就是確定套餐屬性的問題。

如果假設套餐的質量屬性是常數,那麼變量就只有各個套餐的價格和流量了。

所以,計算最大期望利潤的方法為:

  • 統計得到CRC'R
  • 確定各個套餐的質量
  • 確定各個套餐的價格或者流量,把另一個設置為變量。
  • 對變量進行梯度下降,使上面那個和式取最大值
    • fnf_n可以在有用戶的數學模型之後,蒙特卡羅方法得到
    • prp_r為價格,是輸入變量
    • unu_n與用戶的建模相關
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。