您當前的位置:首頁 > 文化

CNN模型合集 | 1 LeNet

作者:由 Mengcius 發表于 文化時間:2019-05-10

1.1 LeNet的設計思想

1998年LeCun提出,經典結構,3層,五臟俱全(卷積層、Pooling層、FC網路、Sigmod層),對標傳統神經網路。

主要設計貢獻

區域性感受野(local receptive fields),區域性連線

權值共享(引數共享)

下采樣(sub-sampling),pooling層

核心結構

CNN模型合集 | 1 LeNet

LeNet-5是LeCun最新的卷積網路,專為手寫和機器列印的字元識別而設計,下面是LeNet-5實際應用的一個例子。

CNN模型合集 | 1 LeNet

傳統網路的全連線FC

(VS區域性連線)

傳統神經網路連線方式是透過全連線,上一層的所有神經元節點x會和下一層的每一個節點y進行互連,線性變換y=w*x_all+b

權值引數多,系統開銷大,稠密

對平移、形變不具有不變性,對區域性資訊不敏感,完全忽略了影象的區域性結構,因為考慮到了所有點。

圖如果發生一點變化就會導致輸出結果產生很大差異(病態問題:對輸入輸出敏不敏感,收集到是資料往往帶有噪聲,若模型對此偏差敏感就是病態系統,不魯棒)

全連線相當於1*1的卷積核

CNN模型合集 | 1 LeNet

引數共享的區域性連線

(VS純區域性連線還是不夠好,想進一步減少引數規模)

減小引數規模,如下圖引數共享的區域性連線引數減少到了10k,後階段做模型時越小越好,大的話終端執行時空間很大載入會很慢,很佔記憶體。

引數共享就是每種(個)filter學習一種feature,同一種filter權值當然是共享,所有的區域性感受野就是用同一種引數,所以就每個卷積層需要很多種filter,也就是depth來學習很多種不同的特徵。

用一組固定的引數和不同視窗做卷積,來得到下一層特徵。每一種濾波器(卷積)就是一種特徵,就像高斯濾波等保留了高頻或低頻的訊號。

神經網路的卷積就是用一種濾波器提取一種特徵,學習多種濾波器,保證多樣性;又在經過下采樣的不同層上來學習不同濾波器,這樣就在不同的力度上提取了不同的特徵,比較完善。

CNN模型合集 | 1 LeNet

卷積

感受野下的各畫素與卷積核相乘,再相加賦給中心畫素。

傅立葉變換與訊號處理的知識,跟高斯濾波、銳化、邊緣檢測等一樣提取高頻訊號。

邊緣檢測時手動設計卷積核為按列遞減的值[[1,0,-1], [1,0,-1],[1,0,-1]],與它相乘就相當於左邊的畫素減去右邊的,就能檢測出垂直邊緣資訊。以前傳統機器學習是手動設計卷積核特徵(如顏色資訊、紋理資訊、形狀資訊)。

CNN模型合集 | 1 LeNet

下采樣(sub-sampling),pooling層

縮小影象,但不會長寬比形變(區別resize),獲得多尺度的資訊,以免單一,相當於均值濾波器

忽略目標的傾斜、旋轉之類的相對位置的變化,以此提高精度,不管怎麼轉獲得的最大值會均值都是不變的

降低了特徵圖的維度,推理時能適應多尺度的影象,

可以避免過擬合,因為維度小了,引數少了,計算量少了

Sigmod層

連續的函式,這裡分類用,逼近不可導的0-1階躍啟用函式,高斯連線,邏輯迴歸函式,1維的,輸出是0~1間的數

而常用的Softmax是2維的,輸出是2個機率值,正樣本的機率和負樣本的機率。

1.2 Caffe實現LeNet

參考:

https://

github。com/XuekuanWang/

demoCaffe

或者

https://

github。com/BVLC/caffe/t

ree/master/examples/mnist

或者

https://

github。com/jklhj222/caf

fe_LeNet/tree/master/LeNet

(1)lenet_solver.prototxt 訓練引數

net:網路模型檔案的路徑

test_iter:在測試的時候需要迭代的次數,即test_iter* batchsize(測試集的)=測試集的大小,測試集batchsize可以在tran_test。prototxt檔案裡設定

test_interval:測試間隔,訓練的時候每迭代500次就進行一次測試。

