0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

深入淺出地介紹了一個有趣的概念:等待時間悖論

zhKF_jqr_AI ? 來源:未知 ? 作者:李倩 ? 2018-11-13 09:01 ? 次閱讀

編者按:在數(shù)據(jù)科學(xué)領(lǐng)域,值得閱讀的好書有很多,尤其是O‘Reilly出版的一系列動物封面英文書。其中一本“蜥蜴書”叫《Python數(shù)據(jù)科學(xué)指南》(Python Data Science Handbook),書中詳細(xì)介紹了Jupyter、Numpy、Pandas、數(shù)據(jù)可視化和scikit-learn模塊的具體使用方式,是新手入門機(jī)器學(xué)習(xí)的一條捷徑。近日,這本書的作者Jake VanderPlas寫了一篇博文,深入淺出地介紹了一個有趣的概念:等待時間悖論。

圖像來源:維基百科 許可:CC-BY-SA 3.0

經(jīng)常乘坐公共交通工具的人可能都遇到過這種情況:

你到公交站臺等車,標(biāo)牌顯示公交車的發(fā)車間隔是10分鐘一輛。你瞥了眼手表,記下時間……11分鐘后,公交車終于來了,你不由開始懊惱:為什么我老是這么倒霉!

已知公交車每隔10分鐘發(fā)一班,你到站臺是在某個隨機(jī)時間點(diǎn)(不借助實時公交APP),面對這種情況,很多人會想當(dāng)然地覺得自己的平均等待時間應(yīng)該是5分鐘。但實際上,5分鐘后,公交車沒來,這時你只能繼續(xù)等;10分鐘后,車子可能還是沒有來……在一些合理的數(shù)學(xué)假設(shè)下,你可以得出一個驚人結(jié)論:

當(dāng)公交車的平均發(fā)車間隔是10分鐘時,乘客平均等公交車的時間也會是10分鐘。

這就是等待時間悖論。

那么這個悖論真實存在嗎?這些“合理的假設(shè)”究竟是只流于理論,還是同樣適用于現(xiàn)實?本文會以美國西雅圖市的真實公交車到達(dá)時間數(shù)據(jù)為例,從模擬和概率論證的角度探討這個問題。

檢驗悖論(Inspection Paradox)

如果每隔10分鐘一定有一班車到這個站臺,那我們的平均等待時間確實是這個間隔的一半:5分鐘。但是,如果10分鐘只是個平均值,乘客的平均等待時間其實會比5分鐘更長一些,這點(diǎn)不難理解。

等待時間悖論其實是檢驗悖論的一個特殊例子,后者在日常生活中更普遍。舉一個簡單例子,假設(shè)你正在調(diào)查某大學(xué)的班級規(guī)模,調(diào)查方法是隨機(jī)選一些學(xué)生問“你所在的班級有多少人”再計算平均值,最后你統(tǒng)計出的結(jié)果是平均56人。但是,全校的班級平均人數(shù)實際上只有36(以上數(shù)據(jù)來自普渡大學(xué)調(diào)查)。這不是說有人撒了謊,而是10人班級和100人班級被抽樣的概率不一樣,隨機(jī)抽樣會導(dǎo)致對人數(shù)較多的班級過度抽樣,使結(jié)果向人多的一方傾斜。

同理,在平均每隔10分鐘就有一班車到站臺的情況下,有時前后兩輛公交車的到達(dá)間隔會超過10分鐘,有時候不到10分鐘,如果你到站臺是個隨機(jī)時間點(diǎn),你就有更大概率會遇到超過10分鐘的情況。所以乘客的平均等待時間更長是有道理的,因為較長間隔被過度采樣了。

但等待時間悖論提出了一個更令人“匪夷所思”的結(jié)論:當(dāng)前后兩輛車的平均到站間隔是N分鐘時,乘客體驗到的公交車平均到站間隔是2N分鐘。這會是真的嗎?

模擬等待時間

為了證明等待時間悖論的結(jié)論是正確的,首先我們可以模擬一些公交車,它們的平均到站時間是10分鐘。已知樣本數(shù)量越大,結(jié)果越準(zhǔn)確,我們設(shè)一共有100萬輛公交車。:

import numpy as np

N = 1000000# 公交車數(shù)量

tau = 10# 平均到站間隔

rand = np.random.RandomState(42) # 隨機(jī)種子

