前情提要:
- 概述
- 本地環(huán)境:Windows、Mac
- 在線環(huán)境:無(wú)痛環(huán)境桨啃、定制無(wú)痛環(huán)境
- 快速學(xué)習(xí):
- 資源
- 案例
之前給大家介紹過(guò)《幾行代碼識(shí)別圖片內(nèi)容》车胡,這個(gè)內(nèi)容是基于在線的juliabox.com的。
這期給大家的內(nèi)容是在本地的機(jī)器上實(shí)現(xiàn)圖片內(nèi)容識(shí)別照瘾。
先來(lái)個(gè)實(shí)現(xiàn)效果圖:
首先匈棘,介紹一下本期的主角:Mocha,是Julia上的一個(gè)實(shí)現(xiàn):摩卡(咖啡)
https://github.com/pluskid/Mocha.jl
(國(guó)外的人都喜歡把相關(guān)的名字起一起析命,只要之前沒(méi)有人在這個(gè)領(lǐng)域使用過(guò)這個(gè)名字即可羹饰。)
這個(gè)程序包是做什么的?
我們來(lái)看看里面的一個(gè)案例碳却,也就是今天要復(fù)刻到本地實(shí)現(xiàn)的基于深度學(xué)習(xí)的圖片內(nèi)容識(shí)別队秩。
大概意思是用一個(gè)預(yù)先訓(xùn)練好的CNN模型(這個(gè)模型之前在Caffe上實(shí)現(xiàn),現(xiàn)在明白主角為什么叫摩卡了吧)來(lái)移植到Julia上實(shí)現(xiàn)昼浦。
(之前已經(jīng)說(shuō)過(guò)Julia有吸星大法馍资,Python、R的很多程序包可以拿來(lái)用)
直接說(shuō)實(shí)現(xiàn)步驟关噪,(在 Mac上實(shí)現(xiàn)):
安裝好 JuliaPro鸟蟹。(參考之前課程)
安裝好Ananconda。(參考之前課程)
-
安裝好Graphviz
brew install Graphviz
在Anaconda上打開(kāi)Jupyter Notebook
然后你會(huì)看到和之前在線環(huán)境(juliabox.com)一樣的界面(實(shí)際上已經(jīng)在本地上實(shí)現(xiàn)了Jupyter):
選擇新建Julia 0.6.4
使兔,這個(gè)是剛才安裝了JuliaPro的版本建钥。(Julia 0.7.0是筆者之前自己安裝的版本)
好了,參考這個(gè)
上面寫(xiě)的虐沥,一步一步進(jìn)行代碼編寫(xiě)(復(fù)制熊经、運(yùn)行泽艘、排雷)。
過(guò)程中你會(huì)發(fā)現(xiàn)需要的模型和文件都沒(méi)有镐依,這里給出來(lái)地址:
-
模型文件
-
其他文件
-
下載整個(gè)Mocha.jl 匹涮,解壓后把代碼里的文件夾和文件復(fù)制到和本地ipynb對(duì)應(yīng)的路徑位置即可
-
這里附上筆者的本地實(shí)現(xiàn)代碼:
Pkg.add("hdf5")
Pkg.build("hdf5")
Pkg.add("Mocha")
using Mocha
backend = CPUBackend()
init(backend)
img_width, img_height, img_channels = (256, 256, 3)
crop_size = (227, 227)
batch_size = 1 # 可以設(shè)置更大的數(shù)字,用于批量識(shí)別圖片
layers = [
MemoryDataLayer(name="data", tops=[:data], batch_size=batch_size,
transformers=[(:data, DataTransformers.Scale(scale=255)),
(:data, DataTransformers.SubMean(mean_file="model/ilsvrc12_mean.hdf5"))],
data = Array[zeros(img_width, img_height, img_channels, batch_size)])
CropLayer(name="crop", tops=[:cropped], bottoms=[:data], crop_size=crop_size)
ConvolutionLayer(name="conv1", tops=[:conv1], bottoms=[:cropped],
kernel=(11,11), stride=(4,4), n_filter=96, neuron=Neurons.ReLU())
PoolingLayer(name="pool1", tops=[:pool1], bottoms=[:conv1],
kernel=(3,3), stride=(2,2), pooling=Pooling.Max())
LRNLayer(name="norm1", tops=[:norm1], bottoms=[:pool1],
kernel=5, scale=0.0001, power=0.75)
ConvolutionLayer(name="conv2", tops=[:conv2], bottoms=[:norm1],
kernel=(5,5), pad=(2,2), n_filter=256, n_group=2, neuron=Neurons.ReLU())
PoolingLayer(name="pool2", tops=[:pool2], bottoms=[:conv2],
kernel=(3,3), stride=(2,2), pooling=Pooling.Max())
LRNLayer(name="norm2", tops=[:norm2], bottoms=[:pool2],
kernel=5, scale=0.0001, power=0.75)
ConvolutionLayer(name="conv3", tops=[:conv3], bottoms=[:norm2],
kernel=(3,3), pad=(1,1), n_filter=384, neuron=Neurons.ReLU())
ConvolutionLayer(name="conv4", tops=[:conv4], bottoms=[:conv3],
kernel=(3,3), pad=(1,1), n_filter=384, n_group=2, neuron=Neurons.ReLU())
ConvolutionLayer(name="conv5", tops=[:conv5], bottoms=[:conv4],
kernel=(3,3), pad=(1,1), n_filter=256, n_group=2, neuron=Neurons.ReLU())
PoolingLayer(name="pool5", tops=[:pool5], bottoms=[:conv5],
kernel=(3,3), stride=(2,2), pooling=Pooling.Max())
InnerProductLayer(name="fc6", tops=[:fc6], bottoms=[:pool5],
output_dim=4096, neuron=Neurons.ReLU())
InnerProductLayer(name="fc7", tops=[:fc7], bottoms=[:fc6],
output_dim=4096, neuron=Neurons.ReLU())
InnerProductLayer(name="fc8", tops=[:fc8], bottoms=[:fc7],
output_dim=1000)
SoftmaxLayer(name="prob", tops=[:prob], bottoms=[:fc8])
]
net = Net("imagenet", backend, layers)
println(net)
open("net.dot", "w") do out net2dot(out, net) end
run(pipeline(`dot -Tpng net.dot`, "net.png"))
using Images
using FileIO
load("net.png")
# 讀取預(yù)先訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)參數(shù)
using HDF5
h5open("model/bvlc_reference_caffenet.hdf5", "r") do h5
load_network(h5, net)
end
init(net)
classes = open("synset_words.txt") do s map(x -> replace(strip(x), r"^n[0-9]+ ", ""), readlines(s)) end
#include(joinpath(Pkg.dir("Mocha"), "tools/image-classifier.jl"))
include("tools/image-classifier.jl")
classifier = ImageClassifier(net, :prob, channel_order=(3,2,1), classes=classes)
println("Classifier constructed")
# 讀取圖片
img = FileIO.load("images/cat256.jpg")
# 識(shí)別圖片
prob, class = classify(classifier, img)
println(class)
# 虎斑貓
using Gadfly
n_plot = 5
n_best = sortperm(vec(prob), rev=true)[1:n_plot]
best_probs = prob[n_best]
best_labels = classes[n_best]
plot(x=1:length(best_probs), y=best_probs, color=best_labels, Geom.bar, Guide.ylabel("probability"))
img2 = FileIO.load("images/bird.jpg")
prob, class = classify(classifier, img2)
println(class)
需要注意的是代碼里設(shè)置了圖片的大小是 256 x 256槐壳,圖片大小不符合的就會(huì)報(bào)錯(cuò)然低。
有需要的可以在代碼里面改,或者把圖片改成合適的尺寸即可务唐。
識(shí)別速度還是挺快的雳攘。無(wú)圖無(wú)真相:
KevinZhang
Sep 3, 2018