caffe在訓練的過程是邊訓練邊測試的。訓練過程中每500次迭代(也就是32000個訓練樣本參與了計算,batchsize為64),計算一次測試誤差。計算一次測試誤差就需要包含所有的測試圖片(這裡為10000),這樣可以認為在一個epoch裡,訓練集中的所有樣本都遍歷一遍,但測試集的所有樣本至少要遍歷一次,至於具體要多少次,也許不是整數次,這就要看程式碼。

base_lr 基本學習率:loss降不下去可能是學習率太大了

momentum 動量:梯度下降最佳化器的引數,為了自適應調整學習率(後面學習率要降低)

weight_decay 權值衰減

# 網路模型檔案,train_test代表訓練網路和測試網路寫到一個檔案裡了,若分開寫注意修改

net: “lenet_train_test。prototxt”

# 在測試的時候需要迭代的次數

test_iter: 100

# 訓練的時候每迭代多少次就進行一次測試

test_interval: 1000

# 網路的基本學習率、動量和權值衰減

base_lr: 0。01

momentum: 0。9

weight_decay: 0。0005

# The learning rate policy,學習率政策

lr_policy: “inv”

gamma: 0。0001

power: 0。75

# 每100次迭代顯示一次

display: 10

# 最大迭代次數

max_iter: 10000

# 每多少次儲存一次快照

snapshot: 1000

# 快照儲存的路徑字首

snapshot_prefix: “/home/kuan/PycharmProjects/demo_cnn_net/cnn_model/mnist/lenet/lenet”

# solver mode: CPU or GPU

solver_mode: GPU

(2)lenet_train_test.prototxt

網路結構

(訓練和測試),區別lenet。prototxt(只預測)

訓練和測試選項:

include { phase: TRAIN }:相位,加上此條代表它這一層只用於訓練,沒有寫明就代表測試和訓練通用

include { phase: TEST}:相位,加上此條代表它這一層只用於測試

data_param {}:

source訓練或測試的資料集路徑

batch_size批次值,每次迭代訓練圖片的數量

隨機梯度下降:每一個樣本訓練下降一次,容易震盪,容易陷入區域性最優

批次梯度下降:引數調整慢,計算所有樣本後求均值,可能會磨滅好的資訊

小批次隨機梯度下降:折中方案,設定batch_size批次值,跑batch_size個後下降一次

層選項:

layer {}:每個layer代表一個層,網路連線就是一層一層堆起來的,

type:每個layer有它的type(Data、Input、Convolution、Pooling、ReLU、InnerProduct全連線層、Softmax、Accuracy、SoftmaxWithLoss),

top、bottom:每個layer還有它的輸入和輸出(top、bottom),輸入層只有top輸出,卷積層bottom是輸入,top是輸出。這三個必須要有。

層的引數:

param {}:

lr_mult:學習率引數,第一個是引數w,第二個是b,如果不寫就是預設

convolution_param {}:卷積核引數,

num_output個數,kernel_size大小,stride步長,我們主要調參是這三個。

weight_filler{}權值初始化方式,bias_filler{}偏差值初始化方式,這倆影響不大。

name: “LeNet”

layer {

name: “mnist”

type: “Data”

top: “data”

top: “label”

include {

phase: TRAIN # 相位

}

transform_param {

scale: 0。00390625

}

data_param {

source: “/home/kuan/PycharmProjects/demo_cnn_net/mnist/mnist_train_lmdb”

batch_size: 16

backend: LMDB

}

}

layer {

name: “mnist”

type: “Data”

top: “data”

top: “label”

include {

phase: TEST

}

transform_param {

scale: 0。00390625

}

data_param {

source: “/home/kuan/PycharmProjects/demo_cnn_net/mnist/mnist_test_lmdb”

batch_size: 16

backend: LMDB

}

}

layer {

name: “conv1”

type: “Convolution”

bottom: “data” # 輸入

top: “conv1” # 輸出

param {

lr_mult: 1 # 引數w

}

param {

lr_mult: 2 # 引數b

}

convolution_param {

num_output: 20

kernel_size: 5

stride: 1

weight_filler {

type: “xavier” # xavier法初始化權重

}

bias_filler {

type: “constant”

}

}

}

layer {

name: “pool1”

type: “Pooling”

bottom: “conv1”

top: “pool1”

pooling_param {

pool: MAX

kernel_size: 2

stride: 2

}

}

