使用预训练的ResNet神经网络进行图像分类
神经网络是一种方便灵活的算法,可以在计算中训练。 通过成功的学习过程,相同的神经网络可以用于许多不同的任务。 例如,这就是着名的神经网络家族。 ResNet,为图像分类而创建。 部分或全部,这样的神经网络用于各种各样的任务,您需要处理图像的数字表示,从图形数据库到样式传输。
在这个例子中,我们将运行一个神经网络。 ResNet 小深度(18层)进行图像分类。 我们将展示输出信息的数据准备和处理的整个链,这对于任何图像都会给我们一个或多或少合适的文本标签,表征图片中描绘的对象。
筹备工作
一个对象 Tape 图书馆 Umlaut,目前,是计算的主要容器,在那里你可以从格式解压缩神经网络 ONNX. 这种触发机制很可能会在不久的将来被改变,因为库 ONNX 它目前正在更新过程中。
Pkg.add(["Umlaut", "ONNX"])
import Pkg; Pkg.add("Umlaut", io=devnull)
import Umlaut: Tape, play!
当然,我们还需要Engee内置的库来使用ONNX格式,该格式通常存储预训练的神经网络,以及用于处理图像的库。
using ONNX
using Images
安装工作文件夹
cd( @__DIR__ )
对象的类 ImageNet
我们的预训练神经网络可以识别的所有类对象的名称都表示为有序向量,并从以下文件加载。
include( "imagenet_classes.jl" );
输入/输出功能
让我们编写三个简单的辅助函数,用于将数据馈送到神经网络并处理结果。:
- 图片上传:我们将其缩放到大小244*244(标准化和裁剪边缘,同时保持比例将是一个受欢迎的补充)
- 预测排序:神经网络返回一个数字向量,该向量指示ImageNet数据集中的一个或另一个类在图像中观察到的概率。 选择
k表示的最可能的类是 - 这些功能的shell允许您在一个动作中上传图像并输出
k最可能的预测
# Загрузка изображения из файла
function imread(path::AbstractString; sz=(224,224))
img = Images.load(path);
img = imresize(img, sz);
x = convert(Array{Float32}, channelview(img))
# Заменим порядок слоев: CHW -> WHC
x = permutedims(x, (3, 2, 1))
return x
end
# Выдача индексов первых k предсказаний
function maxk(a, k)
b = partialsortperm(a, 1:k, rev=true)
return collect(zip(b, a[b]))
end
# Загрузка изображения и выдача десяти наиболее вероятных классов в убывающем порядке
function test_image(tape::Tape, path::AbstractString)
x = imread(path)
x = reshape(x, size(x)..., 1)
y = play!(tape, x)
y = reshape(y, size(y, 1))
top = maxk(y, 10)
classes = []
for (i, (idx, val)) in enumerate(top)
name = IMAGENET_CLASSES[idx - 1]
classes = [classes; "$i: $name ($val)"]
end
return join(classes, "\n")
end
下载神经网络 ResNet18
我们将使用扩展名的文件中的神经网络 *.onnx. 有些库允许您使用更高级别的命令创建和加载此神经网络(例如,[Metalhead library.jl](https://github.com/FluxML/Metalhead.jl)从集合 FluxML),但现在我们将在没有额外库的情况下完成。
预训练的神经网络已经位于指定的目录中,因此该命令将被执行而无需再次下载。
path = "resnet18.onnx"
if !isfile(path)
download("https://github.com/onnx/models/raw/main/vision/classification/resnet/model/resnet18-v1-7.onnx", path)
end
# Создадим пустую матрицу на месте которой будет входное изображение
img = rand( Float32, 224, 224, 3, 1 )
# Загружаем модель в виде объекта Umlaut.Tape
resnet = ONNX.load( path, img );
上传一些图片
如果已下载,则不会再次下载。
path = "data/"
goose_path = download( "https://upload.wikimedia.org/wikipedia/commons/3/3f/Snow_goose_2.jpg", path*"goose.jpg");
dog_path = download( "https://farm4.staticflickr.com/1301/4694470234_6f27a4f602_o.jpg", path*"dog.jpg");
plane_path = download( "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Rossiya%2C_RA-89043%2C_Sukhoi_Superjet_100-95B_%2851271265892%29.jpg/1024px-Rossiya%2C_RA-89043%2C_Sukhoi_Superjet_100-95B_%2851271265892%29.jpg", path*"plane.jpg");
图像分类
display( load(plane_path)[1:5:end, 1:5:end] )
print( test_image( resnet, plane_path ))
display( load(goose_path)[1:5:end, 1:5:end] )
print( test_image( resnet, goose_path ))
display( load(dog_path)[1:5:end, 1:5:end] )
print( test_image( resnet, dog_path ))
结论
我们已经证明,在Engee中下载神经网络并使用它来执行计算很容易。
此机制允许您组织由高级组件组成的复杂信息处理管道。 特别是,将信息处理的某些阶段委托给预先训练的神经网络。


