【寫在前面】
作為一名終身學(xué)習(xí)實踐者萍倡,我持之以恒地學(xué)習(xí)各種深度學(xué)習(xí)和機器學(xué)習(xí)的新知識列敲。一個無聊的假日里我突然想到:反正一樣要記筆記戴而,為什么不把我學(xué)習(xí)的筆記寫成博客供大家一起交流呢翩蘸?于是催首,我就化身數(shù)據(jù)女俠,打算用博客分享的方式開啟我的深度學(xué)習(xí)深度學(xué)習(xí)之旅秧耗。本文僅供學(xué)習(xí)交流使用舶治,侵權(quán)必刪,不用于商業(yè)目的珠闰,轉(zhuǎn)載須注明出處瘫辩。
【學(xué)習(xí)筆記】
之前我們以邏輯回歸 (logistic regression) 為例介紹了神經(jīng)網(wǎng)絡(luò)(吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (上))伐厌,但它并沒有隱藏層,所以并不算嚴(yán)格意義上的神經(jīng)網(wǎng)絡(luò)八酒。在本文中,讓我們隨著Andrew一起深化神經(jīng)網(wǎng)絡(luò)画饥,在sigmoid之前再增加一些ReLU神經(jīng)元浊猾。最后我們會以瘋狂收到AI科學(xué)家迷戀的可愛貓咪圖案為例葫慎,用深度學(xué)習(xí)建立一個貓咪圖案的識別模型。不過在這之前艰额,讓我們來看一下除了上次說到的sigmoid和ReLU之外柄沮,還有什么激活函數(shù)废岂、他們之間又各有什么優(yōu)劣——
激活函數(shù) Activation Functions
1) sigmoid
除了在輸出層(當(dāng)輸出是{0,1}的binary classification時)可能會用到之外湖苞,隱藏層中很少用到sigmoid,因為它的mean是0.5哈扮,同等情況下用均值為0的tanh函數(shù)取代滑肉。
2) tanh
其實就是sigmoid的shifted版本,但輸出從(0, 1)變?yōu)?-1, 1)问畅,所以下一層的輸入是centered护姆,更受歡迎掏击。
3) ReLU (Rectified Linear Unit)
在吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (上)中提到過ReLU激活函數(shù)砚亭,它在深度學(xué)習(xí)中比sigmoid和tanh更常用。這是因為當(dāng)激活函數(shù)的輸入z的值很大或很小的時候添祸,sigmoid和tanh的梯度非常小刃泌,這會大大減緩梯度下降的學(xué)習(xí)速度署尤。所以與sigmoid和tanh相比曹体,ReLU的訓(xùn)練速度要快很多混坞。
4) Leaky ReLU
Leaky ReLU比ReLU要表現(xiàn)得稍微好一丟丟但是實踐中大家往往都用ReLU。
從淺神經(jīng)網(wǎng)絡(luò)到深神經(jīng)網(wǎng)絡(luò)
最開始的邏輯回歸的例子中啥酱,并沒有隱藏層镶殷。在接下來的課程中微酬,Andrew分別介紹了1個隱藏層、2個隱藏層和L個隱藏層的神經(jīng)網(wǎng)絡(luò)滓走。但是只要把前向傳播和反向傳播搞明白了帽馋,再加上之后會講述的一些小撇步绽族,就會發(fā)現(xiàn)其實都是換湯不換藥吧慢。大家準(zhǔn)備好了嗎?和我一起深呼吸再一頭扎進(jìn)深度學(xué)習(xí)的海洋吧~
一般輸入層是不計入神經(jīng)網(wǎng)絡(luò)的層數(shù)的匈仗,如果一個神經(jīng)網(wǎng)絡(luò)有L層锚沸,那么就意味著它有L-1個隱藏層和1個輸出層涕癣。我們可以觀察到輸入層和輸出層坠韩,但是不容易觀察到中間數(shù)據(jù)是怎么變化的炼列,因此在輸入和輸出層之間的部分叫隱藏層俭尖。
訓(xùn)練一個深神經(jīng)網(wǎng)絡(luò)大致分為以下步驟(吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (上)也有詳細(xì)說明):
1. 定義神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)(超參數(shù))
2. 初始化參數(shù)
3. 循環(huán)迭代
? ? 3.1 在前向傳播中稽犁,分為linear forward和activation forward已亥。在linear forward中俱笛,Z[l]=W[l]A[l?1]+b[l]传趾,其中A[0]=X浆兰;在activation forward中镊讼,A[l]=g(Z[l])。期間要儲存W卸亮、b兼贸、Z的值吃溅。最后算出當(dāng)前的Loss决侈。
? ? 3.2 在反向傳播中赖歌,分為activation backward和linear backward。
? ? 3.3 更新參數(shù)孽亲。
下圖展現(xiàn)了一個L層的深度神經(jīng)網(wǎng)絡(luò)返劲、其中L-1個隱藏層都用的是ReLU激活函數(shù)的訓(xùn)練步驟和過程栖茉。
標(biāo)注聲明 Notations:
隨著神經(jīng)網(wǎng)絡(luò)的模型越來越深搔耕,我們會有L-1個隱藏層,每一層都用小寫的L即[l]標(biāo)注為上標(biāo)菩收。z是上一層的輸出(即這一層的輸入)的線性組合娜饵,a是這一層通過激活函數(shù)對z的非線性變化官辈,也叫激活值 (activation values)拳亿。訓(xùn)練數(shù)據(jù)中有m個樣本肺魁,每一個樣本都用(i)來標(biāo)注為上標(biāo)。每一個隱藏層l里都有n[l](上標(biāo)內(nèi)是小寫的L不是1)個神經(jīng)元寂呛,每一個神經(jīng)元都用i標(biāo)注為下標(biāo)贷痪。
超參數(shù)
隨著我們的深度學(xué)習(xí)模型越來越復(fù)雜,我們要學(xué)習(xí)區(qū)分普通參數(shù) (Parameters) 和超參數(shù) (Hyperparameters)东亦。 在上圖的標(biāo)注聲明中出現(xiàn)的W和b是普通的參數(shù)嫉鲸,而超參數(shù)是指:
學(xué)習(xí)速率 (learning rate) alpha、循環(huán)次數(shù) (# iterations)甜紫、隱藏層層數(shù) (# hidden layers) L、每隱藏層中的神經(jīng)元數(shù)量 (size of the hidden layers) n[l] ——上標(biāo)內(nèi)是小寫的L不是1东帅、激活函數(shù) (choice of activation functions) g[l] ——上標(biāo)內(nèi)是小寫的L不是1。除了這些超參數(shù)之外媚朦,之后還會學(xué)習(xí)到以下超參數(shù):動量 (momentum)的圆、小批量更新的樣本數(shù) (minibatch size)店归、正則化系數(shù) (regularization weight),等等遇汞。
隨機初始化 Random Initialization
吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (上)中的邏輯回歸 (logistic regression) 中沒有隱藏層,所以將W直接初始化為0并無大礙。但是在初始化隱藏層的W時如果將每個神經(jīng)元的權(quán)重都初始化為0躏结,那么在之后的梯度下降中媳拴,每一個神經(jīng)元的權(quán)重都會有相同的梯度和更新兆览,這樣的對稱在梯度下降中永遠(yuǎn)無法打破抬探,如此就算隱藏層中有一千一萬個神經(jīng)元小压,也只同于一個神經(jīng)元。所以缠导,為了打破這種對稱的魔咒僻造,在初始化參數(shù)時往往會加入一些微小的抖動髓削,即用較小的隨機數(shù)來初始化W立膛,偏置項b可以初始化為0或者同樣是較小的隨機數(shù)梯码。在Python中轩娶,可以用np.random.randn(a,b) * 0.01來隨機地初始化a*b的W矩陣鳄抒,并用np.zeros((a, 1))來初始化a*1的b矩陣。
為什么是0.01呢瓤鼻?同sigmoid和tanh中所說,數(shù)據(jù)科學(xué)家通常會從將W initialize為很小的隨機數(shù)清焕,防止訓(xùn)練的速度過緩秸妥。但是如果神經(jīng)網(wǎng)絡(luò)很深的話盹憎,0.01這樣小的數(shù)字未必最理想陪每。但是總體來說檩禾,人們還是傾向于從較小的參數(shù)開始訓(xùn)練盼产。
承接上面的超參數(shù)戏售,對于每個隱藏層中的神經(jīng)元數(shù)量,我們可以將這幾個超參數(shù)設(shè)定為layer_dims的array灌灾,如layer_dims = [n_x, 4,3,2,1] 說明輸入的X有n_x個特征搓译,第一層有4個神經(jīng)元,第二層有3個神經(jīng)元锋喜,第三層有2個,最后一個輸出單元嘿般。有一個容易搞錯的地方段标,就是W[l]是n[l]*n[l-1]的矩陣,b[l]是n[l]*1的矩陣炉奴。所以初始化W和b就可以寫成:
for l in range(1, L):
parameters["W"+str(l)] = np.random.randn(layer_dims[l],layer_dims[l-1])*0.01
parameters["b"+str(l)] =np.zeros((layer_dims[l],1))
詳見例2中的initialize_parameters_deep函數(shù)逼庞。
并不是很復(fù)雜有沒有!那么盆佣,下面我們一起跟著Andrew來看幾個神經(jīng)網(wǎng)絡(luò)的例子——
【例 1】用單個隱藏層的神經(jīng)網(wǎng)絡(luò)來分類平面數(shù)據(jù)
第三課的例子是Planar data classification with one hidden layer往堡,即幫助大家搭建一個上圖所示的淺神經(jīng)網(wǎng)絡(luò)(Shallow Neural Networks):一個4個單元的隱藏層 (tanh) 加一個sigmoid的輸出層械荷。
最后一步的prediction是用了0.5的cutoff虑灰,很簡單:
最后的決策邊界如下圖,在訓(xùn)練數(shù)據(jù)上的精確度為90%痹兜,是不是比logistic regression表現(xiàn)強多啦穆咐?可見logistic regression不能學(xué)習(xí)到數(shù)據(jù)中的非線性關(guān)系,而神經(jīng)網(wǎng)絡(luò)可以(哪怕是本例中一個非常淺的神經(jīng)網(wǎng)絡(luò))字旭。
其實本例中的模型也很簡單对湃,如果再復(fù)雜些可以做到更精確,但是可能會overfit遗淳,畢竟從上圖中可以看出現(xiàn)有的模型已經(jīng)抓住了數(shù)據(jù)中的大趨勢拍柒。下面嘗試了在隱藏層中設(shè)置不同個數(shù)的神經(jīng)元,來看模型的精確度和決策邊界是如何變化的:
Accuracy for 1 hidden units: 67.5 %
Accuracy for 2 hidden units: 67.25 %
Accuracy for 3 hidden units: 90.75 %
Accuracy for 4 hidden units: 90.5 %
Accuracy for 5 hidden units: 91.25 %
Accuracy for 20 hidden units: 90.0 %
Accuracy for 50 hidden units: 90.25 %
可以看到屈暗,在訓(xùn)練數(shù)據(jù)上拆讯,5個神經(jīng)元的精確度是最高的,而當(dāng)神經(jīng)元數(shù)超過20時养叛,決策邊界就顯示有overfitting的情況了种呐。不過沒事,之后會學(xué)習(xí)正則化 (regularization)弃甥,能使很復(fù)雜的神經(jīng)網(wǎng)絡(luò)都不會出現(xiàn)overfitting爽室。
這個例子的代碼很簡單,就不貼了淆攻。
【例 2】L層深度神經(jīng)網(wǎng)絡(luò)
第四節(jié)課的例子有三個:第一是一個ReLU+sigmoid的淺層神經(jīng)網(wǎng)絡(luò)阔墩,是為了后面的例子做鋪墊;第二個將其深化瓶珊,用了L-1個ReLU層啸箫,輸出層也是sigmoid;第三個例子就是用前兩個神經(jīng)網(wǎng)絡(luò)訓(xùn)練貓咪識別模型[吐血]艰毒。我將L層的模型和其貓咪識別器的訓(xùn)練過程精簡地說一下筐高。
設(shè)計神經(jīng)網(wǎng)絡(luò)與隨機初始化參數(shù)
下圖就是我們要搭建的L層神經(jīng)網(wǎng)絡(luò),不過在這之前丑瞧,讓我們先挑個lucky number方便以后重復(fù)訓(xùn)練結(jié)果^_^
np.random.seed(1)
其次柑土,讓我們設(shè)計一下我們的神經(jīng)網(wǎng)絡(luò)。因為激活函數(shù)已經(jīng)確定用ReLU了绊汹,所以在本例中我們只需設(shè)計layer_dims稽屏,就能確定輸入的維度、層數(shù)和每層的神經(jīng)元數(shù)西乖。
def initialize_parameters_deep(layer_dims):
? ? parameters = {}
? ? L = len(layer_dims) ? ? ? ? ? ? ? ? ? ? ?# 根據(jù)我們一開始設(shè)計的模型超參數(shù)狐榔,讀取L(其實是L+1)
? ? for l in range(1, L): ? ? ? ? ? ? ? ? ? ? ? # 設(shè)定W1到W(L-1)和b1和b(L-1)坛增,一共有L-1層(其實是L)
? ? ? ? parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l-1]) * 0.01
? ? ? ? parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))
? ? assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l-1]))
? ? assert(parameters['b' + str(l)].shape == (layer_dims[l], 1))
? ? return parameters
和具體的數(shù)據(jù)結(jié)合,就知道了輸入的維度和樣本的數(shù)量薄腻。假設(shè)我們的訓(xùn)練數(shù)據(jù)中有209張圖片收捣,每張都是64*64像素,那么輸入特征數(shù)n_x就是64*64*3 = 12288庵楷,m就是209罢艾,如下圖:
如果我們將W和b參數(shù)設(shè)為parameters,每一個初始化的W和b都是parameters這個list中的一個元素尽纽,那么L-1個循環(huán)隱藏層其實就是len(parameters)//2咐蚯。下圖是一個ReLU層加一個sigmoid層的一個loop,怎么將同樣的計算復(fù)制到我們的L層深度神經(jīng)網(wǎng)絡(luò)中呢弄贿?
前向傳播
前向傳播分為linear forward和activation forward春锋,前者計算Z,后者計算A=g(Z)差凹,g視激活函數(shù)的不同而不同期奔。因為activation forward這步中包括了linear的值,所以名為linear_activation_forward函數(shù)直奋。由于反向傳播的梯度計算中會用到W能庆、b、A的值脚线,所以我們將每一個iteration中將每個神經(jīng)元的這些值暫時儲存在caches這個大列表中搁胆,再在下一輪循環(huán)中覆蓋掉。代碼如下:
def linear_forward(A, W, b):
? ? Z = np.dot(W, A) + b
? ? assert(Z.shape == (W.shape[0], A.shape[1]))
? ? cache = (A, W, b)
? ? return Z, cachedef linear_activation_forward(A_prev, W, b, activation):
? ? if activation == "sigmoid":
? ? ? ? Z, linear_cache = linear_forward(A_prev, W, b)
? ? ? ? A, activation_cache = sigmoid(Z)
? ? elif activation == "relu":
? ? ? ? Z, linear_cache = linear_forward(A_prev, W, b)
? ? ? ? A, activation_cache = relu(Z)
? ? assert (A.shape == (W.shape[0], A_prev.shape[1]))
? ? cache = (linear_cache, activation_cache)
? ? return A, cache
在定義了每一個神經(jīng)單元的linear-activation forward之后邮绿,我們來定義這個L層神經(jīng)網(wǎng)絡(luò)的前向傳播:
def L_model_forward(X, parameters):
? ? caches = []
? ? A = X
? ? L = len(parameters) // 2? ? ? ? ? ? ? ? ? # 因為之前設(shè)定的parameters包含了每一層W和b的初始值渠旁,所以層數(shù)是這個列表長度的一半
? ? for l in range(1, L): ? ? ? ? ? ? ? ? ? ? ? ? ?# L-1個隱藏層用ReLU激活函數(shù)
? ? ? ? A_prev = A
? ? ? ? A, cache = linear_activation_forward(A_prev, parameters['W' + str(l)], parameters['b' + str(l)], activation = "relu")
? ? ? ? caches.append(cache)
? ? AL, cache = linear_activation_forward(A, parameters['W' + str(L)], parameters['b' + str(L)], activation = "sigmoid") ? ? ? ? ? ?# 第L個層用sigmoid函數(shù)
? ? caches.append(cache)
? ? assert(AL.shape == (1,X.shape[1]))
? ? return AL, caches
前向傳播的盡頭是計算當(dāng)前參數(shù)下的損失~不過正如在后面L_model_backward函數(shù)中看到的,我們這里直接計算dL/dAL船逮,并不計算L顾腊,這里計算cost是為了在訓(xùn)練過程檢查代價是不是在穩(wěn)定下降,以確保我們使用了合適的學(xué)習(xí)率挖胃。
def compute_cost(AL, Y):
? ? m = Y.shape[1]
? ? cost = -np.sum(Y*np.log(AL) + (1-Y)*np.log(1-AL))/m
? ? cost = np.squeeze(cost) ? ? ? ? ? ? ? ? ? ? ? ? ? ?# 將類似于?[[17]] 的cost變成 17
? ? assert(cost.shape == ())
? ? return cost
反向傳播
反向傳播和前向傳播的函數(shù)設(shè)計是對稱的杂靶,但是會比前向傳播復(fù)雜一丟丟,需要小心各種線性代數(shù)中的運算規(guī)則——這也是為什么在前向傳播中我們都在return前加入了維度檢查(assert + shape)酱鸭。下圖顯示了每一個神經(jīng)元在反向傳播中的輸入和輸出÷鹂澹現(xiàn)在我們看到之前在前向傳播中緩存的用處了。如果我不儲存W和Z的值凹髓,我就沒有辦法在反向線性傳播中計算dW烁登,db同理。
def linear_backward(dZ, cache):
? ? A_prev, W, b = cache
? ? m = A_prev.shape[1]
? ? dW = np.dot(dZ, A_prev.T)/m
? ? db = np.sum(dZ, axis=1, keepdims=True)/m
? ? dA_prev = np.dot(W.T, dZ)
? ? assert (dA_prev.shape == A_prev.shape)
? ? assert (dW.shape == W.shape)
? ? assert (db.shape == b.shape)
? ? return dA_prev, dW, db
上述的公式用線性代數(shù)表示為下圖:
Andrew貼心地為大家提供了寫好的函數(shù):relu_backward和sigmoid_backward蔚舀,如果我們自己寫的話饵沧,需要在前向傳播中儲存A的值锨络,否則在很多反向傳播中就不知道dA/dZ,因為有些激活函數(shù)的導(dǎo)數(shù)是A的函數(shù)狼牺,比如sigmoid函數(shù)和tanh函數(shù)羡儿。
def linear_activation_backward(dA, cache, activation):
? ? linear_cache, activation_cache = cache
? ? if activation == "relu":
? ? ? ? dZ = relu_backward(dA, activation_cache)
? ? ? ? dA_prev, dW, db = linear_backward(dZ, linear_cache)
? ? elif activation == "sigmoid":
? ? ? ? dZ = sigmoid_backward(dA, activation_cache)
? ? ? ? dA_prev, dW, db = linear_backward(dZ, linear_cache)
? ? return dA_prev, dW, db
同前向傳播一樣,我們將dL/dAL反向傳播锁右,通過每一層的linear-activation backward構(gòu)建整個完整的反向傳播體系:
def L_model_backward(AL, Y, caches):
? ? grads = {}
? ? L = len(caches) # 層數(shù)
? ? m = AL.shape[1]
? ? Y = Y.reshape(AL.shape) # 改變Y的維度失受,確保其與AL的維度統(tǒng)一
? ? dAL = - (np.divide(Y, AL) - np.divide(1 - Y, 1 - AL)) # 代價函數(shù)對輸出層輸出AL的導(dǎo)數(shù)讶泰,就不計算具體的cost了
? ? current_cache = caches[L-1]
? ? grads["dA" + str(L)], grads["dW" + str(L)], grads["db" + str(L)] = linear_activation_backward(dAL, current_cache, activation = "sigmoid")
? ? for l in reversed(range(L-1)):
? ? ? ? current_cache = caches[l]
? ? ? ? dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads["dA"+str(l+2)], current_cache, activation = "relu")
? ? ? ? grads["dA" + str(l + 1)] = dA_prev_temp
? ? ? ? grads["dW" + str(l + 1)] = dW_temp
? ? ? ? grads["db" + str(l + 1)] = db_temp
? ? return grads
一般現(xiàn)實工作中不會用線性代數(shù)如此折磨你咏瑟,就算要自己一步一步這么寫,也可以加入梯度檢查等等來為你增添信心仇让,具體以后再分享~
參數(shù)更新
至此我們已經(jīng)在一個循環(huán)中計算出了當(dāng)前W和b的梯度全闷,最后就是用梯度下降的定義更新參數(shù)逛薇。在下一個例子中我們會看到如何用我們已經(jīng)寫好的每一步的函數(shù),使用for loop執(zhí)行梯度下降余寥,最后得到訓(xùn)練好的模型。
def update_parameters(parameters, grads, learning_rate):
? ? L = len(parameters) // 2
? ? for l in range(L):
? ? ? ? parameters["W" + str(l+1)] = parameters["W" + str(l+1)] - learning_rate*grads["dW" + str(l + 1)]
? ? ? ? parameters["b" + str(l+1)] = parameters["b" + str(l+1)] - learning_rate*grads["db" + str(l + 1)]
? ? return parameters
【例 3】繼續(xù)AI科學(xué)家對貓的執(zhí)念……
下面我們用例2中的L層深度神經(jīng)網(wǎng)絡(luò)來識別一張圖是不是貓咪[捂臉]悯森,因為代碼有點多所以分成了2和3的兩個例子宋舷。
假設(shè)train_x_orig是我們原始的輸入,已經(jīng)將圖片像素數(shù)據(jù)提取并flatten為適合訓(xùn)練的數(shù)據(jù)瓢姻,這里我們將每一個樣本從64*64*3的輸入變成一個12288*1的矢量祝蝠,然后將值標(biāo)準(zhǔn)化到0-1之間:
train_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1).T
train_x = train_x_flatten/255.
設(shè)計一個神經(jīng)網(wǎng)絡(luò):layers_dims = [12288, 20, 7, 5, 1],即每個樣本有12288個像素輸入幻碱,第一層20個ReLU神經(jīng)元绎狭,第二層7個,第三層5個褥傍,最后一個sigmoid儡嘶。
終于可以調(diào)用我們之前辛辛苦苦寫好的函數(shù)啦!之前寫的函數(shù)都是每一個iteration中的每一步驟恍风,現(xiàn)在我們將每一個loop循環(huán)num_iterations次蹦狂。
parameters = initialize_parameters_deep(layers_dims)
for i in range(0, num_iterations):
? ? AL, caches = L_model_forward(X, parameters)
? ? cost = compute_cost(AL, Y)
? ? grads = L_model_backward(AL, Y, caches)
? ? parameters = update_parameters(parameters, grads, learning_rate)
這里的parameters就是訓(xùn)練好的參數(shù),我們就可以用它來預(yù)測新的萌萌噠貓貓啦朋贬。
讀取一張num_px*num_px圖片的像素再將其RGB轉(zhuǎn)換為num_px*num_px*3的方法凯楔,請注意這里的圖片尺寸需和訓(xùn)練數(shù)據(jù)中的一樣:
fname = "images/" + my_image
np.array(ndimage.imread(fname, flatten=False))
scipy.misc.imresize(image, size=(num_px,num_px)).reshape((num_px*num_px*3,1))
最后我們的模型在訓(xùn)練數(shù)據(jù)上的精確度為98.6%。然后我們就可以用類似于predict(test_x, test_y, parameters)這樣的方法就能預(yù)測這個圖片是不是一個喵喵啦兄世!最后得到在訓(xùn)練數(shù)據(jù)上的精確度為80%啼辣,但是讓我們來看看剩下20%沒有正確預(yù)測的樣本是什么樣子的……
除了第五張姿勢扭捏的貓貓外,2和4中的貓貓我們也沒有很好地識別出來御滩。不過不用擔(dān)心鸥拧,卷積神經(jīng)網(wǎng)絡(luò) (Convolutional Neural Networks) 會比image2vector更適合于處理圖片數(shù)據(jù)党远,所以敬請期待以后的更新!