bus_arrival_times = N * tau * np.sort(rand.rand(N))

接著,我們檢查一下它們的平均到站間隔是否接近τ=10:

intervals = np.diff(bus_arrival_times)

intervals.mean()

輸出:9.9999879601518398

模擬好了公交車,之后是模擬大量在這個時間跨度內(nèi)到達(dá)公交站的乘客,并計算他們每個人的等待時間。如下所示,我們把它封裝進(jìn)一個函數(shù)以備后用:

def simulate_wait_times(arrival_times,

rseed=8675309, # Jenny的隨機(jī)種子

n_passengers=1000000):

rand = np.random.RandomState(rseed)

arrival_times = np.asarray(arrival_times)

passenger_times = arrival_times.max() * rand.rand(n_passengers)

# 為每個模擬乘客找到下一輛公交車

i = np.searchsorted(arrival_times, passenger_times, side='right')

return arrival_times[i] - passenger_times

然后我們可以模擬一些等待時間并計算平均值:

wait_times = simulate_wait_times(bus_arrival_times)

wait_times.mean()

輸出:10.001584206227317

正如等待時間悖論預(yù)測的那樣,乘客的平均等待時間也接近10分鐘。

深入挖掘:概率和泊松過程

所以上面的代碼到底是什么意思?

從本質(zhì)上看,等待時間悖論是檢驗悖論的一個特例,觀察某個值的概率和這個值本身有關(guān)。讓我們用p(T)表示公交車到站時間間隔T的分布,這時,對到達(dá)時間的期望值是:

在上面的例子中,我們已經(jīng)設(shè)E[T]=τ=10分鐘。

當(dāng)乘客在隨機(jī)時間點(diǎn)到達(dá)公交站時,他們經(jīng)歷的等待時間的概率既會受p(T)影響,又會受T本身影響:汽車到達(dá)間隔越長,乘客遇到較長等待時間的概率也會相應(yīng)變大。

所以我們可以寫出乘客感受到的汽車到站間隔分布:

它們的比例常數(shù)是:

也就是:

已知乘客的期望等待時間E[W]是他們體驗到的公交車到站間隔的一半,我們可以把它寫成:

改寫上式可得:

現(xiàn)在剩下的就是為p(T)選擇一個列表,并計算積分。

選擇p(T)

我們可以通過繪制公交車到站間隔直方圖來模擬p(T)的分布:

%matplotlib inline

import matplotlib.pyplot as plt

plt.style.use('seaborn')

plt.hist(intervals, bins=np.arange(80), density=True)

plt.axvline(intervals.mean(), color='black', linestyle='dotted')

plt.xlabel('Interval between arrivals (minutes)')

plt.ylabel('Probability density');

圖中虛線表示平均到站時間為10分鐘。可以發(fā)現(xiàn),上圖分布形狀很像指數(shù)分布,這并不是偶然:我們把公交車到站間隔模擬成均勻隨機(jī)數(shù)的做法十分類似泊松過程,而如果構(gòu)成泊松過程,到站間隔的分布一定符合指數(shù)分布。

注:在我們的例子里,到站間隔分布只是近似指數(shù)分布。

如果到站間隔符合指數(shù)分布,它就遵循泊松過程——為了驗證這個推理,我們可以用另一個泊松過程的屬性來檢查:在固定時間范圍內(nèi),公交車到站次數(shù)的分布滿足泊松分布。我們可以在之前的模擬中查看每小時公交車的到站次數(shù):

from scipy.stats import poisson

# 計算1小時內(nèi)公交車到站次數(shù)

binsize = 60

