之前一篇筆記:?Python機(jī)器學(xué)習(xí)筆記:不得不了解的機(jī)器學(xué)習(xí)知識(shí)點(diǎn)(1)
1,什么樣的資料集不適合用深度學(xué)習(xí)?
- 數(shù)據(jù)集太小 ,數(shù)據(jù)樣本不足時(shí),深度學(xué)習(xí)相對(duì)其它機(jī)器學(xué)習(xí)算法,沒(méi)有明顯優(yōu)勢(shì)。
- 數(shù)據(jù)集沒(méi)有局部相關(guān)特性, 目前深度學(xué)習(xí)表現(xiàn)比較好的領(lǐng)域主要是圖像/語(yǔ)音/自然語(yǔ)言處理等領(lǐng)域,這些領(lǐng)域的一個(gè)共性是局部相關(guān)性。圖像中像素組成物體,語(yǔ)音信號(hào)中音位組合成單詞,文本數(shù)據(jù)中單詞組合成句子,這些特征元素的組合一旦被打亂,表示的含義同時(shí)也被改變。對(duì)于沒(méi)有這樣的局部相關(guān)性的數(shù)據(jù)集,不適于使用深度學(xué)習(xí)算法進(jìn)行處理。舉個(gè)例子:預(yù)測(cè)一個(gè)人的健康狀況,相關(guān)的參數(shù)會(huì)有年齡、職業(yè)、收入、家庭狀況等各種元素,將這些元素打亂,并不會(huì)影響相關(guān)的結(jié)果。
2,softmax函數(shù)的數(shù)學(xué)推導(dǎo)及Python實(shí)現(xiàn)
softmax用于多分類(lèi)過(guò)程中最后一層,將多個(gè)神經(jīng)元的輸出,映射到(0, 1)區(qū)間內(nèi),可以看成概率來(lái)理解,從而來(lái)進(jìn)行多分類(lèi)!
softmax函數(shù)如下:
更形象的如下圖表示:
softmax 直白來(lái)說(shuō)就是講原來(lái)輸出是 3, 1, -3 通過(guò) softmax 函數(shù)一作用,就映射成為(0, 1)的值,而這些值的累和為1,那么我們就可以將其理解成概率,在最后選取輸出節(jié)點(diǎn)的時(shí)候,我們可以選取概率最大的節(jié)點(diǎn),作為我們的預(yù)測(cè)目標(biāo)!
Python代碼實(shí)現(xiàn):
# _*_coding:utf-8_*_ import tensorflow as tf import numpy as np import math # softmax函數(shù),或稱(chēng)歸一化指數(shù)函數(shù) def softmax(x, axis=1): # 為了避免求 exp(x) 出現(xiàn)溢出的情況,一般需要減去最大值 # 計(jì)算每行的最大值 row_max = x.max(axis=axis) # 每行元素都需要減去對(duì)應(yīng)的最大值,否則求exp(x)會(huì)溢出,導(dǎo)致INF情況 row_max = row_max.reshpae(-1, 1) x = x - row_max x_exp = np.exp(x) # 如果是列向量,則axis=0 x_sum = np.sum(x_exp, axis=1, keepdims=True) s = x_exp / x_sum return s # 簡(jiǎn)單一些 def softmax(x): """Compute softmax values for each sets of scores in x.""" e_x = np.exp(x - np.max(x)) return e_x / e_x.sum() # 使用 tf的softmax函數(shù) with tf.Session() as sess: tf_s2 = tf.nn.softmax(x, axis=axis) s2 = sess.run(tf_s2)
下面我們分析一下,減去最大值和不減去最大值是否有必要嗎?首先看代碼:
import numpy as np def softmax(x): """Compute softmax values for each sets of scores in x.""" e_x = np.exp(x - np.max(x)) return e_x / e_x.sum() def softmax1(x): """Compute softmax values for each sets of scores in x.""" return np.exp(x) / np.sum(np.exp(x), axis=0) scores = [3.0, 1.0, 0.2] print(softmax(scores)) print(softmax1(scores)) ''' 結(jié)果輸出如下: [0.8360188 0.11314284 0.05083836] [0.8360188 0.11314284 0.05083836] '''
其實(shí)兩個(gè)結(jié)果輸出是一樣的,即使第一個(gè)實(shí)現(xiàn)了每列和最大值的差異,然后除以總和,但是問(wèn)題來(lái)了,實(shí)現(xiàn)在代碼和時(shí)間復(fù)雜度方面是否相似?哪一個(gè)更有效率?
當(dāng)然,他們都是正確的,但是從數(shù)值穩(wěn)定性的角度來(lái)看,第一個(gè)是正確的,因?yàn)槲覀儽苊饬饲?exp(x) 出現(xiàn)溢出的情況,這里減去了最大值。我們推導(dǎo)一下:
# 轉(zhuǎn)化公式: a ^(b – c)=(a ^ b)/(a ^ c) e ^ (x - max(x)) / sum(e^(x - max(x)) = e ^ x / (e ^ max(x) * sum(e ^ x / e ^ max(x))) = e ^ x / sum(e ^ x)
3,歐氏距離和曼哈頓距離
歐氏距離(也稱(chēng)為歐幾里得度量) ,是應(yīng)用勾股定理計(jì)算兩個(gè)點(diǎn)之間的直線(xiàn)距離,也就是指m維空間兩個(gè)點(diǎn)之間的真實(shí)距離,或者向量的自然長(zhǎng)度(即該點(diǎn)到原點(diǎn)的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
? 曼哈頓距離 表示的是兩個(gè)點(diǎn)在標(biāo)準(zhǔn)坐標(biāo)系上絕對(duì)軸距之和,是種使用在幾何度量空間的幾何學(xué)用語(yǔ)。
圖中紅線(xiàn)代表曼哈頓距離,綠色代表歐氏距離,也就是直線(xiàn)距離,而藍(lán)色和黃色代表等價(jià)的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實(shí)現(xiàn):
import numpy as np def manhattan_distance(vec1, vec2): """ This method implements the manhattan distance metric :param p_vec: vector one :param q_vec: vector two :return: the manhattan distance between vector one and two """ return np.sum(np.fabs(vec1 - vec2)) def edclidean_distance(vec1, vec2): """ This method implements the edclidean distance metric :param vec1: vector one :param vec2: vector two :return: the edclidean distance between vector one and two """ # 方法一 distance = np.sqrt(np.sum(np.square(vec1 - vec2))) # method 2 dist = np.linalg.norm(vec1 - vec2) return distance
4,什么是數(shù)據(jù)埋點(diǎn)
數(shù)據(jù)埋點(diǎn)我們可以分為兩類(lèi),其一是頁(yè)面統(tǒng)計(jì),其二是行為統(tǒng)計(jì)。
頁(yè)面統(tǒng)計(jì)可以幫我們知曉某個(gè)頁(yè)面被多少人訪(fǎng)問(wèn)了多少次,行為統(tǒng)計(jì)是指用戶(hù)在界面上的操作行為,應(yīng)用最多的是按鈕的點(diǎn)擊次數(shù)。
5,請(qǐng)簡(jiǎn)要說(shuō)說(shuō)一個(gè)完整的機(jī)器學(xué)習(xí)項(xiàng)目流程
5.1:抽象成數(shù)學(xué)問(wèn)題
明確問(wèn)題是進(jìn)行機(jī)器學(xué)習(xí)的第一步。機(jī)器學(xué)習(xí)的訓(xùn)練過(guò)程通常都是一件非常耗時(shí)的事情,胡亂嘗試時(shí)間成本是非常高的。
這里的抽象成數(shù)學(xué)問(wèn)題,指的我們明確我們可以獲得什么樣的數(shù)據(jù),目標(biāo)是一個(gè)分類(lèi)還是回歸或者是聚類(lèi)的問(wèn)題,如果都不是的話(huà),如果劃歸為其中的某類(lèi)問(wèn)題。
5.2:獲取數(shù)據(jù)
數(shù)據(jù)決定了機(jī)器學(xué)習(xí)結(jié)果的上限,而算法只是盡可能逼近這個(gè)上限。數(shù)據(jù)要有代表性,否則必然會(huì)過(guò)擬合。而且對(duì)于分類(lèi)問(wèn)題,數(shù)據(jù)偏斜不能過(guò)于嚴(yán)重,不同類(lèi)別的數(shù)據(jù)數(shù)量不要有數(shù)個(gè)數(shù)量級(jí)的差距。
而且還要對(duì)數(shù)據(jù)的量級(jí)有一個(gè)評(píng)估,多少個(gè)樣本,多少個(gè)特征,可以估算出其對(duì)內(nèi)存的消耗程度,判斷訓(xùn)練過(guò)程中內(nèi)存是否能夠放得下。如果放不下就得考慮改進(jìn)算法或者使用一些降維的技巧了。如果數(shù)據(jù)量實(shí)在太大,那就要考慮分布式了。
5.3 特征預(yù)處理與特征選擇
良好的數(shù)據(jù)要能夠提取出良好的特征才能真正發(fā)揮效力。
特征預(yù)處理、數(shù)據(jù)清洗是很關(guān)鍵的步驟,往往能夠使得算法的效果和性能得到顯著提高。歸一化、離散化、因子化、缺失值處理、去除共線(xiàn)性等,數(shù)據(jù)挖掘過(guò)程中很多時(shí)間就花在它們上面。這些工作簡(jiǎn)單可復(fù)制,收益穩(wěn)定可預(yù)期,是機(jī)器學(xué)習(xí)的基礎(chǔ)必備步驟。
篩選出顯著特征、摒棄非顯著特征,需要機(jī)器學(xué)習(xí)工程師反復(fù)理解業(yè)務(wù)。這對(duì)很多結(jié)果有決定性的影響。特征選擇好了,非常簡(jiǎn)單的算法也能得出良好、穩(wěn)定的結(jié)果。這需要運(yùn)用特征有效性分析的相關(guān)技術(shù),如相關(guān)系數(shù)、卡方檢驗(yàn)、平均互信息、條件熵、后驗(yàn)概率、邏輯回歸權(quán)重等方法。
5.4:訓(xùn)練模型與調(diào)優(yōu)
直到這一步才用到我們上面說(shuō)的算法進(jìn)行訓(xùn)練。現(xiàn)在很多算法都能夠封裝成黑盒供人使用。但是真正考驗(yàn)水平的是調(diào)整這些算法的(超)參數(shù),使得結(jié)果變得更加優(yōu)良。這需要我們對(duì)算法的原理有深入的理解。理解越深入,就越能發(fā)現(xiàn)問(wèn)題的癥結(jié),提出良好的調(diào)優(yōu)方案。
5.5:模型診斷
如何確定模型調(diào)優(yōu)的方向與思路呢?這就需要對(duì)模型進(jìn)行診斷的技術(shù)。
過(guò)擬合、欠擬合判斷是模型診斷中至關(guān)重要的一步。常見(jiàn)的方法如交叉驗(yàn)證,繪制學(xué)習(xí)曲線(xiàn)等。過(guò)擬合的基本調(diào)優(yōu)思路是增加數(shù)據(jù)量,降低模型復(fù)雜度。欠擬合的基本調(diào)優(yōu)思路是提高特征數(shù)量和質(zhì)量,增加模型復(fù)雜度。
誤差分析 也是機(jī)器學(xué)習(xí)至關(guān)重要的步驟。通過(guò)觀(guān)察誤差樣本,全面分析誤差產(chǎn)生誤差的原因:是參數(shù)的問(wèn)題還是算法選擇的問(wèn)題,是特征的問(wèn)題還是數(shù)據(jù)本身的問(wèn)題……
診斷后的模型需要進(jìn)行調(diào)優(yōu),調(diào)優(yōu)后的新模型需要重新進(jìn)行診斷,這是一個(gè)反復(fù)迭代不斷逼近的過(guò)程,需要不斷地嘗試, 進(jìn)而達(dá)到最優(yōu)狀態(tài)。
5.6:模型融合
一般來(lái)說(shuō),模型融合后都能使得效果有一定提升。而且效果很好。
工程上,主要提升算法準(zhǔn)確度的方法是分別在模型的前端(特征清洗和預(yù)處理,不同的采樣模式)與后端(模型融合)上下功夫。因?yàn)樗麄儽容^標(biāo)準(zhǔn)可復(fù)制,效果比較穩(wěn)定。而直接調(diào)參的工作不會(huì)很多,畢竟大量數(shù)據(jù)訓(xùn)練起來(lái)太慢了,而且效果難以保證。
5.7:上線(xiàn)運(yùn)行
這一部分內(nèi)容主要跟工程實(shí)現(xiàn)的相關(guān)性比較大。工程上是結(jié)果導(dǎo)向,模型在線(xiàn)上運(yùn)行的效果直接決定模型的成敗。 不單純包括其準(zhǔn)確程度、誤差等情況,還包括其運(yùn)行的速度(時(shí)間復(fù)雜度)、資源消耗程度(空間復(fù)雜度)、穩(wěn)定性是否可接受。
這些工作流程主要是工程實(shí)踐上總結(jié)出的一些經(jīng)驗(yàn)。并不是每個(gè)項(xiàng)目都包含完整的一個(gè)流程。這里的部分只是一個(gè)指導(dǎo)性的說(shuō)明,只有大家自己多實(shí)踐,多積累項(xiàng)目經(jīng)驗(yàn),才會(huì)有自己更深刻的認(rèn)識(shí)。
6,全連接神經(jīng)網(wǎng)絡(luò)網(wǎng)絡(luò)結(jié)構(gòu)
(此題參考:https://blog.csdn.net/cuiyuan605/article/details/84307323)
神經(jīng)網(wǎng)絡(luò)算法,是使用計(jì)算機(jī)模擬生物神經(jīng)系統(tǒng),來(lái)模擬人類(lèi)思維方式的算法。它的基本單位就是人工神經(jīng)元。通過(guò)相互連接形成一張神經(jīng)網(wǎng)絡(luò)。對(duì)于神經(jīng)網(wǎng)絡(luò)有些了解的盆友可能都知道,神經(jīng)網(wǎng)絡(luò)其實(shí)就是一個(gè)輸入 X(向量) 到輸出 Y(向量)的映射函數(shù):f(x) = Y,函數(shù)的系數(shù)就是我們所要訓(xùn)練的網(wǎng)絡(luò)參數(shù) W,只要函數(shù)系數(shù)確定下來(lái),對(duì)于任何輸入xi,我們就能得到一個(gè)與之對(duì)應(yīng)的輸出 yi,至于 yi 是否符合我們的預(yù)期,這就是輸入如何提高模型性能方面的問(wèn)題。
?
? 生物神經(jīng)網(wǎng)絡(luò)中,每個(gè)神經(jīng)元與其他神經(jīng)元連接,當(dāng)它“激活”時(shí),會(huì)傳遞化學(xué)物質(zhì)到相連的神經(jīng)元,改變其他神經(jīng)元的電位,當(dāng)電位達(dá)到一定“閾值”,那么這個(gè)神經(jīng)元也會(huì)被激活。
單個(gè)人工神經(jīng)元的計(jì)算公式如下:
其中:
?為輸入?yún)?shù)向量,表示其他神經(jīng)元輸入的信號(hào)。
為每個(gè)輸入?yún)?shù)的權(quán)重值,表示對(duì)應(yīng)神經(jīng)元信號(hào)的權(quán)重。
theta 為閾值或者偏差值,是指該激活神經(jīng)元的難易程度。
y 為神經(jīng)元的輸出值,表示該神經(jīng)元是否被激活。
Act() 為激活函數(shù),理想的激活函數(shù)如下圖(a)中的躍階函數(shù),“1” 為神經(jīng)元興奮,“0”為神經(jīng)元抑制,但由于躍階函數(shù)具有不是連續(xù)可導(dǎo)等不好的性質(zhì),因此一般采用下面(b) 圖的 Sigmoid 函數(shù)作為激活函數(shù):
下面定義一個(gè)全連接神經(jīng)網(wǎng)絡(luò):
全連接神經(jīng)網(wǎng)絡(luò),就是指每一層的每個(gè)神經(jīng)元都和下一層的每個(gè)神經(jīng)元項(xiàng)連接。
Layer:0 為輸入層
Layer:L 為輸出層
其他L-1 個(gè)Layer 為隱層
輸入 x ?:
,我們稱(chēng)一個(gè)輸入值 x 為一個(gè)樣本
輸出 y ?:
,變量的上標(biāo)(L)表示該變量出于神經(jīng)網(wǎng)絡(luò)的那一層。
?表示第 L 層編號(hào)為 i 的神經(jīng)元
?表示第 L 層的神經(jīng)元數(shù)量
?
?7,全連接神經(jīng)網(wǎng)絡(luò)的前向傳播
前向傳播比較簡(jiǎn)單,就是向量點(diǎn)乘,也就是加權(quán)求和,然后經(jīng)過(guò)一個(gè)激活函數(shù)。也就是網(wǎng)絡(luò)如何根據(jù)輸入 X 得到輸出 Y的。
記
?為第 l-1 層第 k個(gè)神經(jīng)元到第 l 層第 j 個(gè)神經(jīng)元的權(quán)重,
?為第 l 層 第 j 個(gè)神經(jīng)元的偏置,
為第 l 層第 j 個(gè)神經(jīng)元的激活值(激活函數(shù)的輸出)。不難看出
?的值取決于上一層神經(jīng)元的激活:
將上面重寫(xiě)為矩陣形式:
為了方便表示,記?
?為每一層權(quán)重輸入,矩陣形式則變?yōu)?
利用矩陣形式可以一層層計(jì)算網(wǎng)絡(luò)的激活值,最終能根據(jù)輸入X 得到相應(yīng)的輸出?
。
8,隨機(jī)梯度下降法
(此題參考:https://blog.csdn.net/qq_38150441/article/details/80533891 和 https://blog.csdn.net/qq_39037383/article/details/89156894)
梯度下降算法的思想就是根據(jù)人類(lèi)在漸進(jìn)學(xué)習(xí)中,不斷從錯(cuò)誤中糾正自己的認(rèn)知的過(guò)程中感觸到的。
8.1 梯度下降
簡(jiǎn)單來(lái)說(shuō),梯度下降就是從山頂找一條最短的路走到山底最低的地方。但是因?yàn)檫x擇方向的原因,我們找到的最低點(diǎn)可能不是真正的最低點(diǎn)。如圖所示,黑色標(biāo)注的路線(xiàn)所指的方向并不是真正的地方。(因?yàn)樘荻认陆凳且环N思想,沒(méi)有嚴(yán)格的定義,所以用一個(gè)比喻來(lái)解釋什么是梯度下降)
既然是選擇一個(gè)方向下山,那么這個(gè)方向該如何選?每次該怎么走?
先說(shuō)選的方向,在算法中是以隨機(jī)方式給出的,這也是造成有時(shí)候走不到真正最低點(diǎn)的原因。如果選定了方向,以后每走一步,都選擇的時(shí)最陡的方向,直到最低點(diǎn)。總結(jié)起來(lái)就是:隨機(jī)選擇一個(gè)方向,然后每次都選擇最陡的方向,直到這個(gè)方向上能達(dá)到的最低點(diǎn)。
在機(jī)器學(xué)習(xí)算法中,有時(shí)候需要對(duì)原始的模型構(gòu)建損失函數(shù),然后通過(guò)優(yōu)化算法對(duì)損失函數(shù)進(jìn)行優(yōu)化,以便尋找到最優(yōu)的參數(shù),使得損失函數(shù)的值最小。而求解機(jī)器學(xué)習(xí)參數(shù)的優(yōu)化算法中,使用最多的就是基于梯度下降的優(yōu)化算法(Gradient Descent GD)。
梯度下降的優(yōu)缺點(diǎn) :
- 優(yōu)點(diǎn):效率。在梯度下降法的求解過(guò)程中,只需求解損失函數(shù)的一階導(dǎo)數(shù),計(jì)算的代價(jià)比較小,可以在很多大規(guī)模數(shù)據(jù)集上應(yīng)用。
- 缺點(diǎn):求解的時(shí)局部最優(yōu)值,即由于方向選擇的問(wèn)題,得到的結(jié)果不一定是全局最優(yōu)步長(zhǎng)選擇,過(guò)小使得函數(shù)收斂速度慢,過(guò)大又容易找不到最優(yōu)解。
8.2 隨機(jī)梯度下降
隨機(jī)梯度下降(SGD)是一種簡(jiǎn)單但非常有效地方法,多用于支持向量機(jī),邏輯回歸等凸損失函數(shù)下的線(xiàn)性分類(lèi)器的學(xué)習(xí)。并且SGD已經(jīng)成功應(yīng)用于文本分類(lèi)和自然語(yǔ)言處理中經(jīng)常遇到的大規(guī)模和稀疏機(jī)器學(xué)習(xí)問(wèn)題。SGD 既可以用于分類(lèi)計(jì)算,也可以用于回歸計(jì)算。
隨機(jī)梯度下降法不是對(duì)每個(gè)樣本集進(jìn)行求梯度更新參數(shù),而是對(duì)一個(gè)或者多個(gè)樣本進(jìn)行求梯度,更新參數(shù),采集多個(gè)樣本為樣本集再進(jìn)行如下操作:
1.初始化參數(shù)為任意值(可以取到面上任意一點(diǎn)) 2.對(duì)樣本集里每個(gè)樣本進(jìn)行遍歷如下操作 1.求解梯度值 2.更新參數(shù) 3.若達(dá)到指定迭代次數(shù)或者收斂條件,則訓(xùn)練結(jié)束
隨機(jī)梯度下降法不同于批量梯度下降,隨機(jī)梯度下降是每次迭代使用一個(gè)樣本來(lái)對(duì)參數(shù)進(jìn)行更新。使得訓(xùn)練速度加快。
對(duì)于一個(gè)樣本的目標(biāo)函數(shù)為:
對(duì)目標(biāo)函數(shù)求偏導(dǎo):
參數(shù)更新:
? 隨機(jī)梯度下降的優(yōu)缺點(diǎn):
- 優(yōu)點(diǎn):由于不是在全部訓(xùn)練數(shù)據(jù)上的損失函數(shù),而是在每輪迭代中,隨機(jī)優(yōu)化某一條訓(xùn)練數(shù)據(jù)上損失函數(shù),這樣每一輪參數(shù)的更新速度大大加快。
- 缺點(diǎn):準(zhǔn)確度下降,由于即使在目標(biāo)函數(shù)為強(qiáng)凸函數(shù)的情況下,SGD仍舊無(wú)法做到線(xiàn)性收斂。可能會(huì)收斂到局部最優(yōu),而單個(gè)樣本并不能代表全體樣本的趨勢(shì),而且不易于并行實(shí)現(xiàn)。
9,LR的原理和Loss的推導(dǎo)
首先,LR是一個(gè)分類(lèi)模型,討論二分類(lèi)情況下,在這個(gè)基礎(chǔ)上我們假設(shè)樣本服從伯努利分布(0~1)分布。做了假設(shè)分布后下一步就是求分布參數(shù),這個(gè)過(guò)程一般采用極大似然估計(jì)MLE(Maximum Likelihood Estimation),具體的方法就是求該假設(shè)分布在訓(xùn)練樣本上的聯(lián)合概率(樣本帶入連乘),然后求其關(guān)于 theta 的最大值,為了方便計(jì)算所以一般取 -log,單調(diào)性保持不變,所有就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
?10,機(jī)器學(xué)習(xí)中,為何要經(jīng)常對(duì)數(shù)據(jù)做歸一化
(參考文獻(xiàn):https://blog.csdn.net/abc_138/article/details/82798674)
一般做機(jī)器學(xué)習(xí)應(yīng)用的時(shí)候大部分時(shí)間是花費(fèi)在特征處理上,其中很關(guān)鍵的一步就是對(duì)特征數(shù)據(jù)進(jìn)行歸一化。
首先要明白歸一化的目的是什么,其目的是為了避免數(shù)值較大的特征A變化掩蓋了數(shù)值較小的特征B變化,最終希望讓特征AB都能對(duì)結(jié)果有影響。
那么為什么要做歸一化呢?
維基百科給出的解釋?zhuān)?,歸一化后加快了梯度下降求最優(yōu)解的速度。2,歸一化有可能提高精度。
解釋?zhuān)簹w一化為什么能提高梯度下降法求解最優(yōu)解的速度?
如下圖所示(來(lái)自:斯坦福機(jī)器學(xué)習(xí)視頻)
?
? 藍(lán)色的圈圈圖代表的是兩個(gè)特征的等高線(xiàn)。其中左圖兩個(gè)特征 X1和 X2的區(qū)間差別非常大,X1區(qū)間為[0, 2000] ,x2區(qū)間是 [1, 5],像這種有的數(shù)據(jù)那么大,有的數(shù)據(jù)那么小,兩類(lèi)之間的幅度相差這么大,其所形成的等高線(xiàn)非常尖。當(dāng)使用梯度下降法尋求最優(yōu)解時(shí),很有可能走“之字型”路線(xiàn)(垂直等高線(xiàn)走),從而導(dǎo)致需要迭代很多次才能收斂。而右圖對(duì)兩個(gè)原始特征進(jìn)行了歸一化,其對(duì)應(yīng)的等高線(xiàn)顯得很圓,在梯度下降進(jìn)行求解時(shí)能較快的收斂,因此如果機(jī)器學(xué)習(xí)模型使用梯度下降法求最優(yōu)解時(shí),歸一化往往非常有必要,否則很難收斂,甚至不能收斂。
解釋?zhuān)簹w一化有可能提高精度
一些分類(lèi)器需要計(jì)算樣本之間的距離(如歐式距離),例如KNN。如果一個(gè)特征值域范圍非常大,那么距離計(jì)算就主要取決于這個(gè)特征,從而與實(shí)際情況相悖(比如這時(shí)實(shí)際情況是值域范圍小的特征更重要)。
歸一化的類(lèi)型
1,線(xiàn)性歸一化
這種歸一化方法比較適用于在數(shù)值比較集中的情況。這種方法有個(gè)缺陷,如果max和min 不穩(wěn)定,很容易使得歸一化結(jié)果不穩(wěn)定,使得后續(xù)使用效果也不穩(wěn)定。實(shí)際使用中可以用經(jīng)驗(yàn)常量值來(lái)替代 max和 min。
2,標(biāo)準(zhǔn)差標(biāo)準(zhǔn)化
經(jīng)過(guò)處理的數(shù)據(jù)符合標(biāo)準(zhǔn)正態(tài)分布,即均值為0,標(biāo)準(zhǔn)差為1。
3,非線(xiàn)性歸一化
經(jīng)常用在數(shù)據(jù)分化比較大的場(chǎng)景,有些數(shù)值很大,有些很小。通過(guò)一些數(shù)學(xué)函數(shù),將原始值進(jìn)行映射。該方法包括 log、指數(shù),正切等。需要根據(jù)數(shù)據(jù)分布的情況,決定非線(xiàn)性函數(shù)的曲線(xiàn),比如log(V, 2)還是log(V, 10)等。
11,batch
深度學(xué)習(xí)中頻繁出現(xiàn)batch這個(gè)詞語(yǔ),所以我們有必要了解一下。
深度學(xué)習(xí)中 的優(yōu)化算法,說(shuō)白了就是梯度下降。每次的參數(shù)更新有兩種方式。
第一種,遍歷全部數(shù)據(jù)集算一次損失函數(shù),然后算函數(shù)對(duì)各個(gè)參數(shù)的梯度,更新梯度。這張方式每更新一次參數(shù)都要把數(shù)據(jù)集里的所有樣本都看一遍,計(jì)算量開(kāi)銷(xiāo)大,計(jì)算速度慢,不支持在線(xiàn)學(xué)習(xí),這稱(chēng)為 Batch gradient descent,批梯度下降。
另一種,每看一個(gè)數(shù)據(jù)就算一下?lián)p失函數(shù),然后求梯度更新參數(shù),這個(gè)稱(chēng)為隨機(jī)梯度下降, stochastic gradient ?descent。這個(gè)方法速度比較快,但是收斂性能不太好,可能在最優(yōu)點(diǎn)附近晃來(lái)晃去, hit 不到最優(yōu)點(diǎn)。兩次參數(shù)的更新也有可能互相抵消掉,造成目標(biāo)函數(shù)震蕩的比較劇烈。
為了克服兩種方法的缺點(diǎn),現(xiàn)在一般采用的時(shí)一種折中手段,mini-batch gradient decent,小批的梯度下降,這種方法把數(shù)據(jù)分為若干個(gè)批,按批來(lái)更新參數(shù)。這樣一個(gè)批中的一組數(shù)據(jù)共同決定了本次梯度的方向,下降起來(lái)就不容易跑偏,減少了隨機(jī)性。另外一方面因?yàn)榕蔚臉颖緮?shù)與整個(gè)數(shù)據(jù)集相比少了很多,計(jì)算量也不是很大。
基本上現(xiàn)在的梯度下降都是基于 mini-batch的,所以Keras的模塊中經(jīng)常會(huì)出現(xiàn) batch_size,就是指這個(gè)。
12,關(guān)于機(jī)器學(xué)習(xí)擬合問(wèn)題
12.1 什么是機(jī)器學(xué)習(xí)過(guò)擬合?
所謂過(guò)擬合,就是指模型在訓(xùn)練集上的效果很好,在測(cè)試集上的預(yù)測(cè)效果很差。
12.2 如何避免過(guò)擬合問(wèn)題?
1,重采樣Bootstrap?
2,L1,L2 正則化
3,決策樹(shù)的剪枝操作
4,交叉驗(yàn)證
12.3 什么是機(jī)器學(xué)習(xí)的欠擬合?
所謂欠擬合就是模型復(fù)雜度低或者數(shù)據(jù)集太小,對(duì)模型數(shù)據(jù)的擬合程度不高,因此模型在訓(xùn)練集上的效果就不好。
12.3 如何避免欠擬合問(wèn)題?
1,增加樣本數(shù)量
2,增加樣本特征的數(shù)量
3,可以進(jìn)行特征維度擴(kuò)展
12.4 ?算法的誤差一般是由那幾個(gè)方面引起的?
1,因模型無(wú)法表達(dá)基本數(shù)據(jù)的復(fù)雜度而造成的偏差(bias)——欠擬合
2,因模型過(guò)度擬合訓(xùn)練集數(shù)據(jù)而造成的方差(variance)——過(guò)擬合
13,為什么樸素貝葉斯如此“樸素”?
貝葉斯算法簡(jiǎn)單高效,在處理分類(lèi)問(wèn)題上,是首先要考慮的方法之一。
貝葉斯分類(lèi)是一類(lèi)分類(lèi)算法的總稱(chēng),這類(lèi)算法均以貝葉斯定理為基礎(chǔ),故統(tǒng)稱(chēng)為貝葉斯分類(lèi)。公式如下:
? 該公式最大的優(yōu)點(diǎn)就是可以忽略AB 的聯(lián)合概率直接求其條件概率分布。
而樸素貝葉斯為什么如此樸素,因?yàn)樗俣ㄋ械奶卣髟跀?shù)據(jù)集中的作用是同樣重要和獨(dú)立的。正如我們所知,這個(gè)假設(shè)在現(xiàn)實(shí)世界中是很不真實(shí)的,因此說(shuō)樸素貝葉斯真的很“樸素”。
樸素貝葉斯分類(lèi)是一種非常簡(jiǎn)單的分類(lèi)算法,其思想是樸素的。即:對(duì)于給出的待分類(lèi)項(xiàng),求解在此項(xiàng)出現(xiàn)的條件下各個(gè)類(lèi)別出現(xiàn)的概率,那個(gè)最大,就認(rèn)為此待分類(lèi)項(xiàng)屬于那個(gè)類(lèi)別。
理論上,樸素貝葉斯模型與其他分類(lèi)方法相比具有最小的誤差率。但是實(shí)際上并非總是如此,這是因?yàn)闃闼刎惾~斯模型給定輸出類(lèi)別的情況下,假設(shè)屬性之間相互獨(dú)立,這個(gè)假設(shè)在實(shí)際應(yīng)用中往往是不成立的,在屬性個(gè)數(shù)比較多或者屬性之間相關(guān)性較大時(shí),分類(lèi)效果不好。而在屬性相關(guān)性較小的時(shí),樸素貝葉斯性能最為良好。對(duì)于這一點(diǎn),有半樸素貝葉斯之類(lèi)的算法通過(guò)考慮部分關(guān)聯(lián)性適度改進(jìn)。
?
14,反向傳播算法(BP算法)的推導(dǎo)及其Python實(shí)現(xiàn)
下面學(xué)習(xí)如何調(diào)整一個(gè)神經(jīng)網(wǎng)絡(luò)的參數(shù),也就是誤差反向傳播算法(BP算法)。以得到一個(gè)能夠根據(jù)輸入,預(yù)測(cè)正確輸出的模型。
14.1,首先我們要了解優(yōu)化的目標(biāo)
根據(jù)人工神經(jīng)元的定義,有以下三個(gè)公式:
其中,Act() 是激活函數(shù),之前學(xué)習(xí)過(guò)。
根據(jù)上面兩個(gè)公式,可以得出各個(gè)神經(jīng)元之間的通用公式,如下:
其中上式是人工神經(jīng)網(wǎng)絡(luò)正向傳播的核心公式。
那么,我們根據(jù)什么來(lái)調(diào)整神經(jīng)網(wǎng)絡(luò)的參數(shù),以得到一個(gè)能夠正確預(yù)測(cè)結(jié)果的模型呢?請(qǐng)看下面的公式:
上式用來(lái)計(jì)算我們期望的輸出和實(shí)際輸出的“差別”,其中cost() 叫做損失函數(shù)。我們的期望是損失函數(shù)值達(dá)到最小。
但是只根據(jù)一次輸出的損失值,對(duì)參數(shù)進(jìn)行調(diào)整,無(wú)法使模型適應(yīng)所有輸入樣本。我們需要的是,調(diào)整參數(shù),使得所有輸入樣本,得到輸出的總損失值最小,而不是只讓妻子一個(gè)樣本的損失值最小,導(dǎo)致其他樣本損失值增大。因此有下面公式:
上式表示一個(gè) batch 的所有樣本輸出的總損失值的平均值。其中,bn 表示一個(gè) batch中樣本的數(shù)量。
為什么不用所有的樣本計(jì)算損失值,而將所有樣本分成一個(gè)個(gè)的 batch呢?因?yàn)樗械挠?xùn)練樣本數(shù)量太大了,可能有數(shù)以百萬(wàn)計(jì),將所有的樣本損失值都一起進(jìn)行運(yùn)算,計(jì)算量過(guò)于龐大,大大降低了模型計(jì)算的速度。
而計(jì)算總的損失值 C,其中是一個(gè)以所有的連接權(quán)重 W 和 所有的閾值 theta 未為變量的多元函數(shù)。我們想要的模型就是求得 C 最小時(shí),所有 W 和 theta 的值。直接計(jì)算顯然是不可能的,因?yàn)閷?duì)于一個(gè)大的深度神經(jīng)網(wǎng)絡(luò),所有的參數(shù)變量,可能數(shù)以萬(wàn)計(jì)。
在這里我們使用梯度下降算法來(lái)逐步逼近 C的最小值,也即是先隨機(jī)得到一組參數(shù)變量的值,然后計(jì)算參數(shù)變量當(dāng)前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調(diào)整參數(shù)值,最終得到 C 的最小值,或者近似最小值。
而將所有樣本,隨機(jī)分成一個(gè)個(gè)固定長(zhǎng)度的 batch,以得到近似的梯度方向,叫做隨機(jī)梯度下降算法。
14.2 開(kāi)始求梯度
? 那么根據(jù)梯度的定義,接下來(lái)的任務(wù),就是求取各個(gè)參數(shù)變量相對(duì)于 C 的偏導(dǎo)數(shù)。我們將使用誤差反向傳播算法來(lái)求取各個(gè)參數(shù)變量的偏導(dǎo)數(shù)。
求取偏導(dǎo)數(shù)的方法和神經(jīng)網(wǎng)絡(luò)正向傳播(根據(jù)樣本計(jì)算輸出值)的方式類(lèi)似,也是逐層求解,只是方向正好相反,從最后一層開(kāi)始,逐層向前。
首先,我們先求神經(jīng)網(wǎng)絡(luò)最后一層,也即是輸出層的相關(guān)參數(shù)的偏導(dǎo)數(shù)。為了降低推導(dǎo)的復(fù)雜性,我們只計(jì)算相對(duì)一個(gè)樣本的損失值函數(shù) Cbi 的偏導(dǎo)數(shù),因?yàn)橄鄬?duì)于總損失值函數(shù) C 的偏導(dǎo)數(shù)值,也不過(guò)是把某個(gè)參數(shù)的所有相對(duì)于 Cbi 偏導(dǎo)數(shù)值加起來(lái)而已。
根據(jù)上面公式,以及 復(fù)合函數(shù)求導(dǎo)法則,可以得到輸出層(L層)某個(gè)神經(jīng)元的權(quán)值參數(shù) W 的偏導(dǎo)數(shù),計(jì)算公式如下:
根據(jù)前面三個(gè)公式求導(dǎo)如下:
將這三個(gè)公式代入上面公式,可以得到:
我們令:
則:
將上式代入損失函數(shù)求導(dǎo)的公式中可以得到:
這樣我們就得到了輸出層 L 相關(guān)的權(quán)重參數(shù) W 的偏導(dǎo)數(shù)計(jì)算公式!
接下來(lái),同理可以求得輸出層 L 相關(guān)的閾值 theta 的偏導(dǎo)數(shù)計(jì)算公式為:
而根據(jù)第二個(gè)公式可以得到:
將上式代入到上上式可以得到:
這就是 輸出層 L 相關(guān)的閾值 theta 的偏導(dǎo)數(shù)計(jì)算公式!
14.3 根據(jù) L 層,求前一層參數(shù)的偏導(dǎo)函數(shù)
從下面公式,可知,一個(gè)權(quán)重參數(shù) W 只影響一個(gè) L-1 層的神經(jīng)元:
? 因此可以得到有下面公式:
將上式代入到上上式可以得到:
根據(jù)假設(shè):
我們可以得到:
將上式代入到上上式,可以得到:
同理,我們可以得到:
根據(jù)14.3 第一個(gè)公式可以得到:
將上式代入到上上式,可以得到:
這樣我們就得到了 L-1 層神經(jīng)元相關(guān)參數(shù)的計(jì)算公式。
下面我們還需要推導(dǎo)一下
?之間的關(guān)系,根據(jù)下面公式:
我們可以得到:
同理可得:
將上式代入到上上式,可以得:
我們知道,一個(gè)權(quán)重參數(shù) W 只影響一個(gè) L-1 層的神經(jīng)元,但這個(gè) L-1 層神經(jīng)元影響了所有 L層的神經(jīng)元。因此,根據(jù)多元復(fù)合函數(shù)求導(dǎo)法則。有:
根據(jù)我們之前的假設(shè),可以得到:
將上式代入到上上式,可以得到:
我們可以知道:
將上式代入到上上式,可以得到:
最后將上式代入之前的公式,可以得到:
這樣我們就得到了反向傳播,逐層推導(dǎo)的通用公式:
這里, W 和 Z 都是整箱傳播過(guò)程中已經(jīng)算好的常數(shù),而
?可以從 L層開(kāi)始逐層向前推導(dǎo),直到第1層,第0層是輸入層,不需要調(diào)整參數(shù),而第L層的參數(shù)可以參考下面公式:
?
? 下面是全連接神經(jīng)網(wǎng)絡(luò)的Python實(shí)現(xiàn)代碼:
#coding=utf-8 import numpy as np import matplotlib.pylab as plt import random class NeuralNetwork(object): def __init__(self, sizes, act, act_derivative, cost_derivative): #sizes表示神經(jīng)網(wǎng)絡(luò)各層的神經(jīng)元個(gè)數(shù),第一層為輸入層,最后一層為輸出層 #act為神經(jīng)元的激活函數(shù) #act_derivative為激活函數(shù)的導(dǎo)數(shù) #cost_derivative為損失函數(shù)的導(dǎo)數(shù) self.num_layers = len(sizes) self.sizes = sizes self.biases = [np.random.randn(nueron_num, 1) for nueron_num in sizes[1:]] self.weights = [np.random.randn(next_layer_nueron_num, nueron_num) for nueron_num, next_layer_nueron_num in zip(sizes[:-1], sizes[1:])] self.act=act self.act_derivative=act_derivative self.cost_derivative=cost_derivative #前向反饋(正向傳播) def feedforward(self, a): #逐層計(jì)算神經(jīng)元的激活值,公式(4) for b, w in zip(self.biases, self.weights): a = self.act(np.dot(w, a)+b) return a #隨機(jī)梯度下降算法 def SGD(self, training_data, epochs, batch_size, learning_rate): #將訓(xùn)練樣本training_data隨機(jī)分為若干個(gè)長(zhǎng)度為batch_size的batch #使用各個(gè)batch的數(shù)據(jù)不斷調(diào)整參數(shù),學(xué)習(xí)率為learning_rate #迭代epochs次 n = len(training_data) for j in range(epochs): random.shuffle(training_data) batches = [training_data[k:k+batch_size] for k in range(0, n, batch_size)] for batch in batches: self.update_batch(batch, learning_rate) print("Epoch {0} complete".format(j)) def update_batch(self, batch, learning_rate): #根據(jù)一個(gè)batch中的訓(xùn)練樣本,調(diào)整各個(gè)參數(shù)值 nabla_b = [np.zeros(b.shape) for b in self.biases] nabla_w = [np.zeros(w.shape) for w in self.weights] for x, y in batch: delta_nabla_b, delta_nabla_w = self.backprop(x, y) nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)] nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)] #計(jì)算梯度,并調(diào)整各個(gè)參數(shù)值 self.weights = [w-(learning_rate/len(batch))*nw for w, nw in zip(self.weights, nabla_w)] self.biases = [b-(learning_rate/len(batch))*nb for b, nb in zip(self.biases, nabla_b)] #反向傳播 def backprop(self, x, y): #保存b和w的偏導(dǎo)數(shù)值 nabla_b = [np.zeros(b.shape) for b in self.biases] nabla_w = [np.zeros(w.shape) for w in self.weights] #正向傳播 activation = x #保存每一層神經(jīng)元的激活值 activations = [x] #保存每一層神經(jīng)元的z值 zs = [] for b, w in zip(self.biases, self.weights): z = np.dot(w, activation)+b zs.append(z) activation = self.act(z) activations.append(activation) #反向傳播得到各個(gè)參數(shù)的偏導(dǎo)數(shù)值 #公式(13) d = self.cost_derivative(activations[-1], y) * self.act_derivative(zs[-1]) #公式(17) nabla_b[-1] = d #公式(14) nabla_w[-1] = np.dot(d, activations[-2].transpose()) #反向逐層計(jì)算 for l in range(2, self.num_layers): z = zs[-l] sp = self.act_derivative(z) #公式(36),反向逐層求參數(shù)偏導(dǎo) d = np.dot(self.weights[-l+1].transpose(), d) * sp #公式(38) nabla_b[-l] = d #公式(37) nabla_w[-l] = np.dot(d, activations[-l-1].transpose()) return (nabla_b, nabla_w) #距離函數(shù)的偏導(dǎo)數(shù) def distance_derivative(output_activations, y): #損失函數(shù)的偏導(dǎo)數(shù) return 2*(output_activations-y) # sigmoid函數(shù) def sigmoid(z): return 1.0/(1.0+np.exp(-z)) # sigmoid函數(shù)的導(dǎo)數(shù) def sigmoid_derivative(z): return sigmoid(z)*(1-sigmoid(z)) if __name__ == "__main__": #創(chuàng)建一個(gè)5層的全連接神經(jīng)網(wǎng)絡(luò),每層的神經(jīng)元個(gè)數(shù)為1,8,5,3,1 #其中第一層為輸入層,最后一層為輸出層 network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative) #訓(xùn)練集樣本 x = np.array([np.linspace(-7, 7, 200)]).T #訓(xùn)練集結(jié)果,由于使用了sigmoid作為激活函數(shù),需保證其結(jié)果落在(0,1)區(qū)間內(nèi) y = (np.cos(x)+1)/2 #使用隨機(jī)梯度下降算法(SGD)對(duì)模型進(jìn)行訓(xùn)練 #迭代5000次;每次隨機(jī)抽取40個(gè)樣本作為一個(gè)batch;學(xué)習(xí)率設(shè)為0.1 training_data=[(np.array([x_value]),np.array([y_value])) for x_value,y_value in zip(x,y)] network.SGD(training_data,5000,40,0.1) #測(cè)試集樣本 x_test = np.array([np.linspace(-9, 9, 120)]) #測(cè)試集結(jié)果 y_predict = network.feedforward(x_test) #圖示對(duì)比訓(xùn)練集和測(cè)試集數(shù)據(jù) plt.plot(x,y,'r',x_test.T,y_predict.T,'*') plt.show()
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
