感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.htmlhtml
1,什麼樣的資料集不適合用深度學習?前端
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!算法
softmax函數以下:後端
更形象的以下圖表示:網絡
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!app
Python代碼實現:dom
coding:utf-8
import tensorflow as tf機器學習
import numpy as np分佈式
import mathide
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.html
1,什麼樣的資料集不適合用深度學習?
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!
softmax函數以下:
更形象的以下圖表示:
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!
Python代碼實現:
coding:utf-8
import tensorflow as tf
import numpy as np
import math
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.html
1,什麼樣的資料集不適合用深度學習?
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!
softmax函數以下:
更形象的以下圖表示:
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!
Python代碼實現:
coding:utf-8
import tensorflow as tf
import numpy as np
import math
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.html
1,什麼樣的資料集不適合用深度學習?
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!
softmax函數以下:
更形象的以下圖表示:
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!
Python代碼實現:
coding:utf-8
import tensorflow as tf
import numpy as np
import math
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.html
1,什麼樣的資料集不適合用深度學習?
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!
softmax函數以下:
更形象的以下圖表示:
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!
Python代碼實現:
coding:utf-8
import tensorflow as tf
import numpy as np
import math
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.html
1,什麼樣的資料集不適合用深度學習?
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!
softmax函數以下:
更形象的以下圖表示:
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!
Python代碼實現:
coding:utf-8
import tensorflow as tf
import numpy as np
import math
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.html
1,什麼樣的資料集不適合用深度學習?
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!
softmax函數以下:
更形象的以下圖表示:
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!
Python代碼實現:
coding:utf-8
import tensorflow as tf
import numpy as np
import math
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.html
1,什麼樣的資料集不適合用深度學習?
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!
softmax函數以下:
更形象的以下圖表示:
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!
Python代碼實現:
coding:utf-8
import tensorflow as tf
import numpy as np
import math
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.html
1,什麼樣的資料集不適合用深度學習?
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!
softmax函數以下:
更形象的以下圖表示:
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!
Python代碼實現:
coding:utf-8
import tensorflow as tf
import numpy as np
import math
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()感謝做者分享-http://bjbsair.com/2020-04-07/tech-info/30748.html
1,什麼樣的資料集不適合用深度學習?
- 數據集過小,數據樣本不足時,深度學習相對其它機器學習算法,沒有明顯優點。
- **數據集沒有局部相關特性,**目前深度學習表現比較好的領域主要是圖像/語音/天然語言處理等領域,這些領域的一個共性是局部相關性。圖像中像素組成物體,語音信號中音位組合成單詞,文本數據中單詞組合成句子,這些特徵元素的組合一旦被打亂,表示的含義同時也被改變。對於沒有這樣的局部相關性的數據集,不適於使用深度學習算法進行處理。舉個例子:預測一我的的健康情況,相關的參數會有年齡、職業、收入、家庭情況等各類元素,將這些元素打亂,並不會影響相關的結果。
2,softmax函數的數學推導及Python實現
softmax用於多分類過程當中最後一層,將多個神經元的輸出,映射到(0, 1)區間內,能夠當作機率來理解,從而來進行多分類!
softmax函數以下:
更形象的以下圖表示:
softmax 直白來講就是講原來輸出是 3, 1, -3 經過 softmax 函數一做用,就映射成爲(0, 1)的值,而這些值的累和爲1,那麼咱們就能夠將其理解成機率,在最後選取輸出節點的時候,咱們能夠選取機率最大的節點,做爲咱們的預測目標!
Python代碼實現:
coding:utf-8
import tensorflow as tf
import numpy as np
import math
softmax函數,或稱歸一化指數函數
def softmax(x, axis=1):
爲了不求 exp(x) 出現溢出的狀況,通常須要減去最大值
計算每行的最大值
row_max = x.max(axis=axis)
每行元素都須要減去對應的最大值,不然求exp(x)會溢出,致使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
簡單一些
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函數
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))
'''
結果輸出以下:
[0.8360188 0.11314284 0.05083836]
[0.8360188 0.11314284 0.05083836]
'''
其實兩個結果輸出是同樣的,即便第一個實現了每列和最大值的差別,而後除以總和,可是問題來了,實如今代碼和時間複雜度方面是否類似?哪個更有效率?
固然,他們都是正確的,可是從數值穩定性的角度來看,第一個是正確的,由於咱們避免了求 exp(x) 出現溢出的狀況,這裏減去了最大值。咱們推導一下:
轉化公式: 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,歐氏距離和曼哈頓距離
歐氏距離(也稱爲歐幾里得度量),是應用勾股定理計算兩個點之間的直線距離,也就是指m維空間兩個點之間的真實距離,或者向量的天然長度(即該點到原點的距離)。
下面是歐式距離的公式(分別是二維空間,三維空間,n維空間):
曼哈頓距離表示的是兩個點在標準座標系上絕對軸距之和,是種使用在幾何度量空間的幾何學用語。
例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離爲:
d(i,j)=|X1-X2|+|Y1-Y2|
如圖所示,很直接明瞭的理解歐氏距離和曼哈頓距離:
圖中紅線表明曼哈頓距離,綠色表明歐氏距離,也就是直線距離,而藍色和黃色表明等價的曼哈頓距離。
歐氏距離和曼哈頓距離的Python實現:
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,什麼是數據埋點
數據埋點咱們能夠分爲兩類,其一是頁面統計,其二是行爲統計。
頁面統計能夠幫咱們知曉某個頁面被多少人訪問了多少次,行爲統計是指用戶在界面上的操做行爲,應用最多的是按鈕的點擊次數。
5,請簡要說說一個完整的機器學習項目流程
5.1:抽象成數學問題
明確問題是進行機器學習的第一步。機器學習的訓練過程一般都是一件很是耗時的事情,胡亂嘗試時間成本是很是高的。 這裏的抽象成數學問題,指的咱們明確咱們能夠得到什麼樣的數據,目標是一個分類仍是迴歸或者是聚類的問題,若是都不是的話,若是劃歸爲其中的某類問題。
5.2:獲取數據
數據決定了機器學習結果的上限,而算法只是儘量逼近這個上限。數據要有表明性,不然必然會過擬合。並且對於分類問題,數據偏斜不能過於嚴重,不一樣類別的數據數量不要有數個數量級的差距。
並且還要對數據的量級有一個評估,多少個樣本,多少個特徵,能夠估算出其對內存的消耗程度,判斷訓練過程當中內存是否可以放得下。若是放不下就得考慮改進算法或者使用一些降維的技巧了。若是數據量實在太大,那就要考慮分佈式了。
5.3 特徵預處理與特徵選擇
良好的數據要可以提取出良好的特徵才能真正發揮效力。
特徵預處理、數據清洗是很關鍵的步驟,每每可以使得算法的效果和性能獲得顯著提升。歸一化、離散化、因子化、缺失值處理、去除共線性等,數據挖掘過程當中不少時間就花在它們上面。這些工做簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。 篩選出顯著特徵、摒棄非顯著特徵,須要機器學習工程師反覆理解業務。這對不少結果有決定性的影響。特徵選擇好了,很是簡單的算法也能得出良好、穩定的結果。這須要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互信息、條件熵、後驗機率、邏輯迴歸權重等方法。
5.4:訓練模型與調優
直到這一步纔用到咱們上面說的算法進行訓練。如今不少算法都可以封裝成黑盒供人使用。可是真正考驗水平的是調整這些算法的(超)參數,使得結果變得更加優良。這須要咱們對算法的原理有深刻的理解。理解越深刻,就越能發現問題的癥結,提出良好的調優方案。
5.5:模型診斷
如何肯定模型調優的方向與思路呢?這就須要對模型進行診斷的技術。 過擬合、欠擬合判斷是模型診斷中相當重要的一步。常見的方法如交叉驗證,繪製學習曲線等。過擬合的基本調優思路是增長數據量,下降模型複雜度。欠擬合的基本調優思路是提升特徵數量和質量,增長模型複雜度。 偏差分析 也是機器學習相當重要的步驟。經過觀察偏差樣本,全面分析偏差產生偏差的緣由:是參數的問題仍是算法選擇的問題,是特徵的問題仍是數據自己的問題…… 診斷後的模型須要進行調優,調優後的新模型須要從新進行診斷,這是一個反覆迭代不斷逼近的過程,須要不斷地嘗試, 進而達到最優狀態。
5.6:模型融合
通常來講,模型融合後都能使得效果有必定提高。並且效果很好。 工程上,主要提高算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不一樣的採樣模式)與後端(模型融合)上下功夫。由於他們比較標準可複製,效果比較穩定。而直接調參的工做不會不少,畢竟大量數據訓練起來太慢了,並且效果難以保證。
5.7:上線運行
這一部份內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上運行的效果直接決定模型的成敗。 不單純包括其準確程度、偏差等狀況,還包括其運行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。 這些工做流程主要是工程實踐上總結出的一些經驗。並非每一個項目都包含完整的一個流程。這裏的部分只是一個指導性的說明,只有你們本身多實踐,多積累項目經驗,纔會有本身更深入的認識。
6,全鏈接神經網絡網絡結構
神經網絡算法,是使用計算機模擬生物神經系統,來模擬人類思惟方式的算法。它的基本單位就是人工神經元。經過相互鏈接造成一張神經網絡。對於神經網絡有些瞭解的盆友可能都知道,神經網絡其實就是一個輸入 X(向量) 到輸出 Y(向量)的映射函數:f(x) = Y,函數的係數就是咱們所要訓練的網絡參數 W,只要函數係數肯定下來,對於任何輸入xi,咱們就能獲得一個與之對應的輸出 yi,至於 yi 是否符合咱們的預期,這就是輸入如何提升模型性能方面的問題。
生物神經網絡中,每一個神經元與其餘神經元鏈接,當它「激活」時,會傳遞化學物質到相連的神經元,改變其餘神經元的電位,當電位達到必定「閾值」,那麼這個神經元也會被激活。
單我的工神經元的計算公式以下:
其中:
爲輸入參數向量,表示其餘神經元輸入的信號。
爲每一個輸入參數的權重值,表示對應神經元信號的權重。
theta 爲閾值或者誤差值,是指該激活神經元的難易程度。
y 爲神經元的輸出值,表示該神經元是否被激活。
Act() 爲激活函數,理想的激活函數以下圖(a)中的躍階函數,「1」 爲神經元興奮,「0」爲神經元抑制,但因爲躍階函數具備不是連續可導等很差的性質,所以通常採用下面(b) 圖的 Sigmoid 函數做爲激活函數:
下面定義一個全鏈接神經網絡:
全鏈接神經網絡,就是指每一層的每一個神經元都和下一層的每一個神經元項鍊接。
Layer:0 爲輸入層
Layer:L 爲輸出層
其餘L-1 個Layer 爲隱層
輸入 x :
,咱們稱一個輸入值 x 爲一個樣本
輸出 y :
,變量的上標(L)表示該變量出於神經網絡的那一層。
表示第 L 層編號爲 i 的神經元
表示第 L 層的神經元數量
7,全鏈接神經網絡的前向傳播
前向傳播比較簡單,就是向量點乘,也就是加權求和,而後通過一個激活函數。也就是網絡如何根據輸入 X 獲得輸出 Y的。
記
爲第 l-1 層第 k個神經元到第 l 層第 j 個神經元的權重,
爲第 l 層 第 j 個神經元的偏置,
爲第 l 層第 j 個神經元的激活值(激活函數的輸出)。不難看出
的值取決於上一層神經元的激活:
將上面重寫爲矩陣形式:
爲了方便表示,記
爲每一層權重輸入,矩陣形式則變爲
利用矩陣形式能夠一層層計算網絡的激活值,最終能根據輸入X 獲得相應的輸出
。
8,隨機梯度降低法
梯度降低算法的思想就是根據人類在漸進學習中,不斷從錯誤中糾正本身的認知的過程當中感觸到的。
8.1 梯度降低
簡單來講,梯度降低就是從山頂找一條最短的路走到山底最低的地方。可是由於選擇方向的緣由,咱們找到的最低點可能不是真正的最低點。如圖所示,黑色標註的路線所指的方向並非真正的地方。(由於梯度降低是一種思想,沒有嚴格的定義,因此用一個比喻來解釋什麼是梯度降低)
既然是選擇一個方向下山,那麼這個方向該如何選?每次該怎麼走?
先說選的方向,在算法中是以隨機方式給出的,這也是形成有時候走不到真正最低點的緣由。若是選定了方向,之後每走一步,都選擇的時最陡的方向,直到最低點。總結起來就是:隨機選擇一個方向,而後每次都選擇最陡的方向,直到這個方向上能達到的最低點。
在機器學習算法中,有時候須要對原始的模型構建損失函數,而後經過優化算法對損失函數進行優化,以便尋找到最優的參數,使得損失函數的值最小。而求解機器學習參數的優化算法中,使用最多的就是基於梯度降低的優化算法(Gradient Descent GD)。
梯度降低的優缺點:
- 優勢:效率。在梯度降低法的求解過程當中,只需求解損失函數的一階導數,計算的代價比較小,能夠在不少大規模數據集上應用。
- 缺點:求解的時局部最優值,即因爲方向選擇的問題,獲得的結果不必定是全局最優步長選擇,太小使得函數收斂速度慢,過大又容易找不到最優解。
8.2 隨機梯度降低
隨機梯度降低(SGD)是一種簡單但很是有效地方法,多用於支持向量機,邏輯迴歸等凸損失函數下的線性分類器的學習。而且SGD已經成功應用於文本分類和天然語言處理中常常遇到的大規模和稀疏機器學習問題。SGD 既能夠用於分類計算,也能夠用於迴歸計算。
隨機梯度降低法不是對每一個樣本集進行求梯度更新參數,而是對一個或者多個樣本進行求梯度,更新參數,採集多個樣本爲樣本集再進行以下操做:
1.初始化參數爲任意值(能夠取到面上任意一點)
2.對樣本集裏每一個樣本進行遍歷以下操做
1.求解梯度值
2.更新參數
3.若達到指定迭代次數或者收斂條件,則訓練結束
隨機梯度降低法不一樣於批量梯度降低,隨機梯度降低是每次迭代使用一個樣原本對參數進行更新。使得訓練速度加快。
對於一個樣本的目標函數爲:
對目標函數求偏導:
參數更新:
隨機梯度降低的優缺點:
- 優勢:因爲不是在所有訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上損失函數,這樣每一輪參數的更新速度大大加快。
- 缺點:準確度降低,因爲即便在目標函數爲強凸函數的狀況下,SGD仍舊沒法作到線性收斂。可能會收斂到局部最優,而單個樣本並不能表明全體樣本的趨勢,並且不易於並行實現。
9,LR的原理和Loss的推導
首先,LR是一個分類模型,討論二分類狀況下,在這個基礎上咱們假設樣本服從伯努利分佈(0~1)分佈。作了假設分佈後下一步就是求分佈參數,這個過程通常採用極大似然估計MLE(Maximum Likelihood Estimation),具體的方法就是求該假設分佈在訓練樣本上的聯合機率(樣本帶入連乘),而後求其關於 theta 的最大值,爲了方便計算因此通常取 -log,單調性保持不變,全部就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。
10,機器學習中,爲什麼要常常對數據作歸一化
通常作機器學習應用的時候大部分時間是花費在特徵處理上,其中很關鍵的一步就是對特徵數據進行歸一化。
首先要明白歸一化的目的是什麼,其目的是爲了不數值較大的特徵A變化掩蓋了數值較小的特徵B變化,最終但願讓特徵AB都能對結果有影響。
那麼爲何要作歸一化呢?
維基百科給出的解釋:1,歸一化後加快了梯度降低求最優解的速度。2,歸一化有可能提升精度。
解釋:歸一化爲何能提升梯度降低法求解最優解的速度?
以下圖所示(來自:斯坦福機器學習視頻)
藍色的圈圈圖表明的是兩個特徵的等高線。其中左圖兩個特徵 X1和 X2的區間差異很是大,X1區間爲[0, 2000] ,x2區間是 [1, 5],像這種有的數據那麼大,有的數據那麼小,兩類之間的幅度相差這麼大,其所造成的等高線很是尖。當使用梯度降低法尋求最優解時,頗有可能走「之字型」路線(垂直等高線走),從而致使須要迭代不少次才能收斂。而右圖對兩個原始特徵進行了歸一化,其對應的等高線顯得很圓,在梯度降低進行求解時能較快的收斂,所以若是機器學習模型使用梯度降低法求最優解時,歸一化每每很是有必要,不然很難收斂,甚至不能收斂。
解釋:歸一化有可能提升精度
一些分類器須要計算樣本之間的距離(如歐式距離),例如KNN。若是一個特徵值域範圍很是大,那麼距離計算就主要取決於這個特徵,從而與實際狀況相悖(好比這時實際狀況是值域範圍小的特徵更重要)。
歸一化的類型
1,線性歸一化
這種歸一化方法比較適用於在數值比較集中的狀況。這種方法有個缺陷,若是max和min 不穩定,很容易使得歸一化結果不穩定,使得後續使用效果也不穩定。實際使用中能夠用經驗常量值來替代 max和 min。
2,標準差標準化
通過處理的數據符合標準正態分佈,即均值爲0,標準差爲1。
3,非線性歸一化
常常用在數據分化比較大的場景,有些數值很大,有些很小。經過一些數學函數,將原始值進行映射。該方法包括 log、指數,正切等。須要根據數據分佈的狀況,決定非線性函數的曲線,好比log(V, 2)仍是log(V, 10)等。
11,batch
深度學習中頻繁出現batch這個詞語,因此咱們有必要了解一下。
深度學習中 的優化算法,說白了就是梯度降低。每次的參數更新有兩種方式。
第一種,遍歷所有數據集算一次損失函數,而後算函數對各個參數的梯度,更新梯度。這張方式每更新一次參數都要把數據集裏的全部樣本都看一遍,計算量開銷大,計算速度慢,不支持在線學習,這稱爲 Batch gradient descent,批梯度降低。
另外一種,每看一個數據就算一下損失函數,而後求梯度更新參數,這個稱爲隨機梯度降低, stochastic gradient descent。這個方法速度比較快,可是收斂性能不太好,可能在最優勢附近晃來晃去, hit 不到最優勢。兩次參數的更新也有可能互相抵消掉,形成目標函數震盪的比較劇烈。
爲了克服兩種方法的缺點,如今通常採用的時一種折中手段,mini-batch gradient decent,小批的梯度降低,這種方法把數據分爲若干個批,按批來更新參數。這樣一個批中的一組數據共同決定了本次梯度的方向,降低起來就不容易跑偏,減小了隨機性。另一方面由於批次的樣本數與整個數據集相比少了不少,計算量也不是很大。
基本上如今的梯度降低都是基於 mini-batch的,因此Keras的模塊中常常會出現 batch_size,就是指這個。
12,關於機器學習擬合問題
12.1 什麼是機器學習過擬合?
所謂過擬合,就是指模型在訓練集上的效果很好,在測試集上的預測效果不好。
12.2 如何避免過擬合問題?
1,重採樣Bootstrap
2,L1,L2 正則化
3,決策樹的剪枝操做
4,交叉驗證
12.3 什麼是機器學習的欠擬合?
所謂欠擬合就是模型複雜度低或者數據集過小,對模型數據的擬合程度不高,所以模型在訓練集上的效果就很差。
12.3 如何避免欠擬合問題?
1,增長樣本數量
2,增長樣本特徵的數量
3,能夠進行特徵維度擴展
12.4 算法的偏差通常是由那幾個方面引發的?
1,因模型沒法表達基本數據的複雜度而形成的誤差(bias)——欠擬合
2,因模型過分擬合訓練集數據而形成的方差(variance)——過擬合
13,爲何樸素貝葉斯如此「樸素」?
貝葉斯算法簡單高效,在處理分類問題上,是首先要考慮的方法之一。
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。公式以下:
該公式最大的優勢就是能夠忽略AB 的聯合機率直接求其條件機率分佈。
而樸素貝葉斯爲何如此樸素,由於他假定全部的特徵在數據集中的做用是一樣重要和獨立的。正如咱們所知,這個假設在現實世界中是很不真實的,所以說樸素貝葉斯真的很「樸素」。
樸素貝葉斯分類是一種很是簡單的分類算法,其思想是樸素的。即:對於給出的待分類項,求解在此項出現的條件下各個類別出現的機率,那個最大,就認爲此待分類項屬於那個類別。
理論上,樸素貝葉斯模型與其餘分類方法相比具備最小的偏差率。可是實際上並不是老是如此,這是由於樸素貝葉斯模型給定輸出類別的狀況下,假設屬性之間相互獨立,這個假設在實際應用中每每是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果很差。而在屬性相關性較小的時,樸素貝葉斯性能最爲良好。對於這一點,有半樸素貝葉斯之類的算法經過考慮部分關聯性適度改進。
14,反向傳播算法(BP算法)的推導及其Python實現
下面學習如何調整一個神經網絡的參數,也就是偏差反向傳播算法(BP算法)。以獲得一個可以根據輸入,預測正確輸出的模型。
14.1,首先咱們要了解優化的目標
根據人工神經元的定義,有如下三個公式:
其中,Act() 是激活函數,以前學習過。
根據上面兩個公式,能夠得出各個神經元之間的通用公式,以下:
其中上式是人工神經網絡正向傳播的核心公式。
那麼,咱們根據什麼來調整神經網絡的參數,以獲得一個可以正確預測結果的模型呢?請看下面的公式:
上式用來計算咱們指望的輸出和實際輸出的「差異」,其中cost() 叫作損失函數。咱們的指望是損失函數值達到最小。
可是隻根據一次輸出的損失值,對參數進行調整,沒法使模型適應全部輸入樣本。咱們須要的是,調整參數,使得全部輸入樣本,獲得輸出的總損失值最小,而不是隻讓妻子一個樣本的損失值最小,致使其餘樣本損失值增大。所以有下面公式:
上式表示一個 batch 的全部樣本輸出的總損失值的平均值。其中,bn 表示一個 batch中樣本的數量。
爲何不用全部的樣本計算損失值,而將全部樣本分紅一個個的 batch呢?由於全部的訓練樣本數量太大了,可能有數以百萬計,將全部的樣本損失值都一塊兒進行運算,計算量過於龐大,大大下降了模型計算的速度。
而計算總的損失值 C,其中是一個以全部的鏈接權重 W 和 全部的閾值 theta 未爲變量的多元函數。咱們想要的模型就是求得 C 最小時,全部 W 和 theta 的值。直接計算顯然是不可能的,由於對於一個大的深度神經網絡,全部的參數變量,可能數以萬計。
在這裏咱們使用梯度降低算法來逐步逼近 C的最小值,也便是先隨機獲得一組參數變量的值,而後計算參數變量當前的梯度,向梯度的反方向,也就是C變小最快的方向,逐步調整參數值,最終獲得 C 的最小值,或者近似最小值。
而將全部樣本,隨機分紅一個個固定長度的 batch,以獲得近似的梯度方向,叫作隨機梯度降低算法。
14.2 開始求梯度
那麼根據梯度的定義,接下來的任務,就是求取各個參數變量相對於 C 的偏導數。咱們將使用偏差反向傳播算法來求取各個參數變量的偏導數。
求取偏導數的方法和神經網絡正向傳播(根據樣本計算輸出值)的方式相似,也是逐層求解,只是方向正好相反,從最後一層開始,逐層向前。
首先,咱們先求神經網絡最後一層,也便是輸出層的相關參數的偏導數。爲了下降推導的複雜性,咱們只計算相對一個樣本的損失值函數 Cbi 的偏導數,由於相對於總損失值函數 C 的偏導數值,也不過是把某個參數的全部相對於 Cbi 偏導數值加起來而已。
根據上面公式,以及 複合函數求導法則,能夠獲得輸出層(L層)某個神經元的權值參數 W 的偏導數,計算公式以下:
根據前面三個公式求導以下:
將這三個公式代入上面公式,能夠獲得:
咱們令:
則:
將上式代入損失函數求導的公式中能夠獲得:
這樣咱們就獲得了輸出層 L 相關的權重參數 W 的偏導數計算公式!
接下來,同理能夠求得輸出層 L 相關的閾值 theta 的偏導數計算公式爲:
而根據第二個公式能夠獲得:
將上式代入到上上式能夠獲得:
這就是 輸出層 L 相關的閾值 theta 的偏導數計算公式!
14.3 根據 L 層,求前一層參數的偏導函數
從下面公式,可知,一個權重參數 W 隻影響一個 L-1 層的神經元:
所以能夠獲得有下面公式:
將上式代入到上上式能夠獲得:
根據假設:
咱們能夠獲得:
將上式代入到上上式,能夠獲得:
同理,咱們能夠獲得:
根據14.3 第一個公式能夠獲得:
將上式代入到上上式,能夠獲得:
這樣咱們就獲得了 L-1 層神經元相關參數的計算公式。
下面咱們還須要推導一下
之間的關係,根據下面公式:
咱們能夠獲得:
同理可得:
將上式代入到上上式,能夠得:
咱們知道,一個權重參數 W 隻影響一個 L-1 層的神經元,但這個 L-1 層神經元影響了全部 L層的神經元。所以,根據多元複合函數求導法則。有:
根據咱們以前的假設,能夠獲得:
將上式代入到上上式,能夠獲得:
咱們能夠知道:
將上式代入到上上式,能夠獲得:
最後將上式代入以前的公式,能夠獲得:
這樣咱們就獲得了反向傳播,逐層推導的通用公式:
這裏, W 和 Z 都是整箱傳播過程當中已經算好的常數,而
能夠從 L層開始逐層向前推導,直到第1層,第0層是輸入層,不須要調整參數,而第L層的參數能夠參考下面公式:
下面是全鏈接神經網絡的Python實現代碼:
#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表示神經網絡各層的神經元個數,第一層爲輸入層,最後一層爲輸出層
#act爲神經元的激活函數
#act_derivative爲激活函數的導數
#cost_derivative爲損失函數的導數
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):
#逐層計算神經元的激活值,公式(4)
for b, w in zip(self.biases, self.weights):
a = self.act(np.dot(w, a)+b)
return a
#隨機梯度降低算法
def SGD(self, training_data, epochs, batch_size, learning_rate):
#將訓練樣本training_data隨機分爲若干個長度爲batch_size的batch
#使用各個batch的數據不斷調整參數,學習率爲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):
#根據一個batch中的訓練樣本,調整各個參數值
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)]
#計算梯度,並調整各個參數值
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的偏導數值
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#正向傳播
activation = x
#保存每一層神經元的激活值
activations = [x]
#保存每一層神經元的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)
#反向傳播獲得各個參數的偏導數值
#公式(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())
#反向逐層計算
for l in range(2, self.num_layers):
z = zs[-l]
sp = self.act_derivative(z)
#公式(36),反向逐層求參數偏導
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)
#距離函數的偏導數
def distance_derivative(output_activations, y):
#損失函數的偏導數
return 2*(output_activations-y)
sigmoid函數
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
sigmoid函數的導數
def sigmoid_derivative(z):
return sigmoid(z)*(1-sigmoid(z))
if name == "main":
#建立一個5層的全鏈接神經網絡,每層的神經元個數爲1,8,5,3,1
#其中第一層爲輸入層,最後一層爲輸出層
network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)
#訓練集樣本
x = np.array([np.linspace(-7, 7, 200)]).T
#訓練集結果,因爲使用了sigmoid做爲激活函數,需保證其結果落在(0,1)區間內
y = (np.cos(x)+1)/2
#使用隨機梯度降低算法(SGD)對模型進行訓練
#迭代5000次;每次隨機抽取40個樣本做爲一個batch;學習率設爲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)
#測試集樣本
x_test = np.array([np.linspace(-9, 9, 120)])
#測試集結果
y_predict = network.feedforward(x_test)
#圖示對比訓練集和測試集數據
plt.plot(x,y,'r',x_test.T,y_predict.T,'*')
plt.show()