使用Pyhon+Flux+Julia實現手寫數字識別
點擊上方“小白學視覺”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達



為什么使用Flux和Julia?
機器學習概論
線性代數的核心思想。(https://medium.com/@Jernfrost/the-core-idea-of-linear-algebra-7405863d8c1d) 線性代數基本上是關于向量和矩陣的,這是你在機器學習中經常用到的東西。 使用引用。(https://medium.com/@Jernfrost/working-with-and-emulating-references-in-julia-e02c1cae5826) 它看起來有點不太好理解,但是如果你想理解像Flux這樣的ML庫,那么理解Julia中的引用是很重要的。 Flux的實現。(https://medium.com/@Jernfrost/implementation-of-a-modern-machine-learning-library-3596badf3be) 如何實現Flux-ML庫的初學者指南。 機器學習簡介。(https://medium.com/@Jernfrost/machine-learning-for-dummies-in-julia-6cd4d2e71a46) 機器學習概論。
簡單多層感知機
using?Flux,?Flux.Data.MNIST,?Statistics
using?Flux:?onehotbatch,?onecold,?crossentropy,?throttle
using?Base.Iterators:?repeated
#?Load?training?data.?28x28?grayscale?images?of?digits
imgs?=?MNIST.images()
#?Reorder?the?layout?of?the?data?for?the?ANN
imagestrip(image::Matrix{<:Gray})?=?Float32.(reshape(image,?:))
X?=?hcat(imagestrip.(imgs)...)
#?Target?output.?What?digit?each?image?represents.
labels?=?MNIST.labels()
Y?=?onehotbatch(labels,?0:9)
#?Defining?the?model?(a?neural?network)
m?=?Chain(
?Dense(28*28,?32,?relu),
?Dense(32,?10),
?softmax)
?
loss(x,?y)?=?crossentropy(m(x),?y)
dataset?=?repeated((X,?Y),?200)
opt?=?ADAM()
evalcb?=?()?->?@show(loss(X,?Y))
#?Perform?training?on?data
Flux.train!(loss,?params(m),?dataset,?opt,?cb?=?throttle(evalcb,?10))
探索輸入數據
imgs?=?MNIST.images()
julia>?size(imgs)
(60000,)
julia>?eltype(imgs)
Array{Gray{FixedPointNumbers.Normed{UInt8,8}},2}
julia>?eltype(imgs)?<:?Matrix{T}?where?T?<:?Gray
true
imgs中的每個元素都是某種值矩陣,這些值屬于某種類型T,它是Gray類型的子類型。什么是Gray類型?help?>?Gray
??Gray?is?a?grayscale?object.?You?can?extract?its?value?with?gray(c).
julia>?size(imgs[1])
(28,?28)
julia>?size(imgs[2])
(28,?28)
Plots庫使你可以繪制函數和圖像。julia>?using?Plots
julia>?plot(imgs[2])

imgplots?=?plot.(imgs[1:9])
plot(imgplots...)

準備輸入數據
28x28=784的長像素帶。reshape函數來改變數組的形狀。下面是一些你如何使用它的例子。A:julia>?A?=?collect(1:4)
4-element?Array{Int64,1}:
?1
?2
?3
?4
reshape我們把它變成一個二乘二的矩陣B:julia>?B?=?reshape(A,?(2,?2))
2×2?Array{Int64,2}:
?1??3
?2??4
julia>?reshape(B,?4)
4-element?Array{Int64,1}:
?1
?2
?3
?4
julia>?reshape(B,?:)
4-element?Array{Int64,1}:
?1
?2
?3
?4
imagestrip函數的實際功能了,它將28x28的灰度矩陣轉換為784個32位浮點值的列向量。imagestrip(image::Matrix{<:Gray})?=?Float32.(reshape(image,?:))
.符號用于將函數應用于數組的每個元素,因此Float32.(xs)與map(Float32, xs)是相同的。imagestrip函數應用于6萬張灰度圖像中的每一張,生成784x6000個輸入矩陣X。X?=?hcat(imagestrip.(imgs)...)
imagestrip.(imgs)將圖像轉換為單個輸入值的數組,例如[X?, X?, X?, ..., X?],其中n = 60,000,每個X?都是784個浮點值。...,我們將其轉換為所有這些列向量的水平連接,以產生模型輸入。X?=?hcat(X?,?X?,?X?,?...,?X?)
size(X)。接下來,我們加載標簽。labels?=?MNIST.labels()
imgplots?=?plot.(imgs[1:9])
plot(imgplots...)
labels[1:9]
獨熱編碼
julia>?Flux.onehot('B',?['A',?'B',?'C'])
3-element?Flux.OneHotVector:
0
1
0
julia>?Flux.onehot("foo",?["foo",?"bar",?"baz"])
3-element?Flux.OneHotVector:
1
0
0
onehot函數,因為我們正在創(chuàng)建一批獨熱編碼標簽,我們將把60000張圖片作為一個批次來處理。Y?=?onehotbatch(labels,?0:9)
構造神經網絡模型
m?=?Chain(
??Dense(28^2,?32,?relu),
??Dense(32,?10),
??softmax)
Chain用于將各個層連接在一起。第一層Dense(28^2, 32, relu)有784(28x28)個輸入節(jié)點,對應于每個圖像中的像素數。sigmoid和tanh。relu等激活函數,這些激活函數在大多數情況下都工作得很好,包括圖像的分類。Softmax函數
softmax函數,它以前一層的輸出的矩陣作為輸入,并沿著每一列進行歸一化。julia>?ys?=?rand(1:10,?10)
10-element?Array{Int64,1}:
??9
??6
?10
??5
?10
??2
??6
??6
??7
??9
LinearAlgebra模塊的normalize,因為它與Julia捆綁在一起。softmax:julia>?softmax(ys)
10-element?Array{Float64,1}:
?0.12919082661651196???
?0.006432032517257137??
?0.3511770763952676????
?0.002366212528045101??
?0.3511770763952676????
?0.00011780678490667763
?0.006432032517257137??
?0.006432032517257137??
?0.017484077111717768??
?0.12919082661651196
julia>?sum(softmax(ys))
0.9999999999999999
normalize的功能進行對比:julia>?using?LinearAlgebra
julia>?normalize(ys)
10-element?Array{Float64,1}:
0.38446094597254243
0.25630729731502827
0.4271788288583805?
0.21358941442919024
0.4271788288583805?
0.0854357657716761?
0.25630729731502827
0.25630729731502827
0.2990251802008663?
0.38446094597254243
julia>?sum(normalize(ys))
2.9902518020086633
julia>?norm(normalize(ys))
1.0
julia>?norm(softmax(ys))
0.52959100847191
normalize歸一化的值求和,它們只會得到一些隨機值,然而如果我們把結果反饋給norm,我們得到的結果正好是1.0。normalize將向量中的值進行了歸一化,以便它們可以表示單位向量,即長度正好為一的向量。norm給出向量的大小。softmax不會將這些值視為向量,而是將其視為概率分布,每個元素表示輸入圖像為該數字的概率。softmax得到一個輸出值是[0.1,0.7,0.2],那么輸入圖像有10%的可能性是A的圖形,有70%的可能性是B的圖形,最后有20%的可能性是C的圖形。softmax作為最后一層的原因。用神經網絡不能絕對確定輸入圖像是什么,但是我們可以給出一個概率分布,它表示更有可能是哪個數字。定義損失函數
loss(x,?y)?=?crossentropy(m(x),?y)
指定Epoch
repeat重復我們的批處理200次。它實際上不會重復我們的數據200次,它只是用迭代器創(chuàng)建了這樣的錯覺。dataset?=?repeated((X,?Y),?200)
dataset?=?[(X1,?Y1),?(X2,?Y2),?...,?(X200,?Y200)]
優(yōu)化器
Descent類型提供的。opt?=?ADAM()
進行訓練
evalcb?=?()?->?@show(loss(X,?Y))
Flux.train!(loss,?params(m),?dataset,?opt,?cb?=?throttle(evalcb,?10))
評價模型預測精度
accuracy(x,?y)?=?mean(onecold((m(x)))?.==?onecold(y))
@show?accuracy(X,?Y)
julia>?onecold([0.1,?0.7,?0.2])
2
julia>?onecold([0.9,?0.05,?0.05])
1
onecold(y)進行比較。用測試數據驗證模型
tX?=?hcat(float.(reshape.(MNIST.images(:test),?:))...)
tY?=?onehotbatch(MNIST.labels(:test),?0:9)
@show?accuracy(tX,?tY)
最后
評論
圖片
表情
