機器學習(1)張量,代價函數(shù)

為什么寫這個

我自己學機器學習大概一年了,有了不少感慨,也走了不少彎路。所以我想寫一份給新手的教程,讓他們可以對機器學習有一個宏觀的把握,不會迷茫。
既然是新手教程,在很多方面我都用了通俗易懂的說法,也許犧牲了一些精確,但可以幫助讀者快速入門。
要學好這份教程,你需要:

  • 高中數(shù)學水平和一點點微積分知識。
  • 熟悉python語法
  • 勤勞的手和熱愛創(chuàng)造的心

我寫的東西肯定不完美,但如果你能從我寫的東西獲得一些收獲,那我是非常高興的。
當然,機器學習我覺得重要的是算法而不是實現(xiàn),所以我會把算法放在一個很重要的位置,至于實現(xiàn),我選擇使用pytorch,scikit,opencv,gensim等等常見庫進行講解。至于一些底層的關于內(nèi)存和計算機的知識,以及一些特別復雜的數(shù)學內(nèi)容,我會單獨標注出來,給有興趣的同學學習。
路漫漫其修遠兮,希望和大家一起進步。

張量(Tensor)

我們高中都學過向量(Vector),例如\left( \begin{array}{ccc} a_1 \\ \vdots \\ a_n \end{array} \right),用a_1a_n分別表示了這個一維的表里不同序號的元素。沒錯,向量就是一張表。
比如我們可以通過以下代碼定義一個向量。

import numpy as np

a = np.array([1,2,3,4])
print(a) #nd.array([1,2,3,4])

在機器學習中,一個向量往往可以描述一個樣本(Sample),這是什么意思呢?
比如一個人的三個科目的成績,就是三個特征(Feature),我們可以用一個三維向量(chinese,math,english)來描述。
當然,不一定多少個特征就多少維的向量,比如我們?nèi)∫粋€特征:情緒,有開心,難過,生氣三個等級。我們一般使用如下方法來表示這個特征:
(1,0,0),if mood=happy\\ (0,1,0),if mood=sad\\ (0,0,1),if mood=angry\\
為什么不用1,2,3三個數(shù)來表示呢,答案很簡單,因為這三個情緒不能比較。
舉個例子,比如人的成績是可以比較的,你比我高,我比你低,我們用1,2,3表示不及格,及格,優(yōu)秀,沒有問題。
但情緒只是狀態(tài),是不可比較的,高興>難過說的過去,但是為什么生氣大于或者小于難過呢,這是難以解釋的,所以我們不這么干。用離散數(shù)學的說法,情緒這個集合不是一個偏序集
說完了一維的表,我們看看二維的例子——矩陣(Matrix),為什么說是二維呢?我們描述里面的元素,要說第幾行第幾列,也就是通過兩個數(shù)來定位元素,比如這個矩陣的下標:\left( \begin{array}{ccc} a_{11} & \cdots & a_{1n}\\ \vdots & \ddots & \vdots \\ a_{n1} & \cdots & a_{nn} \end{array} \right)
矩陣是機器學習的重要部分,基于這個原因后面的文章中我還會引入奇異值分解(SVD),線性空間等等關于高等代數(shù)的內(nèi)容。
下面我們來看看如何在Python定義一個矩陣。

import numpy as np

m = np.array([[1,2],[3,4]])
print(m) #nd.array([[1,2],
         #          [3,4]])

其實你發(fā)現(xiàn),不就是列表套列表,套了兩層嘛。這是個很好的想法!
既然可以套兩層,那為什么不可以套3層,4層,n層呢?我們構造出套了n層的表,把這種結構叫做n維張量!

注意:有的書或者文獻把這種結構叫做數(shù)組(array),這是個偏向計算機的說法,在本教程里一律使用張量。