layer {

name: “conv2”

type: “Convolution”

bottom: “pool1”

top: “conv2”

param {

lr_mult: 1

}

param {

lr_mult: 2

}

convolution_param {

num_output: 50

kernel_size: 5

stride: 1

weight_filler {

type: “xavier”

}

bias_filler {

type: “constant”

}

}

}

layer {

name: “pool2”

type: “Pooling”

bottom: “conv2”

top: “pool2”

pooling_param {

pool: MAX

kernel_size: 2

stride: 2

}

}

layer {

name: “ip1”

type: “InnerProduct”

bottom: “pool2”

top: “ip1”

param {

lr_mult: 1

}

param {

lr_mult: 2

}

inner_product_param {

num_output: 500

weight_filler {

type: “xavier”

}

bias_filler {

type: “constant”

}

}

}

layer {

name: “relu1”

type: “ReLU”

bottom: “ip1”

top: “ip1”

}

layer {

name: “ip2”

type: “InnerProduct”

bottom: “ip1”

top: “ip2”

param {

lr_mult: 1

}

param {

lr_mult: 2

}

inner_product_param {

num_output: 10

weight_filler {

type: “xavier”

}

bias_filler {

type: “constant”

}

}

}

layer {

name: “accuracy”

type: “Accuracy”

bottom: “ip2”

bottom: “label”

top: “accuracy”

include {

phase: TEST

}

}

layer {

name: “loss”

type: “SoftmaxWithLoss”

bottom: “ip2”

bottom: “label”

top: “loss”

}

(3)視覺化caffe網路結構

把caffe給的例程複製到網站

https://

ethereon。github。io/nets

cope/#/editor

http://

ethereon。github。io/nets

cope/#/editor

,按shift+enter得到。

與最原始的相比,這裡實現的LeNet加了relu,卷積核個數、全連線單元數也不一樣,Sigmod也改為了softmax。如圖左邊的是訓練和測試的lenet_train_test。prototxt,中間的是預測的lenet_depoly。prototxt(input_param { shape: { dim: 64 dim: 1 dim: 28 dim: 28 } } #64是batch_size),最右邊的是lenet。prototxt(input_param { shape: { dim: 1 dim: 3 dim: 28 dim: 28 } } )。

CNN模型合集 | 1 LeNet

(4)訓練

編寫好lenet_solver。prototxt和lenet_train_test。prototxt後執行:

# coding utf-8

import caffe

caffe。set_device(0) # GPU的裝置號

caffe。set_mode_gpu() # gpu模式

solver = caffe。SGDSolver(“。/cnn_net/lenet/lenet_solver。prototxt”) # SGD,訓練引數檔案

solver。solve()

(5)預測結果

使用訓練好的模型lenet_iter_10000。caffemodel,按照預測網路結構lenet。prototxt來推斷。參考

https://

github。com/jklhj222/caf

fe_LeNet/blob/master/LeNet/caffe_test。py

#!/usr/bin/env python3

import os

import sys

import numpy as np

import matplotlib。pyplot as plt

caffe_root = ‘/home/s2c/pkg/local/caffe-master_cuDNN’

sys。path。insert(0, caffe_root + ‘python’) # Add the path of pycaffe into environment

import caffe

# Assign the structure of network, differ with lenet_train_test。prototxt

MODEL_FILE = ‘/home/s2c/pkg/local/caffe-master_cuDNN/examples/mnist/lenet。prototxt’

#MODEL_FILE = ‘lenet_train_test。prototxt’

PRETRAINED = ‘/home/s2c/pkg/local/caffe-master_cuDNN/examples/mnist/lenet_iter_10000。caffemodel’

# lenet。prototxt, picture size (28x28), black and white

IMAGE_FILE = ‘/home/s2c/pkg/local/caffe-master_cuDNN/examples/images/test4。png’

input_image = caffe。io。load_image(IMAGE_FILE, color=False)

net = caffe。Classifier(MODEL_FILE, PRETRAINED)

prediction = net。predict([input_image], oversample = False)

caffe。set_mode_gpu()

print( ‘predicted class:’, prediction[0]。argmax() )

print( ‘predicted class2:’, prediction[0] )

轉載請提前告知

標簽: param  type  lenet  caffe  TOP