本文主要介紹了生成式AI的最新發展,提到了GPT-5和AI軟體工程師在行業中的影響,指出AI技術進步對國家競争和個人職業發展的潛在影響。
未來已來
最近有兩則新聞:
- sam altman自曝GPT-5細節,公開宣稱GPT-5提升将非常大,任何小看它的公司都會被碾壓。并發推暗示OpenAI今年的産品會改變人類曆史。
- 關于首個AI軟體工程師的新聞,裡面AI軟體工程師表現已經相當出衆,具備了整體規劃、DevOp、全項目掃描等能力,離真正程式員已經不遠。
雖然一切都在意料之中,但是還是感覺來得快了點。
個人覺得,目前AI技術的進展,至少有兩個方面的影響:
- 大到國家競争層面,有了AI的加持,之前中國對美國的一大優勢—優秀高校畢業生的人數,已經不複存在。後面誰能勝出,就看誰犯的錯誤更少。
- 小到個人飯碗層面,預計2-5年,生産方式就會發生變革,如果沒有跟上,可能會遭受降維打擊。作為一個碼農,抓緊學習AI底層原理,或者參與AI相關應用實踐,才是硬道理。
AI不是黑盒
在開始之前,我想強調一下:AI不是黑盒,它的一切元素、一切過程都是确定的、可解釋的。
我希望能用程式員好懂的方式把AI的原理給撸一遍。希望感興趣的同學讀了這篇文章,能夠跟我一樣,打破AI很複雜、AI是黑盒這樣的迷思。
本文會從神經網絡和深度學習開始,按下面三部分進行解釋:
- 通過一個非常簡單的網絡解釋神經網絡和深度學習的基本原理。
- 再通過一個真實的神經網絡實操給大家一些體感。
- 最後通過一個常見問題引出後面文章要介紹的複雜神經網絡。
神經網絡基本原理
本章重點提示:
- 神經網絡通過“學習”并存儲訓練集的一般規律,來解決訓練集外的問題。
- 存儲是确定的。神經網絡分為多層,每層有多個神經元,每個神經元上有N+1個參數(其中N等于連接配接到神經元的輸入個數)。“學習”到的一般規律,就存儲在(所有神經元的)這些參數裡。
- 過程也是确定的。因為“學習”過程是從高維參數空間(所有神經元的X個參數)的任意一點(參數的初始值是随機給出的)出發,逐漸回歸到損失最低的一點,是一個逐漸調整參數的過程。是以如果調整參數的公式确定,則“學習”的過程就是确定的。是的,調整參數的公式是确定的:模型編譯時,每一層每個神經元每個參數的調整公式,就能根據偏導數的傳遞性,早早被确定了。
▐神經網絡能做什麼
神經網絡和深度學習能解決沒有明确規則或者規律複雜的問題,比如圖像識别(不好寫if else)
▐為什麼神經網絡能解決複雜問題
複雜問題往往不可窮舉(比如不同的貓貓圖),是以沒有一套規則來套用它們所有的執行個體。唯一的辦法就是抽象出它們的一般規律,或者說特征,或者說模式(pattern)。
舉個例子,為什麼text embedding能夠用來做自然語言處理,因為它沒有(也不可能)記錄全部的文本組合,而是通過一個向量來記錄的單個文字或token的模式,這個向量就是對這個文字的抽象。如果兩個文字的向量有部分相似,這種相似性可能對應于它們在特定上下文中的共同特征。具體哪一個向量值代表什麼特征,這些更像是語言文字的中繼資料,我們并不關心。
假設經過訓練,得到king的向量表征是[0.3, 0.5, ..., 0.9],queen是[0.8, 0.5, ..., 0.2],prince是[0.3, 0.7, ..., 0.5],在某一個上下文中,比如 xx is ruling the kingdom,xx可以被king或者queen填充,那它們有可能就是由向量的第2個元素,那個共同的0.5決定的,在另一個上下文,比如 xx is a man,xx可以king或者prince填充,這有可能是由第一個元素決定的。
下面會講到,神經網絡也有一套機制用來計算和存儲這些抽象出來的模式,是以神經網絡非常适合解決涉及抽象概念的複雜問題。
▐神經網絡如何實作
就像我上面說過的,AI不是黑盒。神經網絡和一般程式一樣,也是由資料和計算構成,并且它的存儲和計算都是非常确定的。
舉個例子,我們要解決一個通過x推導y的線性回歸問題。觀察到x=1時y=3,x=2時y=5,現在要求x=3時y=多少。問題本身比較簡單,我們甚至可以直接算出回歸方程式為y = mx + b,其中m = 2, b = 1。
(線性回歸連結:http://www.stat.yale.edu/Courses/1997-98/101/linreg.htm)
問題是,如果我們通過一個單一輸入是x、隻有一層、該層隻有一個神經元、神經元的輸出是y的神經網絡,會以怎樣的方式和過程來“學出”這個結果呢?
網絡1
- 神經網絡的存儲結構
在了解“學習”過程前,我們先來看看神經網絡的存儲結構,即什麼是模型(model)。
上面的[網絡1],它的模型就是由它的結構+它的參數組成。
它的結構是單個輸入、隻有一層、這層隻有一個神經元。
它的參數就是每個神經元上被訓練的資料,這裡隻有一個神經元,它上面有m和b兩個參數。
經過訓練之後的參數(上例中的m=2,b=1),就是被訓練資料集(上例中的x=[1,2,...],y=[3,5,...])的模式,就是對特定問題的抽象。有了這個模式,再灌入别的x,也能算出對應的y。
一個各層緊密相連(Dense)的網絡,每個節點都和上一層所有節點相連,上層所有節點是下層每個節點的輸入。每個節點的輸出是其輸入的權重和,經過激活函數處理後的結果:output = activation_function(W * X + b),其中,X是輸入向量[x1, x2, ..., xn],W是各輸入的權重(weights)向量[w1, w2, ..., wn],b是偏置(bias)常量,activation_function是激活函數。當激活函數是linear時,output = W * X + b。當節點有n個輸入時,節點有[w1, w2, ..., wn, b]共n+1個參數。網絡不同層之間是鍊的關系,結果會向下傳遞,直到最後一層輸出層。任意層的任意一個神經元的任意一個參數,都會影響最終結果。是以這些參數就是神經網絡的存儲單元,用來存儲抽象出來的模式。
再舉一個例子,下圖的[網絡2]是一個有兩個輸入、兩層、第一層2個元、第二層1個元、各層激活函數是linear的網絡。網絡第一層參數總數=(輸入個數+1) 節點數 = (2 + 1) 2 = 6,第二層的參數總數 = (2 + 1) * 1 = 3,網絡參數總數 = 6 + 3 = 9,抽象出來的模式就存儲在這些參數裡。(下圖中的w111,w112,b11,w121,w122,b12,w21,w22,b2)
網絡2
- 激活函數
為什麼要有激活函數(activation function)?我們可以看看如果沒有特殊的激活函數,比如上面的[網絡2],會是什麼情況。
可以看到[網絡2]每一層都是線性函數,根據線性函數的傳導性,最終結果還是一個線性函數。即y_hat=w21*h1+w22*h2+b2=w21*(w111*x1+w112*x2+b11)+w22*(w121*x1+w122*x2+b12)+b2最終可以化簡為y_hat=w1'*x1+w2'*x2+b'。而一個線性函數(直線、平面、…)是沒法拟合/抽象現實問題的複雜度的。
引入激活函數,主要是為了引入非線性函數,讓模型可以拟合/抽象複雜現實問題。
常見的激活函數有:
其中,ReLU用于消除負值,Sigmoid用于增加弧度。
- 深度學習過程
拿上面的[網絡1]舉例。假設模型已按[網絡1]建立,資料集已準備,分為訓練集(training)比如 x=[1,2], y=[3,5] 和驗證集(validation)比如 x=[3], y=[7]。
深度學習即神經網絡訓練步驟:
第1步、初始化參數:這裡隻有一個神經元,m和b兩個參數。随機給值就行,假設m=-1,b=5。
第2步、用訓練集計算輸出y_hat。因為多層網絡的計算是從上往下,是以稱為前向傳播:
第3步、使用損失函數評估輸出的好壞(和實際值的差異),這裡采用MSE(平均方差):
為什麼要用平均方差(Mean squared error):比較适合目前問題(偏離預期回歸線越遠,損失越大)。差的平方(squared error)是為了消除差的負數,并且通過平方擴大內插補點。取平均值(Mean)是将內插補點均攤到訓練集每個樣例。
第4步、通過反向傳播算法計算各參數的梯度(gradient)。
各參數的梯度,即單個參數的變化會多大程度影響損失結果的變化。計算各參數的梯度,再将參數往損失結果變小的方向調整,即可在高維參數空間中找到損失最小值點。
為了計算梯度,我們需要先了解損失曲面。
例子中隻有m和b兩個參數,如果将m和b作為x和y軸,損失函數結果作為z軸,可以得出損失曲面。(如果存在更多參數,形成高維參數空間,道理類似)
我們的目标是找出損失函數結果最小的m和b,這裡即m=2,b=1。具體做法是将參數的目前值m=-1,b=5分次進行一定偏移,往m=2,b=1靠攏。
偏移具體怎麼算呢?這就涉及到計算梯度,數學上就是計算偏導數。
對于一個曲面,目前在高處,要往低處移動,可以分别計算x、y兩個方向(即m和b兩個參數),在目前位置的梯度,即偏導數(partial derivative),即幾何上的切線斜率,即單個參數的變化會多大程度影響損失結果的變化(注意梯度是向上的,用的話要取反)。
幸運的是,對于任何損失函數,都有對應公式算出對于某個參數的偏導數。例如,激活函數是y_hat = m * x + b,損失函數是L = (1/N) * Σ(y - y_hat)^2,則對于m的偏導數是∂L/∂w = (1/N) * Σ -2x(y - y_hat) = (1/N) * Σ -2x(y - (m * x + b))。這裡僅僅是說明能解,因為模型會提供這個能力,是以我們一般不人為關注。
不僅如此,神經網絡還有傳導性,拿[網絡2]舉例,如果我們希望算出第一層參數w111的梯度,則可以按∂L/∂w111 = ∂L/∂y_hat * ∂y_hat/∂h1 * ∂h1/∂w111一層一層反向傳播算回去,得到w111梯度具體的公式。
第5步、按梯度更新各參數:
因為偏導數是向上的,往低處走、梯度下降要取反。
拿m舉例,m的新值m = m - learning_rate * ∂L/∂m。
注意learning_rate的選擇,過大會導緻越過最低點,過小會導緻單次變化太小,訓練時間太長。不過一般模型會提供自動漸進式的算法,我們無需人為關注。
第6步、網絡的訓練過程是疊代的,在每個訓練周期(epoch)中,網絡将通過梯度下降的方式逐漸調整其參數。整個過程會重複多個epoch,直到模型的表現不再顯著提高或滿足特定的停止條件。
每個訓練周期,即會用訓練集進行訓練,也會用驗證集進行驗證。通過對比訓練集和驗證集的結果,能發現是否存在過拟合現象。
關于全局最優解和局部最優解:
如果損失曲面比較複雜,比如有多個低窪,從某個點漸進式移動不一定能找到最低的那個,這種情況會拿到局部最優解而不是全局最優解。
關于訓練batch:如果訓練集非常大,每個訓練周期不一定會拿全部訓練集進行訓練,而是會随機選一批資料進行。常見的方式有Stochastic Gradient Descent(SGD),一次選一個樣例,這樣的好處不僅計算量大大減少,還容易從局部最優解跳出,缺點是不太穩定。另一種方式是Mini-Batch Gradient Descent,這種一次選10-幾百個樣例。具有SGD的優點且比SGD穩定,比較常用。
MNIST資料集深度學習案例
MNIST資料集是深度學習領域的一個經典資料集,它包含了大量的手寫數字圖像,對于驗證深度學習算法的有效性具有标志性意義。
有了前面章節的理論,接下來,我們将通過一個實際案例來展示如何使用神經網絡來解決圖像分類問題。
下面的操作會用到jupyter平台和tensorflow2深度學習架構,但本文重點解釋原理,平台和架構的使用就不多置筆墨了。
- 加載和觀察資料集
在使用圖像進行深度學習時,我們既需要圖像本身(通常表示為 "X"),也需要這些圖像的正确标簽(通常表示為 "Y")。此外,我們需要一組X和Y來訓練模型,然後還需要一組單獨的X和Y來驗證訓練後模型的表現。是以,MNIST資料集需要分成4份:
- x_train:用于訓練神經網絡的圖像
- y_train:x_train圖像的正确标簽,用于評估模型在訓練過程中的預測結果
- x_valid:模型訓練完成後用于驗證模型表現的圖像
- y_valid:x_valid圖像的正确标簽,用于評估模型訓練後的預測結果
我們需要做的第一步,是加載資料集到記憶體,并通過觀察對資料集概貌有一個了解。
通過Keras API加載:
Keras API位址:https://keras.io/
檢視訓練圖像集x_train和驗證圖像集x_valid:可以看到是分别是60000張和10000張28x28 pixel的灰階圖像(灰階0-255):
每個圖像是一個圖像grid的二維數組,下圖是二維數組的内容和可視化圖像:
标簽y_train比較簡單,就是圖像對應的數字:
- 預加工資料集
在将資料輸入到神經網絡之前,通常需要進行一些預處理。這包括将圖像資料展平為一維向量,标準化像素值到0-1之間,并将标簽轉換為适合分類任務的格式,通常是one-hot編碼。
展平:
标準化:
one-hot編碼:
雖然這裡的标簽是0-9的連續整數,但不要把問題看作是一個數值問題(考慮一下這種情況,假設我們不是在識别手寫0-9的圖檔,而是在識别各種動物的圖檔)。
這裡本質上是在處理分類,分類問題的輸出在深度學習架構裡适合用one-hot編碼來表達(一個一維向量,長度為總分類數,所屬分類的值為1,其它值為0)。
- 建立模型
建立一個有效的模型通常需要一定的探索或者經驗。對于MNIST資料集,一個常見的起點是建構一個包含以下層的網絡:
- 784個輸入(對應于28x28像素的輸入圖像)。
- 第一層是輸入層,有512個神經元,激活函數是ReLU。
- 第二層隐藏層,使用512個神經元和ReLU激活函數。
- 第三層是輸出層,10個神經元(對應于10個數字類别),使用Softmax激活函數以輸出機率分布。
激活函數ReLU上面已經介紹過了,這裡的Softmax需要介紹一下:Softmax函數確定輸出層的輸出值總和為1,進而可以被解釋為機率分布。這對于多類分類問題非常有用。例如,輸出層的10個輸出值為[0.9, 0.0, 0.1, 0.0, ..., 0.0]可以解釋為90%機率屬于第1類,10%機率屬于第3類。
按此建立模型并檢視摘要:
可以注意這裡的參數數量。
- 編譯模型
模型在編譯時需要指定損失函數和優化器。對于多分類問題,損失函數通常選擇交叉熵(Categorical Crossentropy),它的特征可以看參考公式:當實際屬于某類(y_actual=1)時,損失等于log(y_hat),否則損失等于log(1-y_hat)。這個損失函數會懲罰錯誤猜測,使其損失接近∞,可以有效地量化預測機率分布與實際分布之間的差距。優化器則負責調整網絡參數以最小化損失函數。
- 訓練并觀察準确率
訓練模型時,我們會在多個訓練周期内疊代更新參數,每個訓練周期會經曆一次完整的前向傳遞計算輸出、損失函數評估結果和後向傳遞更新參數的過程。我們觀察訓練集和驗證集上的準确率,以評估模型的表現和泛化能力。
注意損失曲面、梯度下降等概念和原理,如果不清楚可以回顧一下【深度學習過程】。
下圖中的accuracy是訓練集的準确率,val_accuracy是驗證集的準确率,準确率符合預期。
過拟合和解決方案
如果模型在訓練集上準确率很高,但在驗證集上準确率低,可能出現了過拟合現象(overfitting)。過拟合意味着模型過于複雜或訓練過度,以至于學習了訓練資料中的噪聲而非潛在規律。
訓練集,左邊損失非常小:
驗證集,左邊損失反而更大:
- 出現過拟合說明什麼
左圖可以看到,模型幾乎硬套了訓練集。和人腦類似,硬套部分執行個體,說明模型隻是在記憶這些執行個體,隻有找出它們的規律、特征、模式,才是真正的抽象。這也應證了我前面的說法,神經網絡是在通過抽象解決問題。
- 為什麼會出現過拟合
從被訓練資料來看,過拟合說明訓練集可能特征不明顯,不容易抽象。比如被識别的圖像模糊、亮度不高。
從模型來看,過拟合通常由于模型過于複雜或訓練時間過長造成,走向了死記硬背。
- 如何解決過拟合
AI技術經過多年的發展,現在已經有比較成熟的方案來解決過拟合了,比如卷積神經網絡、遞歸神經網絡,這些我會在後面的文章裡進行介紹。
本文大部分素材來自Nvidia線上課程Getting Started with Deep Learning。
(Getting Started with Deep Learning位址:https://learn.nvidia.com/courses/course-detail?course_id=course-v1:DLI+S-FX-01+V1)
作者:碼一
來源-微信公衆号:大淘寶技術
出處:https://mp.weixin.qq.com/s/zoDHeleVHwnqinSaFaeK2Q