機器學習是近幾年炙手可熱的話題。每天都有新的應用和模型進入人們的視野。世界各地的研究人員每天所公布的實驗結果都顯示了機器學習領域所取得的巨大進步。
技術工作者參加各類課程、搜集各種資料,希望使用這些新技術改進他們的應用。但在很多情形下,要理解機器學習需要深厚的數學功底。這就為那些雖然具有良好的算法技能,但數學概念欠佳的程序員們設置了較高的門檻。
為了掌握它們背後的動機和理論,有必要回顧并建立所有基本推理知識體系,包括統計、概率和微積分。
下面先從一些基本的統計概念開始。
1.3.1 統計學——不确定性建模的基本支柱
統計學可以定義為使用數據樣本,提取和支持關于更大樣本數據結論的學科。考慮到機器學習是研究數據屬性和數據賦值的重要組成部分,本書将使用許多統計概念來定義和證明不同的方法。
描述性統計學——主要操作
接下來将從定義統計學的基本操作和措施入手,并将基本概念作為起點。
(1)平均值(Mean)
這是統計學中直觀、常用的概念。給定一組數字,該集合的平均值是所有元素之和除以集合中元素的數量。
平均值的公式如下。
雖然這是一個非常簡單的概念,但本書還是提供了一個Python代碼示例。在這個示例中,我們将創建樣本集,并用線圖表示它,将整個集合的平均值标記為線,這條線應該位于樣本的加權中心。它既可以作為Python語法的介紹,也可以當作Jupyter Notebook的實驗。代碼如下。
import matplotlib.pyplot as plt #Import the plot library
def mean(sampleset): #Definition header for the mean function
total=0
for element in sampleset:
total=total element
return total/len(sampleset)
myset=[2.,10.,3.,6.,4.,6.,10.] #We create the data set
mymean=mean(myset) #Call the mean funcion
plt.plot(myset) #Plot the dataset
plt.plot([mymean] * 7) #Plot a line of 7 points located on the mean
該程序将輸出數據集元素的時間序列,然後在平均高度上繪制一條線。
如圖1.6所示,平均值是描述樣本集趨勢的一種簡潔(單值)的方式。
圖1.6 用平均值描述樣本集趨勢
因為在第一個例子中,我們使用了一個非常均勻的樣本集,所以均值能夠有效地反映這些樣本值。
下面再嘗試用一個非常分散的樣本集(鼓勵讀者使用這些值)來進行實驗,如圖1.7所示。
圖1.7 分散樣本集的趨勢
(2)方差(Variance)
正如前面的例子所示,平均值不足以描述非均勻或非常分散的樣本數據。
為了使用一個唯一的值來描述樣本值的分散程度,需要介紹方差的概念。它需要将樣本集的平均值作為起點,然後對樣本值到平均值的距離取平均值。方差越大,樣本集越分散。
方差的規範定義如下。
下面采用以前使用的庫,編寫示例代碼來說明這個概念。為了清楚起見,這裡重複mean函數的聲明。代碼如下。
import math #This library is needed for the power operation
def mean(sampleset): #Definition header for the mean function
total=0
for element in sampleset:
total=total element
return total/len(sampleset)
def variance(sampleset): #Definition header for the mean function
total=0
setmean=mean(sampleset)
for element in sampleset:
total=total (math.pow(element-setmean,2))
return total/len(sampleset)
myset1=[2.,10.,3.,6.,4.,6.,10.] #We create the data set
myset2=[1.,-100.,15.,-100.,21.]
print "Variance of first set:" str(variance(myset1))
print "Variance of second set:" str(variance(myset2))
前面的代碼将輸出以下結果。
Variance of first set:8.69387755102
Variance of second set:3070.64
正如上面的結果所示,當樣本值非常分散時,第二組的方差要高得多。因為計算距離平方的均值是一個二次運算,它有助于表示出它們之間的差異。
(3)标準差(Standard Deviation)
标準差隻是對方差中使用的均方值的平方性質進行正則化的一種手段。它有效地将該項線性化。這個方法可以用于其他更複雜的操作。
以下是标準差的表示形式。
1.3.2 概率與随機變量
概率與随機變量對于理解本書所涉概念極為重要。
概率(Probability)是一門數學學科,它的主要目标就是研究随機事件。從實際的角度講,概率試圖從可能發生的所有事件中量化事件發生的确定性(或者不确定性)。
1.事件
為了理解概率,我們首先對事件進行定義。在給定的實驗中,執行确定的動作可能出現不同的結果。事件就是該實驗中所有可能結果的子集。
關于事件的一個例子就是搖骰子時出現的特定數字,或者裝配線上出現的某種産品缺陷。
(1)概率
按照前面的定義,概率是事件發生的可能性。概率被量化為0~1之間的實數。當事件發生的可能性增加時,概率P也按照接近于1的趨勢增加。事件發生概率的數學表達式是P(E)。
(2)随機變量和分布
在分配事件概率時,可以嘗試覆蓋整個樣本,并為樣本空間中的每個可能分配一個概率值。
這個過程具有函數的所有特征。對于每一個随機變量,都會為其可能的事件結果進行賦值。這個函數稱為随機函數。
這些變量有以下兩種類型。
- 離散(Discrete):結果的數量是有限的或可數無窮的。
- 連續(Continuous):結果集屬于連續區間。
這個概率函數也稱為概率分布(Probability Distribution)。
2.常用概率分布
在多種可能的概率分布中,有些函數由于其特殊的性質或它們所代表問題的普遍性而被研究和分析。
本書将描述那些常見的概率分布。它們對機器學習的發展具有特殊的影響。
(1)伯努利分布(Bernoulli Distribution)
從一個簡單的分布開始:像抛硬币一樣,它具有二分類結果(binary outcome)。
這個分布表示單個事件。該事件中1(正面)的概率為p,0(反面)的概率為1−p。
為了實現可視化,可以使用np(NumPy庫)生成大量伯努利分布的事件,并繪制該分布的趨勢。它有以下兩種可能的結果。代碼如下。
plt.figure()
distro = np.random.binomial(1, .6, 10000)/0.5
plt.hist(distro, 2 , normed=1)
下面通過圖1.8中的直方圖顯示二項分布(Binomial Distribution),可以看出結果概率的互補性質。
圖1.8 二項分布
可能結果的概率互補趨勢非常明顯。現在用更多的可能結果來補充模型。當結果的數目大于2時,采用多項式分布(Multinomial Distribution)。代碼如下。
plt.figure()
distro = np.random.binomial(100, .6, 10000)/0.01
plt.hist(distro, 100 , normed=1)
plt.show()
結果如圖1.9所示。
圖1.9 100種可能結果的多項式分布
(2)均勻分布(Uniform Distribution)
這種非常常見的分布是本書出現的第一個連續分布。顧名思義,對于域的任何區間,它都有一個恒定的概率值。
a和b是函數的極值,為了使函數積分為1,這個概率值為1/(b−a)。
下面用一個非常規則的直方圖生成樣本均勻分布的圖。代碼如下。
plt.figure()
uniform_low=0.25
uniform_high=0.8
plt.hist(uniform, 50, normed=1)
plt.show()
結果如圖1.10所示。
圖1.10 均勻分布
(3)正态分布(Normal Distribution)
這是一種常見的連續随機函數,也稱作高斯函數(Gaussian Function)。雖然表達式有些複雜,但它隻需要用均值和方差來定義。
這是函數的标準形式。
查看下面的代碼。
import matplotlib.pyplot as plt #Import the plot library
import numpy as np
mu=0.
sigma=2.
distro = np.random.normal(mu, sigma, 10000)
plt.hist(distro, 100, normed=True)
plt.show()
圖1.11所示為生成的分布直方圖。
圖1.11 正态分布
(4)Logistic分布(Logistic Distribution)
它類似于正态分布,但在形态上與正态分布存在較大差異,其具有細長的尾部。它的重要性在于積累分布函數(Cumulative Distribution Function,CDF),下面的章節中将會使用到它,讀者會覺得它看起來很熟悉。
下面這段代碼表示了它的基本分布。
import matplotlib.pyplot as plt #Import the plot library
import numpy as np
mu=0.5
sigma=0.5
distro2 = np.random.logistic(mu, sigma, 10000)
plt.hist(distro2, 50, normed=True)
distro = np.random.normal(mu, sigma, 10000)
plt.hist(distro, 50, normed=True)
plt.show()
結果如圖1.12所示。
圖1.12 Logistic分布(綠)和正态分布(藍)[1]
如前所述,計算Logistic分布的積累分布函數時,讀者将看到一個非常熟悉的圖形,即Sigmoid曲線。後面在回顧神經網絡激活函數時,還将再次看到它。代碼如下。
plt.figure()
logistic_cumulative = np.random.logistic(mu, sigma, 10000)/0.02
plt.hist(logistic_cumulative, 50, normed=1, cumulative=True)
plt.show()
結果如圖1.13所示。
圖1.13 逆Logistic分布
1.3.3 概率函數的統計度量
這一節中,将看到概率中常見的統計度量。首先是均值和方差,其定義與前面在統計學中看到的定義沒有區别。
1.偏度(Skewness)
它表示了一個概率分布的橫向偏差,即偏離中心的程度或對稱性(非對稱性)。一般來說,如果偏度為負,則表示向右偏離;如果為正,則表示向左偏離。
圖1.14描繪了偏度的統計分布。
圖1.14 分布形狀對偏度的影響
2.峰度(Kurtosis)
峰度顯示了分布的中心聚集程度。它定義了中心區域的銳度,也可以反過來理解,就是函數尾部的分布方式。
峰度的表達式如下。
由圖1.15可以直觀地理解這些新的度量。
圖1.15 分布形狀對峰度的影響
1.3.4 微分基礎
為了覆蓋機器學習的基礎知識,尤其是像梯度下降(Gradient Descent)這樣的學習算法,本書将介紹微分學所涉及的概念。
1.3.5 預備知識
介紹覆蓋梯度下降理論所必需的微積分術語需要很多章節,因此我們假設讀者已經理解連續函數的概念,如線性、二次、對數和指數,以及極限的概念。
為了清楚起見,我們将從一元函數的概念開始,然後簡單地涉及多元函數。
1.變化分析——導數
在前一節中介紹了函數的概念。除了在整個域中定義的常值函數之外,所有函數的值都是動态的。這意味着在x确定的情況下,f(x1)與f(x2)的值是不同的。
微分學的目的是衡量變化。對于這個特定的任務,17世紀的許多數學家(萊布尼茲和牛頓是傑出的倡導者)努力尋找一個簡單的模型來衡量和預測符号定義的函數如何随時間變化。
這項研究将引出一個奇妙的概念—— 一個具有象征性的結果,在一定條件下,表示在某個點上函數變化的程度,以及變化的方向。這就是導數的概念。
在斜線上滑動
如果想測量函數随時間的變化,首先要取一個函數值,在其後的點上測量函數。第一個值減去第二個值,就得到函數随時間變化的程度。代碼如下。
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
def quadratic(var):
return 2* pow(var,2)
x=np.arange(0,.5,.1)
plt.plot(x,quadratic(x))
plt.plot([1,4], [quadratic(1), quadratic(4)], linewidth=2.0)
plt.plot([1,4], [quadratic(1), quadratic(1)], linewidth=3.0,
label="Change in x")
plt.plot([4,4], [quadratic(1), quadratic(4)], linewidth=3.0,
label="Change in y")
plt.legend()
plt.plot (x, 10*x -8 )
plt.plot()
前面的代碼示例首先定義了一個二次方程(2×x2),然後定義arange函數的域(0~0.5,步長0.1)。
定義一個區間,測量y随x的變化,并畫出測量的直線,如圖1.16所示。
圖1.16 求導操作起始設置的初始描述
在x=1和x=4處測量函數,并定義這個區間的變化率。
根據公式,示例程序的運行結果是(36−0)/3=12。
這個方法可以用來近似測量,但它太依賴于測量的點,并且必須在每個時間間隔都進行測量。
為了更好地理解函數的動态變化,需要能夠定義和測量函數域中每個點的瞬時變化率。因為是測量瞬時變化,所以需要減少域x值之間的距離,使各點之間的距離盡量縮短。我們使用初始值x和後續值x Δx來表示這個方法。
下面的代碼中,通過逐步減小Δx來逼近差分值。代碼如下。
initial_delta = .1
x1 = 1
for power in range (1,6):
delta = pow (initial_delta, power)
derivative_aprox= (quadratic(x1 delta) - quadratic (x1) )/
((x1 delta) - x1 )
print "del ta: " str(delta) ", estimated derivative: "
str(derivative_aprox)
在上面的代碼中,首先定義了初始增量Δ,從而獲得初始近似值。然後在差分函數中,對0.1進行乘方運算,幂逐步增大,Δ的值逐步減小,得到如下結果。
delta: 0.1, estimated derivative: 4.2
delta: 0.01, estimated derivative: 4.02
delta: 0.001, estimated derivative: 4.002
delta: 0.0001, estimated derivative: 4.0002
delta: 1e-05, estimated derivative: 4.00002
随着Δ值的逐步減小,變化率将穩定在4左右。但這個過程什麼時候停止呢?事實上,這個過程可以是無限的,至少在數值意義上是這樣。
這就引出了極限的概念。在定義極限的過程中,使 Δ 無限小,得到的結果稱之為f(x)的導數或f ' (x),公式如下。
但是數學家們并沒有停止煩瑣的計算。他們進行了大量的數值運算(大多是在17世紀手工完成的),并希望進一步簡化這些操作。
現在構造一個函數,它可以通過替換x的值來得到相應的導數。對于不同的函數族,從抛物線(y=x2 b)開始,出現了更複雜的函數(見圖1.17),這一巨大的進步發生在17世紀。
圖1.17 複雜函數
2.鍊式法則
在函數導數符号确定後,一個非常重要的結果就是鍊式法則。萊布尼茨在1676年的一篇論文中首次提到這個公式。它可以通過非常簡單優雅的方式求解複合函數的導數,從而簡化複雜函數的求解。
為了定義鍊式法則,假設有一個函數f,F=f (g(x)),那麼導數可以定義如下。
鍊式法則允許對輸入值為另一個函數的方程求導。這與搜索函數之間關聯的變化率是一樣的。鍊式法則是神經網絡訓練階段的主要理論概念之一。因為在這些分層結構中,第一層神經元的輸出将是下一層的輸入。在大多數情況下,複合函數包含了一層以上的嵌套。
偏導數(Partial Derivative)
到目前為止,本書一直使用單變量函數。但是從現在開始,将主要介紹多變量函數。因為數據集将不止包含一個列,并且它們中的每一列将代表不同的變量。
在許多情況下,需要知道函數在一個維度中的變化情況,這将涉及數據集的一列如何對函數的變化産生影響。
偏導數的計算包括将已知的推導規則應用到多變量函數,并把未被求導的變量作為常數導出。
看一看下面的幂函數求導法則。
f(x, y) = 2x3y
當這個函數對x求導時,y作為常量。可以将它重寫為3 ∙ 2 y x2,并将導數應用到變量x,得到以下結果。
d/dx(f(x, y)) = 6y * x2
使用這些方法,可以處理更複雜的多變量函數。這些函數将是特征集的一部分,通常由兩個以上的變量組成。
本文摘自:《機器學習開發者指南》
本書的目标讀者是那些期望掌握機器學習的相關内容、理解主要的基本概念、使用算法思想并能掌握正式數學定義的開發人員。本書使用Python實現了代碼概念,Python語言接口的簡潔性,以及其提供的方便且豐富的工具,将有助于我們處理這些代碼,而有其他編程語言經驗的程序員也能理解書中的代碼。
讀者将學會使用不同類型的算法來解決自己的機器學習相關問題,并了解如何使用這些算法優化模型以得到最佳的結果。如果想要了解現在的機器學習知識和一門友好的編程語言,并且真正走進機器學習的世界,那麼這本書一定能對讀者有所幫助。
本書主要關注機器學習的相關概念,并使用Python語言(版本3)作為編碼工具。本書通過Python 3和Jupyter Notebook來構建工作環境,可以通過編輯和運行它們來更好地理解這些概念。我們專注于如何以最佳方式,利用各種Python庫來構建實際的應用程序。本着這種精神,我們盡力使所有代碼保持友好性和可讀性,使讀者能夠輕松地理解代碼并在不同的場景中使用它們。
,