色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁(yè) > 智能計(jì)算 > 業(yè)界動(dòng)態(tài) > 如何入門Python與機(jī)器學(xué)習(xí)

          如何入門Python與機(jī)器學(xué)習(xí)

          作者: 時(shí)間:2017-10-10 來(lái)源:網(wǎng)絡(luò) 收藏

            編者按:本書節(jié)選自圖書《實(shí)戰(zhàn)》,本身帶有許多的第三方庫(kù),但本書在絕大多數(shù)情況下只會(huì)用到Numpy這個(gè)基礎(chǔ)的科學(xué)計(jì)算庫(kù)來(lái)進(jìn)行算法代碼的實(shí)現(xiàn)。這樣做的目的是希望讀者能夠從實(shí)現(xiàn)的過(guò)程中更好地理解算法的細(xì)節(jié),以及了解Numpy的各種應(yīng)用。不過(guò)作為補(bǔ)充,本書會(huì)在適當(dāng)?shù)臅r(shí)候應(yīng)用scikit-learn這個(gè)成熟的第三方庫(kù)中的模型。

          本文引用地址:http://cafeforensic.com/article/201710/365207.htm

            “機(jī)器學(xué)習(xí)”在最近雖可能不至于到人盡皆知的程度,卻也是非?;馃岬脑~匯。機(jī)器學(xué)習(xí)是英文單詞“Machine Learning”(簡(jiǎn)稱ML)的直譯,從字面上便說(shuō)明了這門技術(shù)是讓機(jī)器進(jìn)行“學(xué)習(xí)”的技術(shù)。然而我們知道機(jī)器終究是死的,所謂的“學(xué)習(xí)”歸根結(jié)底亦只是人類“賦予”機(jī)器的一系列運(yùn)算。這個(gè)“賦予”的過(guò)程可以有很多種實(shí)現(xiàn),而正是其中相對(duì)容易上手、同時(shí)性能又相當(dāng)不錯(cuò)的一門語(yǔ)言。本文打算先談?wù)剻C(jī)器學(xué)習(xí)相關(guān)的一些比較寬泛的知識(shí),再介紹并說(shuō)明為何要使用Python來(lái)作為機(jī)器學(xué)習(xí)的工具。最后,我們會(huì)提供一個(gè)簡(jiǎn)短易懂的、具有實(shí)際意義的例子來(lái)給大家提供一個(gè)直觀的感受。

            具體而言,本章主要涉及的知識(shí)點(diǎn)有:

            機(jī)器學(xué)習(xí)的定義及重要性;

            Python在機(jī)器學(xué)習(xí)領(lǐng)域的優(yōu)異性;

            如何在電腦上配置Python機(jī)器學(xué)習(xí)的環(huán)境;

            機(jī)器學(xué)習(xí)一般性的步驟。

            機(jī)器學(xué)習(xí)緒論

            正如前言所說(shuō),由于近期的各種最新成果,使得“機(jī)器學(xué)習(xí)”成為了非常熱門的詞匯。機(jī)器學(xué)習(xí)在各種領(lǐng)域的優(yōu)異表現(xiàn)(圍棋界的Master是其中最具代表性的存在),使得各行各業(yè)的人們都或多或少地對(duì)機(jī)器學(xué)習(xí)產(chǎn)生了興趣與敬畏。然而與此同時(shí),對(duì)機(jī)器學(xué)習(xí)有所誤解的群體也日益壯大;他們或?qū)C(jī)器學(xué)習(xí)想得過(guò)于神秘,或?qū)⑺氲眠^(guò)于萬(wàn)能。本節(jié)擬對(duì)機(jī)器學(xué)習(xí)進(jìn)行一般性的介紹,同時(shí)會(huì)說(shuō)明機(jī)器學(xué)習(xí)中一些常見(jiàn)的術(shù)語(yǔ)以方便之后章節(jié)的敘述。

            什么是機(jī)器學(xué)習(xí)

            清晨的一句“今天天氣真好”、朋友之間的寒暄“你剛剛是去吃飯了吧”、考試過(guò)后的感嘆“復(fù)習(xí)了那么久終有收獲”……這些日常生活中隨處可見(jiàn)的話語(yǔ),其背后卻已蘊(yùn)含了“學(xué)習(xí)”的思想—它們都是利用以往的經(jīng)驗(yàn)、對(duì)未知的新情況作出的有效的決策。而把這個(gè)決策的過(guò)程交給計(jì)算機(jī)來(lái)做,可以說(shuō)就是“機(jī)器學(xué)習(xí)”的一個(gè)最淺白的定義。

            我們或許可以先說(shuō)說(shuō)機(jī)器學(xué)習(xí)與以往的計(jì)算機(jī)工作樣式有什么不同。傳統(tǒng)的計(jì)算機(jī)如果想要得到某個(gè)結(jié)果,需要人類賦予它一串實(shí)打?qū)嵉闹噶?,然后?jì)算機(jī)就根據(jù)這串指令一步步地執(zhí)行下去。這個(gè)過(guò)程中的因果關(guān)系非常明確,只要人類的理解不出偏差,運(yùn)行結(jié)果是可以準(zhǔn)確預(yù)測(cè)的。但是在機(jī)器學(xué)習(xí)中,這一傳統(tǒng)樣式被打破了:計(jì)算機(jī)確實(shí)仍然需要人類賦予它一串指令,但這串指令往往不能直接得到結(jié)果;相反,它是一串賦予了機(jī)器“學(xué)習(xí)能力”的指令。在此基礎(chǔ)上,計(jì)算機(jī)需要進(jìn)一步地接受“數(shù)據(jù)”,并根據(jù)之前人類賦予它的“學(xué)習(xí)能力”,從中“學(xué)習(xí)”出最終的結(jié)果。這個(gè)結(jié)果往往是無(wú)法僅僅通過(guò)直接編程得出的。因此這里就導(dǎo)出了稍微深一點(diǎn)的機(jī)器學(xué)習(xí)的定義:它是一種讓計(jì)算機(jī)利用數(shù)據(jù)而非指令來(lái)進(jìn)行各種工作的方法。在這背后,最關(guān)鍵的就是“統(tǒng)計(jì)”的思想,它所推崇的“相關(guān)而非因果”的概念是機(jī)器學(xué)習(xí)的理論根基。在此基礎(chǔ)上,機(jī)器學(xué)習(xí)可以說(shuō)是計(jì)算機(jī)使用輸入給它的數(shù)據(jù),利用人類賦予它的算法得到某種模型的過(guò)程,其最終的目的則是使用該模型,預(yù)測(cè)未來(lái)未知數(shù)據(jù)的信息。

            既然提到了統(tǒng)計(jì),那么一定的數(shù)學(xué)理論就不可或缺。相關(guān)的、比較簡(jiǎn)短的定義會(huì)在第4章給出(PAC框架),這里我們就先只敘述機(jī)器學(xué)習(xí)在統(tǒng)計(jì)理論下的、比較深刻的本質(zhì):它追求的是合理的假設(shè)空間(Hypothesis Space)的選取和模型的泛化(Generalization)能力。該句中出現(xiàn)了一些專用術(shù)語(yǔ),詳細(xì)的定義會(huì)在介紹術(shù)語(yǔ)時(shí)提及,這里我們提供一個(gè)直觀的理解:

            所謂的假設(shè)空間,就是我們的模型在數(shù)學(xué)上的“適用場(chǎng)合”。

            所謂的泛化能力,就是我們的模型在未知數(shù)據(jù)上的表現(xiàn)。

            注意:上述本質(zhì)上嚴(yán)格來(lái)說(shuō),應(yīng)該是PAC Learning的本質(zhì);在其余的理論框架下,機(jī)器學(xué)習(xí)是可以具有不同的內(nèi)核的。

            從上面的討論可以看出,機(jī)器學(xué)習(xí)和人類思考的過(guò)程有或多或少的類似。事實(shí)上,我們?cè)诘?、第7章講的神經(jīng)網(wǎng)絡(luò)(Neural Network,NN)和卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network,CNN)背后確實(shí)有著相應(yīng)的神經(jīng)科學(xué)的理論背景。然而與此同時(shí)需要知道的是,機(jī)器學(xué)習(xí)并非是一個(gè)“會(huì)學(xué)習(xí)的機(jī)器人”和“具有學(xué)習(xí)能力的人造人”之類的,這一點(diǎn)從上面諸多討論也可以明晰(慚愧的是,筆者在第一次聽(tīng)到“機(jī)器學(xué)習(xí)”四個(gè)字時(shí),腦海中浮現(xiàn)的正是一個(gè)“聰明的機(jī)器人”的圖像,甚至還幻想過(guò)它和人類一起生活的場(chǎng)景)。相反的,它是被人類利用的、用于發(fā)掘數(shù)據(jù)背后信息的工具。

            當(dāng)然,現(xiàn)在也不乏“危險(xiǎn)的人工智能”的說(shuō)法,霍金大概是其中的“標(biāo)桿”,這位偉大的英國(guó)理論物理學(xué)家甚至警告說(shuō)“人工智能的發(fā)展可能意味著人類的滅亡”。孰好孰壞果然還是見(jiàn)仁見(jiàn)智,但可以肯定的是:本書所介紹的內(nèi)容絕不至于導(dǎo)致世界的毀滅,大家大可輕松愉快地進(jìn)行接下來(lái)的閱讀!

            機(jī)器學(xué)習(xí)常用術(shù)語(yǔ)

            機(jī)器學(xué)習(xí)領(lǐng)域有著許多非?;镜男g(shù)語(yǔ),這些術(shù)語(yǔ)在外人聽(tīng)來(lái)可能相當(dāng)高深莫測(cè)。它們事實(shí)上也可能擁有非常復(fù)雜的數(shù)學(xué)背景,但需要知道:它們往往也擁有著相對(duì)淺顯平凡的直觀理解(上一小節(jié)的假設(shè)空間和泛化能力就是兩個(gè)例子)。本小節(jié)會(huì)對(duì)這些常用的基本術(shù)語(yǔ)進(jìn)行說(shuō)明與解釋,它們背后的數(shù)學(xué)理論會(huì)有所闡述,但不會(huì)涉及過(guò)于本質(zhì)的東西。

            正如前文反復(fù)強(qiáng)調(diào)的,數(shù)據(jù)在機(jī)器學(xué)習(xí)中發(fā)揮著不可或缺的作用;而用于描述數(shù)據(jù)的術(shù)語(yǔ)有好幾個(gè),需要被牢牢記住的如下。

            “數(shù)據(jù)集”(Data Set),就是數(shù)據(jù)的集合的意思。其中,每一條單獨(dú)的數(shù)據(jù)被稱為“樣本”(Sample)。若沒(méi)有進(jìn)行特殊說(shuō)明,本書都會(huì)假設(shè)數(shù)據(jù)集中樣本之間在各種意義下相互獨(dú)立。事實(shí)上,除了某些特殊的模型(如隱馬爾可夫模型和條件隨機(jī)場(chǎng)),該假設(shè)在大多數(shù)場(chǎng)景下都是相當(dāng)合理的。

            對(duì)于每個(gè)樣本,它通常具有一些“屬性”(Attribute)或者說(shuō)“特征”(Feature),特征所具體取的值就被稱為“特征值”(Feature Value)。

            特征和樣本所張成的空間被稱為“特征空間”(Feature Space)和“樣本空間”(Sample Space),可以把它們簡(jiǎn)單地理解為特征和樣本“可能存在的空間”。

            相對(duì)應(yīng)的,我們有“標(biāo)簽空間”(Label Space),它描述了模型的輸出“可能存在的空間”;當(dāng)模型是分類器時(shí),我們通常會(huì)稱之為“類別空間”。

            其中、數(shù)據(jù)集又可以分為以下三類:

            訓(xùn)練集(Training Set);顧名思義,它是總的數(shù)據(jù)集中用來(lái)訓(xùn)練我們模型的部分。雖說(shuō)將所有數(shù)據(jù)集都拿來(lái)當(dāng)作訓(xùn)練集也無(wú)不可,不過(guò)為了提高及合理評(píng)估模型的泛化能力,我們通常只會(huì)取數(shù)據(jù)集中的一部分來(lái)當(dāng)訓(xùn)練集。

            測(cè)試集(Test Set);顧名思義,它是用來(lái)測(cè)試、評(píng)估模型泛化能力的部分。測(cè)試集不會(huì)用在模型的訓(xùn)練部分,換句話說(shuō),測(cè)試集相對(duì)于模型而言是“未知”的,所以拿它來(lái)評(píng)估模型的泛化能力是相當(dāng)合理的。

            交叉驗(yàn)證集(Cross-Validation Set,CV Set);這是比較特殊的一部分?jǐn)?shù)據(jù),它是用來(lái)調(diào)整模型具體參數(shù)的。

            注意:需要指出的是,獲取數(shù)據(jù)集這個(gè)過(guò)程是不平凡的;尤其是當(dāng)今“大數(shù)據(jù)”如日中天的情景下,諸如“得數(shù)據(jù)者得天下”的說(shuō)法也不算誑語(yǔ)。在此筆者推薦一個(gè)非常著名的含有大量真實(shí)數(shù)據(jù)集的網(wǎng)站: http://archive.ics.uci.edu/ml/datasets.html ,本書常常會(huì)用到其中一些合適的數(shù)據(jù)集來(lái)評(píng)估我們自己實(shí)現(xiàn)的模型。

            可以通過(guò)具體的例子來(lái)理解上述概念。比如,我們假設(shè)小明是一個(gè)在北京讀了一年書的學(xué)生,某天他想通過(guò)宿舍窗外的風(fēng)景(能見(jiàn)度、溫度、濕度、路人戴口罩的情況等)來(lái)判斷當(dāng)天的霧霾情況并據(jù)此決定是否戴口罩。此時(shí),他過(guò)去一年的經(jīng)驗(yàn)就是他擁有的數(shù)據(jù)集,過(guò)去一年中每一天的情況就是一個(gè)樣本。“能見(jiàn)度”、“溫度”、“濕度”、“路人戴口罩的情況”就是四個(gè)特征,而(能見(jiàn)度)“低”、(溫度)“低”、(濕度)“高”、(路人戴口罩的)“多”就是相對(duì)應(yīng)的特征值?,F(xiàn)在小明想了想,決定在腦中建立一個(gè)模型來(lái)幫自己做決策,該模型將利用過(guò)去一年的數(shù)據(jù)集來(lái)對(duì)如今的情況做出“是否戴口罩”的決策。此時(shí)小明可以用過(guò)去一年中8個(gè)月的數(shù)據(jù)量來(lái)做訓(xùn)練集、2個(gè)月的量來(lái)做測(cè)試集、2個(gè)月的量來(lái)做交叉驗(yàn)證集,那么小明就需要不斷地思考(訓(xùn)練模型)下列問(wèn)題:

            用訓(xùn)練集訓(xùn)練出的模型是怎樣的?

            該模型在交叉驗(yàn)證集上的表現(xiàn)怎么樣?

            . 如果足夠好了,那么思考結(jié)束(得到最終模型)。

            . 如果不夠好,那么根據(jù)模型在交叉驗(yàn)證集上的表現(xiàn),重新思考(調(diào)整模型參數(shù))

            最后,小明可能會(huì)在測(cè)試集上評(píng)估自己剛剛思考后得到的模型的性能,然后根據(jù)這個(gè)性能和模型做出的“是否戴口罩”的決策來(lái)綜合考慮自己到底戴不戴口罩。

            接下來(lái)說(shuō)明上一小節(jié)中提到過(guò)的重要概念:假設(shè)空間與泛化能力。泛化能力的含義在上文也有說(shuō)明,為強(qiáng)調(diào)起見(jiàn),這里再敘述一遍:

            泛化能力針對(duì)的其實(shí)是學(xué)習(xí)方法,它用于衡量該學(xué)習(xí)方法學(xué)習(xí)到的模型在整個(gè)樣本空間上的表現(xiàn)。

            這一點(diǎn)當(dāng)然是十分重要的,因?yàn)槲覀兡脕?lái)訓(xùn)練模型的數(shù)據(jù)終究只是樣本空間的一個(gè)很小的采樣,如果只是過(guò)分專注于它們,就會(huì)出現(xiàn)所謂的“過(guò)擬合”(Over Fitting)的情況。當(dāng)然,如果過(guò)分罔顧訓(xùn)練數(shù)據(jù),又會(huì)出現(xiàn)“欠擬合”(Under Fitting)??梢杂靡粡垐D來(lái)直觀地感受過(guò)擬合和欠擬合(如圖1所示,左為欠擬合,右為過(guò)擬合)。


          圖1 欠擬合與過(guò)擬合


            圖1 欠擬合與過(guò)擬合

            所以需要“張弛有度”,找到最好的那個(gè)平衡點(diǎn)。統(tǒng)計(jì)學(xué)習(xí)中的結(jié)構(gòu)風(fēng)險(xiǎn)最小化(Structural Risk Minimization,SRM)就是研究這個(gè)的,它和傳統(tǒng)的經(jīng)驗(yàn)風(fēng)險(xiǎn)最小化(Empirical Risk Minimization,ERM)相比,注重于對(duì)風(fēng)險(xiǎn)上界的最小化,而不是單純地使經(jīng)驗(yàn)風(fēng)險(xiǎn)最小化。它有一個(gè)原則:在使風(fēng)險(xiǎn)上界最小的函數(shù)子集中挑選出使經(jīng)驗(yàn)風(fēng)險(xiǎn)最小的函數(shù)。而這個(gè)函數(shù)子集,正是我們之前提到過(guò)的假設(shè)空間。

            注意:所謂經(jīng)驗(yàn)風(fēng)險(xiǎn),可以理解為訓(xùn)練數(shù)據(jù)集上的風(fēng)險(xiǎn)。相對(duì)應(yīng)的,ERM則可以理解為只注重訓(xùn)練數(shù)據(jù)集的學(xué)習(xí)方法,它的理論基礎(chǔ)是經(jīng)驗(yàn)風(fēng)險(xiǎn)在某種足夠合理的數(shù)學(xué)意義上一致收斂于期望風(fēng)險(xiǎn),亦即所謂的“真正的”風(fēng)險(xiǎn)。

            關(guān)于SRM和ERM的詳細(xì)討論會(huì)涉及諸如VC維和正則化的概念,這里不進(jìn)行詳細(xì)展開(kāi),但需要有這么一個(gè)直觀的認(rèn)識(shí):為了使我們學(xué)習(xí)方法訓(xùn)練出的模型泛化能力足夠好,需要對(duì)模型做出一定的“限制”,而這個(gè)“限制”就表現(xiàn)在假設(shè)空間的選取上。一個(gè)非常普遍的做法是對(duì)模型的復(fù)雜度做出一定的懲罰,從而使模型趨于精簡(jiǎn)。這與所謂的“奧卡姆剃刀原理”不謀而合:“如無(wú)必要,勿增實(shí)體”“切勿浪費(fèi)較多的東西去做,用較少的東西、同樣可以做好事情”。

            相比起通過(guò)選取合適的假設(shè)空間來(lái)規(guī)避過(guò)擬合,進(jìn)行交叉驗(yàn)證(Cross Validation)則可以讓我們知道過(guò)擬合的程度,從而幫助我們選擇合適的模型。常見(jiàn)的交叉驗(yàn)證有以下三種。

            S-fold Cross Validation:中文可翻譯成S折交叉驗(yàn)證,它是應(yīng)用最多的一種方法,其方法大致如下。

            . 將數(shù)據(jù)分成S份:D={D_1,D_2,…,D_S},一共做S次試驗(yàn)。

            . 在第i次試驗(yàn)中,使用D-D_i作為訓(xùn)練集,D_i作為測(cè)試集對(duì)模型進(jìn)行訓(xùn)練和評(píng)測(cè)。

            . 最終選擇平均測(cè)試誤差最小的模型。

            留一交叉驗(yàn)證(Leave-one-out Cross Validation):這是S折交叉驗(yàn)證的特殊情況,此時(shí)S=N。

            簡(jiǎn)易交叉驗(yàn)證:這種實(shí)現(xiàn)起來(lái)最簡(jiǎn)單,也是本書(在進(jìn)行交叉驗(yàn)證時(shí))所采用的方法。它簡(jiǎn)單地將數(shù)據(jù)進(jìn)行隨機(jī)分組,最后達(dá)到訓(xùn)練集約占原數(shù)據(jù)70%的程度(這個(gè)比例可以視情況改變),選擇模型時(shí)使用測(cè)試誤差作為標(biāo)準(zhǔn)。

            機(jī)器學(xué)習(xí)的重要性

            道理說(shuō)了不少,但到底為什么要學(xué)機(jī)器學(xué)習(xí),機(jī)器學(xué)習(xí)的重要性又在哪里呢?事實(shí)上,回顧歷史可以發(fā)現(xiàn),人類的發(fā)展通常伴隨著簡(jiǎn)單體力勞動(dòng)向復(fù)雜腦力勞動(dòng)的過(guò)渡。過(guò)去的工作基本上都有著明確的定義,告訴你這一步怎么做、下一步再怎么做。而如今這一類的工作已經(jīng)越來(lái)越少,取而代之的是更為寬泛模糊的、概念性的東西,比如說(shuō)“將本季度的產(chǎn)品推向最合適的市場(chǎng),在最大化期望利潤(rùn)的同時(shí),盡量做到風(fēng)險(xiǎn)最小化”這種需求。想要完成好這樣的任務(wù),需要獲取相應(yīng)的數(shù)據(jù);雖說(shuō)網(wǎng)絡(luò)的存在讓我們能夠得到數(shù)之不盡的數(shù)據(jù),然而從這些數(shù)據(jù)中獲得信息與知識(shí)卻不是一項(xiàng)簡(jiǎn)單的工作。我們當(dāng)然可以人工地、仔細(xì)地逐項(xiàng)甄選,但這樣顯然就又回到了最初的原點(diǎn)。機(jī)器學(xué)習(xí)這門技術(shù),可以說(shuō)正因此應(yīng)運(yùn)而生。

            單單抽象地說(shuō)一大堆空話可能會(huì)讓人頭昏腦漲,我們就舉一舉機(jī)器學(xué)習(xí)具體的應(yīng)用范圍,從中大概能夠比較直觀地看出機(jī)器學(xué)習(xí)的強(qiáng)大與重要。

            發(fā)展到如今,機(jī)器學(xué)習(xí)的“爪牙”可謂已經(jīng)伸展到了各個(gè)角落、包括但不限于:

            機(jī)器視覺(jué),也就是最近機(jī)器學(xué)習(xí)里很火熱的深度學(xué)習(xí)的一種應(yīng)用;

            語(yǔ)音識(shí)別,也就是微軟Cortana背后的核心技術(shù);

            數(shù)據(jù)挖掘,也就是耳熟能詳?shù)拇髷?shù)據(jù)相關(guān)的領(lǐng)域;

            統(tǒng)計(jì)學(xué)習(xí),也就是本書講解的主要范圍之一,有許許多多著名的算法(比如支持向量機(jī)SVM)都源于統(tǒng)計(jì)學(xué)習(xí)(但是統(tǒng)計(jì)學(xué)習(xí)還是和機(jī)器學(xué)習(xí)有區(qū)別的;簡(jiǎn)單地說(shuō),統(tǒng)計(jì)學(xué)習(xí)偏數(shù)學(xué)而機(jī)器學(xué)習(xí)偏實(shí)踐)。

            機(jī)器學(xué)習(xí)還能夠進(jìn)行模式識(shí)別、自然語(yǔ)言處理,等等,之前提到過(guò)的圍棋界的Master和最新人工智能在德州撲克上的表現(xiàn)亦無(wú)不呈現(xiàn)著機(jī)器學(xué)習(xí)強(qiáng)大的潛力。一言以蔽之,機(jī)器學(xué)習(xí)是當(dāng)今的熱點(diǎn),雖說(shuō)不能保證它的熱度能100%地一直延續(xù)下去,至少筆者認(rèn)為、它能在相當(dāng)長(zhǎng)的一段時(shí)間內(nèi)保持強(qiáng)大的生命力。

            人生苦短,我用Python

            上一節(jié)大概地介紹了機(jī)器學(xué)習(xí)的各種概念,這一節(jié)我們主要講講腳本語(yǔ)言Python相關(guān)的一些東西。題目是在Python界流傳甚廣的“諺語(yǔ)”,它講述了Python強(qiáng)大的功能與易于上手的特性。

            為何選擇Python

            援引開(kāi)源運(yùn)動(dòng)的領(lǐng)袖人物Eric Raymond的說(shuō)法:“Python語(yǔ)言非常干凈,設(shè)計(jì)優(yōu)雅,具有出色的模塊化特性。其最出色的地方在于,鼓勵(lì)清晰易讀的代碼,特別適合以漸進(jìn)開(kāi)發(fā)的方式構(gòu)造項(xiàng)目”。Python的可讀性使得即使是剛學(xué)不久的人也能看懂大部分的代碼,Python龐大的社區(qū)和大量的開(kāi)發(fā)文檔更是使得初學(xué)者能夠快速地實(shí)現(xiàn)許許多多令人驚嘆的功能。對(duì)于Python的程序,人們甚至有時(shí)會(huì)戲稱其為“可執(zhí)行的偽代碼(executable pseudo-code)”,以突顯它的清晰性和可讀性。

            Python的強(qiáng)大是毋庸置疑的,上文提到的Eric Raymond甚至稱其“過(guò)于強(qiáng)大了”。與之相對(duì)應(yīng)的,就是Python的速度比較慢。然而比起Python開(kāi)發(fā)環(huán)境提供的海量高級(jí)數(shù)據(jù)結(jié)構(gòu)(如列表、元組、字典、集合等)和數(shù)之不盡的第三方庫(kù),再加上高速的CPU和近代發(fā)展起來(lái)的GPU編程,速度的問(wèn)題就顯得沒(méi)那么尖銳了。況且Python還能通過(guò)各種途徑使用C / C++代碼來(lái)編寫核心代碼,其強(qiáng)大的“膠水”功能使其速度(在程序員能力允許的情況下)和純粹的C / C++相比已經(jīng)相去不遠(yuǎn)。一個(gè)典型的例子,也是我們會(huì)在本書常常運(yùn)用到的Python中Numpy這個(gè)第三方庫(kù)。編寫它的語(yǔ)言正是底層語(yǔ)言(C和Fortran),其支持向量、矩陣操作的特性和優(yōu)異的速度,使得Python在科學(xué)計(jì)算這一領(lǐng)域大放異彩。

            注意:Python及本書用到的兩個(gè)非常優(yōu)異的第三方庫(kù)—Numpy和TensorFlow的簡(jiǎn)要教程我們會(huì)作為附錄章節(jié)放在本書的最后,建議有需要的讀者先閱讀相應(yīng)部分。

            Python 在機(jī)器學(xué)習(xí)領(lǐng)域的優(yōu)勢(shì)

            雖然在上一小節(jié)敘述了Python的種種好處,但不可否認(rèn)的是,確實(shí)存在諸如MATLAB和Mathematica這樣的高級(jí)程序語(yǔ)言。它們對(duì)機(jī)器學(xué)習(xí)的支持也不錯(cuò),MATLAB甚至還自帶許多機(jī)器學(xué)習(xí)的應(yīng)用。但是作為一個(gè)問(wèn)心無(wú)愧的程序員,我們還是需要提倡支持正版,而MATLAB的正版軟件需要花費(fèi)數(shù)千美元。與之相對(duì),由于Python是開(kāi)源項(xiàng)目,幾乎所有必要的組件都是完全免費(fèi)的。

            之前也提到過(guò)Python的速度問(wèn)題,但是更快更底層的語(yǔ)言,比如C和C++,若使用它們來(lái)學(xué)習(xí)機(jī)器學(xué)習(xí),會(huì)不可避免地引發(fā)這么一個(gè)問(wèn)題:即使是實(shí)現(xiàn)一個(gè)非常簡(jiǎn)單的功能,也需要進(jìn)行大量的編寫和調(diào)試的過(guò)程;在這期間,程序員很有可能忘掉學(xué)習(xí)機(jī)器學(xué)習(xí)的初衷而迷失在代碼的海洋中。筆者曾經(jīng)嘗試過(guò)將Python上的神經(jīng)網(wǎng)絡(luò)框架移植到C++上,這之間的折騰至今難忘。

            此外,筆者認(rèn)為、使用Python來(lái)學(xué)習(xí)機(jī)器學(xué)習(xí)是和“不要過(guò)早優(yōu)化”這句編程界的金句有著異曲同工之妙的。Python(幾乎)唯一的缺陷—速度,在初期進(jìn)行快速檢驗(yàn)算法、思想正誤及開(kāi)發(fā)工作時(shí),其實(shí)基本上不是重要問(wèn)題。其中的道理是顯而易見(jiàn)的:如果解決問(wèn)題的思想存在問(wèn)題,那么即使拼命去提高程序的運(yùn)行效率,也只能使問(wèn)題越來(lái)越大而已。這種時(shí)候,先使用Python進(jìn)行快速實(shí)現(xiàn),有必要時(shí)再用底層代碼重寫核心代碼,從各方面來(lái)說(shuō)都是一個(gè)更好的選擇。

            關(guān)于Anaconda

            Python的強(qiáng)大有相當(dāng)大一部分體現(xiàn)在它那浩如煙海的第三方庫(kù)。在使用Python實(shí)現(xiàn)一個(gè)復(fù)雜功能時(shí),如果沒(méi)有特殊的需求,我們通常會(huì)先搜索Google有沒(méi)有現(xiàn)成的第三方庫(kù),然后會(huì)搜索是否有相關(guān)聯(lián)的第三方庫(kù),最后才會(huì)考慮自己重頭實(shí)現(xiàn)。

            第三方庫(kù)是如此之多,從中挑選出心儀而合適的并非易事。幸運(yùn)的是,就連這一點(diǎn)也有第三方軟件進(jìn)行了支持,那就是在Python科學(xué)計(jì)算領(lǐng)域非常出名的Anaconda。這是一個(gè)完全免費(fèi)的軟件,經(jīng)常會(huì)進(jìn)行各種更新;最重要的是,它把幾乎所有常用且優(yōu)異的科學(xué)計(jì)算庫(kù)都集成在了一起。換句話說(shuō),只要你安裝了Anaconda,就意味著擁有了一個(gè)完善精致的機(jī)器學(xué)習(xí)環(huán)境,基本上無(wú)須自己把要用到的庫(kù)一個(gè)一個(gè)通過(guò)命令行來(lái)安裝。

            第一個(gè)機(jī)器學(xué)習(xí)樣例

            作為本章的總結(jié),我們來(lái)運(yùn)用Python解決一個(gè)實(shí)際問(wèn)題,以便對(duì)機(jī)器學(xué)習(xí)有一個(gè)具體的感受。由于該樣例只是為了提供直觀感受,我們就拿比較有名的一個(gè)小問(wèn)題來(lái)進(jìn)行闡述。俗話說(shuō):“麻雀雖小,五臟俱全”,我們完全可以通過(guò)這個(gè)樣例來(lái)對(duì)機(jī)器學(xué)習(xí)的一般性步驟進(jìn)行一個(gè)大致的認(rèn)知。

            該問(wèn)題來(lái)自Coursera上的斯坦福大學(xué)機(jī)器學(xué)習(xí)課程,其敘述如下:現(xiàn)有47個(gè)房子的面積和價(jià)格,需要建立一個(gè)模型對(duì)新的房?jī)r(jià)進(jìn)行預(yù)測(cè)。稍微翻譯問(wèn)題,可以得知:

            輸入數(shù)據(jù)只有一維,亦即房子的面積。

            目標(biāo)數(shù)據(jù)也只有一維,亦即房子的價(jià)格。

            需要做的,就是根據(jù)已知的房子的面積和價(jià)格的關(guān)系進(jìn)行機(jī)器學(xué)習(xí)。

            下面我們就來(lái)一步步地進(jìn)行操作。

            獲取與處理數(shù)據(jù)

            原始數(shù)據(jù)集的前10個(gè)樣本如表1.1所示,這里房子面積和房子價(jià)格的單位可以隨意定奪,因?yàn)樗鼈儾粫?huì)對(duì)結(jié)果造成影響。

            表1.1 房?jī)r(jià)數(shù)據(jù)集



            完整的數(shù)據(jù)集可以參見(jiàn) https://github.com/carefree0910/MachineLearning/blob/master/ _Data/prices.txt 。雖然該數(shù)據(jù)集比較簡(jiǎn)單,但可以看到其中的數(shù)字都相當(dāng)大。保留它原始形式確實(shí)有可能是有必要的,但一般而言,我們應(yīng)該對(duì)它做簡(jiǎn)單的處理以期望降低問(wèn)題的復(fù)雜度。在這個(gè)例子里,采取常用的將輸入數(shù)據(jù)標(biāo)準(zhǔn)化的做法,其數(shù)學(xué)公式為:



            代碼1-1 第一個(gè)機(jī)器學(xué)習(xí)樣例:a_FirstExampleRegression.py

            01 # 導(dǎo)入需要用到的庫(kù)

            02 import numpy as np

            03 import matplotlib.pyplot as plt

            04

            05 # 定義存儲(chǔ)輸入數(shù)據(jù)(x)和目標(biāo)數(shù)據(jù)(y)的數(shù)組

            06 x, y = [], []

            07 # 遍歷數(shù)據(jù)集,變量sample對(duì)應(yīng)的正是一個(gè)個(gè)樣本

            08 for sample in open("../_Data/prices.txt", "r"):

            09 # 由于數(shù)據(jù)是用逗號(hào)隔開(kāi)的,所以調(diào)用Python中的split方法并將逗號(hào)作為參數(shù)傳入

            10 _x, _y = sample.split(",")

            11 # 將字符串?dāng)?shù)據(jù)轉(zhuǎn)化為浮點(diǎn)數(shù)

            12 x.append(float(_x))

            13 y.append(float(_y))

            14 # 讀取完數(shù)據(jù)后,將它們轉(zhuǎn)化為Numpy數(shù)組以方便進(jìn)一步的處理

            15 x, y = np.array(x), np.array(y)

            16 # 標(biāo)準(zhǔn)化

            17 x = (x - x.mean()) / x.std()

            18 # 將原始數(shù)據(jù)以散點(diǎn)圖的形式畫出

            19 plt.figure()

            20 plt.scatter(x, y, c="g", s=6)

            21 plt.show()

            上面這段代碼的運(yùn)行結(jié)果如圖2所示。


          圖2 預(yù)處理后的數(shù)據(jù)散點(diǎn)圖


            圖2 預(yù)處理后的數(shù)據(jù)散點(diǎn)圖

            這里橫軸是標(biāo)準(zhǔn)化后的房子面積,縱軸是房子價(jià)格。以上我們已經(jīng)比較好地完成了機(jī)器學(xué)習(xí)任務(wù)的第一步:數(shù)據(jù)預(yù)處理。

            選擇與訓(xùn)練模型

            在弄好數(shù)據(jù)之后,下一步就要開(kāi)始選擇相應(yīng)的學(xué)習(xí)方法和模型了。幸運(yùn)的是,通過(guò)可視化原始數(shù)據(jù),可以非常直觀地感受到:很有可能通過(guò)線性回歸(Linear Regression)中的多項(xiàng)式擬合來(lái)得到一個(gè)不錯(cuò)的結(jié)果。其模型的數(shù)學(xué)表達(dá)式如下。

            注意:用多項(xiàng)式擬合散點(diǎn)只是線性回歸的很小的一部分,但是它的直觀意義比較明顯??紤]到問(wèn)題比較簡(jiǎn)單,我們才選用了多項(xiàng)式擬合。線性回歸的詳細(xì)討論超出了本書的范圍,這里不再贅述。



            其中f(x|p;n)就是我們的模型,p、n都是模型的參數(shù),其中p是多項(xiàng)式f的各個(gè)系數(shù),n是多項(xiàng)式的次數(shù)。L(p;n)則是模型的損失函數(shù),這里我們采用了常見(jiàn)的平方損失函數(shù),也就是所謂的歐氏距離(或說(shuō)向量的二范數(shù))。x、y則分別是輸入向量和目標(biāo)向量;在我們這個(gè)樣例中,x、y這兩個(gè)向量都是47維的向量,分別由47個(gè)不同的房子面積、房子價(jià)格所構(gòu)成。

            在確定好模型后,就可以開(kāi)始編寫代碼來(lái)進(jìn)行訓(xùn)練了。對(duì)于大多數(shù)機(jī)器學(xué)習(xí)算法,所謂的訓(xùn)練正是最小化某個(gè)損失函數(shù)的過(guò)程,這個(gè)多項(xiàng)式擬合的模型也不例外:我們的目的就是讓上面定義的L(p;n)最小。在數(shù)理統(tǒng)計(jì)領(lǐng)域里有專門的理論研究這種回歸問(wèn)題,其中比較有名的正規(guī)方程更是直接給出了一個(gè)簡(jiǎn)單的解的通式。不過(guò)由于有Numpy的存在,這個(gè)訓(xùn)練過(guò)程甚至變得還要更加簡(jiǎn)單一些。

            22 # 在(-2,4)這個(gè)區(qū)間上取100個(gè)點(diǎn)作為畫圖的基礎(chǔ)

            23 x0 = np.linspace(-2, 4, 100)

            24 # 利用Numpy的函數(shù)定義訓(xùn)練并返回多項(xiàng)式回歸模型的函數(shù)

            25 # deg參數(shù)代表著模型參數(shù)中的n,亦即模型中多項(xiàng)式的次數(shù)

            26 # 返回的模型能夠根據(jù)輸入的x(默認(rèn)是x0),返回相對(duì)應(yīng)的預(yù)測(cè)的y

            27 def get_model(deg):

            28 return lambda input_x=x0: np.polyval(np.polyfit(x, y, deg), input_x)

            這里需要解釋Numpy里面帶的兩個(gè)函數(shù):polyfit和polyval的用法。

            polyfit(x, y, deg):該函數(shù)會(huì)返回使得上述



            (注:該公式中的x和y就是輸入的x和y)最小的參數(shù)p,亦即多項(xiàng)式的各項(xiàng)系數(shù)。換句話說(shuō),該函數(shù)就是模型的訓(xùn)練函數(shù)。

            polyval(p, x):根據(jù)多項(xiàng)式的各項(xiàng)系數(shù)p和多項(xiàng)式中x的值,返回多項(xiàng)式的值y。

            29 # 根據(jù)參數(shù)n、輸入的x、y返回相對(duì)應(yīng)的損失

            30 def get_cost(deg, input_x, input_y):

            31 return 0.5 * ((get_model(deg)(input_x) - input_y) ** 2).sum()

            32 # 定義測(cè)試參數(shù)集并根據(jù)它進(jìn)行各種實(shí)驗(yàn)

            33 test_set = (1, 4, 10)

            34 for d in test_set:

            35 # 輸出相應(yīng)的損失

            36 print(get_cost(d, x, y))

            所得的結(jié)果是:當(dāng)n=1,4,10時(shí),損失的頭兩位數(shù)字分別為96、94和75。這么看來(lái)似乎是n=10優(yōu)于n=4,而n=1最差,但從圖3可以看出,似乎直接選擇n=1作為模型的參數(shù)才是最好的選擇。這里矛盾的來(lái)源正是前文所提到過(guò)的過(guò)擬合情況。


          圖3 線性回歸的可視化


            圖3 線性回歸的可視化

            那么,怎么最直觀地了解是否出現(xiàn)過(guò)擬合了呢?當(dāng)然還是畫圖了。

            37 # 畫出相應(yīng)的圖像

            38 plt.scatter(x, y, c="g", s=20)

            39 for d in test_set:

            40 plt.plot(x0, get_model(d)(), label="degree = {}".format(d))

            41 # 將橫軸、縱軸的范圍分別限制在(-2,4)、(〖10〗^5,8×〖10〗^5)

            42 plt.xlim(-2, 4)

            43 plt.ylim(1e5, 8e5)

            44 # 調(diào)用legend方法使曲線對(duì)應(yīng)的label正確顯示

            45 plt.legend()

            46 plt.show()

            上面這段代碼的運(yùn)行結(jié)果如圖3所示。

            其中,三條線分別代表n=1、n=4、n=10的情況(圖1.10的右上角亦有說(shuō)明)??梢钥闯?,從n=4開(kāi)始模型就已經(jīng)開(kāi)始出現(xiàn)過(guò)擬合現(xiàn)象了,到n=10時(shí)模型已經(jīng)變得非常不合理。

            至此,可以說(shuō)這個(gè)問(wèn)題就已經(jīng)基本上解決了。在這個(gè)樣例里面,除了交叉驗(yàn)證,我們涵蓋了機(jī)器學(xué)習(xí)中的大部分主要步驟(之所以沒(méi)有進(jìn)行交叉驗(yàn)證是因?yàn)閿?shù)據(jù)太少了……)。代碼部分加起來(lái)總共40~50行,應(yīng)該算是一個(gè)比較合適的長(zhǎng)度。希望大家能夠通過(guò)這個(gè)樣例對(duì)機(jī)器學(xué)習(xí)有個(gè)大概的了解,也希望它能引起大家對(duì)機(jī)器學(xué)習(xí)的興趣。

            本章小結(jié)

            與傳統(tǒng)的計(jì)算機(jī)程序不同,機(jī)器學(xué)習(xí)是面向數(shù)據(jù)的算法,能夠從數(shù)據(jù)中獲得信息。它符合新時(shí)代腦力勞動(dòng)代替體力勞動(dòng)的趨勢(shì),是富有生命力的領(lǐng)域。

            Python是一門優(yōu)異的語(yǔ)言,代碼清晰可讀、功能廣泛強(qiáng)大。其最大弱點(diǎn)—速度問(wèn)題也可以通過(guò)很多不太困難的方法彌補(bǔ)。

            Anaconda是Python的一個(gè)很好的集成環(huán)境,它能讓我們免于人工地安裝大量科學(xué)計(jì)算所需要的第三方庫(kù)。

            雖說(shuō)機(jī)器學(xué)習(xí)算法很多,但通常而言,進(jìn)行機(jī)器學(xué)習(xí)的過(guò)程會(huì)包含以下三步:

            . 獲取與處理數(shù)據(jù);

            . 選擇與訓(xùn)練模型;

            . 評(píng)估與可視化結(jié)果。










          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