推薦優化演算法
『壹』 機器學習中有哪些重要的優化演算法
梯度下降是非常常用的優化演算法。作為機器學習的基礎知識,這是一個必須要掌握的演算法。藉助本文,讓我們來一起詳細了解一下這個演算法。
前言
本文的代碼可以到我的Github上獲取:
https://github.com/paulQuei/gradient_descent
本文的演算法示例通過python語言實現,在實現中使用到了numpy和matplotlib。如果你不熟悉這兩個工具,請自行在網上搜索教程。
關於優化
大多數學習演算法都涉及某種形式的優化。優化指的是改變x以最小化或者最大化某個函數的任務。
我們通常以最小化指代大多數最優化問題。最大化可經由最小化來實現。
我們把要最小化或最大化的函數成為目標函數(objective function)或准則(criterion)。
我們通常使用一個上標*表示最小化或最大化函數的x值,記做這樣:
[x^* = arg; min; f(x)]
優化本身是一個非常大的話題。如果有興趣,可以通過《數值優化》和《運籌學》的書籍進行學習。
模型與假設函數
所有的模型都是錯誤的,但其中有些是有用的。– George Edward Pelham Box
模型是我們對要分析的數據的一種假設,它是為解決某個具體問題從老洞數據中學習到的,因此它是機器學習最核心的概念。
針對一個問題,通常有大量的模型可以選擇。
本文不會深入討論這方面的內容,關於各種模型請參閱機器學習的相關書籍。本文僅以最簡單的線性模型為基礎來討論梯度下降演算法。
這里我們先介紹一下在監督學習(supervised learning)中常見的三個符號:
m,描述訓練樣本的數量
x,描述輸入變數或特徵
y,描述輸出變數或者叫目標值
- 請注意,一個樣本笑或可能有很多的特徵,因此x和y通常是一個向量。不過在剛開始學習的時候,為了便於理解,你可以暫時理解為這就是一個具體的數值。
- 代價函數也叫損失函數。
- 不同的模型可能會用不同的損失函數。例如,logistic回歸的假設函數是這樣的:。其代價函數是這樣的:
對於一個函數,怎麼確定下行的方向?
每一步該往前走多遠?
有沒有可能停留在半山腰的平台上?
- 這里的下標i表示第i個參數。 上標k指的是第k步的計算結果,而非k次方。在能夠理解的基礎上,下文的公式中將省略上標k。
收斂是指函數的變化率很小。具體選擇多少合適需要根據具體的項目來確定。在演示項目中我們可以選擇0.01或者0.001這樣的值。不同的值將影響演算法的迭代次數,因為在梯度下降的最後,我們會越來越接近平坦的地方,這個時候函數的變化率也越來越小。如果選擇一個很小的值,將可能導致演算法迭代次數暴增。
公式中的 稱作步長,也稱作學習率(learning rate)。它決定了每一步往前走多遠,關於這個值我們會在下文中詳細講解。你可以暫時人為它是一個類似0.01或0.001的固定值。
在具體的項目,我們不會讓演算法無休止的運行下去,所以通常會設置一個迭代次數的最大上限。
我們隨機選擇了 都為10作為起點
設置最多迭代1000次
收斂的范圍設為0.001
學習步長設為0.01
如果樣本數量較小(例如小於等於2000),選擇BGD即可。
如果樣本數量很大,選擇 來進行MBGD,例如:64,128,256,512。
- 《深度學習》一書中是這樣描述的:「與其說是科學,這更像是一門藝術,我們應該謹慎地參考關於這個問題的大部分指導。」。
對於凸函數或者凹函數來說,不存在局部極值的問題。其局部極值一定是全局極值。
最近的一些研究表明,某些局部極值並沒有想像中的那麼糟糕,它們已經非常的接近全局極值所帶來的結果了。
Wikipeida: Gradient descent
Sebastian Ruder: An overview of gradient descent optimization algorithms
吳恩達:機器學習
吳恩達:深度學習
Peter Flach:機器學習
李宏毅 - ML Lecture 3-1: Gradient Descent
PDF: 李宏毅 - Gradient Descent
Intro to optimization in deep learning: Gradient Descent
Intro to optimization in deep learning: Momentum, RMSProp and Adam
Stochastic Gradient Descent – Mini-batch and more
劉建平Pinard - 梯度下降(Gradient Descent)小結
多元函數的偏導數、方向導數、梯度以及微分之間的關系思考
[Machine Learning] 梯度下降法的三種形式BGD、SGD以及MBGD
- 作者:阿Paul https://paul.pub/gradient-descent/
訓練集會包含很多的樣本,我們用 表示其中第i個樣本。
x是數據樣本的特徵,y是其目標值。例如,在預測房價的模型中,x是房子的各種信息,例如:面積,樓層,位置等等,y是房子的價格。在圖像識別的任務中,x是圖形的所有像素點數據,y是圖像中包含的目標對象。
我們是希望尋找一個函數,將x映射到y,這個函數要足夠的好,以至於能夠預測對應的y。由於歷史原因,這個函數叫做假設函數(hypothesis function)。
學習的過程如下圖所示。即:首先根據已有的數據(稱之為訓練集)訓練我們的演算法模型,然後根據模型的假設函數來進行新數據的預測。
線性模型(linear model)正如其名稱那樣:是希望通過一個直線的形式來描述模式。線性模型的假設函數如下所示:
[h_{ heta}(x) = heta_{0} + heta_{1} * x]
這個公式對於大家來說應該都是非常簡單的。如果把它繪制出來,其實就是一條直線。
下圖是一個具體的例子,即: 的圖形:
在實際的機器學習工程中碰含伍,你會擁有大量的數據。這些數據會來自於某個數據源。它們存儲在csv文件中,或者以其他的形式打包。
但是本文作為演示使用,我們通過一些簡單的代碼自動生成了需要的數據。為了便於計算,演示的數據量也很小。
import numpy as np
max_x = 10
data_size = 10
theta_0 = 5
theta_1 = 2
def get_data:
x = np.linspace(1, max_x, data_size)
noise = np.random.normal(0, 0.2, len(x))
y = theta_0 + theta_1 * x + noise
return x, y
這段代碼很簡單,我們生成了x范圍是 [1, 10] 整數的10條數據。對應的y是以線性模型的形式計算得到,其函數是:。現實中的數據常常受到各種因素的干擾,所以對於y我們故意加上了一些高斯雜訊。因此最終的y值為比原先會有輕微的偏離。
最後我們的數據如下所示:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [6.66, 9.11, 11.08, 12.67, 15.12, 16.76, 18.75, 21.35, 22.77, 24.56]
我們可以把這10條數據繪制出來這樣就有一個直觀的了解了,如下圖所示:
雖然演示用的數據是我們通過公式計算得到的。但在實際的工程中,模型的參數是需要我們通過數據學習到的。所以下文我們假設我們不知道這里線性模式的兩個參數是什麼,而是通過演算法的形式求得。
最後再跟已知的參數進行對比以驗證我們的演算法是否正確。
有了上面的數據,我們可以嘗試畫一條直線來描述我們的模型。
例如,像下面這樣畫一條水平的直線:
很顯然,這條水平線離數據太遠了,非常的不匹配。
那我們可以再畫一條斜線。
我們初次畫的斜線可能也不貼切,它可能像下面這樣:
最後我們通過不斷嘗試,找到了最終最合適的那條,如下所示:
梯度下降演算法的計算過程,就和這種本能式的試探是類似的,它就是不停的迭代,一步步的接近最終的結果。
代價函數
上面我們嘗試了幾次通過一條直線來擬合(fitting)已有的數據。
二維平面上的一條直線可以通過兩個參數唯一的確定,兩個參數的確定也即模型的確定。那如何描述模型與數據的擬合程度呢?答案就是代價函數。
代價函數(cost function)描述了學習到的模型與實際結果的偏差程度。以上面的三幅圖為例,最後一幅圖中的紅線相比第一條水平的綠線,其偏離程度(代價)應該是更小的。
很顯然,我們希望我們的假設函數與數據盡可能的貼近,也就是說:希望代價函數的結果盡可能的小。這就涉及到結果的優化,而梯度下降就是尋找最小值的方法之一。
對於每一個樣本,假設函數會依據計算出一個估算值,我們常常用來表示。即 。
很自然的,我們會想到,通過下面這個公式來描述我們的模型與實際值的偏差程度:
[(h_ heta(x^i) - y^i)^2 = (widehat{y}^{i} - y^i)^2 = ( heta_{0} + heta_{1} * x^{i} - y^{i})^2]
請注意, 是實際數據的值, 是我們的模型的估算值。前者對應了上圖中的離散點的y坐標,後者對應了離散點在直線上投影點的y坐標。
每一條數據都會存在一個偏差值,而代價函數就是對所有樣本的偏差求平均值,其計算公式如下所示:
[L( heta) = frac {1}{m} sum_{i=1}^{m}(h_ heta(x^i) - y^i)^2 = frac {1}{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i})^2]
當損失函數的結果越小,則意味著通過我們的假設函數估算出的結果與真實值越接近。這也就是為什麼我們要最小化損失函數的原因。
藉助上面這個公式,我們可以寫一個函數來實現代價函數:
def cost_function(x, y, t0, t1):
cost_sum = 0
for i in range(len(x)):
cost_item = np.power(t0 + t1 * x[i] - y[i], 2)
cost_sum += cost_item
return cost_sum / len(x)
這個函數的代碼應該不用多做解釋,它就是根據上面的完成計算。
我們可以嘗試選取不同的 和 組合來計算代價函數的值,然後將結果繪制出來:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
theta_0 = 5
theta_1 = 2
def draw_cost(x, y):
fig = plt.figure(figsize=(10, 8))
ax = fig.gca(projection='3d')
scatter_count = 100
radius = 1
t0_range = np.linspace(theta_0 - radius, theta_0 + radius, scatter_count)
t1_range = np.linspace(theta_1 - radius, theta_1 + radius, scatter_count)
cost = np.zeros((len(t0_range), len(t1_range)))
for a in range(len(t0_range)):
for b in range(len(t1_range)):
cost[a][b] = cost_function(x, y, t0_range[a], t1_range[b])
t0, t1 = np.meshgrid(t0_range, t1_range)
ax.set_xlabel('theta_0')
ax.set_ylabel('theta_1')
ax.plot_surface(t0, t1, cost, cmap=cm.hsv)
在這段代碼中,我們對 和 各自指定了一個范圍進行100次的采樣,然後以不同的 組合對來計算代價函數的值。
如果我們將所有點的代價函數值繪制出來,其結果如下圖所示:
從這個圖形中我們可以看出,當 越接近 [5, 2]時其結果(偏差)越小。相反,離得越遠,結果越大。
直觀解釋
從上面這幅圖中我們可以看出,代價函數在不同的位置結果大小不同。
從三維的角度來看,這就和地面的高低起伏一樣。最高的地方就好像是山頂。
而我們的目標就是:從任意一點作為起點,能夠快速尋找到一條路徑並以此到達圖形最低點(代價值最小)的位置。
而梯度下降的演算法過程就和我們從山頂想要快速下山的做法是一樣的。
在生活中,我們很自然會想到沿著最陡峭的路往下行是下山速度最快的。如下面這幅圖所示:
針對這幅圖,細心的讀者可能很快就會有很多的疑問,例如:
這些問題也就是本文接下來要討論的內容。
演算法描述
梯度下降演算法最開始的一點就是需要確定下降的方向,即:梯度。
我們常常用 來表示梯度。
對於一個二維空間的曲線來說,梯度就是其切線的方向。如下圖所示:
而對於更高維空間的函數來說,梯度由所有變數的偏導數決定。
其表達式如下所示:
[ abla f({ heta}) = ( frac{partial f({ heta})}{partial heta_1} , frac{partial f({ heta})}{partial heta_2} , ... , frac{partial f({ heta})}{partial heta_n} )]
在機器學習中,我們主要是用梯度下降演算法來最小化代價函數,記做:
[ heta ^* = arg min L( heta)]
其中,L是代價函數,是參數。
梯度下降演算法的主體邏輯很簡單,就是沿著梯度的方向一直下降,直到參數收斂為止。
記做:
[ heta ^{k + 1}_i = heta^{k}_i - lambda abla f( heta^{k})]
這里有幾點需要說明:
線性回歸的梯度下降
有了上面的知識,我們可以回到線性模型代價函數的梯度下降演算法實現了。
首先,根據代價函數我們可以得到梯度向量如下:
[ abla f({ heta}) = (frac{partial L( heta)}{ partial heta_{0}}, frac{ partial L( heta)}{ partial heta_{1}}) = (frac {2}{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i}) , frac {2}{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i}) x^{i})]
接著,將每個偏導數帶入迭代的公式中,得到:
[ heta_{0} := heta_{0} - lambda frac{partial L( heta_{0})}{ partial heta_{0}} = heta_{0} - frac {2 lambda }{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i}) heta_{1} := heta_{1} - lambda frac{partial L( heta_{1})}{ partial heta_{1}} = heta_{1} - frac {2 lambda }{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i}) x^{i}]
由此就可以通過代碼實現我們的梯度下降演算法了,演算法邏輯並不復雜:
learning_rate = 0.01
def gradient_descent(x, y):
t0 = 10
t1 = 10
delta = 0.001
for times in range(1000):
sum1 = 0
sum2 = 0
for i in range(len(x)):
sum1 += (t0 + t1 * x[i] - y[i])
sum2 += (t0 + t1 * x[i] - y[i]) * x[i]
t0_ = t0 - 2 * learning_rate * sum1 / len(x)
t1_ = t1 - 2 * learning_rate * sum2 / len(x)
print('Times: {}, gradient: [{}, {}]'.format(times, t0_, t1_))
if (abs(t0 - t0_) < delta and abs(t1 - t1_) < delta):
print('Gradient descent finish')
return t0_, t1_
t0 = t0_
t1 = t1_
print('Gradient descent too many times')
return t0, t1
這段代碼說明如下:
如果我們將演算法迭代過程中求得的線性模式繪制出來,可以得到下面這幅動態圖:
最後演算法得到的結果如下:
Times: 657, gradient: [5.196562662718697, 1.952931052920264]
Times: 658, gradient: [5.195558390180733, 1.9530753071808193]
Times: 659, gradient: [5.194558335124868, 1.9532189556399233]
Times: 660, gradient: [5.193562479839619, 1.9533620008416623]
Gradient descent finish
從輸出中可以看出,演算法迭代了660次就收斂了。這時的結果[5.193562479839619, 1.9533620008416623],這已經比較接近目標值 [5, 2]了。如果需要更高的精度,可以將delta的值調的更小,當然,此時會需要更多的迭代次數。
高維擴展
雖然我們舉的例子是二維的,但是對於更高維的情況也是類似的。同樣是根據迭代的公式進行運算即可:
[ heta_{i} = heta_{i} - lambda frac {partial L( heta)}{partial heta_i} = heta_{i} - frac{2lambda}{m} sum_{i=1}^{m}(h_ heta(x^{k})-y^k)x_i^k]
這里的下標i表示第i個參數,上標k表示第k個數據。
梯度下降家族BGD
在上面的內容中我們看到,演算法的每一次迭代都需要把所有樣本進行遍歷處理。這種做法稱為之Batch Gradient Descent,簡稱BGD。作為演示示例只有10條數據,這是沒有問題的。
但在實際的項目中,數據集的數量可能是幾百萬幾千萬條,這時候每一步迭代的計算量就會非常的大了。
於是就有了下面兩個變種。
SGD
Stochastic Gradient Descent,簡稱SGD,這種演算法是每次從樣本集中僅僅選擇一個樣本來進行計算。很顯然,這樣做演算法在每一步的計算量一下就少了很多。
其演算法公式如下:
[ heta_{i} = heta_{i} - lambda frac {partial L( heta)}{partial heta_i} = heta_{i} - lambda(h_ heta(x^k)-y^k)x_i^k]
當然,減少演算法計算量也是有代價的,那就是:演算法結果會強依賴於隨機取到的數據情況,這可能會導致演算法的最終結果不太令人滿意。
MBGD
以上兩種做法其實是兩個極端,一個是每次用到了所有數據,另一個是每次只用一個數據。
我們自然就會想到兩者取其中的方法:每次選擇一小部分數據進行迭代。這樣既避免了數據集過大導致每次迭代計算量過大的問題,也避免了單個數據對演算法的影響。
這種演算法稱之為Mini-batch Gradient Descent,簡稱MBGD。
其演算法公式如下:
[ heta_{i} = heta_{i} - lambda frac {partial L( heta)}{partial heta_i} = heta_{i} - frac{2lambda}{m} sum_{i=a}^{a + b}(h_ heta(x^k)-y^k)x_i^k]
當然,我們可以認為SGD是Mini-batch為1的特例。
針對上面提到的演算法變種,該如何選擇呢?
下面是Andrew Ng給出的建議:
下表是 Optimization for Deep Learning 中對三種演算法的對比
方法准確性更新速度內存佔用在線學習BGD好慢高否SGD好(with annealing)快低是MBGD好中等中等是
演算法優化
式7是演算法的基本形式,在這個基礎上有很多人進行了更多的研究。接下來我們介紹幾種梯度下降演算法的優化方法。
Momentum
Momentum是動量的意思。這個演算法的思想就是藉助了動力學的模型:每次演算法的迭代會使用到上一次的速度作為依據。
演算法的公式如下:
[v^t = gamma v^{t - 1} + lambda abla f( heta) heta = heta - v_t]
對比式7可以看出,這個演算法的主要區別就是引入了,並且,每個時刻的受前一個時刻的影響。
從形式上看,動量演算法引入了變數 v 充當速度角色——它代表參數在參數空間移動的方向和速率。速度被設為負梯度的指數衰減平均。名稱動量來自物理類比,根據牛頓運動定律,負梯度是移動參數空間中粒子的力。動量在物理學上定義為質量乘以速度。在動量學習演算法中,我們假設是單位質量,因此速度向量 v 也可以看作是粒子的動量。
對於可以取值0,而是一個常量,設為0.9是一個比較好的選擇。
下圖是momentum演算法的效果對比:
對原來的演算法稍加修改就可以增加動量效果:
def gradient_descent_with_momentum(x, y):
t0 = 10
t1 = 10
delta = 0.001
v0 = 0
v1 = 0
gamma = 0.9
for times in range(1000):
sum1 = 0
sum2 = 0
for i in range(len(x)):
sum1 += (t0 + t1 * x[i] - y[i])
sum2 += (t0 + t1 * x[i] - y[i]) * x[i]
v0 = gamma * v0 + 2 * learning_rate * sum1 / len(x)
v1 = gamma * v1 + 2 * learning_rate * sum2 / len(x)
t0_ = t0 - v0
t1_ = t1 - v1
print('Times: {}, gradient: [{}, {}]'.format(times, t0_, t1_))
if (abs(t0 - t0_) < delta and abs(t1 - t1_) < delta):
print('Gradient descent finish')
return t0_, t1_
t0 = t0_
t1 = t1_
print('Gradient descent too many times')
return t0, t1
以下是該演算法的輸出:
Times: 125, gradient: [4.955453758569991, 2.000005017897775]
Times: 126, gradient: [4.955309381126545, 1.9956928964532015]
Times: 127, gradient: [4.9542964317327005, 1.9855674828684156]
Times: 128, gradient: [4.9536358220657, 1.9781180992510465]
Times: 129, gradient: [4.95412496254411, 1.9788858350530971]
Gradient descent finish
從結果可以看出,改進的演算法只用了129次迭代就收斂了。速度比原來660次快了很多。
同樣的,我們可以把演算法計算的過程做成動態圖:
對比原始的演算法過程可以看出,改進演算法最大的區別是:在尋找目標值時會在最終結果上下跳動,但是越往後跳動的幅度越小,這也就是動量所產生的效果。
Learning Rate 優化
至此,你可能還是好奇該如何設定學習率的值。
事實上,這個值的選取需要一定的經驗或者反復嘗試才能確定。
關鍵在於,這個值的選取不能過大也不能過小。
如果這個值過小,會導致每一次迭代的步長很小,其結果就是演算法需要迭代非常多的次數。
那麼,如果這個值過大會怎麼樣呢?其結果就是:演算法可能在結果的周圍來回震盪,卻落不到目標的點上。下面這幅圖描述了這個現象:
事實上,學習率的取值未必一定要是一個常數,關於這個值的設定有很多的研究。
下面是比較常見的一些改進演算法。
AdaGrad
AdaGrad是Adaptive Gradient的簡寫,該演算法會為每個參數設定不同的學習率。它使用歷史梯度的平方和作為基礎來進行計算。
其演算法公式如下:
[ heta_i = heta_i - frac{lambda}{sqrt{G_t + epsilon}} abla f( heta)]
對比式7,這里的改動就在於分號下面的根號。
根號中有兩個符號,第二個符號比較好理解,它就是為了避免除0而人為引入的一個很小的常數,例如可以設為:0.001。
第一個符號的表達式展開如下:
[G_t = sum_{i = 1}^{t} abla f( heta){i} abla f( heta){i}^{T}]
這個值其實是歷史中每次梯度的平方的累加和。
AdaGrad演算法能夠在訓練中自動的對learning rate進行調整,對於出現頻率較低參數採用較大的學習率;相反,對於出現頻率較高的參數採用較小的學習率。因此,Adagrad非常適合處理稀疏數據。
但該演算法的缺點是它可能導致學習率非常小以至於演算法收斂非常的慢。
關於這個演算法的直觀解釋可以看李宏毅教授的視頻課程:ML Lecture 3-1: Gradient Descent。
RMSProp
RMS是Root Mean Square的簡寫。RMSProp是AI教父Geoff Hinton提出的一種自適應學習率方法。AdaGrad會累加之前所有的梯度平方,而RMSProp僅僅是計算對應的平均值,因此可緩解Adagrad演算法學習率下降較快的問題。
該演算法的公式如下:
[E[ abla f( heta_{i})^2]^{t} = gamma E[ abla f( heta_{i})^2]^{t - 1} + (1-gamma)( abla f( heta_{i})^{t})^{2} heta_i = heta_i - frac{lambda}{sqrt{E[g^2]^{t+1} + epsilon}} abla f( heta_{i})]
類似的,是為了避免除0而引入。 是衰退參數,通常設為0.9。
這里的 是t時刻梯度平方的平均值。
Adam
Adam是Adaptive Moment Estimation的簡寫。它利用梯度的一階矩估計和二階矩估計動態調整每個參數的學習率。
Adam的優點主要在於經過偏置校正後,每一次迭代學習率都有個確定范圍,使得參數比較平穩。
該演算法公式如下:
[m^{t} = eta_{1} m^{t-1} + (1-eta_{1}) abla f( heta) v^{t} = eta_{2} v^{t-1} + (1-eta_{2}) abla f( heta)^2 widehat{m}^{t} = frac{m^{t}}{1 - eta^{t}_1} widehat{v}^{t} = frac{v^{t}}{1 - eta^{t}_2} heta = heta - frac{lambda}{sqrt{widehat{v}^{t}} + epsilon}widehat{m}^{t}]
,分別是對梯度的一階矩估計和二階矩估計。, 是對,的校正,這樣可以近似為對期望的無偏估計。
Adam演算法的提出者建議 默認值為0.9,默認值為0.999,默認值為 。
在實際應用中 ,Adam較為常用,它可以比較快地得到一個預估結果。
優化小結
這里我們列舉了幾種優化演算法。它們很難說哪種最好,不同的演算法適合於不同的場景。在實際的工程中,可能需要逐個嘗試一下才能確定選擇哪一個,這個過程也是目前現階段AI項目要經歷的工序之一。
實際上,該方面的研究遠不止於此,如果有興趣,可以繼續閱讀 《Sebastian Ruder: An overview of gradient descent optimization algorithms》 這篇論文或者 Optimization for Deep Learning 這個Slides進行更多的研究。
由於篇幅所限,這里不再繼續展開了。
演算法限制
梯度下降演算法存在一定的限制。首先,它要求函數必須是可微分的,對於不可微的函數,無法使用這種方法。
除此之外,在某些情況下,使用梯度下降演算法在接近極值點的時候可能收斂速度很慢,或者產生Z字形的震盪。這一點需要通過調整學習率來迴避。
另外,梯度下降還會遇到下面兩類問題。
局部最小值
局部最小值(Local Minima)指的是,我們找到的最小值僅僅是一個區域內的最小值,而並非全局的。由於演算法的起點是隨意取的,以下面這個圖形為例,我們很容易落到局部最小值的點裡面。
這就是好像你從上頂往下走,你第一次走到的平台未必是山腳,它有可能只是半山腰的一個平台的而已。
演算法的起點決定了演算法收斂的速度以及是否會落到局部最小值上。
壞消息是,目前似乎沒有特別好的方法來確定選取那個點作為起點是比較好的,這就有一點看運氣的成分了。多次嘗試不同的隨機點或許是一個比較好的方法,這也就是為什麼做演算法的優化這項工作是特別消耗時間的了。
但好消息是:
鞍點
除了Local Minima,在梯度下降的過程中,還有可能遇到另外一種情況,即:鞍點(Saddle Point)。鞍點指的是我們找到點某個點確實是梯度為0,但它卻不是函數的極值,它的周圍既有比它小的值,也有比它大的值。這就好像馬鞍一樣。
如下圖所示:
多類隨機函數表現出以下性質:在低維空間中,局部極值很普遍。但在高維空間中,局部極值比較少見,而鞍點則很常見。
不過對於鞍點,可以通過數學方法Hessian矩陣來確定。關於這點,這里就不再展開了,有興趣的讀者可以以這里提供的幾個鏈接繼續探索。
參考資料與推薦讀物
『貳』 優化演算法筆記(一)優化演算法的介紹
(以下描述,均不是學術用語,僅供大家快樂的閱讀)
我們常見常用的演算法有排序演算法,字元串遍歷演算法,尋路演算法等。這些演算法都是為了解決特定的問題而被提出。
演算法本質是一種按照固定步驟執行的過程。
優化演算法也是這樣一種過程,是一種根據概率按照固定步驟尋求問題的最優解的過程。與常見的排序演算法、尋路演算法不同的是,優化演算法不具備等冪性,是一種 概率演算法 。演算法不斷的 迭代 執行同一步驟直到結束,其流程如下圖。
等冪性即 對於同樣的輸入,輸出是相同的 。
比如圖1,對於給定的魚和給定的熊掌,我們在相同的條件下一定可以知道它們誰更重,當然,相同的條件是指魚和熊掌處於相同的重力作用下,且不用考慮水分流失的影響。在這些給定的條件下,我們(無論是誰)都將得出相同的結論,魚更重或者熊掌更重。我們可以認為,秤是一個等冪性的演算法(工具)。
現在把問題變一變,問魚與熊掌你更愛哪個,那麼現在,這個問題,每個人的答案可能不會一樣,魚與熊掌各有所愛。說明喜愛這個演算法不是一個等冪性演算法。當然你可能會問,哪個更重,和更喜歡哪個這兩個問題一個是客觀問題,一個是主觀問題,主觀問題沒有確切的答案的。當我們處理主觀問題時,也會將其轉換成客觀問題,比如給喜歡魚和喜歡熊掌的程度打個分,再去尋求答案,畢竟計算機沒有感情,只認0和1(量子計算機我不認識你)。
說完了等冪性,再來說什麼是概率演算法。簡單來說就是看臉、看人品、看運氣的演算法。
有一場考試,考試的內容全部取自課本,同時老師根據自己的經驗給同學們劃了重點,但是因為試卷並不是該老師所出,也會有考試內容不在重點之內,老師估計試卷中至少80%內容都在重點中。學霸和學渣參加了考試,學霸為了考滿分所以無視重點,學渣為了pass,因此只看了重點。這樣做的結果一定是score(學霸)>=score(學渣)。
當重點跟上圖一樣的時候,所有的內容都是重點的時候,學霸和學渣的學習策略變成了相同的策略,則score(學霸)=score(學渣)。但同時,學渣也要付出跟學霸相同的努力去學習這些內容,學渣心裡苦啊。
當課本如下圖時
學霸?學霸人呢,哪去了快來學習啊,不是說學習一時爽,一直學習一直爽嗎,快來啊,還等什麼。
這時,如果重點內容遠少於書本內容時,學渣的學習策略有了優勢——花費的時間和精力較少。但是同時,學渣的分數也是一個未知數,可能得到80分也可能拿到100分,分數完全取決於重點內容與題目的契合度,契合度越高,分數越高。對學渣來說,自己具體能考多少分無法由自己決定,但是好在能夠知道大概的分數范圍。
學霸的學習策略是一種遍歷性演算法,他會遍歷、通讀全部內容,以保證滿分。
學渣的學習策略則是一種概率演算法,他只會遍歷、學習重點內容,但至於這些重點是不是真重點他也不知道。
與遍歷演算法相比,概率演算法的結果具有不確定性,可能很好,也可能很差,但是會消耗更少的資源,比如時間(人生),空間(記憶)。概率演算法的最大優點就是 花費較少的代價來獲取最高的收益 ,在現實中體現於節省時間,使用很少的時間得到一個不與最優解相差較多的結果。
「莊子:吾生也有涯,而知也無涯;以有涯隨無涯,殆矣。」的意思是:人生是有限的,但知識是無限的(沒有邊界的),用有限的人生追求無限的知識,是必然失敗的。
生活中概率演算法(思想)的應用其實比較廣泛,只是我們很少去注意罷了。關於概率演算法還衍生出了一些有趣的理論,比如墨菲定律和倖存者偏差,此處不再詳述。
上面說到,優化演算法就是不停的執行同樣的策略、步驟直到結束。為什麼要這樣呢?因為優化演算法是一種概率演算法,執行一次操作就得到最優結果幾乎是不可能的,重復多次取得最優的概率也會增大。
栗子又來了,要從1-10這10個數中取出一個大於9的數,只取1次,達到要求的概率為10%,取2次,達到要求的概率為19%。
可以看出取到第10次時,達到要求的概率幾乎65%,取到100次時,達到要求的概率能接近100%。優化演算法就是這樣簡單粗暴的來求解問題的嗎?非也,這並不是一個恰當的例子,因為每次取數的操作之間是相互獨立的,第2次取數的結果不受第1次取數結果的影響,假設前99次都沒達到要求,那麼再取一次達到要求的概率跟取一次達到要求的概率相同。
優化演算法中,後一次的計算會依賴前一次的結果,以保證後一次的結果不會差於前一次的結果。這就不得不談到馬爾可夫鏈了。
由鐵組成的鏈叫做鐵鏈,同理可得,馬爾可夫鏈就是馬爾可夫組成的鏈。
言歸正傳, 馬爾可夫鏈(Markov Chain, MC) ,描述的是 狀態轉移的過程中,當前狀態轉移的概率只取決於上一步的狀態,與其他步的狀態無關 。簡單來說就是當前的結果只受上一步的結果的影響。每當我看到馬爾可夫鏈時,我都會陷入沉思,生活中、或者歷史中有太多太多與馬爾可夫鏈相似的東西。西歐封建等級制度中「附庸的附庸不是我的附庸」與「昨天的努力決定今天的生活,今天的努力決定明天的生活」,你的下一份工作的工資大多由你當前的工資決定,這些都與馬爾可夫鏈有異曲同工之處。
還是從1-10這10個數中取出一個大於9的數的這個例子。基於馬爾可夫鏈的概率演算法在取數時需要使當前取的數不小於上一次取的數。比如上次取到了3,那麼下次只能在3-10這幾個數中取,這樣一來,達到目標的概率應該會顯著提升。還是用數據說話。
取1次達到要求的概率仍然是
取2次內達到要求的概率為
取3次內達到要求的概率為
取4次內……太麻煩了算了不算了
可以看出基於馬爾可夫鏈來取數時,3次內能達到要求的概率與不用馬爾可夫鏈時取6次的概率相當。說明基於馬爾可夫鏈的概率演算法求解效率明顯高於隨機概率演算法。那為什麼不將所有的演算法都基於馬爾可夫鏈呢?原因一,其實現方式不是那麼簡單,例子中我們規定了取數的規則是復合馬爾可夫鏈的,而在其他問題中我們需要建立適當的復合馬爾科夫鏈的模型才能使用。原因二,並不是所有的問題都符合馬爾科夫鏈條件,比如原子內電子出現的位置,女朋友為什麼會生(lou)氣,彩票號碼的規律等,建立模型必須與問題有相似之處才能較好的解決問題。
介紹完了優化演算法,再來討論討論優化演算法的使用場景。
前面說了優化演算法是一種概率演算法,無法保證一定能得到最優解,故如果要求結果必須是確定、穩定的值,則無法使用優化演算法求解。
例1,求城市a與城市b間的最短路線。如果結果用來修建高速、高鐵,那麼其結果必定是唯一確定的值,因為修路寸土寸金,必須選取最優解使花費最少。但如果結果是用來趕路,那麼即使沒有選到最優的路線,我們可能也不會有太大的損失。
例2,求城市a與城市b間的最短路線,即使有兩條路徑,路徑1和路徑2,它們從a到b的距離相同,我們也可以得出這兩條路徑均為滿足條件的解。現在將問題改一下,求城市a到城市b耗時最少的線路。現在我們無法馬上得出確切的答案,因為最短的線路可能並不是最快的路線,還需要考慮到天氣,交通路況等因素,該問題的結果是一個動態的結果,不同的時間不同的天氣我們很可能得出不同的結果。
現實生產、生活中,也有不少的場景使用的優化演算法。例如我們的使用的美圖軟體,停車場車牌識別,人臉識別等,其底層參數可能使用了優化演算法來加速參數計算,其參數的細微差別對結果的影響不太大,需要較快的得出誤差范圍內的參數即可;電商的推薦系統等也使用了優化演算法來加速參數的訓練和收斂,我們會發現每次刷新時,推給我們的商品都有幾個會發生變化,而且隨著我們對商品的瀏覽,系統推給我們的商品也會發生變化,其結果是動態變化的;打車軟體的訂單系統,會根據司機和客人的位置,區域等來派發司機給客人,不同的區域,不同的路況,派發的司機也是動態變化的。
綜上我們可以大致總結一下推薦、不推薦使用優化演算法的場景的特點。
前面說過,優化演算法處理的問題都是客觀的問題,如果遇到主觀的問題,比如「我孰與城北徐公美」,我們需要將這個問題進行量化而轉換成客觀的問題,如身高——「修八尺有餘」,「外貌——形貌昳麗」,自信度——「明日徐公來,孰視之,自以為不如;窺鏡而自視,又弗如遠甚」,轉化成客觀問題後我們可以得到各個解的分數,通過比較分數,我們就能知道如何取捨如何優化。這個轉化過程叫做問題的建模過程,建立的問題模型實際上是一個函數,這個函數對優化演算法來說是一個黑盒函數,即不需要知道其內部實現只需要給出輸入,得到輸出。
在優化演算法中這個黑盒函數叫做 適應度函數 , 優化演算法的求解過程就是尋找適應度函數最優解的過程 ,使用優化演算法時我們最大的挑戰就是如何將抽象的問題建立成具體的模型,一旦合適的模型建立完成,我們就可以愉快的使用優化演算法來求解問題啦。(「合適」二字談何容易)
優化演算法的大致介紹到此結束,後面我們會依次介紹常見、經典的優化演算法,並探究其參數對演算法性能的影響。
——2019.06.20
[目錄]
[下一篇 優化演算法筆記(二)優化演算法的分類]
『叄』 如何做好「推薦演算法」有哪些常見的錯誤需要避免
在這里share一下。
1、推薦演算法的構成
一套標準的推薦演算法,需要四個組成部分
第一:數據源,行為基礎數據的篩選;通常,推薦演算法來源於用戶行為的採集,簡單說就是行為數據越豐富,樣本覆蓋率越全面,結果越准確;如果采樣有偏差,那麼結果就會有偏差。
舉例1:游戲推薦演算法,我們之前限於采樣技術水平和處理能力,用的是登陸用戶玩過的游戲歷史,那麼推薦結果就會偏重於需要登陸的游戲。而隨著技術提升用全部用戶玩過的游戲歷史,就更全面了。
舉例2:在搜索引擎中,對關鍵詞做推薦,有兩種方案,一種是基於廣告主的競價記錄;另一種是基於網民的搜索行為;前一種專業性更強,噪音小;後一種覆蓋面廣,噪音大,各有利弊,根據業務訴求選擇。
推薦演算法,通常來源於用戶的行為記錄,比如關鍵詞推薦用用戶搜索歷史,電商推薦用用戶購物歷史,游戲推薦用玩家玩游戲的歷史,然後基於演算法給出相關度,再排序展示 ;但這不絕對,也有並非基於用戶行為記錄的推薦原理,比如基於用戶身份特徵或其他地區、網路環境等特徵,限於篇幅和常見的業務訴求,這里就不展開說明了。
行為基礎數據必要時要做一些去除噪音的工作,比如你通過日誌分析玩家游戲歷史,或用戶購物歷史,至少知道把各搜索引擎和工具的抓取痕跡過濾出去,否則結果是很難看的。
演算法很多種,網上可以搜到很多,就算搜不到,或者搜到了看不懂,自己編也不難的(我就編過,效果自以為還不錯,但是的確不如人家專業的演算法效果好,所以適合練手,不適合出去吹牛)
不同演算法差異還是蠻大的,需要理解一下業務訴求和目標特徵來選擇。這個我真心不是高手,我們同事講的演算法我都沒能理解,就不多說了。微博上的「張棟_機器學習"和"梁斌penny"都是演算法高手,大家可以多關心他們的微博。
第三:參數!
絕對不要認為用到了好的演算法就可以了!演算法往往會基於一些參數來調優,這些參數哪裡來?很不好意思的告訴你,大部分是拍腦袋出來的。但是你拍腦袋出來後,要知道去分析結果,去看哪裡對,哪裡錯,哪裡可以改,好的演算法可以自動調優,機器學習,不斷自動調整參數達到最優,但是通常可能需要你不斷手工去看,去看badcase,想想是什麼參數因素導致的,改一下是否變好?是否引入新的bad case?
第四:校驗!
校驗一種是人工做盲測,A演算法,B演算法的結果混淆,選案例集,看哪個效果好;或A參數、B參數混淆,同理測試。通過盲測選擇認為更合理的演算法、更適宜的參數.
以上是個人認為,做好推薦演算法的步驟
下面說一下常見問題
1、以為有了演算法就ok了,不對參數優化,不做後續的校驗和數據跟蹤,效果不好就說演算法有問題,這種基本屬於工作態度的問題了。
2、對樣本數據的篩選有問題,或缺乏必要的噪音篩查,導致結果噪音多。比如你有個推廣位天天擺著,導致用戶點擊多,然後導致後台行為數據里它和誰的關聯都高,然後不管用戶到哪裡都推薦這個玩意,這就是沒有足夠篩查。
3、熱度影響
我說一下最簡單的推薦演算法
同時選擇了A和B的人數作為A與B的關聯度。
這個實現最簡單,也最容易理解,但是很容易受熱度影響
我曾經注意過某個熱門圖書電商網站,推薦的關聯書籍一水的熱門書籍,就是這個問題。
這些是非常簡單但是又非常容易出現的,關聯誤區。
4、過於求全
現在也遇到一些朋友,一提到推薦演算法或者推薦系統,就說我這個要考慮,那個要考慮,不管是行為記錄,還是用戶特徵,以至於各種節日效應,等等等等,想通過一個推薦系統完全搞定,目標很大,所以動作就極慢,構思洋洋灑灑做了很多,實現起來無從下手,或者難以寸進;我覺得,還是量力而行,從最容易下手的地方開始,先做到比沒有強,然後根據不斷地數據校驗跟蹤,逐漸加入其他考慮因素,步步前進,而不要一上來就定一個宏偉的龐大的目標;此外要考慮實現成本和開發周期,對於大部分技術實力沒有網路,騰訊,淘寶那麼強的公司而言,先把簡單的東西搞好,已經足夠有效了,然後在運營數據的基礎上逐次推進,會越來越好;有些公司是被自己宏大的目標搞的焦頭爛額,最後說,哎,沒牛人搞不定啊。嗯,反正他們的目標,我顯著是搞不定的。就這些,希望有所幫助
『肆』 跪求各位數學專業計算機專業高手,列舉一下智能優化演算法,以及目前最流行的智能優化演算法。
智能優化演算法有:遺傳演算法,禁忌搜索,模擬退火,蟻群演算法,粒子群優化演算法,動態進化等等。學習這些演算法主要是用來計算,解決計算機方面的一些NP問題的最佳方法。智能的意思是模擬生物物種的智慧。這個方向的實際應用也很強。只是比較復雜非常難學。
『伍』 優化演算法是什麼
智能優化演算法是一種啟發式優化演算法,包括遺傳演算法、蟻群演算法、禁忌搜索演算法、模擬退火演算法、粒子群演算法等。·智能優化演算法一般是針對具體問題設計相關的演算法,理論要求弱,技術性強。一般,我們會把智能演算法與最優化演算法進行比較,相比之下,智能演算法速度快,應用性強。
群體智能優化演算法是一類基於概率的隨機搜索進化演算法,各個演算法之間存在結構、研究內容、計算方法等具有較大的相似性。
各個群體智能演算法之間最大不同在於演算法更新規則上,有基於模擬群居生物運動長更新的(如PSO,AFSA與SFLA),也有根據某種演算法機理設置更新規則(如ACO)。
(5)推薦優化演算法擴展閱讀:
優化演算法有很多,關鍵是針對不同的優化問題,例如可行解變數的取值(連續還是離散)、目標函數和約束條件的復雜程度(線性還是非線性)等,應用不同的演算法。 對於連續和線性等較簡單的問題,可以選擇一些經典演算法,例如梯度、Hessian 矩陣、拉格朗日乘數、單純形法、梯度下降法等;而對於更復雜的問題,則可考慮用一些智能優化演算法。
『陸』 網站優化的234項演算法有哪些
在SEO業內人士都知道,影響網路排名的因素有高達234項!如果一下子答慶寬說出來,都要好幾分鍾清亮,那真正我們日常工作中能否全部都顧及到呢?非常難! 網路的演算法有分大演算法和細微的小演算法,大演算法一般不會有太大的變化而小演算法就會隨時變動。其實萬變不離其宗不管網路怎麼變,一個核心永遠不會變:那就是用戶的需求。如果我們把用戶的需求做好了,我們就可以閃電式的坐在比賽的終點等著網路跑過來。記住:我們所做的任何事情有關SEO的事,都要圍繞用戶需求來做。
在學習234項演算法前,要知道網路有8種常見的演算法:
超鏈接演算法: 可以識別誰最權威。
綠蘿演算法 打擊買賣鏈接
原創星火演算法 支持原創和優質的站點
起源演算法 針對個人差梁優質原創
綠蘿演算法 加大對外鏈軟文的力度
冰桶演算法 強度強行彈窗對用戶體驗的影響
石榴演算法 提高頁面的質量
網路星火計劃 保護原創的「星火計劃」
http://www.luoyuseo.com/?p=30
『柒』 推薦演算法小結
輸入 :與用戶相關的包含眾多特徵(feature)的數據:
用戶的注冊信息(職業、年齡、性別等 顯信息),行為信息(使用功能、有效使用時長等 隱信息)。
輸出 :推薦給用戶的功能列表(根據得分高低排序)
函數 : 傳統演算法 、 機器學習演算法 (Machine Learning)、 深度學習演算法 (Deep Learning)
基於流行度的演算法非常簡單粗暴,類似於各大新聞、微博熱榜等,根據VV、UV、日均PV或分享率等數據來按某種熱度(加權)排序來推薦給用戶。
訪問次數 (VV):記錄1天內所有訪客訪問了該網站多少次,相同的訪客有可能多次訪問該網站,且訪問的次數累加。
獨立訪客 (UV):記錄1天內所有訪客訪問了該網站多少次,雖然相同訪客能多次訪問網站,但只計算為1個獨立訪客。
PV訪問量 (Page View):即頁面訪問量,每打開一次頁面或者刷新一次頁面,PV值+1。
優點:該演算法簡單,適用於剛注冊的新用戶
缺點:無法針對用戶提供個性化的推薦
改進:基於該演算法可做一些優化,例如加入用戶分群的流行度進行排序,通過把熱榜上的體育內容優先推薦給體育迷,把政要熱文推給熱愛談論政治的用戶。
基於用戶的協同過濾推薦演算法 (UserCF):針對目標用戶(A),先通過興趣、愛好或行為習慣找到與他相似的「其他用戶」(BCD...),然後把BCD...喜歡的並且A沒有瀏覽過的物品或功能推給A。
基於物品的協同過濾推薦演算法 (ItemCF):例如由於我之前看過張藝謀導演的《英雄》這部電影,會給我推薦《紅高粱》、《歸來》等同導演電影。
1)分析各個用戶對物品的評價,通過瀏覽記錄、購買記錄等得到用戶的隱性評分;
2)根據用戶對物品的隱性評分計算得到所有用戶之間的相似度;
3)選出與目標用戶最相似的K個用戶;
4)將這K個用戶隱性評分最高並且目標用戶又沒有瀏覽過的物品推薦給目標用戶。
優點:
基於用戶的協同過濾推薦演算法是給目標用戶推薦那些和他有共同興趣的用戶喜歡的物品,所以該演算法推薦較為社會化,即推薦的物品是與用戶興趣一致的那個群體中的熱門物品;
適於物品比用戶多、物品時效性較強的情形,否則計算慢;
能實現跨領域、驚喜度高的結果。
缺點:
在很多時候,很多用戶兩兩之間的共同評分僅有幾個,也即用戶之間的重合度並不高,同時僅有的共同打了分的物品,往往是一些很常見的物品,如票房大片、生活必需品;
用戶之間的距離可能變得很快,這種離線演算法難以瞬間更新推薦結果;
推薦結果的個性化較弱、較寬泛。
改進:
兩個用戶對流行物品的有相似興趣,絲毫不能說明他們有相似的興趣,此時要增加懲罰力度;
如果兩個用戶同時喜歡了相同的物品,那麼可以給這兩個用戶更高的相似度;
在描述鄰居用戶的偏好時,給其最近喜歡的物品較高權重;
把類似地域用戶的行為作為推薦的主要依據。
1)分析各個用戶對物品的瀏覽記錄;
2)依據瀏覽記錄分析得出所有物品之間的相似度;
3)對於目標用戶評價高的物品,找出與之相似度最高的K個物品;
4)將這K個物品中目標用戶沒有瀏覽過的物品推薦給目標用戶
優點:
基於物品的協同過濾推薦演算法則是為目標用戶推薦那些和他之前喜歡的物品類似的物品,所以基於物品的協同過濾推薦演算法的推薦較為個性,因為推薦的物品一般都滿足目標用戶的獨特興趣。
物品之間的距離可能是根據成百上千萬的用戶的隱性評分計算得出,往往能在一段時間內保持穩定。因此,這種演算法可以預先計算距離,其在線部分能更快地生產推薦列表。
應用最廣泛,尤其以電商行業為典型。
適於用戶多、物品少的情形,否則計算慢
推薦精度高,更具個性化
傾向於推薦同類商品
缺點:
不同領域的最熱門物品之間經常具有較高的相似度。比如,基於本演算法,我們可能會給喜歡聽許嵩歌曲的同學推薦汪峰的歌曲,也就是推薦不同領域的暢銷作品,這樣的推薦結果可能並不是我們想要的。
在物品冷啟動、數據稀疏時效果不佳
推薦的多樣性不足,形成信息閉環
改進:
如果是熱門物品,很多人都喜歡,就會接近1,就會造成很多物品都和熱門物品相似,此時要增加懲罰力度;
活躍用戶對物品相似度的貢獻小於不活躍的用戶;
同一個用戶在間隔很短的時間內喜歡的兩件商品之間,可以給予更高的相似度;
在描述目標用戶偏好時,給其最近喜歡的商品較高權重;
同一個用戶在同一個地域內喜歡的兩件商品之間,可以給予更高的相似度。
(相似度計算:餘弦相似度、Jaccard系數、皮爾森相關系數等)
常見經典 ML 分類演算法:
邏輯回歸 (Logistics Regression)
支持向量機 (SVM)
隨機森林 (Random Forest)
提升類演算法 (Boosting):Adaboost、GBDT、XGboost
一般處理流程:數據處理 -> 特徵工程 -> 模型選擇 -> 交叉驗證 -> 模型選擇與模型融合
特徵清洗 :剔除不可信樣本,預設值極多的欄位不予考慮
特徵預處理 :單個特徵(歸一化,離散化,缺失值補全,數據變換),多個特徵(PCA/LDA降維,特徵選擇)
使用工具 :pandas(python開源庫)
模型選擇與模型融合 :根據交叉驗證得分選擇前幾名模型,然後進行模型融合(Bagging、Boosting、Stacking)
DL 優勢 :ML 中特徵工程是十分重要並且要根據行業經驗確定,DL 可以自己從數據中學習特徵。DL 能自動對輸入的低階特徵進行組合、變換,得到高階特徵。對於公司產品應用領域來說,用戶的注冊信息(職業、年齡、性別等 顯信息),行為信息(使用功能、有效使用時長等 隱信息)。這些就可以作為低階特徵輸入。
RNN系列 (處理文本數據)
CNN系列 (處理圖像數據)
DNN (處理一般性分類)