文章目錄:
- [用算法拯救她閨蜜]
- [本質(zhì)上是最優(yōu)解問題]
- [用平行宇宙解釋]
- [蒙特卡洛算法求解]
- [所有的前任只是前戲]
- [每天只想和你做四件事——一日三餐]
我用算法幫女朋友的閨蜜選男友
用算法拯救她閨蜜
下班前收到女友的電話,說晚上要和她的網(wǎng)紅閨蜜一起吃個(gè)飯。
“what?這不是鴻門宴吧?”
“你想什么呢?她最近處的一個(gè)男朋友像她求婚了,不知道要不要答應(yīng)。你不是搞數(shù)據(jù)分析的嗎?想讓你幫忙理性分析一下!”
要說女朋友的閨蜜,條件是真不錯(cuò),中產(chǎn)家庭,高等學(xué)歷,當(dāng)然最關(guān)鍵的顏值很能打,要不然也不能當(dāng)網(wǎng)紅??上в鋈瞬皇?,有幾段失敗的感情經(jīng)歷,也算是受了情傷。自古美女遇渣男,也算是常態(tài)。是時(shí)候用算法來拯救妹子了。
本質(zhì)上是最優(yōu)解問題
如果你讀過《Algorithms to live by》就知道本質(zhì)上這就是一個(gè)“最優(yōu)停止問題”,答案很簡(jiǎn)單,就是37% (1/e)。
我們來把這個(gè)問題說的更清晰一點(diǎn):
問題描述:
我們假設(shè)網(wǎng)紅妹子在一生中有可能會(huì)遇到100個(gè)求婚的男人,妹子要答應(yīng)第幾個(gè)男人才是最優(yōu)的呢?
限制條件:
- 男人會(huì)一個(gè)一個(gè)來求婚。
- 妹子只能對(duì)提出過求婚請(qǐng)求的男人來進(jìn)行打分比較。(也就是在未來有可能求婚的男人你沒有辦法進(jìn)行打分,因?yàn)檫€沒遇到)。
- 已經(jīng)被拒絕的求婚者,就永遠(yuǎn)不再考慮了。
為此,妹子可以這樣做:
- 設(shè)立觀察期,在觀察期內(nèi)對(duì)所有的求婚者只打分不接受求婚
- 選出觀察期內(nèi)的最高得分
- 對(duì)接下來的每一個(gè)求婚者進(jìn)行打分,并與觀察期內(nèi)的最高得分進(jìn)行比較,如果大于等于為真,則接受求婚停止求解,否則拒絕求婚并比較下一個(gè)求婚者。
這個(gè)觀察期的停止最優(yōu)解就是37%,也就是你觀察100 * 37% = 37,妹子只考察前37個(gè)求婚者,只打分不接受求婚。從第38個(gè)人開始,如果得分大于等于前37個(gè)人中的最大值,就接受她的求婚。
現(xiàn)在頭疼的是如何把妹子講明白呢?
用平行宇宙解釋
我們遇到這類問題之所以頭疼是因?yàn)槲覀兊娜松挥幸淮巍5绻@個(gè)世界存在平行宇宙,擁有多個(gè)平行宇宙的你,這個(gè)問題是不是就好解決了?
想象一下你擁有了《十二大戰(zhàn)》中老鼠的異能。當(dāng)然你沒有也沒有關(guān)系,你可以用計(jì)算機(jī)來幫你實(shí)現(xiàn)。
np.random.seed(100)
lifes = np.random.uniform(0,1, size=(100000, 100))
這樣你就產(chǎn)生了100000個(gè)平行宇宙,在每個(gè)宇宙中妹子會(huì)遇到100個(gè)求婚者,每個(gè)求婚者的得分是隨機(jī)生成的,范圍為0~1
蒙特卡洛算法求解
是時(shí)候放大招了,我們要在100000個(gè)平行宇宙,求最優(yōu)解了,這個(gè)時(shí)候咱們就不用什么數(shù)學(xué)證明了,直接用蒙特卡洛算法的思路去解決就好了。
蒙特卡洛算法就是通過構(gòu)建大量的隨機(jī)值去模擬現(xiàn)實(shí)中的數(shù)據(jù),并猜測(cè)最優(yōu)解的過程。
我們先來完成核心的check函數(shù)。
把每一個(gè)平行宇宙的數(shù)據(jù)傳給check,如果我們選到了最大值返回True,否則返回False。
def check(life, stop):
max_in_saw = max(life[:stop])
select = 0
for i in range(stop, len(life)):
if life[i] >= max_in_saw:
select = life[i]
break
maxall = max(life)
if select == maxall:
return True
else:
return False
接下來就遍歷100000個(gè)平行宇宙,在每個(gè)宇宙去,去嘗試不同的stop值,也就是設(shè)置不同的觀察期。
success_count = np.zeros(100)
for stop in range(1, 100):
for life in lifes:
if check(life, stop):
success_count[stop] += 1
輸出success_count數(shù)組的最大值,正好是37。這意味著你用這個(gè)停止條件,獲得的最大值最多(也就是挑選到合適人選的次數(shù))。
print(success_count.argmax())
#輸出值為37
當(dāng)然如果你的平行宇宙?zhèn)€數(shù)和求婚者個(gè)數(shù)和我不一樣,結(jié)果可能會(huì)有差距,但應(yīng)該是在37%的位置左右。
做一個(gè)可視化,讓結(jié)果更好觀察
x_axis = np.arange(1,100)
y_axis = success_count[1:100]
plt.plot(x_axis, y_axis, 'ro-', linewidth=2.0)
plt.show()
所有的前任只是前戲
這種在觀察階段冒著與優(yōu)秀的人選失之交臂的策略,到底值不值呢?
我們簡(jiǎn)單的思考一下,在100個(gè)中候選者中,我們隨機(jī)選一個(gè)人,他是最優(yōu)解的概率是1%。
而在我們剛才示例的100000個(gè)平行宇宙中,如果我們使用stop為37的策略,我們將在37131.0個(gè)平行宇宙中獲得最優(yōu)解。
在就把獲得最優(yōu)解的概率提高到了37.131%。這真是巨大的提升,這就是算法的力量。
所有的前任只是前戲,只有最優(yōu)解才是高潮!
每天只想和你做四件事——一日三餐
晚餐吃的很愉快,席間好好的給女友的閨蜜普及了一下"37%"最優(yōu)解。
"你看假設(shè)你打算38歲之前把自己嫁出去,從18-38這20年間,你每年遇到一個(gè)求婚者也就是20個(gè)!"
你的觀察期最優(yōu)解為2037%= 7.4 也就是你先觀察7個(gè)求婚者,你現(xiàn)在男朋友正好是第8個(gè),從你描述你對(duì)他的評(píng)價(jià)比之前那7個(gè)人都高。所以從概率上來說,你選擇他是你的最優(yōu)解!"*
圖文并茂很是讓女友的閨蜜信服,收獲了無數(shù)崇拜的小星星!
晚上回家,女友問我她是我的第幾個(gè)女朋友,是不是最優(yōu)解?
我肯定的回答,你就是我的最優(yōu)解。
我計(jì)劃38歲結(jié)婚,從18~38,這20年間我在28歲遇到你,你不是我的最優(yōu)解,誰是?
以后:"每天只想和你做四件事——一日三餐"