深度学习基础(CNN详解以及训练过程1)
深度學(xué)習(xí)是一個(gè)框架,包含多個(gè)重要算法:
Convolutional Neural Networks(CNN)卷積神經(jīng)網(wǎng)絡(luò)
AutoEncoder自動(dòng)編碼器
Sparse Coding稀疏編碼
Restricted Boltzmann Machine(RBM)限制波爾茲曼機(jī)
Deep Belief Networks(DBN)深信度網(wǎng)絡(luò)
Recurrent neural Network(RNN)多層反饋循環(huán)神經(jīng)網(wǎng)絡(luò)神經(jīng)網(wǎng)絡(luò)
對(duì)于不同問題(圖像,語(yǔ)音,文本),需要選用不同網(wǎng)絡(luò)模型比如CNN RESNET等才能達(dá)到更好效果。
今天來(lái)講最基礎(chǔ)的CNN網(wǎng)絡(luò)。
可以不可以模仿人類大腦的這個(gè)特點(diǎn),構(gòu)造多層的神經(jīng)網(wǎng)絡(luò),較低層的識(shí)別初級(jí)的圖像特征,若干底層特征組成更上一層特征,最終通過多個(gè)層級(jí)的組合,最終在頂層做出分類呢?答案是肯定的,這也是許多深度學(xué)習(xí)算法(包括CNN)的靈感來(lái)源。
CNN網(wǎng)絡(luò)介紹
卷積神經(jīng)網(wǎng)絡(luò)是一種多層神經(jīng)網(wǎng)絡(luò),擅長(zhǎng)處理圖像特別是大圖像的相關(guān)機(jī)器學(xué)習(xí)問題。
卷積網(wǎng)絡(luò)通過一系列方法,成功將數(shù)據(jù)量龐大的圖像識(shí)別問題不斷降維,最終使其能夠被訓(xùn)練。CNN最早由Yann LeCun提出并應(yīng)用在手寫字體識(shí)別上(MINST)。LeCun提出的網(wǎng)絡(luò)稱為L(zhǎng)eNet,其網(wǎng)絡(luò)結(jié)構(gòu)如下:
這是一個(gè)最典型的卷積網(wǎng)絡(luò),由卷積層、池化層、全連接層組成。其中卷積層與池化層配合,組成多個(gè)卷積組,逐層提取特征,最終通過若干個(gè)全連接層完成分類。
卷積層完成的操作,可以認(rèn)為是受局部感受野概念的啟發(fā),而池化層,主要是為了降低數(shù)據(jù)維度。
綜合起來(lái)說(shuō),CNN通過卷積來(lái)模擬特征區(qū)分,并且通過卷積的權(quán)值共享及池化,來(lái)降低網(wǎng)絡(luò)參數(shù)的數(shù)量級(jí),最后通過傳統(tǒng)神經(jīng)網(wǎng)絡(luò)完成分類等任務(wù)。
降低參數(shù)量級(jí)
為什么要降低參數(shù)量級(jí)?從下面的例子就可以很容易理解了。
如果我們使用傳統(tǒng)神經(jīng)網(wǎng)絡(luò)方式,對(duì)一張圖片進(jìn)行分類,那么,我們把圖片的每個(gè)像素都連接到隱藏層節(jié)點(diǎn)上,那么對(duì)于一張1000x1000像素的圖片,如果我們有1M隱藏層單元,那么一共有10^12個(gè)參數(shù),這顯然是不能接受的。(如下圖所示)
但是我們?cè)贑NN里,可以大大減少參數(shù)個(gè)數(shù),我們基于以下兩個(gè)假設(shè):
1)最底層特征都是局部性的,也就是說(shuō),我們用10x10這樣大小的過濾器就能表示邊緣等底層特征
2)圖像上不同小片段,以及不同圖像上的小片段的特征是類似的,也就是說(shuō),我們能用同樣的一組分類器來(lái)描述各種各樣不同的圖像
基于以上兩個(gè),假設(shè),我們就能把第一層網(wǎng)絡(luò)結(jié)構(gòu)簡(jiǎn)化如下:
我們用100個(gè)10x10的小過濾器,就能夠描述整幅圖片上的底層特征。
卷積(Convolution)
卷積運(yùn)算的定義如下圖所示:
如圖所示,我們有一個(gè)5x5的圖像,我們用一個(gè)3x3的卷積核:
1 0 1
0 1 0
1 0 1
來(lái)對(duì)圖像進(jìn)行卷積操作(可以理解為有一個(gè)滑動(dòng)窗口,把卷積核與對(duì)應(yīng)的圖像像素做乘積然后求和),得到了3x3的卷積結(jié)果。
這個(gè)過程我們可以理解為我們使用一個(gè)過濾器(卷積核)來(lái)過濾圖像的各個(gè)小區(qū)域,從而得到這些小區(qū)域的特征值。
在實(shí)際訓(xùn)練過程中,卷積核的值是在學(xué)習(xí)過程中學(xué)到的。
在具體應(yīng)用中,往往有多個(gè)卷積核,可以認(rèn)為,每個(gè)卷積核代表了一種圖像模式,如果某個(gè)圖像塊與此卷積核卷積出的值大,則認(rèn)為此圖像塊十分接近于此卷積核。如果我們?cè)O(shè)計(jì)了6個(gè)卷積核,可以理解:我們認(rèn)為這個(gè)圖像上有6種底層紋理模式,也就是我們用6中基礎(chǔ)模式就能描繪出一副圖像。以下就是24種不同的卷積核的示例:
池化(Pooling)
池化聽起來(lái)很高深,其實(shí)簡(jiǎn)單的說(shuō)就是下采樣。池化的過程如下圖所示:
上圖中,我們可以看到,原始圖片是20x20的,我們對(duì)其進(jìn)行下采樣,采樣窗口為10x10,最終將其下采樣成為一個(gè)2x2大小的特征圖。
之所以這么做的原因,是因?yàn)榧词棺鐾炅司矸e,圖像仍然很大(因?yàn)榫矸e核比較?。?,所以為了降低數(shù)據(jù)維度,就進(jìn)行下采樣。
之所以能這么做,是因?yàn)榧词箿p少了許多數(shù)據(jù),特征的統(tǒng)計(jì)屬性仍能夠描述圖像,而且由于降低了數(shù)據(jù)維度,有效地避免了過擬合。
在實(shí)際應(yīng)用中,池化根據(jù)下采樣的方法,分為最大值下采樣(Max-Pooling)與平均值下采樣(Mean-Pooling)。
全連接層(fully connected layers,F(xiàn)C)
在整個(gè)卷積神經(jīng)網(wǎng)絡(luò)中起到“分類器”的作用。如果說(shuō)卷積層、池化層和激活函數(shù)層等操作是將原始數(shù)據(jù)映射到隱層特征空間的話,全連接層則起到將學(xué)到的“分布式特征表示”映射到樣本標(biāo) 記空間的作用。在實(shí)際使用中,全連接層可由卷積操作實(shí)現(xiàn):對(duì)前層是全連接的全連接層可以轉(zhuǎn)化為卷積核為1x1的卷積;而前層是卷積層的全連接層可以轉(zhuǎn)化為卷積核為hxw的全局卷積,h和w分別為前層卷積結(jié)果的高和寬。
全連接層的實(shí)現(xiàn)
LeNet介紹
下面再回到LeNet網(wǎng)絡(luò)結(jié)構(gòu):
這回我們就比較好理解了,原始圖像進(jìn)來(lái)以后,先進(jìn)入一個(gè)卷積層C1,由6個(gè)5x5的卷積核組成,卷積出28x28的圖像,然后下采樣到14x14(S2)。
接下來(lái),再進(jìn)一個(gè)卷積層C3,由16個(gè)5x5的卷積核組成,之后再下采樣到5x5(S4)。
注意,這里S2與C3的連接方式并不是全連接,而是部分連接,如下圖所示:
其中行代表S2層的某個(gè)節(jié)點(diǎn),列代表C3層的某個(gè)節(jié)點(diǎn)。
我們可以看出,C3-0跟S2-0,1,2連接,C3-1跟S2-1,2,3連接,后面依次類推,仔細(xì)觀察可以發(fā)現(xiàn),其實(shí)就是排列組合:
0 0 0 1 1 1
0 0 1 1 1 0
0 1 1 1 0 0
...
1 1 1 1 1 1
我們可以領(lǐng)悟作者的意圖,即用不同特征的底層組合,可以得到進(jìn)一步的高級(jí)特征,例如:/ + = ^ (比較抽象O(∩_∩)O~),再比如好多個(gè)斜線段連成一個(gè)圓等等。
最后,通過全連接層C5、F6得到10個(gè)輸出,對(duì)應(yīng)10個(gè)數(shù)字的概率。
最后說(shuō)一點(diǎn)個(gè)人的想法哈,我認(rèn)為第一個(gè)卷積層選6個(gè)卷積核是有原因的,大概也許可能是因?yàn)?~9其實(shí)能用以下6個(gè)邊緣來(lái)代表:
是不是有點(diǎn)道理呢,哈哈
然后C3層的數(shù)量選擇上面也說(shuō)了,是從選3個(gè)開始的排列組合,所以也是可以理解的。
其實(shí)這些都是針對(duì)特定問題的trick,現(xiàn)在更加通用的網(wǎng)絡(luò)的結(jié)構(gòu)都會(huì)復(fù)雜得多,至于這些網(wǎng)絡(luò)的參數(shù)如何選擇,那就需要我們好好學(xué)習(xí)了。
-----------------------------------------------------------------------------------------------------------------------
訓(xùn)練過程
卷積網(wǎng)絡(luò)在本質(zhì)上是一種輸入到輸出的映射,它能夠?qū)W習(xí)大量的輸入與輸出之間的映射關(guān)系,而不需要任何輸入和輸出之間的精確的數(shù)學(xué)表達(dá)式,只要用已知的模式對(duì)卷積網(wǎng)絡(luò)加以訓(xùn)練,網(wǎng)絡(luò)就具有輸入輸出對(duì)之間的映射能力。卷積網(wǎng)絡(luò)執(zhí)行的是有監(jiān)督訓(xùn)練,所以其樣本集是由形如:(輸入向量,理想輸出向量)的向量對(duì)構(gòu)成的。所有這些向量對(duì),都應(yīng)該是來(lái)源于網(wǎng)絡(luò)即將模擬的系統(tǒng)的實(shí)際“運(yùn)行”結(jié)果。它們可以是從實(shí)際運(yùn)行系統(tǒng)中采集來(lái)的。在開始訓(xùn)練前,所有的權(quán)都應(yīng)該用一些不同的小隨機(jī)數(shù)進(jìn)行初始化。“小隨機(jī)數(shù)”用來(lái)保證網(wǎng)絡(luò)不會(huì)因權(quán)值過大而進(jìn)入飽和狀態(tài),從而導(dǎo)致訓(xùn)練失??;“不同”用來(lái)保證網(wǎng)絡(luò)可以正常地學(xué)習(xí)。實(shí)際上,如果用相同的數(shù)去初始化權(quán)矩陣,則網(wǎng)絡(luò)無(wú)能力學(xué)習(xí)。
卷積神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過程與傳統(tǒng)神經(jīng)網(wǎng)絡(luò)類似,也是參照了反向傳播算法。
第一階段,向前傳播階段:
a)從樣本集中取一個(gè)樣本(X,Yp),將X輸入網(wǎng)絡(luò);
b)計(jì)算相應(yīng)的實(shí)際輸出Op。
在此階段,信息從輸入層經(jīng)過逐級(jí)的變換,傳送到輸出層。這個(gè)過程也是網(wǎng)絡(luò)在完成訓(xùn)練后正常運(yùn)行時(shí)執(zhí)行的過程。在此過程中,網(wǎng)絡(luò)執(zhí)行的是計(jì)算(實(shí)際上就是輸入與每層的權(quán)值矩陣相點(diǎn)乘,得到最后的輸出結(jié)果):
Op=Fn(…(F2(F1(XpW(1))W(2))…)W(n))
第二階段,向后傳播階段
a)算實(shí)際輸出Op與相應(yīng)的理想輸出Yp的差;
b)按極小化誤差的方法反向傳播調(diào)整權(quán)矩陣。
以上內(nèi)容摘自其他博客,由于我也沒有仔細(xì)了解這一塊,建議直接參考原博客。
手寫數(shù)字分類的例子,基于tensorflow
引自:使用TensorFlow編寫識(shí)別數(shù)字的CNN訓(xùn)練程序詳解
CNN的結(jié)構(gòu)
從網(wǎng)上借用一張圖片來(lái)表示一下,是一個(gè)有2層hidden layer的CNN。
程序中設(shè)置的一些參數(shù)是:
卷積層1:kernel_size [5, 5], stride=1, 4個(gè)卷積窗口
卷積層2:kernel_size [5, 5], stride=1, 6個(gè)卷積窗口
池化層: pool_size [2, 2], stride = 2
全連接層1: 1024個(gè)特征
MNIST數(shù)據(jù)的獲取
以往我們獲取MINIST的方式是:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
現(xiàn)在可以:
from tensorflow.contrib import learn
mnist = learn.datasets.load_dataset('mnist')
通過mnist.train, mnist.test, mnist.validation來(lái)獲得3個(gè)數(shù)據(jù)集,每個(gè)數(shù)據(jù)集里面的方法有(已train為例):
train.images 圖片數(shù)據(jù),二維數(shù)組 (55000, 784) dtype=float32
train.labels 圖片的分類, 一維數(shù)組,每個(gè)數(shù)值表示圖片對(duì)應(yīng)的數(shù)字
array([7, 3, 4, …, 5, 6, 8], dtype=uint8)
train.num_examples 圖片數(shù)量 55000
train.next_batch 下一批數(shù)據(jù)
n = train.next_batch
n[0] 是images n[1]是labels
第一次load MNIST數(shù)據(jù)的時(shí)候,會(huì)自動(dòng)從網(wǎng)上下載,放到當(dāng)前目錄的MNIST-data目錄下
第一種加載方式,有一個(gè)one-hot參數(shù),此時(shí)每個(gè)樣本的label,返回的是一個(gè)長(zhǎng)度10的vector,其中只有一個(gè)位置是1,其他都是0。 第二種方式,沒有這個(gè)參數(shù),如果需要的話,得直接調(diào)用datasets.mnist.read_data_sets
定義卷積層
在tf.contrib.layers里面有convolution2d,conv2d等方法,其實(shí)都是convolution方法的別名
convolution(inputs, num_outputs, kernel_size, stride=1, padding='SAME', data_format=None, rate=1, activation_fn=nn.relu, normalizer_fn=None, normalizer_params=None, weights_initializer=initializers.xavier_initializer(), weights_regularizer=None, biases_initializer=init_ops.zeros_initializer, biases_regularizer=None, reuse=None, variables_collections=None, outputs_collections=None, trainable=True, scope=None)
這個(gè)函數(shù)很強(qiáng)大,1到3維的卷積都支持。(我暫時(shí)只用過2維)
inputs: 輸入變量,是一個(gè)N+2維的Tensor
類型要求是一個(gè)Tensor,而我們一般訓(xùn)練的數(shù)據(jù)都是常量(比如mnist,load以后得到是python的數(shù)據(jù)類型,不是tf的),所以需要把用tf的方法做一下轉(zhuǎn)換,比如tf.reshape
為什么是N+2維呢,比如圖像,除了寬度和高度,實(shí)際上還有樣本數(shù)量和通道數(shù)量(如RGB3通道),所以多了2維。
inputs的格式,由date_format這個(gè)參數(shù)來(lái)覺得,比如2維,有NHWC和NCHW兩種。N是樣本數(shù)量,H高度,W寬度,C通道數(shù)。
num_outputs: 卷積filter的數(shù)量,或者說(shuō)提取的特征數(shù)量,比如5,10
kernel_size: 卷積核的大小,是N個(gè)參數(shù)的list,比如二維圖像,可以時(shí)候[10,10],如果參數(shù)值相同,用一個(gè)整數(shù)來(lái)表示也可以;
stride: 卷積步長(zhǎng),同樣是N個(gè)參數(shù)的序列,或者都相等的話,用一個(gè)整數(shù)來(lái)表示,默認(rèn)是1.
padding: 字符串格式,默認(rèn)SAME,可選’VALID’。(想問:這兩個(gè)效果上有多大差異?)
data_format: 字符串,指定inputs的格式
一維數(shù)據(jù):”NWC” (default) and “NCW”
二維數(shù)據(jù):”NHWC” (default) and “NCHW”
三維數(shù)據(jù):”NDHWC”
也就是,不指定的話,通道數(shù)都是最后一個(gè)參數(shù)。
rate: a sequence of N positive integers specifying the dilation rate to use for a’trous convolution. Can be a single integer to specify the same value for all spatial dimensions. (暫時(shí)沒看到其作用)
activation_fn: 激活函數(shù),默認(rèn)relu
normalizer_fn: normalization function to use instead of biases.(沒用過,不知道起作用)
normalizer_params: normalization function parameters.
weights_initializer: 這不用說(shuō)了,有默認(rèn)值,估計(jì)用默認(rèn)的就可以了。
weights_regularizer: Optional regularizer for the weights.(沒明白為什么需要這個(gè))
biases_initializer: 有默認(rèn)值,一般也就不用指定。
biases_regularizer: …
reuse: whether or not the layer and its variables should be reused. To be able to reuse the layer scope must be given. 應(yīng)該都需要reuse吧,所以這個(gè)參數(shù)默認(rèn)為True更好,現(xiàn)在是None。
variables_collections: 怎么用暫時(shí)不太明白,但應(yīng)該不用指定也可以;
outputs_collections: 同上;
trainable: If True also add variables to the graph collection GraphKeys.TRAINABLE_VARIABLES,默認(rèn)是True。 (這個(gè)是不是說(shuō)在fit的時(shí)候需要設(shè)為True,evaluate和predict的時(shí)候?yàn)閒alse?)
scope: 也即是variable_scope, 如果用多個(gè)卷積層的話,需要設(shè)置這個(gè)參數(shù),以便把每一次的weight和bias區(qū)別出來(lái)。
我們?cè)趯?duì)MNIST做卷積的時(shí)候,只要指定inputs, num_outputs, kernel_size, scope這幾個(gè)參數(shù)就可以了,比如:
conv1 = tf.contrib.layers.conv2d(inputs, 4, [5, 5], 'conv_layer1') #stride默認(rèn)1,weights和biases也都是默認(rèn)的
定義池化層
可以用 tf.contrib.layers.max_pool2d或者tf.contrib.layers.avg_pool2d
max_pool2d(inputs, kernel_size, stride=2, padding=’VALID’, data_format=DATA_FORMAT_NHWC, outputs_collections=None, scope=None)
inputs: 就是卷積的輸出了;
kernel_size: 是不是叫pool_size更貼切。[kernel_height, kernel_width]或者是一個(gè)整數(shù);
stride: [stride_height, stride_width],不過文檔上說(shuō)目前這兩個(gè)值必須一樣
padding: 這里默認(rèn)是VALID,和卷積默認(rèn)不一樣,為什么要這樣呢?
data_format: 注意和卷積用的一樣哦;
outputs_collections: …
scope: pooling的時(shí)候沒有參數(shù),需要scope嗎?
pool1 = tf.contrib.layers.max_pool2d(conv1, [2, 2], padding='SAME')
定義全連接層
tf.contrib.layers下有可用的全連接方法:
fully_connected(inputs, num_outputs, activation_fn=nn.relu, normalizer_fn=None, normalizer_params=None, weights_initializer=initializers.xavier_initializer(), weights_regularizer=None, biases_initializer=init_ops.zeros_initializer, biases_regularizer=None, reuse=None, variables_collections=None, outputs_collections=None, trainable=True, scope=None)
看這個(gè)函數(shù),參數(shù)和卷積很多地方是一樣的, 我們可以這樣用:
fc = tf.contrib.layers.fully_connected(inputs, 1024, scope='fc_layer')
唯一需要注意的是這里的inputs參數(shù),一般是二維的形式[batch_size, depth],而前面卷積的結(jié)果,一般是[batch_size, height, width, channels]的形式,所以需要做一個(gè)flatten操作后再傳給fully_connected。
一般在fc之后還會(huì)做dropout,可以用如下方法:
dropout(inputs, keep_prob=0.5, noise_shape=None, is_training=True, outputs_collections=None, scope=None)
參數(shù)的意義很明顯,其中is_training需要注意一下,在訓(xùn)練的時(shí)候傳True,其他情況下傳False。
dropout是指在深度學(xué)習(xí)網(wǎng)絡(luò)的訓(xùn)練過程中,對(duì)于神經(jīng)網(wǎng)絡(luò)單元,按照一定的概率將其暫時(shí)從網(wǎng)絡(luò)中丟棄。注意是暫時(shí),對(duì)于隨機(jī)梯度下降來(lái)說(shuō),由于是隨機(jī)丟棄,故而每一個(gè)mini-batch都在訓(xùn)練不同的網(wǎng)絡(luò)。
dropout是CNN中防止過擬合提高效果的一個(gè)大殺器。
定義logits
全連接之后,一般就是用softmax做分類,然后定義loss,就可以訓(xùn)練了。但是看官方的例子,softmax前還加了一步,計(jì)算叫l(wèi)ogits的東西,代碼里面的說(shuō)明是:
We don’t apply softmax here because tf.nn.softmax_cross_entropy_with_logits accepts the unscaled logits and performs the softmax internally for efficiency.
為什么要這樣暫時(shí)不太明白,但是依樣畫葫蘆,定義logtis本身很簡(jiǎn)單,做一個(gè)線性變換,把FC的結(jié)果映射到分類的數(shù)量上:
def inference(x, num_class):
with tf.variable_scope('softmax'):
dtype = x.dtype.base_dtype
# Set up the requested initialization.
init_mean = 0.0
init_stddev = 0.0
weights = tf.get_variable('weights',
[x.get_shape()[1], num_class], initializer=init_ops.random_normal_initializer(init_mean, init_stddev, dtype=dtype), dtype=dtype)
biases = tf.get_variable('bias', [num_class], initializer=init_ops.random_normal_initializer(init_mean, init_stddev, dtype=dtype), dtype=dtype)
logits = tf.nn.xw_plus_b(x, weights, biases)
return logits
定義loss
在tf.contrib.losses下有一些預(yù)定義的loss函數(shù),比如直接用
softmax_cross_entropy(logits, onehot_labels, weights=_WEIGHT_SENTINEL, label_smoothing=0, scope=None)
注意這里的label是onehot格式的, 我們從mnist獲取的label要轉(zhuǎn)換成這個(gè)格式。
定義train_op
可以用tf.contrib.layers.optimize_loss,通過傳遞不同的參數(shù),就可以調(diào)用不同的優(yōu)化方法。
optimize_loss(loss,
global_step,
learning_rate,
optimizer,
gradient_noise_scale=None,
gradient_multipliers=None,
clip_gradients=None,
learning_rate_decay_fn=None,
update_ops=None,
variables=None,
name=None,
summaries=None,
colocate_gradients_with_ops=False):
預(yù)定義的optimizer有:
OPTIMIZER_CLS_NAMES = {
"Adagrad": train.AdagradOptimizer,
"Adam": train.AdamOptimizer,
"Ftrl": train.FtrlOptimizer,
"Momentum": train.MomentumOptimizer,
"RMSProp": train.RMSPropOptimizer,
"SGD": train.GradientDescentOptimizer,
}
或者這么寫
train_op = tf.contrib.layers.optimize_loss(
loss, tf.contrib.framework.get_global_step(), optimizer='Adagrad', learning_rate=0.1)
model和Estimator
結(jié)合上面的內(nèi)容,就可以定義出model, 從而用Estimator完成訓(xùn)練,預(yù)測(cè)等功能,完整的程序如下:
import numpy as np
import sklearn.metrics as metrics
import tensorflow as tf
from PIL import Image
from tensorflow.contrib import learn
from tensorflow.contrib.learn import SKCompat
from tensorflow.contrib.learn.python.learn.estimators import model_fn as model_fn_lib
from tensorflow.python.ops import init_ops
IMAGE_SIZE = 28
LOG_DIR = './ops_logs'
mnist = learn.datasets.load_dataset('mnist')
def inference(x, num_class):
with tf.variable_scope('softmax'):
dtype = x.dtype.base_dtype
init_mean = 0.0
init_stddev = 0.0
weight = tf.get_variable('weights',
[x.get_shape()[1], num_class], initializer=init_ops.random_normal_initializer(init_mean, init_stddev, dtype=dtype), dtype=dtype)
biases = tf.get_variable('bias', [num_class], initializer=init_ops.random_normal_initializer(init_mean, init_stddev, dtype=dtype), dtype=dtype)
logits = tf.nn.xw_plus_b(x, weight, biases)
return logits
def model(features, labels, mode):
if mode != model_fn_lib.ModeKeys.INFER:
labels = tf.one_hot(labels, 10, 1, 0)
else:
labels = None
inputs = tf.reshape(features, (-1, IMAGE_SIZE, IMAGE_SIZE, 1))
#conv1
conv1 = tf.contrib.layers.conv2d(inputs, 4, [5, 5], scope='conv_layer1', activation_fn=tf.nn.tanh);
pool1 = tf.contrib.layers.max_pool2d(conv1, [2, 2], padding='SAME')
#conv2
conv2 = tf.contrib.layers.conv2d(pool1, 6, [5, 5], scope='conv_layer2', activation_fn=tf.nn.tanh);
pool2 = tf.contrib.layers.max_pool2d(conv2, [2, 2], padding='SAME')
pool2_shape = pool2.get_shape()
pool2_in_flat = tf.reshape(pool2, [pool2_shape[0].value or -1, np.prod(pool2_shape[1:]).value])
#fc
fc1 = tf.contrib.layers.fully_connected(pool2_in_flat, 1024, scope='fc_layer1', activation_fn=tf.nn.tanh)
#dropout
is_training = False
if mode == model_fn_lib.ModeKeys.TRAIN:
is_training = True
dropout = tf.contrib.layers.dropout(fc1, keep_prob=0.5, is_training=is_training, scope='dropout')
logits = inference(dropout, 10)
prediction = tf.nn.softmax(logits)
if mode != model_fn_lib.ModeKeys.INFER:
loss = tf.contrib.losses.softmax_cross_entropy(logits, labels)
train_op = tf.contrib.layers.optimize_loss(
loss, tf.contrib.framework.get_global_step(), optimizer='Adagrad',
learning_rate=0.1)
else:
train_op = None
loss = None
return {'class': tf.argmax(prediction, 1), 'prob': prediction}, loss, train_op
classifier = SKCompat(learn.Estimator(model_fn=model, model_dir=LOG_DIR))
classifier.fit(mnist.train.images, mnist.train.labels, steps=1000, batch_size=300)
predictions = classifier.predict(mnist.test.images)
score = metrics.accuracy_score(mnist.test.labels, predictions['class'])
print('Accuracy: {0:f}'.format(score))
總結(jié)
以上是生活随笔為你收集整理的深度学习基础(CNN详解以及训练过程1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 95369如何转人工?
- 下一篇: 中行是什么银行的简称?