# 使用Pyhon+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-ML库的初学者指南。
• 机器学习简介。（https://medium.com/@Jernfrost/machine-learning-for-dummies-in-julia-6cd4d2e71a46） 机器学习概论。

简单多层感知机

我们要编程的人工神经网络被称为简单的多层感知机，这是神经网络（ANN）的基础，大多数教科书都会从它开始。

我先展示整个程序，然后我们再更详细地讲解不同的部分。

``````
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)

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``````

``````
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)``````

``````
julia> using Plots
julia> plot(imgs[2])
``````

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

``````
julia> A = collect(1:4)
4-element Array{Int64,1}:
1
2
3
4
``````

``````
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(image::Matrix{<:Gray}) = Float32.(reshape(image, :))
``````

``````
X = hcat(imagestrip.(imgs)...)
``````

``````
X = hcat(X₁, X₂, X₃, ..., Xₙ)
``````

``````
labels = MNIST.labels()
``````

Xᵢ代表我们所有的特征向量，用机器学习的术语来说，每个像素的灰度值都是一个特征。

``````
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``````

``````
Y = onehotbatch(labels, 0:9)
``````

``````
m = Chain(
Dense(28^2, 32, relu),
Dense(32, 10),
softmax)
``````

Softmax函数

``````
julia> ys = rand(1:10, 10)
10-element Array{Int64,1}:
9
6
10
5
10
2
6
6
7
9
``````

``````
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``````

``````
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
``````

``````
loss(x, y) = crossentropy(m(x), y)
``````

``````
dataset = repeated((X, Y), 200)
``````

``````
dataset = [(X1, Y1), (X2, Y2), ..., (X200, Y200)]
``````

``````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``````

``````
tX = hcat(float.(reshape.(MNIST.images(:test), :))...)
tY = onehotbatch(MNIST.labels(:test), 0:9)

@show accuracy(tX, tY)
``````