构建和训练用于手写数字识别的神经网络
在本示例中,我们将考虑数据处理和图像分类神经网络模型的训练。我们选择 MNIST 数据集作为观察对象集,该数据集包含 7 万张标记过的手写数字图像。示例将使用一个**.csv**文件,其中的图像以表格数据的形式展开,包含每个像素的亮度值。
连接数据处理库:
In [ ]:
Pkg.add(["Colors", "CSV", "Flux"])
In [ ]:
using CSV, DataFrames
将数据加载到变量中
In [ ]:
df = DataFrame(CSV.File("$(@__DIR__)/mnist_784.csv"));
输出数据帧的前五行:
In [ ]:
first(df,5)
Out[0]:
输出数据帧的前五行和最后一列,告诉你观察对象属于哪个类别:
In [ ]:
df[1:5,780:785]
Out[0]:
将数据集按 8 比 2 的比例分为训练样本和测试样本:
In [ ]:
X_train, y_train = Matrix(df[1:56000,1:784]), df[1:56000,785]
X_test, y__test = Matrix(df[56001:end,1:784]), df[56001:end,785]
Out[0]:
将样本转换成神经网络处理所能接受的格式:
In [ ]:
X_train, X_test = convert(Matrix{Float32}, X_train), convert(Matrix{Float32}, X_test)
y_train, y__test = convert(Vector{Float32}, y_train), convert(Vector{Float32}, y__test)
Out[0]:
连接数据可视化库
In [ ]:
using Plots
显示对象及其类别
In [ ]:
test_img = Vector(df[60000,1:784])
test_img = (reshape(test_img, 28, 28)) / 256
using Colors
println("Класс объекта: ", df[60000,785])
plot(Gray.(test_img))
Out[0]:
神经网络处理的最终数据转换
In [ ]:
X_train, X_test = X_train', X_test'
y_train, y__test = y_train', y__test'
Out[0]:
连接机器学习库
In [ ]:
using Flux
using Flux: train!
定义神经网络的结构
In [ ]:
model = Chain(
Dense(784, 15,elu),
Dense(15, 10,sigmoid),
softmax
)
Out[0]:
识别测试结果(模型训练前):
In [ ]:
predict = model(X_test)
Out[0]:
确定训练参数
In [ ]:
loss(x, y) = Flux.mse(model(x), reshape(Flux.onehotbatch(y_train,0:9), 10, 56000)) # функция потерь
ps = Flux.params(model) # указание на параметры корректируемые в процессе обучения
opt = Adam(0.01) # выбор оптимизатора
Out[0]:
定义计算模型准确度的函数:
In [ ]:
function accuracy()
correct = 0
for index in 1:length(y__test)
probs = model(Flux.unsqueeze(X_test[:,index],dims=3))
predicted_digit = argmax(probs)[1]-1
if predicted_digit == y__test'[index]
correct +=1
end
end
return correct/length(y__test')
end
Out[0]:
迭代模型训练过程
In [ ]:
loss_history = [] # определение пустого массива для записи функции потерь
epochs = 50 # определение количества шагов обучения модели
for epoch in 1:epochs # повторение обучения модели на каждом шаге
train!(loss, ps, [(X_train, y_train)], opt) # обучающая функция, корректирующая параметры модели
train_loss = loss(X_train, y_train) # расчёт функции потерь на текущем шаге
push!(loss_history, train_loss) # запись функции потерь
acc = accuracy() * 100
if epoch == 1 # условие для отображения функции потерь на каждом шаге обучения
println("Epoch = $epoch : Training Loss = $train_loss, Model Accuracy = $acc %");
elseif epoch % 1 == 0
println("Epoch = $epoch : Training Loss = $train_loss, Model Accuracy = $acc %");
end
end
每个训练步骤中损失函数变化的可视化:
In [ ]:
plot((1:epochs), loss_history, title="Изменение функции потерь", xlabel="Шаг обучения", ylabel="Функция потерь")
Out[0]:
显示结果
In [ ]:
number = 13000
test_img = Vector(df[56000+number,1:784])
test_img = (reshape(test_img, 28, 28)) / 256
using Colors
result = model(X_test[:,number])
println("Известный класс объекта: ", df[56000+number,785], "\n ", "Вектор, характеризующий класс объекта: ", result)
plot(Gray.(test_img))
Out[0]:
输出
在本示例中,对像素亮度数据进行了预处理,并定义了神经网络架构、优化器参数和损失函数。
模型经过训练后,显示出相当准确的类别划分,但并不完美。为了提高识别质量,可以通过改变层的结构和增加训练样本来修改神经网络。