问题描述
我是 Julia 和 ML 的初学者。我正在尝试重用来自 Flux Model Zoo 的代码,特别是 this,以对来自 this dataset 的图像进行分类。下面是我的代码版本 - 我修改了 build_model 中的数据加载和参数,以说明图像大小和要分类的字符类型数量的差异。原版有 28x28 和 10 个数字,阿拉伯字符集有 32x32 图像和 28 个字符。
function getimages(filename)
filepath = pwd() * "/images/" * filename
mtrx = Matrix(DataFrame(CSV.File(filepath)))
r,_ = size(mtrx)
v = Vector{Matrix{Int64}}()
for i = 1:r
push!(v,reshape(m[i,:],32,32))
end
v
end
function getlabels(filename)
filepath = pwd() * "/images/" * filename
vec(Matrix(DataFrame(CSV.File(filepath))))
end
function load_data(args)
train_data_file = "csvTrainImages.csv"
test_data_file = "csvTestimages.csv"
train_label_file = "csvTrainLabel.csv"
test_label_file = "csvTestLabel.csv"
train_data = getimages(train_data_file)
test_data = getimages(test_data_file)
train_labels = getlabels(train_label_file)
test_labels = getlabels(test_label_file)
xtrain = Flux.flatten(train_data)
xtest = Flux.flatten(test_data)
ytrain,ytest = onehotbatch(train_labels,1:28),onehotbatch(test_labels,1:28)
train_loader = DataLoader((xtrain,ytrain),batchsize=args.batchsize,shuffle=true)
test_loader = DataLoader((xtest,ytest),batchsize=args.batchsize)
return train_loader,test_loader
end
function build_model(; imgsize=(32,1),nclasses=28)
return Chain(
Dense(prod(imgsize),relu),Dense(32,nclasses))
end
function loss_and_accuracy(data_loader,model,device)
acc = 0
ls = 0.0f0
num = 0
for (x,y) in data_loader
x,y = device(x),device(y)
ŷ = model(x)
ls += logitcrossentropy(model(x),y,agg=sum)
acc += sum(onecold(cpu(model(x))) .== onecold(cpu(y)))
num += size(x,2)
end
return ls / num,acc / num
end
@kwdef mutable struct Args
η::Float64 = 3e-4 # learning rate
batchsize::Int = 256 # batch size
epochs::Int = 10 # number of epochs
use_cuda::Bool = true # use gpu (if cuda available)
end
function train(; kws...)
args = Args(; kws...) # collect options in a struct for convenience
if CUDA.functional() && args.use_cuda
@info "Training on CUDA GPU"
CUDA.allowscalar(false)
device = gpu
else
@info "Training on cpu"
device = cpu
end
# Create test and train DataLoaders
train_loader,test_loader = load_data(args)
# Construct model
model = build_model() |> device
ps = Flux.params(model) # model's trainable parameters
## Optimizer
opt = Adam(args.η)
## Training
for epoch in 1:args.epochs
for (x,y) in train_loader
x,device(y) # transfer data to device
gs = gradient(() -> logitcrossentropy(model(x),y),ps) # compute gradient
Flux.Optimise.update!(opt,ps,gs) # update parameters
end
# Report on train and test
train_loss,train_acc = loss_and_accuracy(train_loader,device)
test_loss,test_acc = loss_and_accuracy(test_loader,device)
println("Epoch=$epoch")
println(" train_loss = $train_loss,train_accuracy = $train_acc")
println(" test_loss = $test_loss,test_accuracy = $test_acc")
end
end
我在训练模型时收到以下错误。具体来说,在梯度计算期间。你能帮我理解错误指的是哪两个矩阵并指出我的解决方案吗?我的猜测是它与 build_model 参数有关,但我不太确定需要更改什么以及如何更改。
DimensionMismatch("matrix A has dimensions (32,1024),matrix B has dimensions (1,256)")
macro expansion@interface2.jl:0[inlined]
_pullback(::Zygote.Context,::typeof(throw),::DimensionMismatch)@interface2.jl:9
_pullback@matmul.jl:814[inlined]
_pullback(::Zygote.Context,::typeof(Linearalgebra._generic_matmatmul!),::Matrix{Matrix{Float32}},::Char,::Matrix{Float32},::Matrix{Matrix{Int64}},::Linearalgebra.MulAddMul{true,true,Bool,Bool})@interface2.jl:0
_pullback@matmul.jl:802[inlined]
_pullback(::Zygote.Context,::typeof(Linearalgebra.generic_matmatmul!),Bool})@interface2.jl:0
_pullback@matmul.jl:302[inlined]
_pullback@matmul.jl:275[inlined]
_pullback(::Zygote.Context,::typeof(Linearalgebra.mul!),::Matrix{Matrix{Int64}})@interface2.jl:0
_pullback@matmul.jl:153[inlined]
_pullback(::Zygote.Context,::typeof(*),::Matrix{Matrix{Int64}})@interface2.jl:0
_pullback@basic.jl:147[inlined] ....
解决方法
通过修复如下获取图像方法解决。
function getimages(filename)
filepath = pwd() * "/images/" * filename
mtrx = Matrix(DataFrame(CSV.File(filepath)))
return mtrx'
end