binned_arrivals = np.bincount((bus_arrival_times // binsize).astype(int))

x = np.arange(20)

# 繪制結(jié)果

plt.hist(binned_arrivals, bins=x - 0.5, density=True, alpha=0.5, label='simulation')

plt.plot(x, poisson(binsize / tau).pmf(x), 'ok', label='Poisson prediction')

plt.xlabel('Number of arrivals per hour')

plt.ylabel('frequency')

plt.legend();

如上圖所示,模擬次數(shù)分布(方柱)和泊松分布(黑點(diǎn))幾乎一致?,F(xiàn)在理論、模擬實踐都支持這么一個事實:對于一個足夠大的N,公交車的到站間隔可以用泊松過程描述,到站間隔分布滿足指數(shù)分布。

這意味著我們可以把概率分布寫成:

把上式帶入之前的等式,可得每名乘客的平均等待時間是:

因此,如果公交車的到站間隔符合泊松過程,乘客的平均期望等待時間和公交車的平均到站間隔相同。

推斷這個結(jié)論的另一種補(bǔ)充方法是:泊松過程是一個無記憶過程,這意味事歷史事件與下一事件發(fā)生的預(yù)期時間無關(guān)。所以當(dāng)你到達(dá)公交站時,你對下一班車的平均等待時間始終是一樣的:不管前一班車是什么時候來的,你平均都得等10分鐘。同理,無論你之前已經(jīng)等了多久,乘客對下一班車的預(yù)期等待時間還是10分鐘。

現(xiàn)實中的等待時間

那么泊松過程能描述現(xiàn)實生活中的公交車到站時間嗎?

為了探討等待時間悖論和現(xiàn)實情況是否存在矛盾,我們可以用一些數(shù)據(jù)進(jìn)行更深入的研究(arrival_times.csv,3MB CSV文件)。這個數(shù)據(jù)集包含2016年第二季度美國西雅圖3rd & Pike公交站的記錄,它一共有3條快速線:C、D和E,給出了每輛公交車的預(yù)定和實際到達(dá)時間。

import pandas as pd

df = pd.read_csv('arrival_times.csv')

df = df.dropna(axis=0, how='any')

df.head()

之所以選擇快速線,是因為在一天的大部分時間里,這幾路公交車的到站間隔都穩(wěn)定在10-15分鐘之間。

數(shù)據(jù)清理

首先,讓我們簡單做一些數(shù)據(jù)清理,把數(shù)據(jù)集里的表格轉(zhuǎn)成更易于使用的形式:

# 把日期和時間組合成單個時間戳

df['scheduled'] = pd.to_datetime(df['OPD_DATE'] + ' ' + df['SCH_STOP_TM'])

df['actual'] = pd.to_datetime(df['OPD_DATE'] + ' ' + df['ACT_STOP_TM'])

# 如果公交車的預(yù)計到點(diǎn)和實際到點(diǎn)過了半夜,需要調(diào)整日期

minute = np.timedelta64(1, 'm')

hour = 60 * minute

diff_hrs = (df['actual'] - df['scheduled']) / hour

df.loc[diff_hrs > 20, 'actual'] -= 24 * hour

df.loc[diff_hrs < -20, 'actual'] += 24 * hour

df['minutes_late'] = (df['actual'] - df['scheduled']) / minute

# 內(nèi)外部路徑映射

df['route'] = df['RTE'].replace({673: 'C', 674: 'D', 675: 'E'}).astype('category')

df['direction'] = df['DIR'].replace({'N': 'northbound', 'S': 'southbound'}).astype('category')

# 抓取有用的列

df = df[['route', 'direction', 'scheduled', 'actual', 'minutes_late']].copy()

df.head()

公交車晚點(diǎn)情況

數(shù)據(jù)集中有6組不同數(shù)據(jù):南向行駛和北向行駛的3路公交車。為了感受它們的早到/遲到特點(diǎn),我們可以用實際到達(dá)時間減去預(yù)期到達(dá)時間,繪制6幅公交車“晚點(diǎn)”情況圖:

import seaborn as sns

g = sns.FacetGrid(df, row="direction", col="route")

g.map(plt.hist, "minutes_late", bins=np.arange(-10, 20))

g.set_titles('{col_name} {row_name}')

g.set_axis_labels('minutes late', 'number of buses');

事實上,很多人僅憑經(jīng)驗就知道公交車在剛發(fā)車后的一段時間內(nèi)更不容易晚點(diǎn),公交站越靠后,車子晚點(diǎn)的可能性就越大,晚點(diǎn)時間也越長。這一點(diǎn)在上圖中得到了證實,南向行駛的C路公交車(圖四)、北向行駛的D路公交車(圖二)和北向行駛的E路公交車在剛開出時還很準(zhǔn)時,到最后卻出現(xiàn)了晚點(diǎn)超過十幾分鐘的情況。

預(yù)計到點(diǎn)和實際到點(diǎn)

接著,我們來看看這6條線路的實際到站間隔,這可以用Pandas的groupby函數(shù)計算:

def compute_headway(scheduled):

minute = np.timedelta64(1, 'm')

return scheduled.sort_values().diff() / minute

grouped = df.groupby(['route', 'direction'])

df['actual_interval'] = grouped['actual'].transform(compute_headway)

df['scheduled_interval'] = grouped['scheduled'].transform(compute_headway)

g = sns.FacetGrid(df.dropna(), row="direction", col="route")

g.map(plt.hist, "actual_interval", bins=np.arange(50) + 0.5)

g.set_titles('{col_name} {row_name}')

g.set_axis_labels('actual interval (minutes)', 'number of buses');

很明顯,上述分布和指數(shù)分布差距比較大,但它存在一個潛在影響因素,就是影響實際到站間隔的預(yù)期到站間隔可能本身就是不恒定的。

所以我們得再去看看預(yù)期到站間隔的情況:

g = sns.FacetGrid(df.dropna(), row="direction", col="route")

g.map(plt.hist, "scheduled_interval", bins=np.arange(20) - 0.5)

g.set_titles('{col_name} {row_name}')

g.set_axis_labels('scheduled interval (minutes)', 'frequency');

很顯然,預(yù)期到站間隔不是一個固定值,而且它的變化范圍還很大。所以在這個數(shù)據(jù)集里,我們沒法用實際到站間隔的分布來評估等待時間悖論是否準(zhǔn)確。

構(gòu)建同一時間表

雖然預(yù)期到站間隔不均勻,但它們中也存在一些常見的特定間隔,比如數(shù)據(jù)集中有近2000輛北向行駛的E路車的預(yù)期間隔是10分鐘。為了探究等待時間悖論是否,我們可以按公交路線、行駛方向和預(yù)期到站間隔對數(shù)據(jù)集進(jìn)行分類,篩選出相似的數(shù)據(jù)重新進(jìn)行堆疊分析,假設(shè)它們是連續(xù)發(fā)車的。

def stack_sequence(data):

# first, sort by scheduled time

data = data.sort_values('scheduled')

# re-stack data & recompute relevant quantities

data['scheduled'] = data['scheduled_interval'].cumsum()

data['actual'] = data['scheduled'] + data['minutes_late']

data['actual_interval'] = data['actual'].sort_values().diff()

return data

subset = df[df.scheduled_interval.isin([10, 12, 15])]

grouped = subset.groupby(['route', 'direction', 'scheduled_interval'])

sequenced = grouped.apply(stack_sequence).reset_index(drop=True)

sequenced.head()

利用這些清理過的數(shù)據(jù),我們可以繪制每個公交路線、行駛方向和到站頻率的公交車“實際”到站間隔分布:

for route in ['C', 'D', 'E']:

g = sns.FacetGrid(sequenced.query(f"route == '{route}'"),

row="direction", col="scheduled_interval")

g.map(plt.hist, "actual_interval", bins=np.arange(40) + 0.5)

g.set_titles('{row_name} ({col_name:.0f} min)')

g.set_axis_labels('actual interval (min)', 'count')

g.fig.set_size_inches(8, 4)

g.fig.suptitle(f'{route} line', y=1.05, fontsize=14)

如上圖所示,這三路公交車的到站間隔分布近似高斯分布:在預(yù)期到站間隔附近達(dá)到峰值,一開始標(biāo)準(zhǔn)偏差較小,越往后越大。所以很顯然,這和等待時間悖論的基石——指數(shù)分布相違背。

我們再用上面的數(shù)據(jù)計算每個公交路線、行駛方向和到站頻率的公交車的乘客平均等待時間:

grouped = sequenced.groupby(['route', 'direction', 'scheduled_interval'])

sims = grouped['actual'].apply(simulate_wait_times)

輸出:

route direction scheduled_interval

C northbound 10.0 7.8 +/- 12.5

12.0 7.4 +/- 5.7

15.0 8.8 +/- 6.4

southbound 10.0 6.2 +/- 6.3

12.0 6.8 +/- 5.2

15.0 8.4 +/- 7.3

D northbound 10.0 6.1 +/- 7.1

12.0 6.5 +/- 4.6

15.0 7.9 +/- 5.3

southbound 10.0 6.7 +/- 5.3

12.0 7.5 +/- 5.9

15.0 8.8 +/- 6.5

E northbound 10.0 5.5 +/- 3.7

12.0 6.5 +/- 4.3

15.0 7.9 +/- 4.9

southbound 10.0 6.8 +/- 5.6

12.0 7.3 +/- 5.2

15.0 8.7 +/- 6.0

Name: actual, dtype: object

平均等待時間可能比預(yù)期到站間隔的一半長一兩分鐘,但不是等待時間悖論所暗示的結(jié)果。換句話說,這個結(jié)果證實了檢驗悖論,而等待時間悖論似乎與現(xiàn)實不符。

最后的想法

等待時間悖論一直是一個有趣的論題,它涵蓋模擬、概率統(tǒng)計假設(shè)與現(xiàn)實的比較。雖然我們現(xiàn)在已經(jīng)確認(rèn)現(xiàn)實世界的公交線路確實遵循了一些檢驗悖論,但上述分析也非常明確地表明等待時間悖論背后的核心假設(shè)——公交車到站間隔遵循泊松過程有很大問題。

回想起來,這可能并不令人驚訝:泊松過程是一個無記憶過程,它假設(shè)公交車到站概率完全獨(dú)立于自上次到站以來的時間。但在現(xiàn)實中,一個運(yùn)行良好的公交系統(tǒng)會設(shè)計合理的行車時間表,每輛公交車的出發(fā)時間都不是隨機(jī)的,它們要考慮乘客多少。

而由這個問題引出的更大教訓(xùn),是我們應(yīng)該謹(jǐn)慎對待任何數(shù)據(jù)分析任務(wù)的假設(shè)。雖然泊松過程有時是對到站時間數(shù)據(jù)的良好描述,但我們不能僅僅因為一種類型的數(shù)據(jù)看起來和另一種類型的數(shù)據(jù)很像,就直接想當(dāng)然地認(rèn)為對這種數(shù)據(jù)有效的假設(shè)必然對另一種同樣有效。看似正確的假設(shè)可能導(dǎo)致與現(xiàn)實不符的結(jié)論。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴

原文標(biāo)題:等待時間悖論:為什么我的公交車總是遲到?

文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    深入淺出AVR

    深入淺出AVR,本書。
    發(fā)表于 07-15 12:02

    深入淺出玩轉(zhuǎn)FPGA

    深入淺出玩轉(zhuǎn)FPGA
    發(fā)表于 07-21 09:21

    深入淺出ARM7

    深入淺出ARM7
    發(fā)表于 08-18 10:12

    HDMI技術(shù)深入淺出

    HDMI技術(shù)深入淺出
    發(fā)表于 08-19 10:52

    深入淺出Android

    深入淺出Android
    發(fā)表于 08-20 10:14

    深入淺出Android

    深入淺出Android
    發(fā)表于 04-26 10:48

    深入淺出安防視頻監(jiān)控系統(tǒng)

    深入淺出安防視頻監(jiān)控系統(tǒng)深入淺出安防視頻監(jiān)控系統(tǒng)
    發(fā)表于 05-22 19:28

    深入淺出AVR

    深入淺出AVR
    發(fā)表于 08-23 10:10

    深入淺出matlab

    深入淺出matlab 本書介紹MATLAB 7.X版本與其他語言混合編程的方法。內(nèi)容包括在MATLAB中以文件方式導(dǎo)入、導(dǎo)
    發(fā)表于 06-18 09:13 ?261次下載
    <b class='flag-5'>深入淺出</b>matlab

    深入淺出數(shù)據(jù)分析

    深入淺出數(shù)據(jù)分析,有需要的朋友下來看看。
    發(fā)表于 01-15 14:22 ?0次下載

    深入淺出AVR單片機(jī)_精要

    本書深入淺出介紹AVR單片機(jī)的原理及應(yīng)用
    發(fā)表于 03-24 10:47 ?16次下載

    深入淺出談多層面板布線技巧

    深入淺出談多層面板布線技巧
    發(fā)表于 12-13 22:20 ?0次下載

    深入淺出Android—Android開發(fā)經(jīng)典教材

    深入淺出Android—Android開發(fā)經(jīng)典教材
    發(fā)表于 10-24 08:52 ?15次下載
    <b class='flag-5'>深入淺出</b>Android—Android開發(fā)經(jīng)典教材

    深入淺出數(shù)字信號處理

    深入淺出數(shù)字信號處理
    發(fā)表于 12-07 20:14 ?510次閱讀

    深入淺出學(xué)習(xí)250通信原理資源下載

    深入淺出學(xué)習(xí)250通信原理資源下載
    發(fā)表于 04-12 09:16 ?28次下載