一個n_1 \times n_2 \times ... \times n_ii維張量里的每個元素可以由i個數(shù)唯一確定。
為了讓讀者理解,我們舉個例子:
我們可以認為一個三維張量是由一系列寫著矩陣的紙片疊起來,第幾張紙就是第一維的數(shù)是幾,剩下兩個數(shù)決定了這張紙上的矩陣的第幾列第幾行。沒錯,三維就是把二維套起來。
那四維呢,無非就是把這些紙張一沓一沓摞起來,相當于又嵌套了一層。
具體一點,看下面這個嵌套列表:

a = [ [[1,2],[3,4]] , [[5,6],[7,8]] ,[[9,10],[11,12]]

第一層嵌套有三個元素[[1,2],[3,4]] , [[5,6],[7,8]] ,[[9,10],[11,12]]
每個第二層嵌套有兩個元素,例如[1,2],[3,4]
每個第三層嵌套有兩個元素,例如1,2
所以這個張量是3 \times 2 \times 2的,請務必搞清楚這個關系,我們一般把第幾層嵌套叫做第幾個軸(axis)。第0個軸就是整個張量的第一層,最后一個軸沒有列表套列表結構,只有元素,也就是最里面一層。

請注意,axis0才是第一個軸,對于一些函數(shù),允許傳入負數(shù)軸表示由內(nèi)而外選擇,例如axis=-1表示選擇最里面一層。

代價函數(shù)(Cost Function)

機器學習大部分情況下只是在尋找一個函數(shù)的最小值。——佚名

我們之所以要做機器學習,是為了讓一個模型(model)能夠很好的擬合實際情況,并表現(xiàn)出某種“智能”。
什么是模型,比如一個簡單模型,我看見天氣預報說明天下雨的概率大于0.5,那么我就說明天下雨。
這里的下雨概率是天氣預報給出的數(shù)據(jù),我們用x表示這個輸入,而我通過輸入是否大于0.5來預測出的這個結果記做h(x)。誰是模型呢,我就是這個模型,我把輸入變成了輸出,至于明天是不是真的下雨,又是一組數(shù)據(jù),我們記做y。很容易猜到h(x)y越接近越好。
模型給出的預測和實際結果可能有誤差,例如我輸出了明天要下雨結果沒有下,這就是誤差。
所以,我們需要找一種方法來度量這種誤差,然后盡量讓誤差變小,誤差和什么有關呢?我們認為只和模型有關。

實際上,由于訓練使用的數(shù)據(jù)不可能包括所有可能取值,不同區(qū)間的數(shù)據(jù)可能誤差不一致,例如訓練區(qū)間誤差很小,但是預測效果糟糕,出現(xiàn)了過擬合(Overfitting),但我們在建模的時候,理想的認為誤差應該對什么樣的輸入都一視同仁。

所以我們需要不斷優(yōu)化模型來減小誤差?依據(jù)什么呢,依據(jù)喂給模型的數(shù)據(jù)x,這個過程在機器學習中我們叫做訓練(train)。這個反映模型在這一組數(shù)據(jù)上誤差的函數(shù)叫做代價函數(shù),我們在代碼里一般用loss來指代這個函數(shù)。
舉個例子,假設我就是一個機器學習模型,我通過觀察女朋友的表情x來預測她的心情y(向量表示法和上一節(jié)的mood一樣),她明明生氣,也就是y=(0,0,1),我卻以為她開心,也就是h(x)=(1,0,0),那么我們可以通過計算這兩個向量的距離來反映誤差大小,距離是\sqrt{2}.接下來我開始訓練(優(yōu)化函數(shù)),我發(fā)現(xiàn)她笑里藏刀,可能開心里有點生氣,那就兩種心情五五開,也就是向量h(x)=(0.5,0,0.5),現(xiàn)在兩個向量距離只有0.5了,說明我這個“模型”經(jīng)過訓練,變得更優(yōu)了。
對于這個過程一定要理解清楚,因為對于大多數(shù)有監(jiān)督學習,都是在進行這個過程。我們后續(xù)會用大量例子來進行說明,區(qū)別只是不同的代價函數(shù),建模過程,和優(yōu)化算法。
下篇文章我們會以一個非常簡單的例子,學習一個二次曲線并進行預測,讓大家深入理解這篇文章里面所說的這些概念,同時介紹一種重要的優(yōu)化算法,梯度下降。

對于初學者,下面這些內(nèi)容較為理論化,不感興趣可以跳過,也可以后期再回頭來看。

代價函數(shù)的參數(shù)實際上有兩個,數(shù)據(jù)和模型,模型可以理解為也是一個函數(shù)(從計算機的角度上這個函數(shù)包含了許多參數(shù),所以也可以認為是閉包(Closure)),從這個角度看,也就是在給定數(shù)據(jù)條件下,代價函數(shù)是一個泛函(Functional),把模型映射到實數(shù)空間上。
定義代價函數(shù)loss = costfunction(model,x)。我們一般用預測和實際之間的距離distance(model(x),y)做為這個函數(shù)。但事情并非絕對,這一點我們后期會說到。
可怎么定義這個距離呢?你一定會說因為yh(x)都是向量,只需要用|y-h(x)|^2或者|y-h(x)|不就可以表明二者的誤差了嘛。但實際上并非如此,我們在后期介紹Logist回歸支持向量機的時候,大量使用的是另外一個基于信息量的數(shù)學期望——信息熵的代價函數(shù),這說明兩個向量之間的距離可以有不同的定義。
在實變函數(shù)論里,我們定義了度量空間,也就是集合的任意兩個元素都是有距離的,我們用一個函數(shù)d來輸出距離,度量x,y距離的度量函數(shù)d必須滿足:
(1)距離是大于等于0的,即d(x,y)≥0.
(2)d(x,y)=d(y,x).(對稱性)
(3)d(x,y)+d(y,z)≥d(x,z).(三角不等式)
下面我們給出另外一個概念,范數(shù),這里不想介紹太多實變函數(shù)的概念,一個元素x的范數(shù)是這個元素到R^+的一個映射,記做||x||,你可以理解為某個元素的范數(shù)就是這個元素到某個“原點”的絕對距離,既然是距離,去掉顯然的對稱性,應該就有上面那三條里的兩條:
(1)||x||≥0.
(2)||x||+||y||≥||x+y||.(三角不等式)
但同時我們?nèi)绻?strong>線性空間(線性空間的元素叫做向量)上范數(shù)的定義滿足:
(3)||cx||=|c| \cdot||x||,c \in R。
那么這個賦范線性空間是度量空間,滿足d(x,y)=||x-y||.反之不一定,一個度量空間不一定是賦范空間,你可以理解為這個空間沒有原點,無法定義一個決定的距離。
下面我們介紹幾種常用的向量的范數(shù):
1-范數(shù)||x||=\sum{|x_i|}.也就是各分量絕對值之和。
2-范數(shù)||x||=\sqrt{x^2}=\sqrt{\sum{x_i^2}}.也就是我們常用的歐式距離
\infty-范數(shù)||x||=max(x_1,x_2,\cdots,x_n).也就是取最大分量。
值得一提的是,在線性空間里矩陣也是廣義向量,當然可以有自己的范數(shù)。
numpy等包中我們用函數(shù)norm來計算范數(shù),numpy.linalg是常用的一個線性代數(shù)包,其中就有norm函數(shù)。下面是調(diào)用方法,其中ord是幾就是幾-范數(shù),對于無窮大,我們傳入np.inf即可。

x_norm=np.linalg.norm(x, ord=None)

下面這個自己寫的函數(shù)定義了兩個向量的歐式距離,我們調(diào)用一次試試:

import numpy as np

from numpy.linalg import norm

def distance(x,y):
  return norm(x-y,2)

a = np.array([1,2,3])
b = np.array([3,2,1])
print(distance(a,b)) #2.8284271247461903
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容