版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
深入淺出AI算法基礎(chǔ)概覽目錄TOC\h\h第1章算法入門(mén)\h1.1打開(kāi)算法之門(mén)\h1.1.1算法簡(jiǎn)史\h1.1.2算法與人工智能\h1.1.3什么是數(shù)據(jù)分析\h1.1.4什么是數(shù)據(jù)挖掘\h1.1.5什么是機(jī)器學(xué)習(xí)\h1.2如何學(xué)習(xí)算法\h1.3本文結(jié)構(gòu)\h關(guān)鍵詞回顧\h第2章算法之內(nèi)力\h2.1線性代數(shù)\h2.1.1名詞解釋\h2.1.2向量和矩陣\h2.2排列組合\h2.3高等數(shù)學(xué)\h2.3.1導(dǎo)數(shù)\h2.3.2梯度\h2.4概率與統(tǒng)計(jì)\h2.4.1名詞解釋\h2.4.2概率分布\h2.5最優(yōu)化原理\h2.6動(dòng)腦時(shí)刻\h2.7本章小結(jié)\h關(guān)鍵詞回顧\h第3章算法之招式\h3.1數(shù)據(jù)結(jié)構(gòu)\h3.1.1數(shù)組與鏈表\h3.1.2隊(duì)列和棧\h3.1.3樹(shù)\h3.1.4圖\h3.1.5散列表\h3.2基礎(chǔ)算法\h3.2.1排序\h3.2.2遞歸與分治\h3.2.3貪婪算法和動(dòng)態(tài)規(guī)劃\h3.2.4搜索\h3.2.5最短路徑\h3.2.6最小生成樹(shù)\h3.2.7樹(shù)狀數(shù)組\h3.2.8線段樹(shù)\h3.2.9平衡二叉樹(shù)\h3.2.10并查集\h3.2.11匈牙利算法\h3.3在線評(píng)測(cè)系統(tǒng)\h3.3.1LeetCode\h3.3.2POJ與ZOJ\h3.3.3Tsinsen\h3.4動(dòng)腦時(shí)刻\h3.5本章小結(jié)\h關(guān)鍵詞回顧\h第4章算法之武功秘籍\h4.1類(lèi)別劃分\h4.1.1按是否有監(jiān)督信號(hào)劃分\h4.1.2按學(xué)習(xí)目標(biāo)劃分\h4.2線性回歸模型與邏輯回歸模型\h4.2.1線性回歸模型\h4.2.2邏輯回歸模型\h4.3人工神經(jīng)網(wǎng)絡(luò)\h4.3.1初識(shí)人工神經(jīng)網(wǎng)絡(luò)\h4.3.2深度神經(jīng)網(wǎng)絡(luò)\h4.3.3卷積神經(jīng)網(wǎng)絡(luò)\h4.3.4遞歸神經(jīng)網(wǎng)絡(luò)\h4.3.5圖神經(jīng)網(wǎng)絡(luò)\h4.4決策樹(shù)\h4.4.1概念與方法\h4.4.2剪枝\h4.4.3梯度提升決策樹(shù)\h4.4.4隨機(jī)森林\h4.5聚類(lèi)\h4.5.1距離度量\h4.5.2劃分聚類(lèi)\h4.5.3層次聚類(lèi)\h4.5.4密度聚類(lèi)\h4.5.5模型聚類(lèi)\h4.6貝葉斯分類(lèi)\h4.6.1概率基礎(chǔ)\h4.6.2樸素貝葉斯分類(lèi)\h4.7支持向量機(jī)\h4.8動(dòng)腦時(shí)刻\h4.9本章小結(jié)\h關(guān)鍵詞回顧\h第5章算法工程的組成部分\h5.1數(shù)據(jù)分析\h5.1.1宏觀把握數(shù)據(jù)\h5.1.2微觀感受數(shù)據(jù)\h5.1.3分析方法\h5.2特征工程\h5.2.1數(shù)據(jù)預(yù)處理\h5.2.2特征分類(lèi)\h5.2.3工程技巧\h5.3建模與調(diào)參\h5.3.1建模\h5.3.2調(diào)參\h5.4效果評(píng)估\h5.4.1數(shù)據(jù)集劃分\h5.4.2評(píng)估指標(biāo)\h5.4.3直觀理解AUC\h5.5模型托管\h5.6動(dòng)腦時(shí)刻\h5.7本章小結(jié)\h關(guān)鍵詞回顧\h第6章算法工程實(shí)戰(zhàn)\h6.1環(huán)境準(zhǔn)備\h6.1.1設(shè)備配置\h6.1.2環(huán)境搭建\h6.1.3開(kāi)發(fā)工具\(yùn)h6.1.4基礎(chǔ)調(diào)試\h6.2開(kāi)源算法庫(kù)\h6.2.1scikit-learn\h6.2.2TensorFlow\h6.3算法實(shí)踐\h6.3.1線性回歸模型\h6.3.2神經(jīng)網(wǎng)絡(luò)模型\h6.4工程實(shí)戰(zhàn)\h6.4.1數(shù)據(jù)準(zhǔn)備\h6.4.2數(shù)據(jù)分析\h6.4.3特征工程\h6.4.4模型訓(xùn)練\h6.4.5模型的保存與載入\h6.5算法競(jìng)賽介紹\h6.5.1Kaggle\h6.5.2KDDCup\h6.6動(dòng)腦時(shí)刻\h6.7本章小結(jié)\h關(guān)鍵詞回顧\h第7章進(jìn)階學(xué)習(xí)\h7.1深度學(xué)習(xí)\h7.1.1起源\h7.1.2難點(diǎn)與方法\h7.1.3經(jīng)典模型:AlexNet\h7.2強(qiáng)化學(xué)習(xí)\h7.2.1起源\h7.2.2流派與分類(lèi)\h7.2.3經(jīng)典案例:AlphaGo\h7.3遷移學(xué)習(xí)\h7.3.1簡(jiǎn)介\h7.3.2方法與研究方向\h7.3.3經(jīng)典模型:TrAdaBoost\h7.4動(dòng)腦時(shí)刻\h7.5本章小結(jié)\h關(guān)鍵詞回顧\h第8章思考與展望\h8.1思考\h8.1.1人工智能感悟\h8.1.2萬(wàn)物數(shù)據(jù)化\h8.2展望\h8.2.1人工智能最終能做什么\h8.2.2人類(lèi)最終能做什么\h8.3本章小結(jié)第1章
算法入門(mén)在學(xué)習(xí)一門(mén)技能之前,先了解這門(mén)技能的需求和功能,可以讓學(xué)習(xí)目標(biāo)更加明確,讓學(xué)習(xí)更有動(dòng)力。隨著計(jì)算機(jī)硬件技術(shù)的飛速發(fā)展,我們可以收集到各種類(lèi)型的互聯(lián)網(wǎng)數(shù)據(jù)、交通數(shù)據(jù)、氣象數(shù)據(jù)等并將其保存下來(lái)。根據(jù)收集到的不同場(chǎng)景中的數(shù)據(jù),可以總結(jié)出相應(yīng)的規(guī)律,從而制定、調(diào)整和優(yōu)化針對(duì)不同場(chǎng)景的策略??偨Y(jié)這些規(guī)律的具體方法,就是我們要講的算法。在各大互聯(lián)網(wǎng)公司中,算法相關(guān)的崗位招聘越來(lái)越多。除了比較典型的算法工程師(外企中相應(yīng)的崗位為數(shù)據(jù)科學(xué)家),還有數(shù)據(jù)分析工程師、數(shù)據(jù)挖掘工程師和機(jī)器學(xué)習(xí)工程師。這幾個(gè)崗位的工作內(nèi)容既有相同之處,又有不同之處。那么,算法與數(shù)據(jù)分析、數(shù)據(jù)挖掘、機(jī)器學(xué)習(xí)的區(qū)別與聯(lián)系是什么?算法與人工智能之間有什么關(guān)系?帶著這些問(wèn)題,本章為大家打開(kāi)算法之門(mén),揭開(kāi)算法的神秘面紗。1.1打開(kāi)算法之門(mén)1.1.1算法簡(jiǎn)史算法存在的前提是數(shù)據(jù),有數(shù)據(jù)才能有算法。最早關(guān)于人類(lèi)記錄數(shù)據(jù)的例子是公元前18000年前出現(xiàn)的符木。生活在舊石器時(shí)代的部落人民學(xué)會(huì)了在樹(shù)枝上刻下凹痕來(lái)記錄日常的物品供應(yīng)和一些簡(jiǎn)單的交易活動(dòng),并且能夠通過(guò)比較樹(shù)枝的凹痕進(jìn)行基本的計(jì)算,進(jìn)而對(duì)一些事情做出簡(jiǎn)單的預(yù)測(cè),如食物可以?xún)?chǔ)存多久不變質(zhì)。到了公元前4000年左右,在發(fā)源于亞洲西部亞美尼亞高原的幼發(fā)拉底河與底格里斯河河畔(兩河流域),居住著一群人類(lèi)最早的居民——蘇美爾人,他們創(chuàng)造了璀璨的蘇美爾文明,也就是美索不達(dá)米亞文明的開(kāi)端。在像美索不達(dá)米亞那樣極其惡劣的氣候下,知道播種和收獲的準(zhǔn)確時(shí)間是必不可少的,因此有必要找到某種確定時(shí)間的可靠途徑。最簡(jiǎn)單的方法是利用月亮的盈虧循環(huán)。月亮由最初的蛾眉月到下一個(gè)最初的蛾眉月共需要29天半的時(shí)間,人們就考慮將這樣一個(gè)循環(huán)視為一個(gè)基本的計(jì)時(shí)單位(我們將其稱(chēng)為一個(gè)月),然后在月亮累計(jì)運(yùn)行12個(gè)這樣的計(jì)時(shí)單位(6個(gè)29天,6個(gè)30天)后,一“年”就過(guò)去了,又到了開(kāi)始播種的時(shí)候。不幸的是,他們不知道一年實(shí)際上是地球繞太陽(yáng)公轉(zhuǎn)一周的時(shí)間,月亮的12次循環(huán)或12個(gè)月比一個(gè)太陽(yáng)年少11天。在900年后,蘇美爾人才了解到,每隔幾年他們就要在其年歷上另加一個(gè)閏月,才能準(zhǔn)確地預(yù)測(cè)季節(jié)的循環(huán)。通過(guò)感受季節(jié)的周期性更替,結(jié)合對(duì)太陽(yáng)和月亮的觀察,蘇美爾人花了900年的時(shí)間收集數(shù)據(jù),完成了人類(lèi)的第一個(gè)算法模型——太陰(月)歷。隨后,蘇美爾人發(fā)明了度量,包括12單位度量和60單位度量,這便是人類(lèi)最早的十二進(jìn)制和六十進(jìn)制。現(xiàn)在世界各國(guó)通行的時(shí)間度量方法,每天分為24小時(shí),每小時(shí)包含60分鐘,每分鐘包含60秒,鐘表刻度盤(pán)上走一圈為12小時(shí),還有以12為基本計(jì)量單位的“打”,都是在十二進(jìn)制和六十進(jìn)制的基礎(chǔ)上發(fā)展而來(lái)的。在公元前2500年左右,蘇美爾人就已經(jīng)掌握了加、減、乘、除四則運(yùn)算的計(jì)算方法,形成了早期比較簡(jiǎn)單的幾何與代數(shù)方法論。時(shí)間線走到公元前300年左右,一種耳熟能詳?shù)乃惴ā氜D(zhuǎn)相除法,由古希臘數(shù)學(xué)家歐幾里得提出,因此這個(gè)算法又稱(chēng)為歐幾里得算法。輾轉(zhuǎn)相除法的意思是兩個(gè)正整數(shù)a和b(a>b)的最大公約數(shù),等于a除以b的余數(shù)與b的最大公約數(shù)。該算法的具體步驟如下。(1)輸入兩個(gè)正整數(shù)a和b;(2)計(jì)算a除以b的余數(shù)r;(3)如果r等于0,則最大公約數(shù)為當(dāng)前的b值,算法結(jié)束;(4)如果r不等于0,則a=b,b=r,跳轉(zhuǎn)至步驟(2)。在公元100年左右,比較全面的算法研究出現(xiàn)在由我國(guó)古代的張蒼和耿壽昌撰寫(xiě)的《九章算術(shù)》中。作為我國(guó)古代的數(shù)學(xué)名著,《九章算術(shù)》的內(nèi)容十分豐富,全書(shū)采用問(wèn)題集的形式,總結(jié)了自春秋戰(zhàn)國(guó)至秦漢以來(lái)的數(shù)學(xué)成就,對(duì)246個(gè)與生產(chǎn)、生活有聯(lián)系的應(yīng)用問(wèn)題逐一提供了與之相應(yīng)的解決之法。不過(guò),《九章算術(shù)》存在著不可忽視的缺點(diǎn),那就是全書(shū)沒(méi)有任何數(shù)學(xué)概念的定義,在各個(gè)問(wèn)題的解決方法中,也沒(méi)有給出相關(guān)的理論推導(dǎo)與證明。直到三國(guó)時(shí)期,數(shù)學(xué)家劉徽給《九章算術(shù)》作注,才彌補(bǔ)了這個(gè)缺陷。總之,早期的算法研究?jī)A向于計(jì)算和解決與日常生活息息相關(guān)的數(shù)學(xué)問(wèn)題。隨著算法理論的發(fā)展和人類(lèi)科技的進(jìn)步,算法研究逐漸轉(zhuǎn)向研究數(shù)據(jù)本身的規(guī)律和價(jià)值,尤其是在生產(chǎn)與生活中產(chǎn)生的大量數(shù)據(jù)所帶來(lái)的預(yù)測(cè)價(jià)值和決策價(jià)值。到了20世紀(jì)上半葉,數(shù)理統(tǒng)計(jì)學(xué)蓬勃發(fā)展。作為數(shù)學(xué)的一個(gè)重要分支學(xué)科,數(shù)理統(tǒng)計(jì)學(xué)主要研究隨機(jī)數(shù)據(jù)的收集、匯總與分析之法,然后對(duì)相應(yīng)的實(shí)際問(wèn)題做出預(yù)測(cè)和推斷。這期間先后誕生了影響至今的兩大統(tǒng)計(jì)學(xué)派——頻率學(xué)派和貝葉斯學(xué)派。從20世紀(jì)初開(kāi)始,以Fisher和Pearson為主要代表人物的頻率學(xué)派,推動(dòng)數(shù)理統(tǒng)計(jì)學(xué)發(fā)展成為一門(mén)成熟的學(xué)科。頻率學(xué)派從自然的角度出發(fā),試圖直接給事物本身建模,認(rèn)為概率就是頻率,描述數(shù)據(jù)分布的參數(shù)是固定的,可以使用估計(jì)方法得到數(shù)據(jù)分布的參數(shù)值。然而,頻率學(xué)派這種類(lèi)似上帝視角的問(wèn)題切入法,并不能很好地解決所有的實(shí)際問(wèn)題。在20世紀(jì)中葉以后,曾一度被頻率學(xué)派扼殺的貝葉斯統(tǒng)計(jì)迅速發(fā)展壯大起來(lái),和頻率學(xué)派分庭抗禮。貝葉斯學(xué)派否定了頻率學(xué)派的概率就是頻率的觀點(diǎn),并且不從描述事物本身入手,而是從觀察者角度出發(fā),構(gòu)造出了一套在貝葉斯概率體系下,對(duì)事物不確定性做出推斷的框架和方法。當(dāng)然,無(wú)論是頻率學(xué)派,還是貝葉斯學(xué)派,都貢獻(xiàn)了一系列非常實(shí)用的算法并沿用至今。例如,頻率學(xué)派的最大似然估計(jì)(MaximumLikelihoodEstimate,MLE)在神經(jīng)網(wǎng)絡(luò)模型中應(yīng)用廣泛;貝葉斯學(xué)派的蒙特卡羅方法(MonteCarloMethod)在強(qiáng)化學(xué)習(xí)的探索和發(fā)現(xiàn)中起到了非常關(guān)鍵的作用??傊?,兩大學(xué)派的理論都很重要,缺一不可,并無(wú)高下之分。從20世紀(jì)下半葉開(kāi)始,在兩大統(tǒng)計(jì)學(xué)派的激烈博弈中,感知機(jī)學(xué)習(xí)、統(tǒng)計(jì)學(xué)習(xí)、歸納學(xué)習(xí)、淺層學(xué)習(xí)等陸續(xù)萌芽發(fā)展,這類(lèi)研究數(shù)據(jù)本身規(guī)律和價(jià)值的算法,稱(chēng)為機(jī)器學(xué)習(xí)算法。到了20世紀(jì)80年代,機(jī)器學(xué)習(xí)算法逐漸成了一個(gè)獨(dú)立的研究方向。在這段時(shí)間,誕生了大量關(guān)于機(jī)器學(xué)習(xí)的算法,其中一些比較典型的、具有代表性的算法將在后續(xù)的章節(jié)中介紹。注意:為了避免概念混淆,本書(shū)有關(guān)特定數(shù)學(xué)問(wèn)題的算法(前言中提到的信息學(xué)算法,詳見(jiàn)第3章)統(tǒng)稱(chēng)為基礎(chǔ)算法,有關(guān)研究數(shù)據(jù)規(guī)律和價(jià)值的算法(詳見(jiàn)第4章)統(tǒng)稱(chēng)為機(jī)器學(xué)習(xí)算法(或AI算法)。1.1.2算法與人工智能相信有不少讀者是抱著對(duì)人工智能的興趣閱讀本書(shū)的。在比算法世界更大的世界中,人們談?wù)摳嗟囊彩侨斯ぶ悄埽撬惴?。那么,二者到底有什么關(guān)系?人工智能的概念從提出到現(xiàn)在已經(jīng)過(guò)去了半個(gè)多世紀(jì),但是關(guān)于人工智能的定義卻依然存在爭(zhēng)議。我們不妨仔細(xì)審視一下“人工智能”,它由“人工”和“智能”兩個(gè)詞組成。先看“智能”一詞,它的字面意思是智慧和能力。在自然界,智能可以分為個(gè)體智能和群體智能兩種。除了人類(lèi),被廣泛認(rèn)為具備個(gè)體智能的生物還有大猩猩、海豚和章魚(yú)等,具備群體智能的生物有蜂群、蟻群和沙丁魚(yú)群等。在個(gè)體智能中,只能表現(xiàn)興奮和抑制兩種狀態(tài)的人類(lèi)大腦神經(jīng)元,形成了復(fù)雜的思維與智慧。在群體智能中,通過(guò)分泌信息素完成交流的螞蟻,構(gòu)成了分工明確、井然有序的蟻群。從這個(gè)角度來(lái)看,無(wú)論是個(gè)體智能,還是群體智能,都是由大量簡(jiǎn)單行為連接轉(zhuǎn)化而成的。在20世紀(jì)中期,馮·諾依曼受此啟發(fā),提出了元胞自動(dòng)機(jī)(CellularAutomata,CA)。元胞自動(dòng)機(jī)中單個(gè)個(gè)體的算法非常簡(jiǎn)單,其狀態(tài)改變只受周?chē)苯酉噙B的其他個(gè)體狀態(tài)影響。例如,假設(shè)個(gè)體只有0和1兩種狀態(tài),算法設(shè)定個(gè)體本身的狀態(tài)跟隨周?chē)鷤€(gè)體中多數(shù)狀態(tài)值的變化而變化。令人難以置信的是,這些由簡(jiǎn)單算法構(gòu)成的元胞自動(dòng)機(jī),居然成功模擬出了螞蟻、大雁、洄游魚(yú)類(lèi)等動(dòng)物的一些群體智能行為。再看“人工”一詞,字面理解為由人創(chuàng)造。所謂人工智能,就是由人創(chuàng)造的智能。上文提到的由算法驅(qū)動(dòng)的元胞自動(dòng)機(jī)體現(xiàn)出的群體智能行為,就是一種由人創(chuàng)造的智能。所以,人工智能離不開(kāi)算法,算法是產(chǎn)生人工智能的直接工具。1.1.3什么是數(shù)據(jù)分析顧名思義,數(shù)據(jù)分析(DataAnalysis)就是對(duì)數(shù)據(jù)進(jìn)行分析,即對(duì)收集到的數(shù)據(jù)進(jìn)行匯總與統(tǒng)計(jì),并且從中提取和歸納出有價(jià)值的信息。數(shù)據(jù)分析一般會(huì)預(yù)先確定一個(gè)明確的統(tǒng)計(jì)指標(biāo),如總和、均值等;然后采用相應(yīng)的計(jì)算方法和工具,得到預(yù)定統(tǒng)計(jì)指標(biāo)的結(jié)果;最后采用合適的形式將結(jié)果展示出來(lái)。數(shù)據(jù)分析作為算法研究的第一步,從古至今從未改變,如古代關(guān)于天文、歷法研究的第一步就是長(zhǎng)期收集和匯總數(shù)據(jù)。因此,從工作職能上區(qū)分,與算法工程師相比,數(shù)據(jù)分析工程師一般只需專(zhuān)注于數(shù)據(jù)分析模塊。我們通過(guò)一個(gè)實(shí)例表明數(shù)據(jù)分析到底在做什么。例如,“關(guān)于大學(xué)生手機(jī)使用情況調(diào)研”課題,數(shù)據(jù)分析的目標(biāo)之一是統(tǒng)計(jì)各種數(shù)量總和與均值,包括但不限于不同年級(jí)、不同性別的大學(xué)生購(gòu)買(mǎi)和使用不同款式品牌的手機(jī)數(shù)量總和與均值。然后將這些統(tǒng)計(jì)值使用合適的圖表展示出來(lái)。例如,使用條形圖展示“最受男生歡迎的手機(jī)型號(hào)排序”“銷(xiāo)量最高的大學(xué)生手機(jī)型號(hào)排序”“最受大學(xué)生歡迎的手機(jī)品牌排序”的統(tǒng)計(jì)結(jié)果,使用折線圖展示“大學(xué)生每月新購(gòu)的手機(jī)數(shù)量”“大學(xué)生一周中每天的平均通話時(shí)間”的統(tǒng)計(jì)結(jié)果。1.1.4什么是數(shù)據(jù)挖掘顧名思義,數(shù)據(jù)挖掘(DataMining)就是對(duì)數(shù)據(jù)進(jìn)行深入研究,其目的不僅是獲得數(shù)據(jù)統(tǒng)計(jì)分析的表層結(jié)論,更多的是挖掘數(shù)據(jù)與數(shù)據(jù)之間的內(nèi)在關(guān)系。從這個(gè)層面而言,數(shù)據(jù)挖掘的精髓在于探索,探索數(shù)據(jù)潛在的模式、規(guī)律和規(guī)則,是一種深層次的數(shù)據(jù)分析。數(shù)據(jù)挖掘既有基于統(tǒng)計(jì)的算法,又有基于模型的算法。雖然基于模型的算法和機(jī)器學(xué)習(xí)算法存在不少重合之處,但它們的側(cè)重點(diǎn)不同。數(shù)據(jù)挖掘作為機(jī)器學(xué)習(xí)算法研究中承上啟下的一步,比數(shù)據(jù)分析更能深入數(shù)據(jù),并且不完全依賴(lài)于算法模型。因此,與算法工程師相比,數(shù)據(jù)挖掘工程師對(duì)數(shù)據(jù)模式與規(guī)律、規(guī)則等數(shù)據(jù)方面的“嗅覺(jué)”要更敏銳。在“關(guān)于大學(xué)生手機(jī)使用情況調(diào)研”的課題中,基于統(tǒng)計(jì)的數(shù)據(jù)挖掘,可以研究一些特征的共現(xiàn)情況。例如,根據(jù)“視頻”“游戲”“聊天”“拍攝”等標(biāo)簽的分析統(tǒng)計(jì)結(jié)果,結(jié)合固有人群標(biāo)簽(性別、年級(jí)、專(zhuān)業(yè)等)的統(tǒng)計(jì)結(jié)果,可以得出各個(gè)標(biāo)簽之間的關(guān)聯(lián)度分析結(jié)果?;谀P偷臄?shù)據(jù)挖掘,可以研究相似群體。例如,“具備相似手機(jī)使用習(xí)慣的大學(xué)生”有哪幾類(lèi),每個(gè)類(lèi)別下的大學(xué)生分別具備什么樣的特質(zhì),等等。1.1.5什么是機(jī)器學(xué)習(xí)顧名思義,機(jī)器學(xué)習(xí)(MachineLearning)就是讓機(jī)器自己去學(xué)習(xí)。既然讓機(jī)器自己學(xué)習(xí),就需要人工預(yù)先指定一套學(xué)習(xí)規(guī)則,這套既定的學(xué)習(xí)規(guī)則就是機(jī)器學(xué)習(xí)的算法模型。從這個(gè)層面來(lái)說(shuō),機(jī)器學(xué)習(xí)的精髓在于優(yōu)化,即根據(jù)收集到的數(shù)據(jù)樣本,優(yōu)化指定機(jī)器學(xué)習(xí)算法模型中的各項(xiàng)參數(shù)。機(jī)器學(xué)習(xí)作為算法研究的最后一個(gè)環(huán)節(jié),從狹義上來(lái)說(shuō),其重點(diǎn)強(qiáng)調(diào)的是模型的選擇與參數(shù)優(yōu)化的方法。因此,與算法工程師相比,機(jī)器學(xué)習(xí)工程師專(zhuān)注于模型層面的研究。在“關(guān)于大學(xué)生手機(jī)使用情況調(diào)研”的課題中,機(jī)器學(xué)習(xí)可以利用所有能提取到的大學(xué)生特征,基于模型完成某些特定場(chǎng)景中的預(yù)測(cè)或決策任務(wù)。例如,機(jī)器學(xué)習(xí)可以通過(guò)模型預(yù)測(cè)幫助電商平臺(tái)推薦更適合大學(xué)生用戶群體的手機(jī)品牌與型號(hào),通過(guò)模型決策幫助手機(jī)廠商提高面向大學(xué)生手機(jī)市場(chǎng)的投資收益率(ReturnonInvestment,ROI),等等。1.2如何學(xué)習(xí)算法前面介紹了數(shù)據(jù)分析、數(shù)據(jù)挖掘和機(jī)器學(xué)習(xí)三個(gè)概念,并且闡述了三者對(duì)應(yīng)的工程師在工作職能上與算法工程師之間的區(qū)別與聯(lián)系??傮w而言,算法工程師的要求比較全面,既要求懂?dāng)?shù)據(jù)分析,又要求懂算法模型。算法是一個(gè)很大的概念,AI算法的相關(guān)知識(shí)至少涵蓋了數(shù)據(jù)分析、數(shù)據(jù)挖掘、機(jī)器學(xué)習(xí)的相關(guān)知識(shí)。無(wú)論是哪方面的內(nèi)容,所涉及的理論、方法和工具,都能形成一本書(shū)的內(nèi)容。而相關(guān)書(shū)籍之多,加上缺乏較為清晰和完整的學(xué)習(xí)路線,往往讓大部分初學(xué)者望而卻步,面對(duì)龐雜的知識(shí)體系無(wú)從下手。此外,將算法的所有相關(guān)知識(shí)濃縮到一本只有200多頁(yè)的書(shū)中,也是很難辦到的。那么,究竟如何入門(mén)算法比較合適?要學(xué)習(xí)一個(gè)未知領(lǐng)域的知識(shí),一種比較直觀的學(xué)習(xí)方式是,先了解這個(gè)未知領(lǐng)域的核心是什么,把握整個(gè)領(lǐng)域的重要組成部分與大致脈絡(luò),再對(duì)各個(gè)局部領(lǐng)域的延伸與拓展填充學(xué)習(xí),豐富各個(gè)部分的內(nèi)容細(xì)節(jié)。這種學(xué)習(xí)方法的好處有二:其一,盡早對(duì)未知領(lǐng)域有一個(gè)整體的認(rèn)識(shí),可以降低學(xué)習(xí)過(guò)程中的倦怠性,使學(xué)習(xí)更有動(dòng)力;其二,這種學(xué)習(xí)方式能幫助讀者盡早具備未知領(lǐng)域知識(shí)的完整性,有助于在學(xué)習(xí)過(guò)程中宏觀把控學(xué)習(xí)進(jìn)度,使所學(xué)內(nèi)容更有針對(duì)性。基于上述考量,本書(shū)想做的正是這樣一件幫助讀者構(gòu)建算法認(rèn)知骨架的事情。因?yàn)闊o(wú)論是基礎(chǔ)數(shù)學(xué)、基礎(chǔ)算法,還是模型算法、工程實(shí)戰(zhàn),各自展開(kāi)都遠(yuǎn)不止本書(shū)所講內(nèi)容。本書(shū)的主旨中心思想很簡(jiǎn)單,就是給大家展示AI算法世界的全貌。希望本書(shū)在讀者入門(mén)算法的道路上,可以起到拋磚引玉的作用。本書(shū)要論述的知識(shí)面非常廣,對(duì)于各個(gè)環(huán)節(jié)之中未能提及的內(nèi)容和細(xì)節(jié),讀者可以根據(jù)自己的興趣自行查閱相關(guān)資料,進(jìn)行延伸學(xué)習(xí)。1.3本文結(jié)構(gòu)本書(shū)從算法相關(guān)的數(shù)學(xué)基礎(chǔ)開(kāi)始講起,到信息學(xué)競(jìng)賽常用的基礎(chǔ)算法,以及工業(yè)界常用的機(jī)器學(xué)習(xí)算法,再到算法工程的全貌,手把手教大家構(gòu)建自己的第一個(gè)算法工程,然后介紹三大熱門(mén)研究方向的算法進(jìn)階內(nèi)容,最后對(duì)機(jī)器學(xué)習(xí)算法行業(yè)進(jìn)行一定的思考和展望。第1章,算法入門(mén)。本章主要介紹算法的發(fā)展簡(jiǎn)史、算法與人工智能的關(guān)系、算法的相關(guān)概念,以及相關(guān)職位之間的區(qū)別和聯(lián)系,幫助讀者建立對(duì)算法的第一印象。第2章,算法之內(nèi)力。本章主要介紹算法中的幾個(gè)重要的數(shù)學(xué)知識(shí)點(diǎn)。第3章,算法之招式。本章主要介紹常見(jiàn)的幾種基礎(chǔ)算法。第4章,算法之武功秘籍。本章主要介紹常見(jiàn)的幾種機(jī)器學(xué)習(xí)算法。第5章,算法工程的組成部分。本章主要介紹算法工程的組成部分。第6章,算法工程實(shí)戰(zhàn)。本章主要介紹算法工程具體應(yīng)該如何開(kāi)展,并且附帶實(shí)際操作過(guò)程。第7章,進(jìn)階學(xué)習(xí)。本章主要介紹AI算法的三大進(jìn)階內(nèi)容,包括深度學(xué)習(xí)、強(qiáng)化學(xué)習(xí)和遷移學(xué)習(xí)。第8章,思考與展望。本章內(nèi)容是作者關(guān)于算法行業(yè)的思考與展望。關(guān)鍵詞回顧算法人工智能數(shù)據(jù)分析數(shù)據(jù)挖掘機(jī)器學(xué)習(xí)元胞自動(dòng)機(jī)輾轉(zhuǎn)相除法第2章
算法之內(nèi)力數(shù)學(xué)涵蓋的知識(shí)面非常廣,本章會(huì)根據(jù)重要程度篩選出數(shù)學(xué)與算法之間的相關(guān)知識(shí)點(diǎn),包括線性代數(shù)、排列組合、高等數(shù)學(xué)、概率與統(tǒng)計(jì)、最優(yōu)化原理;然后將每個(gè)知識(shí)點(diǎn)細(xì)分為名詞解釋和具體用法兩部分,按照從易到難的順序,盡量采用通俗易懂的語(yǔ)言進(jìn)行講解,幫助讀者修煉算法世界的“內(nèi)力”。算法是一個(gè)比較抽象的概念。往大了說(shuō),所有涉及運(yùn)算的方法都可以稱(chēng)為算法;往小了說(shuō),在信息技術(shù)(InformationTechnology,IT)領(lǐng)域,算法可以是解決數(shù)學(xué)問(wèn)題的方法與技巧,也可以是描述機(jī)器學(xué)習(xí)或數(shù)據(jù)挖掘的相關(guān)方法,本書(shū)會(huì)從這兩個(gè)方面展開(kāi)剖析。講清楚什么是算法并不是一件容易的事情,完整且淺顯易懂地講明白更是難上加難。算法涵蓋了很多相關(guān)學(xué)科的基礎(chǔ)概念與知識(shí)點(diǎn),涉及的名詞解釋與概念介紹較為生澀,難免會(huì)降低讀者的學(xué)習(xí)興趣。作為一本算法知識(shí)普及圖書(shū),本書(shū)涵蓋的每部分內(nèi)容雖然不必太深,但必須全面。因此,如何保證本書(shū)的閱讀趣味性、內(nèi)容的完整性與連貫性,在提筆寫(xiě)書(shū)之前的很長(zhǎng)一段時(shí)間里,困擾了我很久。直到后來(lái)重看古裝電視劇《天龍八部》才猛然發(fā)現(xiàn),本書(shū)所要講的算法,和金庸先生筆下的武功體系,其實(shí)有著異曲同工之妙。金庸武俠,聞名遐邇。說(shuō)到金庸先生筆下的武功體系,無(wú)外乎兩大方面:內(nèi)力和招式??催^(guò)《天龍八部》的讀者應(yīng)該知道,聚賢莊一役,被逐出丐幫的蕭峰義字當(dāng)頭,對(duì)戰(zhàn)中并沒(méi)有使用半招降龍十八掌,而是只用了一套普普通通的太祖長(zhǎng)拳,就將圍攻他的武林高手打得落花流水,節(jié)節(jié)敗退。為什么?憑的就是他深厚雄渾的內(nèi)力。由此可見(jiàn),一旦具備了深厚的內(nèi)力,普通招式也能發(fā)揮出強(qiáng)大的威力。而在算法的世界中,數(shù)學(xué)功底即“內(nèi)力”,只有將數(shù)學(xué)這門(mén)“內(nèi)力”修煉好,才能讓算法在實(shí)際應(yīng)用中發(fā)揮出強(qiáng)大的作用。2.1線性代數(shù)線性代數(shù)是數(shù)學(xué)的一門(mén)分支學(xué)科,研究的是線性空間中的函數(shù)問(wèn)題。顧名思義,“線性”是指要研究的代數(shù)之間的關(guān)系是簡(jiǎn)單的一次關(guān)系,研究過(guò)程中沒(méi)有復(fù)雜的數(shù)學(xué)運(yùn)算(如平方和開(kāi)方);“代數(shù)”是指用符號(hào)代替數(shù)字,方便研究。對(duì)于數(shù)學(xué)關(guān)系f(x+y)=f(x)+f(y),線性代數(shù)不關(guān)心其中x和y的具體含義是什么,其研究的是擁有這種線性映射關(guān)系的函數(shù)f所具備的性質(zhì)。函數(shù)是指輸入一個(gè)數(shù),在經(jīng)過(guò)某些計(jì)算后輸出另一個(gè)數(shù)。隨著研究的問(wèn)題越來(lái)越復(fù)雜,有時(shí)需要輸入多個(gè)數(shù),然后經(jīng)過(guò)運(yùn)算輸出多個(gè)數(shù)。從這個(gè)角度來(lái)說(shuō),線性代數(shù)解決的就是多輸入或多輸出的函數(shù)問(wèn)題。2.1.1名詞解釋在線性代數(shù)中,單個(gè)數(shù)稱(chēng)為標(biāo)量,用中括號(hào)括起來(lái)的多個(gè)輸入的數(shù)或多個(gè)輸出的數(shù)(多個(gè)標(biāo)量)稱(chēng)為向量和矩陣。標(biāo)量、向量和矩陣是算法工程中經(jīng)常用到的線性代數(shù)核心概念。下面從數(shù)學(xué)角度給出標(biāo)量、向量和矩陣的概念,以便加深讀者對(duì)線性代數(shù)基本概念的理解。?標(biāo)量:表示一個(gè)簡(jiǎn)單的數(shù),如29、31等。?向量:表示一組有序的標(biāo)量,能夠?qū)懗梢恍谢蛞涣械男问健?矩陣:表示一組有序的向量(一個(gè)或多個(gè)),可以用二維數(shù)組的形式表示。下面來(lái)看一個(gè)例子。假設(shè)某家包子鋪周一能賣(mài)出50個(gè)肉包,這里的“50”就是一個(gè)標(biāo)量;如果這家包子鋪某周每天賣(mài)出的包子數(shù)量依次是[50,51,52,53,52,48,45],則“[50,51,52,53,52,48,45]”是一個(gè)向量;加上這周每天賣(mài)出的豆沙包、咸菜包的數(shù)量,組成如下數(shù)據(jù)形式,就是一個(gè)矩陣。2.1.2向量和矩陣標(biāo)量的概念比較簡(jiǎn)單,因此我們重點(diǎn)講解向量和矩陣。向量和矩陣在算法工程中經(jīng)常用到。例如,一條樣本的所有特征值構(gòu)成一個(gè)向量,一批樣本的所有特征值構(gòu)成一個(gè)矩陣。幾乎所有的算法公式都可以寫(xiě)成向量或矩陣的形式,機(jī)器學(xué)習(xí)中的算法模型通常所說(shuō)的批(batch)訓(xùn)練,其底層的計(jì)算邏輯就是利用向量和矩陣的運(yùn)算。由此可見(jiàn),掌握向量和矩陣的相關(guān)知識(shí),對(duì)于算法“內(nèi)力”的修煉至關(guān)重要。既然涉及運(yùn)算,自然會(huì)有相應(yīng)的運(yùn)算法則,那么向量和矩陣的運(yùn)算法則是怎么樣的呢?向量可以分為行向量和列向量,二者在本質(zhì)上并無(wú)區(qū)別,只在進(jìn)行運(yùn)算時(shí)有差別。下面通過(guò)生活中的具體例子,逐一介紹與向量有關(guān)的運(yùn)算法則。某公司有n名員工,月工資用向量[a1,a2,…,an-1,an]表示,其中ai表示第i個(gè)員工的月工資數(shù)額。情形一:公司業(yè)績(jī)不錯(cuò),公司老板決定給每位員工漲薪20%,可以用向量與標(biāo)量之間的乘法來(lái)計(jì)算漲薪后的工資,如表2-1所示,其中k為原工資倍數(shù),即1.2。表2-1員工漲薪情況(一)具體計(jì)算方法用數(shù)學(xué)符號(hào)表示如下,得到的結(jié)果仍然是向量。向量與標(biāo)量之間的除法類(lèi)似,可以理解為向量與標(biāo)量的倒數(shù)相乘。情形二:公司業(yè)績(jī)不錯(cuò),根據(jù)員工完成業(yè)績(jī)的不同,老板決定對(duì)不同的員工給出相應(yīng)的工資漲幅。以絕對(duì)值漲幅為例(也可以是不同的比例漲幅),給第i位員工每月增加bi元工資,可以用行(列)向量與行(列)向量之間的加法來(lái)計(jì)算漲薪后的工資,如表2-2所示。表2-2員工漲薪情況(二)具體計(jì)算方法用數(shù)學(xué)符號(hào)表示如下,計(jì)算結(jié)果仍然是向量。向量與向量之間的減法與加法類(lèi)似,計(jì)算結(jié)果仍然是向量。情形三:老板在按照不同的漲幅比例給員工漲薪之后,想知道工資開(kāi)支的總預(yù)算是多少,可以用行向量與列向量之間的乘法來(lái)計(jì)算。具體計(jì)算方法如下。由此可知,行向量與列向量相乘的結(jié)果是一個(gè)標(biāo)量。根據(jù)行向量與列向量相乘的例子可知,使運(yùn)算成立的一個(gè)隱含條件是,行向量的列數(shù)必須與列向量的行數(shù)相等,如例子中的向量長(zhǎng)度均為n,這有助于理解后面的矩陣運(yùn)算(向量是一種特殊的矩陣)。列向量的列數(shù)與行向量的行數(shù)都等于1。一個(gè)列向量與一個(gè)行向量相乘,即可得到一個(gè)矩陣,具體計(jì)算方法如下。在機(jī)器學(xué)習(xí)中,向量通常用于表示特定維度空間中不同維度的特征值,因此又稱(chēng)為特征向量。例如,一個(gè)二維特征向量[1,2]表示兩個(gè)特征,第一個(gè)特征維度的值為1,第二個(gè)特征維度的值為2。既然是空間,那就存在距離的概念,即同一個(gè)特征空間中不同特征向量之間存在著某種關(guān)系,如相似的特征表現(xiàn)。假設(shè)有另一個(gè)二維特征向量[2,4],其在兩個(gè)特征維度上的值分別為2和4,可以發(fā)現(xiàn),這個(gè)二維特征向量和前面的二維特征向量,在各個(gè)維度上的特征值大小恰好相差一倍,這說(shuō)明二者的特征表現(xiàn)相似,只是程度不同。當(dāng)然,在實(shí)際算法工程中,特征向量之間的關(guān)系會(huì)有更復(fù)雜的度量方式,如相似度、相關(guān)系數(shù)等。矩陣運(yùn)算和向量運(yùn)算的運(yùn)算法則類(lèi)似。標(biāo)量與矩陣的加法、減法、乘法,只需將標(biāo)量與向量的每一個(gè)值分別相加、相減、相乘,得到的結(jié)果仍是矩陣。以標(biāo)量與矩陣的乘法為例,計(jì)算方法如下。矩陣與向量之間只有乘法。如果矩陣與行向量相乘,那么行向量的列數(shù)必須與矩陣的行數(shù)相等,并且行向量必須位于乘號(hào)的左邊,計(jì)算方法如下。如果矩陣與列向量相乘,那么列向量的行數(shù)必須與矩陣的列數(shù)相等,并且列向量必須位于乘號(hào)的右邊,計(jì)算方法如下。矩陣與矩陣相乘,乘號(hào)左邊矩陣的列數(shù)必須與乘號(hào)右邊矩陣的行數(shù)相等,計(jì)算方法如下。假設(shè)A、B、C表示矩陣。矩陣之間的加法滿足交換律,計(jì)算公式如下。矩陣之間的乘法滿足結(jié)合律,計(jì)算公式如下。在線性代數(shù)中,關(guān)于向量和矩陣的知識(shí)點(diǎn)還有很多,包括單位矩陣、對(duì)角矩陣、對(duì)稱(chēng)矩陣等,這些知識(shí)點(diǎn)在PCA降維、協(xié)同過(guò)濾和矩陣分解等算法中都有所運(yùn)用,下文只對(duì)這些概念進(jìn)行簡(jiǎn)單介紹,感興趣的讀者可以自行深入拓展學(xué)習(xí)。單位矩陣是一個(gè)方陣,這個(gè)方陣從左上角到右下角的對(duì)角線(稱(chēng)為主對(duì)角線)上的元素均為1,其他元素均為0,示例如下。對(duì)角矩陣也是一個(gè)方陣,這個(gè)方陣除主對(duì)角線上的元素外,其他元素均為0,主對(duì)角線上的元素可以不為1,示例如下。由此可知,單位矩陣屬于對(duì)角矩陣。對(duì)稱(chēng)矩陣也是一個(gè)方陣,這個(gè)方陣只需滿足以主對(duì)角線為對(duì)稱(chēng)軸,兩邊對(duì)稱(chēng)位置的元素相等,示例如下。由此可知,單位矩陣和對(duì)角矩陣都屬于對(duì)稱(chēng)矩陣。2.2排列組合大部分讀者應(yīng)該對(duì)排列組合比較熟悉,因?yàn)樗诟咧械臄?shù)學(xué)課上出現(xiàn)過(guò)。與解析幾何相比,排列組合的公式簡(jiǎn)單,并且理解起來(lái)比較容易、直觀。排列組合包含兩個(gè)概念:排列和組合。舉個(gè)例子,假設(shè)某小組一共有5個(gè)人,有以下兩個(gè)問(wèn)題。①?gòu)脑撔〗M中選出3個(gè)人站成一排,一共有多少種排法?②從該小組中選出3個(gè)人打掃衛(wèi)生,一共有多少種選法?對(duì)比問(wèn)題①和問(wèn)題②可以發(fā)現(xiàn),問(wèn)題①需要考慮順序,問(wèn)題②不需要考慮順序。這便是排列與組合的區(qū)別。問(wèn)題①要計(jì)算排列種類(lèi)數(shù),排列用字母P(Permutation)或A(Arrangement)表示;問(wèn)題②要計(jì)算組合種類(lèi)數(shù),組合用字母C(Combination)表示。在計(jì)算時(shí),組合種類(lèi)可以看作排列種類(lèi)的子集。可以用形式化的語(yǔ)言描述排列問(wèn)題,即n個(gè)人中計(jì)算m個(gè)人的排列。繼續(xù)思考前面的例子,如果要從5個(gè)人中選3個(gè)人站成一排,那么應(yīng)該如何選擇并排列?首先,從5個(gè)人中選擇1個(gè)人站在位置1上,有5種選法;然后從剩下的4個(gè)人中選擇1個(gè)人站在位置2上,共有4種選法;最后從剩下的3個(gè)人中選出1個(gè)人站在位置3上,一共有3種選法;因此共有60(5×4×3)種排列方法。這種計(jì)算方法就是階乘。使用字母A表示排列,具體計(jì)算公式如下。由于組合不用考慮選出來(lái)的人的排列順序,因此,只需用計(jì)算出來(lái)的排列方法總數(shù)除以選出人數(shù)的排列方法總數(shù)。所有排列方法叫作全排列,n個(gè)人的全排列總數(shù)等于n的階乘。對(duì)于前面的例子,組合方法總數(shù)就是10(60/3!)種。使用字母C表示組合,具體計(jì)算公式如下。在AI算法中,排列組合主要用于計(jì)算特征組合(交叉)后的特征總數(shù)。2.3高等數(shù)學(xué)看到這節(jié),你可能會(huì)問(wèn):搞AI算法還需要學(xué)習(xí)高等數(shù)學(xué)?大家知道,高等數(shù)學(xué)涵蓋的知識(shí)點(diǎn)比較多,并且比較難以理解。別擔(dān)心,本書(shū)只講解高等數(shù)學(xué)中與AI算法最相關(guān)的兩個(gè)知識(shí)點(diǎn)——導(dǎo)數(shù)和梯度。這兩個(gè)知識(shí)點(diǎn)在AI算法的公式推導(dǎo)中至關(guān)重要,有助于幫助我們理解算法模型在實(shí)際應(yīng)用中起作用的原因。2.3.1導(dǎo)數(shù)簡(jiǎn)單地說(shuō),導(dǎo)數(shù)主要用于描述函數(shù)圖像中某一點(diǎn)切線的傾斜程度,這個(gè)傾斜程度又稱(chēng)為斜率。所謂連續(xù)函數(shù),就是函數(shù)圖像隨著x值的連續(xù)變化,y值的變化也是連續(xù)的。連續(xù)函數(shù)不一定處處可導(dǎo),可導(dǎo)函數(shù)的圖像一定是處處連續(xù)的。三角函數(shù)處處連續(xù),同時(shí)處處可導(dǎo)。以正弦函數(shù)y=sinx為例,函數(shù)圖像上的每個(gè)點(diǎn)都是光滑的,可以計(jì)算函數(shù)圖像在該點(diǎn)處的切線斜率,如圖2-1所示。圖2-1正弦函數(shù)y=sinx的圖像如圖2-2所示,用線性絕對(duì)值函數(shù)y=|x|作為對(duì)比,可以看到該函數(shù)圖像同樣處處連續(xù)。但是,在坐標(biāo)為(0,0)的點(diǎn)的位置雖然連續(xù),卻無(wú)法計(jì)算出切線的斜率,因此該函數(shù)是不可導(dǎo)的。圖2-2線性絕對(duì)值函數(shù)y=|x|的圖像在中學(xué)數(shù)學(xué)中,通常使用極限求解導(dǎo)數(shù)。在AI算法中不用那么復(fù)雜,只需掌握以下兩點(diǎn)。第一,弄清楚導(dǎo)數(shù)的意義。導(dǎo)數(shù)是函數(shù)切線的斜率,因此可以用于表示函數(shù)值變化的快慢和趨勢(shì)。例如,朝著變大的方向還是變小的方向,變大變小的速度如何,等等。第二,記住AI算法中常用的幾個(gè)求導(dǎo)公式及導(dǎo)數(shù)的運(yùn)算法則。下面介紹AI算法中常用的幾個(gè)求導(dǎo)公式。常數(shù)求導(dǎo)公式如下。(C)'=0冪函數(shù)的求導(dǎo)公式如下。指數(shù)函數(shù)求導(dǎo)公式如下。對(duì)數(shù)函數(shù)求導(dǎo)公式如下。自然對(duì)數(shù)函數(shù)求導(dǎo)公式如下。現(xiàn)有函數(shù)u和函數(shù)v,函數(shù)四則運(yùn)算的求導(dǎo)法則如下。函數(shù)加減法的求導(dǎo)法則如下。函數(shù)乘法的求導(dǎo)法則如下。函數(shù)除法的求導(dǎo)法則如下。此外,在使用神經(jīng)網(wǎng)絡(luò)的AI算法中,神經(jīng)元的層數(shù)一般不止一層,相鄰層的輸出是下一層的輸入,即一個(gè)函數(shù)的因變量是另一個(gè)函數(shù)的自變量,在求導(dǎo)過(guò)程中會(huì)用到一種稱(chēng)為鏈?zhǔn)椒▌t的復(fù)合函數(shù)求導(dǎo)方法。復(fù)合函數(shù)f(x)=g[h(x)]的鏈?zhǔn)椒▌t如下。f'(x)=g'[h(x)]h'(x)此外,AI算法中的特征維數(shù)通常不止一維,即多維自變量。包含多維自變量的函數(shù)稱(chēng)為多維函數(shù),多維函數(shù)的導(dǎo)數(shù)稱(chēng)為偏導(dǎo)數(shù)。偏導(dǎo)數(shù)的求法很簡(jiǎn)單,在對(duì)多維函數(shù)中的某一維變量求導(dǎo)時(shí),將其他維變量視為常量即可。2.3.2梯度函數(shù)的導(dǎo)數(shù)值又稱(chēng)為梯度,梯度是帶有方向的,多維自變量所在的每個(gè)維度均代表一個(gè)方向。在AI算法中,特征數(shù)據(jù)通常是多維的,每個(gè)維度都有一個(gè)梯度,不同維度上的自變量對(duì)應(yīng)的偏導(dǎo)數(shù)大小不一樣,梯度的大小也就不一樣。在算法訓(xùn)練過(guò)程中常說(shuō)的某個(gè)特征學(xué)得快一點(diǎn),就是因?yàn)檫@個(gè)特征在維度方向上的梯度較大。梯度傳遞是算法訓(xùn)練過(guò)程中的一個(gè)重點(diǎn),其中的梯度消失和梯度爆炸問(wèn)題會(huì)嚴(yán)重影響模型的最終效果,這部分內(nèi)容將在第4章詳細(xì)講解。2.4概率與統(tǒng)計(jì)2.4.1名詞解釋在學(xué)習(xí)新概念之前,掌握常見(jiàn)的名詞解釋?zhuān)帽仍谙聫N炒菜時(shí)能熟練說(shuō)出調(diào)料名和菜名一樣,有助于我們加深對(duì)每個(gè)環(huán)節(jié)的了解,讓學(xué)習(xí)過(guò)程變得更加順暢。此外,準(zhǔn)確理解并說(shuō)出相應(yīng)的名詞概念,也是一種專(zhuān)業(yè)表現(xiàn)。1.概率統(tǒng)計(jì)研究自然界中隨機(jī)現(xiàn)象統(tǒng)計(jì)規(guī)律的數(shù)學(xué)方法,稱(chēng)為概率統(tǒng)計(jì),又稱(chēng)為數(shù)理統(tǒng)計(jì)。概率統(tǒng)計(jì)主要的研究對(duì)象為隨機(jī)事件、隨機(jī)變量及隨機(jī)過(guò)程。2.隨機(jī)事件概率統(tǒng)計(jì)統(tǒng)計(jì)的是隨機(jī)事件發(fā)生的概率。隨機(jī)事件是指在大量的重復(fù)實(shí)驗(yàn)中發(fā)生的概率具有某種規(guī)律的事件。例如,拋擲同一枚硬幣,“正面朝上”就是一個(gè)典型的隨機(jī)事件。隨機(jī)事件通常簡(jiǎn)稱(chēng)為事件。事件之間的基本關(guān)系如表2-3所示。表2-3事件之間的基本關(guān)系和集合運(yùn)算一樣,事件之間的運(yùn)算也具備以下3個(gè)性質(zhì)。?交換律:A∪B=B∪A,A∩B=B∩A。?結(jié)合律:A∪B∪C=A∪(B∪C),A∩B∩C=A∩(B∩C)。?分配律:A∩(B∪C)=(A∩B)∪(A∩C),A∪(B∩C)=(A∪B)∩(A∪C)。3.隨機(jī)變量事件會(huì)發(fā)生就會(huì)有結(jié)果,可以使用隨機(jī)變量描述隨機(jī)事件可能發(fā)生的結(jié)果,如拋十次硬幣正面朝上的次數(shù)、某個(gè)地鐵站每天的上車(chē)人數(shù)、燈管的壽命、某個(gè)班級(jí)學(xué)生的身高和體重等。4.離散型隨機(jī)變量和連續(xù)型隨機(jī)變量拋硬幣正面朝上的次數(shù)和地鐵站的上車(chē)人數(shù)都是可數(shù)的,最小單位是1,在數(shù)學(xué)中稱(chēng)為離散,這類(lèi)隨機(jī)變量稱(chēng)為離散型隨機(jī)變量。燈管壽命、人的身高體重的取值是連續(xù)的,沒(méi)有最小單位,在數(shù)學(xué)中稱(chēng)為連續(xù),這類(lèi)隨機(jī)變量稱(chēng)為連續(xù)型隨機(jī)變量。5.隨機(jī)過(guò)程簡(jiǎn)單而言,隨機(jī)過(guò)程就是隨機(jī)變量隨某個(gè)參數(shù)變化的過(guò)程,這個(gè)參數(shù)通常是時(shí)間,如周一至周五某個(gè)地鐵站隨時(shí)間變化的候車(chē)人數(shù)。6.數(shù)學(xué)期望拋擲一枚質(zhì)地均勻的硬幣,正反兩面出現(xiàn)的概率各占一半,在進(jìn)行足夠數(shù)量的拋擲實(shí)驗(yàn)后,正反兩面實(shí)際出現(xiàn)的次數(shù)會(huì)各自接近50%,這個(gè)50%就是數(shù)學(xué)期望。數(shù)學(xué)期望反映的是隨機(jī)變量的平均值,其計(jì)算方法是用實(shí)驗(yàn)中事件的發(fā)生概率乘重復(fù)實(shí)驗(yàn)的總次數(shù),一般用字母μ或E表示。7.方差顧名思義,方差是某種差值,主要用于衡量隨機(jī)變量的實(shí)際取值與其數(shù)學(xué)期望之間的偏離程度,計(jì)算公式如下。E{[X–E(X)]2}8.標(biāo)準(zhǔn)差標(biāo)準(zhǔn)差是方差的算術(shù)平方根。9.協(xié)方差協(xié)方差是指方差的多變量擴(kuò)展,主要用于衡量?jī)蓚€(gè)隨機(jī)變量X和Y之間的總體誤差,計(jì)算公式如下。E{[X–E(X)][Y–E(Y)]}10.概率分布概率分布主要用于描述隨機(jī)變量在隨機(jī)事件中表現(xiàn)出來(lái)的一種狀態(tài),是概率關(guān)于隨機(jī)變量的函數(shù)。11.概率密度可以將概率密度直觀地理解為事件發(fā)生的結(jié)果落在隨機(jī)變量某段取值范圍內(nèi)的概率。從數(shù)學(xué)角度來(lái)說(shuō),就是概率分布函數(shù)在某段區(qū)間內(nèi)的積分。有讀者可能已經(jīng)發(fā)現(xiàn),只有連續(xù)型隨機(jī)變量才有概率密度,離散型隨機(jī)變量對(duì)應(yīng)的概念為概率質(zhì)量。12.條件概率顧名思義,條件概率是指事件滿足一定條件所發(fā)生的概率。在通常情況下,兩個(gè)事件A和B,P(A|B)表示在事件B發(fā)生的前提下,事件A發(fā)生的概率。2.4.2概率分布日常生活中到處都有概率分布的身影,本節(jié)按照從易到難的思路,給大家講解最常見(jiàn)的幾種概率分布。1.伯努利分布伯努利分布是最簡(jiǎn)單的概率分布,隨機(jī)變量只能是離散型隨機(jī)變量,只有兩種取值(事件成功取1,失敗取0)。生活中的伯努利分布有很多。例如,明天是否下雨,雷霆隊(duì)下一場(chǎng)對(duì)勇士隊(duì)的比賽是否能贏,等等。伯努利分布的數(shù)學(xué)期望如下。μ=p伯努利分布的概率質(zhì)量函數(shù)如下。2.均勻分布均勻分布的隨機(jī)變量可以是離散型隨機(jī)變量,也可以是連續(xù)型隨機(jī)變量,隨機(jī)變量不同取值出現(xiàn)的概率相等,如搖骰子就是典型的均勻分布。均勻分布的數(shù)學(xué)期望如下。均勻分布的連續(xù)型隨機(jī)變量的概率密度函數(shù)如下。均勻分布的連續(xù)型隨機(jī)變量的概率密度函數(shù)圖像如圖2-3所示(假設(shè)b=2,a=1)。圖2-3均勻分布的連續(xù)型隨機(jī)變量的概率密度函數(shù)圖像3.二項(xiàng)分布顧名思義,二項(xiàng)分布就是取值只有正、負(fù)兩種結(jié)果的概率分布,因此其隨機(jī)變量只能是離散型隨機(jī)變量。用數(shù)學(xué)語(yǔ)言描述就是,關(guān)于n個(gè)獨(dú)立的二值實(shí)驗(yàn)中有多少次為正的離散型概率分布。二項(xiàng)分布最典型的例子是拋硬幣實(shí)驗(yàn),拋n次硬幣,k次正面朝上的概率對(duì)應(yīng)的數(shù)學(xué)期望如下。μ=np根據(jù)排列組合,二項(xiàng)分布的概率質(zhì)量函數(shù)如下。當(dāng)p=0.5、n=12時(shí),二項(xiàng)分布的概率質(zhì)量函數(shù)圖像如圖2-4所示。圖2-4二項(xiàng)分布的概率質(zhì)量函數(shù)圖像(p=0.5,n=12)4.幾何分布和二項(xiàng)分布一樣,幾何分布的隨機(jī)變量也只能是離散型隨機(jī)變量。與二項(xiàng)分布不同,幾何分布關(guān)心的是事件(或?qū)嶒?yàn))發(fā)生n次,在第x次取得成功的概率。典型的例子是打靶,在n次打靶過(guò)程中第一次命中靶心的概率。幾何分布的數(shù)學(xué)期望如下。幾何分布的概率質(zhì)量函數(shù)如下。當(dāng)p=0.5時(shí),幾何分布的概率質(zhì)量函數(shù)圖像如圖2-5所示。圖2-5幾何分布的概率質(zhì)量函數(shù)圖像(p=0.5)5.泊松分布在計(jì)算二項(xiàng)分布的概率分布時(shí),如果需要計(jì)算發(fā)生k次的概率,那么在二項(xiàng)分布中必須事先知道一個(gè)全局的n。然而,在實(shí)際問(wèn)題中很難或無(wú)法預(yù)先知道對(duì)應(yīng)的n是多少,如潛在乘坐公交車(chē)的乘客總數(shù)、潛在需要去銀行辦理業(yè)務(wù)的客戶總數(shù)、潛在包子鋪顧客總數(shù)等??倲?shù)n未知,難道就沒(méi)有辦法求概率P了嗎?聰明的你應(yīng)該已經(jīng)聯(lián)想到了取n的極限來(lái)求解P。沒(méi)錯(cuò),取n的極限來(lái)求解P正是泊松分布的推導(dǎo)過(guò)程。根據(jù)二項(xiàng)分布的數(shù)學(xué)期望μ=np可以推導(dǎo)出泊松分布的推導(dǎo)過(guò)程如下。將上式各部分拆開(kāi)計(jì)算,根據(jù)指數(shù)e的下述極限計(jì)算方法,代入極限求解,P最終變成了只與k、μ相關(guān)的式子。根據(jù)泊松分布的推導(dǎo)過(guò)程可知,泊松分布是二項(xiàng)分布的極限形式,因此隨機(jī)變量也只能是離散型隨機(jī)變量。泊松分布的概率質(zhì)量函數(shù)如下。當(dāng)μ=0.9時(shí),泊松分布的概率質(zhì)量函數(shù)圖像如圖2-6所示。圖2-6泊松分布的概率質(zhì)量函數(shù)圖像(μ=0.9)根據(jù)泊松分布的概率質(zhì)量函數(shù),已知均值μ,不需要知道總數(shù)n,就可以求得k值對(duì)應(yīng)的概率。6.指數(shù)分布對(duì)于泊松分布,如果將時(shí)間長(zhǎng)度納入考慮,就可以描述在某段時(shí)間內(nèi),事件的發(fā)生概率,而指數(shù)分布主要用于描述事件的時(shí)間間隔概率,如一家醫(yī)院嬰兒的出生時(shí)間間隔、一家網(wǎng)站的訪問(wèn)時(shí)間間隔等。因此,指數(shù)分布的隨機(jī)變量是離散型隨機(jī)變量,數(shù)學(xué)期望如下。指數(shù)分布的概率質(zhì)量函數(shù)可以通過(guò)泊松分布推導(dǎo)而來(lái),具體如下。當(dāng)λ=0.8時(shí),指數(shù)分布的概率質(zhì)量函數(shù)圖像如圖2-7所示。圖2-7指數(shù)分布的概率質(zhì)量函數(shù)圖像(λ=0.8)7.高斯分布高斯分布即正態(tài)分布,是生活中出現(xiàn)頻率很高的一種概率分布,如一所學(xué)校所有學(xué)生的身高和體重、某一科考試的分?jǐn)?shù)都服從高斯分布。雖然稱(chēng)為高斯分布,但并不是數(shù)學(xué)家高斯提出的。其實(shí)早在高斯之前就有正態(tài)分布了,只是高斯率先將正態(tài)分布應(yīng)用于天文學(xué)研究,他的研究對(duì)后世影響較大,因此稱(chēng)為高斯分布。高斯分布的概率密度函數(shù)如下。高斯分布的概率密度函數(shù)圖像如圖2-8所示。圖2-8高斯分布的概率密度函數(shù)圖像2.5最優(yōu)化原理最優(yōu)化原理是應(yīng)用數(shù)學(xué)的一個(gè)分支,是關(guān)于最優(yōu)設(shè)計(jì)、最優(yōu)控制、最優(yōu)管理問(wèn)題的理論與方法。AI算法要解決的大部分問(wèn)題都是在尋找一組適配模型的最優(yōu)參數(shù)解,都可以歸結(jié)為最優(yōu)化問(wèn)題。最優(yōu)化問(wèn)題就是將問(wèn)題先用最優(yōu)化的方法建立數(shù)學(xué)模型,再以最優(yōu)化的方式求解。最優(yōu)化問(wèn)題分為有約束的最優(yōu)化問(wèn)題和無(wú)約束的最優(yōu)化問(wèn)題。有約束的最優(yōu)化問(wèn)題分為等式約束優(yōu)化問(wèn)題和不等式約束優(yōu)化問(wèn)題,這類(lèi)問(wèn)題通常使用拉格朗日乘數(shù)法和KKT條件解決;無(wú)約束的最優(yōu)化問(wèn)題分為全局最優(yōu)化問(wèn)題和局部最優(yōu)化問(wèn)題,這類(lèi)問(wèn)題可以使用牛頓法和最小二乘法解決。最優(yōu)化問(wèn)題還有一個(gè)分支,叫作凸優(yōu)化。凸優(yōu)化的局部最優(yōu)解就是全局最優(yōu)解。而大部分AI算法問(wèn)題,其實(shí)都是在解決凸優(yōu)化問(wèn)題。解決凸優(yōu)化問(wèn)題的方法是梯度下降法,大致步驟如下:首先初始化算法模型的參數(shù)權(quán)重,然后依據(jù)樣本數(shù)據(jù)計(jì)算誤差和梯度,最后根據(jù)梯度下降法優(yōu)化各參數(shù)權(quán)重,直到誤差下降到可接受范圍內(nèi),訓(xùn)練結(jié)束。最優(yōu)化問(wèn)題的學(xué)術(shù)理論要求較高,本書(shū)的側(cè)重點(diǎn)并不在于此,感興趣的讀者可以自行深入學(xué)習(xí)。2.6動(dòng)腦時(shí)刻1.石頭平時(shí)比較喜歡自己在家里榨果汁,主要使用5種原材料:杧果、草莓、香蕉、牛奶和木瓜。石頭在榨果汁時(shí)常用的4種配方如表2-4所示,5種原材料在不同超市的售賣(mài)價(jià)格如表2-5所示。以矩陣運(yùn)算的形式計(jì)算這4種果汁配方的成本分別是多少。表2-4石頭在榨果汁時(shí)常用的4種配方(單位:份)表2-55種原材料在不同超市的售賣(mài)價(jià)格(單位:元/份)2.假設(shè)模型中有5個(gè)特征,通過(guò)特征之間的任意交叉組合,最多可以增加多少個(gè)特征?3.5個(gè)人圍成一圈做游戲,一共有多少種不同的圍法?4.在概率統(tǒng)計(jì)中,標(biāo)準(zhǔn)差是方差的算術(shù)平方根,既然有了方差,為什么還需要標(biāo)準(zhǔn)差?5.已知包子鋪歷史每天平均賣(mài)出μ=100個(gè)包子,為了保證未來(lái)每天不夠賣(mài)的概率低于10%,每天最少需要準(zhǔn)備多少個(gè)包子?(已知服從泊松分布)6.某醫(yī)院平均每小時(shí)出生3個(gè)嬰兒,在接下來(lái)的第15~30分鐘,有嬰兒出生的概率是多少?(已知服從指數(shù)分布)2.7本章小結(jié)本章首先講解了線性代數(shù)中的向量和矩陣,這兩個(gè)概念對(duì)AI算法而言是最基本的數(shù)據(jù)承載體。然后講解了與AI算法有關(guān)的排列組合及高等數(shù)學(xué)中的幾個(gè)知識(shí)點(diǎn)。緊接著詳細(xì)講解了概率與統(tǒng)計(jì)。如果AI算法從業(yè)者對(duì)數(shù)據(jù)具備良好的概率與統(tǒng)計(jì)素養(yǎng),那么在解決實(shí)際問(wèn)題時(shí),會(huì)將模型運(yùn)用得更深刻、全面。最后簡(jiǎn)單講解了什么是最優(yōu)化原理。本章內(nèi)容都是與算法有關(guān)的數(shù)學(xué)基礎(chǔ)知識(shí),在語(yǔ)言描述上難免會(huì)有些晦澀??紤]到AI算法中數(shù)學(xué)知識(shí)的實(shí)際使用概率,以及本書(shū)希望面向的廣大受眾,本章只講解了相關(guān)數(shù)學(xué)基礎(chǔ)知識(shí)最核心的知識(shí)點(diǎn),章節(jié)末尾的動(dòng)腦時(shí)刻也盡量避免了生僻的數(shù)學(xué)公式。這樣做的目的只有一個(gè),就是讓讀者盡可能快地學(xué)習(xí)算法世界中的數(shù)學(xué)知識(shí),以便在后面可以快速進(jìn)入算法工程的實(shí)戰(zhàn)中。關(guān)鍵詞回顧標(biāo)量向量行向量列向量矩陣單位矩陣對(duì)角矩陣對(duì)稱(chēng)矩陣排列組合導(dǎo)數(shù)梯度隨機(jī)事件隨機(jī)變量離散型隨機(jī)變量連續(xù)型隨機(jī)變量隨機(jī)過(guò)程數(shù)學(xué)期望方差標(biāo)準(zhǔn)差協(xié)方差概率密度條件概率概率分布伯努利分布均勻分布二項(xiàng)分布幾何分布泊松分布指數(shù)分布高斯分布凸優(yōu)化第3章
算法之招式在《倚天屠龍記》中,九陽(yáng)神功是上乘的內(nèi)功心法。但如果張無(wú)忌只學(xué)會(huì)九陽(yáng)神功,不會(huì)后面的乾坤大挪移等武功,充其量只能做到神功護(hù)體,而不能與人爭(zhēng)鋒。算法世界同樣如此,即使數(shù)學(xué)學(xué)得再好,在算法世界中沒(méi)有合適的運(yùn)用場(chǎng)景,亦是徒勞。本章要講解的就是算法世界中以數(shù)學(xué)為內(nèi)力驅(qū)動(dòng)的招式。反之,如果AI相關(guān)從業(yè)者的數(shù)學(xué)基礎(chǔ)較差,就很難將這些招式運(yùn)用自如,在學(xué)習(xí)后續(xù)算法的武功秘籍時(shí)也會(huì)比較吃力。在解決實(shí)際問(wèn)題的過(guò)程中,我們往往會(huì)遇到這樣的問(wèn)題:算法過(guò)程中的數(shù)據(jù)如何存儲(chǔ)?用什么結(jié)構(gòu)存儲(chǔ)效率更高?數(shù)據(jù)有什么高效的查詢(xún)和排序方法?某些特定問(wèn)題是否有相應(yīng)的算法可以將其巧妙地解決?如何衡量算法運(yùn)行需要耗費(fèi)的運(yùn)算時(shí)間和存儲(chǔ)空間?相信讀者在學(xué)完本章的算法招式后,可以找到這些問(wèn)題的答案。所謂算法招式,其實(shí)就是數(shù)據(jù)結(jié)構(gòu)和基礎(chǔ)算法(為了和機(jī)器學(xué)習(xí)算法區(qū)分開(kāi),本章講解的算法統(tǒng)稱(chēng)為基礎(chǔ)算法)。本章根據(jù)數(shù)據(jù)結(jié)構(gòu)和基礎(chǔ)算法之間相輔相成的關(guān)系,先講解數(shù)據(jù)結(jié)構(gòu)的相關(guān)知識(shí),再講解常用的基礎(chǔ)算法。按照從易到難的順序,盡量采用通俗易懂的語(yǔ)言,幫助讀者修煉好算法世界的招式。3.1數(shù)據(jù)結(jié)構(gòu)如果數(shù)據(jù)結(jié)構(gòu)是土壤,基礎(chǔ)算法就是從這片土壤中生長(zhǎng)出來(lái)的一株株植物。3.1.1數(shù)組與鏈表數(shù)組與鏈表是最簡(jiǎn)單的兩種數(shù)據(jù)結(jié)構(gòu)。在不同的場(chǎng)景應(yīng)用中,二者各有所長(zhǎng),在性能表現(xiàn)方面各有優(yōu)缺點(diǎn)。1.數(shù)組數(shù)組(Array)是一種順序存儲(chǔ)結(jié)構(gòu),其中的數(shù)據(jù)元素是采用相鄰連續(xù)分配的方式存儲(chǔ)的。由于是連續(xù)存儲(chǔ),因此只要知道某個(gè)元素在數(shù)組中的編號(hào)(下標(biāo))及數(shù)組的起始位置,相加計(jì)算偏移就能訪問(wèn)這個(gè)元素的值。數(shù)組按空間維度劃分,可以分為一維數(shù)組、二維數(shù)組、多維數(shù)組,一維數(shù)組的存儲(chǔ)圖例如圖3-1所示。圖3-1一維數(shù)組的存儲(chǔ)圖例上述描述或許比較抽象,下面我們以電影院選座位為例進(jìn)行說(shuō)明。小王、小李和小張一起去電影院看電影,在買(mǎi)票選座位時(shí)希望選擇同一排的連號(hào)座位,這種座位分配方式就是一維數(shù)組的存儲(chǔ)方式。假設(shè)小王、小李、小張按從左至右的順序依次入座,編號(hào)分別為0、1、2。由于3個(gè)人挨著坐,因此只需知道最左邊小王的座位號(hào),通過(guò)對(duì)編號(hào)進(jìn)行相加,就能知道另外兩個(gè)人的座位號(hào)了。其實(shí),一個(gè)影廳的座位可以理解成由一維數(shù)組(每一排)組成的二維數(shù)組,所謂的“幾排幾號(hào)”其實(shí)就是二維數(shù)組的索引方式。如果影廳有多層,就可以理解為三維數(shù)組,座位索引就是“幾層幾排幾號(hào)”。數(shù)組的這種分配方式存在一個(gè)很明顯的問(wèn)題,就是在插入新元素時(shí),即使相鄰存儲(chǔ)空間足夠,也需要從插入位置整體向后移動(dòng)各元素;而在相鄰存儲(chǔ)空間不夠時(shí),需要在其他空余位置申請(qǐng)存儲(chǔ)空間,由于不在同一個(gè)連續(xù)的存儲(chǔ)區(qū)域,因此新元素的添加和查詢(xún)會(huì)比較慢。對(duì)于這個(gè)問(wèn)題,一種最直觀的解決方法是從一開(kāi)始就分配足夠的數(shù)組空間。這種方法存在如下兩個(gè)缺點(diǎn):?額外申請(qǐng)的存儲(chǔ)空間可能永遠(yuǎn)用不上,在申請(qǐng)占用后無(wú)法給別的程序使用。?無(wú)法保證分配足夠的數(shù)組空間,因?yàn)榭倳?huì)有不夠用的時(shí)候。針對(duì)這兩個(gè)缺點(diǎn),另一種數(shù)據(jù)結(jié)構(gòu)形式——鏈表便出現(xiàn)了。2.鏈表還是以電影院選座位為例。小王、小李和小張一起去看電影,小王是小李的朋友,有小李的聯(lián)系方式,小李是小張的朋友,有小張的聯(lián)系方式。到了電影院發(fā)現(xiàn)最近一場(chǎng)電影的放映時(shí)間已經(jīng)沒(méi)有連號(hào)的三個(gè)座位了,于是三人買(mǎi)了分開(kāi)的座位。這種入座方式就是鏈表(List)的存儲(chǔ)方式,不要求數(shù)據(jù)存儲(chǔ)的連續(xù)性,有位置即可。在電影放映過(guò)程中,小王接到老板發(fā)來(lái)的緊急消息,需要他立刻返回公司。于是,小王將先行離開(kāi)的消息通知了小李,小李又將該消息通知了小張,這種消息傳遞的方式就是鏈表的數(shù)據(jù)訪問(wèn)方式,即鏈?zhǔn)皆L問(wèn),小王只能聯(lián)系小李,不能聯(lián)系小張,只能由小李聯(lián)系小張。根據(jù)上述例子我們了解到,鏈表是一種鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu),其中的數(shù)據(jù)元素在存儲(chǔ)時(shí)不要求相鄰、連續(xù),當(dāng)添加新的數(shù)據(jù)元素時(shí),只需開(kāi)辟任意一個(gè)新的存儲(chǔ)空間,然后將鏈表末尾元素的指針指向這個(gè)新元素的位置。這樣既可以避免出現(xiàn)元素頻繁移動(dòng)的問(wèn)題,又可以非常快速地查詢(xún)。鏈表和數(shù)組一樣,支持多維結(jié)構(gòu)(多維鏈表)。不僅如此,鏈表還支持雙向查詢(xún)(雙向鏈表)。單鏈表的存儲(chǔ)結(jié)構(gòu)圖例如圖3-2所示。圖3-2單鏈表的存儲(chǔ)結(jié)構(gòu)圖例任何事情都有得有失。鏈表雖然在元素插入方面占據(jù)優(yōu)勢(shì),但不能隨意讀取任意位置的元素值。由于鏈表的前后節(jié)點(diǎn)相連,因此當(dāng)需要讀取某個(gè)編號(hào)的元素值時(shí),必須從第一個(gè)元素開(kāi)始訪問(wèn),向后依次查詢(xún),直到找到該編號(hào)的元素值為止。而數(shù)組由于是連續(xù)的存儲(chǔ)空間,通過(guò)下標(biāo)即可快速獲取當(dāng)前編號(hào)的元素值。例如,進(jìn)行隨機(jī)取數(shù),數(shù)組的效率比鏈表的效率要高很多。概括數(shù)組和鏈表的優(yōu)缺點(diǎn):數(shù)組的查詢(xún)效率高、擴(kuò)展效率低,鏈表的查詢(xún)效率低、擴(kuò)展效率高。3.1.2隊(duì)列和棧隊(duì)列和棧,與數(shù)組、鏈表一樣都是順序存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)。除數(shù)據(jù)存儲(chǔ)的功能外,隊(duì)列和棧分別提供了不同的數(shù)據(jù)檢索能力,用于滿足不同場(chǎng)景的需求。1.隊(duì)列隊(duì)列(Queue)的數(shù)據(jù)插入特點(diǎn)是先進(jìn)先出(FirstInFirstOut,F(xiàn)IFO)。FIFO在計(jì)算機(jī)的很多方面都有應(yīng)用,如計(jì)算機(jī)內(nèi)存頁(yè)的替換策略、網(wǎng)絡(luò)路由器的流量分配策略等。直觀地理解,隊(duì)列的例子就是生活中的各種排隊(duì)。例如,在火車(chē)站出站后打出租車(chē)需要排隊(duì),按先來(lái)后到的順序依次上車(chē);在食堂窗口前排隊(duì),講究的也是先來(lái)后到。因此,我們可以將隊(duì)列理解為提供FIFO功能的一維數(shù)據(jù)存儲(chǔ)結(jié)構(gòu),既支持向尾部(隊(duì)尾)加入數(shù)據(jù)元素,又支持移出頭部(隊(duì)首)的數(shù)據(jù)元素。2.棧理解了隊(duì)列,棧(Stack)就比較好理解了。棧的數(shù)據(jù)插入特點(diǎn)是后進(jìn)先出(LastInFirstOut,LIFO)。棧的特性在計(jì)算機(jī)中有著廣泛的應(yīng)用,可以說(shuō)程序員無(wú)時(shí)無(wú)刻不在和LIFO打交道。一個(gè)最典型的例子就是程序中的函數(shù)調(diào)用。除此之外,在滿足遞歸定義的問(wèn)題中,棧的運(yùn)用也比較多。因此,我們可以理解棧為提供LIFO功能的一維數(shù)據(jù)存儲(chǔ)結(jié)構(gòu),既支持向頭部(棧頂)加入數(shù)據(jù)元素,又支持移出頭部(棧頂)的數(shù)據(jù)元素。3.1.3樹(shù)掌握了鏈表,樹(shù)(Tree)這種結(jié)構(gòu)就很好理解了。在討論數(shù)據(jù)結(jié)構(gòu)與算法時(shí),經(jīng)常可以聽(tīng)到二叉樹(shù)、三叉樹(shù)、多叉樹(shù),下面我們通過(guò)一個(gè)例子直觀地了解一下,數(shù)據(jù)結(jié)構(gòu)中的樹(shù)是什么樣子的。一個(gè)深入敵后潛伏的情報(bào)組織,每級(jí)情報(bào)員都分配了若干名下級(jí)情報(bào)員,相鄰兩級(jí)情報(bào)員分別叫作彼此的上線和下線。為了防止下線在暴露之后對(duì)整個(gè)組織造成威脅,上線和下線之間是單向通信的,上線能聯(lián)系下線,下線無(wú)法聯(lián)系上線,并且信息通路不形成環(huán)路(如我下線的下線不會(huì)是我的上線)。如果每級(jí)情報(bào)員的下線固定最多有2名情報(bào)員,那么這種情報(bào)結(jié)構(gòu)就是二叉樹(shù)結(jié)構(gòu);如果固定最多有3名情報(bào)員,那么這種情報(bào)結(jié)構(gòu)就是三叉樹(shù)結(jié)構(gòu);以此類(lèi)推。不僅結(jié)構(gòu)相似,情報(bào)組織的信息傳遞方式也和樹(shù)的數(shù)據(jù)訪問(wèn)順序類(lèi)似,只能從頂部(根部)往底部傳遞。不管幾叉樹(shù),每個(gè)節(jié)點(diǎn)都以鏈表的形式指向若干個(gè)新節(jié)點(diǎn),并且樹(shù)中的節(jié)點(diǎn)不會(huì)形成環(huán)狀連接。以最常見(jiàn)的二叉樹(shù)為例,從根節(jié)點(diǎn)開(kāi)始,每個(gè)節(jié)點(diǎn)都可以指向另外兩個(gè)新節(jié)點(diǎn),為了方便理解,這個(gè)節(jié)點(diǎn)稱(chēng)為父節(jié)點(diǎn),指向的兩個(gè)新節(jié)點(diǎn)稱(chēng)為左孩子節(jié)點(diǎn)和右孩子節(jié)點(diǎn)。二叉樹(shù)的存儲(chǔ)結(jié)構(gòu)圖例如圖3-3所示。圖3-3二叉樹(shù)的存儲(chǔ)結(jié)構(gòu)圖例既然是樹(shù),就會(huì)有高度。從根節(jié)點(diǎn)開(kāi)始向下累積的層數(shù)就是樹(shù)的高度,如圖3-3中的二叉樹(shù)的高度為3。二叉樹(shù)之所以被廣泛應(yīng)用,是因?yàn)樗詈?jiǎn)單,又最具有代表性。二叉樹(shù)的種類(lèi)有很多,如完全二叉樹(shù)、滿二叉樹(shù)、平衡二叉樹(shù)、霍夫曼樹(shù)、B樹(shù)等。不同種類(lèi)的二叉樹(shù)具有不同的性質(zhì)、不同的應(yīng)用場(chǎng)景,感興趣的讀者可以自行深入了解。二叉樹(shù)不像鏈表的順序遍歷那么簡(jiǎn)單,因?yàn)槊總€(gè)節(jié)點(diǎn)最多有兩個(gè)孩子節(jié)點(diǎn),所以遍歷方法有4種:前序遍歷、中序遍歷、后序遍歷和層序遍歷。前序遍歷的口訣是“中左右”,即先遍歷當(dāng)前父節(jié)點(diǎn),再遍歷左孩子節(jié)點(diǎn),最后遍歷右孩子節(jié)點(diǎn);相應(yīng)地,中序遍歷的口訣是“左中右”,后序遍歷的口訣是“左右中”,遍歷順序以此類(lèi)推。層序遍歷稍微有所區(qū)別,它會(huì)逐層按從左至右的順序遍歷所有節(jié)點(diǎn)。下面來(lái)看一個(gè)例子,分別用4種遍歷方法遍歷圖3-4所示的二叉樹(shù)。圖3-4二叉樹(shù)的遍歷前序遍歷:1→2→4→5→3→6→7。中序遍歷:4→2→5→1→6→3→7。后序遍歷:4→5→2→6→7→3→1。層序遍歷:1→2→3→4→5→6→7。這里特別提一句,多棵樹(shù)放在一起稱(chēng)為森林(Forest),森林的概念在后面的算法中也會(huì)用到。此外,前文特別提到樹(shù)這種數(shù)據(jù)結(jié)構(gòu)不能形成環(huán)狀,如果形成環(huán)狀,那么會(huì)是什么結(jié)構(gòu)?沒(méi)錯(cuò),正是下一節(jié)要講的圖。3.1.4圖圖(Graph)是一種包含節(jié)點(diǎn)和表達(dá)節(jié)點(diǎn)之間關(guān)系的邊的一種數(shù)據(jù)結(jié)構(gòu)。前面講到的鏈表和樹(shù),其實(shí)都是圖的特殊情況,鏈表只能向一個(gè)方向進(jìn)行鏈接,樹(shù)的節(jié)點(diǎn)之間不允許形成環(huán)。圖結(jié)構(gòu)沒(méi)有這些限制,圖中節(jié)點(diǎn)之間的連接稱(chēng)為邊。圖可以分為兩種,分別為有向圖和無(wú)向圖。顧名思義,有向圖就是邊帶方向的圖,如圖3-5(a)所示;無(wú)向圖就是邊不帶方向的圖,如圖3-5(b)所示??梢詫o(wú)向圖看作每條邊都有兩個(gè)方向的有向圖。圖3-5有向圖和無(wú)向圖圖的邊除了可以表示連接關(guān)系和連接方向,還可以附帶權(quán)重等信息,從而進(jìn)一步表示節(jié)點(diǎn)之間的某種關(guān)系。例如,以城市為節(jié)點(diǎn),可以將城市之間的距離作為連接這些節(jié)點(diǎn)的邊的權(quán)重。圖是一種非常實(shí)用的數(shù)據(jù)結(jié)構(gòu),在工作、生活的方方面面都能用到它。例如,如果將每個(gè)人作為節(jié)點(diǎn),將人與人之間的關(guān)系作為邊,可以構(gòu)成一個(gè)大小為70多億節(jié)點(diǎn)的社交網(wǎng)絡(luò)圖。著名的小世界現(xiàn)象,你和任何陌生人之間所間隔的人數(shù)不會(huì)超過(guò)6個(gè),就是基于社交網(wǎng)絡(luò)圖得出的猜想。在計(jì)算機(jī)世界中,圖經(jīng)常用于描述任務(wù)的狀態(tài)轉(zhuǎn)換和調(diào)度關(guān)系。例如,節(jié)點(diǎn)代表待執(zhí)行的任務(wù),邊代表任務(wù)相關(guān)性或依賴(lài)順序。圖的存儲(chǔ)方式有兩種,一種是以鏈表形式存儲(chǔ),每個(gè)節(jié)點(diǎn)及其相鄰節(jié)點(diǎn)都用一個(gè)鏈表表示,這種存儲(chǔ)方式稱(chēng)為鄰接鏈表;另一種是以數(shù)組形式存儲(chǔ),用一維數(shù)組記錄所有節(jié)點(diǎn),用一個(gè)二維數(shù)組記錄所有邊,這種存儲(chǔ)方式稱(chēng)為鄰接矩陣。鄰接鏈表和鄰接矩陣的優(yōu)劣對(duì)比與鏈表和數(shù)組之間的對(duì)比類(lèi)似,鄰接鏈表使用的是鏈表,鄰接矩陣使用的是二維數(shù)組。以圖3-5中的有向圖為例,鄰接鏈表和鄰接矩陣的具體存儲(chǔ)形式如圖3-6所示。圖3-6鄰接鏈表和鄰接矩陣的具體存儲(chǔ)形式3.1.5散列表散列表(HashTable)又稱(chēng)為哈希表。在講解散列表之前,我們先從一個(gè)實(shí)際問(wèn)題出發(fā):如何在全國(guó)范圍內(nèi)較快速地根據(jù)姓名查詢(xún)對(duì)應(yīng)的身份證號(hào)碼?如果使用數(shù)組或鏈表存儲(chǔ)身份證信息,則需要從頭到尾查詢(xún)一遍才能保證找到所查姓名的身份證號(hào)碼,時(shí)間復(fù)雜度都是O(N);如果使用二叉排序樹(shù)存儲(chǔ)身份證信息,時(shí)間復(fù)雜度也只能提高到O(log2N),通常默認(rèn)對(duì)數(shù)底為2,可簡(jiǎn)寫(xiě)為O(logN)。這里補(bǔ)充說(shuō)明一下什么是時(shí)間復(fù)雜度。O(N)和O(logN)都是描述算法復(fù)雜度的符號(hào),算法復(fù)雜度主要包含兩個(gè)方面:空間復(fù)雜度和時(shí)間復(fù)雜度。其中,空間復(fù)雜度定性地描述了一個(gè)算法運(yùn)行所需內(nèi)存空間的數(shù)量級(jí),時(shí)間復(fù)雜度定性地描述了一個(gè)算法運(yùn)行所需時(shí)間的數(shù)量級(jí)。在通常情況下,我們優(yōu)先考慮算法的時(shí)間復(fù)雜度。在時(shí)間復(fù)雜度中,O(N)表示當(dāng)數(shù)據(jù)量為N時(shí),計(jì)算機(jī)需要執(zhí)行的基本運(yùn)算次數(shù)的數(shù)量級(jí)為線性級(jí)別;O(logN)表示當(dāng)數(shù)據(jù)量為N時(shí),計(jì)算機(jī)需要執(zhí)行的基本運(yùn)算次數(shù)數(shù)量級(jí)為對(duì)數(shù)級(jí)別。除了O(N)和O(logN),還有O(NlogN)、O(N2)、O(N3)等,含義以此類(lèi)推。O(logN)的時(shí)間復(fù)雜度比O(N)的時(shí)間復(fù)雜度低,表示O(logN)的算法比O(N)的算法更合適。例如,當(dāng)N為1024時(shí),logN只有10。O(logN)的時(shí)間復(fù)雜度已經(jīng)足夠低了,但是散列表的時(shí)間復(fù)雜度能更低。散列表可以將查詢(xún)身份證號(hào)碼的時(shí)間復(fù)雜度降到O(1),即常數(shù)級(jí)別。散列表用到的關(guān)鍵技術(shù)是函數(shù)值映射,利用散列函數(shù),將key值(姓名字符串)映射到一個(gè)有限的數(shù)值空間內(nèi)。例如,一個(gè)長(zhǎng)度為10億的數(shù)組,如果使用恰當(dāng)?shù)纳⒘泻瘮?shù),那么映射后的值會(huì)均勻分布到這個(gè)數(shù)組中。在查詢(xún)時(shí),計(jì)算被查詢(xún)姓名的散列值,即可直接取出數(shù)組中對(duì)應(yīng)下標(biāo)的身份證號(hào)碼。這里你可能會(huì)問(wèn),姓名有重復(fù)怎么辦?沒(méi)關(guān)系,這個(gè)問(wèn)題在散列表中經(jīng)常出現(xiàn),這種現(xiàn)象稱(chēng)為鍵值沖突。鍵值沖突問(wèn)題的解決方法比較簡(jiǎn)單,在遇到重復(fù)key值時(shí),只需在對(duì)應(yīng)的散列值后面增加一個(gè)鏈表,用于存儲(chǔ)重復(fù)key值。散列表的沖突存儲(chǔ)方式與鄰接鏈表的存儲(chǔ)方式類(lèi)似,重復(fù)的key值會(huì)被存儲(chǔ)于同一個(gè)散列值生成的鏈表中。當(dāng)然,散列函數(shù)直接影響到了鍵值沖突問(wèn)題的大小,一個(gè)映射不均勻的散列函數(shù)有可能導(dǎo)致嚴(yán)重的鏈表傾斜,即大量數(shù)據(jù)被映射到同一個(gè)鍵值,導(dǎo)致對(duì)這些鍵值的訪問(wèn)退化成順序遍歷,降低檢索效率。針對(duì)這個(gè)問(wèn)題,一方面可以選取合適的散列函數(shù);另一方面,在發(fā)生鍵值沖突后,可以采取二次散列法和設(shè)計(jì)公共溢出區(qū)等措施。3.2基礎(chǔ)算法算法是針對(duì)一類(lèi)數(shù)學(xué)問(wèn)題制訂的完整而準(zhǔn)確的解決方案,代表用系統(tǒng)的方法描述解決問(wèn)題的策略機(jī)制。也就是說(shuō),對(duì)于符合一定要求的輸入,算法必須在有限時(shí)間內(nèi)獲得相應(yīng)的輸出。不同的算法能用不同的時(shí)間效率、空間效率來(lái)完成相同的任務(wù),它們的性能可以用時(shí)間復(fù)雜度與空間復(fù)雜度衡量。算法作為數(shù)據(jù)結(jié)構(gòu)的產(chǎn)物,它的實(shí)現(xiàn)離不開(kāi)數(shù)據(jù)結(jié)構(gòu)的支持。基于數(shù)組、鏈表、樹(shù)和圖的算法有很多,下面介紹幾種常用且有趣的算法,幫助大家開(kāi)啟AI算法的思維之門(mén)。3.2.1排序基礎(chǔ)算法中最常用的算法,非排序莫屬?,F(xiàn)實(shí)生活中存在不少排序的例子。例如,人群按照身高站隊(duì)需要排序,考試分?jǐn)?shù)需要排序,整理卷子編號(hào)需要排序,等等。那么常用的排序算法有哪些,它們分別如何實(shí)現(xiàn)?排序算法的種類(lèi)很多,按照時(shí)間復(fù)雜度劃分,從慢到快主要有以下9種排序算法。O(N2):選擇排序、插入排序、冒泡排序。O(NlogN):快速排序、堆排序、歸并排序。O(N):計(jì)數(shù)排序、桶排序、基數(shù)排序。1.選擇排序選擇排序(SelectionSort)的基本思路是每次選出剩余序列中的最值按先后順序排列。如果要求按從小到大的順序排序(升序排序),則每次選擇最小值來(lái)組成新的序列;如果要求按從大到小的順序排序(降序排序),則每次選擇最大值來(lái)組成新的序列。對(duì)于一個(gè)長(zhǎng)度為N的待排序列,算法在執(zhí)行第1輪排序時(shí),會(huì)從N個(gè)元素中選出最值,需要執(zhí)行N-1次比較運(yùn)算;算法在執(zhí)行第2輪排序時(shí),會(huì)從剩下的N-1個(gè)元素中選出最值,需要執(zhí)行N-2次比較運(yùn)算;以此類(lèi)推,序列剩下的最后兩個(gè)元素需要執(zhí)行1次比較運(yùn)算。這樣總的比較次數(shù)是算法復(fù)雜度的衡量是看最高數(shù)量級(jí),此處為二次方項(xiàng),在不影響當(dāng)前數(shù)量級(jí)的情況下,將常數(shù)項(xiàng)系數(shù)省略,所以選擇排序的時(shí)間復(fù)雜度是O(N2)。以升序排序?yàn)槔?,選擇排序的執(zhí)行過(guò)程如圖3-7所示。圖3-7選擇排序的執(zhí)行過(guò)程2.插入排序插入排序(InsertionSort)的基本思路是依次取出序列中的每個(gè)元素并將其插入一個(gè)有序序列。對(duì)于一個(gè)長(zhǎng)度為N的待排序列,初始有序序列為空,算法在執(zhí)行第1輪排序時(shí),會(huì)取一個(gè)元素插入空的有序序列,需要執(zhí)行0次比較運(yùn)算;算法在執(zhí)行第2輪排序時(shí),會(huì)取一個(gè)元素插入長(zhǎng)度為1的有序序列,需要執(zhí)行1次比較運(yùn)算;以此類(lèi)推,算法在執(zhí)行第N輪排序時(shí),會(huì)取一個(gè)元素插入長(zhǎng)度為N-1的有序序列,需要執(zhí)行N-1次比較運(yùn)算。這樣總的比較次數(shù)是因此插入排序的時(shí)間復(fù)雜度和選擇排序的時(shí)間復(fù)雜度相同,也是O(N2)。以升序排序?yàn)槔?,插入排序的?zhí)行過(guò)程如圖3-8所示。圖3-8插入排序的執(zhí)行過(guò)程3.冒泡排序顧名思義,冒泡排序(BubbleSort)的基本思路是循環(huán)比較相鄰的元素值,將最值像水里的氣泡冒上水面一樣選出來(lái)。與選擇排序和插入排序相比,冒泡排序不需要額外的序列存儲(chǔ)空間,在算法執(zhí)行完成后,原序列即可變成有序序列。對(duì)于一個(gè)長(zhǎng)度為N的待排序列,以升序排序?yàn)槔恳惠喤判蚨紩?huì)從原序列的最后一個(gè)元素開(kāi)始。算法在執(zhí)行第1輪排序時(shí),會(huì)從后向前依次比較相鄰兩個(gè)元素值,如果前面的元素值大于后面的元素值,就交換兩個(gè)元素的位置,直到第一個(gè)元素,需要執(zhí)行N-1次比較運(yùn)算;算法在執(zhí)行第2輪排序時(shí),會(huì)從后向前依次比較相鄰兩個(gè)元素值,直到第二個(gè)元素,需要執(zhí)行N-2次比較運(yùn)算;以此類(lèi)推,最后一輪比較為首的兩個(gè)元素值,需要執(zhí)行1次比較運(yùn)算。這樣,總的比較次數(shù)也是因此冒泡排序的時(shí)間復(fù)雜度也是O(N2)。以升序排序?yàn)槔?,冒泡排序的?zhí)行過(guò)程如圖3-9所示。圖3-9冒泡排序的執(zhí)行過(guò)程4.快速排序快速排序(QuickSort)簡(jiǎn)稱(chēng)快排,是程序員面試時(shí)考官最??疾榈呐判蛩惴ㄖ?,它的基本思路是每次確定待排序列中一個(gè)元素的最終排序位置。對(duì)于一個(gè)長(zhǎng)度為N的待排序列,以升序排序?yàn)槔?,算法在?zhí)行第1輪排序時(shí),當(dāng)前序列為原序列,從原序列中選出第一個(gè)元素,兩個(gè)指針?lè)謩e從序列兩端向中間遍歷,比較所選元素與指針遍歷元素的大小,通過(guò)交換位置,確保所選元素的最終位置,并且將當(dāng)前序列一分為二,分為左序列和右序列(左序列中的元素值都不大于所選元素值,右序列中的元素值都不小于所選元素值);算法在執(zhí)行第2輪排序時(shí),當(dāng)前序列為原序列的左序列,具體操作同前一步;算法在執(zhí)行第3輪排序時(shí),當(dāng)前序列為原序列的右序列,具體操作同前一步;以此遞推,直到找到所有元素的最終位置,快速排序結(jié)束。快速排序由于采用折半操作,因此時(shí)間復(fù)雜度為O(NlogN)。以升序排序?yàn)槔焖倥判虻?輪排序的執(zhí)行過(guò)程如圖3-10所示。圖3-10快速排序第1輪排序的執(zhí)行過(guò)程需要特別注意的是,如果原序列本身就是有序序列,那么折半操作會(huì)退化成線性操作,時(shí)間復(fù)雜度也會(huì)變?yōu)镺(N2)??焖倥判蛑钥欤且?yàn)樗屆枯喫x元素的最終位置盡量靠近序列中央,這樣就起到了折半的作用。所以,快速排序的關(guān)鍵在于如何隨機(jī)選擇元素,讓所選元素在數(shù)學(xué)期望下靠近中間位置。因此,在每一輪排序開(kāi)始時(shí),只需加上一個(gè)隨機(jī)函數(shù),隨機(jī)從當(dāng)前序列中選擇一個(gè)元素與待排元素事先交換,這樣的快速排序又稱(chēng)為隨機(jī)快速排序。5.堆排序堆排序(HeapSort)的基本思路是先將序列構(gòu)建成一個(gè)最大二叉堆或最小二叉堆。二叉堆是二叉樹(shù)的一種。最大二叉堆是指每個(gè)節(jié)點(diǎn)的元素值都比其左、右孩子節(jié)點(diǎn)的元素值要大的二叉堆,最小二叉堆是指每個(gè)節(jié)點(diǎn)的元素值都比其左、右孩子節(jié)點(diǎn)的元素值要小的二叉堆。算法在執(zhí)行時(shí),每次從二叉堆中移出堆頂元素,并且將末尾元素移至堆頂,然后調(diào)整二叉堆結(jié)構(gòu),維持最大二叉堆或最小二叉堆的結(jié)構(gòu)特點(diǎn)。如果構(gòu)建的是最大二叉堆,那么得到的是降序序列;如果構(gòu)建的是最小二叉堆,那么得到的是升序序列。由于二叉堆是二叉樹(shù)的一種,維持最大二叉堆或最小二叉堆的結(jié)構(gòu)特點(diǎn)是一個(gè)二分查找的過(guò)程,因此堆排序的時(shí)間復(fù)雜度和快速排序的時(shí)間復(fù)雜度一樣,也是O(NlogN)。以升序排序?yàn)槔?,堆排序?輪排序的執(zhí)行過(guò)程如圖3-11所示。二叉堆各節(jié)點(diǎn)的元素值可以使用數(shù)組存儲(chǔ),數(shù)組下標(biāo)從1開(kāi)始,假設(shè)父節(jié)點(diǎn)的下標(biāo)為i,那么左、右孩子節(jié)點(diǎn)的下標(biāo)分別為2i、2i+1。圖3-11堆排序第1輪排序的執(zhí)行過(guò)程6.歸并排序歸并排序(MergeSort)采用遞歸與分治的思想(在3.2.2節(jié)會(huì)詳細(xì)詳解),先保證局部有序,再保證整體有序,從局部到整體可以看作一個(gè)歸納合并的過(guò)程,這也是該排序算法名字的由來(lái)。對(duì)于一個(gè)長(zhǎng)度為N的待排序列,以升序排序?yàn)槔?,算法在?zhí)行第1輪排序時(shí),原序列中的每個(gè)元素都可以看作一個(gè)局部有序序列,將相鄰的兩個(gè)局部有序序列合并成一個(gè)長(zhǎng)度為2的局部有序序列,局部最大比較次數(shù)為1;算法在執(zhí)行第2輪排序時(shí),合并相鄰的兩個(gè)長(zhǎng)度為2的局部有序序列,得到長(zhǎng)度為4的局部有序序列,局部最大比較次數(shù)為3;以此類(lèi)推,直到原序列有序。由此可見(jiàn),歸并排序總的執(zhí)行輪次是logN,因此其時(shí)間復(fù)雜度為O(NlogN)。以升序排序?yàn)槔?,歸并排序的執(zhí)行過(guò)程如圖3-12所示。圖3-12歸并排序的執(zhí)行過(guò)程7.計(jì)數(shù)排序計(jì)數(shù)排序(CountSort)是一種用更多存儲(chǔ)空間交換更高時(shí)間效率的排序算法,這種排序算法無(wú)須做任何比較操作,只需創(chuàng)建一個(gè)count數(shù)組,這個(gè)數(shù)組的長(zhǎng)度大于待排序列中元素值的極差(最大元素值與最小元素值的差)。對(duì)于一個(gè)長(zhǎng)度為N的待排序列,值域?yàn)閇0,K-1],初始化一個(gè)長(zhǎng)度為K、各個(gè)位置上元素值均為0的數(shù)組,依次遍歷待排序列,將count數(shù)組中以當(dāng)前元素值為下標(biāo)的位置加1,排序完成。如果要進(jìn)行升序排序,那么按照下標(biāo)從小到大的順序遍歷數(shù)組,遇到幾就輸出幾個(gè)當(dāng)前位置的下標(biāo)值,直到遍歷結(jié)束;如果要進(jìn)行降序序列,那么按照下標(biāo)從大到小的順序遍歷數(shù)組,遇到幾就輸出幾個(gè)當(dāng)前位置的下標(biāo)值,直到遍歷結(jié)束。計(jì)數(shù)排序只涉及線性操作,時(shí)間復(fù)雜度為O(N+K)。很明顯,在存儲(chǔ)空間有限的情況下,計(jì)數(shù)排序?qū)θ≈捣秶^小的待排序列有比較明顯的速度優(yōu)勢(shì)。以升序排序?yàn)槔?jì)數(shù)排序的執(zhí)行過(guò)程如圖3-13所示。圖3-13計(jì)數(shù)排序的執(zhí)行過(guò)程8.桶排序計(jì)數(shù)排序的最大問(wèn)題是隨著待排序列值域的擴(kuò)大,空間復(fù)雜度也隨之增加。桶排序(BucketSort)是計(jì)數(shù)排序的進(jìn)化版本,它不是一對(duì)一的下標(biāo)映射,而是通過(guò)一個(gè)映射函數(shù),一對(duì)多地將大小接近的數(shù)存儲(chǔ)于一個(gè)桶中,然后對(duì)每個(gè)桶中的序列進(jìn)行排序。如果每個(gè)桶中排序的時(shí)間復(fù)雜度為O(NlogN),那么桶排序的時(shí)間復(fù)雜度為∑O(NilogNi)。9.基數(shù)排序計(jì)數(shù)排序和桶排序都較難解決混合數(shù)據(jù)的排序問(wèn)題,如字符串之間的排序?;鶖?shù)排序(RadixSort)是桶排序的升級(jí)版,其基本思路是從待排元素的低位到高位每輪都按位分桶,按位比較元素值的大小,擺脫了數(shù)據(jù)類(lèi)型的限定?;鶖?shù)排序的時(shí)間復(fù)雜度為O(dN),其中d是最大位數(shù)。在實(shí)際使用過(guò)程中,除了時(shí)間復(fù)雜度,有時(shí)還需要考慮排序算法的穩(wěn)定性。排序算法的穩(wěn)定性是指在排序過(guò)程中是否會(huì)改變?nèi)我鈨蓚€(gè)相等元素的前后順序。一個(gè)排序算法如果不改變?nèi)我鈨蓚€(gè)相等元素的前后順序,則是穩(wěn)定的排序,否則是不穩(wěn)定的排序。為了方便讀者理解和記憶,下面對(duì)以上9種排序算法在時(shí)間復(fù)雜度和穩(wěn)定性上進(jìn)行優(yōu)劣對(duì)比,如表3-1所示。表3-19種排序算法對(duì)比3.2.2遞歸與分治1.遞歸簡(jiǎn)單地說(shuō),程序調(diào)用自身的編程技巧稱(chēng)為遞歸。遞歸(Recursion)的學(xué)術(shù)定義如下:一個(gè)函數(shù)、過(guò)程、概念或數(shù)學(xué)結(jié)構(gòu),如果在其定義或說(shuō)明內(nèi)部直接或間接地出現(xiàn)其本身的引用,則它們是遞歸的或遞歸定義的。具體而言,遞歸可以分為遞推和回歸兩個(gè)階段。問(wèn)題逐層往前遞進(jìn)推動(dòng),這個(gè)過(guò)程叫作遞推;逐一解決子問(wèn)題,最后匯總為原問(wèn)題,這個(gè)過(guò)程叫作回歸。二者交替配合,就形成了遞歸。我們通過(guò)一個(gè)直觀的例子感受遞歸的整體流程。某所中學(xué)的校團(tuán)委為了籌集團(tuán)員活動(dòng)經(jīng)費(fèi),計(jì)劃向本校的每一位團(tuán)員收取團(tuán)費(fèi)。該通知采取逐級(jí)傳達(dá)的方式,校團(tuán)委通知年級(jí)團(tuán)委,然后年級(jí)團(tuán)委通知班團(tuán)委,最后班團(tuán)委通知到班里的每一位團(tuán)員。這種逐層遞進(jìn)傳遞任務(wù)的過(guò)程,就是遞推過(guò)程。在任務(wù)發(fā)布后,只有在每一級(jí)的團(tuán)費(fèi)收集任務(wù)全部完成后,才能向上一級(jí)匯報(bào)。例如,在班里每一位團(tuán)員的團(tuán)費(fèi)都收齊之后,班團(tuán)委才能向年級(jí)團(tuán)委匯報(bào);在每個(gè)班的團(tuán)費(fèi)都收齊之后,年級(jí)團(tuán)委才能向校團(tuán)委匯報(bào)。這種在子任務(wù)全部完成之后,自下向上匯報(bào)的過(guò)程,就是回歸過(guò)程。整個(gè)團(tuán)費(fèi)收集的過(guò)程,就是一個(gè)完整的遞歸過(guò)程。當(dāng)然,有遞歸就有非遞歸。所謂非遞歸,就是不用層級(jí)關(guān)系來(lái)表達(dá)任務(wù),而是將任務(wù)拉平成線性關(guān)系表達(dá)任務(wù)。因此,支持遞歸實(shí)現(xiàn)的基礎(chǔ)算法會(huì)比非遞歸實(shí)現(xiàn)理解起來(lái)較為簡(jiǎn)單直觀。舉個(gè)例子,求長(zhǎng)度為n的斐波那契數(shù)列各項(xiàng)之和。遞歸寫(xiě)法和非遞歸寫(xiě)法的代碼實(shí)現(xiàn)分別如下。對(duì)比發(fā)現(xiàn),遞歸寫(xiě)法的程序具備結(jié)構(gòu)清晰、可讀性強(qiáng)等優(yōu)點(diǎn),并且遞歸寫(xiě)法比非遞歸寫(xiě)法的代碼更容易實(shí)現(xiàn)。當(dāng)然,一些問(wèn)題如果使用遞歸算法求解,會(huì)因?yàn)橹貜?fù)計(jì)算的問(wèn)題讓算法變得低效,遞歸的代碼抽象,容易出錯(cuò)且很難調(diào)試。例如,斐波那契數(shù)列求和就不適合使用遞歸算法求解。所以,只有當(dāng)問(wèn)題本身是遞歸定義的,或者問(wèn)題涉及的數(shù)據(jù)結(jié)構(gòu)是遞歸定義的時(shí),遞歸算法才是最佳選擇。經(jīng)典的遞歸問(wèn)題有八皇后問(wèn)題、漢諾塔問(wèn)題和全排列問(wèn)題。2.分治分治(DivideConquerAlgorithm)就是“分而治
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年國(guó)家電投廣西核電社會(huì)招聘筆試參考題庫(kù)含答案解析
- 2025年江西鷹潭市文旅投集團(tuán)招聘筆試參考題庫(kù)含答案解析
- 2025年湘潭城鄉(xiāng)建設(shè)發(fā)展集團(tuán)招聘筆試參考題庫(kù)含答案解析
- 2025年湖北新華書(shū)店有限公司招聘筆試參考題庫(kù)含答案解析
- 2025年福建寧德市福鼎市融媒文化投資發(fā)展有限公司招聘筆試參考題庫(kù)附帶答案詳解
- 2025年浙江寧波市奉化區(qū)城市投資發(fā)展集團(tuán)有限公司招聘筆試參考題庫(kù)附帶答案詳解
- 停車(chē)場(chǎng)收費(fèi)委托管理協(xié)議
- 政府與展覽公司合作協(xié)議
- 二零二五年度大數(shù)據(jù)分析與咨詢(xún)服務(wù)合同(GF-2025)2篇
- 二零二五年度氣象能源開(kāi)發(fā)利用合作協(xié)議2篇
- 領(lǐng)導(dǎo)學(xué) 課件全套 孫健 第1-9章 領(lǐng)導(dǎo)要素- 領(lǐng)導(dǎo)力開(kāi)發(fā)
- 2024-2025學(xué)年七年級(jí)上學(xué)期語(yǔ)文期末考前押題卷(統(tǒng)編版2024+含答案)
- 土建定額培訓(xùn)課件
- ISO 56001-2024《創(chuàng)新管理體系-要求》專(zhuān)業(yè)解讀與應(yīng)用實(shí)踐指導(dǎo)材料之13:“6策劃-6.2創(chuàng)新目標(biāo)及其實(shí)現(xiàn)的策劃”(雷澤佳編制-2025B0)
- 2024年保護(hù)環(huán)境的建議書(shū)范文(33篇)
- 退休人員公益活動(dòng)合作合同
- 四年級(jí)數(shù)學(xué)(四則混合運(yùn)算帶括號(hào))計(jì)算題專(zhuān)項(xiàng)練習(xí)與答案
- 急診創(chuàng)傷疼痛護(hù)理
- 2022年期貨從業(yè)資格《期貨基礎(chǔ)知識(shí)》考試題庫(kù)(含典型題)
- 浙江省湖州市2023-2024學(xué)年高二上學(xué)期期末調(diào)研測(cè)試數(shù)學(xué)試題 含解析
- 浙江省杭州市蕭山區(qū)2023-2024學(xué)年高二上學(xué)期1月期末考試物理試題(含答案)
評(píng)論
0/150
提交評(píng)論